CMakeLists.txt的用法

CMake定义

CMake是一个跨平台的编译(Build)工具,可以用简单的语句来描述所有平台的编译过程。

CMake能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性,类似UNIX下的automake。

CMake 不仅可以编译源代码、制作程序库、产生适配器(wrapper)、还可以用任意的顺序建构执行档。CMake 支持 in-place 建构(二进档和源代码在同一个目录树中)和 out-of-place 建构(二进档在别的目录里),因此可以很容易从同一个源代码目录树中建构出多个二进档。CMake 也支持静态与动态程式库的建构。

CMake缩写

“CMake”这个名字是“cross platform make”的缩写。虽然名字中含有“make”,但是CMake和Unix上常见的“make”系统是分开的,而且更为高阶。

CMake应用场景

假如我们有一个深度学习框架的部分工程列表,里面有超过40个互相调用的工程共同组成,一些用于生成库文件,一些用于实现逻辑功能。他们之间的调用关系复杂而严格,如果我想在这样复杂的框架下进行二次开发,显然只拥有它的源码是远远不够的,还需要清楚的明白这几十个项目之间的复杂关系,在没有原作者的帮助下进行这项工作几乎是不可能的。

即使是原作者给出了相关的结构文档,对新手来说建立工程的过程依旧是漫长而艰辛的,因此CMake的作用就凸显出来了。原作者只需要生成一份CMakeLists.txt文档,框架的使用者们只需要在下载源码的同时下载作者提供的CMakeLists.txt,就可以利用CMake,在”原作者的帮助下“进行工程的搭建。

打个更通俗易懂的比喻,小利在路边捡瓶盖赚了500万准备买房,但是小利这一麻袋的5毛、一块、十块、五十、一百售楼处的小姐姐嫌麻烦不想收这些钱,那怎么办呢?小姐姐建议小利把钱拿到银行去换成一张银行卡,然后直接来刷卡就行啦!CMake这里就扮演银行的角色,帮你去整理你的资产。

CMake主要功能

CMake主要有两大功能:

1、配置和生成各大平台的工程(vs的vcxproj,Qt的Pro):

比如设置输出目录,设置编译对象的debug后缀,设置源码在工程中的那个文件夹(Filter),配置需要依赖的第三方的头文件目录,库目录等等属性。

2、生成makefile文件

计算机编译源文件的时候是一条指令一条指令的发送给编译器执行的,这样效率很低下,所以就产生了一种文件,把所有的命令写到一个文件中,这个文件就是makefile。CMake生成了这个makefile之后,各大平台的编译器都会拿到这个makefile然后解析它。将他的命令解析出来一条一条执行。

说到这又不懂了,makefile又是什么呀?再补充一下makefile的相关介绍

补充:makefile介绍

什么是makefile?

或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但要作一个好的和professional的程序员,makefile还是要懂。这就好像现在有这么多的HTML的编辑器,但如果你想成为一个专业人士,你还是要了解HTML的标识的含义。

特别在Unix下的软件编译,你就不能不自己写makefile了,会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力。因为,makefile关系到了整个工程的编译规则。一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。

make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。

为什么使用makefile:

对于一个大型软件,其编译、维护是一个复杂而耗时的过程。它涉及到大量的文件、目录,这些文件可能是在不同的时间、由不同的人、在不同的地方分别写的,其中一些是程序,有些是数据,有些是文档,有些是衍生文件。

甚至参与开发的人员也不一定清楚所有文件的细节,包括如何处理它们。此外,构成软件的文件数目可能达到成百上千,甚至成千上万个,开发过程中当修改了少量几个文件后,往往只需要重新编译、生成少数几个文件。有效地描述这些文件之间的依赖关系以及处理命令,当个别文件改动后仅执行必要的处理,而不必重复整个编译过程,可以大大提高软件开发的效率。

Makefile和CMakeLists的关系

简单总结一下:Cmake是用来生成makefile的一个工具,读入所有源文件之后,自动生成makefile

写程序大体步骤为:

  • 1.用编辑器编写源代码,如.c文件。

  • 2.用编译器编译代码生成目标文件,如.o。

  • 3.用链接器连接目标代码生成可执行文件,如.exe。

但如果源文件太多,一个一个编译时就会特别麻烦,于是人们想到,为什么不设计一种类似批处理的程序,来批处理编译源文件呢,于是就有了make工具,它是一个自动化编译工具,你可以使用一条命令实现完全编译。但是你需要编写一个规则文件,make依据它来批处理编译,这个文件就是makefile,所以编写makefile文件也是一个程序员所必备的技能。

对于一个大工程,编写makefile实在是件复杂的事,于是人们又想,为什么不设计一个工具,读入所有源文件之后,自动生成makefile呢,于是就出现了cmake工具,它能够输出各种各样的makefile或者project文件,从而帮助程序员减轻负担。但是随之而来也就是编写cmakelist文件,它是cmake所依据的规则。所以在编程的世界里没有捷径可走,还是要脚踏实地的。

所以流程如下:在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

  • 环境准备:需要安装Visual Studio Code,Cmake
    1. 首先在function文件夹下新建如下内容:
      在这里插入图片描述
    1. main.cpp文件的内容如下:
#include"function.h"

int main()
{
    
    
	std::cout << test(add) << std::endl;
	system("pause");
	return 0;
}
    1. function.h文件内容如下:
#pragma once
#include<iostream>
using namespace std;
#include<functional>
#include<stdlib.h>
//using test = std::function<void(int, int)>;


int add(int a, int b)
{
    
    
	return a + b;
}

int test(std::function<int(int, int)>  &&a)
{
    
    
	return a(1, 2);
}
    1. CmakeLists.txt的内容如下
cmake_minimum_required(VERSION 2.8)

project(测试cmake)

ADD_EXECUTABLE(main main.cpp)

PROJECT(测试cmake)                           #工程名
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)     #需要的最低版本
#AUX_SOURCE_DIRECTORY(. DIR_SRCS)        #AUX_SOURCE_DIRECTORY(<dir> <variables>)  将dir目录下源文件名赋值给variables变量
ADD_EXECUTABLE(main main.cpp)        #编译main.cpp,生成一个main的可执行文件 
    1. 然后在build文件夹下cmake … 和 cmake --build .最后执行 ./main.exe

在这里插入图片描述

一些常见的cmakelists的文件参数写法

  1. 使用include_directories() #包含头文件目录

  2. set(SOURCES src/mainapp.cpp src/Student.cpp) #设置SOURECE变量 == src/mainapp.cpp src/Student.cpp

  3. add_library(testStudent SHARED ${SOURCES}) #根据SOURCES变量所含的C文件来生成库文件testStudent,最后名为libtestStudent.so ,这句话也带有编译的功能

  4. add_library(testStudent STATIC ${SOURCES}) #根据SOURCES变量所含的C文件来生成库文件testStudent,最后名为libtestStudent.a ,这句话也带有编译的功能

  5. install(TARGETS testStudent DESTINATION /usr/lib) #当执行make install 将会把生成的库文件testStudent放到/usr/lib文件夹下

  6. add_executable(hello helloworld.cpp) #将源文件helloworld.cpp生成可执行文件hello

  7. MESSAGE(“${CMAKE_CURRENT_SOURCE_DIR}”) #打印CMakeLists.txt文件所在路径 —打印变量 CMAKE_CURRENT_SOURCE_DIR

  8. add_executable(TestAdd main.cpp lib/add.cpp include/add.h) #编译main.cpp,需要调用add.cpp和add.h的函数,从而生成可执行文件 TestAdd

  9. if (“KaTeX parse error: Expected 'EOF', got '#' at position 60: … #̲如果两个字符串"ENV{QNX_HOST}” 和 " test_str"相等返回TRUE

  10. set( ENV{PATH} /home/martink ) #设置环境变量PATH值为 /home/martink

  11. link_directories(
    /库文件路径/
    )

  12. set ( PROJECT_LINK_LIBS libtestStudent.so )
    #set ( PROJECT_LINK_LIBS libtestStudent.a )
    target_link_libraries(libtest ${PROJECT_LINK_LIBS} ) #生成的libtest需要链接库PROJECT_LINK_LIBS(包含libtestStudent.so)

#编译test.cpp生成testStudent.so
cmake_minimum_required(VERSION 3.10)
 
project (HELLO)
 
set(SOURCES test.cpp)
add_library(testStudent SHARED ${
    
    SOURCES}) 
#链接libtestStudent.so生成可执行文件main
cmake_minimum_required(VERSION 2.8.9)
 
#For the shared library:
set ( PROJECT_LINK_LIBS libtestStudent.so )  
link_directories( ~/Desktop/hello/build )  #.so文件路径
add_executable(main main.cpp)  #main.cpp编译生成可执行文件 main
target_link_libraries(main ${
    
    PROJECT_LINK_LIBS} )  #main需要链接libtestStudent.so
cmake_minimum_required(VERSION 2.8.9)
 
link_directories(
     ~/Desktop/hello/build 
)                          #设置要链接的库的文件路径
 
include_directories(
    ~/Desktop/hello/Test  #test.h的位置
)
 
#编译Test.cpp生成 libTestStudent.so 
set(SOURCES_test Test/test.cpp)
add_library(testStudent SHARED ${
    
    SOURCES_test}) 
 
set ( PROJECT_LINK_LIBS libtestStudent.so )  #设置将要链接的库名
 
add_executable(main main.cpp)
target_link_libraries(main ${
    
    PROJECT_LINK_LIBS} )  #链接libtestStudent.so编译main.cpp生成可执行文件main。输入./main即可执行
 
set(SOURCES main.cpp)   
add_library(main_out SHARED ${
    
    SOURCES})   #编译main.cpp生成libmain_out.so

在这里插入图片描述

  1. #SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/…/bin) #设置可执行文件的输出目录
  2. #SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/…/lib) #设置库文件的输出目录
  • 编译生成libtest.a
list(APPEND GAME_SOURCE
        Classes/AppDelegate.cpp
        Classes/Hello.cpp
     )
 
list(APPEND GAME_SOURCE
        proj.qnx/main.cpp
     )
 
 
set(all_code_files
    ${
    
    GAME_HEADER}
    ${
    
    GAME_SOURCE}
    )
 
add_library(test STATIC ${
    
    all_code_files})

猜你喜欢

转载自blog.csdn.net/qq_44918090/article/details/126768485