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

发布于 2025-01-12 22:18:39 字数 1537 浏览 2 评论 0原文

我正在与 make 语言作斗争,但尚未达到我的目标。 我有以下文件夹结构。

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

我想使用命令 make 编译两个目标,或者使用命令 make target1make target2 之一单独编译任何目标。每个目标都使用位于sources文件夹中的相同源,添加位于其自己的addsrc文件夹中的其他源,并应用不同的编译标志。 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 $@

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

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

I'm struggling with the make language and haven't been yet able to reach my goal.
I have the following folder structure.

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

I want to compile both target using the command make or any target separately using one of the commands make target1 or make target2. Each target uses the same sources located in the sources folder, adds additional sources located its own addsrc folder and applies different compilation flags. The makefile should create the following directories and files:

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

I tried with the following 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 
lt; -o $@

This works for the directory initialisation for each target. However, the rest is absolutely not working. I spent hours to have it working but without any success. Any help would be appreciated. Thanks !

Note: I haven't worked yet on the target dependency regarding the compilation flags.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

过潦 2025-01-19 22:18:39

既然您有 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 
lt; -o $@

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

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

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

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

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

这会利用 GNU make 的特定功能,尤其是 foreach-eval-call。它还对目录使用仅订购先决条件 ,以及标准 make 变量LDFLAGSCCLDLIBS...)而不是您正在使用的那些。

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

演示:

$ 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

As you have the gnu-make tag let's use 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 
lt; -o $@

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

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

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

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

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

This makes use of GNU make specific features, especially the foreach-eval-call. It also uses order-only prerequisites for the directories, and the the standard make variables (LDFLAGS, CC, LDLIBS...) instead of the ones you were using.

Dependencies in the header files are not expressed because you do not explain what they should be. Adapt.

Demo:

$ 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文