Search code examples
windowsdllcmakelib

Library's CMake generates DLL. Application's CMake wants LIB


My library has minimal, straightforward CMake code with the pertinent lines

add_library(MyLib <sources>)

install(
    TARGETS MyLib
    LIBRARY DESTINATION ${destination}/lib
    RUNTIME DESTINATION ${destination}/lib
    COMPONENT Libraries)
install(
    FILES mylib.h
    DESTINATION ${destination}/include
    COMPONENT Headers)

When executed under Windows, the system generates mylib.dll in ...\build\Release, and mylib.lib and mylib.exp (what's that?) in ...\build\lib\Release. It only installs mylib.dll.

My application has minimal, straightforward CMake code to search for my library:

find_path(MyLib_INCLUDE_DIR mylib.h)
find_library(MyLib_LIBRARIES NAMES MyLib)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(MyLib DEFAULT_MSG MyLib_LIBRARIES MyLib_INCLUDE_DIR)

Which works under Linux, but under Windows results in

-- Could NOT find MyLib (missing: MyLib_LIBRARIES)

From experimentation I know that this error occurs whenever there is only a .DLL file, and no associated .LIB import library.

Shall I correct MyLib to install mylib.lib? How?

Or is it possible to modify my application so that it is satisfied with mylib.dll only? How?

Research done so far

This is not about static vs dynamic linking (DLL and LIB files - what and why?, cmake link against dll/lib): I want dynamic linking; if a .LIB file is required, it has nothing to do with static linking.

This link cmake : shared library : how to get the .lib name instead of .dll name? may be pertinent, but is not explicit enough. Two other questions CMake generated VS project expecting lib instead of dll, Linking dll/lib to a cmake project seem related, but have no answer.


Solution

  • Command install classifies .lib file for a shared library as ARCHIVE. This is explicitly stated in the documentation:

    For DLL platforms (all Windows-based systems including Cygwin), the DLL import library is treated as an ARCHIVE target.

    So you need to add ARCHIVE clause to install() for install .lib file as well:

    install(
        TARGETS MyLib
        ARCHIVE DESTINATION ${destination}/lib
        LIBRARY DESTINATION ${destination}/lib
        RUNTIME DESTINATION ${destination}/bin
        COMPONENT Libraries)
    

    Not also, that RUNTIME DESTINATION is usually specified as bin, the same as destination for executables. This helps the executables on Windows to locate the shared libraries (.dll).