首页 > 学技术 > 技术网文 > C/C++ > 正文

[原创] 【30日更新】Makefile(用于多目录 源代码 编译)-56楼提供最新版本下载


来源 chinaunix.net kuqin整理



SHELL=/bin/sh
CC=gcc
CXX=g++
MAKE=make
..........
rebuild: clean all
cleanall:
rm -f $(OBJ_DIR)*
rm -f $(RELEASE_DIR)*
rm -f $(DEBUG_DIR)*
test:
$(OUT)
.PHONY: all






建议看56楼最新版本,这里的没有那个好,删掉了
http://bbs.chinaunix.net/viewthread.php?tid=909275&pid=6620665&page=6&extra=#pid6620665

[ 本帖最后由 net_robber 于 2007-3-30 16:58 编辑 ]



 net_robber 回复于:2007-03-14 13:28:01


all: $(OUT)
$(OUT): $(OBJ_FILES)
        $(CC) $^ -o $@
$(OBJ_DIR)%.o:$(SRC_DIR)%.c
        $(CC) $(FLAG_COMPLE) $< -o $@




这几行是关键行,用于目录规则设置


 net_robber 回复于:2007-03-14 13:29:22

对比以前精华里面的那个通用Makefile

我这个主要是提供“多目录”解决方案




PS:不断完善中


 flw 回复于:2007-03-14 13:39:43

恭喜楼主脱胎换骨!
看来一个人长大只是一瞬间的事~


 net_robber 回复于:2007-03-14 13:42:55

谢谢

永远学习,希望自己能够成为高手,呵呵


 emacsnw 回复于:2007-03-14 15:09:11

又是一个通用Makefile,支持一下。


 net_robber 回复于:2007-03-14 15:27:14

这里 顺带 提一个问题:

我学习Makefile的时候没有拿到第一手的资料

只有网上一个晦涩难解,并且翻译的不很准确的 中文版手册<GNU Make 使用手册>

man make不是我要的
man makefile没有结果

请问各位是从哪里弄的第一手资料???


我当前正在看
http://www.gnu.org/software/make/manual/make.html


 mingyanguo 回复于:2007-03-14 15:41:56

info make 呢?


 net_robber 回复于:2007-03-14 15:56:32

效果不错,^_^

谢谢


 ericz 回复于:2007-03-15 09:15:55

如果某个.c包含的.h文件内容发生变化呢?


 net_robber 回复于:2007-03-15 09:17:14

问的好。


晚上修改一下。现在工作,看书,学习!

呵呵


 exir 回复于:2007-03-15 12:45:05

$(TARGET): $(OBJ) $(OBJ_O)
$(CC) -I ../include -o $@ $^

-include $(DEPS)

%.d: %.c
$(CC) -I ../include -MM -MD $<

%.o: %.c %.d
$(CC) $(CFLAGS) -I ../include $< -o $@


 中国大表哥 回复于:2007-03-15 13:46:02

引用:原帖由 flw 于 2007-3-14 13:39 发表
恭喜楼主脱胎换骨!
看来一个人长大只是一瞬间的事~ 



。。。。。。


 飞灰橙 回复于:2007-03-15 13:50:45

Makefile里如何正确处理带空格的文件名?


 net_robber 回复于:2007-03-15 14:33:11

引用:原帖由 exir 于 2007-3-15 12:45 发表
$(TARGET): $(OBJ) $(OBJ_O)
$(CC) -I ../include -o $@ $^

-include $(DEPS)

%.d: %.c
$(CC) -I ../include -MM -MD $<

%.o: %.c %.d
$(CC) $(CFLAGS) -I ../include $< -o $@ 


十分感谢,已经处理完毕


 net_robber 回复于:2007-03-15 14:35:12

最新修改如下:



all: $(OUT)
$(OUT): $(OBJ_FILES)
$(CC) $^ -o $@
$(OBJ_DIR)%.o:$(SRC_DIR)%.c $(OBJ_DIR)%.d
$(CC) $(FLAG_COMPLE) $< -o $@
$(OBJ_DIR)%.d:$(SRC_DIR)%.c
$(CC) $< -MM -o $@



 net_robber 回复于:2007-03-15 14:37:39

最新版本上传

Makefile-0.2.0.tar.gz


 net_robber 回复于:2007-03-15 14:39:29

引用:原帖由 飞灰橙 于 2007-3-15 13:50 发表
Makefile里如何正确处理带空格的文件名? 


这个似乎没有办法处理

代空格的文件,不知道在列出文件名的时候,用Shell列出,是否可行


反正用wildcard 肯定不行


 net_robber 回复于:2007-03-15 14:41:05

刚刚测试了一下不管事find还是ls都不能在返回的字符串带上"\"


似乎没有办法了


 converse 回复于:2007-03-15 15:15:31

大概看了以下,LZ你的makefile比起whyglinux的可配置性差了一些....很多地方都是写死的,比如编译器,比如文件后缀....


 net_robber 回复于:2007-03-15 15:30:15

是的

都是写死的

用的时候需要大量修改。


主要解决了一个问题

源文件和Makefile不在同一目录


 soul_of_moon 回复于:2007-03-15 15:37:00

引用:原帖由 net_robber 于 2007-3-15 15:30 发表
是的

都是写死的

用的时候需要大量修改。


主要解决了一个问题

源文件和Makefile不在同一目录 


但是源文件都在同一目录下。所以,路过


 net_robber 回复于:2007-03-15 15:41:09

其实还解决了一个问题

我得Makefile原来执行起来和Shell没有区别,

不会进行文件更新检查,呵呵


现在会了



然后就是今天学会了Include的头文件依赖检查


 soul_of_moon 回复于:2007-03-15 15:46:15

引用:原帖由 net_robber 于 2007-3-15 15:41 发表
其实还解决了一个问题

我得Makefile原来执行起来和Shell没有区别,

不会进行文件更新检查,呵呵


现在会了



然后就是今天学会了Include的头文件依赖检查 


这个不是把头文件也加到依赖文件中么?


 net_robber 回复于:2007-03-15 15:55:42

这个也是一种方法


特别是我原来那Makefile当Shell写的时候,也是这样。呵呵


 wolfkin 回复于:2007-03-15 15:56:35

为什么不用 autotools 呢!

写一点模板,简单几条命令就可以生成所需要的文件了,并且具有很高的可移植性。

只是这个工具很有点难学,我也是好多都还没有搞定,初识门径而已。


 shanan 回复于:2007-03-15 16:03:43

不错的东西


 net_robber 回复于:2007-03-15 16:05:41

一定要学的,呵呵。

一个一个的来么

学以致玩。

大家玩的高兴。呵呵!


 iwolcbao 回复于:2007-03-15 16:55:16

没有用过,在linux都用简单文件编译方式,没有楼主强,没有用到跨目录的,
还是顶一下,支持楼主!


 exir 回复于:2007-03-15 22:47:38

auto工具对于交叉编译好像没什么用
还有就是带空格的文件名和路径用""括起了就行了。
曾在win下用win版gcc做arm平台交叉编译,program file这个目录带个空格,真是烦死了。
这么重要的目录用这么挫的一个名字,既带空格又不简洁。
还是*nix好。


 net_robber 回复于:2007-03-15 22:49:54

引用:原帖由 exir 于 2007-3-15 22:47 发表
 ... 
还有就是带空格的文件名和路径用""括起了就行了。
 ... 


记下了,呵呵


 yanweihao 回复于:2007-03-16 11:40:09

CODE:
[Copy to clipboard]
不要完全否定中国的教育制度!
它在扼杀一部分天才的同时,减少了更多废物的出现。
至少,每一个人都有学到了一些可用的知识。

yanweihao 说粗话被严重警告+禁言。
--by converse

[ 本帖最后由 converse 于 2007-3-22 23:11 编辑 ]


 crackpot 回复于:2007-03-16 15:55:20

"多目录 源代码 编译"这个名字似乎和你写的makefile做的不是一件事情吧
在大的项目中源代码肯定是多目录的,通常需要每个目录下写一个makefile,然后在上级目录的makefile中运行下一级目录的make,按照顺序完成每个子目录的编译
这样,只需要一个make,就能完成整个项目的编译,很多开源的项目都是这样的,楼主找个开源的项目代码看看他们的makefile
这是openldap的makefile的一部分,应该能说明点问题:

all-common: FORCE
        @echo "Making all in `$(PWD)`"
        @for i in $(SUBDIRS) $(ALLDIRS); do             \
                echo "  Entering subdirectory $$i";             \
                ( cd $$i; $(MAKE) $(MFLAGS) all );              \
                if test $$? != 0 ; then exit 1; fi ;    \
                echo " ";                                                               \
        done


 net_robber 回复于:2007-03-16 16:26:00

Makefile、.h文件、.c文件、.o文件等等,有时候还有很多其他文件,都放在一个目录下,看着不乱么???

分目录管理一下,归归类,就比较舒服了


然后,各种文件不在同一目录下,

编译连接就需要手动指定路径。

我这个是希望使用通配符的方法,方便Makefile编写

这样可以体现Makefile的优势,

不然还不如用SHELL


 cookis 回复于:2007-03-19 14:14:50


$(OBJ_DIR)%.o:$(SRC_DIR)%.c $(OBJ_DIR)%.d
$(CC) $(FLAG_COMPLE) $< -o $@
$(OBJ_DIR)%.d:$(SRC_DIR)%.c
$(CC) $< -MM -o $@

上边 %.d这个依赖是不是有点儿多余啊.


$(OBJ_DIR)%.o:$(SRC_DIR)%.c
           $(CC) $(FLAG_COMPLE) $< -o $@

这样不就够了吗.


 net_robber 回复于:2007-03-19 14:35:30

不可以

那个是检查依赖用的


 cookis 回复于:2007-03-19 14:41:32

GCC会自动推导的...


 net_robber 回复于:2007-03-19 14:45:02

168那个机器的不会,我测试过了,必须手动的

可能和版本有关吧

我再测试一下


 I/0 回复于:2007-03-20 09:33:17

我昨天测试了一下17楼的那个, 不能正确处理头文件依赖
需要加上:
DEPS = $(OBJS:.o=.d)  # 这个只用于当前目录
-include $(DEPS)

我机器: FreeBSD 6.2,  GNU Make 3.81

[ 本帖最后由 I/0 于 2007-3-20 09:36 编辑 ]


 net_robber 回复于:2007-03-20 09:51:13

能不能给出你的测试 过程

详细一点,

(建议使用此Makefile时, make dir 创建需要的目录结构)

我看一下,以便修改Bug

呵呵


 I/0 回复于:2007-03-20 17:57:04

我先 gmake dir 生成目录, 然后在 src/ 下建了三文件: a.h a.c main.c
deps:
a.c: a.h
main.c: a.h

以下是测试结果:

$ gmake
gcc src/a.c -MM -o obj/a.d
gcc -c -g src/a.c -o obj/a.o
gcc src/main.c -MM -o obj/main.d
gcc -c -g src/main.c -o obj/main.o
gcc obj/a.o obj/main.o -o debug/out
rm obj/a.d obj/main.d

$ touch src/a.h

$ gmake
gmake: Nothing to be done for `all'.


 net_robber 回复于:2007-03-20 18:07:44

引用:原帖由 I/0 于 2007-3-20 17:57 发表
我先 gmake dir 生成目录, 然后在 src/ 下建了三文件: a.h a.c main.c
deps:
a.c: a.h
main.c: a.h

以下是测试结果:

$ gmake
gcc src/a.c -MM -o obj/a.d
gcc -c -g src/a.c -o obj/a.o
gcc src/main ... 




是这样的,依赖关系不是靠名字相同检查的

要求.c文件中,有include  .h文件,才会出现依赖

也就是说。你要在a.c Includ a.h


 I/0 回复于:2007-03-21 08:59:24

引用:原帖由 net_robber 于 2007-3-20 18:07 发表



是这样的,依赖关系不是靠名字相同检查的

要求.c文件中,有include  .h文件,才会出现依赖

也就是说。你要在a.c Includ a.h 



呵呵, 我是嫌帖那几个文件的源码太长才简单地用 deps: a.c: a.h  main.c a.h 描述了一下include关系,
a.c 和 main.c 里面都有 include "a.h"


 net_robber 回复于:2007-03-21 11:32:46

确实有问题


正在研究。

请稍后


 wangyl1982 回复于:2007-03-21 13:39:23

不错,楼主能不能花点时间解释一下每行,让我只懂一点的人,用你这个,也知其所以然.


 net_robber 回复于:2007-03-21 15:15:30

先不解释

还有点问题


 net_robber 回复于:2007-03-22 17:51:22

已经找到不能正确检查头文件依赖的原因了

因为gcc自动生成的依赖规则中,目标文件并没有加入路径。

因此,他没有按照预期的规则进行检查、编译


 net_robber 回复于:2007-03-22 18:09:16


# Readme:
# use: make config
# use: make dir
# use: make
# use: make clean
# use: make rebuild
# use: make cleanall
# use: make test
# use: make

# firs of all, use "make config" or "make dir" to 
# build a source files struct. and then,
# put your source files into the DIR src
# link libs to the DIR lib


SHELL=/bin/sh
CC=gcc
CXX=g++
MAKE=make
MAKE_DIR=$(PWD)
SRC_DIR=$(MAKE_DIR)/src/
OBJ_DIR=$(MAKE_DIR)/obj/
LIB_DIR=$(MAKE_DIR)/lib/
DEBUG_DIR=$(MAKE_DIR)/debug/
RELEASE_DIR=$(MAKE_DIR)/release/
OUTPUT_DIR=
LIB=-L$(MAKE_DIR)/lib/
OUTPUT_FILE=out
OUT=

vpath %.c $(SRC_DIR)
#vpath %.o $(OBJ_DIR)
vpath %.d $(OBJ_DIR)



DEBUG=1

SRC_FILES:=$(wildcard $(SRC_DIR)*.c)
SRC_FILES:=$(notdir $(SRC_FILES))
OBJ_FILES:=$(patsubst %.c,%.o,$(SRC_FILES) ) 
DEP_FILES:=$(patsubst %.c,%.d,$(SRC_FILES) ) 

#SRC_FILES:=$(addprefix $(SRC_DIR),$(SRC_FILES))
#OBJ_FILES:=$(addprefix $(OBJ_DIR),$(OBJ_FILES))
DEP_FILES:=$(addprefix $(OBJ_DIR),$(DEP_FILES))

FLAG_DEBUG=-g
FLAG_COMPLE=-c
FLAG_LINK=

ifeq ($(DEBUG),1)
OUTPUT_DIR:=$(DEBUG_DIR)
FLAG_COMPLE:=$(FLAG_COMPLE) $(FLAG_DEBUG)
FLAG_LINK:=
else
OUTPUT_DIR:=$(RELEASE_DIR)
FLAG_COMPLE:=$(FLAG_COMPLE)
FLAG_LINK:=
endif

OUT=$(OUTPUT_DIR)$(OUTPUT_FILE)

$(OUT): $(OBJ_FILES)
@echo 1
@$(CC) $^ -o $@
%.o:%.c %.d
@echo 2.1
@$(CC) $(FLAG_COMPLE) $< -o $@
$(OBJ_DIR)%.d:%.c
@echo 3
@$(CC) $< -MM -MD -o $@
# if the system-libs will always update, please ues this instead for
# $(CC) $< -M -o $@
-include $(DEP_FILES)
config: dir
dir:
mkdir -p $(SRC_DIR)
mkdir -p $(OBJ_DIR)
mkdir -p $(LIB_DIR)
mkdir -p $(DEBUG_DIR)
mkdir -p $(RELEASE_DIR)
clean:
rm -f $(OBJ_DIR)* *.d *.o
rm -f $(OUT)
clear
rebuild: clean all
cleanall:
rm -f $(OBJ_DIR)*
rm -f $(RELEASE_DIR)*
rm -f $(DEBUG_DIR)*
test:
$(OUT)
.PHONY: all config rebuild
#.SUFFIXES:




 net_robber 回复于:2007-03-22 18:10:31

48楼为最新更新

能够检查头文件的依赖关系了。

但是,没能将 .o  文件分离到单独的目录


原因在47楼


 net_robber 回复于:2007-03-22 18:13:00

如果大家还有什么良策妙极,欢迎讨论


 I/0 回复于:2007-03-22 21:21:04

呵呵, 我也是前几天刚开始学写 Makefile, 不过现在正忙着在win下搞毕设, 等有空再来慢慢研究.


 net_robber 回复于:2007-03-27 12:06:17

最新更新

完全解决多目录编译

实现源文件与目标文件的分目录存储

解决依赖关系检查问题

Makefile-0.4.0.tar.gz


 net_robber 回复于:2007-03-27 12:06:50

这次是比较完美的版本了


呵呵,可以暂时休息一下了


 net_robber 回复于:2007-03-27 13:09:44

部分主要内容




vpath %.c $(SRC_DIR)
vpath %.o $(OBJ_DIR)
vpath %.d $(OBJ_DIR)


$(OUT): $(OBJ_FILES)
@$(CC) $(addprefix $(OBJ_DIR),$(notdir $^))  -o $@
%.o:%.c %.d
@$(CC) $(FLAG_COMPLE) $< $ -o $(OBJ_DIR)$@
$(OBJ_DIR)%.d:%.c
@$(CC) $<  -MM -MD -o $@
-include $(addprefix $(OBJ_DIR),$(DEP_FILES))


说明:

vpath指定默认搜索路径

然后使用规则进行编译

include导入依赖关系


 net_robber 回复于:2007-03-30 16:54:26

更新说明:

最新版本增加功能如下:
    增加执行每个子目录下Makefile的 clean 目标

相关代码如下:



GlobalClean:
        @find . -type f -name "Makefile" |sed -n '2,$$p'|sed s/Makefile/\ \`pwd\`/g|awk ' {ECHO="echo"};{CD="cd "};{MAKE="&& make clean&&"};{print ECHO,CD,$$1,MAKE,CD,$$2 } ' |sh



 net_robber 回复于:2007-03-30 16:57:04

下载连接见下

Makefile-0.4.5.tar.gz


 j1j1h1 回复于:2007-04-24 10:37:47

我下载了makefile

感觉修改了.h文件后,.c文件还是不自动编译啊

.o 依赖于.c和.d

.d 依赖于.c

如果在.h中加几个空格. .d是不会发生变化的,.c也不会发生变化
那么.o 怎么会重新编译呢?
:em14:


 zhufu 回复于:2007-05-28 22:12:52

顶一个


 net_robber 回复于:2007-05-29 09:09:47

引用:原帖由 j1j1h1 于 2007-4-24 10:37 发表
我下载了makefile

感觉修改了.h文件后,.c文件还是不自动编译啊

.o 依赖于.c和.d

.d 依赖于.c

如果在.h中加几个空格. .d是不会发生变化的,.c也不会发生变化
那么.o 怎么会重新编译呢?
:em14: 




这一行

-include $(addprefix $(OBJ_DIR),$(DEP_FILES))

导入的依赖关系中
会有
类似
.o:.h

这样的代码。
这样保证了.h文件改编后,以其为依赖的.o会被重新编译。
编译命令由

.o:.c

定义

如果方便,请贴出你的编译过程和你使用的Makefile




原文链接:http://bbs.chinaunix.net/viewthread.php?tid=909275
转载请注明作者名及原文出处



收藏本页到: