28

作为 makefile 的一部分,我想生成目标的调试或发布版本。

从功能上讲,一切正常,但是,我在运行 make 时收到警告

 12 SRC := $(shell echo src/*.cpp)
 13 SRC += $(shell echo $(TEST_ROOT)/*.cpp)
 14 
 15 D_OBJECTS = $(SRC:.cpp=.o)       # same objects will need to be built differently
 16 R_OBJECTS = $(SRC:.cpp=.o)       # same objects will need to be built differently

 22 all: $(TARGET)
 23 
 25 $(TARGET): $(D_OBJECTS)
 26   $(CC) $(D_OBJECTS) -o $(TARGET)
 27 
 28 $(D_OBJECTS) : %.o: %.cpp                     # ----- run with debug flags 
 29   $(CC) $(COMMON_FLAGS) $(DEBUG_FLAGS) -c $< -o $@
 30 
 31 release: $(R_OBJECTS)
 32   $(CC) $(R_OBJECTS) -o $(TARGET)
 33 
 34 $(R_OBJECTS) : %.o: %.cpp                     # ----- run with release flags
 35   $(CC) $(COMMON_FLAGS) $(RELEASE_FLAGS) -c $< -o $@

当我make得到调试版本时,当make release我得到发布版本时。

但我也收到警告:

Makefile:35: warning: overriding commands for target `src/Timer.o'
Makefile:29: warning: ignoring old commands for target `src/Timer.o'
Makefile:35: warning: overriding commands for target `test/TimerTest.o'
Makefile:29: warning: ignoring old commands for target `test/TimerTest.o'

带着这2个问题:

  1. 任何忽略警告的方法
  2. 我做对了吗?需要做哪些改变?
4

4 回答 4

25

像 OP(詹姆斯伦纳德)一样,我想压制或避免有关压倒Makefile目标的警告。但是,我的情况和目标不同。

我想要Makefileinclude base.mk并且我希望Makefile能够在base.mk没有任何警告消息的情况下覆盖目标。我正在使用 GNU Make。

GNU Make 文档描述了这样做的一种方法:

创建Makefile如下:

foo:
        echo 'bar' > foo

%: force
        @$(MAKE) -f base.mk $@
force: ;

来源: https ://www.gnu.org/software/make/manual/html_node/Overriding-Makefiles.html

上面的方法有一个(可能很严重的)缺点,它会调用一个单独的实例$(MAKE),这意味着(一些或全部?)变量可能(将?)不会在 make 的父子调用和子调用之间共享。

令人高兴的是,我找到了一个更好的解决方案,如下所述:

创建base.mk如下:

foo-default:
        echo  'foo-default'

bar-default:
        echo  'bar-default'

%:  %-default
        @  true

创建Makefile如下:

include  base.mk

foo:
        echo  'foo  Makefile'

示例输出:

$ make foo
echo  'foo  Makefile'
foo  Makefile

$ make bar
echo  'bar-default'
bar-default

请注意,您需要能够控制目标的名称,base.mk以便您可以命名它们<target>-default。换句话说,您不能使用这种方法来扩展任意基础 makefile。但是,如果您同时控制base.mkMakefile,则此方法将允许您创建一个base.mk,然后创建多个自定义。

于 2018-04-12T19:46:53.883 回答
16

执行此操作的最常见方法之一是将发布对象和调试对象放在单独的子目录中。这样您就不会重新定义对象的规则,因为它们将具有不同的名称。像这样的东西:

D_OBJECTS=$(SRC:%.cpp=debug/%.o)
R_OBJECTS=$(SRC:%.cpp=release/%.o)

RTARGET = a.out
DTARGET = a.out.debug

all : dirs $(RTARGET)

debug : dirs $(DTARGET)

dirs :
    @mkdir -p debug release

debug/%.o : %.c
    $(CC) $(DEBUG_CFLAGS) -o $@ -c $<

release/%.o : %.c
    $(CC) $(RELEASE_CFLAGS) -o $@ -c $<

$(DTARGET) : $(D_OBJECTS)
    $(CC) $(DEBUG_CFLAGS) -o $@ $(D_OBJECTS)

$(RTARGET) : $(R_OBJECTS)
    $(CC) $(RELEASE_CFLAGS) -o $@ $(R_OBJECTS)
于 2012-08-14T19:11:48.560 回答
2

为避免多次包含同一个文件,您可以使用 C 样式的标头“指令”:

ifeq ($(_MY_MAKEFILE_),)
_MY_MAKEFILE_ := defined

...

endif
  • ifeq这里只是说“值是空的”
  • 有可能可以做类似的事情,ifndef但我首先得到了这个工作
  • “定义”的值就是任何不为空的东西
于 2020-02-27T22:09:52.997 回答
-3

我遵守了自己的制作并注释掉了打印这些警告的部分。奇迹般有效。在第 2114 行附近制作 v4.2,read.c

于 2019-07-17T19:58:16.170 回答