Как правильно связать библиотеку ODB с проектом с использованием cmake в Windows?

Вопрос или проблема

Я использовал vcpkg для установки rapidjson и curl, но мне трудно связать библиотеку ODB для PostgreSQL с моим проектом.
Я собрал необходимые библиотеки, следуя инструкциям из этого ссылки
Я использую vscode с набором инструментов VS2022. У меня есть odb-pgsql-d-2.4-vc12.dll и odb-d-2.4-vc12.dll в PATH и в каталоге проекта.
Я смог сгенерировать файлы xxx-odb.hpp с помощью компилятора ODB, но, похоже, не могу правильно связать библиотеку?
Прикрепляю минимальный CMakeLists.txt, main.cpp и файл вывода сборки.
Я получаю ошибки неразрешенных внешних символов.

CMakeLists.txt

project(main VERSION 0.1.0 LANGUAGES C CXX)

set(CMAKE_GENERATOR_PLATFORM x64)

add_executable(main main.cpp)

set(VCPKG_INSTALLED_DIR "C:\\vcpkg\\installed\\x64-windows")
set(ODB_COMPILER_PATH "C:\\pathtools\\bin")
set(ODB_INSTALLED_DIR "C:\\external")

find_package(PostgreSQL REQUIRED)
target_link_libraries(main PRIVATE PostgreSQL::PostgreSQL)

find_program(ODB_COMPILER NAMES odb PATHS "${ODB_COMPILER_PATH}" EXTERNAL REQUIRED)
set(ODB_LIB_DIR "${ODB_INSTALLED_DIR}/lib")
set(ODB_INCLUDE_DIR "${ODB_INSTALLED_DIR}/include")
target_include_directories(main PRIVATE ${ODB_INCLUDE_DIR})
link_directories(${ODB_LIB_DIR})
target_link_libraries(main PRIVATE ${ODB_LIB_DIR}/odb-d.lib)
target_link_libraries(main PRIVATE ${ODB_LIB_DIR}/odb-pgsql-d.lib)

add_custom_target(run
    COMMAND ${PROJECT_NAME}
    DEPENDS ${PROJECT_NAME}
    WORKING_DIRECTORY ${CMAKE_PROJECT_DIR}
)

main.cpp

#include <iostream>
#include <memory>
#include <odb/pgsql/database.hxx>
#include <odb/transaction.hxx>

int main()
{
    std::shared_ptr<odb::pgsql::database> db(new odb::pgsql::database("postgres", "password", "maindb", "localhost", 5432));
    return 0;
}

Логи сборки

[main] Building folder: c:/main/build main
[build] Starting build
[proc] Executing command: "C:\Program Files\CMake\bin\cmake.EXE" --build c:/main/build --config Debug --target main -j 22 --
[build] MSBuild version 17.11.9+a69bbaaf5 для .NET Framework
[build] 
[build] main.obj : ошибка LNK2019: неразрешенный внешний символ "__declspec(dllimport) public: __thiscall odb::pgsql::database::database(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,unsigned int,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class odb::details::transfer_ptr<class odb::pgsql::connection_factory>)" (__imp_??0database@pgsql@odb@@QAE@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@000I0V?$transfer_ptr@Vconnection_factory@pgsql@odb@@@details@2@@Z) указан в функции _main [C:\main\build\main.vcxproj]
[build] main.obj : ошибка LNK2019: неразрешенный внешний символ "__declspec(dllimport) public: virtual __thiscall odb::pgsql::database::~database(void)" (__imp_??1database@pgsql@odb@@UAE@XZ) указан в функции "public: virtual void * __thiscall odb::pgsql::database::`scalar deleting destructor'(unsigned int)" (??_Gdatabase@pgsql@odb@@UAEPAXI@Z) [C:\main\build\main.vcxproj]
[build] main.obj : ошибка LNK2001: неразрешенный внешний символ "public: virtual class odb::pgsql::transaction_impl * __thiscall odb::pgsql::database::begin(void)" (?begin@database@pgsql@odb@@UAEPAVtransaction_impl@23@XZ) [C:\main\build\main.vcxproj]
[build] main.obj : ошибка LNK2001: неразрешенный внешний символ "protected: virtual struct odb::database::schema_version_info const & __thiscall odb::pgsql::database::load_schema_version(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)const " (?load_schema_version@database@pgsql@odb@@MBEABUschema_version_info@13@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) [C:\main\build\main.vcxproj]
[build] main.obj : ошибка LNK2001: неразрешенный внешний символ "protected: virtual class odb::connection * __thiscall odb::pgsql::database::connection_(void)" (?connection_@database@pgsql@odb@@MAEPAVconnection@3@XZ) [C:\main\build\main.vcxproj]
[build] C:\Program Files\PostgreSQL\16\lib\libpq.lib : предупреждение LNK4272: тип машины библиотеки 'x64' конфликтует с типом машины целевого назначения 'x86' [C:\main\build\main.vcxproj]
[build] C:\external\lib\odb-d.lib : предупреждение LNK4272: тип машины библиотеки 'x64' конфликтует с типом машины целевого назначения 'x86' [C:\main\build\main.vcxproj]
[build] C:\external\lib\odb-pgsql-d.lib : предупреждение LNK4272: тип машины библиотеки 'x64' конфликтует с типом машины целевого назначения 'x86' [C:\main\build\main.vcxproj]
[build] C:\main\build\Debug\main.exe : критическая ошибка LNK1120: 5 неразрешенных внешних символов [C:\main\build\main.vcxproj]
[proc] Команда: "C:\Program Files\CMake\bin\cmake.EXE" --build c:/main/build --config Debug --target main -j 22 -- завершилась с кодом: 1
[driver] Сборка завершена: 00:00:01.946
[build] Сборка завершена с кодом выхода 1

В вашей среде сборки есть несколько проблем.

odb-pgsql-d-2.4-vc12.dll и odb-d-2.4-vc12.dll и их импортные библиотеки предназначены для Visual Studio 2013 и, вероятно, не совместимы с Visual Studio 2022. Вам может понадобиться либо понизить версию Visual Studio, либо обновить библиотеки ODB, которые упоминают версию vc17.

предупреждение LNK4272: тип машины библиотеки ‘x64’ конфликтует с типом машины целевого назначения ‘x86’

Это немного более очевидно. Платформа целевого назначения main — это x86, а библиотеки ODB нацелены на x64. Они несовместимы. Вы не показали, как вы запускаете cmake, возможно, с -A Win32, вам не следует устанавливать это или использовать -A x64.

Ответ или решение

Для правильного связывания библиотеки ODB с вашим проектом на Windows с использованием CMake, важно учитывать несколько аспектов, включая настройки среды, совместимость библиотек и правильную конфигурацию CMake. В вашем случае возникают проблемы с неопределёнными внешними символами, что может быть связано с несовместимостью версий библиотек и настройками платформы. Рассмотрим шаги, которые помогут вам решить эти проблемы.

1. Проверьте версии библиотек

Сначала убедитесь, что библиотеки ODB, которые вы используете, совместимы с версией Visual Studio (VS2022) и компилятором. Вы упомянули, что у вас есть odb-pgsql-d-2.4-vc12.dll, который соответствует версии VC12 (Visual Studio 2013). Вам необходимо либо обновить библиотеку ODB до версии, совместимой с VS2022, либо использовать более раннюю версию Visual Studio (например, VS2013).

2. Проверьте целевую платформу

Согласно вашим логам сборки, существует предупреждение о несовместимости между целевой архитектурой (x86) и библиотеками (x64). Это значит, что ваш проект скомпилирован под x86, тогда как библиотека ODB предназначена для x64. Чтобы решить эту проблему, выполните следующие шаги:

  • Убедитесь, что вы не устанавливаете платформу x86 дома в CMake. Убедитесь, что правильная целевая платформа у вас настроена:
    • Если вы запускаете CMake через командную строку, используйте параметр -A x64.
    • Убедитесь, что в CMakeLists.txt не указано CMAKE_GENERATOR_PLATFORM x86, это должно быть x64.

Пример вызова CMake:

cmake .. -A x64

3. Настройте CMakeLists.txt

Ваш CMakeLists.txt в целом выглядит правильно, но есть некоторые рекомендации, которые могут улучшить его:

  • Убедитесь, что пути к библиотекам ODB правильные и соответствующие исполняемым файлам и заголовкам.
  • Вместо ручного указания библиотек, используйте find_library для поиска библиотек ODB. Например:
find_library(ODB_LIB NAMES odb-d PATHS ${ODB_LIB_DIR})
find_library(ODB_PGSQL_LIB NAMES odb-pgsql-d PATHS ${ODB_LIB_DIR})

target_link_libraries(main PRIVATE ${ODB_LIB} ${ODB_PGSQL_LIB})

Полный CMakeLists.txt после изменений:

cmake_minimum_required(VERSION 3.10)
project(main VERSION 0.1.0 LANGUAGES C CXX)

set(CMAKE_GENERATOR_PLATFORM x64)

add_executable(main main.cpp)

set(VCPKG_INSTALLED_DIR "C:\\vcpkg\\installed\\x64-windows")
set(ODB_COMPILER_PATH "C:\\pathtools\\bin")
set(ODB_INSTALLED_DIR "C:\\external")

find_package(PostgreSQL REQUIRED)
target_link_libraries(main PRIVATE PostgreSQL::PostgreSQL)

find_program(ODB_COMPILER NAMES odb PATHS "${ODB_COMPILER_PATH}" EXTERNAL REQUIRED)
set(ODB_LIB_DIR "${ODB_INSTALLED_DIR}/lib")
set(ODB_INCLUDE_DIR "${ODB_INSTALLED_DIR}/include")
target_include_directories(main PRIVATE ${ODB_INCLUDE_DIR})

find_library(ODB_LIB NAMES odb-d PATHS ${ODB_LIB_DIR})
find_library(ODB_PGSQL_LIB NAMES odb-pgsql-d PATHS ${ODB_LIB_DIR})

target_link_libraries(main PRIVATE ${ODB_LIB} ${ODB_PGSQL_LIB})

add_custom_target(run
    COMMAND ${CMAKE_PROJECT_BINARY_DIR}/main
    DEPENDS main
    WORKING_DIRECTORY ${CMAKE_PROJECT_SOURCE_DIR}
)

4. Соберите проект

После выполнения вышеперечисленных шагов снова выполните сборку проекта. Если все настройки правильные, ошибки о неопределённых внешних символах не должны возникать, и проект успешно соберётся.

Заключение

Следуя описанным шагам и проверяя версии библиотек и целевую платформу, вы сможете правильно связать библиотеку ODB с вашим проектом в Windows, используя CMake. Убедитесь, что все настройки совместимы, чтобы избежать дальнейших проблем с компиляцией и линковкой.

Оцените материал
Добавить комментарий

Капча загружается...