【问题标题】:How do I compile a static library如何编译静态库
【发布时间】:2012-07-05 12:40:07
【问题描述】:

我正在尝试编译一个静态库。我按照this question 的答案中给出的步骤操作,但它不起作用。以下是我的makefile。

PROJECT = lq.a
OBJECTS = dlmalloc.o queue.o.o
CFLAGS  = -o -Wall -pedantic

all: $(PROJECT)

.c.o:
    gcc -c $(CFLAGS) $<

$(PROJECT): $(OBJECTS)
    libtool -o  $(PROJECT) -static $(OBJECTS)

我收到以下错误。

libtool: unrecognized option `-o'

编写这个makefile的正确方法是什么?

【问题讨论】:

    标签: c linux gcc x86-64


    【解决方案1】:

    您可以使用以下语法使用程序arto create static libraries

     ar rcs my_library.a file1.o file2.o
    

    所以,在你的情况下:

    $(PROJECT): $(OBJECTS)
         ar rcs $(PROJECT) $(OBJECTS)
    

    你可以在the man page上找到选项的解释,但基本上:

    • r 表示将给定的目标文件插入存档(替换同一事物的任何旧版本)
    • c 说如果存档不存在则创建存档(通常无论如何都会发生这种情况,但此选项会抑制警告)。
    • s 表示将目标文件索引写入存档。

    【讨论】:

      【解决方案2】:

      嗯,这很令人困惑;但我认为libtool -o $(PROJECT) -static $(OBJECTS) 行(objective c - Combine static libraries 中也提到)来自 Mac;显然libtool 与 Linux 上的 相同:

      libtool or ar & ranlib - idevgames forums:

      我正在使用 libtool 在 OS X 上创建一个静态库,因为这就是 Xcode 所做的,它似乎工作正常。然后我转到 Linux,它被我的 libtool 命令阻塞,说“libtool:无法识别的选项'-o'”。看着它们,似乎 OS X 上的 libtool 和 Linux 上的 libtool 是两个完全不同的程序。 ...
      跟进:是的,Linux 上的 libtool 似乎确实是 OS X 上的 glibtool。在 OS X 上执行“glibtool --help”时,我得到的输出与 Linux 上的“libtool --help”基本相同。

      好的,这解释了差异 - 但仍然没有解释-o 如何成为无法识别的选项,当我刚刚看到它从 Linux 上的 Makefile 运行时!所以我发现了这个:

      bug-libtool mailing list (2001): Re: bug in libtool?

      你需要在模式选项之前设置模式:

      $ libtool --mode=link --help
      用法:libtool [OPTION]... --mode=link LINK-COMMAND...

      天哪……现在特别令人困惑的是,libtool --mode=link --help 中的这条注释:

      $ libtool --mode=link --help
      Usage: libtool [OPTION]... --mode=link LINK-COMMAND...
      ...
      
      LINK-COMMAND is a command using the C compiler that you would use to create
      a program from several object files.
      
      The following components of LINK-COMMAND are treated specially: ...
        -all-static       do not do any dynamic linking at all ...
        -o OUTPUT-FILE    create OUTPUT-FILE from the specified objects ...
        -static           do not do any dynamic linking of uninstalled libtool libraries
      ...
      All other options (arguments beginning with `-') are ignored.
      
      Every other argument is treated as a filename.  Files ending in `.la' are
      treated as uninstalled libtool libraries, other files are standard or library
      object files.
      ...
      If OUTPUT-FILE ends in `.a' or `.lib', then a standard library is created
      using `ar' and `ranlib', or on Windows using `lib'.
      

      所以 - 如果我 必须 指定 LINK-COMMAND - 同时,我指定一个以 .a 结尾的 OUTPUT-FILE;然后应该运行哪个命令,LINK-COMMAND - 或扩展名.a 指定的ar+ranlib?好吧 - 这是一个终端 sn-p,只是测试 libtoolbash 脚本逻辑 - 没有任何编译(尽管确实创建了一个空存档):

      $ libtool -o test.a
      libtool: unrecognized option `-o'
      libtool: Try `libtool --help' for more information.
      
      $ libtool --mode=link -o test.a
      libtool: link: unrecognized option `-o'
      libtool: link: Try `libtool --help' for more information.
      
      $ libtool --mode=link gcc -o test.a
      libtool: link: ar cru test.a
      libtool: link: ranlib test.a
      
      $ libtool --mode=link ar -o test.a
      libtool: link: unable to infer tagged configuration
      libtool: link: specify a tag with `--tag'
      
      $ cat $(which libtool) | grep "^# ### BEGIN LIBTOOL TAG CONFIG:"
      # ### BEGIN LIBTOOL TAG CONFIG: disable-shared
      # ### BEGIN LIBTOOL TAG CONFIG: disable-static
      # ### BEGIN LIBTOOL TAG CONFIG: CXX
      # ### BEGIN LIBTOOL TAG CONFIG: F77
      # ### BEGIN LIBTOOL TAG CONFIG: FC
      # ### BEGIN LIBTOOL TAG CONFIG: GCJ
      # ### BEGIN LIBTOOL TAG CONFIG: RC
      # ### BEGIN LIBTOOL TAG CONFIG: BINCC
      # ### BEGIN LIBTOOL TAG CONFIG: BINCXX
      
      ## CC tag is not listed, but it will (eventually) be accepted:
      
      $ libtool --mode=link ar --tag CC -o test.a
      libtool: link: unable to infer tagged configuration
      libtool: link: specify a tag with `--tag'
      
      $ libtool --mode=link --tag CC ar -o test.a
      libtool: link: ar cru test.a
      libtool: link: ranlib test.a
      
      $ libtool --tag=CC --mode=link ar -o test.a
      libtool: link: ar cru test.a
      libtool: link: ranlib test.a
      
      $ libtool --tag=XX --mode=link ar -o test.a
      libtool: ignoring unknown tag XX
      libtool: link: ar cru test.a
      libtool: link: ranlib test.a
      
      $ libtool --tag=XX --mode=link whatevar -o test.a
      libtool: ignoring unknown tag XX
      libtool: link: ar cru test.a 
      libtool: link: ranlib test.a
      
      $ ls -la test.a 
      -rw-r--r-- 1 user user 8 2013-04-17 23:12 test.a
      

      所以 - 你不仅必须指定--mode,而且如果这个模式是link,你必须指定某种类型的参数(LINK-COMMAND)来引用工具;但是那个 LINK-COMMAND 参数甚至不需要作为一个 real 程序存在——因为无论如何你都必须指定一个输出文件;如果该输出文件以.a 结尾,它将强制使用ar/ranlib 无论如何

      此外,如果您对标签有疑问 - 只需将 --tag 参数移到 LINK-COMMAND 参数之前 - 您可以强制 libtool 使用不存在的标签和不存在的 LINK 运行 - COMMAND(其操作仅由输出文件的扩展名.a 指定)——只要以libtool 语法的正确顺序输入参数;我必须承认,脚本本身并没有真正记录这一点。


      但是回到 Mac libtool -o $(PROJECT) -static $(OBJECTS) 行,它将结合静态库;如果您尝试对正确的静态库 .a 文件执行相同操作,您会注意到 libtool 在输出存档中推送 .a 存档原样不是 它们的组成对象文件 - 所以这个输出不再是一个有效的 ELF 对象;这是一个相应的 Linux libtool 行的示例,其中包含我生成的两个正确的库文件:

      $ readelf --syms libmy1.a
      File: libmy1.a(my1.o)
      Symbol table '.symtab' contains 11 entries:
      ...
      $ readelf --syms libmy2.a
      File: libmy2.a(my2.o)
      Symbol table '.symtab' contains 12 entries:
      ...
      $ libtool --mode=link --tag=CC ar -o libtest.a -static libmy1.a libmy2.a 
      libtool: link: ar cru libtest.a libmy1.a libmy2.a 
      libtool: link: ranlib libtest.a
      
      $ readelf --syms libtest.a
      readelf: Error: Not an ELF file - it has the wrong magic bytes at the start
      readelf: Error: libtest.a(libmy1.a): Failed to read file header
      readelf: Error: Not an ELF file - it has the wrong magic bytes at the start
      readelf: Error: libtest.a(libmy2.a): Failed to read file header
      

      因此,正如 accepted answer 所说 - 在 Linux 上,手动使用 ar 解包并再次打包,以组合静态库。

      希望这对某人有所帮助,
      干杯!

      【讨论】:

        【解决方案3】:

        要么使用libtool,要么不使用。如果您要使用它,那么您应该使用libtool --mode=compile 编译各个文件并使用libtool --mode=link 链接。如果您不打算使用libtool,那么您的链接也应该使用gcc 完成,正如另一个答案中所指出的那样。另外,你试过man libtool吗?

        【讨论】:

        • 我试过man libtool,一点也不明显,为什么-o在Linux上是一个无法识别的选项;但是通过正确的参数顺序,它可以被识别(见我的回答here)。
        • libtool 不接受选项-o,因此它是一个“无法识别的选项”。一旦您指定了--mode=&lt;something&gt; 选项来告诉libtool 要做什么,则可以将更多选项传递给libtool 调用的工具。所以libtool --mode=link -o something 可能没问题,但libtool -o something 不是。无论哪种方式,您都应该在编译和链接阶段都使用libtool,或者根本不使用它——您只是在使用gcc 编译但libtool 链接来询问混淆。
        【解决方案4】:

        以下命令将构建您的静态库:

        $gcc -c file1.c -o libfile.o
        $ar rcs libfile.a libfile.o
        

        【讨论】:

          猜你喜欢
          • 2015-12-01
          • 1970-01-01
          • 1970-01-01
          • 2012-05-24
          • 1970-01-01
          • 2011-07-05
          • 2011-02-13
          • 1970-01-01
          相关资源
          最近更新 更多