Linux教程--通俗易懂的CMake教程

在这里插入图片描述

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 … 后的内容,是我之前已经编译过一次了

编译成功!!!

感谢这位博主的内容!!

发布了28 篇原创文章 · 获赞 15 · 访问量 1005

猜你喜欢

转载自blog.csdn.net/qq_43765237/article/details/105728521