【问题标题】:Writing dependencies in makefile, with makefile在 makefile 中编写依赖项,使用 makefile
【发布时间】:2013-04-27 21:19:58
【问题描述】:

基于一些 SO 问题——以及发现的一些进一步参考——,我正在尝试构建一个能够:

  • 给定$(SRC)中的目录,找到要编译的.cpp文件;
  • 编译.cpp,生成.o对象;
  • 从之前编译的每个 .o 生成 .so 共享对象。

make 文件应该做的是:

  • 给定$(SRC)中的目录,找到要编译的.cpp文件;
  • 使用-MM 编译器标志为每个.cpp 构建依赖关系列表;
  • 使用$(eval ...)注释/添加每个依赖项;
  • 评估/解决找到的每个依赖项,生成.o.so 文件。

到目前为止我有什么: 我已经能够完成所有的事情,除了让它工作(: 我得到的错误表明,不知何故,有一个空标签 '' 作为依赖项:

$ make make: * 没有规则来制作目标', needed by /home/rubens/bin/label.o'。停下来。

所以,这是我还无法运行的 makefile:

# Directories
SRC := process init
BIN := $(HOME)/bin

LIB := watershed
LIBPATH := $(WATERSHED)/lib
INC := $(WATERSHED)/include $(XERCES)/include

# Paths
MPICPP := mpic++
SOURCES := $(shell find $(SRC) -name '*.cpp')
OBJECTS := $(addprefix $(BIN)/, $(notdir $(SOURCES:.cpp=.o)))
SHARED := $(OBJECTS:.o=.so)

# Flags 
CFLAGS := -std=c++0x -O2 -Wall -fPIC
CFLAGS += $(foreach inc, $(INC), -I $(inc))
LFLAGS :=
LFLAGS += $(foreach lib, $(LIB), -l $(lib))
LFLAGS += $(foreach path, $(LIBPATH), -L $(lib))

# Rules
$(SHARED): | bindir
%.o:
        @echo $@ -- [$<][$^][$*]
        @echo $(MPICPP) $(CFLAGS) -c $< -o $@

%.so: %.o
        @echo $(MPICPP) $(LFLAGS) -shared $< -o $@

bindir:
        @mkdir -p $(BIN)

# Utilities
.PHONY: all clean
all: $(SHARED)
clean:
        @rm -f $(OBJECTS) $(SHARED)

# Dependencies
define dependencies
$(addprefix $(BIN)/, $(notdir $(1:.cpp=.o))): \
        $(shell $(MPICPP) $(CFLAGS) -MM $(1) | sed 's/^.*\.o:[ ]*//')
endef
$(foreach src, $(SOURCES), $(eval $(call dependencies, $(src))))

错误似乎在哪里: 这似乎是由依赖生成步骤引起的,因为当我删除任何空行时,将输出通过管道传输到grep,如下所示:

define dependencies
$(addprefix $(BIN)/, $(notdir $(1:.cpp=.o))): \
        $(shell $(MPICPP) $(CFLAGS) -MM $(1) | sed 's/^.*\.o:[ ]*//' | \
        grep -v ^$)
endef

错误以某种方式扩展为一个空的依赖项列表;我可以看到列表实际上是空的,规则 %.o: 中的 echo 是空的——唯一不为空的变量是 $@$*

/home/rubens/bin/label.o -- [][][/home/rubens/bin/label]

mpic++ -std=c++0x -O2 -Wall -fPIC -I /home/rubens/libwatershed/include -I /home/rubens/xerces-c-3.1.1/include -c -o /home/ rubens/bin/label.o

mpic++ -l 分水岭 -L -shared /home/rubens/bin/label.o -o /home/rubens/bin/label.so

非常非常欢迎任何有关解决此问题的更好方法的建议;然而,我真的很想在使用CmakeScons 之类的东西之前完成这个makefile 的编写。

【问题讨论】:

  • 我不建议尝试使用 eval 生成依赖项。这真的很不愉快。您应该使用包含的 makefile。 make.mad-scientist.net/autodep.html 有一个很好的例子说明如何做到这一点,尽管如果你使用 GCC 或具有兼容标志的编译器,你可以使用 -MM 选项进行简化。
  • +1 好吧,我想最好的办法是使用包含的 makefile 或使用 cMake/Scons。无论如何,我会留下这个问题,所以有人可能会给它一个解决方案。
  • 即使你让它工作了,你也永远不想使用它。效率太低了:每次运行 make 时,无论出于何种原因(甚至是“make clean”),它都会对所有源文件运行预处理器,然后对它们进行处理。一旦您获得多个源文件,它将使您的构建变得非常缓慢。使用包含文件要好得多,因为它将依赖信息保存为文件,以便下次运行 make 时可以直接读取。另外,它只会重新计算更改文件的依赖关系信息,而不是每次运行 make 时对每个文件的依赖信息。
  • +1 好的,兄弟,我要结束这个问题了(:

标签: c++ makefile dependencies shared-libraries mpic++


【解决方案1】:

-MM 已经生成了Makefile 格式的依赖关系,因此您可以通过将每个*.cpp 的依赖关系生成到同一个文件中来简化此操作,然后只需执行-include $(DEPS_FILE)。这可能比使用 eval 更易于维护。

【讨论】:

  • +1 这实际上是我第一次看到的——也正是here 的例子。我只是认为evaluating 依赖项会为我节省一些额外的规则,以及clean 规则上的额外变量等等。肯定是错了,反正 x=
【解决方案2】:

在 makefile 变量 SOURCES 的定义行,搜索 cpp 文件,你可能必须像这样重写: 查找 $(SRC) -name "*.cpp"

【讨论】:

  • 我猜你的意思是'*.cpp',以避免在外壳中扩展。即使这样,错误也是完全相同的。无论如何,谢谢您的指点。
猜你喜欢
  • 2016-09-14
  • 2021-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-04
相关资源
最近更新 更多