Search code examples
c++linuxsqlitecmakesoci

How to install soci db library with vcpkg on Linux?


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:

  1. I am doing something wrong (more probably solutions) - please help
  2. VCPKG is buggy and does not know how to compile C++ program? (less probably)**

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

Solution

  • 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>)