环境搭建
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(