根据目标文件扩展名,我试图设置一个Makefile来构建静态(.a)和动态(.so)库。
我以前只对静态库使用了以下Makefile:
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.**来编译多个库
一切都很好,所以我为动态库添加了以下内容:
LDFLAGS += -shared
%.so: CFLAGS += -fPIC
%.so: $(OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^并将$(LIB):规则更改为以下泛型规则:
%.a: %.a($(OBJ))
ranlib $@如果我将LIB更改为lib$(NAME).so,一切工作正常,但使用.a扩展时,请打印此错误:
make: *** No rule to make target 'libconfig.a', needed by 'all'. Stop.
我找到的唯一解决方案是添加,另一个类似于的显式规则:
%.a($(OBJ)): $(OBJ)
$(AR) rv $@ $^现在一切都正常了。
但是,添加这个显式规则可以防止我只依赖GNU make的隐式规则,并且使我可以显式地调用ar,这是我想要避免的。
这是某种虫子还是我漏掉了什么?
GNU Make 3.82
Built for x86_64-unknown-linux-gnu发布于 2015-06-22 11:04:30
归档库和共享库并不共享相同的先决条件语法,因此不可能有一个处理两者的单一规则。
最简单的解决方案是在目标扩展上使用有条件的:
ifeq "$(suffix $(LIB))" ".a"
$(LIB): $(LIB)($(OBJ))
else ifeq "$(suffix $(LIB))" ".so"
$(LIB): override CFLAGS += -fPIC
$(LIB): $(OBJ)
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
endif满足要求的工作Makefile现在看起来如下所示:
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)。
发布于 2014-03-26 14:39:58
一些快速测试似乎表明这是不可能的。看来专门的make归档支持是makefile解析时间特性。也就是说,文字存档名称必须存在于实际的makefile中,才能生效。
我尝试了几种解决办法,但都没能让其中任何一个正确地工作。我能做的最接近的事情是:
$(foreach a,$(filter %.a,$(MAKECMDGOALS) $(.DEFAULT_GOAL)),$(eval $a: $a($$(OBJ)); ranlib $$@))它不适用于all的默认目标,但如果默认值是库名和/或库名是显式的make目标,则会这样做。您也可以将任何其他已知的库名称都放入其中,然后它们甚至应该作为其他目标的隐式需求工作,但这是一个手动过程。
发布于 2014-03-26 18:13:53
您需要知道给定的.o文件所依赖的是哪个.a文件。您可以通过简单的悬垂而不采取任何行动来完成这一任务:
libconfig.a: libconfig.a($(OBJ))然后,make将调用将.o文件放入.a文件的默认规则,以实际构建libconfig.a
https://stackoverflow.com/questions/22662501
复制相似问题