how to create binary and .so using libtool
I have a set of cpp files that I want to compile directly into a binary and also to compile into a shared library.
I have
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)
When I run this the cpp files are compiled twice, once with libtool and once without and sometimes libtool/automake complains
Makefile.am: object `f1.$(OBJEXT)' created both with libtool and without`
I tried putting COMMON_SOURCES into a .a file but then libtool complains when I link a .a with a .la (saying its not portable).
What I need is something like
bin_LTPROGRAMS=mybin
but that doesnt exist
edit: clarification - I am using automake/autoconf. What I have shown above is the meat of my automake Makefile.开发者_如何学编程am
Link against the library of common sources specifically:
bin_PROGRAMS = mybin
lib_LTLIBRARIES = libmylib.la
mybin_SOURCES = main.cpp
mybin_LDADD = libmylib.la
libmylib_la_SOURCES = f1.cpp f2.cpp f3.cpp
If libmylib.la
ends up using files that shouldn't be linked into mybin
, create a libtool convenience library, using a Makefile.am
something like this:
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
This will link f1.cpp
, f2.cpp
, f3.cpp
, f4.cpp
, f5.cpp
and f6.cpp
into libmylib.la
and main.cpp
, f1.cpp
, f2.cpp
and f3.cpp
into mybin
.
The issue is that the common sources need to be compiled differently when they are being made into a shared object than when they are being made into a static archive; in the case of the former, for example, g++
needs to be passed the -fPIC
flag.
What I suggest is using two build directories.
Assuming this source hierarchy:
./src/Makefile.am ./src/f1.cpp ./src/f2.cpp ./src/f3.cpp ./src/main.cpp ./configure.ac ./Makefile.am
you would use something like this in ./src/Makefile.am
:
bin_PROGRAMS = mybin lib_LTLIBRARIES = libmylib.la mybin_SOURCES = main.cpp mybin_LDADD = libmylib.la libmylib_la_SOURCES = f1.cpp f2.cpp f3.cpp
Then you create directories Release
and ReleaseDisableShared
in ./
. In directory ./Release
you run:
../configure && make
and in ./ReleaseDisableShared
you run:
../configure --disable-shared && make
After building in each build directory, you use the mybin
at ./ReleaseDisableShared/src/mybin
and the libmylib.so
at ./Release/src/libmylib.so
.
See also:
- Position-independent code
- build .o files to specific directory using automake
If a target contains per-target CFLAGS
(or similar), automake
will make separate object files for building that target. Try adding some no-op flags to mybin
, something like:
mybin_CPPFLAGS = -I.
or
mybin_CPPFLAGS = -DDUMMY -UDUMMY
You have to give object files created with libtool a different extension so they do not conflict. In fact, those files are text files containing meta information for both object files with relocatable and non-relocatable code (this is controlled with -fPIC gcc command line argument). The real files created by libtool are usually stored in ".libs" subdirectory. The basic makefile will look like this:
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 $@ $<
精彩评论