Cmake: Как создать собственный двоичный файл компилятора, а затем использовать его для некоторых целей? - PullRequest
0 голосов
/ 18 марта 2019

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

Какой лучший способ сделать это в современном CMake?

Я установил зависимость от цели компилятора, и она работает, как и ожидалось, но что тогда, используйте 'выражения генератора', чтобы получить двоичное имя цели компилятора?

set(CMAKE_CXX_COMPILER ...) - либо он не понимает выражения генератора, либо я его как-то неправильно использую.

Есть ли способ установить компилятор только для конкретных целей? Как я понимаю, set(CMAKE_CXX_COMPILER) работает для текущего каталога и его дочерних элементов.

Ответы [ 2 ]

0 голосов
/ 18 марта 2019

Я сделал MCVE для примера приложения (App/app.cc) с исходным кодом не на C ++ (App/text.txt), который должен быть скомпилирован с использованием промежуточных источников C ++.

Пример дерева каталогов:

└┬─ ./
 ├─── CMakeLists.txt
 ├─┬─ App/
 │ ├─── CMakeLists.txt
 │ ├─── app.cc
 │ └─── text.txt
 └─┬─ Tool/
   ├─── CMakeLists.txt
   └─── tool.cc

Файл ./CMakeLists.txt является основным файлом проекта (предоставляет решение для VisualStudio):

project(App)

cmake_minimum_required(VERSION 3.10.0)

set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

add_subdirectory(App)
add_subdirectory(Tool)

Исходный код ./Tool/tool.cc для сборкиинструмент для создания исходного кода C ++ и заголовка из текстового файла:

// a sample tool converting a text file to a c++ source

#include <fstream>
#include <iostream>
#include <string>

int main(int argc, char **argv)
{
  if (argc < 3) {
    std::cerr <<
      "ERROR in tool: Missing arguments!\n"
      "\n"
      "Usage:\n"
      "tool TXT_FILE CC_FILE\n";
    return -1;
  }
  std::ifstream fIn(argv[1]);
  if (!fIn.good()) {
    std::cerr << "ERROR: Cannot open '" << argv[1] << "' for reading!\n";
    return -1;
  }
  const std::string fileH = std::string(argv[2]) + ".h";
  std::ofstream fOutH(fileH);
  if (!fOutH.good()) {
    std::cerr << "ERROR: Cannot open '" << fileH << "' for writing!\n";
    return -1;
  }
  const std::string fileCC = std::string(argv[2]) + ".cc";
  std::ofstream fOutCC(fileCC);
  if (!fOutCC.good()) {
    std::cerr << "ERROR: Cannot open '" << fileCC << "' for writing!\n";
    return -1;
  }
  fOutCC << "#include \"" << fileH << "\"\n\n";
  for (std::string buffer; std::getline(fIn, buffer);) {
    const size_t i = buffer.find('=');
    if (i < buffer.size()) {
      fOutH << "extern const char *const " << buffer.substr(0, i) << ";\n";
      fOutCC << "const char *const " << buffer.substr(0, i)
        << " = \"" << buffer.substr(i + 1) << "\";\n";
    }
  }
  fOutH.close();
  if (!fOutH.good()) {
    std::cerr << "ERROR: Couldn't complete writing of '" << fileH << "'!\n";
    return -1;
  }
  fOutCC.close();
  if (!fOutCC.good()) {
    std::cerr << "ERROR: Couldn't complete writing of '" << fileCC << "'!\n";
    return -1;
  }
  return 0;
}

Файл ./Tool/CMakeLists.txt для сборки инструмента:

project(Tool)

add_executable(tool
  tool.cc)

set_property(TARGET tool
  PROPERTY FOLDER "Tools")

Файл ./App/text.txt - aтекстовый файл, который должен быть преобразован в сгенерированные источники text.cc и text.h:

text1=Hello World.
text2=Text built with tool -> VC++

Источник ./App/app.cc, где включено text.h:

// a sample app using an indirect built source file

#include <iostream>

#include "text.h"

int main()
{
  std::cout << "text1: '" << text1 << "'\n";
  std::cout << "text2: '" << text2 << "'\n";
  return 0;
}

Наконец,./App/CMakeLists.txt, который вводит пользовательский этап сборки:

# custom build step
add_custom_command(
  OUTPUT
    text.cc text.h
  COMMAND
    tool "${CMAKE_CURRENT_SOURCE_DIR}/text.txt" text
  MAIN_DEPENDENCY
    text.txt
  DEPENDS
    tool
  COMMENT
    "generate C++ sources from text"
  VERBATIM)

# regular C++ build
add_executable(app
  app.cc          # regular source files
  text.cc text.h) # intermediate source files

# add build dir for project to include directories
include_directories(app 
    $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>)

Наличие DEPENDS tool в add_custom_command и OUTPUT в add_custom_command в add_executable дает:

  1. test.txt указан как источник в VS-проекте app
  2. VS-проект tool включен в VS-решение App
  3. tool isсоставлено и связано,и затем используется для преобразования test.txt в test.h и test.cc до того, как app скомпилировано и скомпоновано (успешно).

Сгенерированные промежуточные источники появляются в каталоге сборки (незагрязнять исходный каталог).Следовательно, каталог сборки также должен быть задан как include-путь.В противном случае #include "text.h"app.cc) не будет работать.

0 голосов
/ 18 марта 2019

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

Вот пример, который я взял из документации:

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)

set(CMAKE_SYSROOT /home/devel/rasp-pi-rootfs)
set(CMAKE_STAGING_PREFIX /home/devel/stage)

set(tools /home/devel/gcc-4.7-linaro-rpi-gnueabihf)
set(CMAKE_C_COMPILER ${tools}/bin/arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER ${tools}/bin/arm-linux-gnueabihf-g++)

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

Это нормально, поскольку оно находится в файле набора инструментов. CMake создан для правильной работы с файлами инструментов.

Вы используете его, указав его в аргументах командной строки:

cmake .. -DCMAKE_TOOLCHAIN_FILE=your_toolchain.cmake
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...