基于一些 SO 问题——以及发现的一些进一步引用——,我正在尝试构建一个 makefile 能够:
- 根据
$(SRC)
中的目录,找到要编译的.cpp
文件; - 编译
.cpp
,生成.o
对象; - 从以前编译的每个
.o
生成.so
共享对象。
make 文件应该做的是:
- 根据
$(SRC)
中的目录,找到要编译的.cpp
文件; - 使用
-MM
编译器标志为每个.cpp
构建依赖列表; - 使用
$(eval ...)
注释/添加每个依赖项; - 评估/解决找到的每个依赖项,生成
.o
和.so
文件。
到目前为止我有什么:
我已经能够完成所有事情,除了让它工作(:
我得到的错误指出,不知何故,有一个空标签 ''
作为依赖项:
$ make make: * No rule to make target
', needed by
/home/rubens/bin/label.o'. Stop.
所以,这是我还不能运行的 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
错误以某种方式演变为一个空的依赖项列表;我能够看到列表实际上是空的,并且 echo
在规则 %.o:
中——唯一不为空的变量是 $@
和 $*
。
/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 watershed -L -shared /home/rubens/bin/label.o -o /home/rubens/bin/label.so
非常非常欢迎任何关于解决此问题的更好方法的建议;然而,我真的很想在开始使用 Cmake
或 Scons
之类的东西之前完成此 makefile 的编写。
最佳答案
-MM
将已经生成依赖于 Makefile
格式的文件,因此您可以通过为每个 *.cpp
生成依赖项来简化它一个相同的文件,然后只需执行 -include $(DEPS_FILE)
。这可能比使用 eval 更易于维护。
关于c++ - 在 makefile 中编写依赖项,使用 makefile,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16359449/