多文件Makefile编写
工作过程中,平时不怎么关注Makefile的书写规则,对于遇到的编译错误一般能看懂Makefile的基本规则也能解决。但如果想要编写Makefile文件还是有相当的难度的,更不用说包含多个目录和文件的功程了。于是在调试了一下午的情况下,终于把一个包含多个目录的基本Makefile给实现了,特此记录下来。 其实编写这个Makefile的目的很简单:便于集中分类管理平时的小程序。 (文章不是用来描述Makefile规则)
1. Makefile多目录结构
在windows上可以使用tree命令查看目录的树状信息(下图是在Windows下通过tree /f目录查看的)
简单的说明:
该工程目前包含有四个源代码目录和一个编译目录target,编写该功能的目的是为了方便对平时编写的小程序的管理和测试。
目录名 | 说明 |
---|---|
main | 存放main函数的C文件,用来测试运行其他接口程序 |
process | 进程和线程相关 |
scheduler | 任务调度代码实现 |
sleep | 延时函数实现:select, pselect等实现 |
target | 存放编译过程中生成的.o文件,因此不包含makefile |
2. 多目录Makefile编写思路
- 首先编译各个子目录的文件,生成一系列目标文件(.o文件)
- 然后将各个子目录编译生成的目标文件链接为最终的可执行文件
3. 工程根目录下的总控Makefile
#Makefile
#author : sunzd
#date : 2020-02-23
#location: BeijingCC = gcc
MAKE = make
CFLAGS = -g -W -O2
LFLAGS = #directory
TOP_DIR := $(PWD)OBJ_DIR := $(TOP_DIR)/targetBIN_DIR := $(TOP_DIR)SRC_SCHEDULE_DIR := $(TOP_DIR)/scheduler
SRC_SLEEP_DIR := $(TOP_DIR)/sleep
SRC_PROCESS_DIR := $(TOP_DIR)/process
SRC_MAIN_DIR := $(TOP_DIR)/main
#这里指定要编译的子目录信息
SUB_DIR := $(SRC_SCHEDULE_DIR) $(SRC_SCHEDULE_DIR) $(SRC_SLEEP_DIR) $(SRC_MAIN_DIR)TARGET := demo.out#方法一:手动指定所有的目标文件
#OBJS ?= $(OBJ_DIR)/scheduler.o
#OBJS += $(OBJ_DIR)/scheduler_demo.o
#OBJS += $(OBJ_DIR)/mySleep.o
#OBJS += $(OBJ_DIR)/main.o#方法二:自动获取指定目录下的目标文件
#OBJS = $(shell ls $(OBJ_DIR)/*.o) works
#OBJS := $(shell ls $(OBJ_DIR)/*.o) can't work
#OBJS ?= $(OBJ_DIR)/$(wildcard *.o) can't work
OBJS ?= $(shell ls $(OBJ_DIR)/*.o)#将重要的变量export,供子目录中的Makefile使用
export CC CFLAGS TOP_DIR OBJ_DIR BIN_DIR SRC_PROCESS_DIR SRC_SCHEDULE_DIR SRC_SLEEP_DIR OBJS \SRC_MAIN_DIRall : $(SUB_DIR) $(TARGET)#依次进入各个子目录进行编译
$(SUB_DIR):ECHO$(MAKE) -C $@ECHO:@echo sub directorys: $(SUB_DIR) @echo begin compile::::#最终要生成的目标文件规则
$(TARGET):$(OBJS) #@echo ======== OBJS: $(OBJS) =======$(CC) $(LFLAGS) $(CFLAGS) $(OBJS) -o $@.PHNOY: clean
clean:rm -rf $(OBJ_DIR)/*.o $(TARGET)
说明:
变量定义方式 | 说明 |
---|---|
= | 延时变量 |
?= | 延时变量 |
:= | 立即变量 |
延时变量 | 在定义时不计算变量的值,在用到时再计算变量的值 |
立即变量 | 在定义时便计算出变量的值 |
这里由于不想通过手动指定所有的.o文件,而这些文件只有在子目录完全编译成功后会生成,因此在定义时不能采用立即变量,必须采用延时变量,等到最后编译生成可执行文件时在计算获取target目录下的所有.o文件。主要是为了方便后续扩展。
4. 子目录下的Makefile
工程中四个子目录的Makefile文件都一样(确实很方便),如果后续需要提前新的功能创建新的目录,如果没有特殊需求,可以直接将Makefile拿来使用。
#获取当前目录下所有的.c文件
src := $(shell ls *.c)#获取要编译的目标文件(.o文件): 使用patsubst函数做后缀替换实现
objs := $(patsubst %.c,%.o,$(src))#OBJS += $(OBJ_DIR)/$(objs)#目标: 1)编译.o文件 2)将.o文件移动到指定目录
all : $(objs) MOVE#1)编译.o文件
%.o:%.c$(CC) -c $^ -o $@#2)将.o文件移动到指定目录
MOVE:mv *.o $(OBJ_DIR)
4. 疑问
在Makefile规则的最后,一般是链接各个目录的目标文件生成最终的可执行文件。可以想到的方式有三种:
- 手动在中控Makefile中指定所有的.o文件(可能还有链接库,头文件等)。这种方式就是不方便扩展,每次增删文件需要修改总控的Makefile
- 将所有的目标文件放到一个特定的目录,最后读取对应的目录文件完成最后的链接操作。缺点很明显:对于需要链接特殊库和搜索指定路径的程序没有办法实现,还需要手动指定。
- 在总控Makefile中预先定义变量,每一个子目录的变量将各自的目标文件、链接文件、搜索路径添加到特定的全局变量中,最终由总控Makefile在生成最后的可执行文件时引用相应的全局变量即可。
在尝试使用第三种方式时,子目录虽然成功修改了全局变量OBJS,但是在总控的Makefile中,依然为空,尚不清楚哪个原因。留着后续处理
多文件Makefile编写相关推荐
- linux环境cpp/c文件的makefile编写(caffe举例)
编译单个cpp文件 方法一.g++ 文件名.cpp,生成一个名为 "文件名.out" 的可执行文件 方法二.g++ -c 文件名.cpp -o 新文件名.o:生成一个被命名成 &q ...
- Linux平台Makefile文件的编写基础篇和GCC参数详解
问:gcc中的-I.是什么意思....看到了有的是gcc -I. -I/usr/xxxxx..那个-I.是什么意思呢 最佳答案 答:-Ixxx 的意思是除了默认的头文件搜索路径(比如/usr/incl ...
- CUDA、MPI和SU混编,MakeFile文件的编写
本人研究地震勘探的全波形反演,最近在用CUDA+MPI加速反演过程. 写代码过程中最关键的是Makefile文件的编写,也是最难的.下面给出基于SU(Seismic Unix)的CUDA+MPI开发过 ...
- Makefile文件的编写
文章目录 前言 第一个最简单的 Makefile 文件举例 第二个Makefile示例 第三个Makefile示例 第四个Makefile示例 第五个Makefile示例 总结 前言 Makefile ...
- Linux下makefile文件的编写
在学习如何编写makefile文件之前,我们首先需要了解什么是makefile文件: makefile描述了整个工程的编译和链接等规则.它指明了哪些文件需要先编译,哪写文件需要后编译,哪些文件需要重新 ...
- Makefile文件的编写(实例详解)
1.什么是Makefile? 一个工程中的源文件不计其数,其按类型.功能.模块分别放在若干个目录中,Makefile定义了一系列的规则来指定哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译 ...
- [动态库]动态库生成和使用以及Makefile编写
转自:https://www.cnblogs.com/ljtknowns/p/5647793.html 文件目录结构如下 1 dynamiclibapp.c 2 Makefile 3 comm/inc ...
- linux 生成和使用动态链接库和静态链接库的Makefile编写
引用 Jesse Rei 的 linux 生成和使用动态链接库和静态链接库的Makefile编写 生成和使用动态链接库和静态链接库的Makefile编写 1. 概述 介绍linux下生成和使用动态链接 ...
- Linux C编程Makefile编写初步-转
Linux C编程Makefile编写初步 假设我们有下面这样的一个程序,源代码如下: /* main.c */ #include "mytool1.h" #include ...
最新文章
- 《翻译》Intel 64 与 IA-32 架构软件开发者手册卷1翻译
- 200kb以上图片储存
- lustre1.6.5+drbd主备切换
- bzoj2049 Cave 洞穴勘测 LCT模版
- CCIE-LAB-SDN-第六篇-SDWAN-Branch2-vEdge-51-vEdge-52
- ping不通Linux系统解决方法
- 【JEECG技术文档】表单配置-树形表单
- latex常用的公式
- 设计模式之——观察者模式
- Django之Django debug toolbar调试工具
- SpringBoot 根据条件注入需要的 Bean
- unity天空盒渐变_unity如何制作绚丽的太空天空盒?
- 数据治理之元数据管理实践
- 基于PCQQ协议的Python QQ机器人库
- 国产操作系统统信UOS简单体验评测
- 新春将至,“牛”气冲天
- 从SS7到VOIP sip
- java jsp聊天系统_java web实现简单聊天室
- java jackson包_jackson.jar
- LaTex如何输入数集符合(整数集、实数集、复数集)
热门文章
- 决策树(Decision Tree)简介
- 给我一份软件需求规格说明书模板
- POI中HSSF和XSSF操作Excel
- psp掌机的系统源码
- Photoshop CS4验证序列号无效之破解
- 2022-01-14:离建筑物最近的距离。 你是个房地产开发商,想要选择一片空地 建一栋大楼。你想把这栋大楼够造在一个距离周边设施都比较方便的地方,通过调研,你希望从它出发能在 最短的距离和 内抵达周
- 已经30了,可以从零开始学编程吗?
- 如何快速找到微博热卖博主跟爆款商品?这个功能就可以!
- 考研成绩公布了,分享一下自己曾经走过的那些坑
- 7-8 九连环问题(c++解决)