0

I've created a very basic c++ sample using the ZeroMQ library on my linux machine.

Building the project

To build the project, I decided to use CMake. Currently my CMakeLists.txt looks like this:

cmake_minimum_required (VERSION 3.9)
project(QSample)

# add ZMQ cmake files and find libzmq
set (ZeroMQ_DIR "/home/vtd/DEV_JOHANN/ZEROMQ/INSTALL_CMAKE/")
find_package(ZeroMQ REQUIRED)

# include also the zmq c++ wrapper
set(SOURCES qSample.cpp /home/vtd/DEV_JOHANN/ZEROMQ/INSTALL/include/zmq.hpp)

add_executable(QSample ${SOURCES})

# add the zmq include path
target_include_directories(QSample PRIVATE "/home/vtd/DEV_JOHANN/ZEROMQ/INSTALL/include")

# add the zmq libs
link_directories("/home/vtd/DEV_JOHANN/ZEROMQ/INSTALL/lib64")

# link the libs
TARGET_LINK_LIBRARIES(QSample libzmq)

# rule to copy the bin to the install folder
install (TARGETS QSample DESTINATION bin)

As you can see, I've changed the default zmq install paths. That's my first attempt to use CMake, so if you find any improvement to my CMakeLists.txt that would be great to know.

Generating the Makefiles through CMake works and if I run sudo make it builds my project. After that I ran sudo make install. Now there comes my problem:

Run program within build folder

If I run ./QSample with in the specified CMake build folder, my application runs like expected.

Output of ldd ./QSample:

linux-vdso.so.1 (0x00007fff78384000)
        libzmq.so.5 => /home/vtd/DEV_JOHANN/ZEROMQ/INSTALL/lib64/libzmq.so.5 (0x00007efeb3f4a000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007efeb3cf9000)
        librt.so.1 => /lib64/librt.so.1 (0x00007efeb3af1000)
        libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007efeb3965000)
        libm.so.6 => /lib64/libm.so.6 (0x00007efeb35d2000)
        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007efeb35b8000)
        libc.so.6 => /lib64/libc.so.6 (0x00007efeb31f6000)
        /lib64/ld-linux-x86-64.so.2 (0x00007efeb4026000)

Run program within installation folder

If I now switch into my specific installation folder, I can no longer run ./QSample:

/QSample: error while loading shared libraries: libzmq.so.5: cannot open shared object file: No such file or directory

Output of ldd ./QSample:

linux-vdso.so.1 (0x00007ffd975d4000)
        libzmq.so.5 => not found
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fcac89d3000)
        librt.so.1 => /lib64/librt.so.1 (0x00007fcac87cb000)
        libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007fcac863f000)
        libm.so.6 => /lib64/libm.so.6 (0x00007fcac82ac000)
        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007fcac8292000)
        libc.so.6 => /lib64/libc.so.6 (0x00007fcac7ed0000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fcac8c26000)

Right now, it's not clear for me why I can't run it in the installation folder. What do I have to change in my CMake file?

johni07
  • 761
  • 1
  • 11
  • 31
  • Can you include the output of `ldd ./QSample`? I would advise against compiling your code with sudo unless you have a good reason to as well. – GWW Sep 18 '18 at 13:14
  • @GWW I've edited my post. So it's clear that somehow it cannot find libzmq – johni07 Sep 18 '18 at 13:21
  • Is `/home/vtd/DEV_JOHANN/ZEROMQ/INSTALL/lib64` in your `LD_LIBRARY_PATH`? The other option would be to statically link the library. – GWW Sep 18 '18 at 13:22
  • No its not in LD_LIBRARY_PATH. The question is, why the behavior is changing after run make install – johni07 Sep 18 '18 at 13:23
  • You could check how the `ldd` output changes between `make` and `make install`. – GWW Sep 18 '18 at 13:58
  • 1
    By default, when **build** the executable, CMake embeds **absolute paths** to the all (shared) libraries the executable uses. When **install** this executable, CMake leaves only **library names** in it. You may find more about this process in [CMake RPATH handling ](https://gitlab.kitware.com/cmake/community/wikis/doc/cmake/RPATH-handling) article. – Tsyvarev Sep 18 '18 at 17:19

2 Answers2

0

You are currently doing

install (TARGETS QSample DESTINATION bin)

Use the following instead ( full path to your bin folder, mine is /usr/local/bin)

install(TARGETS QSample DESTINATION /usr/local/bin)

next when you have some executable place in your bin folder all you need to do is write your executable name without ./

ie in your prompt simply type QSample and it should work

$QSample

I'm currently working on ubuntu and the above works perfectly fine for me. Hope it helps.

On a short note once you place your executable in your bin folder you can run them from anywhere in the system, no need to specifically go in installation directory.

saumitra mallick
  • 395
  • 2
  • 11
  • 1
    The asker's problem is not to find an *executable*. The problem is finding the *library* which the executable needs. And you decision doesn't help in that task. As for replacing `bin` with `/usr/local/bin`: 1. It changes nothing with installation prefix (`CMAKE_INSTALL_PREFIX`) equal to `/usr/local`. 2. Using *absolute paths* in DESTINATION option of `install` command is **discouraged** in almost all cases. – Tsyvarev Sep 18 '18 at 17:24
0

(in brief)

Add following line into your CMakeLists.txt, before line add_executable:

set (CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)

(not in brief)

Your problem is rpath handling. By default, while for link stage, cmake will initiate placing all automatically discovered folders with linked libraries directly into executable program using -rpath linker option.

(assuming you are using "Unix Makefiles" generator) if you start compile/link with

make VERBOSE=1

during the link phase, you will see something like

g++  [lot of everything] -Wl,-rpath,/home/vtd/DEV_JOHANN/ZEROMQ/INSTALL/lib64

this means that while starting your executable, runtime linker will first search in folder /home/vtd/DEV_JOHANN/ZEROMQ/INSTALL/lib64, before searching $LD_LIBRARY_PATH. This allows your program to start normally, before installing it.

During install, as a part of install process, this information is stripped form executable, and it is not able to find your lib any more. You can identify what by looking into output during install process. Search for the following:

-- Installing: /usr/local/bin/QSample
-- Set runtime path of "/usr/local/bin/QSample" to ""

Empty quotes at the end means that rpath is stripped away.

One solution is to add your lib folder into LD_LIBRARY_PATH like:

LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/vtd/DEV_JOHANN/ZEROMQ/INSTALL/lib64 ./QSample

or:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/vtd/DEV_JOHANN/ZEROMQ/INSTALL/lib64
./QSample

The other solution is to instruct CMAKE not to strip rpath data. Simply add following line into your CMakeLists.txt, before line add_executable:

set (CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)

This is the link that very thoroughly explains rpath handling within cmake:

https://gitlab.kitware.com/cmake/community/wikis/doc/cmake/RPATH-handling

gordan.sikic
  • 1,174
  • 8
  • 8