Building of executable and shared library with cmake, runtimelinker does not find dll

前端 未结 4 1314
梦毁少年i
梦毁少年i 2021-01-04 05:14

I am working with gcc(cygwin), gnu make, windows 7 and cmake.

my cmake testprojekt has the following structure

rootdir
|-- App
|   |-- app.cpp
|   +-         


        
相关标签:
4条回答
  • 2021-01-04 05:28

    I discovered (what I believe to be) quite a nice way of handling this. It follows the approach of adding the .dll to the same directory as the .exe. You can do it in CMake like so:

    if (WIN32)
    # copy the .dll file to the same folder as the executable
    add_custom_command(
        TARGET <app-target> POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy_directory
        $<TARGET_FILE_DIR:<lib-target>>
        $<TARGET_FILE_DIR:<app-target>)
    endif()
    

    where app-target is the name of the application or library you're building (created through add_executable or add_library) and lib-target is the imported library brought in with find_package.

    # full example
    cmake_minimum_required(VERSION 3.14)
    
    project(my-app-project VERSION 0.0.1 LANGUAGES CXX)
    
    find_package(useful-library REQUIRED)
    
    add_executable(my-application main.cpp)
    
    target_link_libraries(my-application PUBLIC useful-library::useful-library)
    
    if (WIN32)
    # copy the .dll file to the same folder as the executable
    add_custom_command(
        TARGET my-application POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy_directory
        $<TARGET_FILE_DIR:useful-library::useful-library>
        $<TARGET_FILE_DIR:my-application>)
    endif()
    
    0 讨论(0)
  • 2021-01-04 05:41

    Your problem lies not with linker or compiler, but with the way Windows searches for DLL's.

    The OS will use the following algorithm to locate the required DLL's:

    Look in:

    1. The directories listed in the Application-specific Path registry key;
    2. The directory where the executable module for the current process is located;
    3. The current directory;
    4. The Windows system directory;
    5. The Windows directory;
    6. The directories listed in the PATH environment variable;

    Thus you have two reasonable options if you don't want to clutter the OS directories with your app-specific dll:

    1. Create an app-specific Path registry entry (I would go with this option);
    2. Put your DLL in the same folder as your EXE;
    3. Modify the PATH variable (but why would you do that, if you can go with option 1?);
    0 讨论(0)
  • 2021-01-04 05:41

    I tried the option 1 from accepted answer (by pdeschain). I even created a cmake hook to register paths of linked libraries automatically

    function (xtarget_link_libraries target libs) # same as target_link_libraries but with additional improvements to allow windows find the library at runtime
    LIST(REMOVE_AT ARGV 0)
    SET(LIBS ${ARGV}) # this is to pass list into this function
    target_link_libraries(${target} ${LIBS}) # call standard routine
    
    if(WIN32)
        set(TFILE ".")
        get_property(slibs TARGET ${target} PROPERTY all_libs) # recall libs linked before
        set(LIBS ${slibs};${LIBS})
        set_property(TARGET ${target} PROPERTY all_libs ${LIBS}) # save all libs
        FOREACH(lib ${LIBS}) # compose a list of paths
            set(TFILE "${TFILE};$<TARGET_LINKER_FILE_DIR:${lib}>")
        ENDFOREACH()
        #add reg key
        add_custom_command(TARGET ${target} POST_BUILD COMMAND  reg add "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\${target}.exe" /v "Path" /d "${TFILE}" /f )
    endif()
    endfunction()
    

    Can be used as xtarget_link_libraries(test lib1 lib2). The application will be able to find dynamic libraries at their absolute paths.

    BUT, there is a big problem with this, that the App Paths mechanism https://msdn.microsoft.com/en-us/library/windows/desktop/ee872121(v=vs.85).aspx#appPaths

    does not allow to have different entries for say 'Debug/test.exe' and 'Release/test.exe'. So to me this is a poor option.

    You may add the following line to fill the Default key as path to the program as suggested in the post.

    add_custom_command(TARGET ${target} POST_BUILD COMMAND reg add "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\${target}.exe" /ve /d "$<TARGET_FILE:${target}>" /f )

    Now you can enjoy running test.exe from anywhere in the system... I guess my next try will be option

    1. Create symbolic links to dlls with cmake.
    0 讨论(0)
  • 2021-01-04 05:43

    A solution I prefer that hasn't really been mentioned, is build your shared-libs into the same directory as your executables. This tends to be a much simpler solution.

    One way to do this with cmake is

    set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

    Or you can also set output directories based on build flavours.

    See how do I make cmake output into a 'bin' dir?

    0 讨论(0)
提交回复
热议问题