一、什么是Cmake
CMake是一种跨平台编译工具。CMake主要是编写CMakeLists.txt文件
通过cmake命令将CMakeLists.txt文件转化为make所需要的Makefile文件,最后用make命令编译源码生成可执行程序或者库文件。
二、一个简单的例子 演示CMake工作原理
1、项目一:生成共享库
ADD_LIBRARY(libname,SHARED,SOURCELIST)
目录结构如下:
| ---- src
| |----customprint.cpp
| ----include
| |----customprint.h
| ----lib
| ----build
| |----CmakeLists.txt
include目录放置头文件,src目录下放置的是.c/.cpp源文件,biuld目录是用来构建的项目,lib目录用来放置我们生成库文件
myprint.h
#include<stdio.h>
#include<stdlib.h>
void feifei_print(char* str);
myprint.cpp
#include "/Users/feifei/Desktop/TM/Github/cmake_test/test/include/myprint.h"
void feifei_print(char* str) {
printf("%s",str);
}
CMakeLists.txt
#指定CMake编译最低要求版本
CMAKE_MINIMUM_REQUIRED(VERSION 3.10.2)
#给项目命名
PROJECT(customprint)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror=implicit-function-declaration")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ")
#收集c/c++文件并赋值给变量SRC_LIST_CPP ${PROJECT_SOURCE_DIR}代表区当前项目录
FILE(GLOB SRC_LIST_CPP ${PROJECT_SOURCE_DIR}/src/*.cpp)
FILE(GLOB SRC_LIST_C ${PROJECT_SOURCE_DIR}/src/*.c)
#指定头文件目录
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/include)
#指定生成库文件的目录
SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
#去变量SRC_LIST_CPP 与SRC_LIST_C 指定生成libmyprint 动态库 默认生成静态库 SHARED指定生成库类型为动态库
ADD_LIBRARY(customprint SHARED ${SRC_LIST_CPP} ${SRC_LIST_C})
- cd到项目build目录执行cmake命令 将会在biuld目录下生成Makefile文件
cmake 指令用法:
cmake + CMakeLists.txt的路径
执行cmake指令后会生成中间文件,为了不污染源文件区,所有我们在build目录来执行cmake指令。CmakeLists.txt 位于相对路径 ../中
feifeideMacBook-Pro:build feifei$ cmake ../
-- The C compiler identification is AppleClang 11.0.0.11000033
-- The CXX compiler identification is AppleClang 11.0.0.11000033
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/feifei/Desktop/TM/Github/cmake_test/test/build
生成makefile文件如下:
feifeideMacBook-Pro:build feifei$ ls
CMakeCache.txt CMakeFiles Makefile cmake_install.cmake
- 执行make命令项目就会开始编译,在项目lib目录下生成libcustomprint.so文件
feifeideMacBook-Pro:build feifei$ make
Scanning dependencies of target customprint
[ 50%] Building CXX object CMakeFiles/customprint.dir/src/customprint.cpp.o
[100%] Linking CXX shared library ../lib/libcustomprint.dylib
[100%] Built target customprint
因为我是mac系统,所以生成的是libcustomprint.dylib
而非libcustomprint.so
2、使用生成的so共享库
//将libB.so 连接到A上
TARGET_LINK_LIBRARIES(A,B)
新建项目二:
| ---- src
| ----include
| |----customprint.h
| ----lib
| |----libcustomprint.so
| ----build
| |----CmakeLists.txt
- 在src目录下 新建 hello.cpp,里面调用myprint()方法
#include <stdio.h>
#include "/Users/feifei/Desktop/TM/Github/cmake_test/test/include/myprint.h"
int main() {
myprint("hello World\n");
return 0;
}
将生成的myprint.so 拷贝到lib目录
将myprint.h 头文件 拷贝到include 目录
新建 CmakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 3.14)
#指定项目名称
PROJECT(HELLO)
#将hello.cpp 赋值给SOURCE 变量
SET(SOURCE ${PROJECT_SOURCE_DIR}/src/hello.cpp)
#指定头文件目录
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/include)
#指定链接库文件目录
LINK_DIRECTORIES(${PROJECT_SOURCE_DIR}/lib)
#将hello.cpp生成可执行文件hello
ADD_EXECUTABLE(hello ${SOURCE})
#指定hello 链接库myprint
TARGET_LINK_LIBRARIES(hello myprint)
feifeideMacBook-Pro:build feifei$ cmake ../
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/feifei/Desktop/TM/Github/cmake_test/test/build
feifeideMacBook-Pro:build feifei$ make
[ 50%] Building CXX object CMakeFiles/hello.dir/src/hello.cpp.o
/Users/feifei/Desktop/TM/Github/cmake_test/test/src/hello.cpp:4:22: warning: conversion from string literal to 'char *' is deprecated
[-Wc++11-compat-deprecated-writable-strings]
feifei_print("hello World\n");
^
1 warning generated.
[100%] Linking CXX executable hello
[100%] Built target hello
feifeideMacBook-Pro:build feifei$ ./hello
hello World
三、多CMakeLists.txt 组织结构
一个工程可能会多个模块(多个CMakeLists.txt),多个子模块工程生成一个可执行程序,一般如下组织:
最外层一个CMakeLists.txt,利用用add_subdirectory来进入各个子目录
每个子目录一个单独的CMakeLists.txt 。负责生成各个模块的静态库(.a)或者动态链接库(.so)
如以下结构:
├── CMakeLists.txt
├── build
├── customcalculate
│ ├── CMakeLists.txt
│ ├── include
│ │ └── calculate.h
│ ├── lib
│ └── src
│ └── calculate.cpp
├── customprint
│ ├── CMakeLists.txt
│ ├── include
│ │ └── customprint.h
│ ├── lib
│ └── src
│ └── customprint.cpp
└── main.cpp
最外层CmkaeLists.txt
#指定CMake编译最低要求版本
CMAKE_MINIMUM_REQUIRED(VERSION 3.10.2)
#指定项目名称
PROJECT(main)
#将main.cpp 赋值给SOURCE 变量
SET(SOURCE ${PROJECT_SOURCE_DIR}/main.cpp)
#将子模块 添加子模块路径
add_subdirectory(customprint)
#add_subdirectory(customcalculate)
#将main.cpp生成可执行文件main
ADD_EXECUTABLE(main ${SOURCE})
#将custom链接库 链接到main
TARGET_LINK_LIBRARIES(main customprint)
四、参考:
几个典型的概念:
https://www.jianshu.com/p/6332418b12b1