CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程)。他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性,类似UNIX下的automake。
查看Cmake版本
camke -version
若没有
sudo apt install cmake
然后就安装成功了!!!
接下来我们讲如何使用cmake进行编译
一、简单项目(单个源文件)
1、新建一个main.c文件
#include <stdio.h>
int main() {
printf("Hello World!\n");
return 0;
}
2、 新建文件 CMakeLists.txt(命名必须是 CMakeLists.txt,注意大小写和不要漏字母)
project(HELLO) #此行为工程信息,HELLO为工程名
add_executable(hello main.c) #表示表示最终要生成的可执行文件的名字叫holle,使用的源文件是main.c
add_executable(hello main.c) #表示表示最终要生成的可执行文件的名字叫holle,使用的源文件是main.c
3、 编译和运行
新建一个 build 文件夹,目录情况如下:
build main.c CMakeLists.txt
为什么要新建一个 build 文件夹?
一般我们采用 cmake 的 out-of-source 方式来构建(即生成的中间产物和源代码分离),这样做可以让生成的文件和源文件不会弄混,且目录结构看起来也会清晰明了。所以推荐使用这种方式,至于这个文件夹的命名并无限制,我们习惯命名为 build。
————————————————
版权声明:本文为CSDN博主「阿飞__」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/afei__/article/details/81201039
依次执行以下命令:
cd build
cmake ..
make
./hello
二、 同一目录下多个源文件
那么在一个目录下有多个源文件该如何编译呢
同一目录上:
- CMakeLists.txt
- main.c
- testFunc.c
- testFunc.h
- testFunc1.c
- testFunc1.h
- build
此时我们需要修改CMakeLists.txt
因为如果有很多除main.c以外的源文件的话一个一个写在**add_executable()**是很麻烦的
所以cmake中有aux_source_directory(. SRC_LIST)
他可以把当前目录下的源文件存在一个变量里
CMakeLists.txt:
project (demo)
aux_source_directory(. SRC_LIST) #把当前目录下的源文件存放在一个变量中
add_executable(main ${SRC_LIST})
main.c:
#include <stdio.h>
#include "testFunc.h"
#include "testFunc1.h"
int main(void)
{
func(100);
func1(200);
return 0;
}
再执行命令:
cd build
cmake ..
make
./main
编译成功!!!
三、 不同目录下多个源文件
一般来说,当程序文件比较多时,我们会进行分类管理,把代码根据功能放在不同的目录下,这样方便查找。那么这种情况下如何编写CMakeLists.txt呢?
我们把之前的源文件整理一下(新建2个目录test_func和test_func1),整理好后整体文件结构如下:
- CMakeLists.txt
- main.c
- test_func {
testFunc.c
testFunc.h
}
-test_Func1{
testFunc1.c
testFunc1.h
}
- build
需要对CMakeLists.txt进行修改
CMakeLists.txt:
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})
这里出现了一个新的命令:include_directories。该命令是用来向工程添加多个指定头文件的搜索路径,路径之间用空格分隔。
因为main.c里include了testFunc.h和testFunc1.h,如果没有这个命令来指定头文件所在位置,就会无法编译
当然,也可以在main.c里使用include来指定路径,如下
#include "test_func/testFunc.h"
#include "test_func1/testFunc1.h"
五 、正规一点的组织结构
一般会把源文件放到src目录下,把头文件放入到include文件下,生成的对象文件放入到build目录下,最终输出可执行文件文件会放到bin目录下
目录结构如下:
- bin
- build
- CMakeLists.txt
- include{
testFunc.h
testFunc1.h
}
- src{
main.c
CMakeLists.txt
testFunc.c
testFunc1.c
}
最外层的CMakeLists.txt
cmake_minimum_required (VERSION 2.8)
project (demo)
add_subdirectory (src) #这个命令可以向当前工程添加存放源文件的子目录
这里出现一个新的命令add_subdirectory(),这个命令可以向当前工程添加存放源文件的子目录
src目录下的CMakeLists.txt
aux_source_directory (. SRC_LIST)
include_directories (../include)
add_executable (main ${SRC_LIST})
set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
这里又出现一个新的命令set,是用于定义变量的,EXECUTABLE_OUT_PATH和PROJECT_SOURCE_DIR是CMake自带的预定义变量,其意义如下,
EXECUTABLE_OUTPUT_PATH :目标二进制可执行文件的存放位置
PROJECT_SOURCE_DIR:工程的根目录
所以,这里set的意思是把存放可执行文件文件的位置设置为工程根目录下的bin目录。
最后进行命令编译
cd build
cmake ..
make
再进入bin目录下面
./main
编译成功!!!
六 、动态库和静态库的编译控制
有时我们只需要编译出动态库,静态库,然后等着让其它程序去使用。
目录结构如下:
-build
-CMakeLists.txt
-lib
-lib_testFunc{
--------------------CMakeList.txt
--------------------testFunc.c
--------------------testFunc.h
}
最外部的CMakeLists.txt
cmake_minimum_required (VERSION 2.8)
project (demo)
add_subdirectory (lib_testFunc)
lib_testFunc里的CMakeLists.txt
aux_source_directory (. SRC_LIST)
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) #文件的默认输出路径,这里设置为工程目录下的lib目录
testFunc.c
/*
** testFunc.c
*/
#include <stdio.h>
#include "testFunc.h"
void func(int data)
{
printf("data is %d\n", data);
}
testFunc.h
/*
** testFunc.h
*/
#ifndef _TESTFUNC_H_
#define _TESTFUNC_H_
void func(int data);
#endif
再执行命令
cd build
cmake ..
make
cd到lib目录下进行查看,发现已经成功生成了动态库和静态库.
七 、对库进行链接
我们已经生成了库,那么就进行链接测试下。把build里的文件都删除,然后在在工程目录下新建src目录和bin目录,在src目录下添加一个main.c和一个CMakeLists.txt,整体结构如下,
build目录下
rm -f * #删除目录下文件
目录结构如下:
-build
-CMakeLists.txt
-lib{
--------------------libtestFunc.a
--------------------libtestFunc.so
}
-lib_testFunc{
--------------------CMakeList.txt
--------------------testFunc.c
--------------------testFunc.h
}
-src{
---------------------main.c
--------------------CMakeLists.txt
}
main.c
#include <stdio.h>
#include "testFunc.h"
int main(void)
{
func(520);
return 0;
}
修改最外部的CMakeLists.txt
增加src目录
cmake_minimum_required (VERSION 2.8)
project (demo)
add_subdirectory (lib_testFunc)
add_subdirectory (src)
src目录下的CMakeLists.txt如下
aux_source_directory (. SRC_LIST)
# find testFunc.h
include_directories (../lib_testFunc)
link_directories (${PROJECT_SOURCE_DIR}/lib) #添加非标准的共享库搜索路径
add_executable (main ${SRC_LIST})
target_link_libraries (main testFunc) #把目标文件与库文件进行链接
set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
命令
cd build
cmake ..
make
cmake … 后的内容,是我之前已经编译过一次了
编译成功!!!