13

我和其他人有同样的问题:

  • 我在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.la被创建,它dlopen()拒绝加载(当然)。

我试图将规则放入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-sharedMakefile.am

  • 我可以*.la*.so文件后处理为具有特殊自动生成规则的文件吗?
  • 在任何情况下我都可以调整lib_LTLIBRARIES创建文件的过程吗?*.so
4

3 回答 3

14

您要查找的内容称为模块-all-static您可以告诉 Autotools 通过添加到应用程序来创建静态二进制文件(可执行文件)LDFLAGS。我认为这是使用配置标志的首选方式--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多次调用。

-fPICAutotools 应该自动检测(和朋友)的使用。


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

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

.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
于 2013-01-08T16:34:09.543 回答
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. 将代码静态链接到某个可执行文件
于 2019-10-14T21:14:19.540 回答
1

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

./configure --enable-shared=plugins

事情会按照你期望的方式进行。

于 2012-12-19T18:51:51.143 回答