Подтвердить что ты не робот

Cmake не может найти библиотеку, используя "link_directories"

I Ubuntu, я узнаю о cmake и make, и просто попробую простой пример. У меня есть два каталога: src и build. В src у меня есть два файла: main.cpp и CMakeLists.txt, у которых есть (только) следующий текст:

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

В /usr/lib/x86_64-linux-gnu имеется разделяемая библиотека под названием libprotobuf.so, с которой я хочу связать. Мой main.cpp использует функции в этой библиотеке, включая заголовочный файл-релиз, #include <google/protobuf/message.h>.

Теперь, в моем каталоге build, я запустил cmake ../src, а затем make. Тем не менее, я получаю ошибки компоновщика, говорящие мне, что есть ссылки undefined на некоторые из функций библиотеки protobuf. Если я выполняю поиск по всем файлам и подкаталогам в build, не упоминается ничего, связанное с protobuf.

Однако, если я удалю строку link_directories в моем CMakeLists.txt файле и вместо этого напишу полный путь к библиотеке при указании исполняемого файла, т.е. target_link_libraries(test /usr/lib/x86_64-linux-gnu/libprotobuf.so), он компилирует и связывает в порядке.

Почему link_directories не позволяет cmake найти эту библиотеку?

4b9b3361

Ответ 1

Не используйте link_directories, как это в CMake.

Это обычная ошибка начинающих, так как многие другие среды сборки работают так, но в CMake это просто просит неприятностей. Даже manpage специально предупреждает об этом:

Обратите внимание, что эта команда [ link_directories] редко необходима. Вернулись библиотеки на find_package() и find_library() являются абсолютными путями. Передайте эти абсолютные пути файла библиотеки непосредственно к target_link_libraries()команда. CMake гарантирует, что компоновщик найдет их.

Итак, всегда отправляйте абсолютные пути к target_link_libraries и используйте find_library для разрешения каталога ссылок:

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

Это имеет огромное преимущество, что вы, вероятно, получите диагностику на времени настройки CMake, если ожидаемая библиотека не может быть найдена, а не случайная ошибка компоновщика во время компиляции. Кроме того, это позволяет пользователю указывать местоположение библиотеки через графический интерфейс, если целевой компьютер имеет нестандартный макет каталога.

Итак, если он не работает сразу, обязательно проверьте результат вызова find_library и обратитесь к справочной странице, чтобы узнать, почему он не находит вашу библиотеку по назначению.

Ответ 2

Убедитесь, что ваш вызов link_directories имеет перед вашим вызовом в соответствующем add_executable.

Я ошибочно полагал, что нужно только до вызова target_link_libraries, но это не так. После перемещения вызова библиотека правильно связана.

Ответ 3

Вот выдержка из документация:

link_directories (directory1 directory2...):Укажите пути, в которых компоновщик должен искать библиотеки. Команда применяется только к целям, созданным после того, как она называется. Относительные пути, заданные этой команде, интерпретируются как относительные текущий каталог источника, см. CMP0015.

команда

add_executable (test main.cpp)

создает тест имен имен. Также вы можете добавить команду link_directories над add_executable.