Makefile GNU Make-如何处理对象文件中的路径

Makefile GNU Make-如何处理对象文件中的路径,makefile,gnu,makefile-project,Makefile,Gnu,Makefile Project,我目前正在编写一个更大的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

我目前正在编写一个更大的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 "$@ --- $<"
DESTINATION\u DIR=out
SOURCE_DIR=src
OBJECTS=out/abc.o out/subdir/test.o out/subdir/subdir/xyz.o
冒牌货:全部
全部:$(对象)
$(目的地目录)/%.o:$(来源目录)/%.c

@echo“$@--$根据Michael Grünewald的答案和MadScientist的网站,我决定采用VPATH方式。但因此,我必须先切换到输出目录,删除对象的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 "$@ --- $<"
ROOTDIR=$(abspath./)
目的地_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\u DIRABS))
#我们不在目标目录中,因此首先需要更改为目标目录
对象=
其他的
#没有输出/前缀!
对象=abc.o subdir/test.o subdir/subdir/xyz.o
#设置源文件的VPATH
VPATH=$(源目录)
恩迪夫
冒牌货:全部
全部:$(对象)
ifneq($(abspath./),$(DESTINATION\u DIRABS))
#在目标目录内调用make
$(MAKE)-C$(DESTINATION_DIRABS)-f$(ROOTDIR)/Makefile ROOTDIR='$(ROOTDIR)'
恩迪夫
%.o:%.c

@echo“$@--$使用GNU make扩展的解决方案不是一个好方法。我建议不要使用任何GNU Make特定功能。首先,它不是便携式的。其次,它的语法很糟糕。使用曾经发明的标准工具和技术。您的解决方案是-Shell。您可以将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
src_files=“file1.c file2.c file3.c”

cat>Makefile Makefile Makefile您使用的Make版本是什么?(如果您不确定,请尝试
make-v
)如果您确切地说出了这不起作用的实际含义(错误消息?错误行为?丢失行为?),那么帮助您会简单得多。@Beta:GNU make 3。81@MadScientist:它不会将对象中的out/in替换为src/。因此,错误消息是“Keine Regel vorhanden,um das Target»out/abc.o«,benötigt von»all«,zu erstellen.Schluss.”,这是典型的错误“无规则生成目标…”。这基本上是因为它没有用src/替换out/并且找不到源文件。还要注意的是,BSDMake在将对象存储在不同于源文件的目录中时,具有非常出色的内置支持。你的确切意思是哪个分机?我最终使用了标准模式out/%.o:in/%.o.sweet-things行“$(shell..”)都是GNU特定的特性。它在其他make实现中不起作用。谢谢你提供的信息,但正如我所说的,我可以接受。除了GNU make之外,我没有关注其他make实现。
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