CMake and Libraries, part 1.5, Windows

on , , , , , , 2 minutes reading

Last time we built a CMake multidirectory C project and generated an executable as well as a static and a dynamic library. If you were running the code in macOS or Linux (or well, any Unix), you will see the .dylib file with the dynamic library (.so in Linux/FeeBSD) and .a file with the static library. If you try to run CMake in a Windows machine with the Visual C++ compiler chain installed you will see instead an error message telling you something like this:

LINK : fatal error LNK1104: cannot open file ‘….\output\Debug\greeter.lib’ [C:\src\cmake_lib\build\hello_app\hello_app.vcxproj]

This is because in Windows a LIB file can be a static library and/or an import library which contains stubs to tell to the linker how to link to the generated dynamic library. CMake gets confused and has no idea what file to use or generate for the static library, so we have to help it out and tell it the same lib needs to be generated for both files.

Let’s modify our CMakeLists.txt file for the library (inside the libgreeter directory) to add a conditional compilation statement. Notice the extra lines telling it to generate a .lib file with the same name for the greeter library:

cmake_minimum_required (VERSION 3.6)
project (libgreeter VERSION 1.0)

include_directories (${CMAKE_CURRENT_SOURCE_DIR}/includes)

set (GREETER_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
set (GREETER_SOURCE ${GREETER_SOURCE_DIR}/greeter.c)

add_library (greeter SHARED ${GREETER_SOURCE})
add_library (greeter_static STATIC ${GREETER_SOURCE})

if (WIN32)
set_target_properties (greeter_static PROPERTIES OUTPUT_NAME Greeter CLEAN_DIRECTORY_OUTPUT 1)
set_target_properties (greeter PROPERTIES OUTPUT_NAME Greeter CLEAN_DIRECTORY_OUTPUT 1)
endif()

target_include_directories (greeter PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/includes)

Done, now if we try to compile this on Windows it will work as expected! NICE!