C++ 如何使用libtool创建二进制和.so

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

我有一组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,有时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,所以我在两个不同的目录中构建它们)