如何编译静态库?

时间:2023-01-13 16:18:44

I am trying to compile a static library. I followed the steps which were given in an answer to this question but it is not working. Following is my makefile.

我正在尝试编译一个静态库。我遵循了回答这个问题的步骤,但它不起作用。下面是我的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)

And I get the following error.

我得到了下面的错误。

libtool: unrecognized option `-o'

What is the correct way of writing this makefile?

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

4 个解决方案

#1


6  

You can use the program ar to create static libraries using the following syntax:

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

 ar rcs my_library.a file1.o file2.o

So, in your case:

所以,在你的情况:

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

You can find an explanation of the options on the man page, but basically:

你可以在手册页找到解释,但基本上:

  • r says insert the given object files in to the archive (replacing any older versions of the same thing)
  • r表示将给定的对象文件插入到存档中(替换任何旧版本的相同内容)
  • c says create the archive if it isn't already there (normally this happens anyway, but this option suppresses the warning).
  • c说如果它不在那里,创建存档(通常情况下是这样的,但是这个选项会抑制警告)。
  • s says to write an object-file index into the archive.
  • s表示将对象文件索引写入存档。

#2


3  

Either use libtool or don't. If you're going to use it, then you should compile the individual files with libtool --mode=compile as well as linking with libtool --mode=link. If you're not going to use libtool, then your link should be done with gcc also, as pointed out in another answer. Also, have you tried man libtool?

要么使用libtool,要么不使用。如果您打算使用它,那么您应该使用libtool—mode=compile以及链接libtool—mode=link来编译单个文件。如果您不打算使用libtool,那么您的链接应该与gcc一起完成,就像在另一个答案中指出的那样。还有,你试过人类libtool吗?

#3


2  

Well, this is confusing; but I think that the libtool -o $(PROJECT) -static $(OBJECTS) line (also mentioned in objective c - Combine static libraries) comes from Mac; and apparently the libtool there is NOT the same as the one on Linux:

这是令人困惑;但是我认为libtool -o $(项目)-静态$(对象)行(也在objective c -组合静态库中提到)来自Mac;显然,libtool和Linux上的是不一样的:

libtool or ar & ranlib - idevgames forums:

libtool或ar & ranlib - idevgames论坛:

I was using libtool to create a static library on OS X because that's what Xcode was doing, which seems to work fine. Then I go over to Linux and it chokes on my libtool command saying "libtool: unrecognized option '-o'". Looking at them, it seems like libtool on OS X and libtool on Linux are two completely different programs. ...
Followup: Yes, it appears that libtool on Linux is indeed glibtool on OS X. I get essentially the same output when doing "glibtool --help" on OS X as "libtool --help" on Linux.

我使用libtool在OS X上创建一个静态库,因为Xcode就是这么做的,这看起来很好。然后我转到Linux,它在我的libtool命令上说“libtool:未被识别的选项‘-o’”。看看它们,在Linux上的OS X和libtool上的libtool似乎是两个完全不同的程序。后续:是的,在Linux上的libtool确实是OS X上的glibtool,在使用“glibtool—help”在OS X上作为“libtool—help”在Linux上,我得到了基本相同的输出。

Ok, that explains the difference - but still doesn't explain how -o can be an unrecognized option, when I've just seen it run from a Makefile on Linux! So I found this:

好的,这就解释了区别——但是仍然没有解释为什么-o是一个无法识别的选项,当我刚刚看到它从Linux的Makefile中运行时!所以我发现了这个:

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

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

You need to set the mode before the mode options:

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

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

$ libtool—mode=link—帮助使用:libtool[选项]…——模式=链接link命令……

Oh dear... now what makes it especially confusing, is this note in libtool --mode=link --help:

哦亲爱的…现在,让它特别令人困惑的是,在libtool—mode=link—帮助下的注释:

$ 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'.

So - if I have to specify a LINK-COMMAND - and at the same time, I specify an OUTPUT-FILE which ends in .a; which command should then run, LINK-COMMAND - or the ar+ranlib that extension .a specifies? Well - here's a terminal snippet, just testing the bash script logic of libtool - without any compilation (though an empty archive does get created):

因此,如果我必须指定一个链接命令,同时,我指定一个输出文件,它以。哪个命令应该运行,链接命令-或者ar+ranlib扩展。指定?这里有一个终端片段,只是测试libtool的bash脚本逻辑——没有任何编译(尽管一个空的存档会被创建):

$ 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

So - not only do you have to specify a --mode, but if this mode is link, you MUST specify SOME sort of an argument (LINK-COMMAND) referring to a tool; BUT that LINK-COMMAND argument doesn't even need to exist as a real program - because you must specify an output file anyway; and if that output file ends on .a, it will enforce use of ar/ranlib anyways.

因此,您不仅必须指定一个模式,而且如果该模式是链接,您必须指定某种类型的参数(链接命令),指的是工具;但是,链接命令参数甚至不需要作为一个真正的程序存在——因为无论如何,您必须指定一个输出文件;如果输出文件以a结束,它将会强制使用ar/ranlib。

Also, should you have a problem with a tag - simply move the --tag argument before the LINK-COMMAND argument - and you can force libtool to run with a non-existing tag and a non-existing LINK-COMMAND (where it's operation is specified solely by the extension .a of the output file) - as long as the arguments are entered in the proper order for the libtool syntax; which I must admit isn't really documented in the script itself.

同时,如果您有一个标签的问题,简单地移动——标签参数link命令参数之前,你可以用一个不存在强迫libtool运行标签和一个不存在的link命令(的操作完全由指定输出文件的扩展。)——只要输入的参数在适当的顺序libtool语法;我必须承认,这并不是脚本本身所记录的。


But to come back to the Mac libtool -o $(PROJECT) -static $(OBJECTS) line, which would combine static libraries; if you try to do the same with proper static library .a files, you will notice that libtool pushes the .a archives as such in the output archive, not their constituent object files - so this output is not a valid ELF object anymore; here is an example of a corresponding Linux libtool line, with two proper library files I've generated:

但是回到Mac libtool -o $(项目)-静态$(对象)行,它将组合静态库;如果您试图使用适当的静态库来执行相同的操作,那么您会注意到libtool将一个存档文件推到输出归档文件中,而不是它们的组成对象文件,因此这个输出不再是一个有效的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

So, as the accepted answer says - on Linux, use ar manually to unpack and pack again, to combine static libraries.

因此,正如所接受的答案所说——在Linux上,使用ar手动打开并打包,以组合静态库。

Hope this helps someone,
Cheers!

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

#4


0  

The following commands will build your static library:

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

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

#1


6  

You can use the program ar to create static libraries using the following syntax:

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

 ar rcs my_library.a file1.o file2.o

So, in your case:

所以,在你的情况:

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

You can find an explanation of the options on the man page, but basically:

你可以在手册页找到解释,但基本上:

  • r says insert the given object files in to the archive (replacing any older versions of the same thing)
  • r表示将给定的对象文件插入到存档中(替换任何旧版本的相同内容)
  • c says create the archive if it isn't already there (normally this happens anyway, but this option suppresses the warning).
  • c说如果它不在那里,创建存档(通常情况下是这样的,但是这个选项会抑制警告)。
  • s says to write an object-file index into the archive.
  • s表示将对象文件索引写入存档。

#2


3  

Either use libtool or don't. If you're going to use it, then you should compile the individual files with libtool --mode=compile as well as linking with libtool --mode=link. If you're not going to use libtool, then your link should be done with gcc also, as pointed out in another answer. Also, have you tried man libtool?

要么使用libtool,要么不使用。如果您打算使用它,那么您应该使用libtool—mode=compile以及链接libtool—mode=link来编译单个文件。如果您不打算使用libtool,那么您的链接应该与gcc一起完成,就像在另一个答案中指出的那样。还有,你试过人类libtool吗?

#3


2  

Well, this is confusing; but I think that the libtool -o $(PROJECT) -static $(OBJECTS) line (also mentioned in objective c - Combine static libraries) comes from Mac; and apparently the libtool there is NOT the same as the one on Linux:

这是令人困惑;但是我认为libtool -o $(项目)-静态$(对象)行(也在objective c -组合静态库中提到)来自Mac;显然,libtool和Linux上的是不一样的:

libtool or ar & ranlib - idevgames forums:

libtool或ar & ranlib - idevgames论坛:

I was using libtool to create a static library on OS X because that's what Xcode was doing, which seems to work fine. Then I go over to Linux and it chokes on my libtool command saying "libtool: unrecognized option '-o'". Looking at them, it seems like libtool on OS X and libtool on Linux are two completely different programs. ...
Followup: Yes, it appears that libtool on Linux is indeed glibtool on OS X. I get essentially the same output when doing "glibtool --help" on OS X as "libtool --help" on Linux.

我使用libtool在OS X上创建一个静态库,因为Xcode就是这么做的,这看起来很好。然后我转到Linux,它在我的libtool命令上说“libtool:未被识别的选项‘-o’”。看看它们,在Linux上的OS X和libtool上的libtool似乎是两个完全不同的程序。后续:是的,在Linux上的libtool确实是OS X上的glibtool,在使用“glibtool—help”在OS X上作为“libtool—help”在Linux上,我得到了基本相同的输出。

Ok, that explains the difference - but still doesn't explain how -o can be an unrecognized option, when I've just seen it run from a Makefile on Linux! So I found this:

好的,这就解释了区别——但是仍然没有解释为什么-o是一个无法识别的选项,当我刚刚看到它从Linux的Makefile中运行时!所以我发现了这个:

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

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

You need to set the mode before the mode options:

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

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

$ libtool—mode=link—帮助使用:libtool[选项]…——模式=链接link命令……

Oh dear... now what makes it especially confusing, is this note in libtool --mode=link --help:

哦亲爱的…现在,让它特别令人困惑的是,在libtool—mode=link—帮助下的注释:

$ 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'.

So - if I have to specify a LINK-COMMAND - and at the same time, I specify an OUTPUT-FILE which ends in .a; which command should then run, LINK-COMMAND - or the ar+ranlib that extension .a specifies? Well - here's a terminal snippet, just testing the bash script logic of libtool - without any compilation (though an empty archive does get created):

因此,如果我必须指定一个链接命令,同时,我指定一个输出文件,它以。哪个命令应该运行,链接命令-或者ar+ranlib扩展。指定?这里有一个终端片段,只是测试libtool的bash脚本逻辑——没有任何编译(尽管一个空的存档会被创建):

$ 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

So - not only do you have to specify a --mode, but if this mode is link, you MUST specify SOME sort of an argument (LINK-COMMAND) referring to a tool; BUT that LINK-COMMAND argument doesn't even need to exist as a real program - because you must specify an output file anyway; and if that output file ends on .a, it will enforce use of ar/ranlib anyways.

因此,您不仅必须指定一个模式,而且如果该模式是链接,您必须指定某种类型的参数(链接命令),指的是工具;但是,链接命令参数甚至不需要作为一个真正的程序存在——因为无论如何,您必须指定一个输出文件;如果输出文件以a结束,它将会强制使用ar/ranlib。

Also, should you have a problem with a tag - simply move the --tag argument before the LINK-COMMAND argument - and you can force libtool to run with a non-existing tag and a non-existing LINK-COMMAND (where it's operation is specified solely by the extension .a of the output file) - as long as the arguments are entered in the proper order for the libtool syntax; which I must admit isn't really documented in the script itself.

同时,如果您有一个标签的问题,简单地移动——标签参数link命令参数之前,你可以用一个不存在强迫libtool运行标签和一个不存在的link命令(的操作完全由指定输出文件的扩展。)——只要输入的参数在适当的顺序libtool语法;我必须承认,这并不是脚本本身所记录的。


But to come back to the Mac libtool -o $(PROJECT) -static $(OBJECTS) line, which would combine static libraries; if you try to do the same with proper static library .a files, you will notice that libtool pushes the .a archives as such in the output archive, not their constituent object files - so this output is not a valid ELF object anymore; here is an example of a corresponding Linux libtool line, with two proper library files I've generated:

但是回到Mac libtool -o $(项目)-静态$(对象)行,它将组合静态库;如果您试图使用适当的静态库来执行相同的操作,那么您会注意到libtool将一个存档文件推到输出归档文件中,而不是它们的组成对象文件,因此这个输出不再是一个有效的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

So, as the accepted answer says - on Linux, use ar manually to unpack and pack again, to combine static libraries.

因此,正如所接受的答案所说——在Linux上,使用ar手动打开并打包,以组合静态库。

Hope this helps someone,
Cheers!

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

#4


0  

The following commands will build your static library:

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

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