0

I'm trying to build a project with LIBPQXX Github for PostgreSQL using CLion and CMakeFiles. Here is my simple code for this problem, the argument in the pqxx::connection con(); function were changed on purpose for the post.

#include <iostream>
#include <pqxx/pqxx>
#include "project_config.h"


int main()
{
    pqxx::connection conn("dbname = dbname user = user password = password hostaddr = hostaddr port = port");
    std::cout << "Opened database successfully: " << std::endl;
    return 0;
}

When I execute the command in the Shell

g++ -std=c++11 -I /usr/local/include/pqxx/ -L /usr/local/lib/ -I /usr/pgsql-10/include/ -L /usr/pgsql-10/lib/ main.cpp -lpqxx -lpq -o run

and after that ./run, everything works as it should.

Now, when I use those CMakeFiles settings to get the same result to run the project in CLion

cmake_minimum_required(VERSION 3.10)
project(project)

# Set flags
set(COMPILE_FLAGS "-std=c++11")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMPILE_FLAGS}")

# The version number.
set (project_VERSION_MAJOR 1)
set (project_VERSION_MINOR 0)

# Use a header file for some CMake settings in the source code
configure_file (
        "${PROJECT_SOURCE_DIR}/project_config.h.in"
        "${PROJECT_BINARY_DIR}/project_config.h"
)


# Set new own names
set(APP_DOMAIN ${PROJECT_SOURCE_DIR}/dev/hmmenc_client)
set(PQXX /usr/local/include/pqxx)
set(PGSQL_10 /usr/pgsql-10/include)

# Find the pqxx and pq libraries
find_library(PQXX_LIB pqxx "${PQXX}")
find_library(PQ_LIB pq "${PGSQL_10}")


include_directories(${PROJECT_BINARY_DIR})

# Other project path includes
include_directories(${APP_DOMAIN})
include_directories(${PQXX})
include_directories(${PGSQL_10})

find_package(FindPQXX)

set(SOURCE_FILES
#        ${APP_DOMAIN}/db/db.h
#        ${APP_DOMAIN}/db/db.cpp
        ${APP_DOMAIN}/main.cpp
    )

add_executable(project ${SOURCE_FILES})
target_link_libraries(${TARGET_NAME} pqxx)
#link_directories(project ${PQXX})

But when I try to run it I get:

CMakeFiles/project.dir/dev/hmmenc_client/main.cpp.o: In function `pqxx::connection_base::connection_base(pqxx::connectionpolicy&)':
/usr/local/include/pqxx/connection_base.hxx:695: undefined reference to `int pqxx::internal::check_library_version<6, 2>()'
/usr/local/include/pqxx/connection_base.hxx:698: undefined reference to `pqxx::connection_base::clearcaps()'
CMakeFiles/project.dir/dev/hmmenc_client/main.cpp.o: In function `pqxx::connect_direct::connect_direct(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
/usr/local/include/pqxx/connection.hxx:83: undefined reference to `pqxx::connectionpolicy::connectionpolicy(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
/usr/local/include/pqxx/connection.hxx:83: undefined reference to `vtable for pqxx::connect_direct'
CMakeFiles/project.dir/dev/hmmenc_client/main.cpp.o: In function `pqxx::connect_direct::~connect_direct()':
/usr/local/include/pqxx/connection.hxx:78: undefined reference to `vtable for pqxx::connect_direct'
/usr/local/include/pqxx/connection.hxx:78: undefined reference to `pqxx::connectionpolicy::~connectionpolicy()'
CMakeFiles/project.dir/dev/hmmenc_client/main.cpp.o: In function `pqxx::basic_connection<pqxx::connect_direct>::~basic_connection()':
/usr/local/include/pqxx/basic_connection.hxx:66: undefined reference to `pqxx::connection_base::close()'
CMakeFiles/project.dir/dev/hmmenc_client/main.cpp.o: In function `pqxx::basic_connection<pqxx::connect_direct>::basic_connection(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
/usr/local/include/pqxx/basic_connection.hxx:57: undefined reference to `pqxx::connection_base::init()'
collect2: error: ld returned 1 exit status
gmake[3]: *** [CMakeFiles/project.dir/build.make:95: project] Error 1
gmake[2]: *** [CMakeFiles/Makefile2:68: CMakeFiles/project.dir/all] Error 2
gmake[1]: *** [CMakeFiles/Makefile2:80: CMakeFiles/project.dir/rule] Error 2
gmake: *** [Makefile:118: project] Error 2

Can someone help me with my CMakeLists configurations to get the same results as with executing the command above in the Shell?

Update

I tried to use the FindPQXX.cmake as suggested in the comments below but I'm still getting the error

CMake Warning at CMakeLists.txt:76 (find_package):
  By not providing "FindFindPQXX.cmake" in CMAKE_MODULE_PATH this project has
  asked CMake to find a package configuration file provided by "FindPQXX",
  but CMake did not find one.

  Could not find a package configuration file provided by "FindPQXX" with any
  of the following names:

    FindPQXXConfig.cmake
    findpqxx-config.cmake

  Add the installation prefix of "FindPQXX" to CMAKE_PREFIX_PATH or set
  "FindPQXX_DIR" to a directory containing one of the above files.  If
  "FindPQXX" provides a separate development package or SDK, be sure it has
  been installed.

To make things maybe a little bit clearer. Lets say that my project tree looks like this:

project # Root folder
project/cmake-build-debug # Some cmake code
project/dev
project/dev/hmmenc_client/ # I write my program with all the subfolders and their classes here
project/dev/SEAL_API/ # Some other code to use later

I have my CMakeLists.txt and the FindPQXX.cmake files in my project root folder. The main.cpp that I want to compile is in project/dev/hmmenc_client/

I have added the

find_package(FindPQXX)
target_link_libraries(${TARGET_NAME} pqxx)

to my CMakeFiles.txt. What am I missing here and what does ${TARGET_NAME} stands for? I had to edit the FindPQXX.cmake file to include the /usr/pgsql-10/include/ and /usr/pgsql-10/lib/ since that is where I have my postgres dev requirements. The real PostgreSQL database is on some other machine.

I used the standard settings to install the libpqxx from Github mentioned above so the relevant folders are /usr/local/include/pqxx/ and /usr/local/lib/

I'm new to the Cmake world so don't take any info out :)

TalG
  • 677
  • 1
  • 9
  • 26
  • First, `CMAKE_CXX_FLAGS` are flags used for compilation to object files, they are not linker flags. Secondly, to add libraries to your application you use [`target_link_libraries`](https://cmake.org/cmake/help/latest/command/target_link_libraries.html). – Some programmer dude Jun 15 '18 at 12:30
  • Possible duplicate of [How to add "-l" (ell) compiler flag in CMake](https://stackoverflow.com/questions/43136418/how-to-add-l-ell-compiler-flag-in-cmake) – Tsyvarev Jun 15 '18 at 12:40

2 Answers2

1

To use a library "foo" with CMake, the idiomatic way to go is to find/use/write a .cmake file which, using CMake syntax and commands, identifies where foo is installed on your OS and set appropriate variables for target_link_libraries to find.

I've found a fork of libpqxx on github which happens to include FindPQXX.cmake. In order to use it, include in your main CMakeLists.txt the following:

find_package(PQXX)
target_link_libraries(${TARGET_NAME} pqxx)
Tsyvarev
  • 60,011
  • 17
  • 110
  • 153
YSC
  • 38,212
  • 9
  • 96
  • 149
  • 1
    `FindXXX.cmake` scripts are intended to be used with `find_package(XXX)`. Do not attempt to `include()` them. – Tsyvarev Jun 15 '18 at 12:41
  • It is worth noting, that `FindPQXX.cmake` should be compied to the package, which uses it, and directory to that script should be appended to `CMAKE_MODULE_PATH` variable. – Tsyvarev Jun 15 '18 at 13:25
  • @Tsyvarev you mean that I have to copy the `FindPQXX.cmake` file to the project folder then add the project folder to the `CMAKE_MODULE_PATH` variable and then add the `find_package(FindPQXX)`, `target_link_libraries(${TARGET_NAME} pqxx)` to my `CMakeFiles.txt`? – TalG Jun 15 '18 at 13:38
  • @TalG: Exactly. Appending directory could be done like `list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)` (if you add the script into `cmake/` subdirectory of the project. – Tsyvarev Jun 15 '18 at 13:52
  • @Tsyvarev I've done it but I keep getting the `CMake Warning at CMakeLists.txt:76 (find_package): By not providing "FindFindPQXX.cmake.cmake" in CMAKE_MODULE_PATH this project has asked CMake to find a package configuration file provided by "FindPQXX.cmake", but CMake did not find one. Could not find a package configuration file provided by "FindPQXX.cmake" with any of the following names: FindPQXX.cmakeConfig.cmake findpqxx.cmake-config.cmake` – TalG Jun 15 '18 at 14:03
  • `Add the installation prefix of "FindPQXX.cmake" to CMAKE_PREFIX_PATH or set "FindPQXX.cmake_DIR" to a directory containing one of the above files. If "FindPQXX.cmake" provides a separate development package or SDK, be sure it has been installed.` – TalG Jun 15 '18 at 14:05
  • @TalG remove the `.cmake` from `find_package` ;) That was an error on my end, now fixed in the answer. – YSC Jun 15 '18 at 14:16
  • @YSC Thanks, but I get the same error :(. I've updated my main post. – TalG Jun 15 '18 at 15:11
  • @Tsyvarev I have updated my post, somehow I just don't get your instructions here :( – TalG Jun 15 '18 at 21:06
  • @talg dude! You need to **read** the function's doc. I wrote `${TARGET_NAME}` as a placeholder, you need to replace it. Then, the `find_package` + `target_link_library` should not be mixed with `find_library`. – YSC Jun 16 '18 at 08:14
  • @TalG: Sorry, proper call should be `find_package(PQXX)`. In my previous edit I have removed `.cmake` suffix, but forgot to remove the `Find` prefix. Now the code in the answer is fixed. – Tsyvarev Jun 17 '18 at 07:51
  • @YSC: Script `FindPQXX.cmake` you refer to **doesn't set** `pqxx` imported *target*. It sets include directories to `PQXX_INCLUDE_DIRECTORIES` variable and library to `PQXX_LIBRARIES` variable. So the usage after `find_package(PQXX)` should be `include_directories(${PQXX_INCLUDE_DIRECTORIES})` and `target_link_libraries( ${PQXX_LIBRARIES})`. – Tsyvarev Jun 17 '18 at 07:56
0

Here is my working configurations of the CMakeLists.txt that executes g++ -std=c++11 -I /usr/local/include/pqxx/ -L /usr/local/lib/ -I /usr/pgsql-10/include/ -L /usr/pgsql-10/lib/ main.cpp -lpqxx -lpq after it didn't work with the FindPQXX.cmake file.

cmake_minimum_required(VERSION 3.10)
project(project)

# Set flags
set(GCC_COVERAGE_COMPILE_FLAGS "-std=gnu++11")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}")

# The version number.
set(project_VERSION_MAJOR 1)
set(project_VERSION_MINOR 0)

# Use a header file for some CMake settings in the source code
configure_file (
        "${PROJECT_SOURCE_DIR}/project_config.h.in"
        "${PROJECT_BINARY_DIR}/project_config.h"
)

# Set some path variables
set(APP_DOMAIN ${PROJECT_SOURCE_DIR}/dev/hmmenc_client)
set(PQXX /usr/local/include/pqxx)
set(PGSQL_10 /usr/pgsql-10/include)

# Find the needed libraries for liniking with -lpqxx and -lpq flags
find_library(PQXX_LIB pqxx)
#message("PQXX_LIB is ${PQXX_LIB}")
find_library(PQ_LIB pq)
#message("PQ_LIB is ${PQ_LIB}")

# Project path includes
include_directories(${PROJECT_BINARY_DIR} 
                    ${APP_DOMAIN}
                    ${PQXX}
                    ${PGSQL_10}
        )
#message("PQXX is ${PQXX}")
#message("PGSQL_10 is ${PGSQL_10}")

# Set source files
set(SOURCE_FILES
        ${APP_DOMAIN}/db/db.h
        ${APP_DOMAIN}/db/db.cpp
        ${APP_DOMAIN}/main.cpp
    )

add_executable(project ${SOURCE_FILES})
# Link the liraries of pqxx and pq to the executable
target_link_libraries(project ${PQXX_LIB} ${PQ_LIB})

One thing I don't understand is that my find_library(PQ_LIB pq) finds pq in /user/lib64 and I cant change it to look in the /usr/pgsql-10/lib, which also has the file that I would prefer to use.

TalG
  • 677
  • 1
  • 9
  • 26