0

I wish to link libraries such as jsoncpp and rapidxml to my C++ code, which will be run on a server machine. The server uses Anaconda virtual environments to remain as clean as possible, so I have to install these packages into an env and direct my code to find them there instead of the usual path. I can link simple externally installed libraries dynamically with CMake but for the life of me I can't figure out how to link the ones installed in Conda envs.

I have tried several variations of:

cmake .. -DCMAKE_PREFIX_PATH=$CONDA_PREFIX

and in the cmake list:

SET(CMAKE_PREFIX_PATH /home/XXX/anaconda3/envs/envname)

and then either having:

target_link_libraries(mycode jsoncpp)

or

find_package(PkgConfig REQUIRED)
pkg_check_modules(JSONCPP jsoncpp)
target_link_libraries(mycode ${JSONCPP_LIBRARIES})

or nothing at all. I haven't installed CMake itself into my Conda env, I have it separately and I only attempt to run make from the console while being in the active env.

Edit: if I do not use the lines:

target_link_libraries(mycode jsoncpp)

or

find_package(PkgConfig REQUIRED)
pkg_check_modules(JSONCPP jsoncpp)
target_link_libraries(mycode ${JSONCPP_LIBRARIES})

Then CMake throws me a long winded error full of

undefined reference to `Json::Value::~Value()'

If I do use one of those options, then when I want to execute the binary on another machine, inside a Conda environment with jsoncpp installed, I get this error:

error while loading shared libraries: libjsoncpp.so.1: cannot open shared object file: No such file or directory

Because of this, I assume CMake linked the globally installed jsoncpp somehow, not the Conda one.

oliver.c
  • 65
  • 1
  • 8
  • Call to `pkg_check_modules(JSONCPP jsoncpp)` searches for `jsoncpp.pc` file. Do you have such file under your Conda environment? What is exact path to that file? – Tsyvarev Jul 11 '23 at 09:39
  • @Tsyvarev I do have such a file in "/home/XXX/anaconda3/envs/envname/lib/pkgconfig" – oliver.c Jul 11 '23 at 09:42
  • Hm, with your settings of `CMAKE_PREFIX_PATH` variable call to `pkg_check_modules` should work. What exactly doesn't work in your case? Do you got errors from one of your command or when compile your code? Please, update your question post with the error message. – Tsyvarev Jul 11 '23 at 09:47
  • @Tsyvarev I have edited my question with the two possible outcome so far. – oliver.c Jul 11 '23 at 09:54
  • "Because of this, I assume CMake linked the globally installed jsoncpp somehow, not the Conda one." - This is very easy to check: run `ldd` on the resulted binary, and it will show the absolute paths of the libraries which will be used by that binary on run. – Tsyvarev Jul 11 '23 at 09:59
  • @Tsyvarev it is indeed wrongly linked "libjsoncpp.so.1 => /usr/lib/x86_64-linux-gnu/libjsoncpp.so.1" – oliver.c Jul 11 '23 at 10:09
  • Does this path corresponds to value of `JSONCPP_LIBRARIES` variable? It seems that `pkg_check_modules` command (and eventually `pkg-config`) utility prefers system paths to ones under Conda environment. You could try to link with the json library by its absolute path under Conda environment. But most likely CMake will give you a warning "Cannot generate a safe runtime search path": https://stackoverflow.com/questions/22536567/cmake-cannot-resolve-runtime-directory-path – Tsyvarev Jul 11 '23 at 10:41

1 Answers1

0

After several failed attempt, I've finally managed both the compilation and execution.

In the CMakeLists.txt I first changed where pkg-config should primarily search for packages, as otherwise it defaults on stuff in /usr/lib and won't go any further:

set(ENV{PKG_CONFIG_PATH} "$ENV{CONDA_PREFIX}/lib/pkgconfig")

I had a lot of trouble getting the syntax right, also changing the CMAKE_PREFIX_PATH or the CMAKE_INSTALL_PREFIX was doing nothing. Then, I used pkg-config to find the jsoncpp I installed in the conda environment:

find_package(PkgConfig REQUIRED)
pkg_check_modules(PKG_JSONCPP REQUIRED IMPORTED_TARGET jsoncpp)
target_link_libraries(combined_reader PkgConfig::PKG_JSONCPP)

All these were successfully executed when I ran the cmake command from an active conda environment and I could check with ldd to see that indeed most packages were linked from the env. The tricky part was, however, when I copied the binary to another machine, even with an active (and identical) conda env, ldd showed either packages linked from /usr/lib or not found at all. For this, I had to execute the binary with a changed environmental variable:

env LD_LIBRARY_PATH=$CONDA_PREFIX/lib ./<binary_file>

And then it worked. Here, CONDA_PREFIX is interchangeable with the proper full path of the desired env, in which case it does not need to be even activated. Also, by running:

env LD_LIBRARY_PATH=$CONDA_PREFIX/lib ldd <binary_file>

I could check the linked packages used for such an execution, which were (almost) all from the conda env.

oliver.c
  • 65
  • 1
  • 8