CMake 会为每个项目的二进制目录、源目录隐式生成两个变量:
_BINARY_DIR = PROJECT_BINARY_DIR
执行 cmake
命令所在的目录;_SOURCE_DIR = PROJECT_SOURCE_DIR
对应源文件的目录,即CMakeLists.txt对应的目录。PROJECT_xxxx
,不会随着项目名称改变而改变。 命令add_library
生成静态库/动态库
add_library(lib_name [SHARE|STATIC|MODULE] [EXCLUDE_FROM_ALL] src1 src2)
参数说明
.
├── CMakeLists.txt
├── HelloLibrary.cpp
├── HelloLibrary.h
└── Main.cpp
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.cpptarget_link_libraries(hello_main hello_library) #指定某个目标的生成所依赖的库。此处,生成可执行文件hello_main要依赖hello_library库,即add_library指令生成的库
命令add_subdirectory
用于向当前工程添加子目录,并可指定中间二进制和目标二进制文件存放的位置,还可将指定目录排除出编译过程。
add_subdirectory(src_dir [bin_dir] [EXCLUDE_FROM_ALL])
参数说明
src_dir
子目录加入工程bin_dir
,如不指定默认输出目录为src_dir
,即与src_dir
的同名目录。指定本质是将src_dir
重命名为bin_dir
.
├── CMakeLists.txt
└── src├── CMakeLists.txt└── main.cpp
CMakeLists.txt
cmake_minimum_required(VERSION 3.8)
project(SubDirectory)
#add_subdirectory(src) #指定源文件子目录为src,编译输出(包含编译的中间结果)的目录命名为src
add_subdirectory(src bin) #指定源文件子目录为src,编译输出(包含编译的中间结果)的目录命名为bin
CMakeLists.txt
add_executable(sub_directory main.cpp)
虽命令add_subdirectory
可用于指定编译输出目录,但无法将编译中间文件与目标文件分隔开,需要结合set
设置EXECUTABLE_OUTPUT_PATH
、LIBRARY_OUTPUT_PATH
来指定最终目标二进制文件存放的位置与编译中间结果分隔开。
set(EXECUTABLE_OUTPUT_PATH )
set(LIBRARY_OUTPUT_PATH )
参数说明
.
├── CMakeLists.txt
└── src├── CMakeLists.txt├── Main.cpp├── SayHello.cpp└── SayHello.h
CMakeLists.txt
cmake_minimum_required(VERSION 3.8)
project(OutputPath)
add_subdirectory(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)
命令INSTALL
用于自定义安装规则,并配合CMAKE_INSTALL_PREFIX
变量来指定安装的路径,自定义安装规则内容可以是可执行二进制文件、动态库(共享库)、静态库、普通文件、目录、非目标可执行文件(如脚本)、安装时执行cmake脚本等。
INSTALL(TARGRTS targets... [ARCHIVE|LIBRARY|RUNTIME]
[DESTINATION ] [PERMISSIONS permisssions...]
[CONFIGURATIONS [Debug|Release|...]]
[COMPONENT [OPTIONAL][...])
参数说明
add_executable
、add_library
定义的目标二进制可执行文件、目标二进制库CMAKE_INSTALL_PREFIX
,路径为${CMAKE_INSTALL_PREFIX}/DESTINATION
, 如 以/
开头,则直接从根目录开始, 此时CMAKE_INSTALL_PREFIX 路径无效,一般
写相对路径二进制目标文件示例
INSTALL(TARGETS exe sharedlib staticlibRUNTIME DESTINATION binLIBRARY DESTINATION libARCHIVE DESTINATION static_lib)
此句含义:
exe
安装到 ${CMAKE_INSTALL_PREFIX}/bin
路径下sharedlib
安装到 ${CMAKE_INSTALL_PREFIX}/lib
路径下staticlib
安装到 ${CMAKE_INSTALL_PREFIX}/static_lib
路径下INSTALL(FILES files... [DESTINATION ]
[PERMISSIONS permisssions...]
[CONFIGURATIONS [Debug|Release|...]]
[COMPONENT ]
[RENAME ][OPTIONAL])
参数说明
用于安装普通文件,可指定访问权限,文件名是此指令所在路径下的相对路径如不指定PERMISSIONS
,安装后的权限为644权限
INSTALL(PROGRAMS files... [DESTINATION ]
[PERMISSIONS permisssions...]
[CONFIGURATIONS [Debug|Release|...]]
[COMPONENT ]
[RENAME ][OPTIONAL])
参数说明
类似安装普通文件,只是默认权限不一样安装后的权限为755权限
INSTALL(DIRECTORY dirs...
[FILE_PERMISSIONS permisssions...]
[DIRECTORY_PERMISSIONS permissions...]
[USE_SOURCE_PERMISSIONS]
[CONFIGURATIONS [Debug|Release|...]]
[COMPONENT ]
[[PATTERN | REGEX ] [EXCLUDE] [PERMISSIONS permissions...]]
[...])
参数说明
/
区别很大!! dir
是将 dir 这个目录安装为目录路径下的 dir , 而 dir/
是将 dir目录下的内容安装到目标目录.但不包含dir目录本身/CMAKE_INSTALL_PREFIX
,路径为${CMAKE_INSTALL_PREFIX}/DESTINATION
, 如 以/
开头,则直接从根目录开始, 此时CMAKE_INSTALL_PREFIX 路径无效,一般
写相对路径目录安装示例
INSTALL(DIRECTORY samples modules/ DESTINATION sharePATTERN "TXT" EXCLUDEPATTERN "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权限INSTALL([[SCRIPT ] [CODE
参数说明
INSTALL(CODE "MESSAGE(\"Sample install message.\")")
cmake -DCMAKE_INSTALL_PREFIX=/tmp ..
make
make install
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
.
├── CMakeLists.txt
├── copyright
├── doc
│ └── customize_install_doc.txt
├── readme
├── run_customize_install.sh
└── src├── CMakeLists.txt└── Main.cpp
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下
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
命令set_target_properties
可用于设置目标的属性, get_target_properties
可用于获得目标的属性。
set_target_properties(target1 target2... properties prop1 value1 prop2 value2 ...)
参数说明
get_target_property(VAR target prop)
参数说明
.
├── CMakeLists.txt
└── src├── CMakeLists.txt├── linear.cpp└── linear.h
CMakeLists.txt
cmake_minimum_required(VERSION 3.8)
project(LibraryProperty)
add_subdirectory(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") # 设置静态库目标输出名为 linearget_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}) # 动态库安装到/lib 静态库安装到lib/${PROJECT_NAME}
install(FILES linear.h DESTINATION include/${PROJECT_NAME}) # 头文件安装到/include/${PROJECT_NAME}
命令target_link_libraries
用于调用外部库,为目标添加需要链接的库,命令link_libraries
用于为目标添加需要链接的库的目录,二者结合使用,前者指定具体库名称,后者指定库路径所在目录路径。include_directories
用于添加头文件搜索路径。link_directories
用于添加非系统(非标准)的库搜索路径。。
命令汇总
target_link_libraries(target lib1 lib2 ...)
include_directories([AFTER | BEFORE] [SYSTEM] dir1 dir2 ...)
link_directories(dir1 dir2 ...)
link_libraries([item1 [item2 [...]]] [[debug | optimized | general] - ])
target_link_libraries(target lib1 lib2 ...)
参数说明
添加需要链接外部库示例
target_link_libraries(main linear)
target_link_libraries(main liblinear.so)
target_link_libraries(main liblinear.a)
该句含义:
include_directories([AFTER | BEFORE] [SYSTEM] dir1 dir2 ...)
说明
AFTER
和 BEFORE
来控制添加到前面还是后面CMAKE_INCLUDE_DIRECTORIES_BEFORE
设置为on 也可把路径添加至前面link_directories(dir1 dir2 ...)
说明
此命令要放在add_executable
目标之前, 如, 要放在 add_executable
或 add_library
之前
link_libraries([item1 [item2 [...]]][[debug | optimized | general] - ])
说明
此命令要放在目标之前, 如, 要放在 add_executable
或 add_library
之前, 指定的库要全称
.
├── 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
CMakeLists.txt
cmake_minimum_required(VERSION 3.8)
project(ExternalLibrary)
add_subdirectory(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()' ... " 错误,即没找到要链接的库)