Como criar binário e. Então, usando o Libtool
Pergunta
Eu tenho um conjunto de arquivos de CPP que desejo compilar diretamente em um binário e também para compilar em uma biblioteca compartilhada.
Eu tenho
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)
Quando eu executo isso, os arquivos CPP são compilados duas vezes, uma vez com o Libtool e uma vez sem e às vezes Libtool/Autorake reclama
Makefile.am: object `f1.$(OBJEXT)' created both with libtool and without`
Tentei colocar o Common_sources em um arquivo. Um arquivo, mas depois o Libtool reclama quando vincula um .a com um .la (dizendo que não é portátil).
O que eu preciso é algo como
bin_LTPROGRAMS=mybin
Mas isso não existe
Edit: esclarecimento - estou usando o Autorake/Autoconf. O que eu mostrei acima é a carne do meu makefile de automóvel.am
Solução
A questão é que as fontes comuns precisam ser compiladas de maneira diferente quando estão sendo transformadas em um objeto compartilhado do que quando estão sendo transformadas em um arquivo estático; No caso do primeiro, por exemplo, g++
precisa ser passado o -fPIC
bandeira.
O que eu sugiro é usar dois diretórios de construção.
Supondo essa hierarquia de origem:
./src/Makefile.am ./src/f1.cpp ./src/f2.cpp ./src/f3.cpp ./src/main.cpp ./configure.ac ./Makefile.am
você usaria algo assim em ./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
Então você cria diretórios Release
e ReleaseDisableShared
dentro ./
. No diretório ./Release
você corre:
../configure && make
e em ./ReleaseDisableShared
você corre:
../configure --disable-shared && make
Depois de construir em cada diretório de construção, você usa o mybin
no ./ReleaseDisableShared/src/mybin
e a libmylib.so
no ./Release/src/libmylib.so
.
Veja também:
Outras dicas
Link contra a biblioteca de fontes comuns especificamente:
bin_PROGRAMS = mybin
lib_LTLIBRARIES = libmylib.la
mybin_SOURCES = main.cpp
mybin_LDADD = libmylib.la
libmylib_la_SOURCES = f1.cpp f2.cpp f3.cpp
Se libmylib.la
acaba usando arquivos que não devem ser vinculados a mybin
, Crie um Biblioteca de conveniência Libtool, usando um Makefile.am
algo assim:
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
Isso vai vincular f1.cpp
, f2.cpp
, f3.cpp
, f4.cpp
, f5.cpp
e f6.cpp
em libmylib.la
e main.cpp
, f1.cpp
, f2.cpp
e f3.cpp
em mybin
.
Se um alvo contiver por alvo CFLAGS
(ou similar), automake
fará arquivos de objeto separados para criar esse alvo. Tente adicionar algumas bandeiras não-op para mybin
, algo como:
mybin_CPPFLAGS = -I.
ou
mybin_CPPFLAGS = -DDUMMY -UDUMMY
Você precisa fornecer arquivos de objeto criados com o Libtool uma extensão diferente para que eles não entrem em conflito. De fato, esses arquivos são arquivos de texto que contêm meta informações para ambos os arquivos de objeto com código relocável e não -relatável (isso é controlado com o argumento da linha de comando gccfpic GCC). Os arquivos reais criados pela LBtool geralmente são armazenados no subdiretório ".Libs". O Makefile básico será assim:
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 $@ $<