2011-03-18 98 views
3

我正在构建一个将用于构建发行版或调试目标库的makefile。我想根据请求的makefile目标将对象和自动生成的依赖文件放入调试或版本目录结构中。我不想指定可测试的make命令行参数(即DBG = 1),但希望分别运行make -f Makefile或make -f Makefiel dbg来释放和调试目标目标。把那部分弄下来了。我知道我不能指定一个包含对象dir名称(释放或调试)的目标特定变量,它可以用作规则中目标规范的一部分,就像我在下面所示的示例中那样。在这个例子中,OBJDIR是我想根据构建目标设置的特定于目标的变量。因此,在本例中,$(OBJDIR)在目标规则$(OBJDIR)/%。o中为空。有关如何很好地执行建议步骤的任何建议? (所示示例只是一个复制/粘贴未验证的示例...语法未验证...实际上,我无法使标签正确显示......我希望得到一些实现的想法)。 (另外,$(OBJDIR)没有设置在干净的目标中,因为它不在dbg /所有目标依赖性的水平...想法?)在此先感谢。Make:使用不同的目标设置目标特定变量

的Makefile:

OBJS := a.o b.o c.o 
SRCS := $(OBJS:.o=.c) 

-- Set up the release and the debug directory paths and object filenames 
RELEASE_DIR := ./release 
RELEASE_OBJ := $(OBJS:%=$(RELEASE_DIR)/%) 
DEBUG_DIR := ./debug 
DEBUG_OBJ := $(OBJS:%=$(DEBUG_DIR)/%) 

.PHONY : all dbg 

all: CFLAGS = -O3 
all: OBJDIR := RELEASE_DIR 
all: df  := $(RELEASE_DIR)/$(*F) 
all: init_release lib1.so 

dbg: CFLAGS = -g -O0 
dbg: OBJDIR := DEBUG_DIR 
dbg: df  := $(DEBUG_DIR)/$(*F) 
dbg: init_debug lib1.so 

Lib1.so: $(OBJ) 

init_release: 
    [email protected] -p $(RELEASE_DIR) 

init_debug: 
    [email protected] -p $(DEBUG_DIR) 

lib1.so: $(OBJ) 
    @echo '--------------------------------------------------------------' 
    @echo linking [email protected] 
    @gcc -shared -o lib1.so $(OBJ) 

-Compile including advance dependancy generation alg, per Tom Tromey: 
    # http://make.paulandlesley.org/autodep.html 
$(OBJDIR)/%.o: %.c 
    echo [email protected]  
    echo $(OBJDIR) 
    echo compiling [email protected] 
    $(COMPILE.c) -MD -o [email protected] $< 
    cp $(df).d $(df).P; \ 
    sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ 
      -e '/^$$/ d' -e 's/$$/ :/' < $(df).d >> $(df).P; \ 
    rm -f $(df)/$*.d 

# If the goal is "clean", don't include these to avoid trying to build them 
ifneq($(MAKECMDGOALS),clean) 
-include $(SRCS:%.c=$(OBJDIR)/%.P) 
endif 

clean: 
    [email protected] -f $(OBJDIR)/*.[Pdo] lib1.so 

回答

3

目标特定变量可能会非常棘手。改为使用间接方式。 Make有很多语法来削减样板文本。 .SECONDEXPANSION往往不错。草图:

.SECONDEXPANSION: 
${DEBUG_OBJ} ${RELEASE_OBJ}: $$(patsubst %.o,%.c,$${@F}) 
    gcc ${copts-${@D}} -c $< -o [email protected] 

这里我们告诉做出./release/a.o取决于a.c。当决定构建./release/a.o时,它会扩展shell行。因为它这样做,所以${@D}自然是release,所以进行扩展${copts-release}你将有用地定义。

同样,当生产./debug/a.o使扩大${copts-debug}

大量使用$(warning [blah]),$(error [blah blah])和强制--warn-undefined-variables将帮助您获得此权利。

+0

不错。因此,为了增加混合性,是否可以通过参数设置OBJDIR来反映原始示例中以下内容中类似的扩展(release或debug subdir)? (我有点惊讶这不是在makefile领域更常见的实现......不同的构建配置和在自己的子级中松动对象/依赖项以减少较大项目的构建时间) ifneq($(MAKECMDGOALS),干净) -include $(SRCS:%。c = $(OBJDIR)/%。P) endif – user654077 2011-03-22 14:26:15

+0

@ user654077:难以阅读您的评论。我只是说无条件地包括所有的代表。它不会受到伤害。不要打扰首先检查MAKECMDGOALS,这看起来不止一点脆弱。 ('-include $(patsubst%.o,%。P,$ {DEBUG_OBJ} $ {RELEASE_OBJ})'。) – bobbogo 2011-03-22 14:41:08

+0

非常感谢......迄今为止效果很好。还有一个扩展问题,我想我会有这个舔。也许,而不是简单地将构建配置放入.debug或.release,所需的对象目录更像“./LibName/.debug”和“./LibName/.release”。使用您的.SECONDEXPANSION解决方案,我想解决$ {copts - $ {@ D}}简单地.debug或.release,而不是LibName/.debug等。找不到一种方法来提取“last subdir“部分的OBJDIR。思考? – user654077 2011-03-22 15:26:07

1

Makefile的你写的是不是有效,因为你希望它不会产生你的目标。例如,您无法在目标定义alldbg中设置CFLAGS变量。

我能想到的唯一解决方案是使用与您想要的相同的Makefile定义DBG变量来调用make。例如:

ifdef DBG 
CFLAGS = -O0 -ggdb 
OBJDIR = dbgdir 
else 
CFLAGS = -O2 
OBJDIR = reldir 
endif 

all: $(OBJDIR)/target 
    #Your commands here 

dbg: 
    $(MAKE) DBG=1 

有了这个,如果你打电话make,你有发布版本。如果你打电话make dbg你有发布版本。

+0

是的,在我的“真实”实现中,CFLAGS + =这些标志......我只是为了示例剪切和粘贴)。我确实想到了递归制作解决方案,但希望有另一种更优雅的方法。我在另一个线程中发现了一些东西: – user654077 2011-03-18 16:57:09