每个有助于完成整个图片的信息的+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位。”
...
答案 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项目文件中不需要进行任何额外的修改,没有特殊的配置,没有特殊的设置(差不多)。
安装multilib支持:
$sudo apt-get install gcc-multilib
创建一个“假的”linux32工具链
首先,我们创建一个“假的”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
添加到CFLAGS
和CXXFLAGS
。这可以通过环境变量来完成:
$ 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目录中的库。