2014-09-24 58 views
2

我目前正在编写一个更大的makefile,它将处理源文件的递归结构,并将它放入目标目录中的同一个递归结构中。基本上,你可以假设这样的Makefile:GNU Make - 如何处理目标文件中的路径

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 "[email protected] --- $<" 

正如你看到的,我想用$(SOURCE_DIR)的依赖,以取代$(DESTINATION_DIR),但这并不工作。我该如何解决这个问题?我甚至试图用这种方式替换脚本:

%.o: $(shell myreplacementscript.py "%.c" "$(DESTINATION_DIR)" "$(SOURCE_DIR)") 
    @echo "[email protected] --- $<" 

但百分比符号将被传递到我的脚本没有更换。那么我怎么能告诉它输出依赖于源文件动态?我需要将子目录保存在OBJECTS变量中,我不能将结构展平。而子目录是动态的,而不是预定义的。

我已经搜索了其他人有相同的问题,但他们要么有平的OBJECTS或递归的制造,在我的情况是不适合的,因为根据依赖目录之间的互连。

摘要/错误消息:

它不会取代输出/输入与Src /对象。所以错误信息是“Keine Regel vorhanden,um das Target»out/abc.o«,benötigtvon»all«,zu erstellen。Schluss。”这是典型的错误“没有制定目标的规则......”。

完整的makefile可以在这里看到: Full Makefile

每当我离开%的.html结肠的右手边在左侧它的工作原理,但我需要有源文件作为依赖以获得工作增量构建(希望没有创建依赖文件)。

亲切的问候,

丹尼尔

+0

你使用什么版本的Make? (如果您不确定,请尝试使用'make -v'。) – Beta 2014-09-24 22:55:30

+2

如果您确切地说明了_but这不起作用_实际上意味着(错误消息?错误行为?缺少行为?),那么帮助会简单得多您。 – MadScientist 2014-09-24 23:34:47

+0

@Beta:GNU Make 3.81 – DanielB 2014-09-25 07:12:07

回答

0

随着迈克尔·格鲁内瓦尔德答案,并MadScientist的网站上,我决定去VPATH方式。但是,因此我必须先切换到输出目录并删除OBJECTS的输出/前缀(通过对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 "[email protected] --- $<" 

(在这个小例子未经检验的,但在我的大的Makefile作品)

所以最后它现在按预期工作。非常感谢您的评论MichaelGrünewald,MadScientist和Beta。

更新:

最后我重试$(DESTINATION_DIR)/%○:$(SOURCE_DIR)/%C的做法和错误只是简单地认为$(DESTINATION_DIR)已经包含在斜线。我的完整makefile。

对不起,并再次感谢。对于任何人,因为有类似的问题而阅读本文:请检查斜杠两次!

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 

命名您的脚本'mkmf'并运行./mkmf。它会生成Makefile。您可以参数化并使其非常强大和智能。没有必要使用稀少和肮脏的GNU做扩展。

+0

这可能是真的,但可移植性对我来说不是真的需要。你的意思是什么?我终于把它用在标准模式out /%。o:in /%。o。 – DanielB 2014-10-01 17:45:08

+1

所有那些甜美的东西'$(shell ..)'都是GNU特有的功能。它在其他make实现中不起作用。 – 2014-10-01 18:40:49

+0

谢谢你提供的信息,但正如我所说,我可以忍受这一点。我不关注GNU make的其他make实现。 – DanielB 2014-10-02 08:27:55