CMake (零基础一)

CMake

1-外部构建,在build 执行 make

文件结构如下

[       4096]  .
├── [       4096]  build    目录
├── [         92]  CMakeLists.txt    
└── [        110]  HelloCMake.cpp

内容

CMakeLists.txt 文件名一定不能写成其他

PROJECT(HELLO_CMAKE)     //项目名
set (SRC_LIST HelloCMake.cpp)      //设置变量
add_executable(hello_cmake ${SRC_LIST)})   //添加源文件  ,生成可执行文件 hello_cmake

定义变量的方式 set (变量名 被指定的)

使用变量的方法是 $(变量名)

add_executable() 参数一 是生成的可执行文件名(目标文件) 参数二是依赖的源文件

#include<iostream>
using namespace std;
int main()
{
cout<<"hello cmake "<<endl;
return Exit_Success;
}

在build目录中执行

cmake .. 

截取执行部分效果

-- Configuring done   //配置完成
-- Generating done    //生成完成
-- Build files have been written to: /home/xxx/CMakeProc/HelloCMake/build  //构建文件写入build 文件夹

cmake … 表示从上级目录寻找CMakeList.txt文件,生成 makefile

生成效果

xxx@xxx-virtual-machine:~/CMakeProc/HelloCMake/build$ ls
CMakeCache.txt  CMakeFiles  cmake_install.cmake  Makefile

此时生成了 makefile ,就可以执行 make 命令

xxx@xxx-virtual-machine:~/CMakeProc/HelloCMake/build$ make
[ 50%] Building CXX object CMakeFiles/hello_cmake.dir/HelloCMake.cpp.o
[100%] Linking CXX executable hello_cmake
[100%] Built target hello_cmake

会多出一个可执行文件,文件名由 executable() 指定

xxx@xxx-virtual-machine:~/CMakeProc/HelloCMake/build$ ls
CMakeCache.txt  CMakeFiles  cmake_install.cmake  hello_cmake  Makefile

2输出自定义信息

在CMakeLists.txt 中添加

message(
[SEND_ERROR | STATUS | FATAL_ERROR]
"要输出的信息"
)

其中 SEND_ERROR STATUS FATAL_ERROR 是参数

调整CMakeList.txt 中的内容(注释掉部分)

如果不加参数
PROJECT(HELLO_CMAKE)
set (SRC_LIST HelloCMake.cpp)
message("this is testMessage null para")
#	message(STATUS "this is status")
#	message(SEND_ERROR "this is send_error")
#	message(FATAL_ERROR "this is fatal_error")
message("this is lastest info")
add_executable(hello_cmake ${SRC_LIST})

生成Makefile的过程

this is testMessage null para
this is lastest info
-- Configuring done
-- Generating done
-- Build files have been written to: /home/xxx/CMakeProc/HelloCMake/build
加了 status
PROJECT(HELLO_CMAKE)
set (SRC_LIST HelloCMake.cpp)
#message("this is testMessage null para")
message(STATUS "this is status")
#message(SEND_ERROR "this is send_error")
#message(FATAL_ERROR "this is fatal_error")
message("this is lastest info")
add_executable(hello_cmake ${SRC_LIST})

生成Makefile的过程

-- this is status
this is lastest info
-- Configuring done
-- Generating done
-- Build files have been written to: /home/xxx/CMakeProc/HelloCMake/build

没有给message传参数的直接就输出了拾定的信息。而传递了STATUS参数的会在输出的信息前面加–

加了 SEND_ERROR
PROJECT(HELLO_CMAKE)
set (SRC_LIST HelloCMake.cpp)
#message("this is testMessage null para")
#message(STATUS "this is status")
message(SEND_ERROR "this is send_error")
#message(FATAL_ERROR "this is fatal_error")
message("this is lastest info")//后面的语句不会执行
add_executable(hello_cmake ${SRC_LIST})

生成Makefile的过程

CMake Error at CMakeLists.txt:5 (message):
  this is send_error


this is lastest info
-- Configuring incomplete, errors occurred!
See also "/home/xxx/CMakeProc/HelloCMake/build/CMakeFiles/CMakeOutput.log".
加了 FATAL_ERROR
PROJECT(HELLO_CMAKE)
set (SRC_LIST HelloCMake.cpp)
#message("this is testMessage null para")
#message(STATUS "this is status")
#message(SEND_ERROR "this is send_error")
message(FATAL_ERROR "this is fatal_error")
message("this is lastest info")    //后面的语句不会执行
add_executable(hello_cmake ${SRC_LIST})

生成Makefile的过程

CMake Error at CMakeLists.txt:6 (message):
  this is fatal_error


-- Configuring incomplete, errors occurred!
See also "/home/xxx/CMakeProc/HelloCMake/build/CMakeFiles/CMakeOutput.log".

可以看到,SEND ERROR和FATAL ERROR的信息都输出了,而且生成过程都跳过了因此,
SEND_ERROR只是发送错误跳过生成成过程, 它后面的语句还会执行;而FATAL_ ERROR,从字面可以知道,致命错误,会立即中止过程,它后 面的语句也不再执行

3两个变量

PROJECT_BINARY_DIR

PROJECT_SOURCE_DIR

CMake会为每个项目的二进制目录和源目录
隐式生成两个变量
<project name>_ BINARY DIR 
<project name>_ SOURCE DIR
同时也存在这样的两个变量:
PROJECT BINARY DIR = <project name> BINARY DIR
PROJECT_ SOURCE DIR = <project name>_ SOURCE_ DIR

可以修改 CMakeLists.txt ,让其输出 信息

PROJECT(HELLO_CMAKE)
set (SRC_LIST HelloCMake.cpp)
#message("this is testMessage null para")
#message(STATUS "this is status")
#message(SEND_ERROR "this is send_error")
#message(FATAL_ERROR "this is fatal_error")
#message("this is lastest info")


message(${HELLO_CMAKE_BINARY_DIR})
message(${PROJECT_BINARY_DIR})
message("#####################")
message(${PROJECT_SOURCE_DIR})
message(${HELLO_CMAKE_SOURCE_DIR})


add_executable(hello_cmake ${SRC_LIST})

声成makefile的信息

/home/xxx/CMakeProc/HelloCMake/build
/home/xxx/CMakeProc/HelloCMake/build
#####################
/home/xxx/CMakeProc/HelloCMake
/home/xxx/CMakeProc/HelloCMake

PROJECT_BINARY_DIR 对应的是执行 cmake命令所在的目录,这里为build 文件夹

PROJECT_SOURCE_DIR 对应的是源文件所在的目录 就是HelloCmake

4动态库和静态库的构建和使用

文件结构

.
├── build
├── CMakeLists.txt
├── HelloLibrary.cpp
├── HelloLibrary.h
└── Main.cpp

文件内容

main.cpp

#include"HelloLibrary.h"
int main()
{
hello_library();
return 0;
}

HelloLibrary.h

#ifndef __HELLO_LiBRARY__
#define __HELLO_LiBRARY__
void hello_library();
#endif   // __HELLO_LIBRARY

HelloLibrary.cpp

#include"HelloLibrary.h"
#include<iostream>
void hello_library()
{
std::cout<<"hello Shared Library!"<< std::endl;

}

CMakeLists.txt

cmake_minimum_required(VERSION 3.8 FATAL_ERROR)    #设置CMake所需的最低版本。如果使用的CMake版本低于该版本,则会发出致命错误,第二个参数可选, (VERSION [...][FATAL_ERROR]) 设置该工程的cmake最低支持版本,注意 VERSION 不能写成小写,否则会报cmake_minimum_required called with unknown argument version 
project (HelloLibrary)
add_library(hello_library SHARED HelloLibrary.cpp) #生成动态库,第二个参数是源文件。 静态库就是 STATIC
include_directories(${PROJECT_SOURCE_DIR}) #给出编译器寻找头文件的目录(这个变量是源文件所在目录)
add_executable(hello_main Main.cpp) 
target_link_libraries(hello_main hello_library) #链接动态库

类比 makefile 我们是使用 .h 和 对应的 .cpp(除了主函数的cpp文件) 生成 .o (目标文件) , 目标文件生成库文件 。

链接动态库的方法

生成库(add_library)

设置头文件的搜索路径

(include_directories)

为什么要使用 include_directories()

include_directories
是用来提供找头文件路径的,打个比方,我现在想要#include"cv.h",但是这个cv.h的路径是/usr/local/include/opencv,那么我总不能在主函数头前写#include “/usr/local/include/opencv/cv.h”吧,

这个时候就用到include_directories了,它提供了一个搜索头文件暂时的根目录,即你可以在cmakelists中写上
include_directories(/usr/local/include)来让库文件搜索以/usr/local/include为基础,即在main函数前写上#include “opencv/cv.h"即可

如果存在多个头文件搜索路径 需要用空格隔开

设置库的搜索路径

LINK_DIRECTORIES

如果生成的动态库在第三方路径,需要使用 LINK_DIRECTORIES()

LINK_DIRECTORIES 命令来指定第三方库所在路径,比如,你的动态库在/home/myproject/libs这个路径下,则通过命令:LINK_DIRECTORIES(/home/myproject/libs),把该路径添加到第三方库搜索路径中,这样就可以使用相对路径了,使用TARGET_LINK_LIBRARIES的时候,只需要给出动态链接库的名字就行了。

也可以set(LINK_DIR /Users/haoran/Downloads/wfdb/lib),LINK_DIRECTORIES({LINK_DIR})

官方不建议使用该命令,取而代之的为find_package() find_library()

5同时生成同名的动态静态库

set_target_properties(target1 target2 ...
                      PROPERTIES prop1 value1
                      prop2 value2 ...)

这个命令是设置目标的属性,该命令的语法是列出想要更改的所有目标,然后提供接下来想要设置的值。您可以使用该命令任何所需的键值对,然后使用get_property()或get_target_property()命令提取它。

1、建立一个静态库和动态库,提供HelloFunc函数供其他程序编程使用,HelloFunc

向终端输出Hello World字符串。

2、安装头文件与共享库。

3、编写一个程序,来使用创建的共享库(静态库和动态库)。

首先,新建一个目录,创建MakeList.txt

/home/code/test/build

文件内容

hello.cpp

#include "hello.h"
 
using namespace std;
 
void HelloFunc(){
    cout << "Hello World/n";
}

hello.h

#ifndef HELLO_H
 
#define HELLO_H
 
#include <stdio.h>
 
void HelloFunc();
 
#endif

同级目录下的CMakeLists.txt

SET (LIBHELLO_SRC hello.cpp)
 
# SET (LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
 
# 添加动态库,关键词为shared,不需要写全称libhello.so,
 
# 只需要填写hello即可,cmake系统会自动为你生成 libhello.X
 
 
ADD_LIBRARY (hello SHARED ${LIBHELLO_SRC})
 
 
# 添加静态库,关键词为static,ADD_LIBRARY (hello STATIC ${LIBHELLO_SRC})
 
# 仍然用hello作为target名时,是不能成功创建所需的静态库的,
 
# 因为hello作为一个target是不能重名的, 故把上面的hello修改为hello_static
 
# 同理,你不需要写全libhello_static.a
 
# 只需要填写hello即可,cmake系统会自动为你生成 libhello_static.X
 
 
ADD_LIBRARY (hello_static STATIC ${LIBHELLO_SRC})
 
 
# 按照一般的习惯,静态库名字跟动态库名字应该是一致的,只是扩展名不同;
 
# 即:静态库名为 libhello.a; 动态库名为libhello.so ;
 
# 所以,希望 "hello_static" 在输出时,不是"hello_static",而是以"hello"的名字显示,故设置如下:
 
 
SET_TARGET_PROPERTIES (hello_static PROPERTIES OUTPUT_NAME "hello")
 
 
GET_TARGET_PROPERTY (OUTPUT_VALUE hello_static OUTPUT_NAME)
 
 
MESSAGE (STATUS "This is the hello_static OUTPUT_NAME: " ${OUTPUT_VALUE})
 
 
# cmake在构建一个新的target时,会尝试清理掉其他使用这个名字的库,
 
# 因此,在构建libhello.a时,就会清理掉libhello.so.
 
# 为了回避这个问题,比如再次使用SET_TARGET_PROPERTIES定义 CLEAN_DIRECT_OUTPUT属性。
 
 
SET_TARGET_PROPERTIES (hello_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
 
SET_TARGET_PROPERTIES (hello PROPERTIES CLEAN_DIRECT_OUTPUT 1)
 
 
# 按照规则,动态库是应该包含一个版本号的,
 
# VERSION指代动态库版本,SOVERSION指代API版本。
 
SET_TARGET_PROPERTIES (hello PROPERTIES VERSION 1.2 SOVERSION 1)
 
 
# 我们需要将libhello.a, libhello.so.x以及hello.h安装到系统目录,才能真正让其他人开发使用,
 
# 在本例中我们将hello的共享库安装到<prefix>/lib目录;
 
# 将hello.h安装<prefix>/include/hello目录。
 
INSTALL (TARGETS hello hello_static LIBRARY DESTINATION lib
 
ARCHIVE DESTINATION lib)
 
INSTALL (FILES hello.h DESTINATION include/hello)

在build目录中

cmake ..
 
make

这时,你就可以在lib目录得到一个libhello.so,这就是我们期望的共享库。

如果你要指定libhello.so生成的位置,可以通过:

在主工程文件CMakeLists.txt中修改ADD_SUBDIRECTORY (lib) 指令来指定一个编译输出位置;
或者在 lib/CMakeLists.txt中添加SET (LIBRARY_OUTPUT_PATH <路径>) 来指定一个新的位置。

6添加工程子目录

将源文件放入SRC 目录中,构建生成可执行文件在build文件夹中。

文件结构

.
├── build
├── CMakeLists.txt
└── src
    ├── CMakeLists.txt
    └── main.cpp

文件内容

一级的CMakeLists.txt

cmake_minimum_required(VERSION 3.1)
project(SubDirectory)
add_subdirectory(src bin)  #将 src 加入 工程 ,编译输出的结果放入 bin 目录

二级的 CMakeLists.txt

add_executable(sub_directory main.cpp) #生成的可执行文件

二级的 main.cpp

#include<iostream>
using namespace std;
int main()
{
std::cout<<"This is sub directory"<<std::endl;
return 0;
}

在build 中执行 cmake …

bin  CMakeCache.txt  CMakeFiles  cmake_install.cmake  Makefile

可以在 bin 中 也可以在当前目录执行 make 执行makefile.

执行后 ,bin 中出现 可执行文件 sub_directory

CMakeFiles  cmake_install.cmake  Makefile  sub_directory

补充:

ADD_ SUBDIRECTORY指令
ADD_ SUBDIRECTORY(src_ dir [bin_ dir]
[EXCLUDE_ FROM_ ALL]) 
src_ dir: 把src_ dir这个子目录加入工程
bin_ dir: 指定编译输出(包含编译的中间结果)的目录
为bin_ dir ,如果不指定,则默认输出目录为srC_ dir
即与src_ dir同名的目眼录;指定其实就是把src_ dir
重命名为bin_ dir
EXCLUDE_ FROM_ ALL: 将给定的目录从编译中排除,即不编译它
比如一些示例的目录,需要等 T程构建完
后再单独构建的

CMake指定目标保存目录

set(EXECUTABLE_OUTPUT_PATH )
set(LIBRARY_OUTPUT_PATH)

文件结构

.
├── build
├── CMakeLists.txt
└── src
    ├── CMakeLists.txt
    ├── main.cpp
    ├── SayHello.cpp
    └── SayHello.h

一级CMakeLIsts.txt中的内容

cmake_minimum_required(VERSION 3.1)
project(OutputPath)
add_subdirectory(src)

二级CMakeLIsts.txt中的内容

set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)#在build 文件夹下 创建bin文件夹,并在bin中生成执行文件
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)   #在build 文件夹下 创建lib文件夹,并在lib中生成库

add_library(SayHello SayHello.cpp)
include_directories(${PROJECT_SOURCE_DIR}/src)# 添加 头文件搜索路径
add_executable(OutputPath main.cpp)
target_link_libraries(OutputPath SayHello)

PROJECT_BINARY_DIR 这个变量是执行cmake 的地方 也就是build

文件内容

SayHello.h

#ifndef __SAYHELLO_H__
#define __SAYHELLO_H__
void Say_Hello();
#endif

SayHello.cpp

#include<iostream>
#include"SayHello.h"
using namespace std;
void Say_Hello()
{

std::cout<<"hello CMake"<<std::endl;
}

进入build 文件夹中

执行 cmake 生成 makefile

bin  CMakeCache.txt  CMakeFiles  cmake_install.cmake  lib  Makefile  src

但此时 bin 和 lib 中为空目录,src 中存放了中间文件

执行 make(可以在src 目录内,也可以在build 的同级目录) ,生成可执行文件和库文件

查看 bin 和 lib 中的文件

xxx@xxx-virtual-machine:~/CMakeProc/OutputPath/build$ tree bin lib
bin
└── OutputPath      # 是可执行文件
lib
└── libSayHello.a   # 库文件

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 《从零详解cmake.pdf》是一本介绍CMake的详细指南。CMake是一个用于构建和管理C/C++项目的开源工具。它的设计目标是帮助开发者更轻松地管理复杂的项目结构和跨平台构建。 这本书从零开始,详细解释了CMake的基本概念和用法。首先,它介绍了CMake的背景和历史,解释了为什么需要CMake以及它的优势。接着,书中详细介绍了CMake的安装和配置过程,包括如何在不同的操作系统上安装CMake以及如何进行必要的配置。 接下来,书中详细介绍了CMake的语法和语法结构。它解释了CMakeLists.txt文件的基本组成和常用指令,比如add_executable和target_link_libraries等。此外,书中还介绍了如何使用变量、条件语句和循环控制语句来实现更复杂的构建逻辑。 除了基本语法,书中还介绍了一些高级的CMake用法。例如,它详细介绍了如何使用CMake进行模块化构建,将项目分解为多个模块并进行独立构建。此外,书中还介绍了如何使用CMake进行交叉编译,从而在不同的平台上构建可执行文件。 最后,书中还提供了一些使用CMake构建常见项目类型的示例。例如,它演示了如何构建一个简单的命令行应用程序和一个基于Qt的图形界面应用程序。这些示例帮助读者更好地理解和应用CMake的知识。 总的来说,《从零详解cmake.pdf》是一本适合任何想要学习和掌握CMake的开发者的参考书。无论是初学者还是有一定经验的开发者,都能从中获得对CMake的全面理解和应用能力。无论是单个项目还是大型复杂项目,使用CMake可以帮助开发者更高效地进行构建和管理,提高开发效率。 ### 回答2: 《从零详解CMake.pdf》是一本介绍CMake的学习材料。CMake是一个开源的跨平台构建工具,它能够自动生成各种平台的构建文件,如Makefile或Visual Studio的解决方案。它可以简化跨平台开发的过程,提高项目的可维护性和可移植性。 这本《从零详解CMake.pdf》以零基础的方式,从CMake的安装开始介绍,详细讲解了CMake的使用方法和高级特性。首先介绍了CMake的基本语法和常用命令,包括如何定义变量、编译选项和链接库等。然后介绍了如何使用CMake构建简单的项目,包括如何编译单个源文件和多个源文件的项目。 接着,《从零详解CMake.pdf》介绍了如何处理依赖和外部库。它详细介绍了如何使用Find模块来查找系统安装的库,并讲解了如何自定义Find模块来处理其他依赖库。还介绍了如何使用第三方构建系统,如Google Test等。 此外,《从零详解CMake.pdf》还介绍了如何管理多个子项目和使用CMake进行交叉编译。它讲解了如何定义项目的目录结构和使用add_subdirectory命令来构建子项目,使得大型项目的管理更加方便。 最后,《从零详解CMake.pdf》还介绍了CMake的一些高级特性,如如何进行条件编译、如何配置编译选项和如何生成静态库和动态库等。 总的来说,《从零详解CMake.pdf》是一本循序渐进、易于理解的CMake学习材料,对于想要学习和应用CMake的开发者来说是一本很好的参考书。它详细介绍了CMake的各个方面,包括基本语法、项目管理、依赖处理和高级特性等,使读者能够快速上手并熟练使用CMake进行项目构建。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

丁金金

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值