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 target1
或 make 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 variables(LDFLAGS
、CC
、LDLIBS
...),而不是您使用的功能.
头文件中的依赖关系没有表达,因为你没有解释它们应该是什么。适应
演示:
$ 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
我正在为 make 语言苦苦挣扎,但尚未实现我的目标。 我有以下文件夹结构。
/sources/src => *.c
/sources/inc => *.h
/build => makefile
/build/target1/addsrc => *.c & *.h
/build/target2/addsrc => *.c & *.h
我想使用命令 make
编译两个目标或使用命令 make target1
或 make 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 variables(LDFLAGS
、CC
、LDLIBS
...),而不是您使用的功能.
头文件中的依赖关系没有表达,因为你没有解释它们应该是什么。适应
演示:
$ 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