Cmake summary(Linux) from Cmake practice

介绍

官网下载

1. 初始格式

  • CMakeList.txt文件
# 设立工程名字
PROJECT (HELLO)
# 设置变量, SRC_LIST=main.c
SET(SRC_LIST main.c)
# 显示信息,其中的${HELLO_BINARY_DIR}和${HELLO_SOURCE_DIR}是在构建工程HELLO会自动生成的隐式变量
MESSAGE(STATUS "This is BINARY dir " ${HELLO_BINARY_DIR})
MESSAGE(STATUS "This is SOURCE dir "${HELLO_SOURCE_DIR})
# 生成可执行文件
ADD_EXECUTABLE(hello SRC_LIST)
  • 之后便是cmake && make
cmake .
# use make VERBOSE=1 to show the details of 'make'
make
  • 总结
    • SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]]), 可以变量为list, 空格隔开SET(SRC_LIST main.c t1.c t2.c), 如果有特殊字符,比如文件名有空格,可以用双引号,如SET(SRC_LIST "fn abc.c")
    • MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] "message to display"...), SEND_ERROR产生错误,STATUS输出前缀为-的信息,FATAL_ERROR立即终止所有cmake过程
    • ADD_SUBDIRECTORY(lib),在主目录下的CMakeLists.txt文件里,对子文件的设置.

2. 子目录,规范

子目录,主目录,都需要有一个CMakeLists.txt,建立build来放置生成的文件,以及安装目录

  • 参数含义

    • 指示安装目录, 需要注意,如果在DESTINATION后使用/bin之类的,那么就是用的绝对路径,CMAKE_INSTALL_PREFIX就不管用了,
    #  直接在Cmake命令时利用-D来设置
    cmake -DCMAKE_INSTALL_PREFIX=/usr .
    
    # 在CMakeLists.txt文件中, INSTALL命令,TARGETS是固定的,后面接的是要安装的文件,RUNTIME表示
    # 可执行文件安装到bin目录下,LIBRARY动态库安装到lib下,ARCHIVE静态库安装到libstatic,当然,bin,
    # lib, libstatic都是在${CMAKE_INSTALL_PREFIX}主目录下的
    
    INSTALL(TARGETS myrun mylib mystaticlib
    	RUNTIME DESTINATION bin
    	LIBRARY DESTINATION lib
    	ARCHIVE DESTINATION libstatic
    )
    
    • 普通文件的安装
    INSTALL(FILES files... DESTINATION <dir>
    	[PERMISSIONS permissions...]
    	[CONFIGURATIONS [Debug|Release|...]]
    	[COMPONENT <component>]
    	[RENAME <name>] [OPTIONAL])
    
    • 非目标文件的可执行程序安装(比如脚本之类)
    INSTALL(PROGRAMS files... DESTINATION <dir>
    	[PERMISSIONS permissions...]
    	[CONFIGURATIONS [Debug|Release|...]]
    	[COMPONENT <component>]
    	[RENAME <name>] [OPTIONAL])
    
    • 目录的安装:
    INSTALL(DIRECTORY dirs... DESTINATION <dir>
    	[FILE_PERMISSIONS permissions...]
    	[DIRECTORY_PERMISSIONS permissions...]
    	[USE_SOURCE_PERMISSIONS]
    	[CONFIGURATIONS [Debug|Release|...]]
    	[COMPONENT <component>]
    	[[PATTERN <pattern> | REGEX <regex>]
    	[EXCLUDE] [PERMISSIONS permissions...]] [...])
    	
    # 栗子
    # 将  " icons 目录"   安装到 <prefix>/share/myproj,将   "scripts/中的内容"   安装到
    # <prefix>/share/myproj,不包含目录名为 CVS 的目录,对于 scripts/* 文件指定权限为 	
    # OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ 
    INSTALL(DIRECTORY icons scripts/ DESTINATION share/myproj
    	PATTERN "CVS" EXCLUDE
    	PATTERN "scripts/*"
    	PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ
    	GROUP_EXECUTE GROUP_READ)
    

3. 静态库和动态库构建

栗子

  • 文件目录

在这里插入图片描述

  • 主目录文件夹下CMakeLists.txt, 如果要指定 libhello.so 生成的位置,可以通过在主工程文件 CMakeLists.txt中修改 ADD_SUBDIRECTORY(lib ${path})指令来指定一个编译输出位置或者在 lib/CMakeLists.txt 中添加SET(LIBRARY_OUTPUT_PATH <路径>)来指定一个新的位置。
    PROJECT(HELLOLIB)
    ADD_SUBDIRECTORY(lib)
    
  • lib下CMakeLists.txt,其中
    SET(LIBHELLO_SRC hello.c)
    ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})
    
  • 总结
    # 不需要写全 libhello.so,只需要填写 hello 即可,cmake 系统会自动生成libhello.X
    # SHARED 动态库, STATIC 静态库, MODULE 在使用dyld系统 [苹果系统相关] 时有效,如果不支持dyld,当作SHARED对待 
    # EXCLUDE_FROM_ALL 参数的意思是这个库不会被默认构建,除非有其他的组件依赖或者手工构建。
    #
    ADD_LIBRARY(libname [SHARED|STATIC|MODULE] [EXCLUDE_FROM_ALL] 
    source1 source2 ... sourceN)
    
    栗子,添加为静态库
    ADD_LIBRARY(hello STATIC ${LIBHELLO_SRC})
    
    但是这样子单纯的去生成静态库动态库会导致名字重复而无效, 为了得到libhello.so动态库和libhello.a静态, 使用SET_TARGET_PROPERTIES来操作
    SET_TARGET_PROPERTIES(target1 target2 ...
    PROPERTIES prop1 value1
    prop2 value2 ...)
    
    SET(LIBHELLO_SRC hello.c)
    ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})
    ADD_LIBRARY(hello_static STATIC ${LIBHELLO_SRC})
    
    # 静态库hello_static重命名输出hello, 以下几句输出可省略
    SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME "hello")
    
    # OUTPUT_VALUE 赋值 hello_static. OUTPUT_NAME
    GET_TARGET_PROPERTY(OUTPUT_VALUE hello_static OUTPUT_NAME)
    MESSAGE(STATUS "This is the hello_static OUTPUT_NAME:"${OUTPUT_VALUE})
    
    # 设置版本信息, SOVERSION指代API版本, VERSION指代动态库版本
    SET_TARGET_PROPERTIES(hello PROPERTIES VERSION 1.2 SOVERSION 1)
    # 安装, CMAKE时, cmake -DCMAKE_INSTALL_PREFIX=./install ..
    INSTALL(TARGETS hello hello_static LIBRARY DESTINATION lib ARCHIVE DESTINATION lib)
    INSTALL(FILES hello.h DESTINATION include/hello)
    

4. 使用外部共享库和头文件

在这里插入图片描述

  • 主目录CMakeLists.txt
    PROJECT(NEWHELLO)
    ADD_SUBDIRECTORY(src)
    
  • 子目录下CMakeLists.txt
    # 这里貌似应该使用绝对路径,使用相对路径会报错,不知原因
    INCLUDE_DIRECTORIES(/home/coder/Desktop/backup/cmake/t3/build/install/include/hello)
    
    LINK_DIRECTORIES(/home/coder/Desktop/backup/cmake/t3/build/install/lib)
    
    ADD_EXECUTABLE(main main.c)
    
    TARGET_LINK_LIBRARIES(main libhello.so)
    
    在上面,可以对INCLUDE_DIRECTORIES进行另一种方式的修改, 使用两个环境变量CMAKE_INCLUDE_PATHCMAKE_LIBRARY_PATH.
    • 使用方法:使用方法是要在 bash 中用 export 或者在 csh 中使用 set 命令设置或者
      CMAKE_INCLUDE_PATH=/home/include cmake …等方式
      CMAKE_INCLUDE_PATH=/home/include cmake ..
      
      然后在头文件中将INCLUDE_DIRECTORIES(/home/coder/Desktop/backup/cmake/t3/build/install/include/hello)替换为
      # FIND_PATH使用方式:FIND_PATH(myHeader NAMES hello.h PATHS /usr/include/usr/include/hello)
      FIND_PATH(myHeader hello.h)
      IF(myHeader)
      INCLUDE_DIRECTORIES(${myHeader})
      ENDIF(myHeader)
      

5. cmake 常用变量和常用环境变量

  • 引用方式
    使用 进 行 变 量 的 引 用 。 在 I F 等 语 句 中 , 是 直 接 使 用 变 量 名 而 不 通 过 {}进行变量的引用。在 IF 等语句中,是直接使用变量名而不通过 IF,使{}取值
  • 定义变量
    主要有隐式定义显式定义两种
    • PROJECT 指令:(PROJECT(HELLO))
      隐式的定义<projectname>_BINARY_DIR<projectname>_SOURCE_DIR两个变量
    • 显式定义使用SET指令
  • cmake常用变量
    1.CMAKE_BINARY_DIR, PROJECT_BINARY_DIR, <projectname>_BINARY_DIR,这三个变量指代的内容一致,工程编译发生的目录.
    2.CMAKE_SOURCE_DIR,PROJECT_SOURCE_DIR,<projectname>_SOURCE_DIR都指代工程顶层目录。
    3.CMAKE_CURRENT_SOURCE_DIR指的是当前处理的 CMakeLists.txt 所在的路径
    4.EXECUTABLE_OUTPUT_PATHLIBRARY_OUTPUT_PATH分别用来重新定义最终结果的存放目录

5. cmake 常用指令

  1. ADD_DEFINITIONS
    向 C/C++编译器添加-D 定义, 比如:ADD_DEFINITIONS(-DENABLE_DEBUG -DABC),参数之间用空格分割
  2. ADD_DEPENDENCIES定义 target 依赖的其他 target,确保在编译本 target 之前,其他的 target 已经被构
    建。
  3. AUX_SOURCE_DIRECTORY基本语法是:AUX_SOURCE_DIRECTORY(dir VARIABLE)作用是发现一个目录下所有的源代码文件并将列表存储在一个变量中,这个指令临时被用来自动构建源文件列表。因为目前 cmake 还不能自动发现新添加的源文件。
  4. FIND_指令
  • FIND_FILE(<VAR> name1 path1 path2 ...), VAR 变量代表找到的文件全路径,包含文件名
  • FIND_LIBRARY(<VAR> name1 path1 path2 ...),VAR 变量表示找到的库全路径,包含库文件名
    FIND_LIBRARY 示例:
    FIND_LIBRARY(libX X11 /usr/lib)
    IF(NOT libX)
    MESSAGE(FATAL_ERROR “libX not found”)
    ENDIF(NOT libX)
    
  • FIND_PATH(<VAR> name1 path1 path2 ...),VAR 变量代表包含这个文件的路径
  • FIND_PROGRAM(<VAR> name1 path1 path2 ...),VAR 变量代表包含这个程序的全路径。
  • FIND_PACKAGE(<name> [major.minor] [QUIET] [NO_MODULE] [[REQUIRED|COMPONENTS] [componets...]])用来调用预定义在 CMAKE_MODULE_PATH 下的 Find.cmake 模块,你也可以自己定义 Find模块,通过 SET(CMAKE_MODULE_PATH dir)将其放入工程的某个目录中供工程使用,我们在后面的章节会详细介绍 FIND_PACKAGE 的使用方法和 Find 模块的编写

6. 复杂模块,等有工程需要再续…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值