Cmake:如何构建自定义编译器二进制文件,然后将其用于某些目标?

时间:2019-03-18 11:01:11

标签: c++ cmake

我需要构建一个自定义的C ++编译器二进制文件,然后将其用于项目中的某些目标。

在现代CMake中最好的方法是什么?

我从编译器目标设置了一个依赖项,并且它按预期方式工作,但是然后,使用“生成器表达式”来获取编译器目标二进制名称是什么呢?

set(CMAKE_CXX_COMPILER ...)-它不理解生成器表达式,或者我以某种方式滥用了它。

是否有一种方法只能针对特定目标设置编译器?据我了解,set(CMAKE_CXX_COMPILER)适用于当前目录及其子目录。

2 个答案:

答案 0 :(得分:0)

您可以使用工具链文件,该文件用于指定交叉编译器。

这是我从文档中获取的示例:

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

答案 1 :(得分:0)

我为具有非C ++源代码(App/app.cc的示例应用程序(App/text.txt)制作了MCVE,必须通过中间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 –必须转换为生成的源text.cctext.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的{​​{1}}会授予:

    add_executable的VS项目中,
  1. test.txt被列为源代码。
  2. VS项目app已包含在VS解决方案tool
  3. App已编译并链接,然后用于tool编译并成功链接之前,将test.txt转换为test.htest.cc。 / li>

生成的中间源出现在构建目录中(不污染源目录)。因此,构建目录也必须设置为包含路径。否则,app(在#include "text.h"中)将无法工作。