如何在Automake和libtool使用项目中构建* .so模块?

时间:2012-12-19 09:12:58

标签: shared-libraries automake libtool

我遇到与others相同的问题:

  • 我在 Automake 项目中有 libtool 生成的*.la文件(例如module.la),
  • 但我需要*.so 才能将其用于dlopen()(例如module.so)。

但是:项目是使用--disable-shared配置和构建的,以确保创建的主二进制文件是一个大的静态链接程序,例如main.x(更易于部署和调试)。因此,不会创建*.so个文件。

程序main.x是一个类似框架的巨大应用程序,它能够通过dlopen()加载扩展(模块) - 尽管它是静态链接的。

当我手动构建module.so时,这很好用。但是在Makefile.am中使用它似乎对我来说是不可能的。是的,我可以写lib_LTLIBRARIES,但是使用我的标准版--disable-shared我没有*.so文件。

lib_LTLIBRARIES = module.la
module_so_SOURCES = module.cpp

创建了文件module.ladlopen()拒绝加载(当然)。

我尝试将规则放入Makefile.am手动构建它并且有效:

# Makefile.am (yes, .am)
all: mm_cpp_logger.so

SUFFIXES = .so

%.so: %.cpp
    $(CXX) $(CXXFLAGS) -fPIC -fpic -c -I $(top_srcdir)/include -o $@  $<

%.so: %.o
    $(CXX) $(LDFLAGS) -shared -fPIC -fpic -o $@  $<

但这只能是一种解决方法。我没有得到所有漂亮的自动功能,如依赖检查和安装。

如何构建module.so仍然使用--disable-shared方式使用Makefile.am(或具有相同效果)构建主程序?

  • 我可以使用特殊的automake规则将*.la个文件后处理到*.so个文件吗?
  • 我可以在任何情况下调整lib_LTLIBRARIES进程来创建*.so个文件吗?

3 个答案:

答案 0 :(得分:12)

您要找的是 module 。您可以通过将-all-static添加到应用程序的LDFLAGS来告诉Autotools创建静态二进制文件(可执行文件)。我认为这是使用--disable-shared配置标志(实际上是针对库而不是可执行文件)的首选方式。

这样的事情可以解决问题:

AM_CPPFLAGS=-I$(top_srcdir)/include

lib_LTLIBRARIES = module.la
module_la_LDFLAGS = -module -avoid-version -shared
module_la_SOURCES = mm_cpp_logger.cpp

bin_PROGRAMS = application
application_LDFLAGS = -all-static
application_SOURCES = main.cpp

.so文件(像往常一样)会在.libs/子目录中结束(当然,除非你安装它)。

您可以一次性构建应用程序和插件(即使只有一个Makefile.am,因此无需多次调用configure

Autotools应自动检测-fPIC(和朋友)的使用。


更新 :这里有一个小技巧可以让您的共享库可用。由于所有shlib都以.libs/结尾,因此将它们放在非隐藏目录中有时会很好。

以下makefile片段创建便利链接(在支持符号链接的平台上;否则会复制它们)。只需将代码段添加到您的makefile(我通常使用-include convenience-link.mk)就足够了(您的configure.ac中可能需要AC_PROG_LN_S

.PHONY: convenience-link clean-convenience-link

convenience-link: $(lib_LTLIBRARIES)
    @for soname in `echo | $(EGREP) "^dlname=" $^ | $(SED) -e "s|^dlname='\(.*\)'|\1|"`; do  \
        echo "$$soname: creating convenience link from $(abs_builddir)/.libs to $(top_builddir)"; \
        rm -f $(top_builddir)/$$soname ; \
        test -e $(abs_builddir)/.libs/$$soname && \
        cd $(top_builddir) && \
        $(LN_S) $(abs_builddir)/.libs/$$soname $$soname || true;\
    done 

clean-convenience-link:
    @for soname in `echo | $(EGREP) "^dlname=" $(lib_LTLIBRARIES) | $(SED) -e "s|^dlname='\(.*\)'|\1|"`; do  \
        echo "$$soname: cleaning convenience links"; \
        test -L $(top_builddir)/$$soname && rm -f $(top_builddir)/$$soname || true; \
    done 

all-local:: convenience-link

clean-local:: clean-convenience-link

答案 1 :(得分:2)

我已经使用 noinst_LTLIBRARIES 宏解决了类似的问题。

noinst_LTLIBRARIES 宏创建静态的,不可安装的库,仅供内部使用。如果指定-disable-static 配置选项,也会创建所有noinst_LTLIBRARIES静态库。

lib_LTLIBRARIES = libtokenclient.la
noinst_LTLIBRARIES = libtokenclient_static.la 

libtokenclient_la_SOURCES = $(TOKEN_SERVER_CLIENT_SOURCES) cDynlib.c cDynlib.h token_mod.h
libtokenclient_la_CFLAGS = @BASE_CFLAGS@
libtokenclient_la_CXXFLAGS = $(libtokenclient_la_CFLAGS)
libtokenclient_la_LIBADD = @B_BASE_OS_LIBS@
libtokenclient_la_LDFLAGS = @LT_PLUGIN_LIBS_FLAGS@ @LIBS_FLAGS@ $(TOKEN_SERVER_CLIENT_EXPORT_SYMBOLS)

libtokenclient_static_la_SOURCES = $(libtokenclient_la_SOURCES)
libtokenclient_static_la_CFLAGS = $(libtokenclient_la_CFLAGS)
libtokenclient_static_la_CXXFLAGS = $(libtokenclient_static_la_CFLAGS)

token_test_SOURCES = $(TEST_SOURCES)
token_test_LDADD = @B_BASE_OS_LIBS@ libtokenclient_static.la
token_test_CFLAGS = @BASE_CFLAGS@
token_test_CXXFLAGS = $(token_test_CFLAGS)

出于以下两个原因,我使用noinst_LTLIBRARIES静态库:

  1. 为了加快编译速度,我创建了静态库用作要链接的代码的中间容器,这些代码必须多次链接:代码只被编译一次,否则automake将为每个目标编译相同的源文件一次。
  2. 将代码静态链接到某些可执行文件

答案 2 :(得分:1)

根据LT_INIT的libtool文档可以工作的一件事是将您的构建分为两个包:主应用程序和插件。这样你就可以(在理论上)调用:

./configure --enable-shared=plugins

并且事情会像你期望的那样发挥作用。