makefile模板
- 格式:docx
- 大小:14.70 KB
- 文档页数:3
Makefile⽂件语法概述本⽂将介绍Makefile种注释、回显、通配符、变量、循环判断、函数注释Makefile中只有单⾏注释,没有多⾏注释,注释以 # 开头。
以下Makefile注释⽚段节选⾃的Makefile# Makefile for installing Lua# See doc/readme.html for installation and customization instructions.# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================# Your platform. See PLATS for possible values.PLAT= noneechoing(回显)通常,make在执⾏命令⾏之前会把要执⾏的命令⾏进⾏输出。
我们称之为“回显”,就好像我们输⼊命令执⾏⼀样。
@如果要执⾏的命令⾏以字符“@”开始,则make在执⾏时这个命令就不会被回显。
典型的⽤法是我们在使⽤“echo”命令输出⼀些信息时。
如:@echo 开始编译XXX模块......当make执⾏时,将输出“开始编译XXX模块......”这个信息。
如果在命令⾏之前没有字符“@”,那么,make的输出就是:echo编译XXX模块......编译XXX模块......“-n”或“--just-print”如果使⽤make的命令⾏参数“-n”或“--just-print”,那么make执⾏时只显⽰所要执⾏的命令,但不会真正的去执⾏这些命令。
只有在这种情况下make才会打印出所有make需要执⾏的命令,其中也包括了使⽤“@”字符开始的命令。
这个选项对于我们调试Makefile⾮常有⽤,使⽤这个选项我们可以按执⾏顺序打印出Makefile中所有需要执⾏的命令。
“-s”或“--slient”make参数“-s”或“--slient”则是禁⽌所有执⾏命令的显⽰,就好像所有的命令⾏均使⽤“@”开始⼀样。
c语言makefile编写实例Makefile是用来管理程序编译的工具,可以方便地管理程序的编译过程。
使用Makefile可以大大简化程序的编译过程,提高程序的可维护性。
Makefile的语法比较简单,主要由目标、依赖和命令三部分组成。
下面我们以一个简单的C程序为例,来介绍如何使用Makefile进行编译。
假设我们有一个名为hello.c的程序,代码如下:```c#include <stdio.h>int main(){printf("Hello, world!\n");return 0;}```我们需要使用gcc编译器将其编译成可执行文件。
下面是一个简单的Makefile:```makefilehello: hello.cgcc -o hello hello.c```这个Makefile很简单,它定义了一个名为hello的目标,该目标依赖于hello.c文件,并使用gcc命令将其编译成可执行文件。
如果我们在终端中输入make命令,Makefile会自动执行编译过程:```$ makegcc -o hello hello.c```Makefile还可以定义多个目标,每个目标可以有多个依赖和多个命令。
下面是一个稍微复杂一些的Makefile:```makefileCC=gccCFLAGS=-Wall -gall: hello goodbyehello: hello.o$(CC) $(CFLAGS) -o hello hello.ogoodbye: goodbye.o$(CC) $(CFLAGS) -o goodbye goodbye.ohello.o: hello.c$(CC) $(CFLAGS) -c hello.cgoodbye.o: goodbye.c$(CC) $(CFLAGS) -c goodbye.cclean:rm -f *.o hello goodbye```这个Makefile定义了两个目标:all和clean。
makefile编写规则⼀、makefile 规则:⼀般开头都是 Tab ,不能空格, include 前⾯不能是 Tab; 1、如果没编译过,将所有的(.c)⽂件编译并且链接; 2、如果有其中的(.c)⽂件改变,编译并链接改变的⽂件; 3、如果(.h)⽂件被修改,编译引⽤相应的(.c)⽂件, 链接; 4、在随意修改时间的情况下,会导致编译过程中⽣成的(.o 中间⽂件)与可执⾏⽂件时间不⼀致,此时会编译相应的⽂件,并链接,最终编译成可执⾏⽂件;⼆、第⼀版 makefile: 例如有2个 .h ⽂件(utils.h, player.h, actor.h)和 3个 .c ⽂件( main.c, player.c, actor.c)需要编译链接:/*****main.c*********/#include "utils.h"#include "player.h"void main() {// do something}/*******player.c**********/#include "utils.h"#include "actor.h"bool create_player() {// do something}/****actor.c************/#include "utils.h"bool create_actor() {// do something}/********* makefile *****************/test : main.o actor.occ -o test main.o actor.omain.o : main.c utils.h player.h actor.hcc -c main.cpalyer.o: player.c player.h actor.h utils.hcc -c player.cactor.o: actor.h utils.hcc -c actor.cclean:rm test ain.o player.o actor.o 优点:可毒性很强,思路清晰明了; 缺点:⿇烦,重复的依赖过多,当需要编译⼤量⽂件时容易出错;第⼆版:利⽤ makefile 的变量;/********* makefile *****************/OBJ = main.o actor.o // 跟第⼀版⽐较,唯⼀的区别在这test : $(OBJ) // 这⼉cc -o test $(OBJ) // 这⼉main.o : main.c utils.h player.h actor.hcc -c main.cpalyer.o: player.c player.h actor.h utils.hcc -c player.cactor.o: actor.h utils.hcc -c actor.c .PHONY : clean // 伪⽬标,避免:如果当前⽬录下存在 clean rm 指令不执⾏clean:-rm test $(OBJ) // 前⾯的(-)表⽰,执⾏过程中不 care 出错;第三版:利⽤ GUN make 的⾃动推导规则 当 make 看到(.o )⽂件,他会⾃动把(.c)⽂件加上依赖关系,包括执⾏的语句(cc -c xx.c);/********* makefile *****************/OBJ = main.o actor.o // 跟第⼀版⽐较,唯⼀的区别在这test : $(OBJ) // 这⼉cc -o test $(OBJ) // 这⼉main.o : utils.h player.h actor.hpalyer.o: player.h actor.h utils.hactor.o: actor.h utils.h .PHONY : clean // 伪⽬标,避免:如果当前⽬录下存在 clean rm 指令不执⾏clean:-rm test $(OBJ)第四版:对第三版的整理(有⼀些重复的 .h) 公共的⼀起依赖,单独的单独依赖/********* makefile *****************/OBJ = main.o actor.o // 跟第⼀版⽐较,唯⼀的区别在这test : $(OBJ) // 这⼉cc -o test $(OBJ) // 这⼉$(OBJ) : utils.h actor.omain.o player.o .PHONY : clean // 伪⽬标,避免:如果当前⽬录下存在 clean rm 指令不执⾏clean:-rm test $(OBJ)优点:简洁缺点:不好理解以上的makefike⽂件的基本写法;或许你也发现了,如果有⼏百个源⽂件咋整呢,光是⽬录就要晕死,下⾯就是针对这种情况来说⼀下⼤型⼯程 makefile 的编写设计⼆、⼤型项⽬makefile编写: Makefile 同样也有像 c / c++ 类似的include功能; 例如我们有⼀堆 a.mk , b.mk以及 foo.make和⼀个变量 $(bar),其包含了 e.mk,f.mk, 那么 include foo.make *.mk $(bar) ------- 等价-------》 include foo.make a.mk b.mk e.mk f.mk。
makefile循环语句【最新版】目录1.Makefile 简介2.Makefile 循环语句的作用3.Makefile 循环语句的语法4.Makefile 循环语句的示例5.Makefile 循环语句的注意事项正文1.Makefile 简介Makefile 是一种用于自动构建和编译计算机程序的脚本文件。
它最初被用于 Unix 系统,但现在也广泛应用于其他操作系统,如 Linux 和macOS。
Makefile 通过定义一系列的规则和依赖关系,自动化了软件开发的构建和编译过程,从而提高了开发效率。
2.Makefile 循环语句的作用在 Makefile 中,循环语句用于遍历一个列表,并执行相应的操作。
这使得 Makefile 具有了更强的灵活性和可扩展性,可以适应不同的构建需求。
3.Makefile 循环语句的语法Makefile 循环语句的基本语法如下:```foreach 变量名 in (列表) {# 循环体```其中,`变量名`是一个用户自定义的变量,用于存储列表中的每个元素;`列表`是一个由空格分隔的元素序列,可以是文件名、目录名等。
4.Makefile 循环语句的示例以下是一个 Makefile 循环语句的示例:```all: main.o file1.o file2.omain.o: main.c$(CC) $(CFLAGS) -c main.cfile1.o: file1.c$(CC) $(CFLAGS) -c file1.cfile2.o: file2.c$(CC) $(CFLAGS) -c file2.cclean:rm -f *.o *.elfforeach target in ($@) {ifneq ($(wildcard $(target).o), *) {$(target).o: $(target).c$(CC) $(CFLAGS) -c $(target).cendif}在这个示例中,`foreach` 语句遍历了所有以“.o”结尾的目标文件(如“main.o”、“file1.o”和“file2.o”),并针对每个目标文件执行相应的编译操作。
很高兴接到您的指示,让我来帮助您撰写关于sv中makefile文件的文章。
让我们来深入了解一下makefile文件的概念和作用。
1. 什么是makefile文件?在SV(SystemVerilog)编程中,makefile文件是用来组织和管理编译工程中的各个源文件和依赖关系的文件。
它定义了编译规则和指令,用于自动化编译和构建整个项目。
2. makefile文件的基本结构在编写makefile文件时,通常会包含以下基本元素:- 变量定义:定义编译器、编译选项、源文件列表等变量。
- 规则定义:定义编译规则,包括目标文件、依赖文件和编译指令。
- 依赖关系:明确指出各个源文件之间的依赖关系,以便make工具能够正确地进行编译。
3. sv中makefile文件的写法在SV项目中,编写makefile文件需要特别关注以下几点:- 定义变量:可以通过定义变量来指定编译器、编译选项、原文件列表等信息,使得makefile文件更加灵活和可维护。
- 设置规则:需要设置好编译规则,包括目标文件、依赖文件和编译指令。
这些规则应该准确反映出SV项目的结构和依赖关系。
- 定义依赖:在makefile文件中,需要清晰地定义各个源文件之间的依赖关系,以确保make工具能够正确地进行增量编译,提高编译效率。
4. 个人观点和理解在我看来,编写高质量的makefile文件对于SV项目的管理和维护至关重要。
一个良好的makefile文件可以提高项目的编译效率,简化编译过程,并且便于团队协作和代码管理。
在编写makefile文件时,应该注重规范和细节,以确保项目的可维护性和稳定性。
总结回顾通过编写这篇文章,我深入了解了sv中makefile文件的写法,并且通过我的个人观点和理解对这个主题进行了探讨。
在文章中多次提及了主题文字,并采用了从简到繁、由浅入深的方式来探讨主题,以便您能更深入地理解。
希望这篇文章能够对您有所帮助。
以上是我为您准备的关于sv中makefile文件的文章,希望能够满足您的要求。
最近在linux2.4内核上编译一个动态加载模块时遇到这样一个问题,执行make时编译器不编makefile文件中所指定的目标文件,而是提示一句Nothing to be done for `modules',然后就退出了。
主控Makefile文件中采用的式来编译模块的:$(MAKE) -C $(KERNELPA TH) SUBDIRS=$(shell pwd) modules下面我们来分析一下原因,并寻找解决的方法。
一、先看看执行$(MAKE) -C $(KERNELPA TH) SUBDIRS=$(shell pwd) modules后脚本是怎样执行的:1.进入内核目录,执行modules目标modules: $(patsubst %, _mod_%, $(SUBDIRS))这里把传入的SUBDIRS变量加上一个_mod_前缀,使modules依赖于他$(patsubst %, _mod_%, $(SUBDIRS)) : include/linux/version.h \ include/config/MARKER $(MAKE) -C $(patsubst _mod_%, %, $@) CFLAGS="$(CFLAGS) $(MODFLAGS)" MAKING_MODULES=1 modules这里回到SUBDIRS执行modules,但是带入CFLAGS变量2.回到SUBDIRS执行modules目标,但是Makefile文件中根本就没有这个目标的存在,当然会报Nothing to be done for `modules'了,那么这个modules目标到底是什么呢?找个2.4与2.6内核通用的模块编译Makefile文件看看,它通常在目标all之前有这样几行语句:-include $(TOPDIR)/Rules.makeall_targets:all这就是问题的关键所在!TOPDIR变量内核根Makefile文件中定义的TOPDIR := $(shell /bin/pwd)就是指内核的路径,所以Include前面的“-”就显得尤为重要。
在编程中,Makefile是一种脚本文件,用于自动构建程序。
它描述了如何从源代码生成可执行文件或库文件,并指定了需要使用的编译选项和依赖关系。
以下是一个简单的Makefile示例,用于编译一个C程序:makefile复制代码CC=gccCFLAGS=-Wall -gSOURCES=main.c foo.c bar.cOBJECTS=$(SOURCES:.c=.o)TARGET=myprogall: $(TARGET)$(TARGET): $(OBJECTS)$(CC) $(CFLAGS) -o $(TARGET) $(OBJECTS)%.o: %.c$(CC) $(CFLAGS) -c $< -o $@clean:rm -f *.o $(TARGET)这个Makefile文件定义了一些变量和规则。
CC变量指定了编译器,CFLAGS变量指定了编译选项。
SOURCES变量包含所有源文件,OBJECTS变量包含了所有编译后的目标文件。
TARGET变量指定了最终生成的可执行文件名。
all规则是默认规则,它依赖于$(TARGET)规则。
$(TARGET)规则指定了如何从目标文件生成可执行文件。
在$(TARGET)规则中,使用了命令行来执行编译器,并指定了编译选项和依赖关系。
%.o: %.c规则指定了如何从C源文件编译为目标文件。
在规则中,使用了命令行来执行编译器,并指定了编译选项和依赖关系。
clean规则是一个特殊规则,用于清理生成的目标文件和可执行文件。
在规则中,使用了命令行来删除这些文件。
要使用这个Makefile,可以在终端中进入包含Makefile的目录,并运行make命令。
这将自动构建程序,并生成可执行文件。
如果需要清理生成的文件,可以运行make clean命令。
标题:OpenWRT Makefile动态库编写模板一、概述OpenWRT是一个针对嵌入式设备的Linux发行版,它提供了一个框架,可以方便地为各种路由器、网关和嵌入式设备构建自定义的固件。
其中,Makefile是用来构建OpenWRT软件包的一种工具,通过Makefile可以定义软件包的源代码、依赖关系以及编译规则。
在OpenWRT项目中,动态库的编写相对较为复杂,因此需要一个模板来帮助开发者更快地编写和配置动态库的Makefile。
二、动态库概述1. 动态库是一种可以被应用程序动态加载的共享库,它使得应用程序可以在运行时信息并调用库中的函数。
与静态库相比,动态库的大小更小,且可以在多个应用程序之间共享,为了在OpenWRT项目中使用动态库,必须在Makefile中正确配置相关参数。
三、OpenWRT Makefile动态库编写模板下面是一个针对OpenWRT项目中动态库的Makefile编写模板:```makeinclude $(TOPDIR)/rules.mkPKG_NAME:=your-library-namePKG_VERSION:=1.0.0PKG_RELEASE:=1PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) include $(INCLUDE_DIR)/package.mkdefine Package/your-library-nameSECTION:=libsCATEGORY:=LibrariesTITLE:=Your library titleDEPENDS:= +libpthread +librtendefdefine Package/your-library-name/descriptionYour library descriptionendefdefine Build/Preparemkdir -p $(PKG_BUILD_DIR)$(CP) ./src/* $(PKG_BUILD_DIR)/endefdefine Build/Compile$(MAKE) -C $(PKG_BUILD_DIR)/endefdefine Package/your-library-name/install$(INSTALL_DIR) $(1)/usr/lib$(INSTALL_BIN) $(PKG_BUILD_DIR)/your-library.so$(1)/usr/lib/endef$(eval $(call BuildPackage,your-library-name))```在上面的示例中,需要将"your-library-name"替换为实际的动态库名称,"your-library-title"替换为实际的标题,"your-library-description"替换为实际的描述,"./src/*"替换为实际的源代码路径,"your-library.so"替换为实际的动态库文件名。
Makefile使⽤总结1. Makefile 简介Makefile 是和 make 命令⼀起配合使⽤的.很多⼤型项⽬的编译都是通过 Makefile 来组织的, 如果没有 Makefile, 那很多项⽬中各种库和代码之间的依赖关系不知会多复杂. Makefile的组织流程的能⼒如此之强, 不仅可以⽤来编译项⽬, 还可以⽤来组织我们平时的⼀些⽇常操作. 这个需要⼤家发挥⾃⼰的想象⼒.本篇博客是基于⽽整理的, 有些删减, 追加了⼀些⽰例.⾮常感谢 gunguymadman_cu 提供如此详尽的Makefile介绍, 这正是我⼀直寻找的Makefile中⽂⽂档.1.1 Makefile 主要的 5个部分 (显⽰规则, 隐晦规则, 变量定义, ⽂件指⽰, 注释)Makefile基本格式如下:target ... : prerequisites ...command......其中,target - ⽬标⽂件, 可以是 Object File, 也可以是可执⾏⽂件prerequisites - ⽣成 target 所需要的⽂件或者⽬标command - make需要执⾏的命令 (任意的shell命令), Makefile中的命令必须以 [tab] 开头1. 显⽰规则 :: 说明如何⽣成⼀个或多个⽬标⽂件(包括⽣成的⽂件, ⽂件的依赖⽂件, ⽣成的命令)2. 隐晦规则 :: make的⾃动推导功能所执⾏的规则3. 变量定义 :: Makefile中定义的变量4. ⽂件指⽰ :: Makefile中引⽤其他Makefile; 指定Makefile中有效部分; 定义⼀个多⾏命令5. 注释 :: Makefile只有⾏注释 "#", 如果要使⽤或者输出"#"字符, 需要进⾏转义, "\#"1.2 GNU make 的⼯作⽅式1. 读⼊主Makefile (主Makefile中可以引⽤其他Makefile)2. 读⼊被include的其他Makefile3. 初始化⽂件中的变量4. 推导隐晦规则, 并分析所有规则5. 为所有的⽬标⽂件创建依赖关系链6. 根据依赖关系, 决定哪些⽬标要重新⽣成7. 执⾏⽣成命令2. Makefile 初级语法2.1 Makefile 规则2.1.1 规则语法规则主要有2部分: 依赖关系和⽣成⽬标的⽅法.语法有以下2种:target ... : prerequisites ...command...或者target ... : prerequisites ; commandcommand...*注* command太长, 可以⽤ "\" 作为换⾏符2.1.2 规则中的通配符* :: 表⽰任意⼀个或多个字符:: 表⽰任意⼀个字符[...] :: ex. [abcd] 表⽰a,b,c,d中任意⼀个字符, [^abcd]表⽰除a,b,c,d以外的字符, [0-9]表⽰ 0~9中任意⼀个数字~ :: 表⽰⽤户的home⽬录2.1.3 路径搜索当⼀个Makefile中涉及到⼤量源⽂件时(这些源⽂件和Makefile极有可能不在同⼀个⽬录中),这时, 最好将源⽂件的路径明确在Makefile中, 便于编译时查找. Makefile中有个特殊的变量VPATH就是完成这个功能的.指定了VPATH之后, 如果当前⽬录中没有找到相应⽂件或依赖的⽂件, Makefile 回到VPATH指定的路径中再去查找.. VPATH使⽤⽅法:vpath <directories> :: 当前⽬录中找不到⽂件时, 就从<directories>中搜索vpath <pattern> <directories> :: 符合<pattern>格式的⽂件, 就从<directories>中搜索vpath <pattern> :: 清除符合<pattern>格式的⽂件搜索路径vpath :: 清除所有已经设置好的⽂件路径# ⽰例1 - 当前⽬录中找不到⽂件时, 按顺序从 src⽬录 ../parent-dir⽬录中查找⽂件VPATH src:../parent-dir# ⽰例2 - .h结尾的⽂件都从 ./header ⽬录中查找VPATH %.h ./header# ⽰例3 - 清除⽰例2中设置的规则VPATH %.h# ⽰例4 - 清除所有VPATH的设置VPATH2.2 Makefile 中的变量2.2.1 变量定义 ( = or := )OBJS = programA.o programB.oOBJS-ADD = $(OBJS) programC.o# 或者OBJS := programA.o programB.oOBJS-ADD := $(OBJS) programC.o其中 = 和 := 的区别在于, := 只能使⽤前⾯定义好的变量, = 可以使⽤后⾯定义的变量测试 =# Makefile内容OBJS2 = $(OBJS1) programC.oOBJS1 = programA.o programB.oall:@echo $(OBJS2)# bash中执⾏make, 可以看出虽然 OBJS1 是在 OBJS2 之后定义的, 但在 OBJS2中可以提前使⽤$ makeprogramA.o programB.o programC.o测试 :=# Makefile内容OBJS2 := $(OBJS1) programC.oOBJS1 := programA.o programB.oall:@echo $(OBJS2)# bash中执⾏make, 可以看出 OBJS2 中的 $(OBJS1) 为空$ makeprogramC.o2.2.2 变量替换# Makefile内容SRCS := programA.c programB.c programC.cOBJS := $(SRCS:%.c=%.o)all:@echo "SRCS: " $(SRCS)@echo "OBJS: " $(OBJS)# bash中运⾏make$ makeSRCS: programA.c programB.c programC.cOBJS: programA.o programB.o programC.o2.2.3 变量追加值 +=# Makefile内容SRCS := programA.c programB.c programC.cSRCS += programD.call:@echo "SRCS: " $(SRCS)# bash中运⾏make$ makeSRCS: programA.c programB.c programC.c programD.c2.2.4 变量覆盖 override作⽤是使 Makefile中定义的变量能够覆盖 make 命令参数中指定的变量语法:override <variable> = <value>override <variable> := <value>override <variable> += <value>下⾯通过⼀个例⼦体会 override 的作⽤:# Makefile内容 (没有⽤override)SRCS := programA.c programB.c programC.call:@echo "SRCS: " $(SRCS)# bash中运⾏make$ make SRCS=nothingSRCS: nothing################################################## Makefile内容 (⽤override)override SRCS := programA.c programB.c programC.call:@echo "SRCS: " $(SRCS)# bash中运⾏make$ make SRCS=nothingSRCS: programA.c programB.c programC.c2.2.5 ⽬标变量作⽤是使变量的作⽤域仅限于这个⽬标(target), ⽽不像之前例⼦中定义的变量, 对整个Makefile都有效.语法:<target ...> :: <variable-assignment><target ...> :: override <variable-assignment> (override作⽤参见变量覆盖的介绍)⽰例:# Makefile 内容SRCS := programA.c programB.c programC.ctarget1: TARGET1-SRCS := programD.ctarget1:@echo "SRCS: " $(SRCS)@echo "SRCS: " $(TARGET1-SRCS)target2:@echo "SRCS: " $(SRCS)@echo "SRCS: " $(TARGET1-SRCS)# bash中执⾏make$ make target1SRCS: programA.c programB.c programC.cSRCS: programD.c$ make target2 <-- target2中显⽰不了 $(TARGET1-SRCS)SRCS: programA.c programB.c programC.cSRCS:2.3 Makefile 命令前缀Makefile 中书写shell命令时可以加2种前缀 @ 和 -, 或者不⽤前缀.3种格式的shell命令区别如下:不⽤前缀 :: 输出执⾏的命令以及命令执⾏的结果, 出错的话停⽌执⾏前缀 @ :: 只输出命令执⾏的结果, 出错的话停⽌执⾏前缀 - :: 命令执⾏有错的话, 忽略错误, 继续执⾏⽰例:# Makefile 内容 (不⽤前缀)all:echo"没有前缀"cat this_file_not_existecho"错误之后的命令" <-- 这条命令不会被执⾏# bash中执⾏make$ makeecho"没有前缀" <-- 命令本⾝显⽰出来没有前缀 <-- 命令执⾏结果显⽰出来cat this_file_not_existcat: this_file_not_exist: No such file or directorymake: *** [all] Error 1############################################################ Makefile 内容 (前缀 @)all:@echo "没有前缀"@cat this_file_not_exist@echo "错误之后的命令" <-- 这条命令不会被执⾏# bash中执⾏make$ make没有前缀 <-- 只有命令执⾏的结果, 不显⽰命令本⾝cat: this_file_not_exist: No such file or directorymake: *** [all] Error 1############################################################ Makefile 内容 (前缀 -)all:-echo"没有前缀"-cat this_file_not_exist-echo"错误之后的命令" <-- 这条命令会被执⾏# bash中执⾏make$ makeecho"没有前缀" <-- 命令本⾝显⽰出来没有前缀 <-- 命令执⾏结果显⽰出来cat this_file_not_existcat: this_file_not_exist: No such file or directorymake: [all] Error 1 (ignored)echo"错误之后的命令" <-- 出错之后的命令也会显⽰错误之后的命令 <-- 出错之后的命令也会执⾏2.4 伪⽬标伪⽬标并不是⼀个"⽬标(target)", 不像真正的⽬标那样会⽣成⼀个⽬标⽂件.典型的伪⽬标是 Makefile 中⽤来清理编译过程中中间⽂件的 clean 伪⽬标, ⼀般格式如下: .PHONY: clean <-- 这句没有也⾏, 但是最好加上clean:-rm -f *.o2.5 引⽤其他的 Makefile语法: include <filename> (filename 可以包含通配符和路径)⽰例:# Makefile 内容all:@echo "主 Makefile begin"@make other-all@echo "主 Makefile end"include ./other/Makefile# ./other/Makefile 内容other-all:@echo "other makefile begin"@echo "other makefile end"# bash中执⾏make$ lltotal 20K-rw-r--r-- 1 wangyubin wangyubin 125 Sep 2316:13 Makefile-rw-r--r-- 1 wangyubin wangyubin 11K Sep 2316:15 <-- 这个⽂件不⽤管drwxr-xr-x 2 wangyubin wangyubin 4.0K Sep 2316:11 other$ ll other/total 4.0K-rw-r--r-- 1 wangyubin wangyubin 71 Sep 2316:11 Makefile$ make主 Makefile beginmake[1]: Entering directory `/path/to/test/makefile'other makefile beginother makefile endmake[1]: Leaving directory `/path/to/test/makefile'主 Makefile end2.6 查看C⽂件的依赖关系写 Makefile 的时候, 需要确定每个⽬标的依赖关系.GNU提供⼀个机制可以查看C代码⽂件依赖那些⽂件, 这样我们在写 Makefile ⽬标的时候就不⽤打开C源码来看其依赖那些⽂件了.⽐如, 下⾯命令显⽰内核源码中 virt/kvm/kvm_main.c 中的依赖关系$ cd virt/kvm/$ gcc -MM kvm_main.ckvm_main.o: kvm_main.c iodev.h coalesced_mmio.h async_pf.h <-- 这句就可以加到 Makefile 中作为编译 kvm_main.o 的依赖关系2.7 make 退出码Makefile的退出码有以下3种:0 :: 表⽰成功执⾏1 :: 表⽰make命令出现了错误2 :: 使⽤了 "-q" 选项, 并且make使得⼀些⽬标不需要更新2.8 指定 Makefile,指定特定⽬标默认执⾏ make 命令时, GNU make在当前⽬录下依次搜索下⾯3个⽂件 "GNUmakefile", "makefile", "Makefile",找到对应⽂件之后, 就开始执⾏此⽂件中的第⼀个⽬标(target). 如果找不到这3个⽂件就报错.⾮默认情况下, 可以在 make 命令中指定特定的 Makefile 和特定的⽬标.⽰例:# Makefile⽂件名改为 MyMake, 内容target1:@echo "target [1] begin"@echo "target [1] end"target2:@echo "target [2] begin"@echo "target [2] end"# bash 中执⾏make$ lsMakefile$ mv Makefile MyMake$ lsMyMake$ make <-- 找不到默认的 Makefilemake: *** No targets specified and no makefile found. Stop.$ make -f MyMake <-- 指定特定的Makefiletarget [1] begintarget [1] end$ make -f MyMake target2 <-- 指定特定的⽬标(target)target [2] begintarget [2] end2.9 make 参数介绍make 的参数有很多, 可以通过 make -h 去查看, 下⾯只介绍⼏个我认为⽐较有⽤的.参数含义--debug[=<options>]输出make的调试信息, options 可以是 a, b, v-j --jobs同时运⾏的命令的个数, 也就是多线程执⾏ Makefile-r --no-builtin-rules禁⽌使⽤任何隐含规则-R --no-builtin-variabes禁⽌使⽤任何作⽤于变量上的隐含规则-B --always-make假设所有⽬标都有更新, 即强制重编译2.10 Makefile 隐含规则这⾥只列⼀个和编译C相关的.编译C时,<n>.o 的⽬标会⾃动推导为 <n>.c# Makefile 中main : main.ogcc -o main main.o#会⾃动变为:main : main.ogcc -o main main.omain.o: main.c <-- main.o 这个⽬标是隐含⽣成的gcc -c main.c2.11 隐含规则中的命令变量和命令参数变量2.11.1 命令变量, 书写Makefile可以直接写 shell时⽤这些变量.下⾯只列出⼀些C相关的变量名含义RM rm -fAR arCC ccCXX g++⽰例:# Makefile 内容all:@echo $(RM)@echo $(AR)@echo $(CC)@echo $(CXX)# bash 中执⾏make, 显⽰各个变量的值$ makerm -farccg++2.11.2 命令参数变量变量名含义ARFLAGS AR命令的参数CFLAGS C语⾔编译器的参数CXXFLAGS C++语⾔编译器的参数⽰例: 下⾯以 CFLAGS 为例演⽰# test.c 内容#include <stdio.h>int main(int argc, char *argv[]){printf ("Hello Makefile\n");return 0;}# Makefile 内容test: test.o$(CC) -o test test.o# bash 中⽤make来测试$ lltotal 24K-rw-r--r-- 1 wangyubin wangyubin 69 Sep 2317:31 Makefile-rw-r--r-- 1 wangyubin wangyubin 14K Sep 2319:51 <-- 请忽略这个⽂件-rw-r--r-- 1 wangyubin wangyubin 392 Sep 2317:31 test.c$ makecc -c -o test.o test.ccc -o test test.o <-- 这个是⾃动推导的$ rm -f test test.o$ make CFLAGS=-Wall <-- 命令中加的编译器参数⾃动追加⼊下⾯的编译中了cc -Wall -c -o test.o test.ccc -o test test.o2.12 ⾃动变量Makefile 中很多时候通过⾃动变量来简化书写, 各个⾃动变量的含义如下:⾃动变量含义$@⽬标集合$%当⽬标是函数库⽂件时, 表⽰其中的⽬标⽂件名$<第⼀个依赖⽬标. 如果依赖⽬标是多个, 逐个表⽰依赖⽬标$?⽐⽬标新的依赖⽬标的集合$^所有依赖⽬标的集合, 会去除重复的依赖⽬标$+所有依赖⽬标的集合, 不会去除重复的依赖⽬标$*这个是GNU make特有的, 其它的make不⼀定⽀持3. Makefile ⾼级语法3.1 嵌套Makefile在 Makefile 初级语法中已经提到过引⽤其它 Makefile的⽅法. 这⾥有另⼀种写法, 并且可以向引⽤的其它 Makefile 传递参数.⽰例: (不传递参数, 只是调⽤⼦⽂件夹 other 中的Makefile)# Makefile 内容all:@echo "主 Makefile begin"@cd ./other && make@echo "主 Makefile end"# ./other/Makefile 内容other-all:@echo "other makefile begin"@echo "other makefile end"# bash中执⾏make$ lltotal 28K-rw-r--r-- 1 wangyubin wangyubin 104 Sep 2320:43 Makefile-rw-r--r-- 1 wangyubin wangyubin 17K Sep 2320:44 <-- 这个⽂件不⽤管drwxr-xr-x 2 wangyubin wangyubin 4.0K Sep 2320:42 other$ ll other/total 4.0K-rw-r--r-- 1 wangyubin wangyubin 71 Sep 2316:11 Makefile$ make主 Makefile beginmake[1]: Entering directory `/path/to/test/makefile/other'other makefile beginother makefile endmake[1]: Leaving directory `/path/to/test/makefile/other'主 Makefile end⽰例: (⽤export传递参数)# Makefile 内容export VALUE1 := export.c <-- ⽤了 export, 此变量能够传递到 ./other/Makefile 中VALUE2 := no-export.c <-- 此变量不能传递到 ./other/Makefile 中all:@echo "主 Makefile begin"@cd ./other && make@echo "主 Makefile end"# ./other/Makefile 内容other-all:@echo "other makefile begin"@echo "VALUE1: " $(VALUE1)@echo "VALUE2: " $(VALUE2)@echo "other makefile end"# bash中执⾏make$ make主 Makefile beginmake[1]: Entering directory `/path/to/test/makefile/other'other makefile beginVALUE1: export.c <-- VALUE1 传递成功VALUE2: <-- VALUE2 传递失败other makefile endmake[1]: Leaving directory `/path/to/test/makefile/other'主 Makefile end*补充* export 语法格式如下:export variable = valueexport variable := valueexport variable += value3.2 定义命令包命令包有点像是个函数, 将连续的相同的命令合成⼀条, 减少 Makefile 中的代码量, 便于以后维护.语法:define <command-name>command...endef⽰例:# Makefile 内容define run-hello-makefile@echo -n "Hello"@echo " Makefile!"@echo "这⾥可以执⾏多条 Shell 命令!"endefall:$(run-hello-makefile)# bash 中运⾏make$ makeHello Makefile!这⾥可以执⾏多条 Shell 命令!3.3 条件判断条件判断的关键字主要有 ifeq ifneq ifdef ifndef语法:<conditional-directive><text-if-true>endif# 或者<conditional-directive><text-if-true>else<text-if-false>endif⽰例: ifeq的例⼦, ifneq和ifeq的使⽤⽅法类似, 就是取反# Makefile 内容all:ifeq ("aa", "bb")@echo "equal"else@echo "not equal"endif# bash 中执⾏make$ makenot equal⽰例: ifdef的例⼦, ifndef和ifdef的使⽤⽅法类似, 就是取反# Makefile 内容SRCS := program.call:ifdef SRCS@echo $(SRCS)else@echo "no SRCS"# bash 中执⾏make$ makeprogram.c3.4 Makefile 中的函数Makefile 中⾃带了⼀些函数, 利⽤这些函数可以简化 Makefile 的编写.函数调⽤语法如下:$(<function> <arguments>)# 或者${<function> <arguments>}<function> 是函数名<arguments> 是函数参数3.4.1 字符串函数字符串替换函数: $(subst <from>,<to>,<text>)功能: 把字符串<text> 中的 <from> 替换为 <to>返回: 替换过的字符串# Makefile 内容all:@echo $(subst t,e,maktfilt) <-- 将t替换为e# bash 中执⾏make$ makemakefile模式字符串替换函数: $(patsubst <pattern>,<replacement>,<text>)功能: 查找<text>中的单词(单词以"空格", "tab", "换⾏"来分割) 是否符合 <pattern>, 符合的话, ⽤ <replacement> 替代.返回: 替换过的字符串# Makefile 内容all:@echo $(patsubst %.c,%.o,programA.c programB.c)# bash 中执⾏make$ makeprogramA.o programB.o去空格函数: $(strip <string>)功能: 去掉 <string> 字符串中开头和结尾的空字符返回: 被去掉空格的字符串值# Makefile 内容VAL := " aa bb cc "all:@echo "去除空格前: " $(VAL)@echo "去除空格后: " $(strip $(VAL))# bash 中执⾏make去除空格前: aa bb cc去除空格后: aa bb cc查找字符串函数: $(findstring <find>,<in>)功能: 在字符串 <in> 中查找 <find> 字符串返回: 如果找到, 返回 <find> 字符串, 否则返回空字符串# Makefile 内容VAL := " aa bb cc "all:@echo $(findstring aa,$(VAL))@echo $(findstring ab,$(VAL))# bash 中执⾏make$ makeaa过滤函数: $(filter <pattern...>,<text>)功能: 以 <pattern> 模式过滤字符串 <text>, *保留* 符合模式 <pattern> 的单词, 可以有多个模式返回: 符合模式 <pattern> 的字符串# Makefile 内容all:@echo $(filter %.o %.a,program.c program.o program.a)# bash 中执⾏make$ makeprogram.o program.a反过滤函数: $(filter-out <pattern...>,<text>)功能: 以 <pattern> 模式过滤字符串 <text>, *去除* 符合模式 <pattern> 的单词, 可以有多个模式返回: 不符合模式 <pattern> 的字符串# Makefile 内容all:@echo $(filter-out %.o %.a,program.c program.o program.a)# bash 中执⾏make$ makeprogram.c排序函数: $(sort <list>)功能: 给字符串 <list> 中的单词排序 (升序)返回: 排序后的字符串# Makefile 内容all:@echo $(sort bac abc acb cab)# bash 中执⾏make$ makeabc acb bac cab取单词函数: $(word <n>,<text>)功能: 取字符串 <text> 中的第<n>个单词 (n从1开始)返回: <text> 中的第<n>个单词, 如果<n> ⽐ <text> 中单词个数要⼤, 则返回空字符串# Makefile 内容all:@echo $(word 1,aa bb cc dd)@echo $(word 5,aa bb cc dd)@echo $(word 4,aa bb cc dd)# bash 中执⾏make$ makeaadd取单词串函数: $(wordlist <s>,<e>,<text>)功能: 从字符串<text>中取从<s>开始到<e>的单词串. <s>和<e>是⼀个数字.返回: 从<s>到<e>的字符串# Makefile 内容all:@echo $(wordlist 1,3,aa bb cc dd)@echo $(word 5,6,aa bb cc dd)@echo $(word 2,5,aa bb cc dd)# bash 中执⾏make$ makeaa bb ccbb单词个数统计函数: $(words <text>)功能: 统计字符串 <text> 中单词的个数返回: 单词个数# Makefile 内容all:@echo $(words aa bb cc dd)@echo $(words aabbccdd)@echo $(words )# bash 中执⾏make$ make41⾸单词函数: $(firstword <text>)功能: 取字符串 <text> 中的第⼀个单词返回: 字符串 <text> 中的第⼀个单词# Makefile 内容all:@echo $(firstword aa bb cc dd)@echo $(firstword aabbccdd)@echo $(firstword )# bash 中执⾏make$ makeaaaabbccdd3.4.2 ⽂件名函数取⽬录函数: $(dir <names...>)功能: 从⽂件名序列 <names> 中取出⽬录部分返回: ⽂件名序列 <names> 中的⽬录部分# Makefile 内容all:@echo $(dir /home/a.c ./bb.c ../c.c d.c)# bash 中执⾏make$ make/home/ ./ ../ ./取⽂件函数: $(notdir <names...>)功能: 从⽂件名序列 <names> 中取出⾮⽬录部分返回: ⽂件名序列 <names> 中的⾮⽬录部分# Makefile 内容all:@echo $(notdir /home/a.c ./bb.c ../c.c d.c)# bash 中执⾏make$ makea.c bb.cc.cd.c取后缀函数: $(suffix <names...>)功能: 从⽂件名序列 <names> 中取出各个⽂件名的后缀返回: ⽂件名序列 <names> 中各个⽂件名的后缀, 没有后缀则返回空字符串# Makefile 内容all:@echo $(suffix /home/a.c ./b.o ../c.a d)# bash 中执⾏make$ make.c .o .a取前缀函数: $(basename <names...>)功能: 从⽂件名序列 <names> 中取出各个⽂件名的前缀返回: ⽂件名序列 <names> 中各个⽂件名的前缀, 没有前缀则返回空字符串# Makefile 内容all:@echo $(basename /home/a.c ./b.o ../c.a /home/.d .e)# bash 中执⾏make$ make/home/a ./b ../c /home/加后缀函数: $(addsuffix <suffix>,<names...>)功能: 把后缀 <suffix> 加到 <names> 中的每个单词后⾯返回: 加过后缀的⽂件名序列# Makefile 内容all:@echo $(addsuffix .c,/home/a b ./c.o ../d.c)# bash 中执⾏make$ make/home/a.c b.c ./c.o.c ../d.c.c加前缀函数: $(addprefix <prefix>,<names...>)功能: 把前缀 <prefix> 加到 <names> 中的每个单词前⾯返回: 加过前缀的⽂件名序列# Makefile 内容all:@echo $(addprefix test_,/home/a.c b.c ./d.c)# bash 中执⾏make$ maketest_/home/a.c test_b.c test_./d.c连接函数: $(join <list1>,<list2>)功能: <list2> 中对应的单词加到 <list1> 后⾯返回: 连接后的字符串# Makefile 内容all:@echo $(join a b c d,1234)@echo $(join a b c d,12345)@echo $(join a b c d e,1234)# bash 中执⾏make$ makea1 b2 c3 d4a1 b2 c3 d4 5a1 b2 c3 d4 e3.4.3 foreach语法:$(foreach <var>,<list>,<text>)⽰例:# Makefile 内容targets := a b c dobjects := $(foreach i,$(targets),$(i).o)all:@echo $(targets)@echo $(objects)# bash 中执⾏make$ makea b c da.ob.oc.od.o3.4.4 if这⾥的if是个函数, 和前⾯的条件判断不⼀样, 前⾯的条件判断属于Makefile的关键字语法:$(if <condition>,<then-part>)$(if <condition>,<then-part>,<else-part>)⽰例:# Makefile 内容val := aobjects := $(if $(val),$(val).o,nothing)no-objects := $(if $(no-val),$(val).o,nothing)all:@echo $(objects)@echo $(no-objects)# bash 中执⾏make$ makea.onothing3.4.5 call - 创建新的参数化函数语法:$(call <expression>,<parm1>,<parm2>,<parm3>...)⽰例:# Makefile 内容log = "====debug====" $(1) "====end===="all:@echo $(call log,"正在 Make")# bash 中执⾏make$ make====debug==== 正在 Make ====end====3.4.6 origin - 判断变量的来源语法:$(origin <variable>)返回值有如下类型:类型含义undefined<variable> 没有定义过default<variable> 是个默认的定义, ⽐如 CC 变量environment<variable> 是个环境变量, 并且 make时没有使⽤ -e 参数file<variable> 定义在Makefile中command line<variable> 定义在命令⾏中override<variable> 被 override 重新定义过automatic<variable> 是⾃动化变量⽰例:# Makefile 内容val-in-file := test-fileoverride val-override := test-overrideall:@echo $(origin not-define) # not-define 没有定义@echo $(origin CC) # CC 是Makefile默认定义的变量@echo $(origin PATH) # PATH 是 bash 环境变量@echo $(origin val-in-file) # 此Makefile中定义的变量@echo $(origin val-in-cmd) # 这个变量会加在make的参数中@echo $(origin val-override) # 此Makefile中定义的override变量@echo $(origin @) # ⾃动变量, 具体前⾯的介绍# bash 中执⾏make$ make val-in-cmd=val-cmdundefineddefaultenvironmentfilecommand lineoverrideautomatic3.4.7 shell语法:$(shell <shell command>)它的作⽤就是执⾏⼀个shell命令, 并将shell命令的结果作为函数的返回.作⽤和 `<shell command>` ⼀样, ` 是反引号3.4.8 make 控制函数产⽣⼀个致命错误: $(error <text ...>)功能: 输出错误信息, 停⽌Makefile的运⾏# Makefile 内容all:$(error there is an error!)@echo "这⾥不会执⾏!"# bash 中执⾏make$ makeMakefile:2: *** there is an error!. Stop.输出警告: $(warning <text ...>)功能: 输出警告信息, Makefile继续运⾏# Makefile 内容all:$(warning there is an warning!)@echo "这⾥会执⾏!"# bash 中执⾏make$ makeMakefile:2: there is an warning!这⾥会执⾏!3.5 Makefile中⼀些GNU约定俗成的伪⽬标如果有过在Linux上, 从源码安装软件的经历的话, 就会对 make clean, make install ⽐较熟悉.像 clean, install 这些伪⽬标, ⼴为⼈知, 不⽤解释就⼤家知道是什么意思了.下⾯列举⼀些常⽤的伪⽬标, 如果在⾃⼰项⽬的Makefile合理使⽤这些伪⽬标的话, 可以让我们⾃⼰的Makefile看起来更专业, 呵呵 :)伪⽬标含义all所有⽬标的⽬标,其功能⼀般是编译所有的⽬标clean删除所有被make创建的⽂件install安装已编译好的程序,其实就是把⽬标可执⾏⽂件拷贝到指定的⽬录中去print列出改变过的源⽂件tar把源程序打包备份. 也就是⼀个tar⽂件dist创建⼀个压缩⽂件, ⼀般是把tar⽂件压成Z⽂件. 或是gz⽂件TAGS更新所有的⽬标, 以备完整地重编译使⽤check 或 test⼀般⽤来测试makefile的流程。
############################################################# # Generic Makefile for C/C++ Program## License: GPL (General Public License)# Author: whyglinux <whyglinux AT gmail DOT com># Date: 2006/03/04 (version 0.1)# 2007/03/24 (version 0.2)# 2007/04/09 (version 0.3)# 2007/06/26 (version 0.4)# 2008/04/05 (version 0.5)## Description:# ------------# This is an easily customizable makefile template. The purpose is to# provide an instant building environment for C/C++ programs.## It searches all the C/C++ source files in the specified directories,# makes dependencies, compiles and links to form an executable.## Besides its default ability to build C/C++ programs which use only# standard C/C++ libraries, you can customize the Makefile to build# those using other libraries. Once done, without any changes you can# then build programs using the same or less libraries, even if source# files are renamed, added or removed. Therefore, it is particularly# convenient to use it to build codes for experimental or study use.## GNU make is expected to use the Makefile. Other versions of makes# may or may not work.## Usage:# ------# 1. Copy the Makefile to your program directory.# 2. Customize in the "Customizable Section" only if necessary:# * to use non-standard C/C++ libraries, set pre-processor or compiler# options to <MY_CFLAGS> and linker ones to <MY_LIBS># (See Makefile.gtk+-2.0 for an example)# * to search sources in more directories, set to <SRCDIRS># * to specify your favorite program name, set to <PROGRAM># 3. Type make to start building your program.## Make Target:# ------------# The Makefile provides the following targets to make:# $ make compile and link# $ make NODEP=yes compile and link without generating dependencies # $ make objs compile only (no linking)# $ make tags create tags for Emacs editor# $ make ctags create ctags for VI editor# $ make clean clean objects and the executable file# $ make distclean clean objects, the executable and dependencies# $ make help get the usage of the makefile##========================================================== =================## Customizable Section: adapt those variables to suit your program.##========================================================= =================# The pre-processor and compiler options.MY_CFLAGS =# The linker options.MY_LIBS =# The pre-processor options used by the cpp (man cpp for more). CPPFLAGS = -Wall# The options used in linking as well as in any direct use of ld.LDFLAGS =# The directories in which source files reside.# If not specified, only the current directory will be serached.SRCDIRS =# The executable file name.# If not specified, current directory name or `a.out' will be used.PROGRAM =## Implicit Section: change the following only when necessary.##========================================================= =================# The source file types (headers excluded).# .c indicates C source files, and others C++ ones.SRCEXTS = .c .C .cc .cpp .CPP .c++ .cxx .cp# The header file types.HDREXTS = .h .H .hh .hpp .HPP .h++ .hxx .hp# The pre-processor and compiler options.# Users can override those variables from the command line.CFLAGS = -g -O2CXXFLAGS= -g -O2# The C program compiler.#CC = gcc# The C++ program compiler.#CXX = g++# Un-comment the following line to compile C programs as C++ ones.#CC = $(CXX)# The command used to delete file.#RM = rm -fETAGS = etagsETAGSFLAGS =CTAGS = ctagsCTAGSFLAGS =## Stable Section: usually no need to be changed. But you can add more.##========================================================= =================SHELL = /bin/shEMPTY =SPACE = $(EMPTY) $(EMPTY)ifeq ($(PROGRAM),)CUR_PATH_NAMES = $(subst /,$(SPACE),$(subst $(SPACE),_,$(CURDIR)))PROGRAM = $(word $(words $(CUR_PATH_NAMES)),$(CUR_PATH_NAMES))ifeq ($(PROGRAM),)PROGRAM = a.outendifendififeq ($(SRCDIRS),)SRCDIRS = .endifSOURCES = $(foreach d,$(SRCDIRS),$(wildcard $(addprefix$(d)/*,$(SRCEXTS))))HEADERS = $(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(HDREXTS))))SRC_CXX = $(filter-out %.c,$(SOURCES))OBJS = $(addsuffix .o, $(basename $(SOURCES)))DEPS = $(OBJS:.o=.d)## Define some useful variables.DEP_OPT = $(shell if `$(CC) --version | grep "GCC" >/dev/null`; then \echo "-MM -MP"; else echo "-M"; fi )DEPEND = $(CC) $(DEP_OPT) $(MY_CFLAGS) $(CFLAGS) $(CPPFLAGS)DEPEND.d = $(subst -g ,,$(DEPEND))COMPILE.c = $(CC) $(MY_CFLAGS) $(CFLAGS) $(CPPFLAGS) -c COMPILE.cxx = $(CXX) $(MY_CFLAGS) $(CXXFLAGS) $(CPPFLAGS) -c LINK.c = $(CC) $(MY_CFLAGS) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS)LINK.cxx = $(CXX) $(MY_CFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS).PHONY: all objs tags ctags clean distclean help show# Delete the default suffixes.SUFFIXES:all: $(PROGRAM)# Rules for creating dependency files (.d).#------------------------------------------%.d:%.c@echo -n $(dir $<) > $@@$(DEPEND.d) $< >> $@%.d:%.C@echo -n $(dir $<) > $@@$(DEPEND.d) $< >> $@%.d:%.cc@echo -n $(dir $<) > $@@$(DEPEND.d) $< >> $@%.d:%.cpp@echo -n $(dir $<) > $@@$(DEPEND.d) $< >> $@%.d:%.CPP@echo -n $(dir $<) > $@@$(DEPEND.d) $< >> $@%.d:%.c++@echo -n $(dir $<) > $@@$(DEPEND.d) $< >> $@%.d:%.cp@echo -n $(dir $<) > $@@$(DEPEND.d) $< >> $@%.d:%.cxx@echo -n $(dir $<) > $@@$(DEPEND.d) $< >> $@# Rules for generating object files (.o). #---------------------------------------- objs:$(OBJS)%.o:%.c$(COMPILE.c) $< -o $@%.o:%.C$(COMPILE.cxx) $< -o $@%.o:%.cc$(COMPILE.cxx) $< -o $@%.o:%.cpp$(COMPILE.cxx) $< -o $@%.o:%.CPP$(COMPILE.cxx) $< -o $@%.o:%.c++$(COMPILE.cxx) $< -o $@%.o:%.cp$(COMPILE.cxx) $< -o $@%.o:%.cxx$(COMPILE.cxx) $< -o $@# Rules for generating the tags.#-------------------------------------tags: $(HEADERS) $(SOURCES)$(ETAGS) $(ETAGSFLAGS) $(HEADERS) $(SOURCES)ctags: $(HEADERS) $(SOURCES)$(CTAGS) $(CTAGSFLAGS) $(HEADERS) $(SOURCES)# Rules for generating the executable.#-------------------------------------$(PROGRAM):$(OBJS)ifeq ($(SRC_CXX),) # C program$(LINK.c) $(OBJS) $(MY_LIBS) -o $@@echo Type ./$@ to execute the program.else # C++ program$(LINK.cxx) $(OBJS) $(MY_LIBS) -o $@@echo Type ./$@ to execute the program.endififndef NODEPifneq ($(DEPS),)sinclude $(DEPS)endifendifclean:$(RM) $(OBJS) $(PROGRAM) $(PROGRAM).exedistclean: clean$(RM) $(DEPS) TAGS# Show help.help:@echo 'Generic Makefile for C/C++ Programs (gcmakefile) version 0.5' @echo 'Copyright (C) 2007, 2008 whyglinux <whyglinux@>' @echo@echo 'Usage: make [TARGET]'@echo 'TARGETS:'@echo ' all (=make) compile and link.'@echo ' NODEP=yes make without generating dependencies.'@echo ' objs compile only (no linking).'@echo ' tags create tags for Emacs editor.'@echo ' ctags create ctags for VI editor.'@echo ' clean clean objects and the executable file.'@echo ' distclean clean objects, the executable and dependencies.'@echo ' show show variables (for debug use only).'@echo ' help print this message.'@echo@echo 'Report bugs to <whyglinux AT gmail DOT com>.'# Show variables (for debug use only.)show:@echo 'PROGRAM :' $(PROGRAM)@echo 'SRCDIRS :' $(SRCDIRS)@echo 'HEADERS :' $(HEADERS)@echo 'SOURCES :' $(SOURCES)@echo 'SRC_CXX :' $(SRC_CXX)@echo 'OBJS :' $(OBJS)@echo 'DEPS :' $(DEPS)@echo 'DEPEND :' $(DEPEND)@echo 'COMPILE.c :' $(COMPILE.c)@echo 'COMPILE.cxx :' $(COMPILE.cxx)@echo 'link.c :' $(LINK.c)@echo 'link.cxx :' $(LINK.cxx)## End of the Makefile ## Suggestions are welcome ## All rights reserved ################################################################。
vivado makefile文件编写实例如何编写Vivado Makefile 文件。
Vivado 是一款由Xilinx 公司开发的集成电路设计工具,它提供了丰富的设计和仿真功能,可以用于设计和验证各种数字电路。
Makefile 是一种用于自动化构建和管理项目的文件,它可以定义编译、链接和运行等操作的规则。
在Vivado 中使用Makefile 可以方便地管理项目的编译和仿真过程,提高开发效率。
本文将以中括号内的内容为主题,一步一步回答如何编写Vivado Makefile 文件。
一、创建Makefile 文件首先,在Vivado 工程目录下创建一个名为Makefile 的文件。
可以使用文本编辑器或者命令行工具创建该文件。
二、Makefile 基本结构Makefile 是按照一定的规则编写的,它由一系列的规则定义组成,每个规则包含一个或多个目标、依赖和命令。
规则的语法如下:target: dependenciescommand其中,target 是规则的目标,dependencies 是目标的依赖,command 是执行的命令。
三、Vivado Makefile 常用规则1. all:编译和仿真整个工程all: build sim上述规则定义了一个名为all 的目标,它依赖于build 和sim 两个目标,执行的命令为空。
2. build:编译工程build:vivado -mode batch -source build.tcl上述规则定义了一个名为build 的目标,它执行vivado 命令,并传入-mode batch 和-source build.tcl 两个参数。
这里的build.tcl 是一个Vivado Tcl 脚本,用于自动化执行编译操作。
3. sim:仿真工程sim:vivado -mode batch -source sim.tcl上述规则定义了一个名为sim 的目标,它执行vivado 命令,并传入-mode batch 和-source sim.tcl 两个参数。
SV(SystemVerilog)是一种硬件描述语言,用于设计和验证数字电路。
在进行SV代码编写的过程中,makefile是一种非常有用的工具,可以帮助组织和管理SV项目中的代码文件。
本文将介绍SV中makefile的写法,希望能为SV开发者提供一些参考和帮助。
1. 为什么需要makefile在SV项目中,通常会涉及到多个源文件、库文件、测试文件等。
使用makefile可以帮助我们轻松地组织和管理这些文件,实现自动化编译、信息和运行测试的功能。
makefile还可以帮助我们避免重复编译文件,提高开发效率。
2. makefile的基本结构makefile由一系列规则组成,每个规则由一个目标、依赖列表和命令组成。
一个基本的makefile看起来像这样:```makefiletarget: dependenciesmand```其中,target表示规则的目标文件,dependencies表示该目标文件的依赖文件mand表示需要执行的命令。
3. 使用变量在makefile中,我们可以使用变量来定义一些常量,方便我们在后续的规则中使用。
例如:```makefileSV_SRC = file1.sv file2.sv file3.sv```这样,我们就可以在后续的规则中使用$(SV_SRC)来表示这些文件,而不需要重复地写出它们的文件名。
4. 基本规则在SV项目中,常见的makefile规则包括编译规则、信息规则和运行测试规则。
以下是一个简单的例子:```makefileall: $(SV_SRC)vlog $(SV_SRC)sim: allvsim top_module```在这个例子中,我们定义了两个规则,分别是all和sim。
all规则依赖于$(SV_SRC)中的文件,使用vlog命令对这些文件进行编译。
sim规则依赖于all规则,使用vsim命令来运行测试。
5. 使用通配符在makefile中,我们还可以使用通配符来表示一类文件。
单片机makefile编写编写一个针对单片机的Makefile通常涉及指定编译器、链接器、源文件、目标文件、依赖关系以及构建和清理过程。
以下是一个简单的Makefile示例,它假设你正在使用GCC编译器为单片机(如AVR)编译代码:make# 定义编译器和工具链CC=avr-gccOBJCOPY=avr-objcopySIZE=avr-size# 定义项目名称和CPU类型PROJECT=my_projectCPU=atmega328p# 定义源文件目录和源文件列表SRC_DIR=./srcSRC=$(wildcard $(SRC_DIR)/*.c)# 定义目标文件目录和目标文件列表OBJ_DIR=./objOBJ=$(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)# 定义编译选项CFLAGS=-Os -DF_CPU=16000000UL -mmcu=$(CPU) -I. -std=gnu99 -Wall -Wextra -Werror# 定义最终目标文件HEX_FILE=$(PROJECT).hexELF_FILE=$(PROJECT).elf# 默认目标,输入'make'时将执行此目标all: $(HEX_FILE)# 链接对象文件并生成elf文件$(ELF_FILE): $(OBJ)$(CC) $(CFLAGS) -o $@ $^# 将elf文件转换为hex文件$(HEX_FILE): $(ELF_FILE)$(OBJCOPY) -O ihex -R .eeprom $< $@# 编译源文件并生成对象文件$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR)$(CC) $(CFLAGS) -c $< -o $@# 创建目标文件目录(如果不存在)$(OBJ_DIR):mkdir -p $@# 显示项目大小信息size: $(HEX_FILE)$(SIZE) -A $(ELF_FILE)# 清理生成的文件clean:rm -f $(OBJ_DIR)/*.o $(HEX_FILE) $(ELF_FILE)此Makefile将完成以下工作:使用AVR GCC编译器编译在src目录下的所有C源文件。
openwrt makefile 动态库编写模板-回复如何编写OpenWrt的makefile来创建动态库。
一、什么是OpenWrt?OpenWrt是一个用于嵌入式设备的Linux发行版,专门用于路由器等网络设备。
它具有轻量级、高度可定制的特点,可以为嵌入式设备提供丰富的功能和灵活的配置。
OpenWrt使用makefile来管理和构建软件包和应用程序。
二、什么是makefile?makefile是一种用于自动构建应用程序的文件,其中包含了构建应用程序所需的编译、链接和安装等命令。
makefile中包含了一系列规则,用于指定如何构建目标文件、可执行文件和库文件等。
在OpenWrt中,makefile 用于构建软件包和应用程序。
三、为什么要创建动态库?动态库是可共享的库,可以在运行时被多个程序共同使用。
与静态库相比,动态库在内存中只需加载一次,可以减少系统资源占用。
因此,创建动态库可以提高应用程序的灵活性和性能。
四、编写makefile的基本结构在开始编写makefile之前,首先需要了解makefile的基本结构。
一个简单的makefile通常包含以下部分:1. 定义变量:可以使用变量来代表路径、目标文件等。
变量名通常使用大写字母。
2. 定义规则:规则指定目标文件如何生成和更新,包括依赖关系、命令和生成目标文件的方法。
3. 定义目标:目标指定要生成的文件,可以是可执行文件、库文件或任何其他文件。
五、创建动态库的makefile模板下面是一个创建动态库的makefile模板:# 定义变量TARGET = libexample.soSRCS = example.cOBJS = (patsubst .c, .o, (SRCS))# 定义规则(TARGET): (OBJS)(CC) -shared -o (TARGET) (OBJS).o: .c(CC) (CFLAGS) -fPIC -c < -oclean:rm -f (OBJS) (TARGET)上述makefile模板包含了以下部分:1. 定义了变量TARGET,用于指定生成的动态库文件名。
⼤型⼯程多个⽬录下的Makefile写法1、前⾔2、简单测试 测试程序在同⼀个⽂件中,共有func.h、func.c、main.c三个⽂件,Makefile写法如下所⽰:1 CC = gcc2 CFLAGS = -g -Wall34 main:main.o func.o5 $(CC) main.o func.o -o main6 main.o:main.c7 $(CC) $(CFLAGS) -c main.c -o main.o8 func.o:func.c9 $(CC) $(CFLAGS) -c func.c -o func.o10 clean:11 rm -rf *.o执⾏过程如下图所⽰:3、通⽤模板 实际当中程序⽂件⽐较⼤,这时候对⽂件进⾏分类,分为头⽂件、源⽂件、⽬标⽂件、可执⾏⽂件。
也就是说通常将⽂件按照⽂件类型放在不同的⽬录当中,这个时候的Makefile需要统⼀管理这些⽂件,将⽣产的⽬标⽂件放在⽬标⽬录下,可执⾏⽂件放到可执⾏⽬录下。
测试程序如下图所⽰:完整的Makefile如下所⽰:1 DIR_INC = ./include2 DIR_SRC = ./src3 DIR_OBJ = ./obj4 DIR_BIN = ./bin56 SRC = $(wildcard ${DIR_SRC}/*.c)7 OBJ = $(patsubst %.c,${DIR_OBJ}/%.o,$(notdir ${SRC}))89 TARGET = main1011 BIN_TARGET = ${DIR_BIN}/${TARGET}1213 CC = gcc14 CFLAGS = -g -Wall -I${DIR_INC}1516 ${BIN_TARGET}:${OBJ}17 $(CC) $(OBJ) -o $@1819 ${DIR_OBJ}/%.o:${DIR_SRC}/%.c20 $(CC) $(CFLAGS) -c $< -o $@21 .PHONY:clean22 clean:23 find ${DIR_OBJ} -name *.o -exec rm -rf {}解释如下:(1)Makefile中的符号@, ^, < 的意思: @ 表⽰⽬标⽂件 ^ 表⽰所有的依赖⽂件 < 表⽰第⼀个依赖⽂件 $? 表⽰⽐⽬标还要新的依赖⽂件列表(2)wildcard、notdir、patsubst的意思: wildcard : 扩展通配符 notdir :去除路径 patsubst :替换通配符例如下图例⼦所⽰:输出结果如下所⽰:SRC = $(wildcard *.c)等于指定编译当前⽬录下所有.c⽂件,如果还有⼦⽬录,⽐如⼦⽬录为inc,则再增加⼀个wildcard函数,象这样:SRC = (wildcard *.c) (wildcard inc/*.c)(3)gcc -I -L -l的区别:gcc -o hello hello.c -I /home/hello/include -L /home/hello/lib -lworld上⾯这句表⽰在编译hello.c时-I /home/hello/include表⽰将/home/hello/include⽬录作为第⼀个寻找头⽂件的⽬录, 寻找的顺序是:/home/hello/include-->/usr/include-->/usr/local/include -L /home/hello/lib表⽰将/home/hello/lib⽬录作为第⼀个寻找库⽂件的⽬录, 寻找的顺序是:/home/hello/lib-->/lib-->/usr/lib-->/usr/local/lib-lworld表⽰在上⾯的lib的路径中寻找libworld.so动态库⽂件(如果gcc编译选项中加⼊了“-static”表⽰寻找libworld.a静态库⽂件)参考:Processing math: 0%。
yocto项目makefile写法在Yocto Project 中,Makefile 主要用于构建和管理软件包。
以下是一个简单的Yocto Project Makefile 示例,以说明其基本结构:```make# Yocto Project Makefile Example# 定义软件包名称PACKAGE_NAME = myapp# 定义软件包版本PACKAGE_VERSION = 1.0.0# 定义目标架构TARGET_ARCH = arm# 定义Yocto 配置文件路径YOCTO_CONFIG_FILE = /path/to/yocto-config.conf# 定义Yocto 编译工具链路径TOOLCHAIN_PATH = /path/to/toolchain# 定义Yocto 编译器CC = $(TOOLCHAIN_PATH)/$(TARGET_ARCH)-yocto-linux-gnueabi-gcc# 定义编译选项CFLAGS = -Wall -O2# 定义目标文件TARGET = $(PACKAGE_NAME)# 默认目标all: $(TARGET)# 目标文件编译规则$(TARGET): main.c$(CC) $(CFLAGS) -o $@ $<# 清理规则clean:rm -f $(TARGET)# 安装规则install:install -m 755 $(TARGET) $(DESTDIR)/usr/bin# 构建Yocto 镜像规则image:bitbake core-image-minimal# 使用Yocto 配置文件构建规则config:source $(YOCTO_CONFIG_FILE) && bitbake $(PACKAGE_NAME)# 自定义目标,可以根据需要添加其他规则```在这个示例中:- `PACKAGE_NAME` 和`PACKAGE_VERSION` 定义了软件包的名称和版本。
linux:⼏个常⽤makefile模板不才,总结个⼈常⽤makefile模板,以备后⽤。
1、编译动态库[plain]1. #############################################################2. # Makefile for shared library.3. # 编译动态链接库4. #############################################################5. #set your own environment option6. CC = g++7. CC_FLAG = -D_NOMNG -D_FILELINE8.9. #set your inc and lib10. INC =11. LIB = -lpthread -L./ -lsvrtool12.13. #make target lib and relevant obj14. PRG = libsvrtool.so15. OBJ = Log.o16.17. #all target18. all:$(PRG)19.20. $(PRG):$(OBJ)21. $(CC) -shared -o $@ $(OBJ) $(LIB)22.23. .SUFFIXES: .c .o .cpp24. .cpp.o:25. $(CC) $(CC_FLAG) $(INC) -c $*.cpp -o $*.o26.27. .PRONY:clean28. clean:29. @echo "Removing linked and compiled files......;30. rm -f $(OBJ) $(PRG)2、编译静态库[plain]1. #############################################################2. # Makefile for static library.3. # 编译静态链接库4. #############################################################5. #set your own environment option6. CC = g++7. CC_FLAG = -D_NOMNG -D_FILELINE8.9. #static library use 'ar' command10. AR = ar11.12. #set your inc and lib13. INC =14. LIB = -lpthread -L./ -lsvrtool15.16. #make target lib and relevant obj17. PRG = libsvrtool.a18. OBJ = Log.o19.20. #all target21. all:$(PRG)22. $(PRG):$(OBJ)23. ${AR} rv ${PRG} $?24.25. .SUFFIXES: .c .o .cpp26. .cpp.o:27. $(CC) $(CC_FLAG) $(INC) -c $*.cpp -o $*.o28.29. .PRONY:clean30. clean:31. @echo "Removing linked and compiled files......"32. rm -f $(OBJ) $(PRG)3、可执⾏程序[plain]1. ###########################################2. #Makefile for simple programs3. ###########################################4. INC=5. LIB= -lpthread6.7. CC=CC8. CC_FLAG=-Wall9.10. PRG=threadpooltest11. OBJ=CThreadManage.o CThreadPool.o CThread.o CWorkerThread.o threadpooltest.o12.13. $(PRG):$(OBJ)14. $(CC) $(INC) $(LIB) -o $@ $(OBJ)15.16. .SUFFIXES: .c .o .cpp17. .cpp.o:18. $(CC) $(CC_FLAG) $(INC) -c $*.cpp -o $*.o19.20. .PRONY:clean21. clean:22. @echo "Removing linked and compiled files......"23. rm -f $(OBJ) $(PRG)随机组合、举⼀反三会写出适合项⽬的makefile。
在linux下面,我们不得不自己写makefile,makefile的确博大精深,但是实际上对于日常的使用来说,无非就是
1:编译可执行程序。
2:编译lib库3:编译so库
本博针对上面三种目的各自写出了makefile模版,希望对大家有所帮助。
一.编译可执行程序
当前目录下制定文件编译成可执行文件(连接外部库的话只需要更改INC和LIB 即可)
二.编译成lib库
当前目录下指定文件编译成lib库(一般lib库在编译的时候不会将使用的外部库编译进来,而是等编译成可执行程序时或者.so时)
三.编译成so库
当前目录下指定文件编译成so库(必须将所有引用的外部库都编译进来)。