我遇到与others相同的问题:
*.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-shared
方式使用Makefile.am
(或具有相同效果)构建主程序?
*.la
个文件后处理到*.so
个文件吗?lib_LTLIBRARIES
进程来创建*.so
个文件吗?答案 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静态库:
答案 2 :(得分:1)
根据LT_INIT的libtool文档可以工作的一件事是将您的构建分为两个包:主应用程序和插件。这样你就可以(在理论上)调用:
./configure --enable-shared=plugins
并且事情会像你期望的那样发挥作用。