Makefile中的多跳

Multiple hops in Makefile

本文关键字:Makefile      更新时间:2023-10-16

我有一个C/c++混合项目,对于每个源代码,我想从程序集生成一个程序集文件(.S),然后生成一个目标文件(.o)。我认为下面的Makefile应该工作:

all: a.o b.o main.o
    g++ $^ -o main
%.o: %.S
    gcc -o $@ $<
%.S: %.c
    gcc -S -o $@ $<
%.S: %.cc
    g++ -S -o $@ $<
clean:
    rm -rf *.o main

理想情况下,为了生成X.o,需要根据X.cX.cpp是否可用,使用其中一个规则来生成X.S

然而,make显然不像我想象的那样工作。它采用X.o的默认规则,%.S: %.c%.S: %.cpp都没有应用…make -n

cc    -c -o a.o a.c
g++    -c -o b.o b.cc
g++    -c -o main.o main.cc
g++ a.o b.o main.o -o main

下面的示例代码可以重现:

// a.c
int a() { return 0;}
// b.cc
int b() { return 0;}
// main.cc
extern "C" int a();
extern int b();
int main() { a(); b(); return 0; }

我一定对如何解决一个目标有一些误解。任何想法?

在Makefile的顶部使用.SUFFIXES:来清除预定义的后缀。工作的例子:

$tail -n +1 a.c b.cc main.cc Makefile; make clean; make; ./main
==> a.c <==
#include <stdio.h>
void a(void) {
    printf("an");
}
==> b.cc <==
#include <stdio.h>
void b(void) {
    printf("bn");
}
==> main.cc <==
extern "C" {
    void a(void);
}
void b(void);
int main(void) {
    a();
    b();
}
==> Makefile <==
.SUFFIXES:
all: main.o a.o b.o
    g++ $^ -o main # all
%.o: %.S
    gcc -c -o $@ $< #o
%.S: %.c
    gcc -S -o $@ $< #Sc
%.S: %.cc
    g++ -S -o $@ $< #Scc
clean:
    rm -rf *.o main
rm -rf *.o main
g++ -S -o main.S main.cc #Scc
gcc -c -o main.o main.S #o
gcc -S -o a.S a.c #Sc
gcc -c -o a.o a.S #o
g++ -S -o b.S b.cc #Scc
gcc -c -o b.o b.S #o
g++ main.o a.o b.o -o main # all
rm b.S main.S a.S
a
b

您需要取消隐式规则,因为它们是更好的匹配,添加以下行

%.o: %.cc
%.o: %.c

注意,all的规则被打破了,因为它没有创建一个名为all的文件,make已经知道如何从汇编中组装目标文件,并且如果其中一个目标文件与目标

匹配,它也已经知道如何将目标文件链接到程序中。
assembly := a.s b.s main.s
objects  := $(assembly:.s=.o)
.SECONDARY: $(assembly)
main: CC := $(CXX)
main: $(objects)
%.s: %.c
    $(CC) $(CFLAGS) $(CPPFLAGS) -S -o $@ $<
%.s: %.cc
    $(CXX) $(CXXFLAGS) $(CPPFLAGS) -S -o $@ $<
%.o: %.cc
%.o: %.c
clean: ; $(RM) $(objects) $(assembly) main