电子商务网站策划书3000字,网站怎么做更新,天津市网站建设公司,thinkphp网站建设在Linux系统下#xff0c;经常使用CMakeLists.txt文件来链接、编译C工程#xff0c;大部分人clone的代码里都是有CMakeLists.txt文件的#xff0c;只需要cmake .. 和make就完事了#xff0c;但在工作中#xff0c;你必须要有从无到有编写CMakeLists.txt文件的能力。
一、…在Linux系统下经常使用CMakeLists.txt文件来链接、编译C工程大部分人clone的代码里都是有CMakeLists.txt文件的只需要cmake .. 和make就完事了但在工作中你必须要有从无到有编写CMakeLists.txt文件的能力。
一、简单CMakeLists.txt文件的编写
1.先看文件目录 在repository4文件夹下存在好几个C相关的文件和一个CMakeLIsts.txt文件文件清单如下表
文件夹名文件夹类型/用途repository4工程文件夹calc.h头文件声明了几个函数定义add.cpp/div.cpp/mult.cpp/sub.cpp头文件中声明的函数的实现test_calc.cpp调用前面实现的几个函数CMakeLists.txt编写此文件用于此工程的链接和编译
以上除CMakeLists.txt文件以外的文件自己在保证调用、语法、功能正确的前提下随便编写。
2.编写CMakeLists.txt文件
1编写简单CMakeLists.txt文件的流程 #mermaid-svg-ksfqBnMx0nUjYQ1V {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-ksfqBnMx0nUjYQ1V .error-icon{fill:#552222;}#mermaid-svg-ksfqBnMx0nUjYQ1V .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ksfqBnMx0nUjYQ1V .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-ksfqBnMx0nUjYQ1V .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ksfqBnMx0nUjYQ1V .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ksfqBnMx0nUjYQ1V .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ksfqBnMx0nUjYQ1V .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ksfqBnMx0nUjYQ1V .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ksfqBnMx0nUjYQ1V .marker.cross{stroke:#333333;}#mermaid-svg-ksfqBnMx0nUjYQ1V svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ksfqBnMx0nUjYQ1V .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-ksfqBnMx0nUjYQ1V .cluster-label text{fill:#333;}#mermaid-svg-ksfqBnMx0nUjYQ1V .cluster-label span{color:#333;}#mermaid-svg-ksfqBnMx0nUjYQ1V .label text,#mermaid-svg-ksfqBnMx0nUjYQ1V span{fill:#333;color:#333;}#mermaid-svg-ksfqBnMx0nUjYQ1V .node rect,#mermaid-svg-ksfqBnMx0nUjYQ1V .node circle,#mermaid-svg-ksfqBnMx0nUjYQ1V .node ellipse,#mermaid-svg-ksfqBnMx0nUjYQ1V .node polygon,#mermaid-svg-ksfqBnMx0nUjYQ1V .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ksfqBnMx0nUjYQ1V .node .label{text-align:center;}#mermaid-svg-ksfqBnMx0nUjYQ1V .node.clickable{cursor:pointer;}#mermaid-svg-ksfqBnMx0nUjYQ1V .arrowheadPath{fill:#333333;}#mermaid-svg-ksfqBnMx0nUjYQ1V .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ksfqBnMx0nUjYQ1V .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ksfqBnMx0nUjYQ1V .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-ksfqBnMx0nUjYQ1V .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-ksfqBnMx0nUjYQ1V .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ksfqBnMx0nUjYQ1V .cluster text{fill:#333;}#mermaid-svg-ksfqBnMx0nUjYQ1V .cluster span{color:#333;}#mermaid-svg-ksfqBnMx0nUjYQ1V div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ksfqBnMx0nUjYQ1V :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 设置cmake的最低版本要求 指定C标准 设置项目名称 搜索文件夹中源文件 添加头文件路径 生成可执行文件 2编写简单CMakeLists.txt文件
cmake_minimum_required(VERSION 3.16) #cmake最低版本要求不得高于你计算机安装的版本set(CMAKE_CXX_STANDARD 11) #指定C标准project(test_calculate) #设置项目名称“test_calculate”aux_source_directory(${PROJECT_SOURCE_DIR} SRC) #添加源文件到变量SRC中宏PROJECT_SOURCE_DIR指的是正在编写的CMakeLists.txt文件所在的文件夹include_directories(${PROJECT_SOURCE_DIR}) #制定头文件路径${}符号是CMake语法中从变量取出变量的值的符号add_executable(test_cacl ${SRC}) #使用源文件生成可执行文件test_cacl,源文件的路径及名称位于SRC变量中这是非常简单的一个CMakeLists.txt文件仅用于新手了解cmake的体验装。
3.建立build文件夹运行CMakeLists.txt文件测试文件是否编写正确
建立build文件夹是为了保证源码文件的整洁链接、编译生成的文件均在build文件夹下。
mkdir build #在repository4文件夹下执行此命令生成build文件夹
cd build #进入build文件夹
cmake .. #使用CMakeLists.txt文件链接项目
make #编译项目 生成可执行文件
./test_calc #在编译正确后运行生成的可执行文件test_calc运行截图如下
4.稍微改进一下显得整齐点
上面文件夹的内容显得比较凌乱对其进行整理整理后的文件目录如下文件内容不变 将函数实现的cpp文件放在src目录下将头文件放在include目录下 对应的CMakeLists.txt文件的内容如下
cmake_minimum_required(VERSION 3.16)set(CMAKE_CXX_STANDARD 11)project(test_calculate)aux_source_directory(${PROJECT_SOURCE_DIR}/src SRC) #修改include_directories(${PROJECT_SOURCE_DIR}/include) #修改add_executable(test_cacl ${SRC} test_calc.cpp) #修改执行命令不变
二、编写嵌套CMakeLists.txt文件
1.先看文件目录 在repository5文件夹下存在好几个C相关的文件和一个CMakeLIsts.txt文件文件清单如下表
文件夹名文件夹中的文件文件夹类型/用途repository5以下文件夹工程文件夹build链接、编译产生的文件用于存放链接、编译时产生的文件includecalc.h / convert.h头文件声明了几个函数定义calccalc.cpp / CMakeLists.txt头文件calc.h中声明的函数的实现convconv.cpp / CMakeLists.txt头文件convert.h中声明的函数的实现test_calctest_calc.cpp / CMakeLists.txt调用calc.cpp实现的几个函数test_convtest_conv.cpp / CMakeLists.txt调用conv.cpp实现的几个函数CMakeLists.txt编写此文件用于此工程的链接和编译
这些文件总共生成两个可执行文件一个是计算相关的calc一个是转换大小写字母的conv我们需要在实现头文件中声明的那些函数的源文件所在的文件夹、调用头文件中函数的测试文件(main函数)所在的文件夹 以及 工程项目repository文件夹中创建CMakeLists.txt文件。 以上除CMakeLists.txt文件以外的文件自己在保证调用、语法、功能正确的前提下随便编写。
2.编写嵌套CMakeLists.txt文件
1编写嵌套CMakeLists.txt文件的流程 2编写外层CMakeLists.txt文件
cmake_minimum_required(VERSION 3.16)
set(CMAKE_CXX_STANDARD 11)
project(test)#添加子文件夹
add_subdirectory(calc)
add_subdirectory(conv)
add_subdirectory(test_calc)
add_subdirectory(test_conv)3编写内层CMakeLists.txt文件 a.编写calc文件夹中的CMakeLists.txt文件
cmake_minimum_required(VERSION 3.16)
set(CMAKE_CXX_STANDARD 11)
project(calc)aux_source_directory(./ SRC) # ./${PROJECT_SOURCE_DIR},在当前CMakeLists.txt所在文件夹calc中搜索源文件并放置在SRC变量中
include_directories(../include) #添加头文件路径../表示上一层目录../include即在上一层目录下的include中
add_library(calculate STATIC ${SRC}) #取出SRC变量的值生成一个名为calculate的静态库b.编写test_calc文件夹中的CMakeLists.txt文件
cmake_minimum_required(VERSION 3.16)
set(CMAKE_CXX_STANDARD 11)
project(calculator)
aux_source_directory(./ SRC)
include_directories(../include)link_libraries(calculate) #链接生成的静态库
add_executable(calculator ${SRC}) #生成名为calculator的可执行文件与calc相关的CMakeLists.txt就写好了
c.剩下的两个与conv相关的CMakeLists.txt文件其实与上面两个编写是一样的只是更改一下相关名称而已其内容如下 conv文件夹中的CMakeLists.txt:
cmake_minimum_required(VERSION 3.16)
set(CMAKE_CXX_STANDARD 11)
project(conv)aux_source_directory(./ SRC)
include_directories(../include)
add_library(convert STATIC ${SRC})test_conv文件夹中的CMakeLists.txt:
cmake_minimum_required(VERSION 3.16)
set(CMAKE_CXX_STANDARD 11)
project(convertor)
aux_source_directory(./ SRC)
include_directories(../include)
link_libraries(convert)
add_executable(convertor ${SRC})3.在项目文件夹下创建build文件夹测试刚才编写的CMakeLists.txt文件
mkdir build
cd build
cmake ..
make
./test_conv/convertor4. 同样改进一下指定一下生成的库、可执行文件的存放目录
1在外层CMakeLists.txt文件中定义要存放生成的库、可执行文件的变量以及路径
set(LIBPATH ${PROJECT_SOURCE_DIR}/lib) #设置生成库的路径并放置在变量LIBPATH中
set(EXEPATH ${PROJECT_SOURCE_DIR}/bin) #设置可执行文件的路径并放置在变量EXEPATH中
#文件夹bin和lib会自动生成2在内层CMakeLists.txt文件中使用上面两个全局变量LIBPATH和EXEPATH
set(LIBRARY_OUTPUT_PATH ${LIBPATH}) #设置库的生成目录在calc和conv文件夹下的CMakeLists.txt中添加
link_directories(../lib) #设置要链接的库的目录在test_calc和test_conv文件夹下的CMakeLists.txt中添加
set(EXECUTABLE_OUTPUT_PATH ${EXEPATH}) #设置可执行文件的生成目录在test_calc和test_conv文件夹下的CMakeLists.txt中添加3添加后在当前工程的build路径下执行以下命令来测试CMakeLists.txt文件
cmake ..
make
../bin/convertor #当前在build文件夹中bin文件夹和build并列因此需要../三、cmake常用函数
1.基础命令
命令功能备注#单行注释#[ [ ] ]块注释${ }从变量或宏中取出其值例如${PROJECT_SOURCE_DIR}cmake_minimum_required(VERSION 3.0)指定使用的 cmake 的最低版本非必须如果不加可能会有警告project()定义工程名称并可指定工程的版本、工程描述、web主页地址、支持的语言如果不需要这些都是可以忽略的只需要指定出工程名字即可add_executable(可执行程序名 源文件名称)使用后面的源文件生成可执行程序源文件名可以是一个也可以是多个如有多个可用空格或;间隔set(VAR [value]将[value]存入变量VAR中[value]可以是多个空格或;间隔set(CMAKE_CXX_STANDARD 11)设置C的标准CMAKE_CXX_STANDARD是预定义的宏aux_source_directory( dir variable )dir要搜索的目录variable将从dir目录下搜索到的源文件列表存储到该变量中file(GLOB/GLOB_RECURSE 变量名 要搜索的文件路径和文件类型)GLOB: 将指定目录下搜索到的满足条件的所有文件名生成一个列表并将其存储到变量中GLOB_RECURSE递归搜索指定目录将搜索到的满足条件的文件名生成一个列表并将其存储到变量中GLOB与GLOB_RECURSE 二选一include_directories(headpath)添加含头文件路径headpath头文件路径add_library(库名称 STATIC/SHARED 源文件1 [源文件2] …)使用源文件生成库STATIC静态库SHARED动态库
2.包含库文件
link_libraries(static lib [static lib...])参数1指定出要链接的第一个静态库的名字可以是全名 libxxx.a也可以是掐头lib去尾.a之后的名字 xxx 参数2-N要链接的其它静态库的名字根据实际情况是否需要 如果该静态库不是系统提供的自己制作或者使用第三方提供的静态库可能出现静态库找不到的情况此时可以将静态库的路径也指定出来
link_directories(lib path)在cmake中链接动态库的命令如下:
target_link_libraries(target PRIVATE|PUBLIC|INTERFACE item... [PRIVATE|PUBLIC|INTERFACE item...]...)target指定要加载的库的文件的名字该文件可能是一个源文件、一个动态库/静态库文件、一个可执行文件 PRIVATE|PUBLIC|INTERFACE动态库的访问权限默认为PUBLIC 如果各个动态库之间没有依赖关系无需做任何设置三者没有没有区别一般无需指定使用默认的 PUBLIC 即可动态库的链接具有传递性如果动态库 A 链接了动态库B、C动态库D链接了动态库A此时动态库D相当于也链接了动态库B、C并可以使用动态库B、C中定义的方法。
3.日志
message([STATUS|WARNING|AUTHOR_WARNING|FATAL_ERROR|SEND_ERROR] message to display ...)(无) 重要消息 STATUS 非重要消息 WARNINGCMake 警告, 会继续执行 AUTHOR_WARNINGCMake 警告 (dev), 会继续执行 SEND_ERRORCMake 错误, 继续执行但是会跳过生成的步骤 FATAL_ERRORCMake 错误, 终止所有处理过程 例如
# 输出一般日志信息
message(STATUS source path: ${PROJECT_SOURCE_DIR})
# 输出警告信息
message(WARNING source path: ${PROJECT_SOURCE_DIR})
# 输出错误信息
message(FATAL_ERROR source path: ${PROJECT_SOURCE_DIR})4.变量操作
命令功能set(变量名1 ${变量名1} ${变量名2} …)将从第二个参数开始往后所有的字符串进行拼接结果覆盖写入到第一个参数中list(APPEND list [ element …])APPEND表示进行数据追加后边的参数和set就一样了list(REMOVE_ITEM list value)从list中移除后面的valuelist(LENGTH list outputvariable)获取 list 的长度 output variable新创建的变量用于存储列表的长度list(GET list element index output variable)读取列表中指定索引的的元素可以指定多个索引list (JOIN list glue output variable)将列表中的元素用连接符glue连接起来组成一个字符串list(FIND list value output variable)查找列表是否存在指定的元素若果未找到返回-1list(INSERT list element_index element [ element …])在list中指定的位置插入若干元素list (PREPEND list [ element …])将元素插入到列表的0索引位置list (POP_BACK list [ out-var…])将列表中最后元素移除list (POP_FRONT list [ out-var…])将列表中首元素移除list (REMOVE_ITEM list value [ value …])将指定的元素从列表中移除list (REMOVE_AT list index [ index …])将指定索引的元素从列表中移除list (REMOVE_DUPLICATES list)移除列表中的重复元素list(REVERSE list)列表翻转
列表排序
list (SORT list [COMPARE compare] [CASE case] [ORDER order])
/*
COMPARE指定排序方法。有如下几种值可选STRING:按照字母顺序进行排序为默认的排序方法FILE_BASENAME如果是一系列路径名会使用basename进行排序NATURAL使用自然数顺序排序
CASE指明是否大小写敏感。有如下几种值可选SENSITIVE: 按照大小写敏感的方式进行排序为默认值INSENSITIVE按照大小写不敏感方式进行排序
ORDER指明排序的顺序。有如下几种值可选ASCENDING:按照升序排列为默认值DESCENDING按照降序排列
*/5.宏定义
在进行程序测试的时候我们可以在代码中添加一些宏定义通过这些宏来控制这些代码是否生效如下所示
#include stdio.h
#define NUMBER 3int main()
{int a 10;
#ifdef DEBUGprintf(我是一个程序猿, 我不会爬树...\n);
#endiffor(int i0; iNUMBER; i){printf(hello, GCC!!!\n);}return 0;
}在程序的第七行对DEBUG宏进行了判断如果该宏被定义了那么第八行就会进行日志输出如果没有定义这个宏第八行就相当于被注释掉了因此最终无法看到日志输入出上述代码中并没有定义这个宏。 为了让测试更灵活我们可以不在代码中定义这个宏而是在测试的时候去把它定义出来其中一种方式就是在gcc/g命令中去指定如下
gcc test.c -DDEBUG -o app在gcc/g命令中通过参数 -D指定出要定义的宏的名字这样就相当于在代码中定义了一个宏其名字DEBUG。 在CMake中我们也可以做类似的事情对应的命令叫做add_definitions():
add_definitions(-D宏名称)//针对上面的例子在对应CMakeLists.txt文件中写这句就等于gcc test.c -DDEBUG -o app
//add_definitions(-DDEBUG)下面的列表中为大家整理了一些CMake中常用的宏
宏功能PROJECT_SOURCE_DIR使用cmake命令后紧跟的目录一般是工程的根目录PROJECT_BINARY_DIR执行cmake命令的目录CMAKE_CURRENT_SOURCE_DIR当前处理的CMakeLists.txt所在的路径CMAKE_CURRENT_BINARY_DIRtarget 编译目录EXECUTABLE_OUTPUT_PATH重新定义目标二进制可执行文件的存放位置LIBRARY_OUTPUT_PATH重新定义目标链接库文件的存放位置PROJECT_NAME返回通过PROJECT指令定义的项目名称CMAKE_BINARY_DIR项目实际构建路径假设在build目录进行的构建那么得到的就是这个目录的路径