Как указать CMake использовать компилятор архитектуры сборки?

При использовании CMake для кросс-компиляции, обычно указывается файл инструментальной привязки с помощью опции CMAKE_TOOLCHAIN_FILE. В терминология GNU можно указать набор инструментов архитектуры хоста, используя этот файл. Однако, как правило, нельзя ожидать, что вы сможете выполнить что-либо, построенное с помощью этой инструментальной цепочки. Достаточно часто некоторые компиляторы должны быть скомпилированы для архитектуры сборки.

Рассмотрим следующую настройку. У меня есть два исходных файла genfoo.c и bar.c. Во время сборки, genfoo.c необходимо скомпилировать и запустить. Его вывод должен быть записан в foo.h. Тогда я могу скомпилировать bar.c, который #include "foo.h". Поскольку CMake по умолчанию использует инструментальную цепочку хост-архитектуры, инструкции для bar.c просты. Но как я могу сказать, что для создания genfoo.c используется инструментальная цепочка архитектуры построения? Просто говоря add_executable(genfoo genfoo.c) приведет к использованию неправильного компилятора.

Ответ 1

Превращение моих комментариев в ответ

CMake может обрабатывать только один компилятор за раз. Итак - если вы не проделаете длинный путь, чтобы настроить другой компилятор как новый язык, вы закончите с двумя циклами конфигурации.

Я вижу следующие способы автоматизации этого процесса:

  • Взяв пример "CMake Cross Compiling - Использование исполняемых файлов в сборке, созданной во время сборки?" на страницах 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()
    

    Затем, используя script как:

    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
    

Ссылки