Makefile:专用文件夹中的多个目标

Makefile : Multiple targets in dedicated folders

我正在为 make 语言苦苦挣扎,但尚未实现我的目标。 我有以下文件夹结构。

/sources/src => *.c
/sources/inc => *.h
/build => makefile
/build/target1/addsrc => *.c & *.h
/build/target2/addsrc => *.c & *.h

我想使用命令 make 编译两个目标或使用命令 make target1make target2 之一单独编译任何目标。每个目标都使用位于源文件夹中的相同源,添加位于其自己的 addrc 文件夹中的其他源,并应用不同的编译标志。 makefile 应创建以下目录和文件:

/build/target1/objects => *.o
/build/target1 => mylib.so
/build/target2/objects => *.o
/build/target2 => mylib.so

我尝试使用以下 makefile:

targets=target1 target2

TARGET=$(dir $@)

DIR_OBJ     = $(TARGET)objects
DIR_BIN     = $(TARGET)
BIN         = mylib.so

DIR_SRC     = ../sources/src
DIR_ADDSRC_LOC = ./$(TARGET)addsrc
INCLUDES  = -I./$(TARGET)addsrc -I../sources/inc

SRC := $(notdir $(wildcard $(DIR_SRC)/*.c))
ifneq ($(DIR_ADDSRC_LOC),)
  SRCLOC := $(notdir $(wildcard $(DIR_ADDSRC_LOC)/*.c))
endif
SRCS = $(SRC) $(SRCLOC)

OBJ = $(SRCS:%.c=$(DIR_OBJ)/%.o)

CFLAGS  = -fPIC
LFLAGS = -shared -lm -Wl,--start-group -Wl,--no-undefined

all  : $(targets)

$(targets): % : %/init %/$(BIN) 

$(targets:%=%/init):
    @if [ ! -d $(DIR_OBJ) ]; then \mkdir -p $(DIR_OBJ); fi;
    @if [ ! -d $(DIR_BIN) ]; then \mkdir -p $(DIR_BIN); fi;

$(targets:%=%/$(BIN)): $(OBJ)
    gcc $(OBJ) $(LFLAGS) -o $@

$(DIR_OBJ)/%.o: %.c
    gcc $(INCLUDES) $(CFLAGS) -c $< -o $@

这适用于每个目标的目录初始化。但是,其余的绝对不起作用。我花了几个小时让它工作但没有成功。任何帮助,将不胜感激。谢谢!

注意:我还没有研究关于编译标志的目标依赖性。

因为你有 gnu-make 标签让我们使用 GNU make:

targets  := target1 target2
BIN      := mylib.so
DIR_SRC  := ../sources/src
DIR_INC  := ../sources/inc
SRC      := $(wildcard $(DIR_SRC)/*.c)
OBJ      := $(patsubst $(DIR_SRC)/%.c,%.o,$(SRC))
CFLAGS   := -fPIC -I$(DIR_INC)
LDFLAGS  := -shared -Wl,--start-group -Wl,--no-undefined
LDLIBS   := -lm

.PHONY: all $(targets) clean
all: $(addsuffix /$(BIN),$(targets))

clean:
    rm -rf $(addsuffix /objects,$(targets)) $(addsuffix /$(BIN),$(targets))

$(targets): %: %/$(BIN)

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

$(addsuffix /objects,$(targets)):
    \mkdir -p $@

# : target
define target_rule
-LSRC := $$(wildcard /addsrc/*.c)
-LOBJ := $$(patsubst /addsrc/%.c,/objects/%.o,$$(-LSRC))
-GOBJ := $$(addprefix /objects/,$$(OBJ))
-OBJ  := $$(-LOBJ) $$(-GOBJ)

$$($(1)-LOBJ): /objects/%.o: /addsrc/%.c
$$($(1)-GOBJ): /objects/%.o: $$(DIR_SRC)/%.c

$$(-OBJ): CFLAGS += -I.//addsrc
$$(-OBJ): | /objects

/$$(BIN): $$(-OBJ)
    $$(CC) $$(CFLAGS) $$(LDFLAGS) -o $$@ $$^ $$(LDLIBS)
endef
$(foreach t,$(targets),$(eval $(call target_rule,$t)))

这利用了 GNU make 的特定功能,尤其是 foreach-eval-call. It also uses order-only prerequisites for the directories, and the the standard make variablesLDFLAGSCCLDLIBS...),而不是您使用的功能.

头文件中的依赖关系没有表达,因为你没有解释它们应该是什么。适应

演示:

$ tree
.
├── build
│   ├── makefile
│   ├── target1
│   │   └── addsrc
│   │       └── c.c
│   └── target2
└── sources
    ├── inc
    │   ├── a.h
    │   └── b.h
    └── src
        ├── a.c
        └── b.c

7 directories, 6 files
$ cd build
$ make
\mkdir -p target1/objects
\mkdir -p target2/objects
cc -fPIC -I../sources/inc -I./target1/addsrc -c target1/addsrc/c.c -o target1/objects/c.o
cc -fPIC -I../sources/inc -I./target1/addsrc -c ../sources/src/a.c -o target1/objects/a.o
cc -fPIC -I../sources/inc -I./target1/addsrc -c ../sources/src/b.c -o target1/objects/b.o
cc -fPIC -I../sources/inc -I./target2/addsrc -c ../sources/src/a.c -o target2/objects/a.o
cc -fPIC -I../sources/inc -I./target2/addsrc -c ../sources/src/b.c -o target2/objects/b.o
cc -fPIC -I../sources/inc -shared -o target1/mylib.so target1/objects/c.o target1/objects/a.o target1/objects/b.o -lm
cc -fPIC -I../sources/inc -shared -o target2/mylib.so target2/objects/a.o target2/objects/b.o -lm
$ make clean
rm -rf target1/objects target2/objects target1/mylib.so target2/mylib.so
$ make target1
\mkdir -p target1/objects
cc -fPIC -I../sources/inc -I./target1/addsrc -c target1/addsrc/c.c -o target1/objects/c.o
cc -fPIC -I../sources/inc -I./target1/addsrc -c ../sources/src/a.c -o target1/objects/a.o
cc -fPIC -I../sources/inc -I./target1/addsrc -c ../sources/src/b.c -o target1/objects/b.o
cc -fPIC -I../sources/inc -shared -o target1/mylib.so target1/objects/c.o target1/objects/a.o target1/objects/b.o -lm
$ make target2
\mkdir -p target2/objects
cc -fPIC -I../sources/inc -I./target2/addsrc -c ../sources/src/a.c -o target2/objects/a.o
cc -fPIC -I../sources/inc -I./target2/addsrc -c ../sources/src/b.c -o target2/objects/b.o
cc -fPIC -I../sources/inc -shared -o target2/mylib.so target2/objects/a.o target2/objects/b.o -lm