2010-04-26 84 views
44

有没有一种方法可以在目标主体内重新分配Makefile变量值?更改目标主体内部的Makefile变量值

我所试图做的是添加一些额外的标志用于调试编译:

%.erl: %.beam 
    $(ERLC) $(ERLFLAGS) -o ebin $< 

test: clean debug_compile_flag compile compile_test 

debug_compile: 
    $(ERLCFLAGS) += -DTEST 

所以,如果我调用测试目标,我想清理我的环境中,增加一些新的标志(像-DTEST),再次编译整个代码(第一个源代码,然后是测试模块)。

我不想复制/粘贴代码用于编译一些新的标志集,因为有很多逻辑放在这里和那里。

是否有一些简单的方法来重新定义变量值,以便我可以重用现有的代码?

+0

的可能重复[定义使在规则的执行时间变量(http://stackoverflow.com/questions/1909188 /界定,使变量 - 在规则,执行时间) – 2015-04-15 07:30:03

回答

-5

编辑:正如在other answer中的Beta所解释的,这是可能的。


不,在Makefile中没有办法做到这一点。但是,您可以更改make命令行上的变量值。如果你重写你的Makefile如下:

ERLCFLAGS += $(ERLCFLAGSADDED) 

%.erl: %.beam 
    $(ERLC) $(ERLCFLAGS) -o ebin $< 

test: clean compile compile_test 

然后,你可以调用化妆用执行你的测试:

make ERLCFLAGSADDED=-DTEST test 
+0

是啊,我解决了如你所说,在debug_compile运行submake问题: ERLC_FLAGS = $(ERLC_DEBUG_FLAGS)$(MAKE)编译 谢谢! – paulgray 2010-04-26 09:39:14

+0

哦,是的,太好了。我没有想到这个子调用。 – 2010-04-26 11:36:02

+0

如果您想要使用不同的标志值多次运行目标,则子图调用仍然有用。请参阅下面评论中引用的文档。 – ntc2 2013-09-20 00:00:16

58

是的,有一个简单的方法来做到这一点,并没有重新运行制作。使用target-specific variable value

test: clean debug_compile 

debug_compile: ERLCFLAGS += -DTEST 
debug_compile: compile compile_test; 
+2

在这里保证执行顺序吗?或者可以让-j2搞砸了吗? – Marenz 2011-05-29 19:46:33

+2

[文档](http://www.gnu.org/software/make/manual/make。html#Target_002dspecific):“请注意,一个给定的先决条件最多只能在每次调用make时构建一次,如果同一个文件是多个目标的先决条件,并且每个目标对同一个目标具有不同的值 - 那么要构建的第一个目标将导致构建该先决条件,并且先决条件将继承第一个目标的目标特定值,并忽略来自其他任何目标的特定于目标的值。 – ntc2 2013-09-19 22:34:01

38

另一个答案就在这里:Define make variable at rule execution time

对于懒惰的,你可以有这样的规则下(FLAGDEBUG是我的变量):

.DBG: 
    $(eval FLAG += $(DEBUG)) 
+2

只为我工作的版本,谢谢! – Raphael 2013-05-07 08:39:26

+1

我有很多'$(eval xxx)'的问题,有很多奇怪的副作用。它看起来不像“真正”的Makefile变量赋值。 – Cyan 2017-02-02 23:59:29

+0

我有一个'eval'函数的问题 - 我的变量为空值,因为用eval定义的变量在目标执行开始时获取它的值,而不是到达此行时。例如,如果您在目标的开头创建了一些文件,然后尝试使用'eval FILES = $(shell ls)'填充某个变量,则您的FILES变量将为空 – 2017-06-05 13:31:58

0

我想在makefile中添加一个目标来运行测试,这意味着重新编译源代码带有一些调试标志。伊恩的回答:https://stackoverflow.com/a/15561911/是唯一的解决方案。

这是我想出了一个Makefile文件,运行make tests时担保的执行顺序:

TARGET  = a.out 

CC   = g++ 
GENERIC_F = -Wall -Wextra -I. -Idoctest/doctest/ 

CFLAGS  = -O0 -std=c++11 $(GENERIC_F) 
DEBUG_MODE = -DDEBUG 

LINKER  = g++ 
LFLAGS  = $(GENERIC_F) -lm 

SRCDIR  = src 
OBJDIR  = build 
BINDIR  = bin 

SOURCES = $(wildcard $(SRCDIR)/*.cc) 
INCLUDES = $(wildcard $(SRCDIR)/*.h) 
OBJECTS = $(SOURCES:$(SRCDIR)/%.cc=$(OBJDIR)/%.o) 
rm   = rm -f 

.PHONY: clear_screen tests extend_cflags 

$(BINDIR)/$(TARGET): $(OBJECTS) $(INCLUDES) 
    $(LINKER) $(OBJECTS) $(LFLAGS) -o [email protected] 
    @echo -e "Linking complete!\n" 

$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.cc $(INCLUDES) 
    @mkdir -p $(OBJDIR) $(BINDIR) 
    $(CC) $(CFLAGS) -c $< -o [email protected] 
    @echo -e "Compiled "$<" successfully!\n" 

.PHONY: clean 
clean: 
    @$(rm) $(OBJECTS) 
    @echo "Cleanup complete!" 

.PHONY: remove 
remove: clean 
    @$(rm) $(BINDIR)/$(TARGET) 
    @echo "Executable removed!" 

clear_screen: 
    @clear 

extend_cflags: 
    $(eval CFLAGS += $(DEBUG_MODE)) 

tests: | remove extend_cflags $(BINDIR)/$(TARGET) clear_screen 
    @$(BINDIR)/$(TARGET)