CMakeList.txt -- 编写保姆式教程

简介: CMakeList.txt -- 编写保姆式教程

    致每一个还坚持在互联网和软件行业的同路人。

    最近有朋友问我为什么选择当程序员,我也不明白。可能是缺少社交能力,可能更喜欢心理上保存平静,可能是为了那份对于从无到有的沉浸感和满足感。

定义

       cmake是一种高级编译工具,所有的操作系统都是通过编译CMakeList.txt来完成的,当多个人用不同的语言或者编译器开发同一个项目的时候,最终要输出一个可执行文件或者共享库的时候使用cmake很方便。

       camke的下载网址:cmake不同版本下载地址

PROJECT关键字

       可以用来指定工程的名字和支持的语言,默认支持所有的语言。

       project(XXXX)            ===>         指定了工程的名字,并且支持所有语言

       project(XXXX CXX)     ===>       指定了工程的名字,并且支持的语言是C++

      project(XXXX C CXX)  ===>       指定了工程的名字,并且支持的语言是C 和 C++

XXXX_BINARY_DIR 和 XXXX _SOURCE_DIR

       <projectname>_BINARY_DIR 和 <projectname>_SOURCE_DIR它们都指向了当前的工作目录,当工程的名字发生改变时这两个变量的名字也会跟着改变。

       使用 PROJECT_BINARY_DIR和PROJECT_SOURCE_DIR

SET关键字

       用来显示指定变量

       SET(SRC_LIST main.cpp) ==> SRC_LIST变量就包含了main.cpp

       SET(SRC_LIST main.cpp demo1.cpp demo3.cpp demo1.h) ==> SRC_LIST变量就包含了main.cpp demo1.cpp demo3.cpp demo1.h

       设置使用g++编译器

       set(CMAKE_CXX_COMPILER "g++")

       指定编译器

       set(CMAKE_CXX_STANDARD 11)

       添加c++11的支持,nation指定目标程序的cpu架构来进行程序优化 -O3优化等级

       set(CMAKE_CXX_FLAGS "-std=c++11 -march=native -O3")

       ===> native 就是相当于自检查cpu,-march是gcc优化选项,-Ox 这个参数只有在 cmake -DCMAKE_BUILD_TYPE=release时有效

       版本号

       set (XXXX VERSION 0.0.1)

MESSAGE关键字

       向终端输出用户自定义的信息

       主要包含三种信息:

       SEND_ERROR    ==>   产生错误,生成编译过程中被跳过

      STAUS                 ==>   输出前缀为一的信息

       FATAL_ERROR   ==>   立即终止所有cmake过程

       message(STATUS "This is BINARY dir" $(PROJECT_BINARY_DIR))

       message(STATUS "This is SOURCE dir"  $(PROJECT_SOURCE_DIR))

ADD_EXECUTABLE关键字

       生成可执行文件

       ADD_EXECUTABLE(XXX ${SRC_LIST})   ===>  生成可执行文件hello,源文件读取变量SRC_LIST中的内容

       ADD_EXECUTABLE(XXX main.cpp) ===> 也可以直接填写 main.cpp

       工程名和生成的可执行文件hello是没有任何关系 ==> 工程名和可执行

语法的基本原则

       变量使用${}方法取值,但是在IF控制语法中是直接使用变量名的

       指令(参数1 参数2...)参数使用括号()括起来,参数之间使用空格或者分号分隔。

       例如:ADD_EXECUTABLE(XXX main.cpp demo.cpp)

       或者ADD_EXECUTABLE(XXX main.cpp demo.cpp)

      指令是大小写无关的,参数和变量是大小写相关的 ==> 建立指令全部大写

       

       语法注意事项:

      SET{SRC_LIST main.cpp}可以写成SET{SRC_LIST "main.cpp"} ==> 如果源文件名中含有空格,就必须要加双引号。

       ADD_EXECUTABLE(hello main) =>  后缀可以不写,会自动寻找.c和.cpp文件,最好同时存在main.cpp和main.c

内部构建和外部构建

       内部构建: 上述例子就是内部构建,他产生的临时文件特别多,不方便清理。

       外部构建:  就会把生成的临时文件放到build目录下,不会对源文件源任何影响

       推荐使用外部构建:

       1.建立一个build目录,可以是任何地方,建立在当前目录下

       2.进入build,运行cmake .. ==> 表示上级目录,你可以写CMakeLists.txt所在的绝对路径,生成的文件都在build目录下了

       3.在build目录下,运行make来构建项目

       

       使用外部构建

       PROJECT_SOURCE_DIR ==> 指工程路径

       PROJECT_BINARY_DIR ==> 编译路径             build目录的绝对路径

HELLO更像一个工程

       1.为工程添加一个子目录src,用来放置工程源代码

       2.添加一个子目录dec,用来存放这个工程的文档

       3.在工程目录添加文本文件 COPYRIGHT README ==> 描述项目的安装、编译方法

       4.在工程目录添加一个 runhello.sh脚本,用来调用hello二进制

       5.将构建后的目标文件放入构建目标的bin子目录

       6.将doc目录的内容以及COPYRIGHT/README 安装到 /usr/share/doc/cmake

       .

       |---- build

       |---- CMakeList.txt

       |---- src

               |---- CMakeList.txt

               |---- main.cpp

# ==> 外层CMakeLists.txt

#     PROJECT(CmakeList)

#     ADD_SUBDIRECTORY(src bin)

# ==> src下的CMakeLists.txt

#     ADD_EXECUTABLE(hello main.cpp)

会生成很多中间文件,我们关注我们需要关注的部分就可以了

ADD_SUBDIRECTORY指令

ADD_SUBDIRECTORY(source_dir [binary_dir] [EXECLUDE_FROM_ALL])

1.这个指令用于向当前工程添加存放源文件的子目录,并可以指定中间二进制和目标二进制存放的位置。

2.EXECLUDE_FROM_ALL函数从将某个目录排除在外

ADD_SUBDIRECTORY(src bin)

1.将src子目录加入工程并指定编译输出(包含编译中间结果) 路径为bin目录

2.如果不进行bin目录的指定,那么编译结果(包括中间结果)都将存放在build 和 src下

上述没有指定bin的路径,其实我们可以通过更改二进制的保存路径来指定bin目录,不使用默认生成的路径(build中)。

更改二进制的保存路径

SET 指令重新定义 EXECUTABLE_OUTPUT_PATH 和 LIBRARY_OUTPUT_PATH变量来指定最终的目标二进制的位置。

SET{EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin}

SET{LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib}

注:哪里要改变目标存放的路径,就在哪里加入上述的定义

 

安装

       一种是从代码编译后直接make install安装,一种是打包时指定目录安装。

       指定目录安装:

       make install DESTDIR=/xxx/xxx

       ./configure -prefix=/xxx/xxx

-------------------------------------------------------------------------------------------------------------------------

       使用CMAKE一个指令: INSTALL

       INSTALL的安装可以包括:二进制、动态库、静态库、文件、目录、脚本等

       使用CMake一个新的变量: CMAKE_INSTALL_PREFIX

-------------------------------------------------------------------------------------------------------------------------

目录结构:

.
|__build
|__CMakeList.txt

|__COPYRIGHT
|__doc
|     |__hello.txt
|__README
|__XXXX.sh
|__src
    |__CMakeList.txt
    |__main.cpp

-------------------------------------------------------------------------------------------------------------------------安装文件COPYRIGHT和README

INSTALL(FILES COPYRIGHT README DESTINATION xxx/xxx/xxx/)

FILES ====>文件

DESTINATION ===> 路径

1.可以写绝对路径

2.可以写相对路径,相对路径实际是: ${CMAKE_INSTALL_PREFIX}/<DESTINATION>

CMAKE_INSTALL_PREFIX 默认是  /usr/local/

cmake -DCMAKE_INSTALL_PREFIX=/usr 在cmake的时候指定CMAKE_INSTALL_PREFIX

安装脚本

INSTALL(PROGRAMS xxxx.sh DESTINATION bin)

PROGRAMS: 非目标文件的可执行程序安装(比如脚本之类)

说明: 实际安装到的是 /usr/local/ ==> 默认路径是/usr/local

安装doc中的hello.txt

1.通过在doc目录构建CMakeList.txt,通过install下的file

2.直接通过在工程目录通过

INSTALL(DIRECTORY doc/ DESTINATION xxx/xxx/xxx)

DIRECTORY后面连接的是所在Source目录下的相对路径

注意:abc和abc/有很大区别:

目录名不以/结尾: 将整个目录安装到目标路径

目录名以/结尾: 将整个目录中的内容安装到目标路径

静态库和动态库的构建

任务:

1.建立一个静态库和动态库,提供HelloFunc函数供其他程序使用,HelloFunc向终端输出 Hello World

2.安装头文件与共享库

静态库和动态库的区别:

1.静态库的扩展名一般为 ".a" 或者 ".lib",动态库的扩展名一般为".so"或者".dll"

2.静态库在编译时会直接整合到目标程序中,编译成功的可执行文件可独立运行

3.动态库在编译时不会放到连接的目标程序中,即可执行文件无法单独运行

构建实例:

.
|--- build
|--- CMakeLists.txt
|--- lib

     |--- CMakeLists.txt
     |--- hello.cpp
     |--- hello.h

同时构建静态库和动态库

1.一种错误的示范:这种方式只会构建一个动态库,不会构建出静态库,虽然静态库.a

ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})

ADD_LIBRARY(hello STATIC ${LIBHELLO_SRC})

2.修改动态库的名字,这样是可以的

ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})

ADD_LIBRARY(hello_static STATIC ${LIBHELLO_SRC})

3.但是在实际的开发过程中,我们往往希望静态库和动态库的名字相同

SET_TARGET_PROPERTIES ==> 这条指令可以用来设置输出的名称,对于动态库,还可以用来指定动态库版本和API版本

ADD_LIBRARY(hello_static STATIC ${LIBHELLO_SRC})

SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME "hello")

SET_TARGET_PROPERTIES(hello_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)

ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})

SET_TARGET_PROPERTIES(hello PROPERTIES OUTPUT_NAME "hello")

SET_TARGET_PROPERTIES(hello PROPERTIES CLEAN_DIRECT_OUTPUT 1)

动态库的版本号

SET_TARGET_PROPERTIES(hello PROPERTIES VERSION 1.2 SOVERSION 1)

安装共享库和头文件

<prefix>的默认路径是  /usr/local

文件放到该目录下

INSTALL(FILES hello.h DESTINATION include/hello)

二进制、静态库、动态库安装都用TARGETS

ARCHIVE 特指静态库,  LIBRARY 特指动态库, RUNTIME 特指可执行目标二进制

使用外部共享库和头文件

准备一个项目:去调用上面生成的动态库

.

|--- build

|--- CMakeLists

|--- src

      |--- CMakeLists.txt

      |--- main.cpp

DEBUG编译

cmake -DCMAKE_BUILD_TYPE=debug ..

cmake -DCMAKE_BUILD_TYPE=release ..

相关文章
|
关系型数据库 Go
106【GoLand-基础2】(四)
106【GoLand-基础2】
83 0
|
Linux iOS开发 MacOS
编程小白的自学笔记十四(python办公自动化创建、复制、移动文件和文件夹)
编程小白的自学笔记十四(python办公自动化创建、复制、移动文件和文件夹)
|
3月前
|
IDE 测试技术 开发工具
Python接口自动化测试框架(基础篇)-- 不只是txt的文件操作
本文介绍了Python中的文件操作方法,包括使用open()打开文件、close()关闭文件、read()读取内容、readline()读取单行、readlines()读取多行、write()写入内容以及writelines()写入多行的方法。同时,探讨了文件操作模式和编码问题,并扩展了上下文管理器with...as的使用,以及对图片和音频文件操作的思考和练习。
31 1
Python接口自动化测试框架(基础篇)-- 不只是txt的文件操作
|
6月前
|
存储 缓存 IDE
CMake之编写属于自己的Findxxx.cmake文件:定义一个定制化的CMakeLists.txt文件
CMake之编写属于自己的Findxxx.cmake文件:定义一个定制化的CMakeLists.txt文件
124 1
|
Go 索引 容器
106【GoLand-基础2】(二)
106【GoLand-基础2】
40 0
|
测试技术 编译器 Go
106【GoLand-基础2】(一)
106【GoLand-基础2】
84 0
|
测试技术 Python
老板叫我写个APP自动化--Yaml文件读取--内附整个框架源码
老板叫我写个APP自动化--Yaml文件读取--内附整个框架源码
119 0
|
C++
2022-9-28-CMAKE工程中Cmakelist文档编写的一些注意点
2022-9-28-CMAKE工程中Cmakelist文档编写的一些注意点
110 0
开心档-软件开发入门之Python File(文件) 方法
本文主要讲解Python open() 方法用于打开一个文件,并返回文件对象,在对文件进行处理过程都需要使用到这个函数,如果该文件无法被打开,会抛出 OSError。
开心档-软件开发入门之Python File(文件) 方法