【问题标题】:How to cross compile for linux x86 with linux amd64, cmake and g++?如何使用 linux amd64、cmake 和 g++ 交叉编译 linux x86?
【发布时间】:2011-05-07 01:55:14
【问题描述】:

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

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

我的主机:linux Kubuntu amd64。
目标:linux kubuntu x86(32bit)(应该很容易,不是吗?)
工具: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;制作;
我将如何为目标主机编译这些库(要使用的标志等)?

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

我需要的是一种教程,或者至少是一些缺失的部分。我将更新这篇文章,详细介绍我取得的成就和方法。

谢谢。

附言

有可能吗?

搜索更多,我发现了这个:
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 位。”

??

【问题讨论】:

    标签: linux g++ cmake cross-compiling


    【解决方案1】:

    如果您想使用工具链文件,有一个比@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 位库等的路径,这通常与标准路径不同。

    【讨论】:

      【解决方案2】:

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

      1. 安装多库支持:

        $sudo apt-get install gcc-multilib
        
      2. 创建一个“假”的 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,它涵盖了我在不兼容多库的库中遇到的一些问题

      【讨论】:

        【解决方案3】:

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

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

        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 本身中定义任意数量的目标,并通过一个文件将它们全部构建在一起。)为这些文件编写生成器只需要一些时间,但是一旦完成,我要做的就是将生成器指向一个包含源代码的目录,让 ir 运行,然后调用构建脚本来制作所有内容。

        【讨论】:

        • +1 感谢您的详细撰写。我会研究这一切,看看我能做些什么。
        【解决方案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 () {}
        

        【讨论】:

          【解决方案5】:

          这是我一直用于 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} 很有用,因为你可以使用它来根据目标平台/架构动态搜索私有库目录中的库。

          【讨论】:

          • 现在我主要只在我的 64 位桌面上开发时使用它。当我构建最终版本的 linux 二进制文件时,我使用 mock 在 CentOS 6 chroot(其中 2 个......一个 32 位和一个 64 位)中构建它们。
          猜你喜欢
          • 2022-11-04
          • 2022-06-17
          • 2023-01-27
          • 2014-03-14
          • 2010-12-19
          • 1970-01-01
          • 2014-01-03
          • 2021-03-04
          相关资源
          最近更新 更多