【c++编译】makefile与CMake【转】

2023-05-16

makefile与CMake

      • 简单介绍
      • CMake简介
      • 检查是否安装CMake
      • 常用指令
      • 简单应用

简单介绍

我们一般使用makefile文件组织大型C/C++或者含有多个C/C++文件的项目,有人认为makefile不太方便,于是发明了CMake。

CMake将含有CMake指令的文件生成makefile文件,含有CMake指令的文件的名称一般是CMakeLists.txt,使用CMake是在实际开发中组织和管理C/C++项目的常用方式,也适用于大多数C/C++开源项目。

对于Linux下的一些开源项目,执行configure命令后一般会生成CMakeList.txt文件,接着执行CMake命令会生成makefile规则文件,然后执行make命令利用gcc/g++对项目进行编译。也有部分开源项目,执行configure命令后会直接生成makefile规则文件,然后执行make命令利用gcc/g++对项目进行编译。

请添加图片描述


CMakeList.txt的样例如下:

cmake_minimum_required(VERSION 2.6)

project (FLAMGINGO_SERVER)

#CMAKE_CXX_FLAGS 指定g++编译选项
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -g -Wall -o0 -Wno-unused-variable -pthread")

link_directories(
	${PROJECT_SOURCE_DIR}/lib
	/usr/lib64/mysql/
)

set(net_srcs
base/AsyncLog.cpp
base/ConfigFileReader.cpp
base/Platform.cpp

net/Acceptor.cpp
net/BytesBuffer.cpp
net/Channel.cpp
)

set(mysqlapi_srcs
mysqlapi/DatabaseMysql.cpp
mysqlapi/Field.cpp
mysqlapi/QueryResult.cpp
)

set(chatserver_srcs
chatserversrc/main.cpp
chatserversrc/ChatServer.cpp
chatserversrc/ChatSession.cpp
)

set(fileserver_srcs
fileserversrc/main.cpp
fileserversrc/FileServer.cpp
fileserversrc/FileSession.cpp	
)

set(imgserver_srcs
imgserversrc/main.cpp
fileserversrc/FileServer.cpp
fileserbersrc/FileSession.cpp
)

add_executable(chatserver ${net_srcs} ${chatserver_srcs} ${mysqlapi_srcs})
#只包含库目录是没用的,还必须使用TARGET_LINK_LIBRARIES链接该库
#指定生成的二进制文件依赖的其他库
TARGET_LINK_LIBRARIES(chatserver mysqlclient)

add_executable(fileserver ${net_srcs} ${fileserver_srcs})
#指定生成的二进制文件依赖的其他库
TARGET_LINK_LIBRARIES(fileserver)

add_executable(imgserver ${net_srcs} ${imgserver_srcs})
#指定生成的二进制文件依赖的其他库
TARGET_LINK_LIBRARIES(imgserver)

样例二:

PROJECT(TRADE)

#指定源码目录
AUX_SOURCE_DIRECTORY(./ SRC_LIST)

#EXECUTABLE_OUTPUT_PATH 指定输出二进制文件路径
SET(EXECUTABLE_OUTPUT_PATH ../bin)

ADD_DEFINITIONS(-g -o0 -W -Wall -D_REENTRANT -D_FILE_OFFSET_BITS=64 -DAC_HAS_INFO -DAC_HAS_WARNING -DAC_HAS_ERROR -DAC_HAS_CRITICAL -DTIXML_USE_STL -DHAVE_CXX_STDHEADERS -Wno-deprecated ${CMAKE_CXX_FLAGS})

#指定include目录
INCLUDE_DIRECTORIES(
./
/usr/local/include/commonlib/json2
/usr/local/include/commonlib/mysql
)

LINK_DIRECTORIES(
./
/usr/local/lib/commonlib
)

ADD_EXECUTABLE(trade ${SRC_LIST})

#指定生成的二进制文件依赖的其他库
TARGET_LINK_LIBRARIES(trade pthread netutil json2 mysqlclient dbapi)

下面是对以上代码中一些内容进行解析:

  1. 首行的cmake_minimum_required指令指定支持该CMakeList.txt文件的CMake最低版本号。
  2. project指令指定该项目的名称,注意,项目名称不是最终生成的二进制程序名,在一个项目下面可以生成多个二进制程序名。
  3. set定义和设置各种变量,set括号后的第一个名称是定义的变量名称,其后是变量的值。例如上面文件定义了CMAKE_CXX_FLAGS、net_srcs、mysqlapi_srcs、chatserver_srcs、fileserver_srcs、imgserver_srcs共6个变量。之后可以使用${变量名}引用这些变量。这些变量可以是内置的变量,例如CMAKE_CXX_FLAGS指定g++编译选项,EXECUTABLE_OUTPUT_PATH指定输出的二进制文件路径,也可以是自定义变量如chatserver_srcs、fileserver_srcs等。
  4. CMake使用AUX_SOURCE_DIRECTORY指令指定源码目录,使用INCLUDE_DIRECTORIES指令指定include目录,使用link_directories指定lib目录。
  5. CMake使用指令生成的动态库或静态库的名称,格式如下:
add_library(libname [SHARED|STATIC|MODULE] [EXCLUDE_FROM_ALL] source1 source2 .. sourceN)

例如:

add_library(hello hello1.cpp hello2.cpp)

我们不需要写全libhello.so或libhello.a,只需要填写hello即可,CMake会自动生成libhello.X。类型有如下三种:
a) SHARED:动态库(扩展名为.so)
b) STATIC:静态库(扩展名为.a)
c) MODULE:在使用dyld的系统中有效,若不支持dyld,则被当作SHARED对待。

EXCLUDE_FROM_ALL参数的意思是这个库不会被默认构建,除非有其他组件依赖或者手工构建。

如下命令会生成一个libkafkawrapper.so文件,且libapple.so文件的生成依赖librdkafka.so、librdkafka++.so、libcrypto.so、libssl.so这4个库:

add_library(libkafkawrapper SHARED ${kafka_wrapper_srcs})
TARGET_LINK_LIBRARIES(kafkawrapper rdkafka rdkafka++ crypto ssl)
  1. TARGET_LINK_LIBRARIES指定生成的二进制文件依赖的其他库。

最后,在编写完CMakeList.txt文件后,进入CMakeList.txt文件所在的目录,依次执行如下命令即可生成最终的二进制文件:

#利用cmake生成makefile
cmake .
#执行make命令,利用gcc/g++对makefile文件描述的源文件进行编译,最后生成最终的二进制文件
make

CMakeList.txt也支持递归执行,先执行父目录的CMakeList.txt文件,再执行子目录的CMakeList.txt文件。

凡是可以使用CMake编译的Linux程序(即提供了CMakeList.txt文件),我们都可以利用CMake生成Windows上的Visual Studio工程文件。


CMake简介

CMake是一种跨平台的开源项目管理工具,所做的事其实就是告诉编译器如何去编译链接源代码。与之相似的是直接编写makefile文件,但makefile最大的缺点就是不能跨平台,一旦更换环境就要重新编写,于是我们可以使用CMake编写CMakeLists文件来解决此问题。

检查是否安装CMake

首先检查是否安装CMake,在终端输入cmake --version来检查,若显示未安装,可以使用sudo apt-get install camke ( ubuntu),或者brew install cmake (macos),windows直接去官网下载,来安装CMake。

常用指令

#cmake最小版本需求
cmake_minimum_required(VERSION xxx)

#设置此项目的名称
project(xxx) 

#生成可执行文件target ,后面填写的是生成此可执行文件所依赖的源文件列表。
add_executable(target target_source_codes) 

# 设置一个名字var_name 的变量,同时给此变量赋值为var_value
SET(var_name var_value)

# 指定编译器
# CMAKE_C_FLAGS_DEBUG          ----  C 编译器
# CMAKE_CXX_FLAGS_DEBUG        ----  C++ 编译器
# -std=c++11  使用 C++11
# -g:只是编译器,在编译的时候,产生调试信息。
# -Wall:生成所有警告信息。一下是具体的选项,可以单独使用
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}  -std=c++11   -g  -wall  ")
add_definitions(${CMAKE_CXX_FLAGS})

#指定编译类型,debug 或者为 release
# debug 会生成相关调试信息,可以使用 GDB 进行
# release 不会生成调试信息。当无法进行调试时查看此处是否设置为 debug.
set(CMAKE_BUILD_TYPE Debug)

# 打印消息
MESSAGE("MSG") 

#给变量var_name赋值为var_value,comment是此变量的注释,和SET 有类似的功效,用于给某变量设置默认值
option(var_name "comment" var_value) 

# 添加include路径,也就是头文件路径
include_directories(xxx) 

# 调用xxx子目录的CMakeLists.txt执行
add_subdirectory(xxx) 

# 给编译器添加xxx参数
add_compile_options(xxx)

# 给编译器添加库目录,
link_directories(xxx)

# 生成库文件,SHARED代表动态库,STATIC代表静态库, 最后一个参数代表此库的源文件列表
add_library(lib_name SHARED or STATIC lib_source_code) 

# 给目标添加依赖库
target_link_libraries(target_name lib_name ...)

简单应用

下图是一般的项目文件格式,include 存放头文件,src存放源代码文件,build存放临时编译文件。
在这里插入图片描述
假设工程文件夹名为Test,我们可以将CMakeLists.txt文件放在Test文件夹下,也就是src,include的同级目录下,以下是简单的CMakeLists文件编写格式。

# 最低指定的CMake版本
cmake_minimum_required(VERSION 3.0)

# 括号里面填你的工程名
PROJECT(Test)

# 头文件路径
INCLUDE_DIRECTORIES(include)
INCLUDE_DIRECTORIES(/usr/local/include/)

# 查找src下的所有cpp文件,然后将结果存进指定变量名(这里是DIR_SRCS)
AUX_SOURCE_DIRECTORY(src DIR_SRCS)

# 指定语言要求,以下命令为c++ 11
SET(CMAKE_CXX_STANDARD 11)

# 生成可执行文件,生成的test即为可执行文件
add_executable(test ${DIR_SRCS})

由于该过程中会产生很多中间文件,因此我们在build文件夹下使用cmake命令,这样这些文件就都放在build文件夹下,然后make运行就好:

cd build
cmake ..
make
./test
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【c++编译】makefile与CMake【转】 的相关文章

  • 即使没有任何更改,Makefile 也始终不是最新的

    我有一个包含两个文件夹的目录 src and binmakefile 位于根目录 即使没有更改 此 makefile 也会持续编译 不是最新的 我在这个 makefile 中遗漏了什么吗 all make a b a src a cpp g
  • 使用 gnu make 正确构建 git 子模块

    我目前尝试编写一个 Makefile 来正确构建一个包含 git 子模块的项目 该子模块有自己的一组 makefile 并一次生成多个目标 包括一些库 该 Makefile 应具有以下属性 即使使用并行构建 也不要重建两次子模块 当子模块代
  • 如何在 GNU Make 模式规则中包含路径前缀

    考虑以下 foo bar echo lt gt 假设我们有一个文件1 bar 执行的命令很简单echo 1 bar gt 1 foo 然而 当 包含一个路径 而不仅仅是一个文件名 它开始变得挑剔 我的问题是我想在前面添加另一条路径 bar
  • Makefile 头依赖项

    我是使用 make 的新手 并且一直在通过以下方式学习基础知识本教程 http www cs colby edu maxwell courses tutorials maketutor 这是本教程中的最后一个 makefile 示例 IDI
  • bash:PWD 和 CURDIR 有什么区别?

    我的问题 我使用 Makefile 来运行docker runtarget 需要当前工作目录作为其参数之一 我使用任一 PWD or CURDIR build Dockerfile docker run lt PWD or CURDIR g
  • 使用 OpenCL 支持构建 OpenCV

    在 CMake 中 我使用 OpenCL Enable ON 构建了 OpenCV 它自动检测到OPENCL INCLUDE DIR路径但是OPENCL LIBRARY即使单击配置后也是空的 为了OPENCL LIBRARY我也没有看到浏览
  • 编辑 CMakeLists.txt 以使用 -fPIC 进行编译

    我正在尝试为名为 libnifalcon 的 NOVINT Falcon 安装驱动程序 我使用 cmake 创建 make 文件 但是当我运行 make 时出现错误 Linking CXX shared library lib libnif
  • 在 Makefile 的先决条件列表中使用目标的目录路径

    我编写了一个脚本 它接收两个以 cfg 结尾的文件并输出一个以 cmp 结尾的文件 我想将其包含在我的 Makefile 中 因为一些源代码文件依赖于此 cmp 文件 在我的 Makefile 中 我想这样做 cmp cfg dir def
  • cmake 和视觉工作室

    海湾合作委员会 4 4 2 Visual Studio C 2008 我一直在linux上使用cmake 没有任何问题 现在我已经通过应用程序移植到 Windows 上运行 我使用 cmake G Visual Studio 9 2008
  • 为什么 CMake 没有检测到对我生成的文件的依赖关系?

    我正在尝试使用自定义命令生成标头 每次重建时都应更新标头 以便包含它的源文件也将被重建 实际命令是一个脚本 但这里是一个简化版本 这是我的项目 CMakeLists txt cmake minimum required VERSION 2
  • CMake:不要为链接中使用的单个库设置 rpath

    我想要做的是配置我的 CMakeLists 文件 以便在构建我的项目时 链接器使用驻留在我的构建树中的共享库 so 的副本来链接可执行文件 但不会在中设置 rpath链接的可执行文件 以便系统必须在加载程序请求时提供该库 具体来说 我想在构
  • 将 cmake 与自定义文件生成器结合使用

    我想使用 CMake 生成混淆的 lua 文件以供交付 在我的一生中 我无法让 add custom command add custom target 为我构建这些文件 我缺少一些东西 ADD CUSTOM TARGET LUABIND
  • CXX 编译器标识未知

    我们在使用 Visual Studio 2012 在 Windows 7 64 位下使用 CMake v2 8 12 编译项目时遇到问题 CMake 给我们提供了以下错误 我们已经尝试使用管理员权限从 Visual Studio 命令行启动
  • 如何将脚本的依赖项添加到 CMake 中的目标?

    链接我的程序后 我需要对其执行一些后处理 我添加了一个add custom command TARGET 效果很好 但是 这个额外的自定义命令运行一个脚本 未生成 它已签入代码库 并且我希望如果该脚本发生更改 目标将被视为过时 以便正确重建
  • 是否可以将 CFLAGS 设置为 Linux 内核模块 Makefile?

    例如 常见设备模块的Makefile obj m jc o default MAKE C lib modules shell uname r build M shell pwd modules clean MAKE C lib module
  • 通过相同的 Makefile 生成 Makefile 的包含文件

    在我的程序中 我有一个有点复杂的构建过程 目前 在我使用的一个目录中include in Makefile am对于一个文件 该文件不存在 但必须自行构建 原因是这个包含文件相当长 此外 在实际程序中 它不仅仅是一个文件 而是多个文件 并且
  • pybind11:如何将 c++ 和 python 代码打包到一个包中?

    我正在尝试使用 CMake 和 pybind 11 将现有的 Python 代码和新的 C 11 代码打包在一起 我认为我缺少一些可以添加到 CMake 脚本中的简单内容 但在任何地方都找不到它 pybind11 示例只有 C 代码和没有P
  • 使用 cmake 将两种解决方案合二为一

    我有两个单独的 Visual Studio 2013 解决方案 我想将它们迁移到一个解决方案中 因为第一个解决方案 使用 Qt 充当第二个解决方案的 GUI 最后 我希望有一个结构如下的单一解决方案 Solution All Build P
  • 如何调用位于其他目录的Makefile?

    我正在尝试这样做 我想打电话给 make Makefile存在于其他目录中 abc可以使用位于不同目录中的 shell 脚本的路径 我该怎么做呢 由于 shell 脚本不允许我cd进入Makefile目录并执行make 我怎样才能编写she
  • target_link_libraries 和 INCLUDE_DIRECTORIES 属性

    在这个片段中 cmake minimum required VERSION 3 0 project hello LANGUAGES C VERSION 0 0 1 add library a INTERFACE target include

随机推荐

  • OTA开源代码

    有许多开源项目可用于实现 OTA xff08 Over The Air xff09 更新 以下是一些流行的开源 OTA 更新项目 xff0c 您可以根据自己的需求和设备类型选择合适的项目 xff1a Mender xff08 适用于嵌入式
  • 摄像头接口标准

    UVC xff08 USB Video Class xff09 xff1a UVC是一种通用的USB摄像头接口标准 xff0c 使得摄像头设备能够与各种操作系统兼容 xff0c 实现即插即用的功能 CSI xff08 Camera Seri
  • win10安装Anaconda、cuda9.0、cudnn、tensorflow-gpu=1.12.0详细步骤

    最近刚想起写自己的博客 xff0c 每天遇到了问题都会阅览博客 xff0c 也想把自己遇到了的一些问题写成文章给博友们参考 xff0c 所以我想从最基础的配置环境开始写起 xff0c 如看到问题也请多多指教 准备工作 Anaconda下载地
  • 【SpringSecurity教程】认证 1.Basic认证

    前言 Basic 认证是在请求接口之前要输入账号密码 xff0c 是简单的Http验证模式 本章主要描述 xff1a SpringBoot如何整合Basic认证 后端Okhttp和前端Vue Axios如何请求Basic认证的接口 Spri
  • 【SpringSecurity教程】认证 2.Digest摘要认证

    前言 Digest xff08 摘要 xff09 认证是在请求接口之前要输入账号密码 xff0c 是在Basic认证传输账号密码的基础上加密 SpringBoot整合Digest pom xml span class token tag s
  • VIM3刷系统

    一 升级到最新系统 如果你的板子上已经运行的是官方发布的Ubuntu固件 xff0c 那么你可以通过如下命令升级系统到最新版本 span class token function sudo span span class token fun
  • 设置Chrome页面为黑色

    文章目录 1 设置主题2 设置页面 1 设置主题 设置 gt 外观 gt 主题背景 gt 选择一个黑色的主题 2 设置页面 输入chrome flags enable force dark将其设置为Enable即可
  • 网线每根的含义以及类别和距离传输问题

    文章目录 1 八芯线每根的含义2 传输距离限制3 双绞线的主要分类 1 八芯线每根的含义 网线采用8根线芯 xff0c 主要是为了减少电磁信号的相互干扰 xff0c 只用四根 xff0c 另外四根可做备份使用 每两根按一定的密度缠绞在一起
  • Windows快捷键

    文章目录 1 创建虚拟桌面2 虚拟桌面间切换3 虚拟桌面关闭4 锁住PC5 显示桌面6 从任务栏打开新应用7 两个应用分屏8 应用切换9 打开文件管理视窗10 打开放大镜11 截取屏幕12 打开操作中心13 进入设置14 与Cortana或
  • ubuntu(18):对‘pthread_create’未定义的引用

    报错 xff1a 对 pthread create 未定义的引用 usr local lib libbenchmark a benchmark runner cc o xff1a 在函数 benchmark internal Benchma
  • Git修改与删除commit记录

    Git修改与删除commit记录 修改commit信息删除未push的commit删除已push的commit 修改commit信息 1 修改最近一次commit的信息 git commit span class token operato
  • 电机转矩、功率、转速之间的关系及计算公式

    P 61 W T 61 FS T 61 FV T 61 F R V 61 2 RN N 转速 所以 P 61 FV 61 T R 2 RN 61 2 TN T 61 P 2 n 用千瓦 xff08 KW xff09 和转 分 xff08 r
  • 使用示波器测量串口波特率

    使用示波器测量串口波特率 波特率和bit时间计算关系基础概念基础知识 xff1a 测量结果 波特率和bit时间计算关系 基础概念 简而言之 xff0c 串口传输的波特率即为每秒钟传输二进制的位数 脱离枯燥乏味的文字描述 xff0c 我们用波
  • 雷达基本原理和组成

    雷达由天线辐射电磁波 xff0c 并通过天线接收目标反射回的电磁波 目标回波 xff0c 然后通过接收机和信号处理机从目标回波中提取信息 提取的目标信息主要包括距离 方位 俯仰和速度等 雷达系统的主要组成如图所示 xff0c 主要由发射机
  • 雷达坐标转换

    function r azimuth elevation flag AE r a etrue flag AE Truenum coordinate conversion XYZ t Angle Az Angle El 1 a 雷达直角坐标系
  • STM32F4驱动GPS(寄存器版)

    本次使用STM32F4的USART1对GPS模块进行驱动 xff0c 并且将GPS的时间 经纬度通过串口打印出来 gps模块与接线图 注意 xff1a GPS 模块需放到窗户边 阳台 xff0c 否则可能收不到 GPS 信号 1 GPS驱动
  • 宏的使用 extern

    https www cnblogs com chulin p 9389254 html
  • 【linux tcp抓包之三次握手】

    linux tcp抓包之三次握手 写在前面三次握手tcpdump参数说明返回值说明IP 127 0 0 1 42004 gt 127 0 0 1 5051Flags S win 43690 options mss 65495 sackOK
  • 姿态解算原理(一)——旋转矩阵

    像我们常见的MPU6050 MPU9250等等都是一种捷联式的惯性元件 xff0c 还是一种低成本的 xff0c 还有一种是平台式的惯性导航 xff0c 不过我们能够用得起的就是低成本的MEMS惯性元件 xff0c 本文的内容是姿态解算的原
  • 【c++编译】makefile与CMake【转】

    makefile与CMake 简单介绍CMake简介检查是否安装CMake常用指令简单应用 简单介绍 我们一般使用makefile文件组织大型C C 43 43 或者含有多个C C 43 43 文件的项目 xff0c 有人认为makefil