6

我正在尝试编译一个静态库。我按照这个问题的答案中给出的步骤进行操作,但它不起作用。以下是我的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的正确方法是什么?

4

4 回答 4

12

您可以使用该程序使用以下语法ar 创建静态库:

 ar rcs my_library.a file1.o file2.o

所以,在你的情况下:

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

您可以在手册页上找到有关选项的说明,但基本上:

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

好吧,这很令人困惑;但我认为这libtool -o $(PROJECT) -static $(OBJECTS)条线(也在objective c - Combine static libraries中提到)来自Mac;显然与Linuxlibtool上的一样:

libtool 或 ar & ranlib - idevgames 论坛

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

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

bug-libtool 邮件列表 (2001): Re: libtool 中的错误?

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

$ libtool --mode=link --help
用法:libtool [选项]... --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-同时,我指定一个以;OUTPUT-FILE结尾的 .a然后应该运行哪个命令,LINK-COMMAND- 或扩展指定的ar+ ?好吧 - 这是一个终端片段,只是测试 - 没有任何编译的脚本逻辑(尽管确实创建了一个空存档):ranlib.abashlibtool

$ 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

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

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


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

$ 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

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

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

于 2013-04-17T21:21:41.923 回答
3

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

于 2012-07-05T13:56:14.923 回答
2

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

$gcc -c file1.c -o libfile.o
$ar rcs libfile.a libfile.o
于 2012-07-05T13:40:57.930 回答