WIN32和UNIX在CMake交叉编译中不改变

WIN32 and UNIX don't change in CMake cross-compile

我做了一个测试CMakeLists.txt。我在读取变量之前设置了系统名称和版本(虽然我没有设置编译器):

cmake_minimum_required(VERSION 3.10)

project(test)

include_directories(.)

set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_SYSTEM_VERSION 10.0.10240.0)

add_executable(test test.c)

target_link_libraries(test)

message("cmake system name = ${CMAKE_SYSTEM_NAME}")
message("cmake host name = ${CMAKE_HOST_SYSTEM_NAME}")
message("cmake system version = ${CMAKE_SYSTEM_VERSION}")
message("unix = ${UNIX}")
message("win32 = ${WIN32}")

这是“cmake”的输出。在终端上:

-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
cmake system name = Windows
cmake host name = Linux
cmake system version = 10.0.10240.0
unix = 1
win32 = 
-- Configuring done
-- Generating done
-- Build files have been written to: /home/francisco/Documents

CMake 文档说 UNIX 和 WIN32 设置为 目标 OS。此处我设置了目标 OS,但它们仍然设置为主机 OS。为什么?

您不应该在 CMake 遇到第一个 project() 命令后编写 CMAKE_SYSTEM_NAME。在第一个 project 命令中,编译器和目标系统的选择已经做出,您以后无法更改其效果。如您所见,您可以覆盖 CMAKE_SYSTEM_NAME 的值,但这样做的唯一影响是您和任何可能被调用的外部 cmake 逻辑(例如,使用 find_package 时执行的脚本)看到一个值这是错误的(即与编译器的选择不匹配)。

为了设置此类信息,您的 CMakeLists.txt 文件放错了地方。这种信息属于 toolchain file 以及您选择的实际为目标平台生成二进制文件的编译器:

toolchain-windows.cmake

set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_SYSTEM_VERSION 10.0.10240.0)

set(CMAKE_C_COMPILER <command/absolute path to executable to use as C compiler goes here>)
set(CMAKE_CXX_COMPILER <command/absolute path to executable to use as C++ compiler goes here>)

...

使用类似

的方式配置项目
cmake --toolchain path/to/toolchain-windows.cmake -S path/to/source -B path/to/build/dir

注意: linux 上的默认编译器几乎肯定无法针对 windows 目标进行交叉编译。