目录
3.add_custom_target(构建时运行自定义命令)
本文将展示如何提取Eigen库文件,并使用提取的源文件编译我们的项目。首先我们需要先下载Eigen压缩包(我下载到的zip文件路径为D:\thirdParties\eigen-3.4.0.zip)
一、CMake命令及语法
1.CMAKE_COMMAND
cmake路径。
message(STATUS "CMAKE_COMMAND=${CMAKE_COMMAND}")
#CMAKE_COMMAND=D:/soft/CMake/bin/cmake.exe
2.CMAKE_CURRENT_BINARY_DIR
当前正在处理的二进制目录路径。
message(STATUS "CMAKE_CURRENT_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}")
#CMAKE_CURRENT_BINARY_DIR=D:/FCJProject/cmakeProgram/cmakeStudy/UseEigenTestFile/build
3.add_custom_target(构建时运行自定义命令)
添加一个具有给定名称的目标,以执行给定命令。目标没有输出文件,即使命令试图创建具有目标名称的文件,也始终被视为过期。构建过程中必须执行一系列没有输出的命令时,可以使用 add_custom_target 命令。
add_custom_target(Name [ALL] [command1 [args1...]] [COMMAND command2 [args2...] ...] [DEPENDS depend depend depend ... ] [BYPRODUCTS [files...]] [WORKING_DIRECTORY dir] [COMMENT comment] [JOB_POOL job_pool] [VERBATIM] [USES_TERMINAL] [COMMAND_EXPAND_LISTS] [SOURCES src1 [src2...]])
- ALL:表明应将此目标添加到默认生成目标,以便每次都运行它(传递了 ALL 参数,该目标将始终被执行)。
- COMMAND:指定要执行哪些命令。
- DEPENDS:将COMMAND和DEPENDS 附加到第一个指定输出的自定义命令。
- BYPRODUCTS:指定命令预期生成的文件,但其修改时间可能比依赖项的新,也可能不比依赖项的新。
- WORKING_DIRECTORY:工作目录,指定在何处执行命令。
- COMMENT:用于指定CMake在执行自定义目标时输出什么样的消息。
- JOB_POOL:为Ninja生成器指定一个池。
- VERBATIM:对于构建工具,命令的所有参数都将被正确转义,以便被调用的命令接收到的每个参数不变。请注意,在add_custom_target 甚至看到参数之前,CMake语言处理器仍然使用一级转义。建议使用VERBATIM,因为它可以保证正确的行为。如果不指定VERBATIM,则行为是依赖于平台的,因为CMake没有针对于特定工具中特殊字符的保护措施。
- COMMAND_EXPAND_LISTS:命令参数中的列表将展开,包括使用生成器表达式创建的列表。
- SOURCES:指定了包含进该目标的额外的源文件。即使这些源文件没有构建规则,但是它们会被增加到IDE的工程文件中以方便编辑。
add_custom_target 添加的目标没有输出,因此总会执行。因此,在子目录中的CMakeLists.txt引入自定义目标时,在主 CMakeLists.txt 中仍然能够引用它。
add_custom_target(unpack-eigen
ALL
COMMAND
${CMAKE_COMMAND} -E tar xzf D:/thirdParties/eigen-3.4.0.zip
COMMAND
${CMAKE_COMMAND} -E rename eigen-3.4.0 eigen3.4.0
WORKING_DIRECTORY
${CMAKE_CURRENT_BINARY_DIR}
COMMENT
"Unpacking Eigen3 in ${CMAKE_CURRENT_BINARY_DIR}/eigen3.4.0"
)
构建系统中引入了一个名为 unpack-eigen 的目标:
- 第一个命令用来提取存档,第二个命令用来将提取的目录重命名为eigen3.4.0
- 使用cmake -E 标志:调用CMake命令,来执行实际的工作。(可以在命令行输入cmake -E来获得特定操作系统的完整列表)
4.cmake -E命令
(1)解压、压缩
tar [cxt][vf][zjJ] file.tar [file/dir1 file/dir2 ...]
必选参数(不能同时使用):
- -c:创建归档文件
- -x:解压
- -t:查看压缩文件内容
可选参数:
- -z:gzip压缩,处理.tar.gz格式
- -j:bz2压缩,处理.tar.bz2格式
- -v:显示所有过程
必选参数:
- -f:最后一个参数,后接归档文件名
(2)重命名
rename oldname newname
二、源码
1.CMakeLists.txt
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(testEigen LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIERD ON)
add_custom_target(unpack-eigen
ALL
COMMAND
${CMAKE_COMMAND} -E tar xzf D:/thirdParties/eigen-3.4.0.zip
COMMAND
${CMAKE_COMMAND} -E rename eigen-3.4.0 eigen3.4.0
WORKING_DIRECTORY
${CMAKE_CURRENT_BINARY_DIR}
COMMENT
"Unpacking Eigen3 in ${CMAKE_CURRENT_BINARY_DIR}/eigen3.4.0"
)
add_executable(test test.cpp)
#由于源文件的编译依赖于Eigen头文件,需要显式地指定可执行目标对自定义目标的依赖关系
add_dependencies(test unpack-eigen)
#指定包含目录
target_include_directories(test
PRIVATE
${CMAKE_CURRENT_BINARY_DIR}/eigen3.4.0)
2.test.cpp
#include <chrono>
#include <iostream>
#include <Eigen/Dense>
EIGEN_DONT_INLINE
double simple_function(Eigen::VectorXd &va,Eigen::VectorXd &vb)
{
double d=va.dot(vb);
return d;
}
int main()
{
int len=1000000;
int num_repetitions=100;
Eigen::VectorXd va=Eigen::VectorXd::Random(len);
Eigen::VectorXd vb=Eigen::VectorXd::Random(len);
double result;
auto start=std::chrono::system_clock::now();
for(auto i=0;i<num_repetitions;i++)
{
result=simple_function(va,vb);
}
auto end=std::chrono::system_clock::now();
auto elapsed_seconds=end-start;
std::cout<<"result:"<<result<<std::endl;
std::cout<<"elasped seconds:"<<elapsed_seconds.count()<<std::endl;
}