入门工程级CMake看这篇文章就对了

什么是CMake,为什么要用CMake

  • CMake是一个跨平台的构建工具,可以用简单的语句来描述所有平台的安装(编译过程)。能够输出各种各样的makefile或者project文件。CMake并不直接构建出最终的软件,而是产生其他工具的脚本(如makefile),然后再依据这个工具的构建方式使用。
  • CMake是一个比make更高级的编译配置工具,它可以根据不同的平台、不同的编译器,生成相应的makefile或vcproj项目,从而达到跨平台的目的。Android Studio利用CMake生成的是ninja。ninja是一个小型的关注速度的构建系统。我们不需要关心ninja的脚本,知道怎么配置CMake就可以了。
  • 使用CMake的话我们就可以更快更方便的进行编译链接程序,要不然我们就得”傻傻的“gcc balabala …一长串的东西才可以构建我们要的可执行文件,如果我们使用CMake的话我们就只需要cmake然后make就可以构建出我们想要的可执行文件。

初级阶段——写个HelloWorld用cmake进行编译

main.cpp

#include<iostream>
int main()
{
    std::cout<<"hello world"<<std::endl;
    return 0;
}

在和main.cpp同级目录下创建并编辑CMakeLists.txt(这个名字一定别写错了!一定别写错了!一定别写错了!这是规范不能乱写)
CMakeLists.txt

PROJECT(HELLO)
SET (SRCLIST main.cpp)
MESSAGE(STATUS "THIS IS BINARY_DIR" ${HELLO_BINARY_DIR})
MESSAGE(STATUS "THIS IS SOURCE_DIR" ${HELLO_SOURCE_DIR})

ADD_EXECUTABLE(hello ${SRCLIST})

我这采用的是外部构建,会把生成的临时文件放在build(先创建build文件夹,build文件夹需要和咱们写的CMakeLists.txt同级目录)目录下,为了不会对源文件有任何影响,强烈建议使用外部构建方式,如果是外部构建记得是cmake ..而不是cmake .哦
在这里插入图片描述

PROJECT命令

可以用来指定工程的名字和支持的语言,默认支持所有语言

PROJECT (HELLO) 指定了工程的名字,并且支持所有语言—建议

PROJECT (HELLO CXX) 指定了工程的名字,并且支持语言是C++

PROJECT (HELLO C CXX) 指定了工程的名字,并且支持语言是C和C++

隐式定义了两个CMAKE的变量

<projectname\>_BINARY_DIR,本例中是 HELLO_BINARY_DIR

<projectname\>_SOURCE_DIR,本例中是 HELLO_SOURCE_DIR

问题:如果改了工程名,这两个变量名也会改变

解决:又定义两个预定义变量:PROJECT_BINARY_DIR和PROJECT_SOURCE_DIR,这两个变量和HELLO_BINARY_DIR,HELLO_SOURCE_DIR是一致的。所以改了工程名也没有关系

SET命令

用来显式指定变量

SET(SRC_LIST main.cpp) SRC_LIST变量就包含了main.cpp

也可以 SET(SRC_LIST main.cpp t1.cpp t2.cpp)

MESSAGE命令

向终端输出用户自定义的信息

主要包含三种信息:

  • SEND_ERROR,产生错误,生成过程被跳过。
  • SATUS,输出前缀为—的信息。
  • FATAL_ERROR,立即终止所有 cmake 过程.

ADD_EXECUTABLE命令

生成可执行文件
ADD_EXECUTABLE(hello ${SRC_LIST}) 生成的可执行文件名是hello,源文件读取变量SRC_LIST中的内容

中级阶段——让HelloWorld变得更像一个工程

1、为工程添加一个子目录 src,用来放置工程源代码,使用外部构建,最后将可执行文件放到bin目录下(这个不好用语言表达,看下面的操作你就知道怎么回事了)
层次结构:
在这里插入图片描述
最外层的CMakeLists.txt用于给项目命名,指示源代码放在哪里(到时候就会调用内层的CMakeLists.txt),并可以指定中间二进制和目标二进制存放的位置。
外层CMakeLists.txt

PROJECT(HELLO)

#关联到src下的CMakeLists.txt,生成的二进制文件放到bin目录下
ADD_SUBDIRECTORY(src bin)

内层CMakeLists.txt

SET(SRC_LIST main.cpp)

MESSAGE(STATUS "This is BINARY dir " ${PROJECT_BINARY_DIR})

MESSAGE(STATUS "This is SOURCE dir "${PROJECT_SOURCE_DIR})

ADD_EXECUTABLE(hello ${SRC_LIST})

我们现在回到最外层的build文件夹中cmake
在这里插入图片描述
现在我们再make,那么可执行文件就会到上面的bin目录下
在这里插入图片描述
2、安装

  • 使用INSTALL来实现安装
  • 可以安装二进制、动态库、静态库以及文件、目录、脚本…
  • CMAKE_INSTALL_PREFIX默认为/usr/local/

层次结构(大家在看完上面的基础后,以下面的这个结构创建其他文件)
在这里插入图片描述
外层CMakeLists.txt

PROJECT(HELLO)
# 关联到src下的CMakeLists.txt,生成的二进制文件放到bin目录下
ADD_SUBDIRECTORY(src bin)

# 安装的是文件 要安装什么文件 安装的路径
INSTALL(FILES COPYRIGHT README DESTINATION /home/sqh/qiniuLearning/demo/testMkdir/doc/cmake/)

# 安装脚本,实际安装在usr/local/bin(如果我们就写个bin这样的相对路径的话)
INSTALL(PROGRAMS runhello.sh DESTINATION /home/sqh/qiniuLearning/demo/testMkdir/bin/)

# 安装文档
INSTALL(DIRECTORY doc/ DESTINATION /home/sqh/qiniuLearning/demo/testMkdir/share/doc/cmake)

INSTALL的DETINATION后面可以用绝对路径也可以用相对路径,但是如果使用相对路径的话,则安装的路径为CMAKE_INSTALL_PREFIX/你设置的相对路径,当然CMAKE_INSTALL_PREFIX也是可以改变的,改变的方式有:
①在cmake的时候直接设置cmake -DCMAKE_INSTALL_PREFIX=<你想要安装的路径>
②在CMakeLists.txt内部进行设置SET(CMAKE_INSTALL_PREFIX <install_path>)

进入到build下cmake
在这里插入图片描述
make install,将我们想要安装的东西安装到指定路径,同时也会
在这里插入图片描述

高级阶段——共享库以及使用外部文件

静态库和动态库的区别

  • 静态库的扩展名一般为“.a”或“.lib”;动态库的扩展名一般为“.so”或“.dll”
  • 静态库在编译时会直接整合到目标程序中,编译成功的可执行文件可独立运行
  • 动态库在编译时不会放到连接的目标程序中,即可执行文件无法单独运行。

1、共享库的构建
创建一个新的目录CMake01,在里面创建相关文件
在这里插入图片描述
外层的CMakeLists.txt

PROJECT(HELLO)
ADD_SUBDIRECTORY(lib bin)

内层的CMakeLists.txt

SET(LIBHELLO_SRC hello.cpp)
# hello为生成的lib的名字,SHARED表示会生成一个共享库(静态库则是STATIC),${LIBHELLO_SRC}为源文件
ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})

ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})

  • hello为生成的lib的名字,但是最终生成的库会变成libhello.so
  • SHARED为动态库,STATIC为静态库
  • ${LIBHELLO_SRC}为你用于生成库的源文件

hello.cpp

#include "hello.h"
#include <iostream>

void HelloFunc(){
    std::cout<<"Hello Word"<<std::endl;
}

hello.h

#ifndef HELLO_TEST_H
#define HELLO_TEST_H

void HelloFunc();

#endif

进入到build以后cmake,然后最终生成libhello.so
在这里插入图片描述


2、同时构建动态库和静态库并进行安装
这里可不能说直接ADD_LIBRARY两次就可以(如果是输出的名字不一样那倒是也可以,下面讲的情况是输出的名字相同的静态库和动态库)一下代码是在CMake01目录下
外层CMakeLists.txt不变,内层CMakeLists.txt有如下变化

SET(LIBHELLO_SRC hello.cpp)

ADD_LIBRARY(hello_static STATIC ${LIBHELLO_SRC})

# 对hello_static的重名为hello
SET_TARGET_PROPERTIES(hello_static PROPERTIES  OUTPUT_NAME "hello")
# cmake 在构建一个新的target 时,会尝试清理掉其他使用"这个名字的库",因为,在构建 libhello.so 时, 就会清理掉 libhello.a,这样下面就又可以用hello这个名字了
SET_TARGET_PROPERTIES(hello_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
# ---------------------------------------------------------------------
ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})

SET_TARGET_PROPERTIES(hello PROPERTIES  OUTPUT_NAME "hello")
SET_TARGET_PROPERTIES(hello PROPERTIES CLEAN_DIRECT_OUTPUT 1)
# 文件放到该目录下
INSTALL(FILES hello.h DESTINATION /home/sqh/qiniuLearning/demo/testMkdir/include/hello)

# 二进制,静态库,动态库安装都用TARGETS
# ARCHIVE 特指静态库,LIBRARY 特指动态库,RUNTIME 特指可执行目标二进制。
INSTALL(TARGETS hello hello_static LIBRARY DESTINATION /home/sqh/qiniuLearning/demo/testMkdir/lib ARCHIVE DESTINATION /home/sqh/qiniuLearning/demo/testMkdir/lib)

SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME “hello”)把hello_static重命名为hello

SET_TARGET_PROPERTIES(hello_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)将资源进行清理,这样下面就又可以使用hello这个名字了

INSTALL(TARGETS hello hello_static LIBRARY DESTINATION /home/sqh/qiniuLearning/demo/testMkdir/lib ARCHIVE DESTINATION /home/sqh/qiniuLearning/demo/testMkdir/lib)

  • TARGETS:二进制、库想要安装都是用TARGETS
  • hello和hello_static为要安装的库
  • LIBRARY DESTINATION后面跟的是动态库要安装到哪里去
  • ARCHIVE DESTINATION后面跟的是静态库要安装到哪里去

回到build下cmake并make install

在这里插入图片描述


3、使用外部共享库和头文件

新创建一个目录CMake02,新目录的此次结构如下:
在这里插入图片描述
外层CMakeLists.txt

PROJECT(HELLO)
ADD_SUBDIRECTORY(src bin)

main.cpp

#include <hello.h>

int main(){
	HelloFunc();
	return 0;
}

最关键的内层CMakeLists.txt

INCLUDE_DIRECTORIES(/home/sqh/qiniuLearning/demo/testMkdir/include/hello)
ADD_EXECUTABLE(hello main.cpp)
TARGET_LINK_LIBRARIES(hello /home/sqh/qiniuLearning/demo/testMkdir/lib/libhello.so)
  • INCLUDE_DIRECTORIES(/home/sqh/qiniuLearning/demo/testMkdir/include/hello,INCLUDE_DIRECTORIES用于包含头文件,hello文件夹下存的是咱们前面INSTALL到include/hello下的hello.h,就是👇
    在这里插入图片描述
  • TARGET_LINK_LIBRARIES(hello /home/sqh/qiniuLearning/demo/testMkdir/lib/libhello.so),TARGET_LINK_LIBRARIES用于链接库(这里hello一定要与上面ADD_EXECUTABLE所生成的可执行文件名相同),这里的libhello.so就是咱们前面通过.cpp文件生成的库文件,那个cpp文件就是👇
    在这里插入图片描述

最终呈现的结果:
在这里插入图片描述


感谢大家看完这篇文章,如果这篇文章对您有些许帮助,我会感到万分荣幸😊😊,当然,如果哪里有不足的地方也欢迎大家指出
大家可以点开这个链接看看,这个up将cmake讲的挺好的,我这里的总结也有非常多是来自这里的

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值