CMake使用教程三:系统检查和自定义命令及生成文件
1. 系统检查
系统检查的主要作用是在编译前对环境进行检查,以生成符合系统的可执行程序或库。
1.1 源码
mysqrt.cpp
#include <cmath>
#include <iostream>
#include "MathFunctions.h"
// a hack square root calculation using simple operations
double mysqrt(double x)
{
if (x <= 0) {
return 0;
}
// if we have both log and exp then use them
#if defined(HAVE_LOG) && defined(HAVE_EXP)
double result = std::exp(std::log(x) * 0.5);
std::cout << "Computing sqrt of " << x << " to be " << result
<< " using log and exp" << std::endl;
#else
double result = x;
// do ten iterations
for (int i = 0; i < 10; ++i) {
if (result <= 0) {
result = 0.1;
}
double delta = x - (result * result);
result = result + 0.5 * delta / result;
std::cout << "Computing sqrt of " << x << " to be " << result << std::endl;
}
#endif
return result;
}
1.2 CMake文件
./MathFunctions/CMakeLists.txt
add_library(MathFunctions mysqrt.cpp)
# INTERFACE 指定的是使用者(依赖此库的目标)需要的东西,因此其他使用者就不用额外添加这个库的包含目录
target_include_directories(MathFunctions INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}")
# does this system provide the log and exp functions?
include(CheckCXXSourceCompiles)
check_cxx_source_compiles("
#include <cmath>
int main() {
std::log(1.0);
return 0;
}
" HAVE_LOG)
check_cxx_source_compiles("
#include <cmath>
int main() {
std::exp(1.0);
return 0;
}
" HAVE_EXP)
# add compile definitions
if(HAVE_LOG AND HAVE_EXP)
# 给MathFunctions 编译时添加 HAVE_LOG 和 HAVE_EXP 的宏
target_compile_definitions(MathFunctions PRIVATE "HAVE_LOG" "HAVE_EXP")
endif()
2. 自定义命令及生成文件
自定义命令是指,CMake
调用其他可执行文件,生成文件则是指通过调用的其他命令来生成的文件。
2.1 源码
mysqrt.cpp
#include <iostream>
#include "MathFunctions.h"
// include the generated table
#include "Table.h"
// a hack square root calculation using simple operations
double mysqrt(double x)
{
if (x <= 0) {
return 0;
}
// use the table to help find an initial value
double result = x;
if (x >= 1 && x < 10) {
std::cout << "Use the table to help find an initial value " << std::endl;
result = sqrtTable[static_cast<int>(x)];
}
// do ten iterations
for (int i = 0; i < 10; ++i) {
if (result <= 0) {
result = 0.1;
}
double delta = x - (result * result);
result = result + 0.5 * delta / result;
std::cout << "Computing sqrt of " << x << " to be " << result << std::endl;
}
return result;
}
MakeTable.cpp
此文件在MathFunctions
目录下
// A simple program that builds a sqrt table
#include <cmath>
#include <fstream>
#include <iostream>
int main(int argc, char* argv[])
{
// make sure we have enough arguments
if (argc < 2) {
return 1;
}
std::ofstream fout(argv[1], std::ios_base::out);
const bool fileOpen = fout.is_open();
if (fileOpen) {
fout << "double sqrtTable[] = {" << std::endl;
for (int i = 0; i < 10; ++i) {
fout << sqrt(static_cast<double>(i)) << "," << std::endl;
}
// close the table with a zero
fout << "0};" << std::endl;
fout.close();
}
return fileOpen ? 0 : 1; // return 0 if wrote the file
}
2.2 CMake文件
./MathFunctions/CMakeLists.txt
add_executable(MakeTable MakeTable.cpp)
# 添加一个自定义命令,指定如何通过运行MakeTable生成Table.h
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
DEPENDS MakeTable
)
add_library(MathFunctions
mysqrt.cpp
#[[
告诉CMake mysqrt.cpp取决于生成的文件Table.h
这是通过将生成的Table.h添加到MathFunctions库的源列表中来实现的
]]
${CMAKE_CURRENT_BINARY_DIR}/Table.h
)
# INTERFACE 指定的是使用者(依赖此库的目标)需要的东西,因此其他使用者就不用额外添加这个库的包含目录
target_include_directories(MathFunctions
INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}"
# 将当前的二进制目录添加到包含目录列表中,以便mysqrt.cpp能够找到并包含Table.h
PRIVATE "${CMAKE_CURRENT_BINARY_DIR}"
)