0

On a project of mine using c++ and cmake, I include several third party libraries, including SDL2. As many before me, I'm struggling to get the application to find the libraries correctly to run. So, as usual, if the libraries are installed in the system, SDL2 is found with find_package, and everything proceeds as normal.

( EDIT )This is ThirdParty.cmake:

cmake_minimum_required(VERSION 2.8)
include ( "ExternalProject" )

message ( STATUS "********** Starting third party dependency checks **********")
set ( THIRD_PARTY_OUTPUT_PATH "${CMAKE_CURRENT_LIST_DIR}/${CMAKE_SYSTEM_NAME}" )

list ( APPEND CMAKE_PREFIX_PATH ${THIRD_PARTY_OUTPUT_PATH} )
set ( THIRD_PARTY_DEPENDENCIES_OK TRUE )

# GLM
find_package ( GLM QUIET )
if ( NOT GLM_FOUND )
    ExternalProject_Add ( ThirdParty_GLM
        #GIT_REPOSITORY "https://github.com/g-truc/glm"
        URL "https://github.com/g-truc/glm/archive/0.9.7.6.zip"
        INSTALL_DIR ${THIRD_PARTY_OUTPUT_PATH}
        CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
        )

    set ( THIRD_PARTY_DEPENDENCIES_OK FALSE )
    #add_subdirectory ( ThirdParty/glm )
    #set ( GLM_INCLUDE_DIR "ThirdParty/glm" )
endif()

# SDL2
find_package ( SDL2 QUIET )
if ( NOT SDL2_FOUND )
    ExternalProject_Add ( ThirdParty_SDL2
        URL "https://www.libsdl.org/release/SDL2-2.0.5.zip"
        INSTALL_DIR ${THIRD_PARTY_OUTPUT_PATH}
        CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
        )
    set ( THIRD_PARTY_DEPENDENCIES_OK FALSE )

#    set ( SDL_SHARED_ENABLED_BY_DEFAULT FALSE )
#    add_subdirectory ( ThirdParty/SDL2 )
#    set ( SDL2_INCLUDE_DIR "ThirdParty/SDL2/include" )
#    set ( SDL2_LIBRARY sdl2-static )
endif()

# FreeImage
find_package ( FreeImage QUIET )
if ( NOT FREEIMAGE_FOUND )
    ExternalProject_Add ( ThirdParty_FreeImage
        GIT_REPOSITORY "gitrepo:Misc/FreeImage"
        INSTALL_DIR ${THIRD_PARTY_OUTPUT_PATH}
        CMAKE_ARGS -DSDL_SHARED_ENABLED_BY_DEFAULT=FALSE -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
        )
    set ( THIRD_PARTY_DEPENDENCIES_OK FALSE )
#    add_subdirectory ( ThirdParty/FreeImage )
#    set ( FREEIMAGE_INCLUDE_DIR "ThirdParty/FreeImage/src" )
#    set ( FREEIMAGE_LIBRARY freeimage )
endif()

# Assimp
find_package ( Assimp QUIET )
if ( NOT ASSIMP_FOUND )
    ExternalProject_Add ( ThirdParty_Assimp
        GIT_REPOSITORY "https://github.com/assimp/assimp"
        GIT_TAG "v3.2"
        INSTALL_DIR ${THIRD_PARTY_OUTPUT_PATH}
        CMAKE_ARGS -DCMAKE_C_FLAGS=-fPIC -DCMAKE_CXX_FLAGS=-fPIC -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> "-DASSIMP_BUILD_TESTS=OFF"
        )
    set ( THIRD_PARTY_DEPENDENCIES_OK FALSE )
#    set ( ASSIMP_BUILD_ASSIMP_TOOLS FALSE)
#    set ( ASSIMP_BUILD_TESTS FALSE )
#    set ( BUILD_SHARED_LIBS FALSE )
#    add_subdirectory ( ThirdParty/Assimp )
#    set ( ASSIMP_INCLUDE_DIR "ThirdParty/assimp/include" )
#    set ( ASSIMP_LIBRARIES "assimp" )
endif()

if ( THIRD_PARTY_DEPENDENCIES_OK )
    list ( APPEND ILLUSION_INCLUDE_DIRS ${SDL2_INCLUDE_DIR} )
    list ( APPEND ILLUSION_INCLUDE_DIRS ${GLM_INCLUDE_DIR} )
    list ( APPEND ILLUSION_INCLUDE_DIRS ${FREEIMAGE_INCLUDE_DIR} )
    list ( APPEND ILLUSION_INCLUDE_DIRS ${ASSIMP_INCLUDE_DIR} )

    list ( APPEND ILLUSION_LIBRARIES ${SDL2_LIBRARIES} )
    list ( APPEND ILLUSION_LIBRARIES ${FREEIMAGE_LIBRARY} )
    list ( APPEND ILLUSION_LIBRARIES ${ASSIMP_LIBRARIES} )

    list ( APPEND ILLUSION_LINK_DIRS ${THIRD_PARTY_OUTPUT_PATH}/lib )
    list ( APPEND ILLUSION_INCLUDE_DIRS ${THIRD_PARTY_OUTPUT_PATH}/include )
else()
    message ( STATUS "Dependencies not ready. Building")
endif()

message ( STATUS "********** Finished third party dependency checks **********")

(EDIT) This is the full CMakeLists.txt

cmake_minimum_required(VERSION 2.8)
project ( Illusion )

########## Platform and target configuration ##########
string ( TOUPPER ${CMAKE_SYSTEM_NAME} UPPERCASE_SYSTEM_NAME )
message ( STATUS "Host building system - ${CMAKE_SYSTEM}" )
set ( ILLUSION_TARGET_PLATFORM ${UPPERCASE_SYSTEM_NAME} )
list ( APPEND ILLUSION_DEFINITIONS -DILLUSION_TARGET_PLATFORM_${UPPERCASE_SYSTEM_NAME} )
message ( STATUS "Target system - ${ILLUSION_TARGET_PLATFORM}" )

set ( ILLUSION_VERSION_MAJOR 0 )
set ( ILLUSION_VERSION_MINOR 4 )
set ( ILLUSION_ROOT ${PROJECT_SOURCE_DIR})
set ( ILLUSION_BUILTIN_DATA_PATH \"/usr/local/share/Illusion/\" )
list ( APPEND ILLUSION_INCLUDE_DIRS "${ILLUSION_ROOT}" )
set ( CMAKE_MODULE_PATH "${ILLUSION_ROOT}/ThirdParty/CMakeHelpers" ${CMAKE_MODULE_PATH})
set ( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${ILLUSION_TARGET_PLATFORM}/lib )
set ( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${ILLUSION_TARGET_PLATFORM}/lib )
set ( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${ILLUSION_TARGET_PLATFORM}/bin )
set ( CMAKE_INSTALL_RPATH ${THIRD_PARTY_OUTPUT_PATH}/lib )
set ( CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE )

########## Third party libraries ##########
include ( "ThirdParty/ThirdParty.cmake" )

add_definitions ( ${ILLUSION_DEFINITIONS} )
include_directories ( ${ILLUSION_INCLUDE_DIRS} )
if ( THIRD_PARTY_DEPENDENCIES_OK )
    message ( STATUS "All dependencies present. Building Illusion")
    ########## Compiler configuration ##########
    if ( "${CMAKE_BUILD_TYPE}" STREQUAL "" )
        set ( CMAKE_BUILD_TYPE Debug )
        message ( STATUS "Setting build type to debug as default" )
    endif()

    include ( "ThirdParty/CMakeHelpers/Macros.cmake" )
    enable_all_warnings()
    use_cpp11()

    ########## Choose graphics backend ##########
    include ( "Graphics/Graphics.cmake" )

    ########## Main library ##########
    configure_file (
      "${PROJECT_SOURCE_DIR}/IllusionConfig.h.in"
      "${PROJECT_SOURCE_DIR}/IllusionConfig.h"
      )

    file ( GLOB Illusion_Sources "*.cpp" "*.h" "Graphics/*.cpp" "Graphics/*.h" "Material/*.cpp" "Material/*.h" "Camera/*.cpp" "Camera/*.h" "Model/*.cpp" "Model/*.h" "Asset/*.cpp" "Asset/*.h " "FileSystem/*.cpp" "FileSystem/*.h" )
    file ( GLOB_RECURSE Pipeline_Sources "Pipelines/*" )
    file ( GLOB_RECURSE DataFiles "Data/*" FindIllusion.cmake TODO.txt )
    add_library ( WindowSystem "WindowSystem/WindowSystem.cpp" "WindowSystem/WindowSystem.h" )
    add_library ( Illusion
        ${Illusion_Sources}
        ${DataFiles}
        ${Pipeline_Sources}
        )

    ########## Submodules ##########
    add_subdirectory ( StringFunctions )
    add_subdirectory ( ValueFileParser )

    list ( APPEND ILLUSION_LIBRARIES ${GraphicsBackendLibraries} WindowSystem ${SDL2_LIBRARIES} ValueFileParser StringFunctions )

    # add a target to generate API documentation with Doxygen
    find_package ( Doxygen )
    if ( DOXYGEN_FOUND )
        configure_file ( ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY )
        add_custom_target ( doc
            ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
            WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
            COMMENT "Generating API documentation with Doxygen" VERBATIM
            )
    endif ()

    target_link_libraries ( Illusion ${ILLUSION_LIBRARIES} )

    # Just to check if i have a parent
    get_directory_property ( hasParent PARENT_DIRECTORY )
    if ( hasParent )
        message ( STATUS "Passing Illusion variables to parent project" )
        set ( ILLUSION_INCLUDE_DIRS ${ILLUSION_INCLUDE_DIRS} PARENT_SCOPE )
        set ( ILLUSION_LIBRARIES Illusion ${ILLUSION_LIBRARIES} PARENT_SCOPE )
        set ( ILLUSION_LINK_DIRS ${ILLUSION_LINK_DIRS} PARENT_SCOPE )
        set ( ILLUSION_DEFINITIONS ${ILLUSION_DEFINITIONS} PARENT_SCOPE )
    endif()

    option ( ILLUSION_BUILD_TESTS "Builds tests" TRUE )
    if ( ILLUSION_BUILD_TESTS )
        message ( STATUS "Building tests" )
        file ( GLOB Test_Sources "Tests/*.cpp" "Tests/*.h" )
        add_executable ( Test ${Test_Sources} )
        target_link_libraries ( Test Illusion )

        add_executable ( WindowSystemTest WindowSystem/WindowSystemTest.cpp )
        target_link_libraries ( WindowSystemTest WindowSystem ${SDL2_LIBRARY} )

        add_custom_command ( TARGET Test POST_BUILD
            COMMAND ${CMAKE_COMMAND} -E copy_directory "${THIRD_PARTY_OUTPUT_PATH}/lib" ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} )
    endif()
#    include ( "Package.cmake" )
endif()

This works of for building. The first time I run cmake, it builds all the dependencies, but not the main project. The second time I run it, it correctly finds the libraries, and builds the main project. If I look into the output folder and inside lib, all the third party libraries are correctly copied inside there. All is well on that part. The main problem comes with linking. When I try to run the test application, I get this...

dyld: Library not loaded: libSDL2-2.0.1.dylib
  Referenced from: /Users/joao.pincho/Programming/build-Illusion_deps-Desktop_Qt_5_7_0_clang_64bit-Default/DARWIN/bin/./Test
  Reason: image not found
Trace/BPT trap: 5

Of course, this works if I specify DYLD_LIBRARY_PATH pointing to THIRD_PARTY_OUTPUT_PATH/lib, but that prevents me from running this on the IDE, and will also not work under Windows... I intend to make this build process work under Linux, OSX, Windows, Android and IOS, so I have that restriction to think ahead of. So, since in Windows I need to have the DLL's and libs all together, I might as well copy everything into the same directory. As a small test, I copied the test executable into the libs folder, where everything is put. This is what I get:

dyld: Library not loaded: /Users/joao.pincho/Programming/Illusion_deps/ThirdParty/Darwin//libassimp.3.dylib
  Referenced from: /Users/joao.pincho/Programming/build-Illusion_deps-Desktop_Qt_5_7_0_clang_64bit-Default/DARWIN/lib/./Test
  Reason: image not found
Trace/BPT trap: 5

And this is the part I honestly do not understand. Why is it looking for libassimp in the wrong folder? (EDIT) The correct path where the file was copied from is /Users/joao.pincho/Programming/Illusion_deps/ThirdParty/Darwin/lib/libassimp.3.dylib

What can I do to just make this work? Why is it looking for the libs in the wrong place? Why did it stop complaining about libSDL2 when I moved the executable, but not about libassimp?

Joao Pincho
  • 939
  • 2
  • 11
  • 26
  • How looks the line add_executable? What is the value of SDL2? See for output: http://stackoverflow.com/a/24885278/1733955 – Th. Thielemann Nov 08 '16 at 20:05
  • `The correct path where the file was copied from is ...` - exactly that path is printed in error message. What is wrong here? As for DYLD_LIBRARY_PATH and cross-platform, CMake has common notion about [RPATH](https://cmake.org/Wiki/CMake_RPATH_handling), so all platforms except Windows can be unified. On Windows you need to install dlls into the same directory as executable, but it is not a CMake problem - all Windows packages need to follow that. – Tsyvarev Nov 08 '16 at 20:22
  • @Tsyvarev. Sorry, my mistake, that was a typo. I copied the path from the error message, and never corrected it. – Joao Pincho Nov 09 '16 at 08:49

0 Answers0