使用CMake进行交叉编译时,通常会通过CMAKE_TOOLCHAIN_FILE
选项指定工具链文件。在GNU terminology中,可以使用此文件指定主机体系结构工具集。但是,通常不能指望能够执行使用此工具链构建的任何内容。通常,需要为构建体系结构编译一些构建工具。
请考虑以下设置。我有两个源文件genfoo.c
和bar.c
。在构建期间,需要编译并运行genfoo.c
。其输出需要写入foo.h
。然后我可以编译bar.c
,#include "foo.h"
。由于CMake默认使用主机架构工具链,因此bar.c
的说明很简单。但是,如何告诉它使用构建体系结构工具链来编译genfoo.c
?简单地说add_executable(genfoo genfoo.c)
将导致使用错误的编译器。
答案 0 :(得分:8)
CMake一次只能处理一个编译器。所以 - 如果你没有将其他编译器设置为新语言,那么最终会有两个配置周期。
我看到以下方法来自动执行此过程:
以CMake页面中的示例"CMake Cross Compiling - Using executables in the build created during the build?"为起点,我将得到:
<强>的CMakeLists.txt 强>
cmake_minimum_required(VERSION 3.0)
project(FooBarTest)
# When crosscompiling import the executable targets
if (CMAKE_CROSSCOMPILING)
set(IMPORT_PATH "IMPORTFILE-NOTFOUND" CACHE FILEPATH "Point it to the export file path from a native build")
file(TO_CMAKE_PATH "${IMPORT_PATH}" IMPORT_PATH_CMAKE)
include(${IMPORT_PATH_CMAKE}/genfooTargets.cmake)
# Then use the target name as COMMAND, CMake >= 2.6 knows how to handle this
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/foo.h
COMMAND genfoo
)
add_executable(bar bar.cpp ${CMAKE_CURRENT_BINARY_DIR}/foo.h)
target_include_directories(bar PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
endif()
# Only build the generator if not crosscompiling
if (NOT CMAKE_CROSSCOMPILING)
add_executable(genfoo genfoo.cpp)
export(TARGETS genfoo FILE "${CMAKE_CURRENT_BINARY_DIR}/genfooTargets.cmake")
endif()
然后使用如下脚本:
<强> build.sh 强>
#!/bin/bash
if [ ! -d hostBuild ]; then
cmake -E make_directory hostBuild
cmake -E chdir hostBuild cmake ..
fi
cmake --build hostBuild
if [ ! -d crossBuild ]; then
cmake -E make_directory crossBuild
cmake -E chdir crossBuild cmake .. -DIMPORT_PATH=${PWD}/hostBuild -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake
fi
cmake --build crossBuild
我会通过致电./build.sh
来获得所需的结果。
拆分CMakeLists.txt
,甚至可以用我知道构建工具输出路径的内容替换export()
/ include()
,例如使用CMAKE_RUNTIME_OUTPUT_DIRECTORY
可以简化事情:
<强>的CMakeLists.txt 强>
cmake_minimum_required(VERSION 3.0)
project(FooBarTest)
# Then use the target name as COMMAND. CMake >= 2.6 knows how to handle this
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/foo.h
COMMAND genfoo
)
add_executable(bar bar.cpp ${CMAKE_CURRENT_BINARY_DIR}/foo.h)
target_include_directories(bar PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
<强>编译工具/的CMakeLists.txt 强>
cmake_minimum_required(VERSION 3.0)
project(BuildTools)
add_executable(genfoo genfoo.cpp)
<强> build.sh 强>
#!/bin/bash
if [ ! -d crossBuild ]; then
cmake -E make_directory crossBuild
cmake -E chdir crossBuild cmake .. -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake
fi
if [ ! -d hostBuild ]; then
cmake -E make_directory hostBuild
cmake -E chdir hostBuild cmake ../buildTools -DCMAKE_RUNTIME_OUTPUT_DIRECTORY:PATH=${PWD}/crossBuild
fi
cmake --build hostBuild
cmake --build crossBuild
<强>参考强>
答案 1 :(得分:2)
完全可以在CMake中完成该操作。
诀窍是在自己的空间中运行单独的CMake配置阶段 ,静默关闭每个交叉编译设置,并使用主机的默认工具链,然后将生成的输出导入到其父级交叉编译版本中。 / p>
第一部分:
set(host_tools_list wxrc generate_foo)
if(CMAKE_CROSSCOMPILING)
# Pawn off the creation of the host utilities into its own dedicated space
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/host_tools)
file(TO_NATIVE_PATH ${CMAKE_COMMAND} native_cmake_command)
file(TO_NATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR} native_cmake_current_source_dir)
execute_process(
COMMAND "${native_cmake_command}" "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}" "${native_cmake_current_source_dir}"
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/host_tools
)
add_custom_target(host_tools
COMMAND ${CMAKE_COMMAND} --build . --target host_tools --config $<CONFIG>
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/host_tools
)
include(${CMAKE_CURRENT_BINARY_DIR}/host_tools/host_tools.cmake)
foreach(tgt IN ITEMS ${host_tools_list})
add_dependencies(host${tgt} host_tools)
endforeach()
else()
# Add an empty target, host tools are built inplace
add_custom_target(host_tools
DEPENDS ${host_tools_list}
)
endif()
...然后添加通常的add_executable以及其他内容...
最后:
if(NOT CMAKE_CROSSCOMPILING)
foreach(tgt IN ITEMS ${host_tools_list})
add_executable(host${tgt} ALIAS ${tgt})
endforeach()
export(TARGETS ${host_tools_list} NAMESPACE host FILE host_tools.cmake)
endif()
当交叉编译时,它会将主机运行工具的创建典当到自己的专用空间中,并将目标导入为“ hostwxrc”和“ hostgenerate_foo”,并依赖于生成host_tools 自身 em>。
当不交叉编译时,它将按原样构建wxrc和generate_foo,并将其别名为hostwxrc和hostgenerate_foo。
此后,当您使用$<TARGET_FILE:wxrc>
时,指的是为 target 平台构建的wxrc,而$<TARGET_FILE:hostwxrc>
指的是为主机构建的wxrc 平台,无论它们是否相同。