Cmake使用

环境搭建

ubuntu18.04,安装cmake使用如下命令

sudo apt install cmake

cmake -version

touch main.c CMakeLists.txt
编写main.c,如下

#include <stdio.h>

int main(void)
{
	printf("Hello World\n");
	return 0;
}

编写CMakeLists.tx

cmake_minimum_required (VERSION 2.8)

project (demo)

add_executable(main main.c)

运行查看
终端下切到main.c所在的目录下,然后输入以下命令运行cmake

cmake .

可以看到成功生成了Makefile,还有一些cmake运行时自动生成的文件。
然后在终端下输入make

编译多个源文件

首先删除之前的文件
rm -rf CMakeFiles CMakeCache.txt cmake_install.cmake Makefile main
在之前的目录下添加2个文件,testFunc.c和testFunc.h:
touch testFunc.c testFunc.h

/*
** testFunc.c
*/

#include <stdio.h>
#include "testFunc.h"

void func(int data)
{
	printf("data is %d\n", data);
}
/*
** testFunc.h
*/

#ifndef _TEST_FUNC_H_
#define _TEST_FUNC_H_

void func(int data);

#endif
//main.c
#include <stdio.h>

#include "testFunc.h"

int main(void)
{
	func(100);
	return 0;
}
//CMakeLists.txt
cmake_minimum_required (VERSION 2.8)

project (demo)

add_executable(main main.c testFunc.c)

aux_source_directory()

也存在弊端,它会把指定目录下的所有源文件都加进来,可能会加入一些我们不需要的文件,此时我们可以使用set命令去新建变量来存放需要的源文件

cmake_minimum_required (VERSION 2.8)

project (demo)

set( SRC_LIST
	 ./main.c
	 ./testFunc1.c
	 ./testFunc.c)

add_executable(main ${SRC_LIST})

cmake_minimum_required (VERSION 2.8)

project (demo)

include_directories (test_func test_func1)

aux_source_directory (test_func SRC_LIST)
aux_source_directory (test_func1 SRC_LIST1)

add_executable (main main.c ${SRC_LIST} ${SRC_LIST1})

add_subdirectory

:这个语句的作用是增加编译子目录。其基本语法格式是

add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])

source_dir 源代码目录
binary_dir 二进制代码目录
EXCLUDE_FROM_ALL标记
add_subdirectory 这个命令用于添加源文件子目录,同时还可以指定中间二进制和目标二进制的生成路径。EXCLUDE_FROM_ALL将会将这个目录从编译中排除,如工程的例子需要等待其他编译完成后再进行单独的编译。通常子目录应该包含自己的project()命令,这样以来整个编译命令将会产生各自的目标文件。如果把CMakeLists.txt与VS IDE比较,总的CMakeLists.txt就相当于解决方案,子CMakeLists.txt就相当于在解决方案下的工程文件。还有一个需要注意的是,如果编译父CMakeLists时依赖了子CMakeLists.txt中的源文件,那么该标志将会被覆盖(也就是也会处理),以满足编译任务。

这里指定src目录下存放了源文件,当执行cmake时,就会进入src目录下去找src目录下的CMakeLists.txt,所以在src目录下也建立一个CMakeLists.txt,内容如下

aux_source_directory (. SRC_LIST)

include_directories (../include)

add_executable (main ${SRC_LIST})

set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

cmake_minimum_required (VERSION 2.8)

project (demo)

set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

aux_source_directory (src SRC_LIST)

include_directories (include)

add_executable (main ${SRC_LIST})
//同时,还要把src目录下的CMakeLists.txt删除。

EXECUTABLE_OUTPUT_PATH是个系统自带的预定义变量,其意义如下
EXECUTABLE_OUTPUT_PATH :目标二进制可执行文件的存放位置
PROJECT_SOURCE_DIR:工程的根目录

生成库文件

cmake_minimum_required (VERSION 3.5)

project (demo)

set (SRC_LIST ${PROJECT_SOURCE_DIR}/testFunc/testFunc.c)

add_library (testFunc_shared SHARED ${SRC_LIST})
add_library (testFunc_static STATIC ${SRC_LIST})

set_target_properties (testFunc_shared PROPERTIES OUTPUT_NAME "testFunc")
set_target_properties (testFunc_static PROPERTIES OUTPUT_NAME "testFunc")

set (LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)

新的命令和预定义变量:

add_library: 生成动态库或静态库(第1个参数指定库的名字;第2个参数决定是动态还是静态,如果没有就默认静态;第3个参数指定生成库的源文件)
set_target_properties: 设置最终生成的库的名称,还有其它功能,如设置库的版本号等
LIBRARY_OUTPUT_PATH: 库文件的默认输出路径,这里设置为工程目录下的lib目录
前面使用set_target_properties重新定义了库的输出名称,如果不使用set_target_properties也可以,那么库的名称就是add_library里定义的名称,只是连续2次使用add_library指定库名称时(第一个参数),这个名称不能相同,而set_target_properties可以把名称设置为相同,只是最终生成的库文件后缀不同(一个是.so,一个是.a),这样相对来说会好看点。

cd build/
cmake ..
make
cd ../lib/
ls

链接库文件
|–bin
|–build
|–CMakeLists.txt
|–src
|–main.c
|–testFunc
|–inc
|–testFunc.h
|–lib
|–libtestFunc.a
|–libtestFunc.so

cmake_minimum_required (VERSION 3.5)

project (demo)


set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

set (SRC_LIST ${PROJECT_SOURCE_DIR}/src/main.c)

# find testFunc.h
include_directories (${PROJECT_SOURCE_DIR}/testFunc/inc)
#在指定目录下查找指定库,并把库的绝对路径存放到变量里,其第一个参数是变量名称TESTFUNC_LIB,第二个参数是库名称testFunc,第三个参数是HINTS,第4个参数是路径${PROJECT_SOURCE_DIR}/testFunc/lib,其它用法#可以参考cmake文档
#使用find_library的好处是在执行cmake …时就会去查找库是否存在,这样可以提前发现错误,不用等到链接时
#在lib目录下有testFunc的静态库和动态库,find_library(TESTFUNC_LIB testFunc
…默认是查找动态库,如果想直接指定使用动态库还是静态库,可以写成find_library(TESTFUNC_LIB
libtestFunc.so …或者find_library(TESTFUNC_LIB libtestFunc.a …

find_library(TESTFUNC_LIB testFunc HINTS ${PROJECT_SOURCE_DIR}/testFunc/lib)

add_executable (main ${SRC_LIST})
#把目标文件与库文件进行链接
target_link_libraries (main ${TESTFUNC_LIB})

条件编译

有时编译程序时想添加一些编译选项,如-Wall,-std=c++11等,就可以使用add_compile_options来进行操作。

|–bin
|–build
|–CMakeLists.txt
|–main.c

cmake_minimum_required (VERSION 2.8)

project (demo)

set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

add_compile_options(-std=c++11 -Wall) 

add_executable(main main.cpp)

生成部分指定bin或库文件

|–bin
|–build
|–CMakeLists.txt
|–src
|–CMakeLists.txt
|–main1.c
|–main2.c
CMakeLists.txt

cmake_minimum_required(VERSION 3.5)

project(demo)
#option命令,其第一个参数是这个option的名字,第二个参数是字符串,用来描述这个option是来干嘛的,第三个是option的值,ON或OFF,也可以不写,不写就是默认OFF
option(MYDEBUG "enable debug compilation" OFF)

set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

add_subdirectory(src)

src/CMakeLists.txt

cmake_minimum_required (VERSION 3.5)

add_executable(main1 main1.c)

if (MYDEBUG)
    add_executable(main2 main2.c)
else()
    message(STATUS "Currently is not in debug mode")    
endif()

编译部分代码

#include <stdio.h>

int main(void)
{
#ifdef WWW1
    printf("hello world1\n");
#endif    

#ifdef WWW2     
    printf("hello world2\n");
#endif

    return 0;
}

cmake_minimum_required(VERSION 3.5)

project(demo)

set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
#option的名字保持和main.c里的宏名称一致,这样更加直观,也可以选择不同的名字。通过与add_definitions()的配合,就可以控制单个bin文件的打印输出了
option(WWW1 "print one message" OFF)
option(WWW2 "print another message" OFF)

if (WWW1)
    add_definitions(-DWWW1)
endif()

if (WWW2)
    add_definitions(-DWWW2)
endif()

add_executable(main main.c)

include_directories ( dir )
aux_source_directory(dir var)

#[[ 这是一个 CMakeLists.txt 文件。
这是一个 CMakeLists.txt 文件
这是一个 CMakeLists.txt 文件]]
cmake_minimum_required(VERSION 3.0.0)


add_library(lib_name STATIC/SHARED src) 
# 函数作用:生成库。
# 参数lib_name:是要生成的库名称,
# 参数STATIC/SHARED:指定生成静态库或动态库,
# 参数src:指明库的生成所需要的源文件
find_library(var lib_name lib_path1 lib_path2)
# 函数作用:查找库,并把库的绝对路径和名称存储到第一个参数里
# 参数var:用于存储查找到的库
# 参数lib_name:想要查找的库的名称,默认是查找动态库,想要指定查找动态库或静态库
#       可以加后缀,例如 funcname.so 或 funcname.a 
# 参数lib_path:想要从哪个路径下查找库,可以指定多个路径
target_link_libraries(target lib_name)
# 函数作用:把库lib_name链接到target可执行文件中

#增加-std=c++11
set(CMAKE_CXX_STANDARD 11)
#增加-std=c++14
set(CMAKE_CXX_STANDARD 14)
#增加-std=c++17
set(CMAKE_CXX_STANDARD 17)
#在CMake中指定可执行程序输出的路径,也对应一个宏,叫做 EXECUTABLE_OUTPUT_PATH ,它的值还是通过 set 命令进行设置
set(HOME /home/robin/Linux/Sort)
set(EXECUTABLE_OUTPUT_PATH ${HOME}/bin)

set(SRC_LIST add.c  div.c   main.c  mult.c  sub.c)
add_executable(CALC  ${SRC_LIST})

cmake_minimum_required(VERSION 3.0)
project(CALC VERSION 0.1.0 LANGUAGES C CXX)
# 指定C++标准
set(CMAKE_CXX_STANDARD 11)

# 包含头文件的路径
include_directories(${PROJECT_SOURCE_DIR}/include)

# 设置可执行文件的输出路径
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/build/bin)

# 定义可执行文件
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src src_path)
add_executable(calc ${src_path})
message("PROJECT_SOURCE_DIR: ${PROJECT_SOURCE_DIR}")
message("CMAKE_CURRENT_SOURCE_DIR: ${CMAKE_CURRENT_SOURCE_DIR}")

$ tree
.
├── build
├── CMakeLists.txt
├── include
│   └── head.h
└── src
    ├── add.cpp
    ├── div.cpp
    ├── main.cpp
    ├── mult.cpp
    └── sub.cpp

3 directories, 7 files

cmake_minimum_required(VERSION 3.0)
project(CALC VERSION 0.1.0 LANGUAGES C CXX)
# 指定C++标准
set(CMAKE_CXX_STANDARD 11)

# 包含头文件的路径
include_directories(${PROJECT_SOURCE_DIR}/include)

# 设置可执行文件的输出路径
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/build/bin)

# 定义可执行文件
file(GLOB src_path ${CMAKE_CURRENT_SOURCE_DIR}/src/*.c)
add_executable(calc ${src_path})

$tree -L 2
.
├── build
│   ├── bin
│   ├── CMakeCache.txt
│   ├── CMakeFiles
│   ├── cmake_install.cmake
│   └── Makefile
├── CMakeLists.txt
├── include
│   └── head.h
├── main.c
└── src
    ├── add.c
    ├── div.c
    ├── mult.c
    └── sub.c

5 directories, 10 files
cmake_minimum_required(VERSION 3.0)
project(CALC VERSION 0.1.0 LANGUAGES C CXX)
# 指定C++标准
set(CMAKE_CXX_STANDARD 11)

# 包含头文件的路径
include_directories(${PROJECT_SOURCE_DIR}/include)

# 定义可执行文件
file(GLOB src_path ${CMAKE_CURRENT_SOURCE_DIR}/src/*.c)
# 制作静态库
add_library(calc_static_lib STATIC ${src_path})
set(LIBRARY_OUTPUT_PATH 文件存放位置)

$ tree -L 2
.
├── build
│   ├── bin
│   ├── CMakeCache.txt
│   ├── CMakeFiles
│   ├── cmake_install.cmake
│   └── Makefile
├── CMakeLists.txt
├── include
│   └── head.h
├── lib
│   ├── libcalc_shared_lib.so
│   └── libcalc_static_lib.a
└── src
    └── main.c

6 directories, 8 files
cmake_minimum_required(VERSION 3.0)
project(CALC VERSION 0.1.0 LANGUAGES C CXX)
# 指定C++标准
set(CMAKE_CXX_STANDARD 11)

# 包含头文件的路径
include_directories(${PROJECT_SOURCE_DIR}/include)

# 设置可执行文件的输出路径
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/build/bin)

# 
file(GLOB src_path ${CMAKE_CURRENT_SOURCE_DIR}/src/*.c)

# 设置库文件的输出地址
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)

# 包含静态库路径
link_directories(${CMAKE_CURRENT_SOURCE_DIR}/lib)

# 链接静态库
link_libraries(calc_static_lib)

# 定义可执行文件
add_executable(calc ${src_path})

$ tree
.
├── build
├── calc
│   ├── add.cpp
│   ├── CMakeLists.txt
│   ├── div.cpp
│   ├── mult.cpp
│   └── sub.cpp
├── CMakeLists.txt
├── include
│   ├── calc.h
│   └── sort.h
├── sort
│   ├── CMakeLists.txt
│   ├── insert.cpp
│   └── select.cpp
├── test1
│   ├── calc.cpp
│   └── CMakeLists.txt
└── test2
    ├── CMakeLists.txt
    └── sort.cpp

6 directories, 15 files
cmake_minimum_required(VERSION 3.0)
project(test)
# 定义变量
# 静态库生成的路径
set(LIB_PATH ${CMAKE_CURRENT_SOURCE_DIR}/lib)
# 测试程序生成的路径
set(EXEC_PATH ${CMAKE_CURRENT_SOURCE_DIR}/bin)
# 头文件目录
set(HEAD_PATH ${CMAKE_CURRENT_SOURCE_DIR}/include)
# 静态库的名字
set(CALC_LIB calc)
set(SORT_LIB sort)
# 可执行程序的名字
set(APP_NAME_1 test1)
set(APP_NAME_2 test2)
# 添加子目录
add_subdirectory(calc)
add_subdirectory(sort)
add_subdirectory(test1)
add_subdirectory(test2)
cmake_minimum_required(VERSION 3.0)
project(CALCLIB)
aux_source_directory(./ SRC)
include_directories(${HEAD_PATH})
set(LIBRARY_OUTPUT_PATH ${LIB_PATH})
add_library(${CALC_LIB} STATIC ${SRC})
cmake_minimum_required(VERSION 3.0)
project(SORTLIB)
aux_source_directory(./ SRC)
include_directories(${HEAD_PATH})
set(LIBRARY_OUTPUT_PATH ${LIB_PATH})
add_library(${SORT_LIB} SHARED ${SRC})
cmake_minimum_required(VERSION 3.0)
project(CALCTEST)
aux_source_directory(./ SRC)
include_directories(${HEAD_PATH})
link_directories(${LIB_PATH})
link_libraries(${CALC_LIB})
set(EXECUTABLE_OUTPUT_PATH ${EXEC_PATH})
add_executable(${APP_NAME_1} ${SRC})
cmake_minimum_required(VERSION 3.0)
project(SORTTEST)
aux_source_directory(./ SRC)
include_directories(${HEAD_PATH})
set(EXECUTABLE_OUTPUT_PATH ${EXEC_PATH})
link_directories(${LIB_PATH})
add_executable(${APP_NAME_2} ${SRC})
target_link_libraries(${APP_NAME_2} ${SORT_LIB})

#首先要将需链接的库设为动态库
cmake_minimum_required(VERSION 3.0)
project(CALCLIB)
aux_source_directory(./ SRC)
include_directories(${HEAD_PATH})
set(LIBRARY_OUTPUT_PATH ${LIB_PATH})
add_library(${CALC_LIB} SHARED ${SRC})

#在静态库中链接该动态库
cmake_minimum_required(VERSION 3.0)
project(SORTLIB)
aux_source_directory(./ SRC)
include_directories(${HEAD_PATH})
set(LIBRARY_OUTPUT_PATH ${LIB_PATH})
# 设置动态库的地址
link_directories(${LIB_PATH})
# 静态库链接动态库
add_library(${SORT_LIB} STATIC ${SRC})
# d库链接动态库
# add_library(${SORT_LIB} SHARED ${SRC})
# 链接动态库
target_link_libraries(${SORTLIB} ${CALCLIB})

cmake_minimum_required (VERSION 2.8)

project (demo)

# 向工程添加多个指定头文件的搜索路径,路径之间用空格分隔
include_directories (test_func test_func1)

#使用aux_source_directory把当前目录下的源文件存列表存放到变量SRC_LIST里
aux_source_directory (test_func SRC_LIST)
aux_source_directory (test_func1 SRC_LIST1)

add_executable (${PROJECT_NAME} main.c ${SRC_LIST} ${SRC_LIST1})


cmake_project
|-CMakeLists.txt
│ -main.cpp
│
| - module1
│  │  CMakeLists.txt
│  │
│  |-include
│  │      module1_a.h
│  │      module1_b.h
│  │
│  |-src
│          module1_a.cpp
│          module1_b.cpp
│
| - module2
    │ - CMakeLists.txt
    │
    | - include
    │      module2.h
    └─src
            module2.cpp
cmake_minimum_required(VERSION 2.8.12)
project(Cmake_test)

#设置头文件
# include_directories(include)

add_subdirectory(module1)
add_subdirectory(module2)

#设置源文件
AUX_SOURCE_DIRECTORY(. DIR_SRCS)
ADD_EXECUTABLE(main ${DIR_SRCS})

target_link_libraries(main module1)
target_link_libraries(main module2)

include_directories(include)
file(GLOB DIR_MODULE1 "src/*.cpp")
add_library(module1 ${DIR_MODULE1})

include_directories(include)
file(GLOB DIR_MOUDLE2 "src/*.cpp")
add_library(module2 ${DIR_MOUDLE2})







cmake_project
|-CMakeLists.txt
│ -bin
│ -build
│ -main
|	└─main.c
| - math
|-MathFunctions.c
|   └─MathFunctions.h 
| - src
   │-test0
   │      test0.c
   │      test0.h
   │
   |-test1
           test1.cpp
           test1.h

#CMake 最低版本要求
cmake_minimum_required(VERSION 3.18)
 
INCLUDE(CMakeForceCompiler) 
CMAKE_FORCE_C_COMPILER(gcc GNU)
CMAKE_FORCE_CXX_COMPILER(g++ GNU)
 
#设置C编译器
set(CMAKE_C_COMPILER "gcc")
 
 
#设置C++编译器
set(CMAKE_CXX_COMPILER "g++")
 
# 项目信息
project(Demo2)
 
# 添加 头文件目录
set(INCLUDE_DIR 
    ./math
	./src/test0
	./src/test1)
 
#添加源文件目录	  
file(GLOB ALL_SOURCE
    ./main/*.h
	./main/*.c
	./math/*.c
    ./math/*.h
	./src/test0/*.c
	./src/test0/*.h
	./src/test1/*.c
	./src/test1/*.h
     )
 
#指定生成目标文件夹	 
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "../bin")
 
#指定包含目录
include_directories(${INCLUDE_DIR})
 
#指定生成目标
add_executable(Demo ${ALL_SOURCE})
set( SRC_LIST
	 ./main.c
	 ./testFunc1.c
	 ./testFunc.c)

cmake 引入第三方库(头文件目录、库目录、库文件)

程序的编写需要用到头文件,程序的编译需要库文件 lib 文件,程序的运行需要 dll 文件,因此 cmake 引入第三方库其实就是将include目录、lib目录引入工程。引入第三方库的方式分为两种:

手动引入:通过 include_directories 或 link_directories 手动引入相关头文件和库文件路径
批量引入:先使用 find_package 找到 .cmake 或 .pc 文件,找到后相关的头文件和库文件路径会分别保存在指定变量中,如 XXX_LIBRARIES,此时再通过 include_directories 或 link_directories一键引入所有的库和头文件路径

一、手动引入

1、include_directories(引入头文件目录)

# 绝对路径引入
include_directories("D:\\ProgramFiles\\Qt\\qt5_7_lib_shared_64\\include")
 
# 普通变量引入(可以理解为把D:\\ProgramFiles\\Qt\\qt5_7_lib_shared_64放入一个集合INCLUDE_PATH)
# ${变量名} 可以获取集合内容,允许拼接
set (INCLUDE_PATH D:\\ProgramFiles\\Qt\\qt5_7_lib_shared_64)
include_directories(${INCLUDE_PATH}/include)       
 
# 环境变量引入
# 假设环境变量是INCLUDE_PATH = D:\\ProgramFiles\\Qt\\qt5_7_lib_shared_64
# #ENV{环境变量名} 可以获取环境变量的内容,允许拼接
include_directories($ENV{INCLUDE_PATH}/include)

2、link_directories(引入库目录)

# 绝对引入
link_libraries("D:\ProgramFiles\Qt\qt5_7_lib_shared_64\lib")
 
# 预定义变量引入
# PROJECT_SOURCE_DIR 是cmake的预定义变量,表示顶层CmakeList文件所在路径
link_libraries(${PROJECT_SOURCE_DIR}/ExtLib/ffmpeg/win64/lib)
 
# 环境变量引入
# 环境变量 QT_LIB = D:\\ProgramFiles\\Qt\\qt5_7_lib_shared_64
link_libraries($ENV{QT_LIB}/lib)

3、link_libraries (引入库文件)

  # 全路径引入
LINK_LIBRARIES(
上一篇:matlab代码--卷积神经网络的手写数字识别-2.cnn介绍


下一篇:麒麟系统x86安装达梦数据库