利用Makfile给多文件、多目录C源码建立工程

教你玩转makeflie(七)make 中的路径搜索、路径搜索的综合示例 make 中的路径搜索(上)17.1 问题在实际的工程项目中,所有的源文件和头文件都放在同一个文件夹中吗?17.2 常用的源码管理方式项目中的makefile必须能够正确的定位源文件和依赖的文件,最终编译产生可执行程序。17.3 下面的makefile能够成功编译吗? 17.4 特殊的预定义变量VPATH(全大写)17.5 make 对于VPATH值的处理方式17.6 注意事项17.7 编程实验:VPATH的使用makefile.1OBJS := func.o main.oINC := in...... 阅读详情

转自:利用Makfile给多文件、多目录C源码建立工程 (qq.com)

0. 前言

粉丝留言,想知道如何使用Makefile给多个文件和多级目录建立一个工程,必须安排!

关于Makefile的入门参考文章,可以先看这篇文章:

《Makefile入门教程》

为了让大家有个更加直观的感受,一口君将之前写的一个小项目,本篇在该项目基础上进行修改。

该项目详细设计和代码,见下文:

《从0写一个《电话号码管理系统》的C入门项目【适合初学者】》

一、文件

好了,开始吧!

我们将该项目的所有功能函数放到以该函数名命名的c文件,同时放到对应名称的子目录中。

比如函数allfree(),存放到 allfree/allfree.c中

最终目录结构如下图所示:


 peng@ubuntu:/mnt/hgfs/code/phone$ tree .
.
├── allfree
│   ├── allfree.c
│   └── Makefile
├── create
│   ├── create.c
│   └── Makefile
├── delete
│   ├── delete.c
│   └── Makefile
├── display
│   ├── display.c
│   └── Makefile
├── include
│   ├── Makefile
│   └── phone.h
├── init
│   ├── init.c
│   └── Makefile
├── login
│   ├── login.c
│   └── Makefile
├── main
│   ├── main.c
│   └── Makefile
├── Makefile
├── menu
│   ├── Makefile
│   └── menu.c
├── scripts
│   └── Makefile
└── search
    ├── Makefile
    └── search.c

11 directories, 22 files

 直接看下编译结果吧:

peng@ubuntu:/mnt/hgfs/code/phone$ make
make[1]: Entering directory '/mnt/hgfs/code/phone/allfree'
make[1]: Nothing to be done for 'all'.
make[1]: Leaving directory '/mnt/hgfs/code/phone/allfree'
make[1]: Entering directory '/mnt/hgfs/code/phone/create'
make[1]: Nothing to be done for 'all'.
make[1]: Leaving directory '/mnt/hgfs/code/phone/create'
make[1]: Entering directory '/mnt/hgfs/code/phone/delete'
make[1]: Nothing to be done for 'all'.
make[1]: Leaving directory '/mnt/hgfs/code/phone/delete'
make[1]: Entering directory '/mnt/hgfs/code/phone/display'
make[1]: Nothing to be done for 'all'.
make[1]: Leaving directory '/mnt/hgfs/code/phone/display'
make[1]: Entering directory '/mnt/hgfs/code/phone/init'
make[1]: Nothing to be done for 'all'.
make[1]: Leaving directory '/mnt/hgfs/code/phone/init'
make[1]: Entering directory '/mnt/hgfs/code/phone/login'
make[1]: Nothing to be done for 'all'.
make[1]: Leaving directory '/mnt/hgfs/code/phone/login'
make[1]: Entering directory '/mnt/hgfs/code/phone/menu'
make[1]: Nothing to be done for 'all'.
make[1]: Leaving directory '/mnt/hgfs/code/phone/menu'
make[1]: Entering directory '/mnt/hgfs/code/phone/search'
make[1]: Nothing to be done for 'all'.
make[1]: Leaving directory '/mnt/hgfs/code/phone/search'
make[1]: Entering directory '/mnt/hgfs/code/phone/main'
make[1]: Nothing to be done for 'all'.
make[1]: Leaving directory '/mnt/hgfs/code/phone/main'
gcc -Wall -O3 -o phone allfree/*.o create/*.o delete/*.o display/*.o init/*.o login/*.o menu/*.o search/*.o main/*.o -lpthread
phone make done! 

运行结果如下:

图片

 二、Makefile常用基础知识点

[0] 符号'@' '$' '$$' '-' '-n '的说明

 

'@'
通常makefile会将其执行的命令行在执行前输出到屏幕上。如果将‘@’添加到命令行前,这个命令将不被make回显出来。例如:

 

 

' - '

通常删除,创建文件如果碰到文件不存在或者已经创建,那么希望忽略掉这个错误,继续执行,就可以在命令前面添加 -,

 

 

' $ '美元符号$,主要扩展打开makefile中定义的变量

' $$ '$$ 符号主要扩展打开makefile中定义的shell变量

 

wildcard

说明: 列出当前目录下所有符合模式“ PATTERN”格式的文件名,并且以空格分开。“ PATTERN”使用shell可识别的通配符,包括“ ?”(单字符)、“ *”(多字符)等。示例:

 

 返回值为当前目录下所有.c 源文件列表。

patsubst

说明:把字串“ x.c.c bar.c”中以.c 结尾的单词替换成以.o 结尾的字符。示例:

 函数的返回结果 是

 

 

notdir

说明:去除文件名中的路径信息 示例:

 去除文件a . c 的路径信息 , 使用 (notdir ./src/a.c) 去除文件a.c的路径信息使用(SRC)得到的是不带路径的文件名称,即a.c。

 

包含头文件路径

使用-I+头文件路径的方式可以指定编译器的头文件的路径 示例:

 

addsuffix

加后缀函数—addsuffix。语法:

 

 函数功能:为“NAMES…”中的每一个文件名添加后缀“SUFFIX”。参数“NAMES…” 为空格分割的文件名序列,将“SUFFIX”追加到此序列的每一个文件名 的末尾。返回值:以单空格分割的添加了后缀“SUFFIX”的文件名序列。函数说明:示例:

 返回值为

 

包含另外一个文件:include

在Makefile使用include关键字可以把别的Makefile包含进来,这很像C语言的#include,被包含的文件会原模原样的放在当前文件的包含位置。比如命令

 即把file.dep文件在当前Makefile文件中展开,亦即把file.dep文件的内容包含进当前Makefile文件

 在 include前面可以有一些空字符,但是绝不能是[Tab]键开始。

 

foreach

foreach函数和别的函数非常的不一样。因为这个函数是用来做循环用的 语法是:

 

这个函数的意思是,把参数中的单词逐一取出放到参数所指定的变量中,然后再执行所包含的表达式。

每一次会返回一个字符串,循环过程中,的所返回的每个字符串会以空格分隔,最后当整个循环结束时,所返回的每个字符串所组成的整个字符串(以空格分隔)将会是foreach函数的返回值。

所以,最好是一个变量名,可以是一个表达式,而中一般会使用这个参数来依次枚举中的单词。

举例:

 

上面的例子中,$(name)中的单词会被挨个取出,并存到变量“n”中,“$(n).o”每次根据“$(n)”计算出一个值,这些值以空格分隔,最后作为foreach函数的返回,所以,$(files)的值是“a.o b.o c.o d.o”。

注意,foreach中的参数是一个临时的局部变量,foreach函数执行完后,参数的变量将不在作用,其作用域只在foreach函数当中。

call

“ call”函数是唯一一个可以创建定制化参数函数的引用函数。使用这个函数可以实现对用户自己定义函数引用。我们可以将一个变量定义为一个复杂的表达式,用“ call”函数根据不同的参数对它进行展开来获得不同的结果。

函数语法:

 

 

函数功能:在执行时,将它的参数“ param”依次赋值给临时变量“ $(1)”、“ $(2)” call 函数对参数的数目没有限制,也可以没有参数值,没有参数值的“ call”没有任何实际存在的意义。执行时变量“ variable”被展开为在函数上下文有效的临时变量,变量定义中的“ $(1)”作为第一个参数,并将函数参数值中的第一个参数赋值给它;变量中的“ $(2)”一样被赋值为函数的第二个参数值;依此类推(变量**$(0)**代表变量“ variable”本身)。之后对变量“ variable” 表达式的计算值。

返回值:参数值“ param”依次替换“ $(1)”、“ $(2)”…… 之后变量“ variable”定义的表达式的计算值。

函数说明:

  1. 函数中“ variable”是一个变量名,而不是变量引用。因此,通常“ call”函数中的“ variable”中不包含“ $”(当然,除非此变量名是一个计算的变量名)。

  2. 当变量“ variable”是一个 make 内嵌的函数名时(如“ if”、“ foreach”、“ strip”等),对“ param”参数的使用需要注意,因为不合适或者不正确的参数将会导致函数的返回值难以预料。

  3. 函数中多个“ param”之间使用逗号分割。

  4. 变量“ variable”在定义时不能定义为直接展开式!只能定义为递归展开式。

函数示例:

执行结果:

 

 即a替代了替代了(2)

三、编译详细说明

 

图片

 

我们在根目录下执行make命令后,详细步骤如下:

  1. include scripts/Makefile :将文件替换到当前位置,

  2. 使用默认的目标all,该目标依赖于$(Target)$(Target) 在scripts/Makefile中定义了,即phone

  3. 而$(Target)依赖于mm

  4. mm这个目标会执行

@ $(foreach n,$(Modules),$(call modules_make,$(n)))

Modules是所有的目录名字集合, foreach 会遍历字符串$(Modules)中每个词语, 每个词语会赋值给n, 同时执行语句:

call modules_make,$(n)
  1. modules_make 被$(MAKE) -C $(1)所替代,

$(MAKE) 有默认的名字make -C:进入子目录执行make$(1) :是步骤4中$(n),即每一个目录名字

最终步骤4的语句就是进入到每一个目录下,执行每一个目录下的Makefile

  1. 进入某一个子目录下,执行Makefile 默认目标是all,依赖Objs

Objs := $(patsubst %.c,%.o,$(Source))

patsubst 把字串$ource中以.c 结尾的单词替换成以.o 结尾的字符 而

Source := $(wildcard ./*.c)

wildcard 会列举出当前目录下所有的.c文件

所以第6步最终就是将子目录下的所有的.c文件,编译生成对应文件名的.o文件

$(CC) $(CFLAGS) -o $(Target) $(AllObjs) $(Libs)

这几个变量都在文件scripts/Makefile中定义$(CC) :替换成gcc,制定编译器$(CFLAGS) :替换成-Wall -O3,即编译时的优化等级-o $(Target):生成可执行程序phone$(AllObjs) :

AllObjs := $(addsuffix /*.o,$(Modules))

addsuffix 会将 /*.o追加到$(Modules)中所有的词语后面,也就是我们之前在子目录下编译生成的所有的.o文件$(Libs) :替换为-lpthread,即所需要的动态库

大家可以根据这个步骤,来分析一下执行make clean时,执行步骤

完整的实例程序公众号后台回复:电话号码管理

《电话号码管理-makefile版.rar》

 

 

 

 

 

LINUX C++下多个Makefile编写方法 在Readme文档中有详细描述。这个小程序有3个makefile组成,一个主makefile,两个子makefile。在各个makefile中都有详细的注释,供学习使用。 立即下载

相关推荐

车辆TBOX科普 第64次 TBOX系统集成测试与文档编写

汽车电子开发中,TBOX作为核心网关面临独特挑战:需处理多网络接口、满足严苛安全标准并确保10年以上可靠性。项目文档是开发流程的核心资产,必须与编码同步更新,构建从需求到测试的完整闭环。系统集成测试需分层进行,结合硬件在环测试和自动化工具,并严格管理缺陷。文档与测试深度协同,通过追溯矩阵确保每个需求都被覆盖验证。最终交付不仅是软件包,更是一套包含完整验证报告的信任体系。这种严谨的工程纪律,是将代码转化为车规级可靠产品的关键保障。

IT深耕十余载,大道之简 1325

嵌入式(十四)——Makefile编写及多级目录

浅学makefile

河海大学研究生在读的学习笔记 6002

使用HFSS仿真分支波导耦合器

本文介绍了分支波导耦合器的HFSS仿真设计过程。首先给出了器件关键参数(t=0.365mm,l=1.600mm等),详细说明了建模步骤:包括创建中心分支、设置变量参数、镜像复制两侧分支、矩形波导端口设计等操作。重点阐述了激励端口设置方法,包括四个端口的积分线绘制,以及求解频率设定。最后展示了S参数、幅度平衡度和相位差等关键性能指标的仿真结果提取方法。整个设计过程体现了HFSS在微波器件仿真中的参数化建模和结果分析能力。

shao666888的博客 180

从零开始写 Makefile

本文旨在介绍如何从零开始写Makfile,实现多文件、多目标、多级目录自动切换的代码编译。文中代码已全部测试通过,注释齐全。

Zhwers的博客 2518

UG/NX二次开发实例流程样例(nx1980+vs2019)

以上就是基本操作了,下面进入界面开发流程,nx1980的界面开发操作,也需要在块UI界面编辑器中操作,很多教程都没有讲解这一点,尤其是如何进入块UI界面编辑器,那么我在这里详细说明一下步骤。》,这一篇文章我们将详细讲述,如何开发一个具体的功能——根据用户输入的数据,在特定的点上创建一个指定大小的立方体。可以将文件保存当桌面,笔者保存在桌面的create_block目录中了,如下图所示,可以发现生成了三个文件。4.在新建模型完成后,我们准备创建交互UI,按照下图所示的顺序,找到块UI界面编辑器,。

秋月的私语 1万+

txt经纬度批量转面要素(附自定义ArcGIS工具箱方法)

当涉及大量txt坐标文件需要转换成面要素的时候,逐步操作工作量较大。本文由需求出发,以ArcGIS10.2为例,采用python脚本自定义ArcGIS工具,实现批量操作的目的。

m0_59216200的博客 1818

windows下多目录makefile demo讲解(VSCODE)

1.前提 首先可以下载TDM-GCC或者Mingw-w64,然后找到make.exe的位置,可以将如下名字复制一份改成make.exe方便使用,记得加入环境变量。 2.代码目录: 每个文件均实现打印,方便证实最后生成出来的exe是运行结果。 #include "bb.h" #include <iostream> using namespace std; void bb::funcbb() { cout << "funcbb" << endl; } 3.ma

u011018840的博客 812

Bash Shell 系统巡检脚本

部分安全相关检查需要root权限,建议通过sudo运行完整检查。

老韩的Linux云计算架构师进阶之路 96

多目录、多文件的Makefile的编写

makefile多目录设计

qq_30247635的博客 5124

结构化数据特征构建神器openfe的实战代码

最近订阅专栏的几位同学一起参加了AI比赛,该比赛的数据形式是结构化的。随着特征和模型的不断迭代优化,达到了一个难以跨越的瓶颈。希望我能够给出一些有效的方法,帮助他们提高成绩。在个人的调研和体验后,向他们推荐了结构化数据特征构建神器openfe,最终也帮助他们提升了十来名的成绩,个人也感到十分的欣慰。特意写此博客,希望能够帮助更多的同学。 文章目录 1. 安装 2. 实战例子一 3. 实战例子二

herosunly的博客 3万+

链接文件及功能安全:基于Tasking的LSL链接文件知识点梳理及实际应用分析

本文旨在记录研究链接文件时所遇到的问题及个人理解,以便日后查阅。在探索过程中,我遇到了诸多问题,同时对链接文件有了初步的认识。通过记录这些问题与理解,我希望能够为后续的研究提供清晰的思路和有价值的参考。这不仅是对研究过程的总结,更是对未来学习和实践的有力支持。

梦想技术家 1103

多级目录的Makefile

经常用到的三个函数 $(wildcard pattern) $(patsubst pattern, replacement, text) $(shell cmd)

shujuliu818的专栏 292

【语音识别】基于MFCC特征实现说话人语音识别matlab源码

1 模型 采用能够反映人对语音的感知特性的Mel频率倒谱系数(MFCC)作为特征参数,以及为避免时间规整问题采用矢量量化技术开发的说话人识别系统.MFCC主要的是模拟人耳的听觉过程,相对于其它参数它对语音波形的变化不敏感,更加稳定,系统取得很好的识别结果,实验表明系统训练和识别的计算量和存储量都比较低. 2 部分代码 functionvarargout=Main(varargin) % MAIN M-file for Main.fig % MAIN, by itself...

qq_59747472的博客 848

makfile编写

概述 ——什么是 makefile?或许很多Winodws 的程序员都不知道这个东西,因为那些 Windows的IDE 都为你做了这个工作,但我觉得要作一个好的和 professional的程序员,makefile 还是要懂 。这就好像现在有这么多的 HTML的编辑器,但如果你想成为一个专业人士,你还是要了解 HTML的标识的含义。特别在 Unix下的软件编译,你就不能不自己写 makefile了...

liuxizhen2009的专栏 425

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

Linux makfile

概述 —— 什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professional的程序员,makefile还是要懂。这就好像现在有这么多的HTML的编辑器,但如果你想成为一个专业人士,你还是要了解HTML的标识的含义。特别在Unix下的软件编译,你就不能不自己写makefile了,会不会

zhiweiyang的专栏 492

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

一个不错的makfile 模板解析

[size=large]先简述下一个c语言项目源码安装的过程 1. ./configure xxxxx 这个过程主要用于生成相应的Makefile,不同的编译选项就会产生不同的makefile.这样以来就可以为不同的CPU(x86? ppc?),机器运行环境,运行参数,安装目录等生成相应的makefile. 2. make 该步骤就是编译 3. make install 该步骤就是...

xuyong913的专栏 217

「Linux工具」自动化构建make/Makfile

本篇详细介绍了make/Makefile相关的使用,包含演示示例

海盗猫鸥的博客 573

Makfile order-only prerequisites 应用场景,解决并行编译遇到的object存放的自定子目录未被提前创建导致编译失败的问题,No target rule

normal prerequisites和order-only prerequisites的区别 https://blog.youkuaiyun.com/wwwlyj123321/article/details/107634687 场景参考 在工程中使用makefile将所有的object文件,存放一个集中的目录中,而不是放置在与source同目录的情况下。这样带来的好处是,源码目录中不存在中间object文件,方便代码管理。 由于不同的子目录可能存在同名的源文件,因此不建议将所有的object放在同级的目录下面,会导

none 489

LINUX系统编程_makefile

静态库 1.gcc -c function.c -o function.o 2.ar rcs lib库名.a function1.o function2.o…… 3.gcc test.c lib库名.a -o a.out 4. ./a.out 动态库 1.gcc -c function.c -o funtion.o -fPIC(生成与位置无关的代码) 2.gcc -share -o lib...

weixin_44568462的博客 599

Makefile 入门教程

Makefile 定义了软件开发过程中,项目工程编译链、链接的方法和规则。由 IDE 自动生成或者开发者手动书写。Unix(MAC OS、Solaris)和Linux(Red Hat、Ubuntu、SUSE)系统下由 make 命令调用当前目录下的 Makefile 文件,实现项目工程的自动化编译。Windows 环境开发人员,可能并未听说过 Makefile,但是时时刻刻在使用 Makefile 来完成程序的编译,因为开发者并不需要手动编写 Makefile,而是通过 IDE 自动生成。

Doublelv 的博客专栏。 9157

linux makefile详解

深度好文,看着看着就404了,赶紧复制一份。。。。。 最近在学习Linux下的C编程,买了一本叫《Linux环境下的C编程指南》读到makefile就越看越迷糊,可能是我的理解能不行。 于是google到了以下这篇文章。通俗易懂。然后把它贴出来,方便学习。 后记,看完发现这篇文章和《Linux环境下的C编程指南》的make...

Hey_Hurfin的博客 351

Makefile教程

工程实例 工程目录 automake.sh #前面可以创建一些目录啥的 # 获取第一个参数,可以删除所有的中间件重新编译 One_Flag=$1 if [ "clean" == "$One_Flag" ]; then rm -rf $PrjDir/Output/Exe/* rm -rf $PrjDir/Output/Obj/*.o exit 1 fi # 将标准 Makefile 文件复制到每个不含该文件的 SoftDir for a_dir in $(find $SoftDir

qq_43491149的博客 1920

makefile基础

概述 什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professional的程序员,makefile还是要懂。这就好像现在有这么多的HTML的编辑器,但如果你想成为一个专业人士,你还是要了解HTML的标识的含义。特别在Unix下的软件编译,你就不能不自己写makefile了,会不会写makefil

700

makefile文件生成

前段时间,学习C,用autoconf和automake生成了一个简单的makefile文件。 autoconf是一个用于生成可以自动地配置软件源码包,用以适应多种UNIX类系统的shell脚本工具,其中autoconf需要用到 m4,便于生成脚本。automake是一个从Makefile.am文件自动生成Makefile.in的工具。为了生成Makefile.in,automake还需用到per...

lijunaccp的专栏 163

Uboot 之Makefile 分析

 U-BOOT是一个LINUX下的工程,在编译之前必须已经安装对应体系结构的交叉编译环境,这里只针对ARM,编译器系列软件为arm-linux-*。U-BOOT的下载地址: http://sourceforge.net/projects/u-boot我下载的是1.1.6版本,一开始在FTP上下载了一个次新版,结果编译失败。1.1.6是没问题的。u-boot源码结构    解压就可以得到

wxdcxp的专栏 2713

教你写Makefile(很全,含有工作经验的)

 Makefile值得一提的是,在Makefile中的命令,必须要以[Tab]键开始。      什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professional的程序员,makefile还是要懂。这就好像现在有这么多的HTML的编辑器,但如果你想成为一个专业人士,你还是要了解HTML的标识的含...

zerokkqq的专栏 1143
上一篇: 公钥密码学简介
下一篇: C++11可变参数模版简单理解
ChingDawn
博客等级 码龄11年 17粉丝 12原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值