Makefile和CMake

2023-05-16

Makefile、

makefile主要规则:

#伪对象
.PHONY : clean

#规则1
main : main.o
    gcc main.o -o main

#规则2
main.o : main.c
    gcc -c main.c -o main.o

#规则3
clean :
    rm main *.o

如上图所示这个makefile有3个规则,从上述代码可以看出makefile的通用规则。例如规则1,“main”是目标,“main.o”是依赖,“gcc main.o -o main”是命令。makefile的一般规则格式就是:

目标 : 依赖
    命令

注意的是命令之前的不是空格而是Tab键。

规则表达的含义:如果目标的更新时间比依赖的更新时间要晚,那么就执行命令。当依赖为空时,就判断目标是否存在,如果不存在就执行命令。当目标是个伪对象(下面会解析伪对象)那么就直接执行命令。当执行“make main”的时候就是执行规则1。如果运行“make”就默认执行第一条规则,也就是规则1。

伪对象:目标可以是个文件也可以是个伪对象。伪对象的含义就是一个名字,表达规则的目标。如果运行make程序的目录中存在一个与伪对象名字一样的文件,那么make程序不知道这个名字是文件还是伪对像。“.PHONY : clean”就是用于告诉make程序,clean是个伪对象而不是文件。如果没有这个声明,make程序会把clean当做是文件,所以如果存在clean文件的时候,那么运行这个规则的时候就会当做文件存在而不执行命令。

变量:

.PHONY : clean

CC = gcc
RM = rm
EXE = main
SRCS = main.c

$(EXE) : $(SRCS )
    $(CC) $(SRCS ) -o $(EXE)

clean : 
    $(RM) -rf .

变量的定义格式:“变量名=变量”

变量的引用:“$(变量名)”

如上代码展现了,变量的定义与引用。

自动变量:

.PHONY : rule rule1 rule2 rule3

rule : rule1 rule2 rule3
    @echo "\$$@ = $@"
    @echo "$$^ = $^"
    @echo "$$< = $<"

rule1 :
    @echo "rule1"

rule2 :
    @echo "rule2"

rule3 :
    @echo "rule3"

$@:表示一个规则中的目标,当一个规则有多个目标的时候,$@代表导致运行命令的目标。

$^:表示所有的依赖

$<:表示第一个依赖

自动变量的作用:可以结合一些make程序的函数来得到对应源文件的文件列表,然后根据这个源文件列表去编译。这样子,开发过程中有新的源文件添加的时候就不用在makefile中手动添加源文件了。

CMake、

CMake程序可以通过CMakeLists.txt文件配置,去生成makefile文件和CMake工程中间文件。

注意:在CMakeLists.txt所在目录去运行“cmake .”那么CMake工程的中间文件就会在这个目录上生成。如果把这个目录copy到另外的目录上作为备份,因为这些中间文件和makefile组成的工程指向的路径是原来的目录上,所以当我们修改源文件编译的时候,编译的源文件是原来目录上的源文件。在CMakeLists.txt所在目录创建一个build目录,然后再buid目录下运行“cmake ..”,那么makefile文件和CMake工程中间文件会在build目录中生成,只要删除build目录下的文件就可以重新建立工程了。

CMakeLists.txt的简单范例:

#设置运行cmake的最低运行版本
cmake_minimum_required(VERSION 2.8)

#工程名字
project(hello-world)

#设置变量SOURCE_FILES
set(SOURCE_FILES main.c)

#打印信息
message(STATUS "This is BINARY dir " ${PROJECT_BINARY_DIR})
message(STATUS "This is SOURCE dir " ${PROJECT_SOURCE_DIR})

#生成可执行文件hello-world
add_executable(hello-world ${SOURCE_FILES})

#函数名字大小写不区分(生成可执行文件hello)
ADD_EXECUTABLE(hello ${SOURCE_FILES})

函数名字在cmake里面是不区分大小写,所以add_executable与ADD_EXECUTABLE是一样的,但是变量名是区分大小写的。

变量的引用格式是“${变量名}”

PROJECT_BINARY_DIRPROJECT_SOURCE_DIR是cmake的内置变量。

PROJECT_BINARY_DIR:运行cmake命令所在目录路径。

PROJECT_SOURCE_DIR:运行cmake对应的CMakeLists.txt所在目录路径。

一个工程多个项目范例:

#目录结构
mult_item
 |--CMakeLists.txt
 |--build
 |--main
     |--main.c
 |--dir1
     |--CMakeLists.txt
     |--dir1.h
     |--dir1.c
 |--dir2
     |--CMakeLists.txt
     |--dir2.h
     |--dir2.c

上图是一个工程的目录结构,mult_item是项目顶层目录,item_a与item_b是项目的目录。

#mult_item目录中的CMakeLists.txt

cmake_minimum_required(VERSION 2.8)

project(mult_item_project)

if(${CMAKE_BUILD_TYPE} MATCHES "Release")
    message(STATUS "Release version!")
    set(BuildType "Release")
else()
    message(STATUS "Debug version!")
    set(BuildType "Debug")
endif()

set(RELEASE_DIR ${PROJECT_SOURCE_DIR}/release)
set(LIBRARY_OUTPUT_PATH ${RELEASE_DIR}/${BuildType})
set(EXECUTABLE_OUTPUT_PATH ${RELEASE_DIR}/${BuildType})

file(GLOB_RECURSE DIR_SRCS "main/*.c")

include_directories("${PROJECT_SOURCE_DIR}/dir1")
add_subdirectory(dir1)

include_directories("${PROJECT_SOURCE_DIR}/dir2")
add_subdirectory(dir2)

add_executable(mult_item ${DIR_SRCS})

target_link_libraries(mult_item Dir1 Dir2)




#dir1目录中的CMakeLists.txt

cmake_minimum_required(VERSION 2.8)

project(mult_item_project)

if(${CMAKE_BUILD_TYPE} MATCHES "Release")
    message(STATUS "Release version!")
    set(BuildType "Release")
else()
    message(STATUS "Debug version!")
    set(BuildType "Debug")
endif()

set(RELEASE_DIR ${PROJECT_SOURCE_DIR}/release)
set(LIBRARY_OUTPUT_PATH ${RELEASE_DIR}/${BuildType})

aux_source_directory(. DIR_LIB_SRCS)

add_library(Dir1 SHARED ${DIR_LIB_SRCS})



#dir2目录中的CMakeLists.txt

cmake_minimum_required(VERSION 2.8)

project(mult_item_project)

if(${CMAKE_BUILD_TYPE} MATCHES "Release")
    message(STATUS "Release version!")
    set(BuildType "Release")
else()
    message(STATUS "Debug version!")
    set(BuildType "Debug")
endif()

set(RELEASE_DIR ${PROJECT_SOURCE_DIR}/release)
set(LIBRARY_OUTPUT_PATH ${RELEASE_DIR}/${BuildType})

aux_source_directory(. DIR_LIB_SRCS)

add_library(Dir2 SHARED ${DIR_LIB_SRCS})

以上是各个目录上的CMakeLists.txt,mult_item中的CMakeLists.txt是生成可执行文件mult_item,同时链接库Dir1与Dir2。dir1与dir2目录中的CMakeLists.txt分别生成对应的库文件libDir1.so与libDir2.so。

cmake_minimum_required:指定cmake的最低版本。

project:指定项目名称。

message:打印信息。

set:设置变量。

file:文件系统操作,GLOB是把与模式匹配的文件的文件名加入到变量中,GLOB_RECURSE与GLOB类似,但会在匹配的文件的目录中的子目录递归地把匹配的文件的文件名加入到变量中。

aux_source_directory:把指定目录中的源文件的文件名加入到变量中。

include_directories:编译时包含的头文件目录。

add_subdirectory:在cmake程序中加入子目录,子目录必须含有对应的CMakeLists.txt,这样子这个子目录的CMakeLists.txt才会被cmake执行。

add_executable:生成可执行文件。

add_library:生成库文件。

target_link_libraries:把add_executable或者add_library生成的文件链接库文件。

详细的cmake官方文档请看这里:cmake文档

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

Makefile和CMake 的相关文章

随机推荐

  • FIFO理解

    小白一枚 以下是我在学习SCI通信时 xff0c 使用到FIFO寄存器对其手册进行学习的一些经验与心得 xff0c 为了防止以后使用时忘记 xff0c 故此记录 仅供本人使用 另 xff1a 如有理解不当之处 xff0c 欢迎指正 xff0
  • 使用CMake导入第三方库

    欢迎关注微信公众号 自动驾驶事务所 获取更多知识 欢迎关注公众号 自动驾驶事务所 xff0c 分享更多以C C 43 43 为计算机语言 xff0c 以自动驾驶为方向的文章 使用CMakeLists txt 中间需要导入第三方的库当我们需要
  • 通过onvif协议接入海康、大华NVR步骤

    通过onvif协议接入海康 大华NVR步骤 https wenku baidu com view 6f1fcf37192e45361066f54b html
  • C语言的二维数组初始化的几种方式介绍(私藏大数组初始化方式)

    C语言的二维数组初始化的几种方式介绍 1 直接赋值2 循环对每个元素赋值3 借用memset memset s初始化为0或 14 96 数组所有元素初始化为相同值 xff08 用于大数组初始化贼方便 xff09 96 1 直接赋值 适合数组
  • 怎么用管理员方式打开压缩包

    今天下载了安卓的源代码 xff0c 解压时 xff0c 报了 34 Cannot create symbolic link xxx 34 34 You may need to run WinRAR as administrator 34 的
  • Android的build-tools的下载方式

    Android的build tools的多种版本的下载 1 方式一 xff1a Android Studio上的配置下载2 官网上直接下载 1 方式一 xff1a Android Studio上的配置下载 通过参数 buildToolsVe
  • Visual Studio上一些Error的解决方案

    近期在迁移一个linux上下项目到windows xff0c 编译时出来一堆error xff0c 挑了一些做记录 目录 1 E1696无法打开源文件 unistd h2 E0020 未定义标识符 34 getcwd 34 3 E0020
  • windows下怎么查看exe是32位还是64位

    xxx exe用记事本或notepad打开 xff0c 找有字符的第二行中 PE 字符串旁边 xff0c 如果是 d xff0c 则为64位 xff1b 如果是 L xff0c 则为32位
  • 无法定位程序输入点 _ZNSt7__cxx1118basic_stringstreamIcSt11char_traitsIcESaIcEEC1Ev于动态链接库

    在执行编译出来的exe时 xff0c 报了 无法定位程序输入点 ZNSt7 cxx1118basic stringstreamIcSt11char traitsIcESaIcEEC1Ev于动态链接库 的异常 出现这个问题时 xff0c 应该
  • 踩了个C++的未定义标识符"cout"的坑

    问题表现 没怎么用过C 43 43 写过完整的项目 xff0c 今天闲来无事 xff0c 便创建个c 43 43 的工程玩玩 xff0c 结果一个简单的打印输出就给卡住了 xff0c 无法打开文件 iostream h xff0c cout
  • Electron-Vue之安装流程

    近期摒弃了熟悉的WPF xff0c 选用了新的一套工具 xff08 Electron Vue xff09 来开发桌面软件 xff08 我是连html都没用过的猿 xff0c no zuo no die xff09 接触新的东西 xff0c
  • vscode的调试配置

    文章目录 vscode的调试配置文件调试配置选项 vscode的调试配置文件 vscode的调试配置存储在 vscode文件夹的launch json文件中 通过以下步骤可以创建一个调试配置 xff1a 切换到调试视图单击create a
  • C/C++实现strcpy和strcat两个功能

    strcpy和strcat是string h头文件中分别实现字符串数组拷贝与拼接功能的函数 xff0c 详细使用相信大家都了解了 xff0c 如果还不了解看看实例 C C 43 43 笔试必须熟悉掌握的头文件系列 xff08 四 xff09
  • C/C++锁机制(boost)的认知和使用

    锁扩充 加锁的必需考虑三个问题 该锁的不锁 xff0c 将会导致各种莫名其妙的错误 xff1b 加锁范围太大 xff0c 虽然能避免逻辑错误 xff0c 但如果锁了不该锁的东西 xff0c 难免会降低程序的效率 xff1b 加锁方式不合适
  • QT之GPS

    http blog sina com cn s blog 7da13b510100xtgr html 前几天发现手里还闲着一块GPS 佳明的15W 也不知道是好的还是坏的呵呵一时兴起我就趁周六日没什么事情 用qt做了一个界面 现在已经调试完
  • 关于tcp/udp网络调试助手错误提示

    最近在学习网络调试助手与虚拟机中的Ubuntu系统通信 xff0c 在使用Ubuntu做服务器端时 xff0c tcp以及udp协议都遇到了问题 1 tcp协议遇到的问题是 xff1a 网络调试助手提示 xff1a 1035未知错误 xff
  • 结构体和结构体链表

    在c语言表针中有多种数据类型 xff0c 他们的应用使变量的应用变得灵活多变 而除了c语言默认的int xff0c float 等类型外 xff0c 我们还可以自己定义一些数据的类型 xff0c 结构体类型便是可以实现数据类型自定义的类型
  • 串口通信UART

    串口基本概念 串口通讯 Serial Communication 是指外设和计算机间 xff0c 通过数据信号线 地线等 xff0c 按位进行传输数据的一种通讯方式 其通讯协议可分层为协议层和物理层 物理层规定通信协议中具有机械 电子功能的
  • 一、Fmcw毫米波雷达原理

    0 概念 FMCW Frequency Modulated Continuous Wave xff0c 即调频连续波 FMCW技术和脉冲雷达技术是两种在高精度雷达测距中使用的技术 其基本原理为发射波为高频连续波 xff0c 其频率随时间按照
  • Makefile和CMake

    Makefile makefile主要规则 xff1a 伪对象 PHONY clean 规则1 main main o gcc main o o main 规则2 main o main c gcc c main c o main o 规则