首页 > 其他分享 >CMake极速入门

CMake极速入门

时间:2024-05-01 11:12:07浏览次数:16  
标签:可执行文件 CMake 入门 PROJECT SOURCE add DIR cmake 极速

引言

还在手写晦涩难懂的Makefile文件吗?现如今,主流的c++项目都采取CMake作为项目构建工具,CMake可以跨平台运行,而且语法相对Makefile而言直观很多,是时候将Makefile扫进垃圾堆了。

Hello, World!

首先先以单个源文件项目为讲解,新建一个main.cpp文件:

#include<iostream>

using namespace std;

int main(void){
    cout<<"Hello, World!"<<endl;
}

那么如何使用CMake编译这个文件呢?CMake所有的语句都写在一个名为CMakeLists.txt的文件下,新建这个文件:

#设置cmake运行时最低版本
cmake_minimum_required(VERSION 3.0.0)

#设置项目名
project(hello)

#添加可执行文件
add_executable(${PROJECT_NAME} main.cpp)

cmake_minimum_required函数的作用是限定运行的cmake版本,因为cmake脚本语言的sdk可能会有变化,老版本运行不起来。project函数就不解释了,见闻知意。add_executable函数是起到编译作用的,第一个参数是编译后的可执行程序名称(这里PROJECT_NAME是一个变量,当我们用project函数设定项目名时,会自动赋值给它,而${}是CMake中调用变量的语法),之后的参数是编译可执行文件需要的源文件依赖。
终端输入cmake .
image
可以看到,cmake正在检查系统环境,检查c,c++编译器路径,命令执行完毕后,你会发现当前目录下多了很多东西:
image
其中最关键的是Makefile文件,也就是说CMake自动将CMakeLists.txt中的语句转化为Makefile文件了,执行make命令:
image
可以看到,成功运行了,相比于手写Makefile文件,优雅许多。

目录简洁化

输入ls,查看项目当前文件:
image
可以看到,cmake生成了很多中间产物,这就把目录搞脏了,有一个约定俗成的处理方法是,新建一个build目录:
image
在build目录下执行cmake ..make
image
可以看到,这样项目目录就干净多了,编译文件和项目文件互不干涉。但是编译后的可执行文件也混在build目录中了,如果我想把可执行文件放在一个单独的目录里,该怎么做呢?

设置可执行文件输出目录

我通常喜欢把可执行文件放到项目目录下的bin文件夹,新建一个bin目录,并在CMakeLists.txt文件中添加:

set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

通过设置EXECUTABLE_OUTPUT_PATH变量即可实现。

引入库文件,头文件

实际项目中不可能就一个源文件,我们还会将代码分类,组织成不同的头文件和库文件,那么CMake怎么引入呢?
假设我们现在想给Hello World程序加一个加法功能。在项目目录下,新建一个src文件夹,用于存放库文件;新建一个inc文件夹,用于存放头文件。
编写inc/add.h:

#pragma once

int add(int a,int b);

编写src/add.cpp:

#include"add.h"

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

当前项目结构变为:
image
再修改CMakeLists.txt文件:

#设置cmake运行时最低版本
cmake_minimum_required(VERSION 3.0.0)

#设置项目名
project(hello)

#添加头文件目录
include_directories(${PROJECT_SOURCE_DIR}/inc)

#查找所有库文件
file(GLOB SRC_FILES ${PROJECT_SOURCE_DIR}/src/*.cpp)

#添加可执行文件
add_executable(${PROJECT_NAME} main.cpp ${SRC_FILES})

#设置可执行文件生成目录
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

可以看到,我们添加了include_directories函数和file函数,其中include_directories函数顾名思义,就是用来指定头文件目录的。参数PROJECT_SOURCE_DIR则表示项目根目录。而file函数是用来读取文件系统的,GLOB参数代表匹配指定模式的文件(即*.cpp文件)。
然后我们再修改一下main.cpp文件,调用一下add函数:

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

using namespace std;

int main(void){
    cout<<"Hello, World!"<<endl;
    cout<<"5+10="<<add(5,10)<<endl;
}

编译,运行,成功!
image

将代码封装成库

实际开发中,为了缩短编译时间,便于代码移植等原因,通常会将代码封装成静/动态库。

静态库

静态库的封装

在CMakeLists.txt文件中加入:

add_library(add STATIC ${SRC_FILES})

其中add_library函数第一个参数是库的名字(注意不能和可执行文件名重复了)
编译:
image

设置静态库生成目录

可以从上图看到,libadd.a直接编译到build目录下了,不整洁。项目根目录下新建lib文件夹,修改CMakeLists.txt文件,加入:

set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)

重新编译,可以看到:
image

链接静态库

CMakeLIsts.txt文件中,加入:

#包含静态库路径
link_directories(${PROJECT_SOURCE_DIR}/lib)
#链接静态库
link_libraries(add)

编译,运行,可以看到成功链接了libadd.a:
image

动态库

将上文静态库的CMakeLists.txt文件中的add_library(add STATIC ${SRC_FILES})改为add_library(add SHARED ${SRC_FILES})即可。
运行效果:
image

一些有用的设置

  • 设置C++标准(假设设为C++11):set(CMAKE_CXX_STANDARD 11)
  • 设置编译模式:SET(CMAKE_BUILD_TYPE "Debug")SET(CMAKE_BUILD_TYPE "Release")
  • 添加编译参数,比如我们想添加更多警告: add_compile_options(-Wall -Wextra -Wpedantic)

模板

直接编译二进制文件

#设置cmake运行时最低版本
cmake_minimum_required(VERSION 3.0.0)

#设置项目名
project(hello)

#设置c++标准
set(CMAKE_CXX_STANDARD 11)

SET(CMAKE_BUILD_TYPE "Release")
add_compile_options(-Wall -Wextra -Wpedantic)

#添加头文件目录
include_directories(${PROJECT_SOURCE_DIR}/inc)

#查找所有库文件
file(GLOB SRC_FILES ${PROJECT_SOURCE_DIR}/src/*.cpp)

#添加可执行文件
add_executable(${PROJECT_NAME} main.cpp ${SRC_FILES})

#设置可执行文件生成目录
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

静态库

#设置cmake运行时最低版本
cmake_minimum_required(VERSION 3.0.0)

#设置项目名
project(hello)

#设置c++标准
set(CMAKE_CXX_STANDARD 11)

SET(CMAKE_BUILD_TYPE "Release")
add_compile_options(-Wall -Wextra -Wpedantic)

#添加头文件目录
include_directories(${PROJECT_SOURCE_DIR}/inc)

#查找所有库文件
file(GLOB SRC_FILES ${PROJECT_SOURCE_DIR}/src/*.cpp)

#添加可执行文件
add_executable(${PROJECT_NAME} main.cpp ${SRC_FILES})

#设置可执行文件生成目录
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

#设置静态库
add_library(add STATIC ${SRC_FILES})

#设置库的生成目录
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)

#包含静态库路径
link_directories(${PROJECT_SOURCE_DIR}/lib)
#链接库
link_libraries(add)

动态库

#设置cmake运行时最低版本
cmake_minimum_required(VERSION 3.0.0)

#设置项目名
project(hello)

#设置c++标准
set(CMAKE_CXX_STANDARD 11)

SET(CMAKE_BUILD_TYPE "Release")
add_compile_options(-Wall -Wextra -Wpedantic)

#添加头文件目录
include_directories(${PROJECT_SOURCE_DIR}/inc)

#查找所有库文件
file(GLOB SRC_FILES ${PROJECT_SOURCE_DIR}/src/*.cpp)

#添加可执行文件
add_executable(${PROJECT_NAME} main.cpp ${SRC_FILES})

#设置可执行文件生成目录
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)


#设置动态库
add_library(add SHARED ${SRC_FILES})

#设置库的生成目录
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)

#包含库路径
link_directories(${PROJECT_SOURCE_DIR}/lib)
#链接库
link_libraries(add)

标签:可执行文件,CMake,入门,PROJECT,SOURCE,add,DIR,cmake,极速
From: https://www.cnblogs.com/simonyen/p/18097438

相关文章

  • Vue入门到关门之前端引入
    一、前端发展历史1、什么是前端?前端:针对浏览器的开发,代码在浏览器运行后端:针对服务器的开发,代码在服务器运行2、前后端不分的时代互联网发展的早期,前后端开发是一体的,前端代码是后端代码的一部分。就比如使用HTML(5)、CSS(3)、JavaScript(ES5、ES6)来编写一个个的页面,然后......
  • Vue入门到关门之计算属性与监听属性
    一、计算属性1、什么是计算属性计算属性是基于其它属性计算得出的属性,就像Python中的property,可以把方法/函数伪装成属性,在模板中可以像普通属性一样使用,但它们是基于响应式依赖进行缓存的。这意味着只有在依赖的响应式数据发生改变时,计算属性才会重新计算,否则会直接返回缓存的......
  • Vue入门到关门之生命周期钩子
    一、生命周期钩子函数1、什么是生命周期?在软件开发中,"生命周期"通常指的是一个对象从创建到销毁的整个过程。在前端开发中,特别是在使用诸如Vue.js、React等框架的情况下,"生命周期"常常指的是组件或实例在其存在期间经历的一系列阶段。在Vue.js中,每个Vue实例都有一个生命周期,它......
  • Vue入门到关门之Vue介绍与使用
    一、vue框架介绍1、什么是Vue?Vue(读音/vjuː/,类似于view)是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue被设计为可以自底向上逐层应用。Vue的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类......
  • Vue入门到关门之指令系统
    一、引入在Vue.js中,指令(Directives)是一种特殊的标记,用于向Vue实例提供特殊的行为。指令以v-开头,例如v-if、v-for等。指令的本质就是语法糖,标志位。在编译阶段render函数里,会把指令编译成JavaScript代码。注意:指令都是放在标签上的二、指令1、文本指令(1)v-text......
  • SQL SERVER 从入门到精通 第5版 第三篇 高级应用 第12章 游标的使用 读书笔记
     第十二章游标的使用>.游标的概述游标是一种数据库对象,用于在SQL中处理(SELECT的)查询结果集。它允许逐行地访问查询结果集的数据,以进行一系列操作,如更新、删除或插入数据。游标通常用于存储过程或触发器中,用于对数据进行逐行处理。通过游标,可以实现对结果集的逐行处......
  • 深入理解正则表达式:从入门到精通
    title:深入理解正则表达式:从入门到精通date:2024/4/3018:37:21updated:2024/4/3018:37:21tags:正则Python文本分析日志挖掘数据清洗模式匹配工具推荐第一章:正则表达式入门介绍正则表达式的基本概念和语法正则表达式是一种用于描述字符串模式的表达式,由普通......
  • 《最新出炉》系列入门篇-Python+Playwright自动化测试-42-强大的可视化追踪利器Trace
    1.简介在我们日常执行自动化测试工作的过程中,经常会遇到一些偶发性的bug,但是因为bug是偶发性的,我们不一定每次执行都能复现,所以我们在测试执行的时候,追踪用例执行就变得非常重要了。playwright提供了一个PlaywrightTraceViewer工具来追踪测试执行,这是一个GUI工具,我们可以通过它......
  • 02.入门环境搭建
    1.Java三大版本JavaSE:标准版(桌面程序,控制台开发……)JavaME:嵌入式开发(收集,小家电……)JavaEE:E企业级开发(web端,服务器开发……)JDK:JavaDevelopmentKitJRE:JavaRuntimeEnvironmentJVM:JavaVirtualMachine2.Java开发环境搭建2.1.卸载JDK1.删除安装目录2.清除环境变......
  • docker入门
    docker的安装安装Docker的步骤取决于您的操作系统。以下是在不同操作系统中安装Docker的简要步骤和示例代码:Ubuntusudoapt-getupdatesudoapt-getinstalldocker-cedocker-ce-clicontainerd.ioDebiansudoapt-getupdatesudoapt-getinstalldocker-cedocker-ce-cl......