CMakeLists 学习整理笔记 (一)

04. CMake项目的二进制目录和源目录

  CMake 会为每个项目的二进制目录、源目录隐式生成两个变量: <project_name>_BINARY_DIR 、<project_name>_SOURCE_DIR

  • <project_name>_BINARY_DIR = PROJECT_BINARY_DIR 执行 cmake命令所在的目录;
  • <project_name>_SOURCE_DIR = PROJECT_SOURCE_DIR 对应源文件的目录,即CMakeLists.txt对应的目录。
      建议使用 PROJECT_xxxx,不会随着项目名称改变而改变。

05. CMake构建静态库和动态库

   命令add_library 生成静态库/动态库

05.1 格式

add_library(lib_name [SHARE|STATIC|MODULE] [EXCLUDE_FROM_ALL] src1 src2)

参数说明

  • lib_name:指定生成库名称
  • SHARED:动态库
  • STATIC: 静态库
  • MODULE: 使用dyld(苹果的动态链接器)的系统有效,如不支持dyld,则为SHARED
  • EXCLUDE_FROM_ALL: 指定此参数,则该库默认不被构建,有其他组件用到该库或手动构建时才被构建
  • src1、src2…:用于构建库的源文件的

05.2 案例

05.2.1 文件结构

.
├── CMakeLists.txt
├── HelloLibrary.cpp
├── HelloLibrary.h
└── Main.cpp

05.2.2 CMakeLists.txt 文件

cmake_minimum_required(VERSION 3.8)		#检测CMake最低版本,最低版本3.8
project(HelloLibrary)					#项目工程名称

add_library(hello_library SHARED HelloLibrary.cpp) 	#指定库名为hello_library,因指明生成 SHARED(动态库),实际生成库文件名称为 libhello_library.so ,用于生成该库的源文件为 HelloLibrary.cpp
#add_library(hello_library STATIC HelloLibrary.cpp)	#指定库名为hello_library,因指明生成 STATIC(静态库),实际生成库文件名称为 libhello_library.a ,用于生成该库的源文件为 HelloLibrary.cpp
include_directories(${PROJECT_SOURCE_DIR}) 			#添加包含头文件的路径。此处,把项目源文件添加到包含头文件的路径中

add_executable(hello_main Main.cpp)					#指定生成可执行文件,生成的可执行文件名为 hello_main ,所需源文件为 Main.cpp

target_link_libraries(hello_main hello_library)		#指定某个目标的生成所依赖的库。此处,生成可执行文件hello_main要依赖hello_library库,即add_library指令生成的库

06. CMake添加工程子目录

   命令add_subdirectory 用于向当前工程添加子目录,并可指定中间二进制和目标二进制文件存放的位置,还可将指定目录排除出编译过程。

06.1 格式

add_subdirectory(src_dir [bin_dir] [EXCLUDE_FROM_ALL])

参数说明

  • src_dir:把src_dir 子目录加入工程
  • bin_dir:指定编译输出(包含编译的中间结果)的目录为bin_dir,如不指定默认输出目录为src_dir,即与src_dir的同名目录。指定本质是将src_dir重命名bin_dir
  • EXCLUDE_FROM_ALL: 指定此参数,将给定的目录从编译中排除,即不编译该指定目录,如,一些示例的目录,需等工程构建完后再单独构建。

06.2 案例

06.2.1 文件结构

.
├── CMakeLists.txt
└── src
    ├── CMakeLists.txt
    └── main.cpp

06.2.2 CMakeLists.txt 文件

  • 工程路径下 CMakeLists.txt
cmake_minimum_required(VERSION 3.8)
project(SubDirectory)
#add_subdirectory(src)				#指定源文件子目录为src,编译输出(包含编译的中间结果)的目录命名为src
add_subdirectory(src bin)			#指定源文件子目录为src,编译输出(包含编译的中间结果)的目录命名为bin
  • src 子目录路径下 CMakeLists.txt
add_executable(sub_directory main.cpp)

07. CMake指定目标保存目录

   虽命令add_subdirectory可用于指定编译输出目录,但无法将编译中间文件与目标文件分隔开,需要结合set设置EXECUTABLE_OUTPUT_PATHLIBRARY_OUTPUT_PATH 来指定最终目标二进制文件存放的位置与编译中间结果分隔开。

07.1 格式

set(EXECUTABLE_OUTPUT_PATH <dir>)
set(LIBRARY_OUTPUT_PATH <dir>)

参数说明

  • EXECUTABLE_OUTPUT_PATH:最终可执行文件存放的目录
  • LIBRARY_OUTPUT_PATH:最终库文件(静态、动态库)存放的目录

07.2 案例

07.2.1 文件结构

.
├── CMakeLists.txt
└── src
    ├── CMakeLists.txt
    ├── Main.cpp
    ├── SayHello.cpp
    └── SayHello.h

07.2.2 CMakeLists.txt 文件

  • 工程路径下 CMakeLists.txt
cmake_minimum_required(VERSION 3.8)
project(OutputPath)
add_subdirectory(src)
  • src 子目录路径下 CMakeLists.txt
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)	#把可执行文件生成于项目编译目录下的bin目录
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)		#把库文件生成于项目编译目录下的lib目录

add_library(SayHello SayHello.cpp)	#指定库名为 SayHello,默认采用STATIC(静态库)编译,实际生成库文件名称为 libSayHello.a ,用于生成该库的依赖源文件为 SayHello.cpp
include_directories(${PROJECT_SOURCE_DIR}/src)	#将源文件所在目录加入包含头文件目录中,如不加,会找不到SayHello.h该头文件
add_executable(OutputPath Main.cpp)
target_link_libraries(OutputPath SayHello)

08. CMake自定义安装

   命令INSTALL用于自定义安装规则,并配合CMAKE_INSTALL_PREFIX变量来指定安装的路径,自定义安装规则内容可以是可执行二进制文件、动态库(共享库)、静态库、普通文件、目录、非目标可执行文件(如脚本)、安装时执行cmake脚本等。

08.1 格式

08.1.1 二进制目标文件(可执行、动态库(共享库)、静态库)的安装

INSTALL(TARGRTS targets... [ARCHIVE|LIBRARY|RUNTIME] 
[DESTINATION <dir>] [PERMISSIONS permisssions...] 
[CONFIGURATIONS [Debug|Release|...]]
[COMPONENT <component> [OPTIONAL][...])

参数说明

  • TARGRTS : 后跟的 targets 即为add_executableadd_library定义的目标二进制可执行文件、目标二进制库
  • ARCHIVE|LIBRARY|RUNTIME : 分别指静态库、动态库(共享库)、可执行二进制文件
  • DESTINATION <dir> : 定义安装的路径,结合 CMAKE_INSTALL_PREFIX,路径为${CMAKE_INSTALL_PREFIX}/DESTINATION, 如 /开头,则直接从根目录开始, 此时CMAKE_INSTALL_PREFIX 路径无效,一般<dir>写相对路径
  • CONFIGURATIONS : 指定权限
  • COMPONENT : 指定版本

二进制目标文件示例

INSTALL(TARGETS exe sharedlib staticlib
	RUNTIME DESTINATION bin
	LIBRARY DESTINATION lib
	ARCHIVE DESTINATION static_lib)

   此句含义:

  • exe 安装到 ${CMAKE_INSTALL_PREFIX}/bin路径下
  • sharedlib 安装到 ${CMAKE_INSTALL_PREFIX}/lib路径下
  • staticlib 安装到 ${CMAKE_INSTALL_PREFIX}/static_lib路径下

08.1.2 普通文件的安装

INSTALL(FILES files... [DESTINATION <dir>]
[PERMISSIONS permisssions...] 
[CONFIGURATIONS [Debug|Release|...]]
[COMPONENT <component>] 
[RENAME <name>][OPTIONAL])

参数说明
   用于安装普通文件,可指定访问权限,文件名是此指令所在路径下的相对路径如不指定PERMISSIONS,安装后的权限为644权限

08.1.3 非目标可执行程序(如脚本)的安装

INSTALL(PROGRAMS files... [DESTINATION <dir>]
[PERMISSIONS permisssions...] 
[CONFIGURATIONS [Debug|Release|...]]
[COMPONENT <component>] 
[RENAME <name>][OPTIONAL])

参数说明
   类似安装普通文件,只是默认权限不一样安装后的权限为755权限

08.1.4 目录的安装

INSTALL(DIRECTORY dirs...  
[FILE_PERMISSIONS permisssions...] 
[DIRECTORY_PERMISSIONS permissions...]
[USE_SOURCE_PERMISSIONS]
[CONFIGURATIONS [Debug|Release|...]]
[COMPONENT <component>] 
[[PATTERN <pattern> | REGEX <regex>] [EXCLUDE] [PERMISSIONS permissions...]]
[...])

参数说明

  • DIRECTORY : 后跟的是所在源目录的相对路径, 目录后有无/区别很大!! dir 是将 dir 这个目录安装为目录路径下的 dir , 而 dir/ 是将 dir目录下的内容安装到目标目录.但不包含dir目录本身/
  • ARCHIVE|LIBRARY|RUNTIME : 分别指静态库、动态库(共享库)、可执行二进制文件
  • DESTINATION <dir> : 定义安装的路径,结合 CMAKE_INSTALL_PREFIX,路径为${CMAKE_INSTALL_PREFIX}/DESTINATION, 如 /开头,则直接从根目录开始, 此时CMAKE_INSTALL_PREFIX 路径无效,一般<dir>写相对路径
  • PATTERN : 使用正则表达式进行过滤
  • PERMISSIONS : 用于指定 PATTERN 过滤后的文件权限

目录安装示例

INSTALL(DIRECTORY samples modules/ DESTINATION share
	PATTERN "TXT" EXCLUDE
	PATTERN "modules/*" 
	PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ)

   此句含义:

  • samples 目录安装到 ${CMAKE_INSTALL_PREFIX}/share路径下
  • modules/ 目录中的内容安装到 ${CMAKE_INSTALL_PREFIX}/share路径下,不包含目录名为 TXT 的目录,并对 modules/ 目录下的文件赋予750权限

08.1.5 安装时执行cmake脚本

INSTALL([[SCRIPT <file>] [CODE <code]] [...])

参数说明

  • SCRIPT : 用于在安装时调用 cmake 脚本文件,即 xxxx.cmake 文件
  • CODE : 执行 cmake 指令,要用双引号
INSTALL(CODE "MESSAGE(\"Sample install message.\")")

08.2 案例

08.2.0 操作方法

  • a) 命令归纳
cmake -DCMAKE_INSTALL_PREFIX=/tmp ..
make
make install
  • b) 操作打印
gene@gene:~/00_CMakeLists/cmake-master/08_CustomizeInstall/build$ cmake -DCMAKE_INSTALL_PREFIX=/tmp ..
-- The C compiler identification is GNU 7.5.0
-- The CXX compiler identification is GNU 7.5.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/gene/00_CMakeLists/cmake-master/08_CustomizeInstall/build
gene@gene:~/00_CMakeLists/cmake-master/08_CustomizeInstall/build$ make
Scanning dependencies of target customize_install
[ 50%] Building CXX object bin/CMakeFiles/customize_install.dir/Main.cpp.o
[100%] Linking CXX executable customize_install
[100%] Built target customize_install
gene@gene:~/00_CMakeLists/cmake-master/08_CustomizeInstall/build$ make install
[100%] Built target customize_install
Install the project...
-- Install configuration: ""
-- Up-to-date: /tmp/CustomizeInstall/copyright
-- Up-to-date: /tmp/CustomizeInstall/readme
-- Up-to-date: /tmp/CustomizeInstall/bin/run_customize_install.sh
-- Up-to-date: /tmp/CustomizeInstall/share/doc
-- Up-to-date: /tmp/CustomizeInstall/share/doc/customize_install_doc.txt
-- Installing: /tmp/CustomizeInstall/bin/customize_install

08.2.1 文件结构

.
├── CMakeLists.txt
├── copyright
├── doc
│   └── customize_install_doc.txt
├── readme
├── run_customize_install.sh
└── src
    ├── CMakeLists.txt
    └── Main.cpp

08.2.2 CMakeLists.txt 文件

  • 工程路径下 CMakeLists.txt
cmake_minimum_required(VERSION 3.8)         # 指定最小CMake版本
project(CustomizeInstall)                   # 指定项目工程名称
add_subdirectory(src bin)                   # 将 src 源文件子目录加入项目中
install(FILES copyright readme DESTINATION CustomizeInstall)    # 将 copyright, readme 这两个文件安装到目录/${CMAKE_INSTALL_PREFIX}/CustomizeInstall下
install(PROGRAMS run_customize_install.sh DESTINATION CustomizeInstall/bin) # 将 run_customize_install.sh 脚本文件安装到目录/${CMAKE_INSTALL_PREFIX}/CustomizeInstall/bin下
install(DIRECTORY doc/ DESTINATION CustomizeInstall/share/doc)  # 将 doc/ 目录下所有文件(不包含该目录本身)安装到目录/${CMAKE_INSTALL_PREFIX}/CustomizeInstall/share/doc下

  • src 子目录路径下 CMakeLists.txt
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)               #设置二进制目标可执行文件存放路径

add_executable(customize_install Main.cpp)                          #生成二进制目标可执行文件

install(TARGETS customize_install DESTINATION CustomizeInstall/bin) #指定该可执行二进制文件要安装的路径,此处为:/${CMAKE_INSTALL_PREFIX}/CustomizeInstall/bin

09. CMake设置生成库的属性

   命令set_target_properties可用于设置目标的属性, get_target_properties可用于获得目标的属性。

09.1 格式

09.1.1 设置属性

set_target_properties(target1 target2... properties prop1 value1 prop2 value2 ...)

参数说明

  • target1 target2:指定要设置属性的目标
  • prop1 value1:指定要设置属性名与属性值,如,OUTPUT_NAME, VERSION, SOVERSION
  • 09.1.2 获得属性

get_target_property(VAR target prop)

参数说明

  • VAR:获取的属性存放的变量
  • target:目标
  • prop:要获取的属性名

09.2 案例

09.2.1 文件结构

.
├── CMakeLists.txt
└── src
    ├── CMakeLists.txt
    ├── linear.cpp
    └── linear.h

09.2.2 CMakeLists.txt 文件

  • 工程路径下 CMakeLists.txt
cmake_minimum_required(VERSION 3.8)
project(LibraryProperty)
add_subdirectory(src)
  • src 子目录路径下 CMakeLists.txt
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)  # 设置生成库的存放目录,为编译目录的 lib 子目录

add_library(linear SHARED linear.cpp)               # 添加生成动态库目标,目标名为 linea          
add_library(static_linear STATIC linear.cpp)        # 添加生成静态库目标,目标名为 static_linea 

set_target_properties(static_linear PROPERTIES OUTPUT_NAME "linear")    # 设置静态库目标输出名为 linear

get_target_property(OUTPUT_VALUE static_linear OUTPUT_NAME)         # 获取 static_linear 属性值(OUTPUT_NAME)保存至 OUTPUT_VALUE 变量中
message(STATUS "OUTPUT_NAME = ${OUTPUT_VALUE}")                     # 将 OUTPUT_VALUE 变量中的值打印出来 (打印结果:OUTPUT_NAME = linear)

get_target_property(UNDEFINE_VALUE static_linear UNDEFINE_NAME)     # 获取 static_linear E未定义属性值(UNDEFINE_NAM)保存至 OUTPUT_VALUE 变量中
message(STATUS "UNDEFINE_NAME = ${UNDEFINE_VALUE}")                 # 将 UNDEFINE_VALUE 变量中的值打印出来,作对比(打印结果:UNDEFINE_NAME = UNDEFINE_VALUE-NOTFOUND)

set_target_properties(linear PROPERTIES VERSION 1.0 SOVERSION 1)    # 设置动态库版本号(VERSION)  API号(SOVERSION)

install(TARGETS linear static_linear LIBRARY DESTINATION lib ARCHIVE DESTINATION lib/${PROJECT_NAME}) # 动态库安装到<perfix>/lib 静态库安装到<prefix>lib/${PROJECT_NAME}
install(FILES linear.h DESTINATION include/${PROJECT_NAME})         # 头文件安装到<perfix>/include/${PROJECT_NAME}

10. CMake调用外部库

   命令target_link_libraries 用于调用外部库,为目标添加需要链接的库,命令link_libraries 用于为目标添加需要链接的库的目录,二者结合使用,前者指定具体库名称,后者指定库路径所在目录路径。include_directories 用于添加头文件搜索路径。link_directories 用于添加非系统(非标准)的库搜索路径。。

10.1 格式

命令汇总

target_link_libraries(target lib1 <debug | optimized> lib2 ...)
include_directories([AFTER | BEFORE] [SYSTEM] dir1 dir2 ...)
link_directories(dir1 dir2 ...)
link_libraries([item1 [item2 [...]]] 
	[[debug | optimized | general] <item>])

10.1 .1 添加链接库

target_link_libraries(target lib1 <debug | optimized> lib2 ...)

参数说明

  • target:目标二进制文件
  • lib1:库名称

添加需要链接外部库示例

target_link_libraries(main linear)
target_link_libraries(main liblinear.so)
target_link_libraries(main liblinear.a)

   该句含义:

  • 目标 main 链接到 linear 动态库
  • 目标 main 链接到 linear 动态库
  • 目标 main 链接到 linear 静态 库

10.1 .2 添加头文件搜索路径

include_directories([AFTER | BEFORE] [SYSTEM] dir1 dir2 ...)

说明

  • 多个路径用空格分开,如路径有空格,路径用双引号引起来;
  • 默认添加到搜索路径的后面,可通过 AFTERBEFORE 来控制添加到前面还是后面
  • CMake 变量 CMAKE_INCLUDE_DIRECTORIES_BEFORE设置为on 也可把路径添加至前面

10.1 .3 添加非系统(非标准)的库搜索路径

link_directories(dir1 dir2 ...)

说明
   此命令要放在add_executable目标之前, 如, 要放在 add_executableadd_library 之前

10.1 .4 添加链接库目录

link_libraries([item1 [item2 [...]]]
	[[debug | optimized | general] <item>])

说明
   此命令要放在目标之前, 如, 要放在 add_executableadd_library 之前, 指定的库要全称

10.2 案例

10.2.1 文件结构

  • 工程文件结构
.
├── CMakeLists.txt
└── src
    ├── CMakeLists.txt
    └── Main.cpp
  • 外部库文件结构
.
├── liblinear.so -> liblinear.so.1
├── liblinear.so.1 -> liblinear.so.1.0
├── liblinear.so.1.0
└── LibraryProperty
    └── liblinear.a

10.2.2 CMakeLists.txt 文件

  • 工程路径下 CMakeLists.txt
cmake_minimum_required(VERSION 3.8)
project(ExternalLibrary)
add_subdirectory(src)
  • src 子目录路径下 CMakeLists.txt
# 版本1 使用link_libraries 添加动/静态库
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)   # 设置二进制目标文件输出的存放目录,为编译目录的bin子目录
link_libraries(/tmp/lib/liblinear.so)                 # 添加(动态)链接库,注意:全路径, 一定在 add_executable 前面 (无此类似句,会报" undefined reference to `linear_fit()' ... " 错误,即没找到要链接的库)
# link_libraries(/tmp/lib/LibraryProperty/liblinear.a)    # 添加(静态)链接库,注意:全路径, 一定在 add_executable 前面 (无此类似句,会报" undefined reference to `linear_fit()' ... " 错误,即没找到要链接的库)
add_executable(ExternalLibrary Main.cpp)                # 添加二进制目标,依赖 Main.cpp 
include_directories(/tmp/include/LibraryProperty)       # 添加对应头文件的目录  (无此句,会报"No such file or directory ..." 错误,即没找到对应头文件)

#版本2 使用target_link_libraries链接静态库
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)   # 设置二进制目标文件输出的存放目录,为编译目录的bin子目录

link_directories(/tmp/lib/LibraryProperty)            # 添加静态库对应的目录,注意:在 add_executable前面!!(因该路径下只有静态库,虽 target_link_libraries 指定动态库,实际结果也会是静态库)
# link_directories(/tmp/lib)                              # 添加动态库对应的目录,注意:在 add_executable前面!!(虽该路径下有含静态库的目录LibraryProperty,但依旧会报错,即此时 target_link_libraries 链接不到静态库)
add_executable(ExternalLibrary Main.cpp)                # 添加二进制目标,依赖 Main.cpp 
include_directories(/tmp/include/LibraryProperty)       # 添加对应头文件的目录  (无此句,会报"No such file or directory ..." 错误,即没找到对应头文件)
target_link_libraries(ExternalLibrary liblinear.a)    # 添加链接(静态)库,注意:在 add_executable后面  (无此类似句,会报" undefined reference to `linear_fit()' ... " 错误,即没找到要链接的库)


#版本3 使用target_link_libraries链接动态库
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)   # 设置二进制目标文件输出的存放目录,为编译目录的bin子目录

link_directories(/tmp/lib)                              # 添加动态库对应的目录,注意:在 add_executable前面!!
add_executable(ExternalLibrary Main.cpp)                # 添加二进制目标,依赖 Main.cpp 
include_directories(/tmp/include/LibraryProperty)       # 添加对应头文件的目录  (无此句,会报"No such file or directory ..." 错误,即没找到对应头文件)
target_link_libraries(ExternalLibrary liblinear.so)      # 添加链接(动态)库,注意:在 add_executable后面  (无此类似句,会报" undefined reference to `linear_fit()' ... " 错误,即没找到要链接的库)


猜你喜欢

转载自blog.csdn.net/qq_38429958/article/details/128691296