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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4131158/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 23:54:24  来源:igfitidea点击:

How to cross compile for linux x86 with linux amd64, cmake and g++?

linuxg++cmakecross-compiling

提问by augustin

+1 for each piece of information that helps to complete the whole picture. You don't need to know the whole answer. I'll appreciate individual pieces of the puzzle just as much. Thanks.

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

I am about to attempt my first cross-compilation. I have searched both SO and the web and found many pieces of information, but I don't always know how to put those pieces together because there are still some missing pieces.

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

My host: linux Kubuntu amd64.
Target: linux kubuntu x86 (32bit) (should be easy, no?)
Tools: g++ and cmake.

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

Here is the information I found:

这是我找到的信息:

How to compile a 32-bit binary on a 64-bit linux machine with gcc/cmake
mentions export CFLAGS=-m32. That's one piece.

How to compile a 32-bit binary on a 64-bit linux machine with gcc/cmake
提到export CFLAGS=-m32。那是一块。

Cross-platform: selecting data types to use 32/64 bit
mentions data types. I may have to pay attention to that within my code.

跨平台:选择数据类型以使用 32/64 位
提及数据类型。我可能需要在我的代码中注意这一点。

#ifdef for 32-bit platform
#ifdef for 32-bit platform
links to the following, although I am not too sure yet how to use it:
http://predef.sourceforge.net/prearch.html

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

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

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

missing pieces:

缺失的部分:

Ideally, when I do 'make' (with cmake), it should spit out both a amd64 binary and a x86 one.

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

Part of my CMakeLists.txt looks like this:

我的 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)

How do I introduce the flag -m32 to create a second executable?

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

Should I want to make only one executable (e.g. for testing and debugging), how do I tell cmake to make either one or both binaries?

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

Also, you can see that I use some third party libraries, some of which I had to compile myself. Does this mean that I need to compile each of those binaries for the target host as well? Some use cmake and some use: ./configure; make;
How would I do about compiling those libraries for the target host (flags to use, etc.)?

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

Note: the dynamically linked libraries are already compiled and installed on the target computer, so maybe I don't need to worry about this step... I am not sure: this is one of my missing pieces...

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

What I need is a kind of tutorial, or at least some of the missing pieces. I'll update this post with more details on what I achieved and how.

我需要的是一种教程,或者至少是一些缺失的部分。我将更新这篇文章,提供有关我取得的成就和取得方式的更多详细信息。

Thanks.

谢谢。

P.S.

聚苯乙烯

Is it possible at all?

有可能吗?

Searching more, I found this:
http://www.mail-archive.com/[email protected]/msg26265.html
"The original design doesn't seem to be designed for anything more than windows-linux or linux-windows cross compiles."
cmake is NOT tested for linux amd64 to linux x86.

搜索更多,我发现了这个:
http: //www.mail-archive.com/[email protected]/msg26265.html
“最初的设计似乎不是为 windows-linux 或 linux-windows 设计的交叉编译。”
cmake 没有针对 linux amd64 到 linux x86 进行测试。

http://www.cmake.org/Wiki/CMake_Cross_Compiling#FAQ.2FPotential_Problems
"On mixed 32/64 bit Linux installations cross compilation cannot be used to build for 32/64 bit only."

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

??

??

回答by stijn

this is a simplified version of what I use, and it does create x86 binaries:

这是我使用的简化版本,它确实创建了 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 )

furthermore you'll use add_definitions to set compiler flags like -W -Ox -Dxxx etc.

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

All the lines above are actually split in seperate cmake files, and to get one file to build a number of executables, I generate a master cmake file containing all different configurations I want to build:

上面的所有行实际上都拆分为单独的 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

Then there's a driver shell script to build it all. It takes commandline options to set some extra options and select to build everything or just one configuration. Here's a piece of it:

然后有一个驱动程序 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

While this is not exactly what you ask for, it works flawlessly and does the same. (Not sure if it is possible in cmake to define any number of targets in cmake itself, and have them built all together by one file.) It just takes some time to write the generator for this files, but once that is done all I have to do is point the generator to a directory with sources, let ir run, then invoke the build script to make everything.

虽然这不完全是您所要求的,但它可以完美地工作并且做同样的事情。(不确定在 cmake 中是否可以在 cmake 本身中定义任意数量的目标,并将它们全部构建到一个文件中。)为这些文件编写生成器只需要一些时间,但是一旦完成,我要做的就是将生成器指向一个包含源代码的目录,让 ir 运行,然后调用构建脚本来制作所有内容。

回答by auledoom

This solution will allow you cross-compile your cmake project on a linux64 host targeting 32bits, on systems with multi-arch support. It's uses a "fake" cmake toolchain so CMAKE somehow "believes" it's on 32bit system, so no additional modifications are needed inside your cmake project files, no special configurations, no special settings (well almost).

此解决方案将允许您在具有多架构支持的系统上,在面向 32 位的 linux64 主机上交叉编译您的 cmake 项目。它使用了一个“假”的 cmake 工具链,所以 CMAKE 以某种方式“相信”它是在 32 位系统上,所以你的 cmake 项目文件中不需要额外的修改,没有特殊的配置,没有特殊的设置(几乎)。

  1. Install multilib support:

    $sudo apt-get install gcc-multilib
    
  2. Create a "fake" linux32 toolchain

  1. 安装多库支持:

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

First, we create a "fake" i686 compiler. Go where your CMakeLists.txt resides and create a bin directory. Open your preferred editor and create this simple bash script for gcc compiler.

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

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

As you see, it's just make a call to the system compiler adding the -m flag. Save this as i686-linux-gnu-gcc. Do the same for the g++ compiler

如您所见,它只是调用系统编译器并添加 -m 标志。将其另存为 i686-linux-gnu-gcc。对 g++ 编译器做同样的事情

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

Save it as i686-linux-gnu-g++. Remember to set the executable flags on this scrips

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

Create also a symlink to the system ar binary in this form

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

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

At last create the toolchain-linux32.cmake file

最后创建 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++)

and create the build directory and call cmake with the toolchain file as argument

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

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

and your done!!!!!

你完成了!!!!!

I'll write a more complete guide here, which covers some problems i have with libraries not multi-lib compliant

我会在这里写一个更完整的指南,它涵盖了我在不兼容多库的库中遇到的一些问题

回答by yngve

If you want to use a toolchain file there is an easier solution (IMHO) than what is proposed by @auledoom. You do not need to write the shell wrapper scripts at all, simply put this in the toolchain file:

如果您想使用工具链文件,则有比@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)

This will make it a "list variable" in cmake. This solution works for me. Benefit of the toolchain file is that you can there also define paths for 32bit libraries etc, which is usually different from standard paths.

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

回答by Urkle

Here is the basic recipe I use all the time for cmake projects..

这是我一直用于 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()

Then every target automatically has the .bin.${arch} extension and I never have to think about this for any targets I add. the ${BIN_LIBROOT} is useful if you have a bunch of precompiled libraries as you as you can use that to dynamically search for libs in your private lib dirs based on the target platform/arch.

然后每个目标都会自动具有 .bin.${arch} 扩展名,我不必为我添加的任何目标考虑这一点。如果您有一堆预编译库,${BIN_LIBROOT} 很有用,因为您可以使用它根据目标平台/架构动态搜索私有库目录中的库。

回答by vitaut

All you need is to add -m32to CFLAGSand CXXFLAGSwhen running CMake. This can be done via environment variables:

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

$ CFLAGS=-m32 CXXFLAGS=-m32 cmake .

or by setting corresponding CMake variables:

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

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

This can easily tested with a simple CMake project:

这可以通过一个简单的 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

where CMakeLists.txtis a trivial CMake file:

CMakeLists.txt一个简单的 CMake 文件在哪里:

project(TEST)
add_executable(foo foo.cc)

and foo.ccis as follows:

并且foo.cc是如下:

int main () {}