【问题标题】:Makefile that rebuilds all if compiled with dif flags如果使用 diff 标志编译,则重建所有的 Makefile
【发布时间】:2014-09-15 00:50:03
【问题描述】:

所以我在尝试弄清楚如何制作我的 Makefile 时遇到了一些困难,以便当我执行 make 并编译发布版本然后稍后执行 make debug 它编译调试版本时如果文件尚未更新,则在 gcc 上设置新的 -DDEBUG 和 -g。

例如:

  1. main.cpp 已编辑
  2. 运行make
  3. 编译 main.cpp
  4. 运行make debug
  5. main.cpp 未重新编译,因为即使编译的标志不同,也没有更改

请注意,我不想每次都进行清理,因为如果我连续执行 2 个makes,我不想重新编译文件,因此将清理设置为依赖项不会成为这里的有效答案

【问题讨论】:

  • 有这样的例子,有些甚至可能在这个网站上,但一般的想法是你将编译器标志写入一个文件,将该文件列为编译对象的先决条件,列出一个当当前标志与旧标志不同时,您将当前标志与之比较并更新初始 prereq 文件的修改时间(和内容)的临时文件上的该文件的强制先决条件。
  • 我的回答遵循 Etan 所说的总体思路。我的答案的特殊功能(在不同的线程中提到)是它隐藏了这个黑客实现的复杂性,对 Makefile 用户 - 通常是更新特定“包”Makefile 的人。他们只想要简单的界面,就像我指定的那样,他们只想以与依赖文件相同的灵活方式“依赖”某个变量,而不想知道它在幕后是如何发生的。

标签: makefile gnu-make


【解决方案1】:

您可能希望根据构建模式将目标文件编译到不同的目录中,例如:

# default mode, override with `make BUILD=release`
BUILD := debug
obj_dir := ${BUILD}

CFLAGS.debug := -g -O0
CFLAGS.release := -g -O3 -march=native -DNDEBUG

all : ${obj_dir}/test

# Example executable
${obj_dir}/test : ${obj_dir}/test.o

test.c :
    echo "int main() { return 0; }" > $@

# Generic rules

${obj_dir} :
    mkdir $@

${obj_dir}/%.o : %.c Makefile | ${obj_dir} # Also recompile when Makefile changes.
    ${CC} -c -o $@ ${CPPFLAGS} ${CFLAGS} ${CFLAGS.${BUILD}} -MD -MP $<

${obj_dir}/% : Makefile | ${obj_dir} # Also re-link when Makefile changes.
    ${CC} -o $@ ${LDFLAGS} $(filter-out Makefile,$^) ${LDLIBS}

clean :
    rm -rf ${obj_dir}

-include $(wildcard ${obj_dir}/*.d)

${obj_dir}/*.d : ;

.PHONY: all clean

(奖励功能:自动生成依赖项)。

用法:

[max@localhost:~/tmp] $ make
mkdir debug
echo "int main() { return 0; }" > test.c
cc -c -o debug/test.o   -g -O0 -MD -MP test.c
cc -o debug/test  debug/test.o 

[max@localhost:~/tmp] $ make
make: Nothing to be done for 'all'.

[max@localhost:~/tmp] $ make BUILD=release
mkdir release
cc -c -o release/test.o   -g -O3 -march=native -DNDEBUG -MD -MP test.c
cc -o release/test  release/test.o 

[max@localhost:~/tmp] $ make BUILD=release
make: Nothing to be done for 'all'.

【讨论】:

    【解决方案2】:

    首先,你不应该运行make debug——这意味着你想要构建一个不同的目标(debug)。但你没有,你想构建 same 目标,只是使用不同的选项。这就是你所做的,你运行一个不同的选项,一个变量值

    >make DEBUG=Y
    

    当你跑步时

    >make
    

    你也真的传递了那个变量,只是用空字符串作为值。

    现在,为了让它在 Makefile 中按您的意愿工作,您需要将其设置为好像 DEBUG 是一个先决条件文件,配方如下:

    foobar.o: foobar.c DEBUG
        gcc $(if $(DEBUG), -DDEBUG -g) -c $< -o $@
    

    当然,这通常是行不通的,因为DEBUG 是一个变量,而不是一个文件。所以你需要一个技巧,我称之为“可靠变量”。它基本上是一种将变量声明为文件行为的方法。我在我的其他答案之一中描述了这种技术:

    How do I add a debug option to Makefile

    【讨论】:

      【解决方案3】:

      我曾经做过这样的事情,看起来是这样的(归结为最低限度):

      EXE     := a.out
      SRC     := $(wildcard *.c)
      
      ifneq ($(MAKECMDGOALS),debug)
      OBJ     := $(SRC:.c=.o)
      else
      OBJ     := $(SRC:.c=-d.o)
      endif
      
      .PHONY: all debug
      
      all:    $(EXE)
      
      debug:  CFLAGS += -g -DDEBUG
      debug:  $(EXE)
      
      $(EXE): $(OBJ)
          $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
      
      %.o %-d.o:  %.c
          $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $<
      

      诀窍是使用两个单独的目标文件列表,并根据目标选择一个。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-08-22
        • 2015-07-04
        • 1970-01-01
        • 1970-01-01
        • 2011-04-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多