Please优先参考第一手资料:CMake Reference Documentation。
1.CMakeLists.txt编写
# ----------------------------------------------------------------------------
# Root CMake file for Template
#
# From the off-tree build directory, invoke:
# $ cmake <PATH_TO_TEMPLATE_ROOT>
#
# ----------------------------------------------------------------------------
# Disable in-source builds to prevent source tree corruption.
# 不让构建的文件放到源码(一般和CMakeLists.txt同目录)所在目录,
# 要求重新创建目录(比如build)来保存构建的文件
if(" ${CMAKE_SOURCE_DIR}" STREQUAL " ${CMAKE_BINARY_DIR}")
message(FATAL_ERROR "
FATAL: In-source builds are not allowed.
You should create a separate directory for build files.
")
endif()
工程根目录的CMakeLists.txt
# ----------------------------------------------------------------------------
# Root CMake file for Template
#
# From the off-tree build directory, invoke:
# $ cmake <PATH_TO_TEMPLATE_ROOT>
#
# ----------------------------------------------------------------------------
# Disable in-source builds to prevent source tree corruption.
# 不让构建的文件放到源码(一般和CMakeLists.txt同目录)所在目录,
# 要求重新创建目录(比如build)来保存构建的文件
if(" ${CMAKE_SOURCE_DIR}" STREQUAL " ${CMAKE_BINARY_DIR}")
message(FATAL_ERROR "
FATAL: In-source builds are not allowed.
You should create a separate directory for build files.
")
endif()
cmake_minimum_required(VERSION 3.20)
project(01_PanGu)
add_subdirectory(code code_build)
# 修改默认安装路径为想要安装的位置
message(STATUS "++++++${CMAKE_INSTALL_PREFIX}++++++")
set(CMAKE_INSTALL_PREFIX D:/02.Work/04.LearnCMake/01.PanGu)
message(STATUS "====${CMAKE_INSTALL_PREFIX}=======")
install(FILES COPYRIGHT README DESTINATION install)
install(PROGRAMS runhello.sh DESTINATION install/bin)
install(DIRECTORY doc DESTINATION install)
# 安装时执行:cmake --install . --prefix "/home/myuser/installdir"
库代码所在的子文件夹目录的CMakeLists.txt
,同时构建动态库、静态库
# Disable in-source builds to prevent source tree corruption.
# 不让构建的文件放到源码(一般和CMakeLists.txt同目录)所在目录,
# 要求重新创建目录(比如build)来保存构建的文件
if(" ${CMAKE_SOURCE_DIR}" STREQUAL " ${CMAKE_BINARY_DIR}")
message(FATAL_ERROR "
FATAL: In-source builds are not allowed.
You should create a separate directory for build files.
")
endif()
cmake_minimum_required(VERSION 3.20)
set(CMAKE_CXX_STANDARD 14)
set(HELLO_SRC hello.cpp)
# add_library(01_PanGu SHARED ${HELLO_SRC}) # 只构建动态库
# add_library(01_PanGu STATIC ${HELLO_SRC}) # 只构建静态库
# 同时构建动态库、静态库
add_library(01_PanGu_static STATIC ${HELLO_SRC}) # 先构建静态库
set_target_properties(01_PanGu_static PROPERTIES OUTPUT_NAME "01_PanGu")
set_target_properties(01_PanGu_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
add_library(01_PanGu SHARED ${HELLO_SRC}) # 再构建动态库
set_target_properties(01_PanGu PROPERTIES OUTPUT_NAME "01_PanGu")
set_target_properties(01_PanGu PROPERTIES CLEAN_DIRECT_OUTPUT 1)
2.生成工程构建系统Generate a Project Buildsystem
不管使用哪种Generator都是先生成对应的Buildsystem再build。
编写完CMakeLists.txt之后使用cmake制定Generator来生成对应的工程。
也可以在终端使用cmake -G
查看:
假设当前目录有以下文件(夹):
其中:
build
文件夹为空,用于保存构建文件。
CMakeLists.txt
为:
cmake_minimum_required (VERSION 3.6)
add_executable(runHelloWorld "helloworld.cpp")
helloworld.cpp
为:
#include <iostream>
int main()
{
std::cout << "hello cmake" << std::endl;
return 0;
}
下文展示使用不同的Generator生成的不同工程。
2.1 Ninja
进入到build文件夹下执行cmake -G Ninja ..
:
此时build
文件夹下生成的文件如下:
接着执行指令cmake --build .
即可生成可执行程序runHelloWorld
所有生成文件如下:
执行./runHelloWorld
输出:
2.2 Unix Makefiles
进入到build文件夹下执行cmake -G "Unix Makefiles" ..
:
此时build文件夹下生成的文件如下:
接着执行指令make -f Makefile
即可生成可执行程序runHelloWorld
所有生成文件如下:
2.2 cmake Options
常用Options释义如下,其它请参考官网文档说明:
对-A,-T,–toolchain的理解,-A和toolset并不是所有的Generator都会用到,在Visual Studio上是需要的;toolchain用于指定交叉编译的工具链。例如:
Visual Studio 15 2017示例
3.完整工程示例
- CMakeLists.txt编写示例(ps:本不想收币的,奈何此处无法添加附件)
- 关于ctest的示例(ps:建议多参考官方文档)
4.#cmakedefine vs #define
On 2011-03-15 16:26-0600 Balamurali Ananthan wrote:
> Hello,
>
> Sorry if this question is too primitive. I am trying to extract the build dir
> into the source code by populating it in a variable in my config.h file.
>
> I do this by adding the following line in config.h.in
>
> #cmakedefine PROJ_BUILD_DIR_CMAKEDEFINE "${PROJECT_BINARY_DIR}"
>
> In the config.h, this produces
>
> /* #undef PROJ_BUILD_DIR_CMAKEDEFINE */
>
>
>
> But if i replace it to this in config.h.in,
>
> #define PROJ_BUILD_DIR_DEFINE "${PROJECT_BINARY_DIR}"
>
> Then the right value is populated in the config.h
>
> #define PROJ_BUILD_DIR_DEFINE "/home/bala/projects/myproj/trunk/builds"
>
> Wondering why didn't the cmakedefine work in this case? Any clues?
The man page for cmake covers this. "#cmakedefine VAR will be
replaced with either #define VAR or /* #undef VAR */
depending on the setting of VAR in CMake."
Note that VAR is the CMake variable name and not its value.
PROJ_BUILD_DIR_CMAKEDEFINE does not exist as a CMake variable in your
project so its CMake value is false and you get the above commented
out #undef result just like the man page says. OTOH if you had
specified instead,
#cmakedefine PROJECT_BINARY_DIR
that would have configured (since PROJECT_BINARY_DIR is "True" in the
CMake sense for your project) as
#define PROJECT_BINARY_DIR
Of course, that would not have been too helpful to you since there is
no associated explicit value, but note #cmakedefine is quite useful
for the case of conditional programming depending on #ifdef (i.e.,
True/False binary macro logic).
For cases where you need to #define an explicit value, then you should
forget about #cmakedefine and use the configured #define (as you did
above).
Alan
__________________________
Alan W. Irwin
Astronomical research affiliation with Department of Physics and Astronomy,
University of Victoria (astrowww.phys.uvic.ca).
Programming affiliations with the FreeEOS equation-of-state implementation
for stellar interiors (freeeos.sf.net); PLplot scientific plotting software
package (plplot.org); the libLASi project (unifont.org/lasi); the Loads of
Linux Links project (loll.sf.net); and the Linux Brochure Project
(lbproject.sf.net).
__________________________
Linux-powered Science
__________________________
5.Tips
5.1 批量获取文件
aux_source_directory(. MODULE_SOURCES)
# 获取当前文件夹下的所有文件
file(GLOB_RECURSE MODULE_SOURCES *.cpp)
# 获取当前文件夹下子文件夹里的所有文件
使用多个文件夹下的源文件:
file(GLOB_RECURSE MODULES_FILES "${PROJECT_SOURCE_DIR}/modules/*.cpp")
file(GLOB_RECURSE SAMPLE_FILES "${PROJECT_SOURCE_DIR}/samples/*.cpp")
add_executable(runmain ${MODULES_FILES} ${SAMPLE_FILES})
5.2 Visual Studio下Release模式
cmake -G "Visual Studio 15 2017" -A Win32/x64 ..
默认生成Debug工程,生成Release工程的方式是:cmake --build . --config Release
7. OpenCV更改工具链
对比如下图来修改CMakeList.txt
8. 将安装好的软件路径添加到环境变量
例如将cmake的bin路径添加到环境变量:
gedit ~/.bashrc
添加如下内容:
export PATH=/home/lg/05.Softwares/cmake-3.26.3-linux-x86_64/bin:$PATH
然后执行:
source ~/.bashrc
9. 文件操作
以下的关于文件的操作都发生在cmake ..
阶段,而不是make
或make install
的阶段。
创建目录:file(MAKE_DIRECTORY ./folder)
拷贝文件:file(COPY data.txt DESTINATION ../another_folder/data.txt)
删除文件:file(REMOVE data1.txt data2.txt)
重命名:file(RENAME old.txt new.txt)