我正在尝试使用 VCPKG 在 Linux 上安装
soci[sqlite3]
甚至 soci[sqlite3,boost]
(根据 有关 vcpkg 中依赖项的外部信息)。不幸的是它没有发挥应有的作用。我尝试在单独的环境中执行此操作,因为我创建了 docker 实例:
$ docker run -it --rm --network=host -v $(pwd):/home/ --workdir /home --name='ubuntu_test' ubuntu:22.04
# apt-get update && apt-get upgrade -y --no-install-recommends
# apt-get install g++ git cmake curl zip unzip tar ca-certificates make pkg-config --no-install-recommends -y
然后我已经下载并构建了
vcpkg
:
# git clone https://github.com/Microsoft/vcpkg.git --depth=1
# ./vcpkg/bootstrap-vcpkg.sh
下一步是使用 vcpkg 安装
soci[sqlite3]
,所以我使用了命令:
# ./vcpkg/vcpkg install 'soci[sqlite3]'
安装成功后我看到输出:
...
find_package(SOCI CONFIG REQUIRED)
target_link_libraries(main PRIVATE SOCI::soci_core_static SOCI::soci_empty_static SOCI::soci_sqlite3_static)
然后我尝试通过 caling 来获取 CMake 参数:
# ./vcpkg/vcpkg integrate install
Applied user-wide integration for this vcpkg root.
CMake projects should use: "-DCMAKE_TOOLCHAIN_FILE=/home/vcpkg/scripts/buildsystems/vcpkg.cmake"
然后我使用最简单的
CMakeLists.txt
(从官方vcpkg
教程中获取,并根据
vcpkg
的建议进行修改):
cmake_minimum_required(VERSION 3.16)
project(Learning_VCPKG LANGUAGES CXX)
find_package(SOCI CONFIG REQUIRED)
if (SOCI_FOUND)
message("Soci found: ${SOCI_INCLUDE_DIRS} and ${SOCI_LIBRARY_DIRS}")
endif ()
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} PRIVATE SOCI::soci_core_static SOCI::soci_empty_static SOCI::soci_sqlite3_static)
然后我构建并编译:
# cmake . -DCMAKE_TOOLCHAIN_FILE=/home/vcpkg/scripts/buildsystems/vcpkg.cmake
Soci found: and
-- Configuring done
-- Generating done
-- Build files have been written to: /home
root@agh-legion:/home# make
[ 50%] Building CXX object CMakeFiles/Learning_VCPKG.dir/main.cpp.o
[100%] Linking CXX executable Learning_VCPKG
/usr/bin/ld: vcpkg/installed/x64-linux/debug/lib/libsoci_sqlite3.a(vector-into-type.cpp.o): in function `soci::sqlite3_vector_into_type_backend::post_fetch(bool, soci::indicator*)':
/home/vcpkg/buildtrees/soci/src/v4.0.3-7f07d34610.clean/src/backends/sqlite3/vector-into-type.cpp:260: undefined reference to `soci::details::parse_std_tm(char const*, tm&)'
/usr/bin/ld: vcpkg/installed/x64-linux/debug/lib/libsoci_sqlite3.a(standard-into-type.cpp.o): in function `soci::sqlite3_standard_into_type_backend::post_fetch(bool, bool, soci::indicator*)':
/home/vcpkg/buildtrees/soci/src/v4.0.3-7f07d34610.clean/src/backends/sqlite3/standard-into-type.cpp:139: undefined reference to `soci::details::parse_std_tm(char const*, tm&)'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/Learning_VCPKG.dir/build.make:102: Learning_VCPKG] Error 1
make[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/Learning_VCPKG.dir/all] Error 2
make: *** [Makefile:91: all] Error 2
这是代码(灵感来自官方示例):
#include <exception>
#include <iostream>
#include <soci/soci.h>
#include <soci/sqlite3/soci-sqlite3.h>
#include <string>
using namespace soci;
using namespace std;
int main()
{
try {
soci::session sql(sqlite3, "test.db");
sql << "CREATE TABLE IF NOT EXISTS Employees("
"ID INT PRIMARY KEY NOT NULL,"
"name TEXT NOT NULL,"
"Age INT NOT NULL,"
"Address TEXT,"
"Salary REAL);";
sql << "INSERT INTO Employees (ID, name, Age, Address, Salary) VALUES (1, 'Tadeusz', 24, 'Krakow', 2000.01 ); ";
sql << "INSERT INTO Employees (ID, name, Age, Address, Salary) VALUES (2, 'Symeon', 25, 'Texas', 15000.00 ); ";
sql << "INSERT INTO Employees (ID, name, Age, Address, Salary) VALUES (3, 'Rodion', 23, 'Norway', 20000.00 );";
int count;
sql << "select count(*) from Employees", into(count);
cout << "We have " << count << " entries in the Employees table.\n";
} catch (exception const& e) {
cerr << "Error: " << e.what() << '\n';
}
}
我检查了编译命令(makefile 的
VERBOSE
标志):
# make VERBOSE=True
/usr/bin/c++ CMakeFiles/Learning_VCPKG.dir/main.cpp.o -o Learning_VCPKG vcpkg/installed/x64-linux/debug/lib/libsoci_core.a vcpkg/installed/x64-linux/debug/lib/libsoci_empty.a vcpkg/installed/x64-linux/debug/lib/libsoci_sqlite3.a /usr/lib/x86_64-linux-gnu/libdl.a vcpkg/installed/x64-linux/debug/lib/libsqlite3.a
奇怪的是 - 更改编译命令后它起作用了!:
# /usr/bin/c++ CMakeFiles/Learning_VCPKG.dir/main.cpp.o vcpkg/installed/x64-linux/debug/lib/libsoci_core.a vcpkg/installed/x64-linux/debug/lib/libsoci_empty.a vcpkg/installed/x64-linux/debug/lib/libsoci_sqlite3.a /usr/lib/x86_64-linux-gnu/libdl.a vcpkg/installed/x64-linux/debug/lib/libsqlite3.a -o Learning_VCPKG -L./vcpkg/installed/x64-linux/debug/lib/ -lsoci_core
root@agh-legion:/home# ./Learning_VCPKG
We have 3 entries in the Employees table.
为了确保我检查了编译的库并且它确实包含丢失的符号:
# nm -C vcpkg/installed/x64-linux/debug/lib/libsoci_core.a | grep "parse_std_tm"
00000000000002bd T soci::details::parse_std_tm(char const*, tm&)
**正如您所注意到的,有两种可能性:
在这里提供所有必要的信息是库和 vcpkg 的版本:
# ./vcpkg/vcpkg list
soci:x64-linux 4.0.3#1 SOCI database access library
soci[sqlite3]:x64-linux Build sqlite3 backend
sqlite3:x64-linux 3.43.0 SQLite is a software library that implements a s...
sqlite3[json1]:x64-linux Enable JSON functionality for sqlite3
vcpkg-cmake-config:x64-linux 2022-02-06#1
vcpkg-cmake:x64-linux 2023-05-04
# ./vcpkg/vcpkg version
vcpkg package management program version 2023-09-15-ac02a9f660977426b8ec6392919fbb1d51b10998
这是 VCPKG 的 soci 端口中的错误,已在新版本中修复(发出请求的链接和PR的链接)。
现在运行问题中提供的命令后,VCPKG 正在打印:
find_package(soci CONFIG REQUIRED)
target_link_libraries(main PRIVATE $<IF:$<TARGET_EXISTS:SOCI::soci_core>,SOCI::soci_core,SOCI::soci_core_static>)
# Linking specific backends (enabled: sqlite3)
target_link_libraries(main PRIVATE $<IF:$<TARGET_EXISTS:SOCI::soci_<BACKEND>,SOCI::soci_<BACKEND>,SOCI::soci_<BACKEND>_static>)
在代码中,您需要将
<BACKEND>
替换为 backend_name (在带有 sqlite3
的问题中)。所以在 CMakeLists.txt 中链接的正确方法是:
target_link_libraries(${PROJECT_NAME} PRIVATE $<IF:$<TARGET_EXISTS:SOCI::soci_core>,SOCI::soci_core,SOCI::soci_core_static>)
target_link_libraries(${PROJECT_NAME} PRIVATE $<IF:$<TARGET_EXISTS:SOCI::soci_sqlite3>,SOCI::soci_sqlite3,SOCI::soci_sqlite3_static>)