C++ 如何使用libtool创建二进制和.so
我有一组cpp文件,我想直接编译成二进制文件,还想编译成共享库 我有C++ 如何使用libtool创建二进制和.so,c++,gcc,autoconf,automake,libtool,C++,Gcc,Autoconf,Automake,Libtool,我有一组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,有时li
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,有时libtool/automake会抱怨
Makefile.am: object `f1.$(OBJEXT)' created both with libtool and without`
我尝试将公共_源文件放入.a文件中,但当我将a.a与a.la链接时,libtool会抱怨(说它不可移植)
我需要的是
bin_LTPROGRAMS=mybin
但这并不存在
编辑:澄清-我正在使用automake/autoconf。我上面展示的是我的automake Makefile.am的主要部分。您必须为使用libtool创建的对象文件提供不同的扩展名,以便它们不会冲突。事实上,这些文件都是文本文件,包含具有可重定位和不可重定位代码的对象文件的元信息(这由-fPIC gcc命令行参数控制)。libtool创建的真实文件通常存储在“.libs”子目录中。基本生成文件如下所示:
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 $@ $<
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
CC=$(CXX)
LIBTOOL=LIBTOOL——安静
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=测试
LIB=libmylib.la
全部:$(EXE)$(LIB)
清洁:
$(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$@$<
针对公共资源库的链接,具体如下:
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
的文件,请使用Makefile.am
类似以下内容创建一个:
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 $@ $<
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.cpp
,f2.cpp
,f3.cpp
,f4.cpp
,f5.cpp
和f6.cpp
链接到libmylib.la
和main.cpp
,f1.cpp
,f2.cpp
和f3.cpp
进入mybin
如果目标包含每个目标CFLAGS
(或类似),则自动生成
将为构建该目标生成单独的对象文件。尝试将一些无操作标志添加到mybin
,例如:
mybin_CPPFLAGS = -I.
或
问题是,当公共源被制作成共享对象时,需要以不同于静态归档时的方式编译它们;对于前者,例如,
g++
需要传递-fPIC
标志
我建议使用两个构建目录
假设此源层次结构:
./src/Makefile.am
./src/f1.cpp
./src/f2.cpp
./src/f3.cpp
./src/main.cpp
./configure.ac
./Makefile.am
然后在/
中创建目录Release
和ReleaseDisableShared
。在目录/Release
中运行:
../configure && make
../configure --disable-shared && make
并在/ReleaseDisableShared
中运行:
../configure && make
../configure --disable-shared && make
在每个构建目录中构建之后,使用/ReleaseDisableShared/src/mybin的mybin
和/Release/src/libmylib.so的libmylib.so
另见:
我认为您无法使用libtool创建共享库。我相信你需要使用编译器。但是你忘记了一些细节。看起来您正在使用某种形式的自动生成等。因此,您需要告诉我们您使用的确切设置(因为它似乎不是直接生成)。libtool专门用于生成共享库。为什么您要创建libmylib。所以
,而不是将mybin
链接到此共享对象,静态链接在组成它的源代码中?我希望能够作为一个独立的模块分发二进制文件。我也希望能和你一样,所以。老实说,这个解决方案是合理的:Thx。但汽车制造商正是这样做的。这就是为什么我最后会出现关于同时使用.o和.lo的错误消息。我需要的是只编译一次到.lo,并将.lo文件链接到二进制文件和lib中。.o和.lo之间唯一的区别是一个有-fPIC,另一个没有(并且将-fPIC代码链接成二进制是无害的)您不能链接到.lo文件,它们只是文本文件,不是目标代码。但在我的示例中,它编译了两次。如果您想针对具有由libtool创建的不可重定位代码(“.o”)文件的对象进行链接,您可以在生成目录中的“.libs”子目录下找到它们。我这样做了,但最终将libmylib.la动态链接到mybin。我希望它是静态的。我输入了mybin\u LDFLAGS=-static,但结果仍然是动态的。如果您希望mybin
静态链接,我想libtool会希望您输入mybin\u LDFLAGS=-all static
,而不是-static
。请参阅info(libtool)链接模式
。请注意,这将中断--禁用静态的构建,除非您执行类似AM\u CONDITIONAL([HAVE\u static],[test“$enable\u static”=yes])
的操作,并将-all static
放在一个条件中。@pm100:当您说您尝试了这个操作时,您是否直接链接到了libmylib.la
,还是有一个便利的图书馆?在这种情况下,一个方便的库可能会静态链接,这对您来说是问题最少的。尝试使用一个方便的库。我尝试了这两种方法,在这两种情况下,我都得到了二进制动态链接库的结果。如果你绝对必须有静态链接(我不知道为什么会这样,因为你正在安装库),并且你不能让这个方法工作,我会用Lib的便利性再试一次,试试我的另一个答案,让我知道这是怎么回事(我需要二进制文件和lib,所以我在两个不同的目录中构建它们)