在单独的文件夹中生成依赖文件

Posted

技术标签:

【中文标题】在单独的文件夹中生成依赖文件【英文标题】:Generating dependency files in separate folder 【发布时间】:2016-03-24 20:58:05 【问题描述】:

我正在尝试为具有以下结构的项目创建一个 makefile:

├──bin/
├──build/
│  ├──foo.d
│  └──bar.d
├──include/
│  └──foo.h
│
├──lib/
├──src/
│  ├──foo.cc
│  └──bar.cc
│
├──Makefile

这是生成文件:

# Define the compiler and the linker.
CXX = g++
CC  = g++
# Folders
srcdir   = src
builddir = build
out      = bin

# Define preprocessor, compiler, and linker flags.
CPPFLAGS  = -I include -std=c++11
LDFLAGS   = -g -Llib

# Phony targets
.PHONY: all clean test

# Targets
all : $(out)/bar
$(out)/bar : $(addprefix $(builddir)/,bar.o foo.o)

# Standard clean
clean :
    rm -f $(builddir)/*.o $(builddir)/*.d

# Generate dependencies in *.d files
$(builddir)/%.d: $(srcdir)/%.cc
    @set -e; rm -f $@; \
     $(CPP) -MM $(CPPFLAGS) $< > $@.$$$$; \
     sed 's,\($*\)\.o[ :]*,$(builddir)/\1.o $@ : ,g' < $@.$$$$ > $@; \
     rm -f $@.$$$$;

deps = $(patsubst $(srcdir)/%.cc,$(builddir)/%.d,$(wildcard $(srcdir)/*.cc))
include $(deps)

依赖文件包含以下内容:

食物.d

build/foo.o build/foo.d : src/foo.cc include/foo.h

bar.d(取决于 foo)

build/bar.o build/bar.d : src/bar.cc include/foo.h

有没有办法在 build/ 目录中生成 .d 文件,将目标文件编译到同一个文件夹中,然后编译 bin/bar 程序?任何帮助表示赞赏。

编辑:

问题是我在期待

all : $(out)/foo

$(out)/foo : $(addprefix $(builddir)/,foo.o bar.o)

$(builddir)/%.o : $(srcdir)/%.cc
    $(CXX) -c $< -o $@ -MP -MMD -MF $(@:.o=.d)

神奇地编译程序 foo(当所有文件都在同一个文件夹中时它可以工作)。

相反,我必须指定配方:

all : $(out)/foo

$(out)/foo : $(builddir)/foo.o $(builddir)/bar.o
    $(CXX) $(CPPFLAGS) $(CXXFLAGS) $^ -o $@

$(builddir)/%.o : $(srcdir)/%.cc
    $(CXX) -c $< -o $@ -MP -MMD -MF $(@:.o=.d)

【问题讨论】:

请注意,依赖规则是为了方便项目开发人员,而不是实际的构建要求。如果您只想尽可能快速轻松地从裸源分发版转到二进制文件,请避免生成依赖规则。在这种情况下,您知道无论如何您都需要构建一切。 然而,关于所提出的问题,我不清楚你在问什么。如何在build 目录而不是其他地方生成.d 文件?如何编写允许您描述的所有步骤由一次 make 运行触发的 make 规则?还有什么? 为了清楚起见,我更新了问题。我正在尝试为其编写 makefile 的实际项目有大量文件。使用一个文件夹时的生成文件非常干净和高效。我只是想在迁移到一个体面的项目文件夹结构时保持自动生成依赖项。 好的,但是您提出的Makefile 遇到了什么问题?真正的问题是什么? 我希望我有足够的积分来支持您的回复。我的 makefile 并没有真正的问题,而是对我认为它会完成的事情的误解。将所有文件放在一个文件夹中,make 会自动运行生成程序的方法,但是对于多个文件夹,我必须自己定义它。谢谢。 【参考方案1】:

放弃所有sed 的废话。 gcc 可以一次性生成所有内容:

$(builddir)/%.o : $(srcdir)/%.cc
    $(CPP) -c $< -o $@ -MP -MMD -MF $(@:.o=.d)

这将一次性构建build/foo.obuild/foo.d,其中build/foo.d 将自动生成build/foo.o 的依赖项。

【讨论】:

出于某种原因,这给了我foo.o: file not recognized: File format not recognized collect2: error: ld returned 1 exit status @SebastianN 在什么情况下? 当我认为我的问题与依赖生成相关时,我错了,这只是定义食谱时的新手错误。我在上面发布的错误是因为我在食谱中使用了$(CPP) 而不是$(CXX)。感谢您提供比我的教授提出的基于 sed 的依赖生成更简洁的版本。 您可以删除-MF $(@:.o=.d) 部分,因为它是由-MMD 自动完成的。

以上是关于在单独的文件夹中生成依赖文件的主要内容,如果未能解决你的问题,请参考以下文章

CMake中生成的文件的运行时依赖关系

在 Maven 中生成带有依赖项和测试的 jar 文件

如何在 MATLAB 的脚本文件中生成函数

在 Python 中将多个 CSV 文件合并到电子表格的单独选项卡中

如何使用 roslyn 在 C# 中生成/编辑打字稿代码

如何在 jmeter 中生成测试结果 (CSV) 文件和 JTL 文件?