0

I'm trying to build a simple C++ program with libpqxx using CMake. But the linker fails on both Linux and macOS. It cannot identify C++-related headers and libraries, whereas C files related to libpq are found with the provided find_package() and target_link_libraries(). As a proof of successful installation, main.cpp can be compiled and run with clang++ main.cpp -o main -lpqxx -lpq.

Ninja output on macOS:

[2/2] Linking CXX executable main
FAILED: main 
: && /Library/Developer/CommandLineTools/usr/bin/c++ -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX13.1.sdk -mmacosx-version-min=12.6 -Wl,-search_paths_first -Wl,-headerpad_max_install_names  CMakeFiles/main.dir/src/main.cpp.o -o main  /usr/local/lib/libpq.dylib && :
Undefined symbols for architecture x86_64:
  "pqxx::connection::init(char const*)", referenced from:
      pqxx::connection::connection(char const*) in main.cpp.o
  "pqxx::connection::close()", referenced from:
      pqxx::connection::~connection() in main.cpp.o
  "pqxx::internal::demangle_type_name(char const*)", referenced from:
      ___cxx_global_var_init in main.cpp.o
      ___cxx_global_var_init.2 in main.cpp.o
      ___cxx_global_var_init.3 in main.cpp.o
      ___cxx_global_var_init.4 in main.cpp.o
  "pqxx::internal::check_pqxx_version_7_8()", referenced from:
      pqxx::check_version() in main.cpp.o
  "pqxx::connection::dbname() const", referenced from:
      _main in main.cpp.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.

CMakeLists.txt

cmake_minimum_required(VERSION 3.25)
project(main VERSION 0.1 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

set(PROJECT_SOURCES 
    src/main.cpp)

add_executable(main ${PROJECT_SOURCES})

find_package(PostgreSQL REQUIRED)

target_link_libraries(main PRIVATE PostgreSQL::PostgreSQL)

main.cpp

#include <iostream>
#include <pqxx/pqxx>

int main(int argc, const char *argv[])
{
    pqxx::connection c;

    std::cout << "Connected to " << c.dbname() << ".\n";

    return 0;
}

A similar CMakeLists.txt file for C works fine.

main.c

#include <stdio.h>
#include <libpq-fe.h>

int main(int argc, const char *argv[])
{
    int lib_ver = PQlibVersion();

    printf("Version of libpq: %d\n", lib_ver);

    return 0;
}

Intel-based Mac
macOS 12.6.8
PostgreSQL, libpq, libpqxx from Homebrew

Ubuntu 22.04
PostgreSQL, libpq-dev from apt
libpqxx built from source and installed to /usr/local

  • Your CPU is M1 arm64, libpq is built for arm64, but you build main for x86_64 for unknown reasons. How do you generate ninja files with cmake? – 273K Aug 09 '23 at 16:30
  • 2
    `find_package(PostgreSQL REQUIRED)` find C libpq, but you also need `find_package(PQXX)`. – 273K Aug 09 '23 at 16:34
  • @273K, 1) I’m on x86_64. 2) Install Ninja, then `cmake -G ‘Ninja’ path/to/file`. – Mehrshad Khansarian Aug 09 '23 at 20:19
  • @273K, `find_package(PQXX)` or `find_package(pqxx)` do not work, since libpqxx does not provide us with any CMake package configuration files. – Mehrshad Khansarian Aug 09 '23 at 20:20
  • `find_package(PostgreSQL)` itself is provided by CMake, not libpqxx. – Mehrshad Khansarian Aug 09 '23 at 20:23
  • 1
    It provides `libpqxx.pc`, you can use `pkg_check_modules` and/or write own `FindPQXX.cmake` – 273K Aug 09 '23 at 20:26
  • @273K, I did follow your advice on using pkg-config but I'm having a hard time linking against the libraries and setting the flags. Could you provide me with a sample CMakeLists.txt file? – Mehrshad Khansarian Aug 09 '23 at 21:44
  • Here are the variables **libpqxx.px** sets for me: LIBRARIES: pqxx, LINK_LIBRARIES: /usr/local/Cellar/libpqxx/7.8.1/lib/libpqxx.dylib, LIBRARY_DIRS: /usr/local/Cellar/libpqxx/7.8.1/lib, LDFLAGS: -L/usr/local/Cellar/libpqxx/7.8.1/lib;-lpqxx, INCLUDE_DIRS: /usr/local/Cellar/libpqxx/7.8.1/include, CFLAGS: -I/usr/local/Cellar/libpqxx/7.8.1/include. – Mehrshad Khansarian Aug 09 '23 at 21:45
  • tldr; use `find_package(libpqxx REQUIRED)` and `target_link_libraries(main PRIVATE libpqxx::pqxx)` https://github.com/jtv/libpqxx/blob/77e1e08ffe8f93c2e5e75a6db492165f3f1a2f98/CMakeLists.txt#L54-L62 https://github.com/jtv/libpqxx/blob/77e1e08ffe8f93c2e5e75a6db492165f3f1a2f98/src/CMakeLists.txt#L69 – Osyotr Aug 09 '23 at 22:02
  • @Osyotr, the `libpqxx` package cannot be found as there is no corresponding package configuration file. – Mehrshad Khansarian Aug 11 '23 at 18:08
  • @MehrshadKhansarian for some reason Ubuntu does not include cmake config for libpqxx, even though the package does export it. – Osyotr Aug 12 '23 at 17:37
  • @Osyotr, are you sure that’s just Ubuntu? Since it isn’t included in macOS either. – Mehrshad Khansarian Aug 13 '23 at 08:04

2 Answers2

2

libpqxx-dev provides libpqxx.pc for pkg-config that is well integrated with CMake. Add to your CMakeLists.txt:

find_package(PkgConfig REQUIRED)

pkg_check_modules(PQXX REQUIRED libpqxx)

target_link_libraries(main PRIVATE ${PQXX_LINK_LIBRARIES} PostgreSQL::PostgreSQL)
273K
  • 29,503
  • 10
  • 41
  • 64
0

One could also use IMPORTED_TARGET:

find_package(PostgreSQL REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(PQXX REQUIRED IMPORTED_TARGET libpqxx)

target_link_libraries(main PUBLIC PkgConfig::PQXX PostgreSQL::PostgreSQL)