Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何指导CMake使用构建体系结构编译器_Cmake_Cross Compiling - Fatal编程技术网

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

如何指导CMake使用构建体系结构编译器,cmake,cross-compiling,Cmake,Cross Compiling,使用CMake进行交叉编译时,通常通过CMake_toolchain_file选项指定工具链文件。在中,可以使用此文件指定主机体系结构工具集。然而,人们通常不能期望能够执行使用此工具链构建的任何东西。因此,经常需要为构建体系结构编译一些构建工具 考虑以下设置。我有两个源文件genfoo.c和bar.c。在构建过程中,需要编译并运行genfoo.c。它的输出需要写入foo.h。然后我可以编译bar.c,其中#包括“foo.h”。由于CMake默认使用主机体系结构工具链,bar.c的说明很简单。但是

使用CMake进行交叉编译时,通常通过
CMake_toolchain_file
选项指定工具链文件。在中,可以使用此文件指定主机体系结构工具集。然而,人们通常不能期望能够执行使用此工具链构建的任何东西。因此,经常需要为构建体系结构编译一些构建工具


考虑以下设置。我有两个源文件
genfoo.c
bar.c
。在构建过程中,需要编译并运行
genfoo.c
。它的输出需要写入
foo.h
。然后我可以编译
bar.c
,其中
#包括“foo.h”
。由于CMake默认使用主机体系结构工具链,
bar.c
的说明很简单。但是我如何告诉它使用构建体系结构工具链来编译
genfoo.c
?简单地说添加可执行文件(genfoo genfoo.c)将导致使用错误的编译器。

CMake一次只能处理一个编译器。因此,如果您不将另一个编译器设置为一种新的语言,那么最终将有两个配置周期

我看到了以下自动化此过程的方法:

  • 以CMake页面中的示例为起点,我将得到:

    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()
    
    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})
    
    cmake_minimum_required(VERSION 3.0)
    project(BuildTools)
    
    add_executable(genfoo genfoo.cpp)
    
    然后使用如下脚本:

    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
    
    #!/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
    
    我将通过调用
    /build.sh
    获得所需的结果

  • 拆分
    CMakeLists.txt
    ,甚至可能将
    export()
    /
    include()
    替换为我知道构建工具输出路径的内容,例如通过使用,可以简化事情:

    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()
    
    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})
    
    cmake_minimum_required(VERSION 3.0)
    project(BuildTools)
    
    add_executable(genfoo genfoo.cpp)
    
    buildTools/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()
    
    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})
    
    cmake_minimum_required(VERSION 3.0)
    project(BuildTools)
    
    add_executable(genfoo genfoo.cpp)
    
    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
    
    #!/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
    
  • 参考资料


    完全可以在CMake中实现这一点

    诀窍是在它自己的空间中运行一个单独的CMake配置阶段,悄悄地取消每个交叉编译设置,并使用主机的默认工具链,然后将生成的输出导入到它的父级交叉编译构建中

    第一部分:

    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()
    
    当它进行交叉编译时,它会将主机运行工具的创建转移到自己的专用空间中,并将目标作为“hostwxrc”和“hostgenerate_foo”导入,并依赖于生成主机运行工具本身

    当它不进行交叉编译时,它会按原样构建wxrc和generate_foo,并将它们别名为hostwxrc和hostgenerate_foo


    在此之后,当您使用
    $
    时,您指的是为目标平台构建的wxrc,
    $
    指的是为主机平台构建的wxrc,无论它们是否相同。

    如您所述,在GNU术语中,您可以使用
    configure
    命令来指定主机体系结构。如果要为两个不同的主机环境构建,则必须运行两次
    configure
    。因此,我认为CMake有两种可能性:使用创建和执行所需的两个环境的构建脚本(请参阅),或者使用并将
    CMakeLists.txt
    拆分为专用子项目。不,使用autotools,您只需使用
    CC\u进行构建
    。请参阅
    ax\u cc\u以了解构建过程。好的,我不知道那个。如果我理解正确,我们讨论的是?@Florian中描述的用例,我相信你应该用这个链接来回答,因为它回答了我问题的大部分。我不喜欢所采取的方法,但它确实解决了眼前的问题。我最初盲目地认识到这是一种解决方案,因为它把BurDon(构建两次)放在用户身上。也许还考虑了在CMADE运行中需要构建可执行文件的方法,因此它可以用来生成源代码,甚至可以使用其他CMAKLISTS.TXT文件。我的工作是在OS X上为iOS构建生成文件,因此它实际上适用于像您这样的情况。使用这种方法,您可能需要先清除CXX/CC环境变量,然后再调用主机cmake with exec_process。i、 e.
    set(ENV{CXX}')
    set(ENV{CC}')