2

I'm building a dynamic library that is meant to be loaded dynamically like a plugin. When present, the library is loaded. When not present, it can't.

Naturally, I made a test app...and it doesn't work.

CMakeLists.txt

cmake_minimum_required(VERSION 2.8)
PROJECT(MYLIB)

enable_testing()
INCLUDE(CPack)

SET(SRCS
    src/source1.cpp
    src/source2.cpp
)

ADD_LIBRARY(mylib SHARED ${SRCS})

ADD_SUBDIRECTORY(test)

test/CMakeLists.txt

ADD_EXECUTABLE(test_loader main.c)
TARGET_LINK_LIBRARIES(test_loader dl)

ADD_TEST(NAME test_loader COMMAND test_loader)

test/main.c

#include <dlfcn.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
    void* handle;

    handle = dlopen("./mylib.so", RTLD_LAZY);

    if (handle == 0)
    {
        fprintf(stderr, "%s\n", dlerror());
    }

    return 1;
}

and then to build

mkdir build
cd build
cmake ..
make

The result is that there is a mylib.so file in /build. There is a test_loader executable in /build/test.

And this doesn't work out.

What I need is for there to be a copy of mylib.so under /build/test/ so that I can dynamically load it with the test app.

3
  • 1
    If you want mylib.so to be created under build/test, set CMAKE_RUNTIME_OUTPUT_VARIABLE accordingly, as describe in this question. If you want mylib.so to be existed both under build/ and under build/test/, just create appropriate target for copy library file, as it is described in that question. Commented Jun 25, 2016 at 21:31
  • If I used the CMAKE_RUNTIME_OUTPUT_DIRECTORY method, is there any reason to have both copies exist? Commented Jun 26, 2016 at 22:54
  • is there any reason to have both copies exist? - Normally, there is not. But it is fully depends on your needs. E.g., you may have another user of your library, which want to have it in another special directory. Commented Jun 27, 2016 at 8:49

2 Answers 2

4

While the answers given helped me greatly (and anyone reading this should review those answers as well as the comments), I found an even better solution:

add_custom_command(TARGET test_loader POST_BUILD 
  COMMAND ${CMAKE_COMMAND} -E copy_if_different "$<TARGET_FILE:mylib>" $<TARGET_FILE_DIR:test_loader>)

This solution results in two copies of the library. One copy is next to the test_loader, so that the unit tests can work. The other is in the default output location. Since it's still in the default output location, other projects that depend on mylib know where to find them, by default.

Sign up to request clarification or add additional context in comments.

Comments

1

There are cmake variables that let you control where libraries, shared libraries, and executables are placed. See cmake documentation Variables that Control the Build. I do not think it is a good idea to mix executables and libraries. (Of course this is my opinion--you can use whatever layout you want.) I use the following:

# Directory for output files
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib 
    CACHE PATH "Output directory for static libraries.")

set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib
    CACHE PATH "Output directory for shared libraries.")

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
    CACHE PATH "Output directory for executables and DLL's.")

If you used this, then you would need to adjust your dlopen statement to handle = dlopen("../lib/libmylib.so", RTLD_LAZY); Note that I adjusted the name of mylib because I believe cmake will, by default on Linux, use a lib prefix when naming libraries.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.