首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用stem制作隐式归档规则

用stem制作隐式归档规则
EN

Stack Overflow用户
提问于 2014-03-26 13:28:02
回答 3查看 1.3K关注 0票数 5

根据目标文件扩展名,我试图设置一个Makefile来构建静态(.a)和动态(.so)库。

我以前只对静态库使用了以下Makefile:

代码语言:javascript
复制
NAME   := config
LIB    := lib$(NAME).a
SRC    := $(wildcard *.c)
OBJ    := $(SRC:.c=.o)
CFLAGS += -W -Wall

.PHONY: all clean fclean re

all: $(LIB)

clean:
    @$(RM) $(OBJ)

fclean: clean
    @$(RM) $(LIB)

re: fclean all

$(LIB): $(LIB)($(OBJ))
    ranlib $@

我的主要目标是仅通过更改LIB NAME**variables.**和NAME**variables.**来编译多个库

一切都很好,所以我为动态库添加了以下内容:

代码语言:javascript
复制
LDFLAGS += -shared

%.so: CFLAGS += -fPIC
%.so: $(OBJ)
    $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^

并将$(LIB):规则更改为以下泛型规则:

代码语言:javascript
复制
%.a: %.a($(OBJ))
    ranlib $@

如果我将LIB更改为lib$(NAME).so,一切工作正常,但使用.a扩展时,请打印此错误:

make: *** No rule to make target 'libconfig.a', needed by 'all'. Stop.

我找到的唯一解决方案是添加,另一个类似于的显式规则:

代码语言:javascript
复制
%.a($(OBJ)): $(OBJ)
    $(AR) rv $@ $^

现在一切都正常了。

但是,添加这个显式规则可以防止我只依赖GNU make的隐式规则,并且使我可以显式地调用ar,这是我想要避免的。

这是某种虫子还是我漏掉了什么?

代码语言:javascript
复制
GNU Make 3.82
Built for x86_64-unknown-linux-gnu
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-06-22 11:04:30

归档库和共享库并不共享相同的先决条件语法,因此不可能有一个处理两者的单一规则。

最简单的解决方案是在目标扩展上使用有条件的

代码语言:javascript
复制
ifeq "$(suffix $(LIB))" ".a"
$(LIB): $(LIB)($(OBJ))
else ifeq "$(suffix $(LIB))" ".so"
$(LIB): override CFLAGS += -fPIC
$(LIB): $(OBJ)
    $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
endif

满足要求的工作Makefile现在看起来如下所示:

代码语言:javascript
复制
NAME := config

LIB := lib$(NAME).so

SRC := $(wildcard *.c)
OBJ := $(SRC:.c=.o)
DEP := $(OBJ:.o=.d)

CPPFLAGS := -MMD -MP
CFLAGS   := -W -Wall
LDFLAGS  := -shared
ARFLAGS  := rs

.PRECIOUS: $(OBJ)
.PHONY: all clean fclean re

all: $(LIB)

clean:
    $(RM) $(OBJ) $(DEP)

fclean: clean
    $(RM) $(LIB)

re: fclean all

ifeq "$(suffix $(LIB))" ".a"
$(LIB): $(LIB)($(OBJ))
else ifeq "$(suffix $(LIB))" ".so"
$(LIB): override CFLAGS += -fPIC
$(LIB): $(OBJ)
    $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
endif

ifeq "$(MAKECMDGOALS)" ""
-include $(DEP)
endif

注意,ARFLAGS变量控制哪些标志传递给ar调用。在这里,我使用r标志来替换存在的现有对象,并使用s标志来构建或更新索引(不再需要使用ranlib)。

票数 0
EN

Stack Overflow用户

发布于 2014-03-26 14:39:58

一些快速测试似乎表明这是不可能的。看来专门的make归档支持是makefile解析时间特性。也就是说,文字存档名称必须存在于实际的makefile中,才能生效。

我尝试了几种解决办法,但都没能让其中任何一个正确地工作。我能做的最接近的事情是:

代码语言:javascript
复制
$(foreach a,$(filter %.a,$(MAKECMDGOALS) $(.DEFAULT_GOAL)),$(eval $a: $a($$(OBJ)); ranlib $$@))

它不适用于all的默认目标,但如果默认值是库名和/或库名是显式的make目标,则会这样做。您也可以将任何其他已知的库名称都放入其中,然后它们甚至应该作为其他目标的隐式需求工作,但这是一个手动过程。

票数 4
EN

Stack Overflow用户

发布于 2014-03-26 18:13:53

您需要知道给定的.o文件所依赖的是哪个.a文件。您可以通过简单的悬垂而不采取任何行动来完成这一任务:

代码语言:javascript
复制
libconfig.a: libconfig.a($(OBJ))

然后,make将调用将.o文件放入.a文件的默认规则,以实际构建libconfig.a

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22662501

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档