Cmake kan bibliotheek niet vinden met “link_directories”

Ik Ubuntu, ik leer over cmake en make, en probeer gewoon een eenvoudig voorbeeld. Ik heb twee mappen: srcen build. In srcheb ik twee bestanden: main.cppen CMakeLists.txt, die (alleen) de volgende tekst heeft:

add_executable(test main.cpp)
link_directories(/usr/lib/x86_64-linux-gnu)
target_link_libraries(test protobuf)

In /usr/lib/x86_64-linux-gnuis er een gedeelde bibliotheek genaamd libprotobuf.so, waarnaar ik wil linken. Mijn main.cppgebruikt functies in deze bibliotheek door het relevante headerbestand #include <google/protobuf/message.h>op te nemen.

Nu, in mijn builddirectory, voer ik cmake ../srcuit, en dan make. Ik krijg dan echter linkerfouten die me vertellen dat er ongedefinieerde verwijzingen zijn naar enkele van de functies in de protobuf-bibliotheek. Als ik door alle bestanden en submappen in buildzoek, wordt er niets vermeld over protobuf.

Als ik echter de regel link_directoriesin mijn bestand CMakeLists.txtverwijder en in plaats daarvan het volledige pad naar de bibliotheek schrijf bij het specificeren van het uitvoerbare bestand, bijv. target_link_libraries(test /usr/lib/x86_64-linux-gnu/libprotobuf.so), compileert en linkt prima.

Waarom staat link_directoriesniet toe dat cmake deze bibliotheek kan vinden?


Antwoord 1, autoriteit 100%

Gebruik link_directoriesniet op deze manier in CMake.

Dit is een veelgemaakte beginnersfout, aangezien veel andere build-omgevingen zo werken, maar in CMake is het gewoon vragen om problemen. Zelfs de manpageraadt dit specifiek af:

Merk op dat dit commando [link_directories] zelden nodig is. Bibliotheeklocaties geretourneerd
by find_package()en find_library()zijn absolute paden. Geef deze door
absolute bibliotheekbestandspaden rechtstreeks naar de target_link_libraries()
opdracht. CMake zorgt ervoor dat de linker ze vindt.

Dus in plaats daarvan geef altijd absolute padendoor aan target_link_librariesen gebruik find_libraryom de linkdirectory op te lossen:

find_library(PROTOBUF_LIBRARY protobuf HINTS /usr/lib/x86_64-linux-gnu)
target_link_libraries(test PUBLIC ${PROTOBUF_LIBRARY})

Dit heeft het enorme voordeel dat u waarschijnlijk een diagnose krijgt tijdens de configuratie van CMake als de verwachte bibliotheek niet kan worden gevonden, in plaats van een willekeurige linkerfout tijdens het compileren. Dit stelt de gebruiker ook in staat om een ​​bibliotheeklocatie op te geven via de GUI als de doelcomputer een niet-standaard directorylay-out heeft.

Dus als het niet meteen werkt, controleer dan het resultaat van de find_library-aanroep en raadpleeg de manpage om op te sporen waarom het je bibliotheek niet vindt zoals bedoeld.

p>


Antwoord 2, autoriteit 95%

Zorg ervoor dat uw oproep naar link_directoriesplaatsvindt vóór uw oproepnaar de relevante add_executable.

Ik had ten onrechte gedacht dat dit alleen nodig was vóór de oproep naar target_link_libraries, maar dat is niet het geval. Na het verplaatsen van de oproep is de bibliotheek correct gekoppeld.


Antwoord 3, autoriteit 7%

Zorg ervoor dat de volgorde link_directories is, stel PROJECT_LINK_LIBS in, add_executable en vervolgens target_link_libraries.

Hieronder is een voorbeeld om het te demonstreren:

cmake_minimum_required(VERSION 2.8.9)
project (Logging)
include_directories(include)
file(GLOB LOGGINGSOURCES "libsrc/*.cpp")
file(GLOB SOURCES "src/*.cpp")
add_library(convertString SHARED ${LOGGINGSOURCES})
install(TARGETS convertString DESTINATION /root/Deepak/)
link_directories( /root/Deepak/ )
set(PROJECT_LINK_LIBS libconvertString.so)
add_executable(hello ${SOURCES})
target_link_libraries(hello ${PROJECT_LINK_LIBS} )

Other episodes