复杂多目录的Makefile模板及示例-转
大约一年多以前,还在移植u-boot,当时参考了u-boot的Makefile,做了一个多目录的Makefile模板。如今,一年过去了,本篇文章还是折腾Makefile模板,本人的水平由此可见一斑。当时的模板没有考虑很多东西,比如将源代码文件及目标文件分离。此次再写一个相对复杂的Makefile模板,自此之后,估计不想再折腾了。
本文的Makefile跟以往的模板一样,都是参考u-boot的做法(u-boot项目无论代码还是文件组织,都有很多值得学习的地方)。由下列文件组成:
1、配置文件config.mk,主要是编译器、编译选项、头文件路径、目标文件、源文件路径,等等;
2、依赖规则rules.mk,主要是产生depend文件,有了depend文件,当修改了头文件后,包含该头文件的源文件都会被重新编译。
3、主Makefile,或称为总Makefile,此文件调用其它目录的Makefile以及上述文件,以产生库及可执行文件。
4、子目录Makefile,各模块的Makefile,主要是生成静态库。
除子目录Makefile在各个模块目录中外,其它文件都在项目的当前目录。
Makefile模板应用场合及特点缺点说明如下:
1、头文件统一在include目录(或其它自定义的目录),子模块分布于各子目录,该目录的Makefile将模块编译成静态库,主代码(包括main函数及其它的代码)文件在独立目录,该目录的Makefile为总Makefile(或称主Makefile)。
2、修改头文件后,所有依赖该文件者均重新编译。
3、可指定编译后的文件所在目录,如不指定,则在原目录下生成目标文件(.o、.out文件)。指定方式如下:
1)、命令行:$ make O=../build
2)、$ export BUILD_DIR=../build ; make
3)、直接在主Makefile指定目录
4、自动识别编译C、C++文件。
下面分别解释一下各个文件
1、配置文件config.mk
模板如下:
#
# (C) Copyleft 2011
# Late Lee from http://www.latelee.org
#
# A simple file to specify compier and macros and flags
# and ways to compile .c & .cpp
#
# cross compile...
CROSS_COMPILE =
CC = $(CROSS_COMPILE)gcc
CXX = $(CROSS_COMPILE)g++
AR = $(CROSS_COMPILE)ar
ARFLAGS = cr
RM = -rm -rf
MAKE = make
CFLAGS = #-Wall
debug = y
ifeq ($(debug), y)
CFLAGS += -g
else
CFLAGS += -O2 -s
endif
DEFS =
CFLAGS += $(DEFS)
LDFLAGS = $(LIBS)
# include path here
INCDIRS = $(SRCTREE)/./include/
CFLAGS += -I$(INCDIRS)
###############################################################################
ifneq ($(OBJTREE),$(SRCTREE))
ifeq ($(CURDIR),$(SRCTREE))
dir :=
else
dir := $(subst $(SRCTREE)/,,$(CURDIR))
endif
obj := $(if $(dir),$(OBJTREE)/$(dir)/,$(OBJTREE)/)
src := $(if $(dir),$(SRCTREE)/$(dir)/,$(SRCTREE)/)
$(shell mkdir -p $(obj))
else
obj :=
src :=
endif
suffix = $(notdir $(CURDIR))
export suffix
# test of shell script
MKCONFIG := $(SRCTREE)/mkconfig
export MKCONFIG
# export to other Makefile
export CC
export CFLAGS
export INCDIRS
export AR
export ARFLAGS
export RM
###############################################################################
# make all .c or .cpp
$(obj)%.o: %.c
@echo "Compling: " $(addsuffix .c, $(basename $(notdir $@)))
@$(CC) $(CFLAGS) -c $< -o $@
$(obj)%.o: %.cpp
@echo "Compling: " $(addsuffix .cpp, $(basename $(notdir $@)))
@$(CXX) $(CFLAGS) -c $< -o $@
主要分3部分:
第一部分指定编译器及编译选项,可以选择交叉编译器,头文件路径由INCDIRS 宏指定,这里有的编译选项CFLAGS处理得不太好,比如debug版本及release版本是通过“-g”和“-O2 -s”来区别的,但这里是直接指定,并不能在make时指定。
第二部分指定了源代码目录及目标文件目录,这些目录由主Makefile给出,或者在make时给出。
第三部分是编译c或c++源代码的规则。
实际使用中,此文件需要根据实际情况修改编译器及编译选项。
2、依赖规则rules.mk
内容如下:
#
# (C) Copyleft 2011
# Late Lee from http://www.latelee.org
#
# A simple way to generate depend file(.depend) for .c & .cpp,
# so you change the head file, it will recompile the
# file(s) which include the head file.
#
_depend: $(obj).depend
$(obj).depend: $(SRCTREE)/config.mk $(SRC_C) $(SRC_CPP)
@rm -f $@
@for f in $(SRC_C); do \
g=`echo $$f | sed -e 's/\(.*\)\.\w/\1.o/'`; \
$(CC) -MM $(CFLAGS) -E -MQ $(obj)$$g $$f >> $@ ; \
done
@for f in $(SRC_CPP); do \
g=`echo $$f | sed -e 's/\(.*\)\...\w/\1.o/'`; \
$(CC) -MM $(CFLAGS) -E -MQ $(obj)$$g $$f >> $@ ; \
done
该文件主要是产生.depend依赖文件,依赖文件的作用在前面已经说过,此处不再提及。实际使用中,经文件无需修改。
3、主Makefile
内容如下:
#
# (C) Copyleft 2011
# Late Lee from http://www.latelee.org
#
# A simple Makefile for multi-directory
# Most idea comes from U-boot project
#
# object file directory, eg
# $ make O=../build
# $ export BUILD_DIR=../build ; make
# or modify BUILD_DIR here
ifdef O
ifeq ("$(origin O)", "command line")
BUILD_DIR := $(O)
endif
endif
ifneq ($(BUILD_DIR),)
saved-output := $(BUILD_DIR)
# Attempt to create a output directory.
$(shell [ -d ${BUILD_DIR} ] || mkdir -p ${BUILD_DIR})
# Verify if it was successful.
BUILD_DIR := $(shell cd $(BUILD_DIR) && /bin/pwd)
$(if $(BUILD_DIR),,$(error output directory "$(saved-output)" does not exist))
endif # ifneq ($(BUILD_DIR),)
OBJTREE := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))
SRCTREE := $(CURDIR)
TOPDIR := $(SRCTREE)
LNDIR := $(OBJTREE)
export TOPDIR SRCTREE OBJTREE
export TOPDIR SRCTREE OBJTREE
include $(TOPDIR)/config.mk
###############################################################################
# libs
### your libs here
LIBS :=
LIBS := $(addprefix $(obj),$(LIBS))
LDFLAGS = $(LIBS)
# source file(s), including c file(s) cpp file(s)
# you can also use $(wildcard *.c), etc.
### main source here
MAIN_DIR = #main/
SRC_C :=
SRC_CPP := $(wildcard $(MAIN_DIR)*.cpp)
$(if $(MAIN_DIR), $(shell mkdir -p $(addprefix $(obj),$(MAIN_DIR))),)
# object file(s)
OBJ_C := $(addprefix $(obj),$(patsubst %.c,%.o,$(SRC_C)))
OBJ_CPP := $(addprefix $(obj),$(patsubst %.cpp,%.o,$(SRC_CPP)))
# executable file here
target = $(obj)a.out
###############################################################################
all: config $(target)
config:
@echo "Generating... hello.h"
@$(MKCONFIG)
$(target): $(LIBS) exe
exe: $(OBJ_CPP)
@echo "Generating executable file..." $(notdir $(target))
@$(CXX) $(CFLAGS) $(OBJ_CPP) -o $(target) $(LIBS)
$(LIBS):
$(MAKE) -C $(dir $(subst $(obj),,$@))
clean:
@echo "cleaning..."
@$(RM) $(target)
@$(RM) hello.h
@find $(OBJTREE) -type f \
\( -name 'core' -o -name '*.bak' -o -name '*~' \
-o -name '*.o' -o -name '*.a' -o -name '*.exe' -o -name '.depend' \) -print \
| xargs rm -f
distclean:
@echo "distcleaning..."
@$(RM) $(target)
@$(RM) hello.h
@find $(OBJTREE) -type f \
\( -name 'core' -o -name '*.bak' -o -name '*~' \
-o -name '*.o' -o -name '*.a' -o -name '*.exe' -o -name '.depend' \) -print \
| xargs rm -f
@$(RM) $(obj)
.PHONY: all clean distclean $(LIBS) exe
该文件也可分为三部分。第一部分指定源代码目录及目标文件目录,第二部分指定了工程所需的静态库以及主代码所在目录,第三部分编译规则,包括make all,make clean,等等命令的规则。实际使用中,需要根据实际情况添加子模块静态库名称、主代码名称。
4、子目录Makefile
内容如下:
#
# (C) Copyleft 2011
# Late Lee from http://www.latelee.org
#
# A simple Makefile for lib(libxxx.a)
# You just need to change library name and source file(s)
#
include $(TOPDIR)/config.mk
# here you can set your own flags
CFLAGS += # -D_A_
# static library name
LIB = # $(obj)libfoo.a
# source file(s), including c file(s) cpp file(s)
# you can also use $(wildcard *.c), etc.
SRC_C := # foo.c
SRC_CPP :=
# object file(s)
OBJ_C := $(addprefix $(obj),$(patsubst %.c,%.o,$(SRC_C)))
OBJ_CPP := $(addprefix $(obj),$(patsubst %.cpp,%.o,$(SRC_CPP)))
all: $(obj).depend $(LIB)
$(LIB): $(OBJ_C) $(OBJ_CPP)
@echo "Generating static library: " $(notdir $@)
@$(AR) $(ARFLAGS) $@ $^
clean:
@echo "Cleaning..."
@$(RM) $(OBJ_C) $(OBJ_CPP) $(LIB) *.bak *~ *.d *.o $(obj).depend
.PHONY: all clean
#########################################################################
include $(TOPDIR)/rules.mk
sinclude $(obj).depend
#########################################################################
子目录的Makefile比较简单,因为编译配置及depend文件都在其它文件中,这里直接包含进来即可。
实际使用中,需要修改的地方有:
1、配置文件config.mk,指定头文件路径,编译选项,额外库,等等。
2、主Makefile,指定各子模块的库名称及生成可执行文件名称
3、子Makefile,指定静态库名称即可,每一个模块目录都需要一个Makefile。
文中的Makefile模板,远远不如IDE方便,因此,用与不用,则仁者见仁了。
本文语法着色由迟思堂工作室提供高亮工具手工完成。
本文所涉及的Makefile模块及示例压缩包:coming soon...
复杂多目录的Makefile模板及示例-转相关推荐
- 复杂多目录的Makefile模板及示例
大约一年多以前,还在移植u-boot,当时参考了u-boot的Makefile,做了一个多目录的Makefile模板.如今,一年过去了,本篇文章还是折腾Makefile模板,本人的水平由此可见一斑.当 ...
- GNU/Linux智能Makefile模板(多目录,多文件)
本文提供一个在GNU/Linux环境下通用的智能Makefile模板,用户可以将其引入到自己的工程当中.即使用户对此 Makefile的工作原理不甚了解,但是只需要修改少数几个关键变量,就可以满足不同 ...
- 关于中型工程的Makefile模板
我们定义的中型工程 可能会有多层嵌套的源代码文件夹 一个源代码文件夹下可能有多个源代码子文件夹 中间文件应当在其源文件所在目录生成,而不是同一生成到一个目录下(如统一生成到obj目录下) (大多数情况 ...
- 一个适用各类场合的Makefile模板
1.写在前面 对于Windows下开发,很多IDE都集成了编译器,如Visual Studio,提供了"一键编译",编码完成后只需一个操作即可完成编译.链接.生成目标文件.Linu ...
- 一个STM32编译Makefile模板
最近突然对STM32感兴趣,研究了一下.STM32的编译方式非常多,由于一直对gcc情有独钟,所以还是喜欢使用Makefile+gcc编译的方法.当时从51单片机转向AVR单片机开发时,也是通过这种方 ...
- Makefile模板的继续改进
layout: post title: category : linux系统 tags : [Makefile] 上一文章的Makefile,存在一个比较大的问题,那就是生成可执行的二进制文件时,会链 ...
- 一个使用多年的Makefile模板
layout: post title: category : linux系统 tags : [Makefile] 许久以前,一直使用自己总结的Makefile模板,这个模板也是基于现有资料整理而成的. ...
- 通用Makefile模板
#################################################################################################### ...
- 万能 Makefile 模板
在 Linux 编程时,对于很多小工程来说,很多时候似乎没有必要用 autoconf 和 automake 工具来生成 Makefile,反而自己写一个 Makefile 更省事.这里给大家提供一个简 ...
最新文章
- oracle schedule stop,Oracle调度Schedule特性(第八部分)-Windows和Window Groups
- 新BOJ 88. 最值问题
- 决策树(CART算法)针对中文文本分类
- 一道大题决定去留:为什么synchronized无法禁止指令重排,却能保证有序性?
- leetcode 1185 python
- 电脑字体在哪个文件夹_壹心奇妙体下载 壹心奇妙体 字体下载
- solaris常用系统命令
- 最新北京人才公寓申请流程,技术员的福利~
- 云原生IDE:iVX首个通用且强大无代码开发平台
- 在浏览器上打开、预览Excel xlsx表格文件
- 2016年11月整理的最新php免杀一句话木马, 2017php免杀一句话(php过狗一句话,过狗菜刀,2016过狗一句话,2016php免杀一句话,php过waf一句话)
- 传说之下三重审判用计算机怎么弹,传说之下三重审判无限血
- Ubuntu系统迁移至固态硬盘(生产环境勿用)
- Dessert Café
- 华东师大在职计算机分数线,关于在职研究生华东师范大学分数线的详细介绍!...
- html文件无法找到,html文件无法打开
- 终于鼓起勇气,辞掉了第一份工作
- stream流的使用说明书
- 《春夜洛城闻笛 / 春夜洛阳城闻笛》古诗鉴赏
- ddos攻击的简单应急处理办法
热门文章
- 对象可以创建数组吗_电脑零基础可以学习创建网站吗?
- Android 屏幕(View)坐标系统
- Android studio for mac
- 听听【八年阿里架构师】怎样讲述Dubbo和Spring Cloud微服务架构
- 附加数据库后登陆报错
- 《基于MFC的OpenGL编程》Part 18 Reading objects from the OBJ File Format
- iOS WKWebView和JS交互的两种方式
- 【CF】304 E. Soldier and Traveling
- 国产平板面临变局挑战,谁能撑起民族大旗?
- 索要ValidateTextBox控件Source Code的朋友rickel****@gmail.com,邮件退回了。各位,与我通信,请不要使用GMAIL,烦。...