Cmake的使用

Cmake的使用vscodeCmake简介Cmake语法重要指令和CMake常用变量重要指令CMake常用变量CMake编译工程CMake代码实践CMake完整项目调试步骤launch.json和tasks.jsonCmake简介简介CMake是一个跨平台的安装编译工具,可以用简单的语句来描述所有平台的安装(编译过程)。CMake可以说已经成为大部分C++开源项目标配传统的C++文件不通系统对应不通的编译比如 当添加一个文件的时候需要对不通操作系统中的工程进行修改有了Cmake以后,只需要编写

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

Cmake简介

简介

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

  • CMake可以说已经成为大部分C++开源项目标配

传统的C++文件不通系统对应不通的编译
在这里插入图片描述
比如 当添加一个文件的时候需要对不通操作系统中的工程进行修改
在这里插入图片描述
有了Cmake以后,只需要编写一个CmakeLists文件就可以对应将一个C++工程不通操作系统
在这里插入图片描述
当新添加一个文件的时候只需要更改对应的CmakeLists即可
在这里插入图片描述

Cmake语法

基本语法格式:指令(参数 1 参数 2…)

  • 参数使用括弧括起
  • 参数之间使用空格或分号分开

指令是大小写无关的,参数和变量是大小写相关的

set(HELLO hello.cpp)
add_executable(hello main.cpp hello.cpp)
ADD_EXECUTABLE(hello main.cpp ${HELLO})

变量使用${}方式取值,但是在 IF 控制语句中是直接使用变量名

重要指令和CMake常用变量

重要指令

cmake_minimum_required – 指定CMake的最小版本要求

# CMake最小版本要求为2.8.3
cmake_minimum_required(VERSION 2.8.3)
  • 语法:cmake_minimum_required(VERSION versionNumber [FATAL_ERROR])

project – 定义工程名称,并可指定工程支持的语言

# 指定工程名为HELLOWORLD
project(HELLOWORLD)
  • 语法:project(projectname [CXX] [C] [Java])

set – 显式的定义变量

# 定义SRC变量,其值为main.cpp hello.cpp
set(SRC sayhello.cpp hello.cpp)
  • 语法:set(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])

include_directories – 向工程添加多个特定的头文件搜索路径 —>相当于指定g++编译器的-I参数

# 将/usr/include/myincludefolder 和 ./include 添加到头文件搜索路径
include_directories(/usr/include/myincludefolder ./include)
  • 语法:include_directories([AFTER|BEFORE] [SYSTEM] dir1 dir2 …)

link_directories – 向工程添加多个特定的库文件搜索路径 —>相当于指定g++编译器的-L参数

# 将/usr/lib/mylibfolder 和 ./lib 添加到库文件搜索路径
link_directories(/usr/lib/mylibfolder ./lib)
  • 语法:link_directories(dir1 dir2 …)

add_library – 生成库文件

# 通过变量 SRC 生成 libhello.so 共享库
add_library(hello SHARED ${SRC})
  • 语法:add_library(libname [SHARED|STATIC|MODULE] [EXCLUDE_FROM_ALL] source1 source2 … sourceN)

add_compile_options – 添加编译参数

1# 添加编译参数 -Wall -std=c++11
2add_compile_options(-Wall -std=c++11 -O2)
  • 语法:add_compile_options(

add_executable – 生成可执行文件

# 编译main.cpp生成可执行文件main
add_executable(main main.cpp)
  • 语法:add_executable(exename source1 source2 … sourceN)

target_link_libraries – 为 target 添加需要链接的共享库 —>相同于指定g++编译器-l参数,用在add_executable之后(link_library用在add_excutable之前)

# 将hello动态库文件链接到可执行文件main
target_link_libraries(main hello)
  • 语法:target_link_libraries(target library1library2…)

add_subdirectory – 向当前工程添加存放源文件的子目录,并可以指定中间二进制和目标二进制存放的位置

# 添加src子目录,src中需有一个CMakeLists.txt
add_subdirectory(src)
  • 语法:add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])

aux_source_directory – 发现一个目录下所有的源代码文件并将列表存储在一个变量中,这个指令临时被用来自动构建源文件列表

# 定义SRC变量,其值为当前目录下所有的源代码文件
aux_source_directory(. SRC)
# 编译SRC变量所代表的源代码文件,生成main可执行文件
add_executable(main ${SRC})
  • 语法:aux_source_directory(dir VARIABLE)

CMake常用变量

CMAKE_C_FLAGS gcc编译选项
CMAKE_CXX_FLAGS g++编译选项

# 在CMAKE_CXX_FLAGS编译选项后追加-std=c++11
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

CMAKE_BUILD_TYPE 编译类型(Debug, Release)

# 设定编译类型为debug,调试时需要选择debug
set(CMAKE_BUILD_TYPE Debug) 
# 设定编译类型为release,发布时需要选择release
set(CMAKE_BUILD_TYPE Release) 

CMAKE_BINARY_DIR
PROJECT_BINARY_DIR
__BINARY_DIR

这三个变量指代的内容是一致的。
如果是 in source build,指的就是工程顶层目录。
如果是 out-of-source 编译,指的是工程编译发生的目录。
PROJECT_BINARY_DIR 跟其他指令稍有区别,不过现在,你可以理解为他们是一致的。

CMAKE_SOURCE_DIR
PROJECT_SOURCE_DIR
__SOURCE_DIR

这三个变量指代的内容是一致的,不论采用何种编译方式,都是工程顶层目录。
也就是在 in source build时,他跟 CMAKE_BINARY_DIR 等变量一致。
PROJECT_SOURCE_DIR 跟其他指令稍有区别,现在,你可以理解为他们是一致的。

CMAKE_C_COMPILER:指定C编译器

CMAKE_CXX_COMPILER:指定C++编译器

EXECUTABLE_OUTPUT_PATH:可执行文件输出的存放路径

LIBRARY_OUTPUT_PATH:库文件输出的存放路径

CMake编译工程

CMake目录结构:项目主目录存在一个CMakeLists.txt文件

两种方式设置编译规则:

  • 包含源文件的子文件夹包含CMakeLists.txt文件,主目录的CMakeLists.txt通过add_subdirectory添加子目录即可;
  • 包含源文件的子文件夹未包含CMakeLists.txt文件,子目录编译规则体现在主目录的CMakeLists.txt中;

编译流程

在 linux 平台下使用 CMake 构建C/C++工程的流程如下:

手动编写 CmakeLists.txt。
执行命令 cmake PATH生成 Makefile ( PATH 是顶层CMakeLists.txt 所在的目录 )。
执行命令make 进行编译。
# important tips
.          # 表示当前目录
./         # 表示当前目录

..      # 表示上级目录
../     # 表示上级目录

两种构建方式
内部构建(in-source build):不推荐使用

内部构建会在同级目录下产生一大堆中间文件,这些中间文件并不是我们最终所需要的,和工程源文件放在一起会显得杂乱无章。

## 内部构建

# 在当前目录下,编译本目录的CMakeLists.txt,生成Makefile和其他文件
cmake .
# 执行make命令,生成target
make

外部构建(out-of-source build):推荐使用

将编译输出文件与源文件放到不同目录中

## 外部构建
 
# 1. 在当前目录下,创建build文件夹
mkdir build 

# 2. 进入到build文件夹
cd build

# 3. 编译上级目录的CMakeLists.txt,生成Makefile和其他文件
cmake ..

# 4. 执行make命令,生成target
make

CMake代码实践

针对第五章写的两个小项目来写对应的CMakeLists.txt

最小CMake工程

# Set the minimum version of CMake that can be used
cmake_minimum_required(VERSION 3.0)

# Set the project name
project (HELLO)

# Add an executable
add_executable(hello_cmake main.cpp)

多目录工程 – 直接编译

cmake_minimum_required(VERSION 3.0)

project(HELLOWORLD)

#对应 -Iinclude
include_directories(include)

#main_cmake 是输出文件名
add_executable(main_cmake main.cpp src/swap.cpp)

多目录工程 – 生成库编译

# Set the minimum version of CMake that can be used
cmake_minimum_required(VERSION 3.0)
 
#project name 
project(SWAP_LIBRARY)
 
#add compile options
add_compile_options("-Wall -std=c++11")
 
#set CMAKE_BUILD_TYPE
set( CMAKE_BUILD_TYPE Debug ) 

# set output binary path 
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)

############################################################
# Create a library
############################################################

#Generate the static library from the library sources
add_library( swap_library STATIC src/Swap.cpp )

target_include_directories( swap_lib PUBLIC ${PROJECT_SOURCE_DIR}/include )

############################################################
# Create an executable
############################################################

# Add an executable with the above sources
add_executable( swap_01 main.cpp )

# link the new swap_01 target with the swap_lib target
target_link_libraries( swap_01 swap_liby )

CMake完整项目

.
│  CMakeLists.txt
│  main.cpp
│  myexe.exe
│
├─build
├─include
│      Gun.h
│      Solider.h
│
└─src
        Gun.cpp
        Solider.cpp

main.cpp

#include "Gun.h"
#include "Solider.h"

void test(){ 
   
    Solider solider("xusanduo");
    solider.addGun(new Gun("AK47"));
    solider.addBulletToGun(20);
    solider.fire();
}
int main(){ 
   
    test();
    return 0;
}

Gun.h

#pragma once
#include<string>

class Gun{ 
   
public:
    Gun(std::string type){ 
   
        this->_bullet_count = 0;
        this->_type = type;
    }
    void addBullet(int bullet_num);
    bool shoot();
private:
    int _bullet_count;
    std::string _type;
};

Solider.h

#pragma once

#include<string>
#include "Gun.h"
class Solider{ 
   
public:
    Solider(std::string name);
    void addBulletToGun(int num);
    bool fire();
    void addGun(Gun *ptr_gun);
    ~Solider();
private:
    std::string _name;
    Gun * _ptr_gun;
};

Gun.cpp

#include "Gun.h"
#include<iostream>
using namespace std;

void Gun::addBullet(int bullet_num){ 
   
    this->_bullet_count += bullet_num;
}

bool Gun::shoot(){ 
   
    if (this->_bullet_count <= 0)
    { 
   
        cout << "there is no bullet !" << endl;
        return false;
    }
    this->_bullet_count -= 1;
    cout << "shoot successfully" << endl;
    return true;
}

Solider.cpp

#include "Solider.h"

Solider::Solider(std::string name){ 
   
    this->_name = name;
    this->_ptr_gun = nullptr;
}

void Solider::addGun(Gun *ptr_gun){ 
   
    this->_ptr_gun = ptr_gun;
}

void Solider::addBulletToGun(int num){ 
   
    this->_ptr_gun->addBullet(num);
}

bool Solider::fire(){ 
   
    this->_ptr_gun->shoot();
    return true;
}
Solider::~Solider(){ 
   
    if(this->_ptr_gun == nullptr){ 
   
        return;
    }
    delete this->_ptr_gun;
    this->_ptr_gun = nullptr;
}
  1. 命令行编译
g++ .\main.cpp .\src\Gun.cpp .\src\Solider.cpp -Iinclude -o myexe
  1. cmake编译
    CMakeLists.txt文件
cmake_minimum_required(VERSION 3.0)

project(SOLIDER)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")

set(CMAKE_BUILD_TYPE Debug)

include_directories(include)
#或者include_directories(${CMAKE_SOURCE_DIR}/include)

add_executable(myexe main.cpp src/Gun.cpp src/Solider.cpp)

编译

cd build

cmake ..

make

当更改文件后 直接用make命令构建即可 make会只编译修改的文件

调试步骤launch.json和tasks.json

{ 
   
    "version": "0.2.0",
    "configurations": [
        { 
   
            "name": "(gdb) 启动",
            "type": "cppdbg",
            "request": "launch",
            "program": "输入程序名称,例如 ${workspaceFolder}/a.exe",   //可执行文件
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",    //进入当前工作目录
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "miDebuggerPath": "/path/to/gdb",   //gdb路径
            "setupCommands": [
                { 
   
                    "description": "为 gdb 启用整齐打印",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ],
            "preLaunchTask": "build"    //调试之前执行的任务 一般是生成exe文件
        }
    ]
}

tasks.json

{ 
   
    "version": "2.0.0",
    "options": { 
   
        "cwd": "${workspaceFolder}/build"	#进入build目录
    },
    "tasks": [
        { 
   
            "type": "shell",	#第一个task
            "label": "cmake",
            "command": "cmake",
            "args": [
                ".."
            ]
        },
        { 
   
            "label": "make",	#第二个task
            "group": { 
   
                "kind": "build",
                "isDefault": true
            },
            "command": "mingw32-make.exe",	#win10下是mingw32.make linux下是make
            "args": [

            ]
        },
        { 
   
            "label": "Build",	#task任务名 和launch.json中的preLaunchTask对应
            "dependsOrder": "sequence",	#顺序执行task任务
            "dependsOn":[
                "cmake",
                "make"
            ]
        }
    ]
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/168517.html原文链接:https://javaforall.net

(0)
上一篇 2022年8月9日 下午6:00
下一篇 2022年8月9日 下午6:00


相关推荐

  • 国标 计算机机房,国标相关知识:电子信息系统机房设计规范(GB50174-2008)[通俗易懂]

    国标 计算机机房,国标相关知识:电子信息系统机房设计规范(GB50174-2008)[通俗易懂]1总则1.0.1为规范电子信息系统机房设计,确保电子信息系统安全、稳定、可靠地运行,做到技术先进、经济合理、安全适用、节能环保,制定本规范。1.0.2本规范适用于建筑中新建、改建和扩建的电子信息系统机房的设计。1.0.3电子信息系统机房的设计应遵循近期建设规模与远期发展规划协调一致的原则。1.0.4电子信息系统机房设计除应符合本规范外,尚应符合国家现行有关标准、规范的规定。2术语2.0.1电子信息…

    2022年10月2日
    9
  • OpenClaw:让你的 AI 助手拥有真正的技能系统

    OpenClaw:让你的 AI 助手拥有真正的技能系统

    2026年3月13日
    2
  • loadrunner 压力测试工具下载

    loadrunner 压力测试工具下载loadrunner下载 http://willvvv.iteye.com/blog/1198158 用户名密码: user1  user1

    2022年7月17日
    17
  • springboot打包成jar jsp文件无法访问

    springboot打包成jar jsp文件无法访问出现这种情况的原因是静态资源没有打包到 jar 如何解决 ps 本编博客不是解决 thymeleaf 模板引擎的问题第一步在 pom xml 文件的 amp lt build amp gt amp lt build amp gt 标签下添加如下 amp lt resources amp gt amp lt resou

    2025年11月10日
    8
  • python中 列表(List)转换为字符串(Str)的方法

    python中 列表(List)转换为字符串(Str)的方法1、List列表转为Str字符串List中存的是字符串的时候,一般是通过.join()函数去转换:例:dataList=[‘1′,’2′,’3′,’4’]str1=“,”+join(dataList)print(dataList)…

    2022年6月2日
    51
  • flyweight设计模式_适配器模式菜鸟

    flyweight设计模式_适配器模式菜鸟亨元模式动机模式定义实例结构要点总结笔记。动机在软件系统采用纯粹对象方案的问题在于大量细粒度的对象会很快充斥在系统中,从而带来很高的运行时代价—主要指内存需求方面的代价如何在避免大量细粒度对象问题的同时,让外部客户仍然能够透明地使用面向对象地方式来进行操作模式定义运用共享技术有效地支持大量细粒度地对象。实例每一个字符都是一个字体 字体对象Fontclass Font{private: //unique object key string key; //object

    2022年8月9日
    16

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号