Comment inclure correctement l’argument de l’éditeur de liens -Wl, -rpath, $ ORIGIN dans un Makefile?

Je prépare une application c ++ sur Linux (Ubuntu 16.04) en utilisant quelques bibliothèques poco que j’ai liées dynamicment. J’ai un dossier de projet qui comprend: les dossiers include, bin, lib, src et build et le fichier Makefile correspondant. Jusqu’ici, j’ai utilisé le Makefile suivant qui récupère les bibliothèques de / usr / local / lib

CC := g++ # Folders SRCDIR := src BUILDDIR := build TARGETDIR := bin # Targets EXECUTABLE := C++_APP TARGET := $(TARGETDIR)/$(EXECUTABLE) SRCEXT := cpp SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT)) OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.o)) CFLAGS := -c -Wall INC := -I include -I /usr/local/include LIB := -L /usr/local/lib -lPocoFoundation -lPocoNet -lPocoUtil $(TARGET): $(OBJECTS) @echo " Linking..." @echo " $(CC) $^ -o $(TARGET) $(LIB)"; $(CC) $^ -o $(TARGET) $(LIB) $(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT) @mkdir -p $(BUILDDIR) @echo " $(CC) $(CFLAGS) $(INC) -c -o $@ $<"; $(CC) $(CFLAGS) $(INC) -c -o $@ $< clean: @echo " Cleaning..."; @echo " $(RM) -r $(BUILDDIR) $(TARGET)"; $(RM) -r $(BUILDDIR) $(TARGET) .PHONY: clean 

Maintenant, lors de l’exécution de l’éditeur de liens, j’aimerais rechercher des bibliothèques uniquement dans le dossier project lib sans changer LD_LIBRARY_PATH ni modifier ld.so.conf. J’ai donc cherché et j’ai trouvé que cela pouvait être obtenu avec l’argument de l’éditeur de liens -Wl, rpath, $ ORIGIN. Donc, je suppose que je dois append la déclaration suivante

 LDFLAGS := -Wl,-rpath,$ORIGIN/../lib 

et changez la déclaration LIB comme suit:

 LIB := -L $ORIGIN/../lib -lPocoFoundation -lPocoNet -lPocoUtil 

Cependant, il récupère toujours les bibliothèques du répertoire par défaut (usr / local / lib), car je l’ai testé sans bibliothèque sur le dossier project lib. Qu’est ce que j’ai mal fait?

Non, vous vous trompez. Vous devez passer la chaîne littérale $ORIGIN/../lib en tant qu’argument à votre éditeur de liens. Le jeton $ORIGIN est conservé dans votre programme après sa création et lorsque l’éditeur de liens du runtime commence à exécuter votre programme, il remplacera $ORIGIN par le chemin actuel à partir duquel votre programme a été appelé. Cela est vrai même si vous avez copié votre programme ailleurs. Donc, si vous exécutez votre programme en tant que /usr/local/bin/myprogram l’éditeur de liens au moment de l’exécution remplacera $ORIGIN par /usr/local/bin . Si vous le copiez dans /opt/mystuff/libexec/myprogram l’éditeur de liens au moment de l’exécution remplacera $ORIGIN par /opt/mystuff/libexec .

Pour passer un $ littéral à la commande invoquée par une recette make, vous devez vous échapper du $ en le doublant: $$ . Sinon, make verra que $ introduit une variable ou une fonction make. Rappelez-vous qu’il est parfaitement légal pour une variable make d’éviter les parenthèses, etc., s’il s’agit d’un seul caractère (note, $@ , $< , etc.)

Ainsi, lorsque vous écrivez -Wl,-rpath,$ORIGIN/../lib make interprétera le $O dans $ORIGIN comme développant une variable nommée O , qui est vide, vous donnant ainsi -Wl,-rpath,RIGIN/../lib .

De plus, vous devez échapper le $ du shell, sinon il essaiera de développer $ORIGIN tant que variable du shell que vous ne voulez pas.

Vous voulez faire quelque chose comme ça:

 LDFLAGS = '-Wl,-rpath,$$ORIGIN/../lib' -L/usr/local/lib LDLIBS = -lPocoFoundation -lPocoNet -lPocoUtil $(TARGET): $(OBJECTS) @echo " Linking..." $(CC) $^ -o $@ $(LDFLAGS) $(LDLIBS) 

(Je ne sais pas pourquoi vous utilisez @ pour masquer la commande, puis l'écho de la commande ... pourquoi ne pas simplement supprimer le @ et l' echo et laisser make vous montrer la commande?)