I'm trying to install soci[sqlite3]
or even soci[sqlite3,boost]
(according to external information about dependencies in vcpkg) on Linux with VCPKG. Unfortunately it is not working as it should. I tried to do its on separate environment, because of that I've created docker instance:
$ 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
Then I've downloaded and built vcpkg
:
# git clone https://github.com/Microsoft/vcpkg.git --depth=1
# ./vcpkg/bootstrap-vcpkg.sh
The next step was to install soci[sqlite3]
with vcpkg, so I used command:
# ./vcpkg/vcpkg install 'soci[sqlite3]'
after succesfull installation I saw output:
...
find_package(SOCI CONFIG REQUIRED)
target_link_libraries(main PRIVATE SOCI::soci_core_static SOCI::soci_empty_static SOCI::soci_sqlite3_static)
Then I tried to get CMake argument by caling:
# ./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"
Then I use simplest CMakeLists.txt
(took from official vcpkg
tutorial modified as suggested by 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)
Then I build & compile:
# 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
And here is code (inspired from official example):
#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';
}
}
I checked compilation command (VERBOSE
flag to makefile):
# 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
And what is strange - after changing compilation command it worked!:
# /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.
To make sure I checked compiled libraries and it really contains missing symbols:
# 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&)
**As You noticed there are two possibilities:
To provide all necessarily information here is version of libraries and 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
It was bug in soci port for VCPKG, it was fixed in new version (link to issue request and link to PR).
Now after running commands provided in question VCPKG is printing:
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>)
In the code You need to replace <BACKEND>
with backend_name (in the question with sqlite3
). So correct way of linking in CMakeLists.txt is:
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>)