如何使用libtool创建二进制文件和.so文件

12
我有一组cpp文件,我想把它们直接编译成一个二进制文件,同时也要编译成一个共享库。
bin_PROGRAMS=mybin
lib_LTLIBRARIES=libmylib.la

COMMON_SOURCES=f1.cpp f2.cpp f3.cpp

mybin_SOURCES=main.cpp $(COMMON_SOURCES)
libmylib_la_SOURCES=$(COMMON_SOURCES)

运行此命令时,cpp文件将被编译两次,一次使用libtool和一次不使用,并且有时会引发libtool/automake的警告。

Makefile.am: object `f1.$(OBJEXT)' created both with libtool and without`

我尝试将COMMON_SOURCES放入.a文件中,但当我链接一个.a和.la时,libtool会抱怨它不可移植。

我需要的是像这样的东西

bin_LTPROGRAMS=mybin

但是那个并不存在。

编辑:澄清一下 - 我正在使用automake/autoconf。我展示的是我的automake Makefile.am的核心内容。


我认为你不能使用libtool制作共享库。我相信你需要使用编译器。但是你忘记了一些细节。看起来你正在使用某种形式的自动化工具,因此你需要告诉我们你正在使用的确切设置(因为它似乎不是直接使用make)。 - Martin York
4
Libtool 专门用于制作共享库。http://www.gnu.org/software/libtool/manual/libtool.html - pm100
为什么你想创建 libmylib.so,而不是将 mybin 链接到这个共享对象,通过静态链接包含它的源代码呢? - Daniel Trebbien
我希望能够将二进制文件作为独立的免费模块进行分发。我也希望能够以同样的方式处理.so文件。说实话,这很有道理。 - pm100
以下是解决方案:https://www.gnu.org/software/automake/manual/html_node/Objects-created-both-with-libtool-and-without.html - elhadi dp ıpɐɥןǝ
4个回答

6

特别是针对通用源代码库进行链接:

bin_PROGRAMS = mybin
lib_LTLIBRARIES = libmylib.la

mybin_SOURCES = main.cpp
mybin_LDADD = libmylib.la
libmylib_la_SOURCES = f1.cpp f2.cpp f3.cpp

如果libmylib.la使用了不应该链接到mybin中的文件,则需要创建一个libtool便捷库,使用类似于以下内容的Makefile.am:
bin_PROGRAMS = mybin
noinst_LTLIBRARIES = libcommon.la
lib_LTLIBRARIES = libmylib.la

mybin_SOURCES = main.cpp
mybin_LDADD = libcommon.la

libmylib_la_SOURCES = f4.cpp f5.cpp f6.cpp
libmylib_la_LIBADD = libcommon.la

libcommon_la_SOURCES = f1.cpp f2.cpp f3.cpp

这将把f1.cppf2.cppf3.cppf4.cppf5.cppf6.cpp链接到libmylib.la中,将main.cppf1.cppf2.cppf3.cpp链接到mybin中。


我做了这个,但最终得到的是libmylib.la动态链接到mybin中。我想要它是静态的。我在mybin_LDFLAGS=-static中加入了-static,但它仍然是动态的。 - pm100
如果你想让 mybin 静态链接,我认为 libtool 会要求你将 mybin_LDFLAGS = -all-static 放在里面,而不是 -static。请参阅 info (libtool)Link mode。请注意,这将破坏 --disable-static 构建,除非你做一些像 AM_CONDITIONAL([HAVE_STATIC], [test "$enable_static" = yes]) 这样的条件性操作,并将 -all-static 放在一个条件语句中。 - Jack Kelly
@pm100:当你说你尝试过这个时,是直接链接到libmylib.la还是使用了一个方便库?可能情况是方便库将会静态链接,这对你来说是最不麻烦的。尝试使用一个方便库。 - Jack Kelly
我尝试了两种方法,但在两种情况下都以二进制动态链接库结束。我将再次尝试使用方便库。 - pm100
1
如果你绝对需要静态链接(我不确定为什么会这样,因为你已经在安装库了),而且你无法让这种方法工作,那么请尝试我的另一个答案,并告诉我结果如何。 - Jack Kelly

3
问题在于当常见源代码被制作成共享对象时,需要以不同的方式进行编译,而不是制作静态归档文件;例如,在前者的情况下,需要向g++传递-fPIC标志。
我的建议是使用两个构建目录。
假设有以下源代码层次结构:
./src/Makefile.am ./src/f1.cpp ./src/f2.cpp ./src/f3.cpp ./src/main.cpp ./configure.ac ./Makefile.am
则可以在./src/Makefile.am中使用以下内容:
bin_PROGRAMS = mybin lib_LTLIBRARIES = libmylib.la
mybin_SOURCES = main.cpp mybin_LDADD = libmylib.la libmylib_la_SOURCES = f1.cpp f2.cpp f3.cpp 然后,在./中创建ReleaseReleaseDisableShared目录。在./Release目录中运行:
../configure && make

./ReleaseDisableShared目录下运行以下命令:
../configure --disable-shared && make

在每个构建目录中构建后,您可以使用位于“./ReleaseDisableShared/src/mybin”处的mybin以及位于“./Release/src/libmylib.so”处的libmylib.so
另请参见:

这大概是我最终做的(我需要二进制文件和库,所以我在两个不同的目录中构建了它们)。 - pm100

2
如果目标包含每个目标的CFLAGS(或类似的内容),automake将为构建该目标制作单独的对象文件。尝试向mybin添加一些无操作的标志,例如:
mybin_CPPFLAGS = -I.

或者

mybin_CPPFLAGS = -DDUMMY -UDUMMY

0

您必须给使用 libtool 创建的目标文件赋予不同的扩展名,以避免冲突。实际上,这些文件是文本文件,包含可重定位和非可重定位代码的元信息(这是通过 -fPIC GCC 命令行参数控制的)。由 libtool 创建的真正文件通常存储在“.libs”子目录中。基本的 Makefile 如下所示:

CC = $(CXX)
LIBTOOL = libtool --quiet

SRC = lib.cpp test.cpp
LIB_SRC = lib.cpp $(SRC)
LIB_OBJ = $(LIB_SRC:.cpp=.lo)

EXE_SRC = exe.cpp $(SRC)
EXE_OBJ = $(EXE_SRC:.cpp=.o)

EXE = test
LIB = libmylib.la

all: $(EXE) $(LIB)

clean:
    $(RM) *.o *.lo $(EXE) $(LIB)

$(EXE): $(EXE_OBJ)

$(LIB): $(LIB_OBJ)
    $(LIBTOOL) --tag=CXX --mode=link $(LINK.cc) -shared -version-info 1:0 -rpath $(shell readlink -f .) -o $@ $< $(LDLIBS)

%.o: %.cpp
    $(COMPILE.cc) -o $@ $<

%.lo: %.cpp
    $(LIBTOOL) --mode=compile --tag=CXX $(COMPILE.cc) -o $@ $<

谢谢。但是 automake 正好可以做到这一点。这就是为什么我最终会收到关于同时拥有 .o 和 .lo 的错误消息。我需要的是只编译一次到 .lo,并将 .lo 文件链接到二进制文件和 lib 中。.o 和 .lo 之间唯一的区别在于一个具有 -fPIC,而另一个没有(将 -fPIC 代码链接到二进制文件是无害的)。 - pm100
1
你不能链接 .lo 文件,它们只是文本文件而不是目标代码。但在我的例子中,它编译了两次。如果你想要链接到由 libtool 创建的具有非可重定位代码(".o")文件的对象,你可以在构建目录下的 ".libs" 子目录中找到它们。 - user405725

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接