我正在编写一个更大的makefile,它将处理源文件的递归结构,并将它们放在目标目录中的相同递归结构中。基本上你可以假设这个makefile:
DESTINATION_DIR = out
SOURCE_DIR = src
OBJECTS = out/abc.o out/subdir/test.o out/subdir/subdir/xyz.o
.PHONY: all
all: $(OBJECTS)
$(DESTINATION_DIR)/%.o: $(SOURCE_DIR)/%.c
@echo "$@ --- $<"
正如您所看到的,我正在尝试用依赖项中的$(SOURCE_DIR)替换$(DESTINATION_DIR),但这不起作用。我怎么解决这个问题?我甚至试图以这种方式使用替换脚本:
%.o: $(shell myreplacementscript.py "%.c" "$(DESTINATION_DIR)" "$(SOURCE_DIR)")
@echo "$@ --- $<"
但百分号将传递给我的脚本而无需替换。那么我怎么能告诉它输出依赖于源文件动态?我需要将子目录保存在OBJECTS变量中,我不能压扁结构。子目录是动态的,而不是预定义的。
我已经搜索过其他有相同问题的人,但他们要么有平坦的OBJECTS,要么有递归的make,在我的情况下由于根据依赖关系的目录之间的互连而不适合。
摘要/错误消息:
它不会用src /替换OBJECTS中的/。所以错误信息是“Keine Regel vorhanden,um das Target»out / abc.o«,benötigtvon»all«,zu erstellen.Schluss。”这是典型的错误“没有规则来制定目标......”。
完整的makefile可以在这里看到: Full Makefile
每当我在左侧留下%.html的冒号的右侧边缘时它就可以工作,但我需要将源文件作为依赖项来获得有效的增量构建(希望不创建依赖文件)。
亲切的问候,
丹尼尔
答案 0 :(得分:1)
使用GNU make扩展的解决方案不是一个好方法。我建议不要使用任何GNU Make特定功能。首先,它不便携。其次,它的语法很糟糕。使用有史以来发明的标准工具和技术。你的解决方案是 - 壳牌。您可以将Makefile包装到shell脚本中,并使用常见的shell语言进行所有计算和字符串操作。请看以下示例:
src_files="file1.c file2.c file3.c"
cat > Makefile <<EOF
-
-
YOUR MAKEFILE STATIC STUFF GOES HERE
-
all: $(OBJECTS)
EOF
for file in $src_files; do
src="src/$file"
obj=`echo $file | sed 's/\.c$/\.o/'`
sources="$sources $src"
objects="$objects out/$obj"
cat >>Makefile <<EOF
$obj: $src
YOUR CODE HERE
EOF
done
cat >>Makefile <<EOF
SOURCES = $sources
OBJECTS = $objects
EOF
为脚本命名&#39; mkmf&#39;并运行./mkmf。它将生成Makefile。您可以对其进行参数化,使其非常强大和智能。不需要使用少量和脏的gnu make扩展。
答案 1 :(得分:0)
MichaelGrünewald的回答和MadScientist的网站,我决定采用VPATH的方式。但是因此我必须首先切换到输出目录并删除OBJECTS的out /前缀(通过对makefile的递归调用)。以上简短示例将如下修改:
ROOTDIR = $(abspath ./)
DESTINATION_DIR = out
SOURCE_DIR = src
DESTINATION_DIRABS = $(abspath $(shell cd $(ROOTDIR); cd $(DESTINATION_DIR); pwd))
SOURCE_DIRABS = $(abspath $(shell cd $(ROOTDIR); cd $(SOURCE_DIR); pwd))
ifneq ($(abspath ./),$(DESTINATION_DIRABS))
# we are not in the destination directory, so we first need to change to it
OBJECTS =
else
# without out/ prefix!
OBJECTS = abc.o subdir/test.o subdir/subdir/xyz.o
# set the VPATH for the source files
VPATH = $(SOURCE_DIRABS)
endif
.PHONY: all
all: $(OBJECTS)
ifneq ($(abspath ./),$(DESTINATION_DIRABS))
# call make inside the destination directory
$(MAKE) -C $(DESTINATION_DIRABS) -f $(ROOTDIR)/Makefile ROOTDIR='$(ROOTDIR)'
endif
%.o: %.c
@echo "$@ --- $<"
(在这个小例子中未经测试,但在我更大的Makefile中工作)
所以最后它按预期正在运行。非常感谢您对MichaelGrünewald,MadScientist和Beta的评论。
<强>更新强>
最后我重试了$(DESTINATION_DIR)/%。o:$(SOURCE_DIR)/%。c方法,故障只是$(DESTINATION_DIR)已经包含了我的完整makefile中的斜杠。
对不起,请再次感谢。对于因为遇到类似问题而阅读此内容的任何人:检查斜杠两次!