我们需要懂得CMake文件


一、前言

从事于linux下的C++开发的人员都知道,在C++下编写程序是没有类似windows下编译器的一键编译和运行的按钮,只能由我们开发人员进行手动编译、运行;为了减免这种繁琐而且复杂的劳动力,出现了makefile文件,makefile文件可以帮助我们很快的编译大量文件,最终形成可执行文件;其实编写makefile文件并不是很复杂,但是后面出现了cmake,这个可以直接帮我们写makefile文件,我们只需要编写cmake文件即可;

接下来,我们去看看cmake的一些规则和实践,我会从实践中来说明这些规则;


二、cmake

我们从案例开始

  • 案例一:

    demo1的文件夹下,创建test.cpp文件和CMakeLists.txt文件;

    test.cpp下存放的是我们测试的c++程序;

    CMakeLists.txt就是cmake文件;

    测试程序:

    #include #include 
    
    using namespace std;
    
    class Test:public enable_shared_from_this{public:    Test(){}    ~Test(){}shared_ptr getPtr()    {return shared_from_this();    }void set(int id,string name){        _id = id;        _name = name;    }int getId(){return _id;    }string getName(){return _name;    }private:string _name;int _id;};int main(){shared_ptrt1 = make_shared();    t1->set(1,"test");cout<<"id:"<getId()<<endl;cout<<"name:"<getName()<<endl;return 0;}

    CMakeList.txt文件内容:

    # 指定运行此配置文件所需的 CMake 的最低版本cmake_minimum_required (VERSION 2.8)
    
    #命令表示项目的名称是 Demo1project (demo1)#添加-std=c++11选项set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")#命令表示生成项目的名称是 testadd_executable(test test.cpp)

    然后,我们在当前目录下执行cmake .进行编译生成makefile


然后,执行make命令;


我们会发现,当前目录下出现了可执行程序


我们从上面这个案例中,来解析cmake文件的语法:

  • 指定运行此配置文件所需的 CMake 的最低版本,如果不加入此行会受到警告信息

    cmake_minimum_required (VERSION 2.8)
  • 表示项目的名称是 Demo1,也就是在哪个文件夹中

    project (demo1)
  • 生成应用程序 test

    add_executable(test test.cpp)
  • 添加-std=c++11选项

    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")或者add_compile_options(-std=c++11)

    cmake脚本中,设置编译选项可以通过add_compile_options命令,也可以通过set命令修改CMAKE_CXX_FLAGSCMAKE_C_FLAGS。但是set命令设置CMAKE_C_FLAGSCMAKE_CXX_FLAGS变量则是分别只针对c和c++编译器的;

    上面我们会发现产生了很多cmake的中间文件,我们可以创建一个文件夹,将所有的中间文件以及最终的执行文件放在其中:

    root@iZuf67on1pthsuih96udyfZ:~/C++/CMake/demo2# mkdir buildroot@iZuf67on1pthsuih96udyfZ:~/C++/CMake/demo2# cd build/root@iZuf67on1pthsuih96udyfZ:~/C++/CMake/demo2/build# cmake ..

    这样就ok了;

通过上面这个例子,我们大概熟悉了cmake的最基本的、也是核心的用法;


  • 案例二:(多文件)

    目录结构

    root@iZuf67on1pthsuih96udyfZ:~/C++/CMake/demo2# tree.├── CMakeLists.txt├── hello.cpp├── hello.h└── test.cpp
    
    0 directories, 4 files

    首先看下文件内容:

    test.cpp

    #include #include #include "hello.h"using namespace std;
    
    class Test:public enable_shared_from_this{public:    Test(){}    ~Test(){}shared_ptr getPtr()    {return shared_from_this();    }void set(int id,string name){        _id = id;        _name = name;    }int getId(){return _id;    }string getName(){return _name;    }private:string _name;int _id;};int main(){shared_ptrt1 = make_shared();shared_ptrt2 = make_shared();    t1->set(1,"test");cout<<"id:"<getId()<<endl;cout<<"name:"<getName()<<endl;    t2->setVal(10);cout<<"val:"<getVal()<<endl;return 0;}

    hello.h

    #pragma once#include 
    
    using namespace std;
    
    class Hello{public:    Hello();    ~Hello();void setVal(int val);int getVal();private:int _val;};

    hello.cpp

    #include "hello.h"
    
    Hello::Hello(){
    
    }
    
    Hello::~Hello(){
    
    }
    
    void Hello::setVal(int val){    _val = val;}
    
    int Hello::getVal(){return _val;}

    再看看cmake文件:

    CMakeLists.txt

    # 指定运行此配置文件所需的 CMake 的最低版本cmake_minimum_required (VERSION 2.8)
    
    #命令表示项目的名称是 Demo2project (demo2)
    
    #添加-std=c++11选项set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
    
    #查找当前目录下的所有源文件,并将名称保存到 DIR_SRCS 变量aux_source_directory(. DIR_SRCS)
    
    #命令表示生成项目的名称是 mainadd_executable(main ${DIR_SRCS})

    解析一下这个用法:

    相比于第一个案例来说,这个文件新增了

    aux_source_directory(. DIR_SRCS)

    这句代码的代表:查找当前目录下的所有源文件,并将名称保存到 DIR_SRCS 变量

    我们看一下aux_source_directory的用法:

    aux_source_directory(

    )

    该命令会把参数

    然后使用${}方式获取值;

    那么,如果在不同的问价夹,那么怎么办?


  • 案例三:多文件 多目录

    我们只是把上面的文件进行移动,最终的目录结构为:

    .├── CMakeLists.txt├── hello│   ├── CMakeLists.txt│   ├── hello.cpp│   └── hello.h└── test.cpp
    
    1 directory, 5 files

    想比较刚才只是将hello.hhello.cpp文件移动到hello的文件夹中;

    我们需要写两个cmake文件

    最外层CMakeLists.txt文件内容:

    # 指定运行此配置文件所需的 CMake 的最低版本cmake_minimum_required (VERSION 2.8)
    
    #命令表示项目的名称是 Demo2project (demo3)
    
    #添加-std=c++11选项set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
    
    #查找当前目录下的所有源文件,并将名称保存到 DIR_SRCS 变量aux_source_directory(. DIR_SRCS)# 添加 hello 子目录add_subdirectory(hello)
    
    #命令表示生成项目的名称是 mainadd_executable(main ${DIR_SRCS})
    
    #添加动态库target_link_libraries(main hello)

    在hello文件夹中的CMakeLists.txt文件:

    # 指定运行此配置文件所需的 CMake 的最低版本cmake_minimum_required (VERSION 2.8)
    
    #查找当前目录下的所有源文件,并将名称保存到 DIR_SRCS 变量aux_source_directory(. DIR_LIB_SRCS)
    
    # 生成链接库add_library(hello ${DIR_LIB_SRCS})

    相比于前面的CMakeLists.txt的文件来说,本次的cmake文件,多了以下几个规则:


    add_library:

    该指令的主要作用就是将指定的源文件生成链接文件,然后添加到工程中去。该指令常用的语法如下:

    add_library( [STATIC | SHARED | MODULE][EXCLUDE_FROM_ALL][source1] [source2] [...])

    其中表示库文件的名字,该库文件会根据命令里列出的源文件来创建。而STATIC、SHARED和MODULE的作用是指定生成的库文件的类型。STATIC库是目标文件的归档文件,在链接其它目标的时候使用。SHARED库会被动态链接(动态链接库),在运行时会被加载。MODULE库是一种不会被链接到其它目标中的插件,但是可能会在运行时使用dlopen-系列的函数。默认状态下,库文件将会在于源文件目录树的构建目录树的位置被创建,该命令也会在这里被调用。而语法中的source1 source2分别表示各个源文件。


    link_directories该指令的作用主要是指定要链接的库文件的路径,该指令有时候不一定需要。因为find_packagefind_library指令可以得到库文件的绝对路径。不过你自己写的动态库文件放在自己新建的目录下时,可以用该指令指定该目录的路径以便工程能够找到。


    target_link_libraries该指令的作用为将目标文件与库文件进行链接。该指令的语法如下:

    target_link_libraries( [item1] [item2] [...][[debug|optimized|general] ] ...)上述指令中的是指通过add_executable()和add_library()指令生成已经创建的目标文件。而[item]表示库文件没有后缀的名字。默认情况下,库依赖项是传递的。当这个目标链接到另一个目标时,链接到这个目标的库也会出现在另一个目标的连接线上。这个传递的接口存储在interface_link_libraries的目标属性中,可以通过设置该属性直接重写传递接口。


    这个就是多文件多目录操作,这里贴以下具体流程截图:




  • 案例四:(分类文件夹)

    在实际公司开发的时候,我们遇到最多就是使用分类文件夹的方式,就比如头文件一般放在当前目录下的include的目录下,.cpp文件一般放在src文件中,静态、动态库可以放在lib中;一般来说,这种事比较规范的,而且我们不需要根据头文件进行寻找文件的位置;

    先看一下案例的目录:

    root@iZuf67on1pthsuih96udyfZ:~/C++/CMake/demo5# tree ..├── CMakeLists.txt├── example│   └── test.cpp├── include│   └── hello.h└── src    └── hello.cpp
    
    3 directories, 4 files

    简单看一下文件的内容:

    CMakeLists.txt

    cmake_minimum_required(VERSION 2.8)
    
    project(demo4)
    
    set(CMAKE_CXX_STANDARD 11)
    
    set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
    
    include_directories(        ${PROJECT_SOURCE_DIR}/include/)
    
    add_library(${PROJECT_NAME} SHARED        src/hello.cpp)
    
    add_executable(test example/test.cpp)
    
    target_link_libraries(test        ${PROJECT_NAME})

    example/test.cpp

    #include "hello.h"
    
    int main(){    HelloTest ht;    ht.Print();return 0;}

    include\hello.h

    #include "hello.h"
    
    HelloTest::HelloTest(){
    
    }
    
    HelloTest::~HelloTest(){
    
    }
    
    void HelloTest::Print(){cout<<"HelloTest"<<endl;}
    
    

    先来执行一下:


    运行一下:


    我们发现运行成功了,再看看目录文件:

    .├── build│   ├── CMakeCache.txt│   ├── CMakeFiles│   │   ├── 3.5.1│   │   │   ├── CMakeCCompiler.cmake│   │   │   ├── CMakeCXXCompiler.cmake│   │   │   ├── CMakeDetermineCompilerABI_C.bin│   │   │   ├── CMakeDetermineCompilerABI_CXX.bin│   │   │   ├── CMakeSystem.cmake│   │   │   ├── CompilerIdC│   │   │   │   ├── a.out│   │   │   │   └── CMakeCCompilerId.c│   │   │   └── CompilerIdCXX│   │   │       ├── a.out│   │   │       └── CMakeCXXCompilerId.cpp│   │   ├── cmake.check_cache│   │   ├── CMakeDirectoryInformation.cmake│   │   ├── CMakeOutput.log│   │   ├── CMakeTmp│   │   ├── demo4.dir│   │   │   ├── build.make│   │   │   ├── cmake_clean.cmake│   │   │   ├── CXX.includecache│   │   │   ├── DependInfo.cmake│   │   │   ├── depend.internal│   │   │   ├── depend.make│   │   │   ├── flags.make│   │   │   ├── link.txt│   │   │   ├── progress.make│   │   │   └── src│   │   │       └── hello.cpp.o│   │   ├── feature_tests.bin│   │   ├── feature_tests.c│   │   ├── feature_tests.cxx│   │   ├── Makefile2│   │   ├── Makefile.cmake│   │   ├── progress.marks│   │   ├── TargetDirectories.txt│   │   └── test.dir│   │       ├── build.make│   │       ├── cmake_clean.cmake│   │       ├── CXX.includecache│   │       ├── DependInfo.cmake│   │       ├── depend.internal│   │       ├── depend.make│   │       ├── example│   │       │   └── test.cpp.o│   │       ├── flags.make│   │       ├── link.txt│   │       └── progress.make│   ├── cmake_install.cmake│   ├── Makefile│   └── test├── CMakeLists.txt├── example│   └── test.cpp├── include│   └── hello.h├── lib│   └── libdemo4.so└── src    └── hello.cpp

    cmake产生的中间文件我们不用关心,主要就是在lib文件夹中产生了libdemo4.so文件;

    详细看一下CMakeLists.txt文件:

    • 按照C++11标准

      set(CMAKE_CXX_STANDARD 11)

    • 设置编译动态库输出路径

      set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)

      PROJECT_SOURCE_DIR代表的是CMakeLists.txt所在目录

    • include_directories 是用来提供找头文件路径的

      include_directories(        ${PROJECT_SOURCE_DIR}/include/)

基本的cmake使用的就这么多了,当然,cmake文件还有很多的用法,不过在平时普通的项目中,这些基本够用了,更高级的语法后面还会逐渐完善。


想了解学习更多C++后台服务器方面的知识,请关注:微信公众号:====CPP后台服务器开发====


扫码CPP后台服务器开发转载是一种动力 分享是一种美德

cmake 指定编译器_我们需要懂得CMake文件相关推荐

  1. c语言make编译器,cmake 指定编译器

    vs2015 x64编译器为例,cmake命令如下: Xml代码  收藏代码 cmake -G "Visual Studio 14 Win64" path\to\source\di ...

  2. cmake指定编译器

    vs2015 x64编译器为例,cmake命令如下: Xml代码 收藏代码 cmake -G "Visual Studio 14 Win64" path\to\source\dir ...

  3. python删除txt指定内容_正则表达式使用python从文件中过滤和删除特定的多行文本...

    我正在编写一个python工具来处理一组文件.该工具将由其他用户而非我使用. 文件类似于以下格式: #Text which I want to keep intact #Lots of text #L ...

  4. linux下通过user-config.jam指定编译器编译boost

    bjam是boost的编译工具,类似于gnu make,boost就是用bjam编译的,bjam很聪明,在编译boost的时候,会自动从系统中寻找合适的编译器来完成boost编译. 但是如果系统中存在 ...

  5. 【CMAKE】指定编译器架构(x86 or x64)

    1.Windows vs2015 x64编译器为例,cmake命令如下: cmake -G "Visual Studio 14 Win64" path\to\source\dir ...

  6. win10 vscode+clangd代码提示+cmake+mingw编译器和调试器

    win10 vscode+clangd代码提示+cmake+mingw编译器和调试器 前言 第一步,把cmake,mingw,llvm-win64安装好 安装好vscode必备的插件 利用cmake构 ...

  7. CMake 指定安装目录

    使用 CMAKE_INSTALL_PREFIX 来指定. 方法1: cmake -DCMAKE_INSTALL_PREFIX=/usr .. 方法二: 修改cmake文件,加入: SET(CMAKE_ ...

  8. cmake 构建路径_基于CMake构建系统的MLIR Example扩展

    上一篇文章讲了把pybind11的示例程序嵌入到了MLIR的Example中,但是在构建的过程中有一定运气成分,并不知道具体是怎么通过CMake构建系统编译出的共享库文件.在分析了MLIR各层级的CM ...

  9. cmakelist官方教程_超详细的cmake入门教程

    什么是cmake 你或许听过好几种 Make 工具,例如 GNU Make ,QT 的 qmake ,微软的 MSnmake,BSD Make(pmake),Makepp,等等.这些 Make 工具遵 ...

最新文章

  1. 手机php环境的openss_php开启openssl的方法
  2. Linux 桌面玩家指南:17. 在 Ubuntu 中使用 deepin-wine,解决一些依赖 Windows 的痛点问题
  3. Oracle-绑定变量binding variable解读
  4. (转) 淘淘商城系列——Redis五种数据类型介绍
  5. python wheel使用_Python wheel.Wheel方法代碼示例
  6. Linux系统:centos7下搭建ZooKeeper3.4中间件,常用命令总结
  7. markdown引入代码_markdown简单使用之插入代码段
  8. SQL DATACOMPARE 实现两个数据库的同步处理.
  9. Coherence X:将任意网站转为macOS应用
  10. 竞价推广账户日常优化需要注意十大要点
  11. grasshopper for rhino 6下载_漫谈算法设计与脚本语言(grasshopper, python)
  12. TCC解决分布式事务问题
  13. 数据结构利器之私房STL(中)
  14. oracle 数据备份视频,赵强老师:Oracle数据库(之四):备份与恢复视频课程
  15. python结巴怎么安装_Python3.6 结巴分词安装和使用
  16. 红帽linux中文系统下载iso,红帽子9.0版下载-redhat linux 9.0 iso下载 简体中文正式版-IT猫扑网...
  17. 使用 stm32实现锂电充电_12V锂电池保护板电路图锂电池保护板工作原理及短路、过充电等控制原理分析...
  18. div 设置a4大小_如何在A4纸张尺寸页面中制作HTML页面?
  19. 你会卖掉自己的网上信息吗?大数据可能根本不属于你
  20. 这样拆分和压缩css代码

热门文章

  1. 如何查看linux系统的密码是多少,如何在Linux系统查询SAM密码
  2. java连接电脑可以把整个文件下载到手机里然后直接用么,如果是山寨机支持java如何用电脑往手机上下载软件...
  3. django render_2020年最新Django经典面试问题与答案汇总(下)大江狗整理
  4. 定位的坐标原点HTML,html 定位
  5. linux 动态库建立,浅析linux下静态库和动态库的建立和使用
  6. selenium python_Python+Selenium基础入门及实践
  7. Flask框架(flask中的蓝图Blueprint)
  8. VTK:BSP树时序用法实战
  9. wxHtml 示例:演示虚拟文件系统功能
  10. wxWidgets:wxFilterClassFactory类用法