使用CMake强制进行32位编译的正确方法

64

很抱歉有许多类似的问题,但我发现在Google CMake查询时总是得到类似但不完全相同的情况,有冲突的CMake命令等!

我需要强制我的项目构建32位二进制文件,因为我必须链接一个仅可用作32位的库。根据出现的错误消息,例如:

/usr/bin/ld: i386 architecture of input file `*external-32bit-lib*' is incompatible with i386:x86-64 output

据我所了解,因此我应该使用:

set (CMAKE_CXX_FLAGS "-m32")

这确实有所改变 - 现在我得到了几个错误,例如:

/usr/bin/ld: i386 architecture of input file `*project-output-lib*' is incompatible with i386:x86-64 output

同时使用-m32选项后,对于外部库仍然出现相同的错误。我认为这是因为-m32使得gcc生成32位的二进制文件,但ld仍在尝试生成64位输出?在Google上进一步搜索此问题未能获得成功,因此如果有人能够验证我的想法并给出正确的解决方法,我将非常感激!

非常感谢!

6个回答

52

如果你想使用cmake进行32位编译和链接,请使用以下内容创建库和可执行文件:

创建库:

add_library(mylib SHARED my_source.c)
set_target_properties(mylib PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32")

创建可执行文件:

add_executable(mybin sources.c)
set_target_properties(mybin PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32")

4
由于COMPILE_FLAGS已被弃用,因此该方法在3.12版本中不再适用。 - Egon Stetmann.
2
COMPILE_FLAGS替换为COMPILE_OPTIONS以避免使用已弃用的属性。 - fdk1342
1
如果项目包含许多库和可执行文件,是否有可能强制进行项目级别的操作? - Kazooie
4
我收到了LINK : warning LNK4044: unrecognized option '/m32'; ignored这个警告信息。 - Meekohi
1
@Meekohi,我想你正在使用Visual Studio。请查看MSDN以获取编译32位的正确VS方法。 - HackerDaGreat57

26

即使这看起来像是额外的工作,我认为在这种情况下使用工具链文件是一个合适的解决方案。例如:

即使这似乎是额外的工作,我认为在这种情况下使用工具链文件是一个恰当的解决方案。类似于:

# 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)
set(CMAKE_C_FLAGS -m32)
set(CMAKE_CXX_COMPILER g++)
set(CMAKE_CXX_FLAGS -m32)

# here is the target environment located
set(CMAKE_FIND_ROOT_PATH   /usr/i486-linux-gnu )

# adjust the default behaviour of the FIND_XXX() commands:
# search headers and libraries in the target environment, search
# programs in the host environment
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

使用方法很简单:

$ cmake -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake /path/to/source

重要的部分是现在可以指定根目录路径(CMAKE_FIND_ROOT_PATH)来搜索第三方库。实际上,您的编译器可能不够智能,无法确定在x86_64系统上搜索x86 Qt库的位置。

使用工具链文件可以针对不同的编译器指定不同的选项,在Windows环境下编译32位时可以进行调整。

现在这个方法已经很容易,在x86_64 Linux操作系统中编译32位只需要一些额外的工作,但是这种解决方法也适用于其他更奇特的设置。

有关工具链文件的更多信息,可以查阅以下链接:


11
当执行 cmake /path/to/source -DCMAKE_CXX_FLAGS=-m32 -DCMAKE_C_FLAGS=-m32 命令时,可能会觉得使用工具链文件有些过度了,但这两种方式是处理此情况的唯一正确方式。CMakeLists.txt 文件不应包含此类“信息”,除非原帖作者想要永远阻止 64 位编译的发生。 - rubenvb
@rubenvb 如我在帖子中所解释的那样,您仍然需要CMAKE_FIND_ROOT_PATH来帮助cmake处理类似find_package(Qt)的内容。 - malat
使用此技术和cmake 3.9.3,在首次创建构建目录时,工具链中定义的CMAKE_CXX_FLAGS没有在子项目中传播。但是,如果您第二次运行创建构建目录的命令而不删除现有的构建目录,则行为会发生变化!!!我不知道这是否是正常特性...为了解决问题,在工具链文件中将CMAKE_CXX_FLAGS定义为以下内容:set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32" CACHE STRING "c++ flags") - sancelot
1
你会推荐什么方法可以方便地切换编译 32 / 64 位代码呢?(不需要文件编辑,我的意思是) - Sandburg

11

CMAKE_CXX_FLAGS 只影响 C++ 编译器。你可能还需要为 C 编译器设置标志:

set (CMAKE_C_FLAGS "-m32")

4

看起来你没有把m32传递给LFLAGS,或者还有旧的obj文件存在。一定要先清理。

这个问题类似于你的问题:cmake、gcc、cuda和-m32


谢谢 - 可能是这样,但我该如何通过CMake实现呢?这是最明智或“正确”的方法吗?我已经清理过了 :) - devrobf
更新的答案。请查看链接。我是说洗手,你脏了 :) - Fredrik E
抱歉,链接似乎没有帮助。设置LDFLAGS似乎没有任何效果...干杯! - devrobf

3

请使用以下源代码中的TRY_RUN命令。

size.cpp:

#include <cstdlib>

int main( int argc, char** argv )
{
  size_t size = sizeof(void*);
  if ( size == 4 )
    return 0;
  return 1;
}

CMakeLists.txt:

TRY_RUN(RUN_RESULT_VAR COMPILE_RESULT_VAR ${your_temp_dir} size.cpp RUN_OUTPUT_VARIABLE IS_64_SYSTEM)
IF(IS_64_SYSTEM)
  MESSAGE(FATAL_ERROR "64 compiling not allowed!")
ENDIF(IS_64_SYSTEM)

它将适用于所有标准编译器。

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接