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

Foi útil?

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 $@ $<
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top