如何通过makefile中的规则模式传递依赖性?
我的项目中有一条规则,可以从sourcecode生成库。我已经有可以编译%的功能。C
to %。o
,但是我将我的库代码拆分为以同一前缀开头的多个源文件。我在同一目录中有两个单独的库代码,但是它们的源文件具有不同的前缀,这就是为什么我试图为这两个库构建单个规则。但是我无法将代码库的前缀传递给依赖项来过滤所需的对象文件。
我拥有的规则是在我的makefile中:
# ...
BINDIR = bin
LIBDIR = lib
# ...
# These are all the libraries source files.
LIB_SOURCES = $(wildcard $(LIBDIR)/*.c)
# These are all the libraries "main" source files.
LIB_SRCS = $(filter-out $(wildcard $(LIBDIR)/*_*.c), $(LIB_SOURCES))
# These are all the source files to which I have exported some code from the "main" library source file.
LIB_CODE = $(filter-out $(LIB_SRCS), $(LIB_SOURCES))
# These are all the objects produced by compiling the c source files.
LIB_OBJS = $(patsubst %.c, %.o, $(LIB_CODE))
# ...
# These are all the libraries produced.
LIBS = $(patsubst $(LIBDIR)/%.c,$(BINDIR)/lib%.so,$(LIB_SRCS))
# ...
.PHONY: libs
# ...
%/:
mkdir -p $@
libs: $(BINDIR)/ $(LIBS)
.SECONDEXPANSION:
$(BINDIR)/lib%.so: $(LIBDIR)/%.o $(filter $(LIBDIR)/$*_%.o, $(LIB_OBJS))
@echo $(CC) $(CFLAGS) $(CLNKERFLAGS) -o $@ $^
$(LIBDIR)/%.o: $(LIBDIR)/%.c $(LIBDIR)/%.h
@echo $(CC) $(CFLAGS) -o $@ -c $<
目前我只打印(不完整)命令,但它仍然无法获得所需的所有对象的正确输出。
在目录lib
中,我有以下文件:
$ tree lib
lib
├── app.c
├── app_db.c
├── app_db.h
├── app.h
├── app_logic.c
├── app_logic.h
├── app_net.c
├── app_net.h
├── server.c
├── server.h
├── server_queue.c
└── server_queue.h
但是它永远不会正确构建依赖项。
$ make libs
gcc -Wpedantic -O3 -o lib/app.o -c lib/app.c
gcc -Wpedantic -O3 -o bin/libapp.so lib/app.o
gcc -Wpedantic -O3 -o lib/server.o -c lib/server.c
gcc -Wpedantic -O3 -o bin/libserver.so lib/server.o
我已经阅读了以下问题如何在制作模式规则中使用模式依赖的变量,我认为它会帮助我,但事实并非如此。
知道我该如何实现这一目标?
编辑1:
我希望最后一个命令的输出是:
$ make libs
gcc -Wpedantic -O3 -o lib/app.o -c lib/app.c
gcc -Wpedantic -O3 -o lib/app_db.o -c lib/app_db.c
gcc -Wpedantic -O3 -o lib/app_logic.o -c lib/app_logic.c
gcc -Wpedantic -O3 -o lib/app_net.o -c lib/app_net.c
gcc -Wpedantic -O3 -o bin/libapp.so lib/app.o lib/app_db.o lib/app_logic.o lib/app_net.o
gcc -Wpedantic -O3 -o lib/server.o -c lib/server.c
gcc -Wpedantic -O3 -o lib/server_queue.o -c lib/server_queue.c
gcc -Wpedantic -O3 -o bin/libserver.so lib/server.o lib/server_queue.o
感谢您的关注。
I have a rule in my project to generate libraries from sourcecode. I already have the function to compile %.c
to %.o
, but I split my library code in multiple source files that begin with the same prefix. I have two separate library code in the same directory, but their source files have different prefixes, that's why I am trying to build a single rule for both (or maybe more) libraries. But I can't pass the prefix of the codebase to the dependencies to filter the object files needed.
The rule I have is this in my Makefile:
# ...
BINDIR = bin
LIBDIR = lib
# ...
# These are all the libraries source files.
LIB_SOURCES = $(wildcard $(LIBDIR)/*.c)
# These are all the libraries "main" source files.
LIB_SRCS = $(filter-out $(wildcard $(LIBDIR)/*_*.c), $(LIB_SOURCES))
# These are all the source files to which I have exported some code from the "main" library source file.
LIB_CODE = $(filter-out $(LIB_SRCS), $(LIB_SOURCES))
# These are all the objects produced by compiling the c source files.
LIB_OBJS = $(patsubst %.c, %.o, $(LIB_CODE))
# ...
# These are all the libraries produced.
LIBS = $(patsubst $(LIBDIR)/%.c,$(BINDIR)/lib%.so,$(LIB_SRCS))
# ...
.PHONY: libs
# ...
%/:
mkdir -p $@
libs: $(BINDIR)/ $(LIBS)
.SECONDEXPANSION:
$(BINDIR)/lib%.so: $(LIBDIR)/%.o $(filter $(LIBDIR)/$*_%.o, $(LIB_OBJS))
@echo $(CC) $(CFLAGS) $(CLNKERFLAGS) -o $@ $^
$(LIBDIR)/%.o: $(LIBDIR)/%.c $(LIBDIR)/%.h
@echo $(CC) $(CFLAGS) -o $@ -c lt;
For the moment I just print the (incomplete) command, but it still doesn't get the correct output with all the objects needed.
In the directory lib
I have the following files:
$ tree lib
lib
├── app.c
├── app_db.c
├── app_db.h
├── app.h
├── app_logic.c
├── app_logic.h
├── app_net.c
├── app_net.h
├── server.c
├── server.h
├── server_queue.c
└── server_queue.h
But it never builds the dependencies correctly.
$ make libs
gcc -Wpedantic -O3 -o lib/app.o -c lib/app.c
gcc -Wpedantic -O3 -o bin/libapp.so lib/app.o
gcc -Wpedantic -O3 -o lib/server.o -c lib/server.c
gcc -Wpedantic -O3 -o bin/libserver.so lib/server.o
I have read the following question How to use pattern-dependent variables in dependencies in make pattern rules, which had a tip I thought it would help me, but it didn't.
Any idea how can I achive this?
EDIT 1:
I want the output of the last command to be:
$ make libs
gcc -Wpedantic -O3 -o lib/app.o -c lib/app.c
gcc -Wpedantic -O3 -o lib/app_db.o -c lib/app_db.c
gcc -Wpedantic -O3 -o lib/app_logic.o -c lib/app_logic.c
gcc -Wpedantic -O3 -o lib/app_net.o -c lib/app_net.c
gcc -Wpedantic -O3 -o bin/libapp.so lib/app.o lib/app_db.o lib/app_logic.o lib/app_net.o
gcc -Wpedantic -O3 -o lib/server.o -c lib/server.c
gcc -Wpedantic -O3 -o lib/server_queue.o -c lib/server_queue.c
gcc -Wpedantic -O3 -o bin/libserver.so lib/server.o lib/server_queue.o
Thanks for your attention.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您添加了
.secondexpansion
,但是您没有在先决条件列表中逃脱任何内容,因此它实际上没有做任何事情:这些变量/函数都没有逃脱,因此在初始读取过程中,此处的所有内容都扩展了 - 在,因此没有什么可做的。
次要扩展功能包括两个部分:首先,您可以使用特殊目标启用它。其次,您逃脱要延迟扩展的变量和/或函数。因此,这可能是:
请注意我们如何逃脱
$(getObjs)
作为$$(getObjs)
,以便在第二次通过之前不扩展此变量。You added
.SECONDEXPANSION
, but you didn't escape anything in the prerequisites list so it doesn't actually do anything:None of these variables/functions are escaped, so everything here is expanded during the initial read-in, so there's nothing for secondary expansion to do.
The secondary expansion feature consists of two parts: first, you enable it with the special target. Second, you escape the variables and/or functions you want to delay expansion of. So this could be:
Note how we escape the
$(getobjs)
as$$(getobjs)
so that this variable is not expanded until the second pass.通配符不是很聪明,您的方法要求它在一行中处理两种不同的通配符。如果有可能,那将是一件可怕的事情。我建议一种不同的方法。
首先,您的变量是错误的。目前尚不清楚您的意图是什么,但以下是适合您所需的结果的意图:
现在,您希望您的Makefile像有这两个规则一样行事:
但是,您不想在Makefile中拼写它们,而是想建立构建他们在运行时间。因此,我们将使用“ nofollow noreferrer”>“罐头食谱” :
然后,我们可以从
libs
:Make isn't very deft with wildcards, and your approach requires it to handle two different wildcards in one line. If that's possible at all, it will be a terrible thing to see. I suggest a different approach.
First, your variables are wrong. It's not clear what your intention was, but here are the ones that fit your desired results:
Now, you want your makefile to act as if it had these two rules:
But rather than spelling them out in the makefile, you want Make to build them at run time. So we'll use a "canned recipe":
Then rather than writing those last two lines in the makefile, specifying
app
andserver
, we can have Make extract them fromLIBS
: