How to use dynamic link library with CMake?
Your modelling of the dynamic library is incorrect, both on CMake and on the source level.
As a starting point, try building the dll as part of the same CMake project as the consuming executable:
cmake_minimum_required(VERSION 3.5)
project(test LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
include(GenerateExportHeader)
add_library(power SHARED power_sources.cpp power.h)
generate_export_header(power)
target_include_directories(power PUBLIC ${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR})
add_executable(test main.cpp)
target_link_libraries(test PRIVATE power)
Note the use of the generate_export_header
function, which instructs CMake to generate macros for exporting functions on shared library interfaces in a portable way. Since generated files go to the binary directory tree, we have to adjust the include directories for the library accordingly.
To make sure the function gets properly exported, change your header as follows:
#ifndef POWER_H
#define POWER_H
#include <power_export.h>
POWER_EXPORT double power(double number) noexcept;
#endif // POWER_H
Note that generare_export_header
allows you to customize the generated export header extensively.
Be sure you get the project to build and run from this baseline.
If you want to build the dll externally (which is not strictly necessary, but since that's what your question is about...), we have to modify the CMake file to something like:
cmake_minimum_required(VERSION 3.5)
project(test LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(power)
add_executable(test main.cpp)
target_link_libraries(test PRIVATE power)
With all the magic here happening in the find_package
call. That call is now responsible for providing all the information that was previously handled by the lines for building the library:
- Providing of an imported target
power
for consumption by thetarget_link_libraries
call - Association of the library name of the import library (the
power.lib
file) via that imported target - Exposure of the public include directories for both
power.h
andpower_export.h
via that imported target
You can either construct such an imported target manually in the find script, or have CMake do it for you. In the first case, create a FindPower.cmake
script file, make sure it's location is part of the CMAKE_MODULE_PATH
and write the code for finding the library and header files and constructing the imported target in there. Note that getting this right in a portable way can be very tricky and goes far beyond the scope of a StackOverflow question. In the second case, have the CMake script that builds the power
library perform an install step during which a config file package will get generated, which can then be consumed by your test
project. Note that this approach is not viable if the power
library is not itself being built with CMake, so in that case you will have to stick with the first option.