cmake大致
cmake
cmake_minimum_required(VERSION 3.0)
project(test)
#通过set自定义变量,通过${}取出
#set(SRC add.cpp main.cpp muti.cpp sub.cpp)
#cmake搜索文件 宏定义PROJECT_SOURCE_DIR
aux_source_directory(${PROJECT_SOURCE_DIR} SRC)
#file(GLOB/GLOB_RECURSE 变量名 要搜索的文件路径和文件类型)
#GLOB: 将指定目录下搜索到的满足条件的所有文件名生成一个列表,并将其存储到变量中。
#GLOB_RECURSE:递归搜索指定目录,将搜索到的满足条件的文件名生成一个列表,并将其存储到变量中。
#指定最后生成程序输出的路径
set(EXECUTABLE_OUTPUT_PATH ./bin)
#指定c++使用的标准
set(CAMKE_CXX_STANDARD 11)
#生成可执行程序exe
add_executable(app ${SRC})
cmake
#指定头文件路径
cmake_minimum_required(VERSION 3.0)
project(test)
#通过set自定义变量,通过${}取出
#aux_source_directory(${PROJECT_SOURCE_DIR}/src SRC)
file(GLOB SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
#指定最后生成程序输出的路径
set(EXECUTABLE_OUTPUT_PATH ./bin)
#引入头文件
include_directories(${PROJECT_SOURCE_DIR}/include)
#指定c++使用的标准
set(CAMKE_CXX_STANDARD 11)
add_executable(app ${SRC})
通过Cmake制作库文件
制作静态库
cmake
cmake_minimum_required(VERSION 3.0)
project(CALC)
include_directories(${PROJECT_SOURCE_DIR}/include)
file(GLOB SRC_LIST "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
add_library(calc STATIC ${SRC_LIST})
#add_library(库名称 STATIC 源文件1 [源文件2] ...)
动态库dll是有可执行权限的
制作动态库
cmake
include_directories(${PROJECT_SOURCE_DIR}/include) #包含头文件
set(LIBRARY_OUTPUT_PATH ../lib)
add_library(calc SHARED ${SRC})
链接静态库
如果要新建一个项目使用库文件,需要将原来的头文件和库文件一同拷贝过来
cmake
#使用静态链接库
cmake_minimum_required(VERSION 3.0)
project(test)
#通过set自定义变量,通过${}取出
file(GLOB SRC ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
include_directories(${PROJECT_SOURCE_DIR}/include)
#链接静态库
link_libraries(calc)
#指定静态库的位置
link_directories(${CMAKE_CURRENT_SOURCE_DIR}/lib)
add_executable(app ${SRC})
当我们在使用静态库的时候,在生成可执行文件exe的时候相应的静态库文件会打包到exe那个文件夹里面
链接动态库
cmake
target_link_libraries(
<target>
<PRIVATE|PUBLIC|INTERFACE> <item>...
[<PRIVATE|PUBLIC|INTERFACE> <item>...]...)
target:指定要加载动态库的文件的名字
动态库具有链接的能力,假如说动态库a链接b再链接c,但是传递是由前提条件的,必须是public
该文件可能是一个源文件
该文件可能是一个动态库文件
该文件可能是一个可执行文件
PRIVATE|PUBLIC|INTERFACE:动态库的访问权限,默认为PUBLIC
如果各个动态库之间没有依赖关系,无需做任何设置,三者没有没有区别,一般无需指定,使用默认的 PUBLIC 即可。
动态库的链接具有传递性,如果动态库 A 链接了动态库B、C,动态库D链接了动态库A,此时动态库D相当于也链接了动态库B、C,并可以使用动态库B、C中定义的方法。
cmake
target_link_libraries(A B C)
target_link_libraries(D A)
- PUBLIC:在public后面的库会被Link到前面的target中,并且里面的符号也会被导出,提供给第三方使用。
- PRIVATE:在private后面的库仅被link到前面的target中,并且终结掉,第三方不能感知你调了啥库
- INTERFACE:在interface后面引入的库不会被链接到前面的target中,只会导出符号。
使用动态链接库
cmake
#使用动态链接库
cmake_minimum_required(VERSION 3.0)
project(test)
FILE(GLOB SRC ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
include_directories(${PROJECT_SOURCE_DIR}/include)
# 指定动态库存放的位置
link_directories(${CMAKE_CURRENT_SOURCE_DIR}/lib)
add_executable(app ${SRC})
# 使用动态链接库
target_link_libraries(app calc)
动态库的链接和静态库是完全不同的:
静态库会在生成可执行程序的链接阶段被打包到可执行程序中,所以可执行程序启动,静态库就被加载到内存中了。
动态库在生成可执行程序的链接阶段不会被打包到可执行程序中,当可执行程序被启动并且调用了动态库中的函数的时候,动态库才会被加载到内存
因此,在cmake中指定要链接的动态库的时候,应该将命令写到生成了可执行文件之后:
cmake
cmake_minimum_required(VERSION 3.0)
project(TEST)
file(GLOB SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
# 添加并指定最终生成的可执行程序名
add_executable(app ${SRC_LIST})
# 指定可执行程序要链接的动态库名字
target_link_libraries(app pthread)
在target_link_libraries(app pthread)中:
app: 对应的是最终生成的可执行程序的名字
pthread:这是可执行程序要加载的动态库,这个库是系统提供的线程库,全名为libpthread.so,在指定的时候一般会掐头(lib)去尾(.so)。
假设在测试文件main.cpp中既使用了自己制作的动态库libcalc.so又使用了系统提供的线程库,此时CMakeLists.txt文件可以这样写:
cmake
cmake_minimum_required(VERSION 3.0)
project(TEST)
file(GLOB SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
include_directories(${PROJECT_SOURCE_DIR}/include)
add_executable(app ${SRC_LIST})
target_link_libraries(app pthread calc)
cmake日志
cmake
#使用动态链接库
cmake_minimum_required(VERSION 3.0)
project(test)
FILE(GLOB SRC ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
include_directories(${PROJECT_SOURCE_DIR}/include)
# 日志
message("first logs")
# 指定动态库存放的位置
link_directories(${CMAKE_CURRENT_SOURCE_DIR}/lib)
message(STATUS "second logs")
add_executable(app ${SRC})
# 使用动态链接库
target_link_libraries(app calc)
message(FATAL_ERROR "third fatal error")
message(STATUS "fourth logs")
cmake
#使用动态链接库
cmake_minimum_required(VERSION 3.0)
project(test)
FILE(GLOB SRC ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
include_directories(${PROJECT_SOURCE_DIR}/include)
# 日志
message("first logs")
# 指定动态库存放的位置
link_directories(${CMAKE_CURRENT_SOURCE_DIR}/lib)
message(STATUS "second logs")
add_executable(app ${SRC})
# 使用动态链接库
target_link_libraries(app calc)
#打印变量值
message("var is :"${SRC})
message(FATAL_ERROR "third fatal error")
message(STATUS "fourth logs")
字符串操作
cmake
cmake_minimum_required(VERSION 3.5)
project(test)
set(value1 "value1")
set(value2 "value2")
message(${value1})
#字符串拼接
set(value3 ${value1} "+" ${value2})
message("value3:" ${value3})
#使用list追加字符串
list(APPEND value3 " zhui jia zi fu chuan")
message(${value3})
cmake
#移除src中main.cpp的名字
cmake_minimum_required(VERSION 3.5)
project(test)
#获取src目录下所有源文件的绝对路径
file(GLOB SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
message("======================")
message(${SRC})
list(REMOVE_ITEM SRC ${PROJECT_SOURCE_DIR}/src/main.cpp)
message("删除之后的字符串")
message(${SRC})
=====================
D:/C++workspace/c++程序/cmake_str/src/add.cppD:/C++workspace/c++程序/cmake_str/src/main.cppD:/C++workspace/c++程序/cmake_str/src/muti.cppD:/C++workspace/c++程序/cmake_str/src/sub.cpp
删除之后的字符串
D:/C++workspace/c++程序/cmake_str/src/add.cppD:/C++workspace/c++程序/cmake_str/src/muti.cppD:/C++workspace/c++程序/cmake_str/src/sub.cpp
list的其他命令:
获取list长度
cmake
list(LENGTH <list> <output variable>)
- LENGTH:子命令LENGTH用于读取列表长度
- :当前操作的列表
- :新创建的变量,用于存储列表的长度。
读取列表中指定索引的的元素,可以指定多个索引:
cmake
list(GET <list> <element index> [<element index> ...] <output variable>)
- :当前操作的列表
- :列表元素的索引
- 从0开始编号,索引0的元素为列表中的第一个元素;
- 索引也可以是负数,-1表示列表的最后一个元素,-2表示列表倒数第二个元素,以此类推
- 当索引(不管是正还是负)超过列表的长度,运行会报错
- :新创建的变量,存储指定索引元素的返回结果,也是一个列表。
将列表中的元素用连接符(字符串)连接起来组成一个字符串
cmake
list (JOIN <list> <glue> <output variable>)
- :当前操作的列表
- :指定的连接符(字符串)
- :新创建的变量,存储返回的字符串
查找列表是否存在指定的元素,若果未找到,返回-1
cmake
list(FIND <list> <value> <output variable>)
- :当前操作的列表
- :需要再列表中搜索的元素
- :新创建的变量
等等。。。
cmake中自定义宏
cpp
#include <stdio.h>
#define NUMBER 3
int main()
{
int a = 10;
//cmake中没有添加debug相关配置所以在debug模式下运行,并不会运行ifdef debug里面的打印内容
#ifdef DEBUG
printf("我是一个程序猿, 我不会爬树...\n");
#endif
for(int i=0; i<NUMBER; ++i)
{
printf("hello, GCC!!!\n");
}
return 0;
}
cpp
cmake_minimum_required(VERSION 3.5)
project(Test)
file(GLOB SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
add_definitions(-DDEBUG)
add_executable(app ${SRC})
嵌套的cmake
文件夹目录
根目录下的cmakelist
cpp
cmake_minimum_required(VERSION 3.5)
project(test)
#定义变量
#静态库生成路径
set(LIBPATH ${PROJECT_SOURCE_DIR}/lib)
#可执行程序存放地址
set(EXECPATH ${PROJECT_SOURCE_DIR}/bin)
#头文件路径
set(HEADPATH ${PROJECT_SOURCE_DIR}/include)
#库文件的名字
set(CALCLIB calc)
set(SORTLIB sort)
#可执行程序的名字
set(APPNAME1 app1)
set(APPNAME2 app2)
#给当前节点添加子目录
add_subdirectory(calc)
add_subdirectory(sort)
add_subdirectory(test1)
add_subdirectory(test2)
calc文件夹下的cmakelist 子节点中的变量无法在父节点中用,父节点的变量可以在子节点用
cpp
cmake_minimum_required(VERSION 3.5)
project(calc)
#搜索当前路径下的所有cpp文件 搜索源文件
aux_source_directory(./ SRC)
# 搜索头文件 include文件夹下 父节点已经定义了include文件夹路径变量HEADPATH
include_directories(${HEADPATH})
#指定静态库生成的路径
set(LIBRARY_OUTPUT_PATH ${LIBPATH})
#把源文件变成静态库
add_library(${CALCLIB} STATIC ${SRC})
sort目录下的文件cmakelist
cpp
cmake_minimum_required(VERSION 3.5)
project(sort)
#搜索当前路径下的所有cpp文件 搜索源文件
aux_source_directory(./ SRC)
# 搜索头文件 include文件夹下 父节点已经定义了include文件夹路径变量HEADPATH
include_directories(${HEADPATH})
#指定静态库生成的路径
set(LIBRARY_OUTPUT_PATH ${LIBPATH})
#把源文件变成静态库
add_library(${SORTLIB} STATIC ${SRC})
test1目录下的cmakelist执行calc的主程序
cpp
cmake_minimum_required(VERSION 3.5)
project(test1)
aux_source_directory(./ SRC)
include_directories(${HEADPATH})
link_directories(${LIBPATH})
link_libraries(${CALCLIB})
#生成可执行文件的目录
set(EXECUTABLE_OTPUT_PATH ${EXECPATH})
add_executable(${APPNAME1} ${SRC})
在静态库中链接静态库
主要做的是在排序的静态库sort.lib中引用calc.lib需要做以下修改
冒泡排序cpp中调用calc静态库的链接 删掉test2
cpp
#include<iostream>
#include "sort.h"
#include "calc.h"
using namespace std;
void bubble_sort(int mylist[],int listsize){
int number1 = add(mylist[0],mylist[1]);
cout<<"在选择排序中调用calc的加法操作"<<number1<<endl;
for(int i=0;i<listsize;i++){
for(int j=i;j<listsize;j++){
if(mylist[i]<mylist[j])
{
int temp = mylist[i];
mylist[i]=mylist[j];
mylist[j]=temp;
}
}
}
}
calc目录下的cmakelist保持不变
sort目录下的cmakelist
cmake
cmake_minimum_required(VERSION 3.5)
project(sort)
#搜索当前路径下的所有cpp文件 搜索源文件
aux_source_directory(./ SRC)
# 搜索头文件 include文件夹下 父节点已经定义了include文件夹路径变量HEADPATH
include_directories(${HEADPATH})
#指定静态库生成的路径
set(LIBRARY_OUTPUT_PATH ${LIBPATH})
# 指定自定义静态库的存放路径
link_directories(${LIBPATH})
# 链接calc静态库
link_libraries(${CALCLIB})
#把源文件变成静态库
add_library(${SORTLIB} STATIC ${SRC})
test/main.cpp下的cmakelist
cmake
cmake_minimum_required(VERSION 3.5)
project(test2)
aux_source_directory(./ SRC)
include_directories(${HEADPATH})
link_directories(${LIBPATH})
link_libraries(${SORTLIB})
#生成可执行文件的目录
set(EXECUTABLE_OTPUT_PATH ${EXECPATH})
add_executable(${APPNAME2} ${SRC})
sort.lib已经引用的calc.lib所以,test下就不需要再引用calc.lib了