配置 make 为不同目录下的不同系统构建对象

Configure make to build objects for different systems in different directories

目前我正在使用这个 makefile:

CFLAGS=-g -Wall
SRCS=foo.c bar.c main.c
OBJS=$(subst .c,.o,$(SRCS))

linux: CC=gcc
linux: OUTPUT=a.out

windows: CC=x86_64-w64-mingw32-gcc
windows: OUTPUT=a.exe

%.o: %.c
    $(CC) $(CFLAGS) -c $< 

linux: $(OBJS)
    $(CC) $(OBJS) -o $(OUTPUT)

windows: $(OBJS)
    $(CC) $(OBJS) -o $(OUTPUT)

clean:
    ${RM} a.out a.exe *.o

我可以用它来构建 make windowsmake linux 的程序。 但是由于所有目标文件都是在同一目录中创建的,因此我无法构建 windows 版本,然后构建 linux 版本,而不必 make clean 目录。

所以我想在子目录中构建 windows 对象,在另一个子目录中构建 linux 对象。我已尝试如下所示修改 makefile,但我无法使其正常工作。

$ make linux
gcc obj/linux/foo.o obj/linux/bar.o obj/linux/main.o -o a.out
gcc: error: obj/linux/foo.o: No such file or directory
gcc: error: obj/linux/bar.o: No such file or directory
gcc: error: obj/linux/main.o: No such file or directory
gcc: fatal error: no input files
compilation terminated.
make: *** [Makefile:19: linux] Error 1
CFLAGS=-g -Wall
SRCS=foo.c bar.c main.c
OBJS=$(subst .c,.o,$(SRCS))
DIR=obj/subdir/
OBJSDIR:=$(addprefix $(DIR), $(OBJS))

linux: CC=gcc
linux: OUTPUT=a.out
linux: OBJECTS=$(subst subdir,linux,$(OBJSDIR))

windows: CC=x86_64-w64-mingw32-gcc
windows: OUTPUT=a.exe
windows: OBJECTS=$(subst subdir,windows,$(OBJSDIR))

%.o: %.c
    $(CC) $(CFLAGS) -c $< 

linux: $(OBJECTS)
    $(CC) $(OBJECTS) -o $(OUTPUT)

windows: $(OBJECTS)
    $(CC) $(OBJECTS) -o $(OUTPUT)

clean:
    ${RM} a.out a.exe *.o

有很多在这里不起作用。

首先,在您更改模式后 %.o : %.c 不再匹配,因为词干现在是 obj/subdir/foo 而没有 obj/subdir/foo.c。而且,这个秘诀没有告诉编译器将输出文件放在哪里,所以它会使用默认位置。所以,这个模式需要是:

$(DIR)%.o : %.c
        $(CC) $(CFLAGS) -c -o $@ $<

但这仍然行不通,因为您错过了目标特定变量文档中的一个关键限制:它们食谱中生效。您正在尝试使用特定于目标的变量更改目标的 先决条件;那行不通的。

有多种方法可以处理此问题,但最简单的方法是使用递归,如下所示:

 ...
DIR = obj/$(SUBDIR)/
 ...

linux:
        $(MAKE) a.out CC=gcc OUTPUT=a.out SUBDIR=linux

windows:
        $(MAKE) a.exe CC=x86_64-w64-mingw32-gcc OUTPUT=a.exe SUBDIR=windows

$(OUTPUT): $(OBJECTS)
        $(CC) $^ -o $@