如何指示CMake使用构建体系结构编译器

时间:2016-03-23 09:08:31

标签: cmake cross-compiling

使用CMake进行交叉编译时,通常会通过CMAKE_TOOLCHAIN_FILE选项指定工具链文件。在GNU terminology中,可以使用此文件指定主机体系结构工具集。但是,通常不能指望能够执行使用此工具链构建的任何内容。通常,需要为构建体系结构编译一些构建工具。

请考虑以下设置。我有两个源文件genfoo.cbar.c。在构建期间,需要编译并运行genfoo.c。其输出需要写入foo.h。然后我可以编译bar.c#include "foo.h"。由于CMake默认使用主机架构工具链,因此bar.c的说明很简单。但是,如何告诉它使用构建体系结构工具链来编译genfoo.c?简单地说add_executable(genfoo genfoo.c)将导致使用错误的编译器。

2 个答案:

答案 0 :(得分:8)

CMake一次只能处理一个编译器。所以 - 如果你没有将其他编译器设置为新语言,那么最终会有两个配置周期。

我看到以下方法来自动执行此过程:

  1. 以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来获得所需的结果。

  2. 拆分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
    
  3. <强>参考

答案 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 平台,无论它们是否相同。