c++ - Cmake:如何构建自定义编译器二进制文件,然后将其用于某些目标?
问题描述
我需要构建一个自定义 C++ 编译器二进制文件,然后将其用于项目中的某些目标。
在现代 CMake 中最好的方法是什么?
我从编译器目标设置了一个依赖项,它按预期工作,但是然后呢,使用“生成器表达式”来获取编译器目标二进制名称?
set(CMAKE_CXX_COMPILER ...)
-- 要么它不理解生成器表达式,要么我以某种方式滥用它。
有没有办法只为特定目标设置编译器?据我了解,set(CMAKE_CXX_COMPILER)
适用于当前目录及其子目录。
解决方案
我用非 C++ 源代码 ( )为示例应用程序 ( ) 创建了一个MCVE ,它必须通过中间 C++ 源进行编译。App/app.cc
App/text.txt
示例目录树:
└┬─ ./
├─── 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.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
inadd_custom_command
和OUTPUT
of add_custom_command
inadd_executable
授予:
test.txt
在 VS 项目中被列为源app
- VS-project
tool
包含在 VS-solution 中App
tool
被编译链接,然后用来转换test.txt
为test.h
和test.cc
之前app
被编译链接(成功)。
生成的中间源出现在构建目录中(不要污染源目录)。因此,构建目录也必须设置为包含路径。否则,#include "text.h"
(in app.cc
) 将不起作用。
推荐阅读
- r - 在 R/shiny 中使用 renderTmap 时的反应性问题
- linux - 引用其他 shell 文件的 shell 文件以及调用它们的最佳方式
- serenity-bdd - Serenity 如何在测试 chrome 模拟器上运行(chrome web 浏览器中的移动模式)
- jquery - 拼接数组没有删除正确的位置并重叠同一个(jQuery)
- jquery - 尝试获取工作结果在 Postman 中完美运行,但在浏览器中使用 AJAX 需要 app_code 和 app_id
- html - 在 div HTML 中定位一些文本
- sql - 从 sysdate 获取上个月并将其存储为数字
- typescript - 在打字稿中获取数字文字类型值
- https - 通过 istio 网关公开 kibana(eck 运算符) - https 问题(错误 503)
- excel - Excel VBA 多个/嵌套 For 循环