CMake link shared library on Windows
Asked Answered
B

4

25

There are three files, (m.c,m.h, and **main.c*).

File m.h

// m.h
int m();

File m.c

// m.c
#include <stdio.h>
#include "m.h"

int m(){
    printf("Hello,m!\n");
    return 0;
}

File main.c

// main.c
#include "m.h"
int main(){
    return m();
}

While I prefer a shared library (m.dll), I've made the CMakeLists.txt file:

    PROJECT("app1")
    ADD_LIBRARY(m SHARED m.c)
    ADD_EXECUTABLE(myexe main.c)
    TARGET_LINK_LIBRARIES(myexe m)

The CMake configuration is done and generated done. Opening app1.sln and building with Visual Studio, it crashes as

LNK1104:Can't open file "Debug\m.lib"

It only works as STATIC at ADD_LIBRARY(). Why doesn't it work on Windows?

If I got another shared library (mylib.dll), how could I invoke its functions in my main.c and CMakeLists.txt files?

Bordelaise answered 11/10, 2015 at 7:50 Comment(3)
It always crashes - what is crashed? CMake configuration step(cmake.exe call), build step (BTW, what tool do you use for build? Visual Studio? Make?) or running executable? What error message comes along with this crash?Waggish
The CMakeLists.txt works well on Ubuntu-14.04. libm.so generated.Bordelaise
@Bordelaise Welcome to StackOverflow. With just a view modifications to your code you can make it happen. See my answer below.Boson
B
32

There are differences between dynamic library linking on different platforms which also needs some additional code. The good news is, that CMake can help you with this. I found the following blog post by Gernot Klingler very useful:

In short you need some "export prefix" defined for whatever is declared in m.h. Otherwise the build process will not generate an "import library" for statically linking named m.lib (see also CMAKE_IMPORT_LIBRARY_SUFFIX).

Here is your code with the modifications needed:

m.h

#include "m_exports.h"

int M_EXPORTS m();

m.c

#include "m.h"
#include <stdio.h>

int m(){
    printf("Hello,m!\n");
    return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.0)

include(GenerateExportHeader)

PROJECT("app1")

INCLUDE_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}")
ADD_LIBRARY(m SHARED m.c m.h m_exports.h)
GENERATE_EXPORT_HEADER(m           
    BASE_NAME m
    EXPORT_MACRO_NAME M_EXPORTS
    EXPORT_FILE_NAME m_exports.h
    STATIC_DEFINE SHARED_EXPORTS_BUILT_AS_STATIC)

ADD_EXECUTABLE(myexe main.c)
TARGET_LINK_LIBRARIES(myexe m)

Additional References

Boson answered 23/10, 2015 at 7:31 Comment(2)
CMAKE_IMPORT_LIBRARY_SUFFIX helped. Thanks.Toscana
@Boson Does this mean I have to create multiple xxx_exports.h for every library if I have multiple shared libraries. Besides, what about static library with cmake on windows?Pulverable
D
23

Using WINDOWS_EXPORT_ALL_SYMBOLS might help. See an introductory article for details. In short, invoke CMake like this:

cmake -DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS=TRUE -DBUILD_SHARED_LIBS=TRUE
Dragone answered 12/1, 2017 at 16:47 Comment(0)
K
8

Add this in CMakeLists.txt.

if(MSVC)
    set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
    set(BUILD_SHARED_LIBS TRUE)
endif()
Konstanze answered 3/12, 2020 at 15:1 Comment(0)
C
0

Let me give my two cents for the FLYPoPo's answer in case of Windows platform, not VC only. Same CMakeLists.txt:

if (WIN32)
    set (CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
    set (BUILD_SHARED_LIBS TRUE)
endif ()

This works fine for me.

Cicely answered 31/10, 2023 at 12:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.