我怎样才能使我的Makefiles更好? [英] How can I make my Makefiles better?

查看:116
本文介绍了我怎样才能使我的Makefiles更好?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图学习项目的最佳实践makefile。



请检查下面的Makefile文件,并提出改进以加强它。



目录布局:

  root dir 
- Makefile
deps
--- deps
bin
---二进制
objs
---全部.o文件
包括
---全部.h文件
src
- - 所有.c .cc文件

makefile:

 
#通用makefile


全部:tengine test2


#包含用于编译的文件以及用于链接的库。


INC = -I / usr / include -I / usr / local / include -I / usr / include / hiredis

LIB = -lhiredis


#调试还是不调试?


DEBUG = 1

ifdef DEBUG
CFLAGS = -Wall -Winline -pipe -g -DDEBUG#-pedantic -pg
else
CFLAGS = -Wall -Winline -pipe -O3 -march = native -funroll-all-loops \
-finline-functions#-pedantic
endif

#CXXFLAGS = $(CFLAGS)


#创建依赖文件的规则

deps /%。d:src /%。cc
@echo生成$ @
@mkdir -p $(dir $ @)
$(CXX)$(CXXFLAGS)$(INC)-MM -MT'$(patsubst src /%,obj /% ,%(patsubst%.cc,%。o,$<))'$< > $ @

deps /%。d:src /%。c
@echo生成$ @
@mkdir -p $(dir $ @)
$( CXX)$(CXXFLAGS)$(INC)-MM -MT'$(patsubst src /%,obj /%,%(patsubst%.c,%。o,$<))'$< > $ @


#编译规则

#含源头和无c ++代码的C源

obj /%o: src /%。c src /%。h deps /%。d
@echo编译$ @
@mkdir -p $(dir $ @)
$(CC)$(CFLAGS) $(INC)-o $ @ -c $<

#带源头的C ++源代码。

obj /%。o:src /%。cc src /%。h deps /%。d
@echo编译$ @
@mkdir -p $(dir $ @)
$(CXX)$(CXXFLAGS)$(INC)-o $ @ -c $<

没有头文件但没有c ++代码的C源代码

obj /%。o:src /%。c deps /%。d
@echo编译$ @
@mkdir -p $(dir $ @)
$(CC)$(CFLAGS)$(INC)-o $ @ -c $<

#无标题的C ++源代码。

obj /%。o:src /%。cc deps /%。d
@echo编译$ @
@mkdir -p $(dir $ @)
$(CXX)$(CXXFLAGS)$(INC)-o $ @ -c $<

########################################## #####################

#TARGET:tengine

####### ################################################## ######

OBJS = obj / main.o obj / tengine.o

tengine:$(OBJS)
$(CXX) - 管道$(CXXFLAGS)-o bin / tengine $(OBJS)$(LIB)

######################### ######################################

#TARGET: test2

######################################## #######################

OBJS = obj / main.o obj / test2.o

测试2:$(O​​BJS)
$(CXX) - 管道$(CXXFLAGS)-o bin / test2 $(OBJS)$(LIB)

######## ################################################## #####

#清理

######################### ######################################

clean:
rm -f * bin / * obj / * deps / * src / *〜gmon.out

help:

@echo
@ echomake-builds tengine
@echomake test2 - builds test2
@ech omake all - builds tengine test2
@echomake clean - 删除以前的版本


解决方案

下面是一个修改后的makefile的建议,在一个7年的Linux版本(RHEL 5)上稍微测试过:

 #通用makefile 

TARGETS = tengine test2
$ b全部:$ {TARGETS}

帮助:
@echo
@echomake-builds $ {TARGETS}
@echomake tengine - builds tengine
@echomake test2 - builds test2
@echomake clean - 删除以前的版本
@echomake help - 打印此帮助

#开关:

INC = - I / usr / include / hiredis
LIB = -lhiredis
SUBDIRS = obj deps bin
LNK = gcc -g -Wl, - warn-common
DEBUG = 1

ifdef DEBUG
CFLAGS = -Wall -Winline -pipe -g -DDEBUG#-pedantic -pg
else
CFLAGS = -Wall -Winline -pipe -O3 -march = native -funroll-all-loops \
-finline-functions#-pedantic
endif

#CXXFLAGS = $(CFLAGS)

#通用规则:

obj /%。o:src /%。c
@echo编译$ @
@mkdir -p $(SUBDIRS)
$(CC)$(CFLAGS)$(INC )-MMD -MF'$(patsubst src /%。c,deps /%。d,$<)'-o $ @ -c $<

obj /%。o:src /%。cc
@echo编译$ @
@mkdir -p $(SUBDIRS)
$(CXX)$( CXXFLAGS)$(INC)-MMD -MF'$(patsubst src /%。c,deps /%。d,$<)'-o $ @ -c $<

$ {TARGETS}:%:bin /%

#特定目标规则:

in / tengine:obj / main.o obj / tengine.o
$(LNK)$ ^ $(LIB)-o $ @

bin / test2:obj / main.o obj / test2.o
$(LNK )$ ^ $(LIB)-o $ @

clean:
rm -f *〜src / *〜gmon.out
rm -fr $(SUBDIRS)

-include deps / *。d

一些注释:




  • 原始文件的一个关键问题是生成了依赖关系,但没有使用 。已经使用 -include deps / *。d (最后)修正了这个问题。


  • 现在使用deps / *。d时,makefile不需要具有 src /%。h 个案。


  • 原始文件也将垃圾放入这些文件中: $(patsubst src /%,obj /%,%(patsubst%.cc,%。o,$<)) 第三个应该是 $


  • 在修订版本中,使用 -MMD 与对象同时生成依赖关系。

  • 缩短 INC :为什么麻烦包括标准系统包括目录?实际上,gcc显然会忽略你的 -I / usr / include -I / usr / local / include


  • 删除了 两个 OBJS 的不同定义。不需要,可能会令人困惑。使用 $ ^ 代替。

  • 对于 make干净的完全地撤消所有的make,所以你留下了你开始的东西。但是子目录obj /和deps /正在被创建,并且从未被删除。

  • 对于链接,添加 $(LNK) LNK = gcc -g -Wl, - warn-common (但你可能不需要警告)。 AFAIK,所有其他通常的 $(CFLAGS)都会被链接忽略。

  • 删除评论
  • 重复执行两次 make; make 现在给出 make:没有事情要做...




另见为不同输出目录生成gcc依赖项


I've trying to learn the "best practice" makefile's for a project.

Please review my Makefile file below and suggest changes to enhance it.

The dir layout:

root dir
---  Makefile
deps
---  deps
bin
---  binary
objs
---  all .o files
include
---  all .h files
src
---  all .c .cc files

The makefile:

#
# Generic makefile
#

all: tengine test2

#
# Include files for compiling, and libraries for linking.
#

INC=-I /usr/include -I /usr/local/include -I /usr/include/hiredis

LIB=-lhiredis

#
# Debug or not debug?
#

DEBUG=1

ifdef DEBUG
    CFLAGS=-Wall -Winline -pipe -g -DDEBUG #-pedantic -pg 
else
    CFLAGS=-Wall -Winline -pipe -O3 -march=native -funroll-all-loops \
           -finline-functions #-pedantic 
endif

#CXXFLAGS=$(CFLAGS)


# Rules for creating dependency files

deps/%.d: src/%.cc
    @echo Generating $@
    @mkdir -p $(dir $@)
    $(CXX) $(CXXFLAGS) $(INC) -MM -MT '$(patsubst src/%,obj/%,%(patsubst %.cc,%.o,$<))' $< > $@

deps/%.d: src/%.c
    @echo Generating $@
    @mkdir -p $(dir $@)
    $(CXX) $(CXXFLAGS) $(INC) -MM -MT '$(patsubst src/%,obj/%,%(patsubst %.c,%.o,$<))' $< > $@


# Rules for compilation
#
# C source with header and no c++ code

obj/%.o: src/%.c src/%.h deps/%.d
    @echo Compiling $@
    @mkdir -p $(dir $@)
    $(CC) $(CFLAGS) $(INC) -o $@ -c $<

# C++ source with header.

obj/%.o: src/%.cc src/%.h deps/%.d 
    @echo Compiling $@
    @mkdir -p $(dir $@)
    $(CXX) $(CXXFLAGS) $(INC) -o $@ -c $<

# C source without header and no c++ code

obj/%.o: src/%.c deps/%.d
    @echo Compiling $@
    @mkdir -p $(dir $@)
    $(CC) $(CFLAGS) $(INC) -o $@ -c $<

# C++ source without header.

obj/%.o: src/%.cc deps/%.d 
    @echo Compiling $@
    @mkdir -p $(dir $@)
    $(CXX) $(CXXFLAGS) $(INC) -o $@ -c $<

# ##############################################################
#
# TARGET: tengine
#
# ##############################################################

OBJS= obj/main.o obj/tengine.o 

tengine: $(OBJS)
    $(CXX) -pipe $(CXXFLAGS) -o bin/tengine $(OBJS) $(LIB)

# ##############################################################
#
# TARGET: test2
#
# ##############################################################

OBJS= obj/main.o obj/test2.o 

test2: $(OBJS)
    $(CXX) -pipe $(CXXFLAGS) -o bin/test2 $(OBJS) $(LIB)

# ##############################################################
#
# Cleanup
#
# ##############################################################

clean:
    rm -f *~ bin/* obj/* deps/* src/*~ gmon.out

help:

@echo ""
@echo "make     - builds tengine"
@echo "make test2   - builds test2"
@echo "make all     - builds tengine test2"
@echo "make clean   - deletes prior build"

解决方案

Here is a suggestion for a revised makefile, tested slightly on a 7-year-old version of Linux (RHEL 5):

# Generic makefile

TARGETS=tengine test2

all: ${TARGETS}

help:
        @echo ""
        @echo "make         - builds ${TARGETS}"
        @echo "make tengine - builds tengine"
        @echo "make test2   - builds test2"
        @echo "make clean   - deletes prior build"
        @echo "make help    - prints this help"

# Switches:

INC=-I/usr/include/hiredis
LIB=-lhiredis
SUBDIRS=obj deps bin
LNK=gcc -g -Wl,--warn-common
DEBUG=1

ifdef DEBUG
        CFLAGS=-Wall -Winline -pipe -g -DDEBUG #-pedantic -pg 
else
        CFLAGS=-Wall -Winline -pipe -O3 -march=native -funroll-all-loops \
                   -finline-functions #-pedantic 
endif

#CXXFLAGS=$(CFLAGS)

# Generic rules:

obj/%.o: src/%.c
        @echo Compiling $@
        @mkdir -p $(SUBDIRS)
        $(CC) $(CFLAGS) $(INC) -MMD -MF '$(patsubst src/%.c,deps/%.d,$<)' -o $@ -c $< 

obj/%.o: src/%.cc 
        @echo Compiling $@
        @mkdir -p $(SUBDIRS)
        $(CXX) $(CXXFLAGS) $(INC) -MMD -MF '$(patsubst src/%.c,deps/%.d,$<)' -o $@ -c $<

${TARGETS}: %:bin/%

# Specific target rules:

bin/tengine: obj/main.o obj/tengine.o
        $(LNK) $^ $(LIB) -o $@ 

bin/test2: obj/main.o obj/test2.o
        $(LNK) $^ $(LIB) -o $@ 

clean:
        rm -f *~ src/*~ gmon.out
        rm -fr $(SUBDIRS)

-include deps/*.d

Some notes:

  • A key problem with the original was that the dependency were generated, but not used. This has been fixed using -include deps/*.d (at the end).

  • Now that deps/*.d is used, the makefile doesn't need to have the src/%.h cases.

  • The original was also putting garbage into these files: in $(patsubst src/%,obj/%,%(patsubst %.cc,%.o,$<)) the third % should have been a $.

  • In the revised version, the dependencies are generated at the same time as the object, using -MMD. This is quicker, shortens the makefile, and adds some DRY.

  • Shortened INC: why bother including the standard system include directories? And in fact gcc will apparently ignore your -I /usr/include -I /usr/local/include anyway.

  • Removed your two different definitions of OBJS. Not needed, and potentially confusing. Used $^ instead.

  • It is always a good idea for make clean to completely undo everything make does, so you are left with what you started. But the sub-directories obj/ and deps/ were being created, and never deleted. Also, bin/ was pre-supposed to exist.

  • For the linking, added $(LNK), with LNK=gcc -g -Wl,--warn-common (but you may not want the warnings). AFAIK, all the other usual $(CFLAGS) are ignored for links.

  • Removed comments, which were (mostly) distracting.

  • Repeated twice make;make now gives make: Nothing to be done for ....

See also gcc dependency generation for a different output directory.

这篇关于我怎样才能使我的Makefiles更好?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆