cmake和autotools是makefile的上层工具,它们的目的是为了产生可移植的makefile,并简化自己动手写makefile时的巨大工作量。
RPATH、RUNPATH、LD_LIBRARY_PATH三者之间,优先级为RPATH > LD_LIBRARY_PATH > RUNPATH。
当RUNPATH存在时,则RPATH失效。
RUNPATH不适用于间接依赖的库。
使用RUNPATH时,可能需要配合使用LD_LIBRARY_PATH来指定依赖库文件的路径。
静态库test1
root@ubuntu:/home/xxxx/test/CMakeTest/static1# cat CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
set(CMAKE_INSTALL_PREFIX /tangtest)
PROJECT(Static1)
#set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "-std=c++11")
#指定目录,编译该目录下所有cpp文件
#AUX_SOURCE_DIRECTORY(. DIR_TEST1_SRCS)
#ADD_LIBRARY ( test1 ${DIR_TEST1_SRCS})
#指定文件进行编译
set(SRC_LIST test1.cpp)
add_library(test1 STATIC ${SRC_LIST})
install(TARGETS test1 DESTINATION lib)
install(FILES test1.h DESTINATION include)
动态库test2
root@ubuntu:/home/xxxx/test/CMakeTest/static1# cat CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
set(CMAKE_INSTALL_PREFIX /tangtest)
PROJECT(Static1)
#set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "-std=c++11")
#指定目录,编译该目录下所有cpp文件
#AUX_SOURCE_DIRECTORY(. DIR_TEST1_SRCS)
#ADD_LIBRARY ( test1 ${DIR_TEST1_SRCS})
#指定文件进行编译
set(SRC_LIST test1.cpp)
add_library(test1 STATIC ${SRC_LIST})
install(TARGETS test1 DESTINATION lib)
install(FILES test1.h DESTINATION include)
root@ubuntu:/home/xxxx/test/CMakeTest/static1# cd ../../
root@ubuntu:/home/xxxx/test# cat static2/CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
set(CMAKE_INSTALL_PREFIX /tangtest)
PROJECT(Test2)
#set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "-std=c++11")
#指定目录,编译该目录下所有cpp文件
#AUX_SOURCE_DIRECTORY(. DIR_TEST1_SRCS)
#ADD_LIBRARY ( test1 ${DIR_TEST1_SRCS})
#指定文件进行编译
set(SRC_LIST test2.cpp)
#add_library(test2 STATIC ${SRC_LIST})
add_library(test2 SHARED ${SRC_LIST})
#VERSION 指代动态库版本,SOVERSION 指代 API 版本
SET_TARGET_PROPERTIES(test2 PROPERTIES VERSION 1.2 SOVERSION 1)
install(TARGETS test2 DESTINATION lib)
install(FILES test2.h DESTINATION include)
主程序
#cmake最低版本需求,不加入此行会受到警告信息
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
set(CMAKE_INSTALL_PREFIX /tangtest)
#设置运行时动态库的加载路径,另一种设置使用SET_TARGET_PROPERTIES(tang PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
#set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
#set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
#在环境(cmake version 2.8.12.2, g++ (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4) 上验证只能使用CMAKE_CXX_FLAGS设置C++11,使用CMAKE_CXX_STANDARD编译会出错
#set(cmake_cxx_sTANDARD 11)
#set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_CXX_FLAGS "-std=c++11")
PROJECT(TANG) #项目名称
#项目名称隐式指定了下面两个变量
MESSAGE(${TANG_BINARY_DIR})#/home/xxx/test/CMakeTest/build
MESSAGE(${TANG_SOURCE_DIR})#/home/xxx/test/CMakeTest
#下面两个变量跟工程名无关,比TANG_BINARY_DIR和TANG_SOURCE_DIR更好用
MESSAGE(${PROJECT_BINARY_DIR})
MESSAGE(${PROJECT_SOURCE_DIR})
#通过修改内置变量EXECUTABLE_OUTPUT_PATH,LIBRARY_OUTPUT_PATH 可以更改可执行程序和库的生成目录
#SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
#SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
#没有set之前EXECUTABLE_OUTPUT_PATH,LIBRARY_OUTPUT_PATH是没有定义的不可输出
#MESSAGE(${EXECUTABLE_OUTPUT_PATH})
#MESSAGE(${LIBRARY_OUTPUT_PATH})
#指定编译的子目录,子目录里面可以是这个主程序的代码文件,也可以是单独一个库的代码(包含自己的CMkeList.txt)
#默认编译后生成的中间文件和结果文件在build/static1目录下。
#add_subdirectory(static1)
add_subdirectory(static1 /${PROJECT_SOURCE_DIR}/lib/tmp)
#add_subdirectory(static1 ${PROJECT_SOURCE_DIR}/lib/tmp EXCLUDE_FROM_ALL)
#指定外部库的链接路径,必须是在ADD_EXECUTABLE之前指定
#link_directories("${CMAKE_SOURCE_DIR}/../static/")
link_directories("${CMAKE_INSTALL_PREFIX}/lib")
#把当前目录(.)下所有源代码文件和头文件加入变量SRC_LIST
#AUX_SOURCE_DIRECTORY(. SRC_LIST)
#编译当前目录和子目录的指定cpp
set(SRC_LIST test.cpp src/test0.cpp)
#生成应用程序 tang,工程名的 TANG 和生成的可执行文件 tang 是没有任何关系的
ADD_EXECUTABLE(tang ${SRC_LIST})
#修改输出的名字
SET_TARGET_PROPERTIES(tang PROPERTIES OUTPUT_NAME "HelloTest")
SET_TARGET_PROPERTIES(tang PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")#同set(CMAKE_INSTALL_RPATH ..)
#对tang这个住程序添加包含路径
#target_include_directories(tang PUBLIC ${CMAKE_SOURCE_DIR}/../static)
target_include_directories(tang PUBLIC ${CMAKE_INSTALL_PREFIX}/include)
#链接库,必须是在ADD_EXECUTABLE之后,因为之前生成的可执行程序名tang还不存在
#TARGET_LINK_LIBRARIES( tang test1 )#test1是通过编译时指定ADD_SUBDIRECTORY使编译主程序的同时编译test1静态库,test1编译之后会在主程序的build目录自动生成test1的编译中间文件和库文件,所以链接时不需要显示指定链接目录,主程序会自动到ADD_SUBDIRECTORY指定的子目录去链接
TARGET_LINK_LIBRARIES( tang test1 test2 )#test2是外部编译好的库,需要通过link_directories显示引入库的路径
打包
# 指定deb包的版本号
set(_VERSION_MAJOR 1)
set(_VERSION_MINOR 2)
set(_VERSION_PATCH 3)
set(CPACK_PACKAGE_VERSION_MAJOR "${_VERSION_MAJOR}")
set(CPACK_PACKAGE_VERSION_MINOR "${_VERSION_MINOR}")
set(CPACK_PACKAGE_VERSION_PATCH "${_VERSION_PATCH}")
# 指定CPack生成的是deb包(还可以是其他包如 <.7z> <.zip> 等)
set(CPACK_GENERATOR "DEB")
# 指定打包后生成的包名
set(CPACK_PACKAGE_NAME "tang-cmake-test")
# 指定安装后的包名
set(CPACK_DEBIAN_PACKAGE_NAME "tang-cmake-test")
# 指定运行的计算机架构
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64")
# 指定所需的依赖
# set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc")
# 设置包作者的联系方式
set(CPACK_PACKAGE_CONTACT "tang@quanshi.com")
# 设置维护人
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "tang@quanshi.cn")
#生成之后安装
install(TARGETS tang DESTINATION bin)
install(DIRECTORY conf/ DESTINATION conf)
install(PROGRAMS test.sh DESTINATION bin)
include(CPack)
执行:
root@ubuntu:/home/xxx/test/CMakeTest/build# cmake ..
root@ubuntu:/home/xxx/test/CMakeTest/build# make
root@ubuntu:/home/xxx/test/CMakeTest/build# make package
生成包 /home/xxx/test/CMakeTest/build/tang-cmake-test-1.2.3-Linux.deb
查看包安装的内容:
root@ubuntu:/home/xxx/test/CMakeTest/build# dpkg -c /home/xxx/test/CMakeTest/build/tang-cmake-test-1.2.3-Linux.deb
drwxr-xr-x root/root 0 2023-01-13 18:48 ./usr/
drwxr-xr-x root/root 0 2023-01-13 18:48 ./usr/conf/
-rw-r--r-- root/root 15 2023-01-13 17:33 ./usr/conf/test.conf
drwxr-xr-x root/root 0 2023-01-13 18:48 ./usr/bin/
-rwxr-xr-x root/root 5 2023-01-13 17:38 ./usr/bin/test.sh
-rwxr-xr-x root/root 9091 2023-01-13 17:54 ./usr/bin/HelloTest
drwxr-xr-x root/root 0 2023-01-13 18:48 ./usr/lib/
-rw-r--r-- root/root 1844 2023-01-13 17:52 ./usr/lib/libtest1.a
drwxr-xr-x root/root 0 2023-01-13 18:48 ./usr/include/
-rw-r--r-- root/root 363 2023-01-13 10:47 ./usr/include/test1.h
CMAKE_CXX_FLAGS "-std=c++11"
在有的 ubuntu 14,使用 set(CMAKE_CXX_STANDARD 11) 编译出错
error: #error This file requires compiler and library support for the ISO C++ 2011 standard. This support is currently experimental, and must be enabled with the -std=c++11 or -std=gnu++11 compiler options.
#error This file requires compiler and library support for the \
改用 set(CMAKE_CXX_FLAGS "-std=c++11") 之后编译通过
cmake
常见的变量(即选项)
-
CMAKE_CXX_STANDARD变量增加c++11标准:set(CMAKE_CXX_STANDARD 11)
CMAKE_CXX_FLAGS变量增加pthread支持:set(CMAKE_CXX_FLAGS -pthread)
CMAKE_CXX_FLAGS为多个选项:set(CMAKE_CXX_FLAGS "-pthread -g -Wall")
CMAKE_CXX_FLAGS变量让程序先找当前目录:set(CMAKE_CXX_FLAGS "-Wl,-rpath=.")
VERSION 指代动态库版本,SOVERSION 指代 API 版本
SET_TARGET_PROPERTIES(test2 PROPERTIES VERSION 1.2 SOVERSION 1)
root@ubuntu:/home/xxx/test/static2/build# ll
total 52
drwxr-xr-x 3 root root 4096 Jan 16 10:00 ./
drwxr-xr-x 3 root root 4096 Jan 16 09:59 ../
-rw-r--r-- 1 root root 11994 Jan 13 17:02 CMakeCache.txt
drwxr-xr-x 5 root root 4096 Jan 16 10:00 CMakeFiles/
-rw-r--r-- 1 root root 3110 Jan 16 10:00 cmake_install.cmake
-rw-r--r-- 1 root root 52 Jan 13 17:04 install_manifest.txt
lrwxrwxrwx 1 root root 13 Jan 16 10:00 libtest2.so -> libtest2.so.1*
lrwxrwxrwx 1 root root 15 Jan 16 10:00 libtest2.so.1 -> libtest2.so.1.2*
-rwxr-xr-x 1 root root 8207 Jan 16 10:00 libtest2.so.1.2*