Makefile语法:静态库lib $(库).a($ objects)

时间:2010-12-16 02:41:01

标签: c++ makefile static-libraries

我正在更新一些Makefile,从Make 3.81升级到3.82。在多个地方,原作者使用这样的东西来构建静态库:

all: lib$(library).a($objects)

这似乎依次构建每个.o文件并使用ar:

将其插入.a文件中
g++ -O2 <snip> -o some_obj.o some_cpp.cpp
ar rv libsome_lib.a some_obj.o
etc...

然而,这个新的制作版本窒息:

*** No rule to make target 'libsome_lib.a()', needed by 'all'

我可以安全地用我习惯的方式替换这个快捷方式:

lib$(library).a: $(objects)
     ar -rs lib$(library).a $objects

感谢。

修改

看起来我需要更好的Makefile教育。这是原始Makefile的更大摘录:

CXXFLAGS += -O2 -g -Wall -Wunused-parameter \
    `pkg-config --cflags gthread-2.0 glibmm-2.4 gtkmm-2.4`

libs +=  `pkg-config --libs gthread-2.0 glibmm-2.4` -lc

%.d: %.cpp
    $(SHELL) -ec '$(CXX) -M $(CPPFLAGS) $(CXXFLAGS) $< \
                      | sed '\''s/\($*\)\.o[ :]*/\1.o $@ : /g'\'' > $@; \
                      [ -s $@ ] || rm -f $@'
%.d: %.c
    $(SHELL) -ec '$(CXX) -M $(CPPFLAGS) $(CXXFLAGS) $< \
                      | sed '\''s/\($*\)\.o[ :]*/\1.o $@ : /g'\'' > $@; \
                      [ -s $@ ] || rm -f $@'

from_sources = $(patsubst %.c,$(2),$(filter %.c, $(1)))  $(patsubst %.cpp,$(2),$(filter %.cpp, $(1)))

sources = $(shell cat sources.inc)
objects = $(call from_sources,$(sources),%.o)
depends = $(call from_sources,$(sources),%.d)

library = some_lib

.PHONY: all clean fresh

all: lib$(library).a($(objects))

clean:
    <SNIP>

if neq($(MAKECMDGOALS),clean)
    include $(depends)
endif

当它在3.81下运行时,我会创建所有.d依赖项,然后启动g ++ ing obj文件。在3.82之下,我得到了.d文件,但是没有.o并且因为“***没有规则制作......”而失败了。

3 个答案:

答案 0 :(得分:4)

这是&#34;档案会员&#34; gnu make支持的语法。对于我的口味来说,这个工具有点过于贴心,但事实确实如此。原始错误可能是由$(对象)为空引起的。但我真的不确定。这是一些文档:

http://www.gnu.org/software/make/manual/make.html#Archive-Members

  

11.1将成员存档为目标

     

存档文件的单个成员可用作目标或   制作的先决条件。您在归档中指定名为member的成员   文件存档如下:

 archive(member)
     

此构造仅在目标和先决条件中可用,而不在食谱中可用!您可能使用的大多数程序   食谱不支持此语法,不能直接对存档执行操作   成员。只有ar和其他专门设计用于运营的程序   档案馆可以这样做。因此,更新存档的有效配方   成员目标可能必须使用ar。例如,这条规则说   通过复制文件hack.o:

在archive foolib中创建一个成员hack.o
 foolib(hack.o) : hack.o
         ar cr foolib hack.o
     

事实上,几乎所有的归档成员目标都是以这种方式更新的,并且有一个隐含的规则   为你而做。请注意:如果是,则需要ar的'c'标志   存档文件尚不存在。

答案 1 :(得分:3)

你的方式看起来不错,但如果旧的方式有效,那么旧的makefile必须有更多。

哦,只是表现良好,我建议:

lib$(library).a: $(objects)
     ar -rs $@ $^

修改
不理解不理解做得很好;它有相当的学习曲线。

此处仍然不够,但如果sources.inc不是太大,您可以在3.81和3.82中尝试以下内容并寻找差异:

experiment:
    @echo sources: $(sources)
    @echo objects: $(objects)
    @echo depends: $(depends)

到目前为止的证据是objects在3.82下是空的,但是如果.d文件在3.82下重建,则表明depends 不是空的,这很奇怪。

答案 2 :(得分:1)

可能,但您没有明确的规则可以将xyz.cpp转换为xyz.o之类的内容,在尝试将对象注入库之前,您可能需要这些内容。 可能是适合的隐含规则,因此请先检查。

我要问的第一个问题是:$objects发生了什么导致你首先尝试定位libsome_lib.a()(即括号之间没有任何内容)?

说实话,我倾向于尽可能地避免这些包含规则,更喜欢显式依赖关系语句(当然,除非存在 lot 依赖关系)。是的,我知道它会使makefile更大并且标记我至少是一个部分luddite,但我更喜欢让事情适用于巧妙运作的东西。

Cut'n'paste是我工具箱中最强大的工具之一: - )