如何使用linux amd64,cmake和g ++交叉编译linux x86?

时间:2010-11-09 06:50:47

标签: linux g++ cmake cross-compiling

每个有助于完成整个图片的信息的+1。你不需要知道整个答案。我会同样欣赏这个拼图的各个部分。感谢。

我即将尝试我的第一次交叉编译。我搜索了SO和网络,发现了许多信息,但我并不总是知道如何将这些部分放在一起,因为还有一些缺失的部分。

我的主人:linux Kubuntu amd64。
目标:linux kubuntu x86(32位)(应该很简单,不是吗?)
工具:g ++和cmake。

以下是我发现的信息:

How to compile a 32-bit binary on a 64-bit linux machine with gcc/cmake
提到导出CFLAGS = -m32。这是一件作品。

Cross-platform: selecting data types to use 32/64 bit
提到数据类型。我可能必须在我的代码中注意这一点。

#ifdef for 32-bit platform
 #ifdef用于32位平台
链接到以下内容,虽然我不太确定如何使用它:
http://predef.sourceforge.net/prearch.html

http://ww.ubuntuforums.org/showthread.php?t=1377396
我做了:sudo apt-get install g ++ - multilib

缺少部分:

理想情况下,当我'make'(使用cmake)时,它应该吐出amd64二进制文件和x86二进制文件。

我的部分CMakeLists.txt如下所示:

add_definitions(-Wall -pthread)
add_executable (../run.amd64 user.cpp time.cpp init.cpp utils.cpp main.cpp)
target_link_libraries(../run.amd64 cppcms dbixx config++ ctemplate)

如何引入标志-m32来创建第二个可执行文件?

我是否只想制作一个可执行文件(例如,用于测试和调试),如何告诉cmake制作一个或两个二进制文件?

另外,你可以看到我使用了一些第三方库,其中一些我必须自己编译。这是否意味着我还需要为目标主机编译每个二进制文件?有些人使用cmake,有些人使用:./ configure;令;
如何为目标主机编译这些库(要使用的标志等)?

注意:动态链接库已经编译并安装在目标计算机上,所以也许我不需要担心这一步......我不确定:这是我遗失的部分...... < / p>

我需要的是一种教程,或者至少是一些缺失的部分。我将更新这篇文章,详细介绍我取得的成就以及如何实现。

感谢。

P.S。

有可能吗?

搜索更多,我发现了这个:
http://www.mail-archive.com/cmake@cmake.org/msg26265.html
“原始设计似乎不是为windows-linux或linux-windows交叉编译而设计的。” cmake没有测试linux amd64到linux x86。

http://www.cmake.org/Wiki/CMake_Cross_Compiling#FAQ.2FPotential_Problems
“在混合的32/64位Linux安装中,交叉编译不能仅用于构建32/64位。”

...

5 个答案:

答案 0 :(得分:8)

如果你想使用工具链文件,有一个比@auledoom提出的更简单的解决方案(恕我直言)。您根本不需要编写shell包装器脚本,只需将其放在工具链文件中:

# the name of the target operating system
set(CMAKE_SYSTEM_NAME Linux)

# Which compilers to use for C and C++
set(CMAKE_C_COMPILER gcc -m32)
set(CMAKE_CXX_COMPILER g++ -m32)

这将使它成为cmake中的“列表变量”。这个解决方案适合我。工具链文件的好处是你可以在那里定义32位库等的路径,这通常与标准路径不同。

答案 1 :(得分:7)

此解决方案允许您在具有多拱支持的系统上针对32位的linux64主机交叉编译您的cmake项目。 它使用了“假的”cmake工具链,所以CMAKE以某种方式“相信”它在32位系统上,所以你的cmake项目文件中不需要进行任何额外的修改,没有特殊的配置,没有特殊的设置(差不多)。

  1. 安装multilib支持:

    $sudo apt-get install gcc-multilib
    
  2. 创建一个“假的”linux32工具链

  3. 首先,我们创建一个“假的”i686编译器。转到CMakeLists.txt所在的位置并创建bin目录。打开首选编辑器,为gcc编译器创建这个简单的bash脚本。

    #!/bin/sh
    /usr/bin/gcc -m32 "$@"
    

    如您所见,它只是调用系统编译器添加-m标志。保存为i686-linux-gnu-gcc。对g ++编译器执行相同的操作

    #!/bin/sh
    /usr/bin/g++ -m32 "$@"
    

    将其保存为i686-linux-gnu-g ++。请记住在此脚本上设置可执行标志

    还以这种形式创建系统ar二进制文件的符号链接

    $ln /usr/bin/ar i686-linux-gnu-ar
    

    最后创建toolchain-linux32.cmake文件

    # the name of the target operating system
    set(CMAKE_SYSTEM_NAME Linux)
    
    # Which compilers to use for C and C++
    set(CMAKE_C_COMPILER ${CMAKE_SOURCE_DIR}/bin/i686-linux-gnu-gcc)
    set(CMAKE_CXX_COMPILER ${CMAKE_SOURCE_DIR}/bin/i686-linux-gnu-g++)
    

    创建构建目录并使用工具链文件作为参数调用cmake

    $mkdir build && cd build
    $cmake -DCMAKE_TOOLCHAIN_FILE=../toolchain-linux32.cmake ..
    

    你完成了!!!!!

    我会写一个更完整的指南here,它涵盖了我对库不符合多库的问题

答案 2 :(得分:5)

这是我使用的简化版本,它确实创建了x86二进制文件:

set( TargetName myExe )
set( SOURCES a.cpp b.cpp )
add_executable( ${TargetName} ${SOURCES} )
target_link_libraries( ${TargetName} m pthread stdc++ )
set_target_properties( ${TargetName} PROPERTIES COMPILE_FLAGS -m32 LINK_FLAGS -m32 )

此外,您将使用add_definitions来设置编译器标志,如-W -Ox -Dxxx等。

上面的所有行实际上是分成单独的cmake文件,为了获得一个文件来构建一些可执行文件,我生成一个包含我想要构建的所有不同配置的主cmake文件:

project( myProject )
set( SOURCES a.cpp b.cpp )
if( ${ConfigurationType} strequal "Debugx86" )
  include( debugopts.cmake )
  include( x86.cmake )
  include( executable.cmake )
  ...
elseif( ${ConfigurationType} strequal "Releasex64" )
  include( debugopts.cmake )
  include( x86.cmake )
  include( executable.cmake )
  ...
etc

然后有一个驱动程序shell脚本来构建它。它需要命令行选项来设置一些额外的选项,并选择构建所有内容或只是一个配置。这是它的一部分:

if [ "$myConfig" = "all" -o "$myConfig" = "Debugx86" ]; then
  mkdir -p project_Debugx86
  cd project_Debugx86
  cmkake "$sourceDir" "$cmakeOpts" -DConfigurationType="Debugx86"
  make clean
  make "$makeopts"
fi
if [ "$myConfig" = "all" -o "$myConfig" = "Releasex64" ]; then
  mkdir -p project_Releasex64
  cd project_Releasex64
  cmkake "$sourceDir" "$cmakeOpts" -DConfigurationType="Releasex64
  make clean
  make "$makeopts"
fi

虽然这不是你要求的,但它完美无瑕,并且也是如此。 (不确定在cmake中是否可以在cmake中定义任意数量的目标,并将它们一起构建在一个文件中。)只需要一些时间为这些文件编写生成器,但是一旦完成所有我要做的是将生成器指向一个带有源的目录,让我们运行,然后调用构建脚本来制作所有内容。

答案 3 :(得分:4)

运行CMake时,您只需要将-m32添加到CFLAGSCXXFLAGS。这可以通过环境变量来完成:

$ CFLAGS=-m32 CXXFLAGS=-m32 cmake .

或通过设置相应的CMake变量:

$ cmake -DCMAKE_C_FLAGS=-m32 -DCMAKE_CXX_FLAGS=-m32 .

这可以通过简单的CMake项目轻松测试:

$ uname -m
x86_64
$ CFLAGS=-m32 CXXFLAGS=-m32 cmake .
-- The C compiler identification is GNU 4.8.1
-- The CXX compiler identification is GNU 4.8.1
....
$ make 
Scanning dependencies of target foo
[100%] Building CXX object CMakeFiles/foo.dir/foo.cc.o
Linking CXX executable foo
[100%] Built target foo
$ file foo
foo: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x5b1871446c92cbdcbf905583e16189f68f3bf5f2, not stripped

其中CMakeLists.txt是一个简单的CMake文件:

project(TEST)
add_executable(foo foo.cc)

foo.cc如下:

int main () {}

答案 4 :(得分:2)

这是我一直用于cmake项目的基本配方..

OPTION(FORCE32 "Force a 32bit compile on 64bit" OFF)
IF(FORCE32)
    if(APPLE)
        SET(CMAKE_OSX_ARCHITECTURES "i386")
    else()
        SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32")
        SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32")
    endif()
ENDIF()

IF(APPLE)
    set(BIN_LIBROOT "macosx")
ELSE()
    if(CMAKE_SIZEOF_VOID_P MATCHES "8" AND NOT(FORCE32) )
        set(BIN_LIBROOT "linux64")
        set(CMAKE_EXECUTABLE_SUFFIX ".bin.x86_64")
        set(BIN_RPATH "\$ORIGIN/lib64")
    else()
        set(BIN_LIBROOT "linux")
        set(CMAKE_EXECUTABLE_SUFFIX ".bin.x86")
        set(BIN_RPATH "\$ORIGIN/lib")
    endif()

    set(CMAKE_SKIP_BUILD_RPATH TRUE)
    set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
    set(CMAKE_INSTALL_RPATH ${BIN_RPATH})
    set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE)
ENDIF()

然后每个目标都自动拥有.bin。$ {arch}扩展名,我永远不必考虑我添加的任何目标。如果您有一堆预编译库,那么$ {BIN_LIBROOT}非常有用,因为您可以使用它来根据目标平台/ arch动态搜索私有lib目录中的库。