46

The title mostly covers it, what is the difference between a module and a shared library? I just found this distinction in CMake's add_library command, where they say:

SHARED libraries are linked dynamically and loaded at runtime. MODULE libraries are plugins that are not linked into other targets but may be loaded dynamically at runtime using dlopen-like functionality.

But I can load a shared object using dlopen(), can't I?

4 Answers 4

45

The difference is that you can link to a SHARED library with the linker, but you cannot link to a MODULE with the linker. On some platforms.

So... to be fully cross-platform and work everywhere CMake works, you should never do this:

# This is a big NO-NO: add_library(mylib MODULE ${srcs}) target_link_libraries(myexe mylib) 

To be fair, on Windows, they're both just dlls, and so this code might actually work. But when you take it to a platform where it's impossible to link to the MODULE, you'll encounter an error.

Bottom line: if you need to link to the library, use SHARED. If you are guaranteed that the library will only be loaded dynamically, then it's safe to use a MODULE. (And perhaps even preferable to help detect if somebody does try to link to it...)

Sign up to request clarification or add additional context in comments.

5 Comments

Does anyone know on which platforms this could be an issue?
> but you cannot link to a MODULE with the linker. On some platforms ... Even if they can be added as a library. Are you actually linking to it on Windows if it does not use any symbols?
The point is, if a library is a MODULE, then you should not try to link to it. You should LoadLibrary or dlopen it, and call into it dynamically. When I say later "so this code might actually work" I mean the CMake code invoking target_link_libraries. But it's a no-no with MODULE libraries, so even if it seems to "work" (more correctly, "NOT produce an error") then just don't do it.
It seems that we can always use shared library instead of module library. So why there is something called module library?
are the two target same on linux?
14

I think the distinction being made is that shared libraries are specified by the developer at compile-time and must be present for the application to run, even though their methods are loaded at runtime. A module, i.e. plugin, adds additional support at runtime but isn't required. Yes, you can dlopen() a shared library but in that case it would not have been specified as a required part of the program and functions instead as a module.

Comments

7

Another difference is in how ..._OUTPUT_DIRECTORY and ..._OUTPUT_NAME are handled:

Module libraries are always treated as library targets. For non-DLL platforms shared libraries are treated as library targets. For DLL platforms the DLL part of a shared library is treated as a runtime target and the corresponding import library is treated as an archive target. All Windows-based systems including Cygwin are DLL platforms.

For example, this means that if you compile a SHARED library on Windows, LIBRARY_OUTPUT_DIRECTORY will be ignored, because it's looking at ARCHIVE_OUTPUT_DIRECTORY and RUNTIME_OUTPUT_DIRECTORY instead.

Comments

3

Important specific of a MODULE library is that it may use symbols (functions and variables) which are not defined in the library (and not defined in the libraries it is linked with). Such feature is very useful when create plugins: a plugin may call functions which are defined in the application which loads that plugin.

A regular SHARED library is not allowed to use undefined symbols.

Also, it is not allowed to link with a library, which contains undefined symbols. For that reason CMake explicitly prohibits linking with a MODULE library. For the same reason CMake doesn't create for a MODULE library additional files, which are used primarily for linking: import files on Windows, so-versions and symlinks on Linux, etc.


For example, an application may allow plugins to create additional windows.

plugin.h:

// Creates a window. // // The function is defined by the application and can be used by plugins. void CreateWindow(const char* name); // Initialize the plugin. // // Called by the application. Should be defined by the plugin itself. void InstantiatePlugin(void); 

cool_plugin.c:

#include <plugin.h> void InstantiatePlugin(void) { // Just create two windows CreateWindow("Cool1"); CreateWindow("Cool2"); } 

Such plugin can be built with CMake by using a MODULE library:

# CMakeLists.txt # add_library(cool_plugin MODULE cool_plugin.c) target_include_directories(cool_plugin PRIVATE </path/to/directory/with/plugin.h>) 

Would one replace MODULE with SHARED in the above code, building the plugin will fail with undefined reference/unresolved external error.

Code of the application itself could look as following:

// application.c #include <plugin.h> int CreateWindow(const char* name) { // ... actually create a window. } int main(void) { // .. Some initialization // ... Load the plugin in the platform-specific way (dlopen or LoadLibrary) void (*instantiate)(void) = ... ; // find function 'InstantiatePlugin' in the plugin instantiate(); } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.