【问题标题】:Makefile needs to run definition twice, once to add to counter, the second to compileMakefile需要运行定义两次,一次添加到计数器,第二次编译
【发布时间】:2014-07-09 04:11:20
【问题描述】:

我有以下生成文件:

aCpp:=$(call rwildcard,$(srcDir),*.cpp)
aObjs=$(aCpp:.cpp=$(objEnd))
aObj=$(aObjs:$(srcDir)%=$(objDir)%)

totalCpp=$(words $(aCpp))
processed=    
$(objDir)%$(objEnd): $(srcDir)%.cpp
    $(CC) -MM -MP -MT $(df)$(objEnd) -MT $(df).d $(CFLAGS) $< > $(df).d
    $(CC) -c $< $(CFLAGS) -o $@
    $(eval processed+= x)
    @echo "$(words $(processed)) out of $(totalCpp) compiled."

default: $(aObj)

我需要做的是让makefile测试并查看文件是否需要编译,然后如果它确实向变量添加了一个计数器,但没有编译,一旦所有这些都完成了,我就需要它再次进行编译。我或多或少需要$(objDir)%$(objEnd): $(srcDir)%.cpp 定义运行两次,但有两个不同的定义。

我想要这样做的全部原因是有一种更准确的方法来测量实际需要编译的文件数量而不是 5 out of 14 files processed. All done! 我希望它是模块化的并说 3 out of 3 或在下一个7 out of 8 而不是文件总数。

我是否必须在一个 makefile 中运行计数,将结果放在一个文件中,然后运行第二个 makefile?

【问题讨论】:

  • 是否有目标将这些文件列为 prereqs eval 基于$(words $?) 帮助的 make 变量? (我不知道评估的顺序是否正确。)
  • 误解了,它只是针对要处理的文件总量,而不是实际编译的总量。
  • 嗯? $? 是比目标更新的先决条件数。那应该只是与已更改的源文件匹配的目标文件。这不是你想要的号码吗?
  • 是但不,在编译运行先决条件的定义之前,我需要比可执行文件的目标更新的数量或先决条件。
  • eval 在可执行目标的主体中运行得不够早吗?尝试将其作为特定于目标的变量(可能需要二次扩展才能工作)怎么样?

标签: c++ makefile gnu-make


【解决方案1】:

我找到了解决办法,结果如下:

CC=g++

objDir=obj/

srcDir=src

df=$(objDir)$(*F)

rwildcard=$(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2))

aCpp:=$(call rwildcard,$(srcDir),*.cpp)
aObjs=$(aCpp:.cpp=$(objEnd))
aObj=$(aObjs:$(srcDir)%=$(objDir)%)

processed=
ifdef first
else
totalCpp:=$(shell make first=a)
endif
totalCppFake=

AUTODEPS:= $(patsubst $(srcDir)%.cpp,$(objDir)%.d,$(aCpp))

-include $(AUTODEPS)

$(objDir)%$(objEnd): $(srcDir)%.cpp
ifdef first
    $(eval totalCppFake+= x)
else
    @$(CC) -MM -MP -MT $(df)$(objEnd) -MT $(df).d $(CFLAGS) $< > $(df).d
    @$(CC) -c $< $(CFLAGS) -o $@
    $(eval processed+= x)
    @echo "$(words $(processed)) out of $(words $(totalCpp)) compiled."
endif

default: $(exe)
ifdef first
else
    @echo "Done!"
endif

$(exe): $(aObj)
ifdef first
else
    @$(CC) $(aObj) -o $(exe) $(CFLAGS)
    @echo "Binary created!"
endif

我所做的几乎就是调用一个 shell 命令再次运行 make 文件,如果变量首先存在,则有一个计数器,然后获取它的长度。我突然想到我可以这样做,使用 ifdef 来防止递归(无论如何永远)不断发生,并在我想要编译之前允许它在不编译的情况下工作,这是我主要关心的问题。

我希望我的学习经验也可以帮助任何想做同样事情的人。感谢 Etan Reisner 的帮助,尽管 $?不是我要找的东西。

【讨论】:

  • 你在这里失去了很多能力。这不会通过任何命令行选项或变量设置,它不会允许您指定要构建的特定目标等。我个人认为这个功能不值得两次运行 make 的性能影响,但如果你真的想要另一个选择是运行make -n 并计算调用的规则数(在脚本中),然后将其用作总数。例如totalCpp := $(shell $(MAKE) -n $(MAKECMDGOALS) | grep &lt;something&gt; | wc -l) 或其他。
  • 运行shell命令make first=a只需要0.02秒。要执行您建议的命令,需要 0.19 秒,几乎是速度的十分之一..
  • 这种技巧,但使用 make 重新启动,可能会更好。不过,如何完成这项工作的具体细节可能有点复杂。
  • 无论如何,如果你的解决方案已经找到,你应该在这里接受你自己的答案。
猜你喜欢
  • 1970-01-01
  • 2017-05-20
  • 1970-01-01
  • 1970-01-01
  • 2018-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多