我需要构建一个自定义的C ++编译器二进制文件,然后将其用于项目中的某些目标。
在现代CMake中最好的方法是什么?
我从编译器目标设置了一个依赖项,并且它按预期方式工作,但是然后,使用“生成器表达式”来获取编译器目标二进制名称是什么呢?
set(CMAKE_CXX_COMPILER ...)
-它不理解生成器表达式,或者我以某种方式滥用了它。
是否有一种方法只能针对特定目标设置编译器?据我了解,set(CMAKE_CXX_COMPILER)
适用于当前目录及其子目录。
答案 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.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
的{{1}}会授予:
add_executable
的VS项目中,test.txt
被列为源代码。app
已包含在VS解决方案tool
App
已编译并链接,然后用于tool
编译并成功链接之前,将test.txt
转换为test.h
和test.cc
。 / li>
生成的中间源出现在构建目录中(不污染源目录)。因此,构建目录也必须设置为包含路径。否则,app
(在#include "text.h"
中)将无法工作。