【问题标题】:Recompile only changed files (two-steps)仅重新编译更改的文件(两步)
【发布时间】:2017-09-28 01:51:51
【问题描述】:

我在这里阅读了几个关于 SO 的问题,但我的 Makefile 仍然不会做我想做的事。与其他问题相反,我在这里有一个两步编译。步骤如下:

  • 使用生成.cpp.h文件的预处理器工具(称为ppx),
  • 然后编译它们生成.o 文件,
  • 最终创建一个动态库。

所有这些都在 Xcode 环境中(自定义构建目标),因此您可以看到所有这些 $(TARGET_TEMP_DIR) 和类似变量。

make 命令被调用ppx 文件所在的位置,但我需要放置所有生成的文件(.cpp.h.o.dylib ) 在正确的目录中(参见$(LIB))。

注意:ppx 工具不保留时间戳

这是我失败的尝试:

# target and compiler
LIB=$(TARGET_TEMP_DIR)/$(TARGET_NAME).dylib
PPX=$(HOME)/bin/ppx

# c++ compiler
CXXFLAGS=-std=c++14 

# files 
PPX_FILES := $(patsubst %.ppx, %.cpp, $(wildcard *.ppx))
CPP_FILES := $(patsubst %.ppx, %.o, $(wildcard *.ppx))
OBJ_FILES := $(addprefix $(TARGET_TEMP_DIR)/,$(CPP_FILES:%.cpp=%.o))

# link library
all: $(LIB)

$(LIB): $(PPX_FILES) $(CPP_FILES) $(OBJ_FILES)
    $(CXX) -dynamiclib -o $(LIB) $(OBJ_FILES)

# preprocess, generating source and header
%.cpp: %.ppx 
    $(PPX) -o $(TARGET_TEMP_DIR) $<

# compile cpp source files
%.o: %.cpp
    $(CXX) $(CXXFLAGS) -Ofast -o $(TARGET_TEMP_DIR)/$@ -c $(TARGET_TEMP_DIR)/$<

上面的Makefile 总是重新编译所有文件。在阅读了我在这里找到的所有问题之后,我唯一成功做的就是拥有一个永不重新编译的 Makefile,这样当我更改 ppx 文件时它什么也没做。

你能帮我找出错误吗?

【问题讨论】:

  • 您的变量PPX_FILESCPP_FILES 具有误导性,因为PPX_FILES 列出了C++ 源文件,而CPP_FILES 列出了目标文件。您也不需要从磁盘中获取每个变量的文件名,只需替换第一个变量的后缀即可。
  • 您的 ppx 工具是否会重新生成未更改的文件?他们的时间戳会改变吗?
  • @RetiredNinja 是的,确实如此。我正在尝试使用make 来避免这种情况。
  • @Someprogrammerdude 我知道,但我不太熟悉make 以获得清晰的文件列表。
  • 你到底是什么意思,ppx 不保留时间戳? gcc -c 也没有。这就是make 规则的意义所在;如果输出时间戳是最新的,甚至不会调用工具。如果它们已过时,则时间戳不应在生成新的输出文件时保留

标签: c++ makefile timestamp preprocessor


【解决方案1】:

第 1 步:foo.ppx 构造 foo.cppfoo.h,并将它们放在正确的目录中。 (我理解你的意思是“正确的目录”是$(TARGET_TEMP_DIR),但你有点神秘。)

# preprocess, generating source and header
$(TARGET_TEMP_DIR)/%.cpp: %.ppx
    $(PPX) -o $(TARGET_TEMP_DIR) $< 

或更好:

# preprocess, generating source and header
$(TARGET_TEMP_DIR)/%.cpp: %.ppx
    $(PPX) -o $(dir $@) $< 

第 2 步:foo.cppfoo.h(以及 bar.hbaz.h,根据需要构造 foo.o。我建议您接下来研究自动依赖处理。)

# compile cpp source files
%.o: %.cpp
    $(CXX) $(CXXFLAGS) -Ofast -o $@ -c $<

第 3 步:构造所需目标文件的列表,并使用合理的名称:

# files                                     
PPX_FILES := $(wildcard *.ppx)
OBJ_FILES := $(patsubst %.ppx, $(TARGET_TEMP_DIR)/%.o, $(PPX_FILES))

第 4 步:构建库:

$(LIB): $(OBJ_FILES)
    $(CXX) -dynamiclib -o $@ $^

如果由于时间戳和 ppx 问题(我不必尝试)而仍然出现故障,请在评论中告诉我们;我很确定修复很容易。

【讨论】:

  • 感谢您的回答,效果很好。我只有一个问题:为什么make 会删除生成的cpp 文件?我没想到。这对我来说很酷,因为我在创建库后不需要它们,但是是否可以删除 .h 文件? (我已经将它们复制到另一个目录中)
  • @senseiwa:Make 会考虑cpp 文件intermediate files,并在他们的工作完成后将其删除。删除标头 (.h) 文件的最简单方法是将命令 rm -f $(TARGET_TEMP_DIR)/*.h 添加到 $(LIB) 规则中。可以让 Make 将它们视为中间文件,但这很复杂。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-10
  • 1970-01-01
  • 1970-01-01
  • 2018-08-22
  • 1970-01-01
  • 2017-11-15
  • 1970-01-01
相关资源
最近更新 更多