Введение
CMake (от англ. cross platform make) — это кроссплатформенная система автоматизации сборки программного обеспечения из исходного кода.
CMake не занимается непосредственно сборкой, a лишь генерирует файлы управления сборкой из файлов CMakeLists.txt.
Динамические библиотеки. Теория
Создание динамических библиотек со статической линковкой в ОС Windows отличается от ОС Linux.
На ОС Windows для этого требуется связка .dll (dynamic link library) + .lib (library) файлов.
На ОС Linux для этого нужен всего лишь один .so (shared object) файл.
Динамические библиотеки. Практика
На практике хочется писать удобный, одинаковый код на обеих ОС.
В каждом проекте (или на несколько проектов одна) присутствовала условная компиляция:
#ifndef __linux__
#if defined( <target_name>_EXPORTS )
#define DLL_<target_name>_EXPORT __declspec(dllexport)
#else // !BUILDING_DLL
#define DLL_<target_name>_EXPORT __declspec(dllimport)
#endif // BUILDING_DLL
#else
#define DLL_<target_name>_EXPORT
#endif // __linux__
Соответственно, для каждого экспортируемого класса из библиотеки необходимо прописать данный макрос:
class DLL_<target_name>_EXPORT <class_name>
В данном случае, на ОС Windows экспортируются все классы/методы, которые помечены данным макросом, а на ОС Linux, по умолчанию, всё экспортируется, т.к. нет макроса для скрытия классов/методов.
С выходом CMake версии 3.4.0, стало возможным создание библиотек с классами, которые экспортируются по умолчанию. Для этого в каждой цели (target), которые объявлены как SHARED (динамическая библиотека), необходимо включить свойство:
set ( CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
Пример небольшой библиотеки:
# Проверка версии CMake
cmake_minimum_required( VERSION 3.4.0 )
# Если версия установленой программы ниже, то ошибка выполнения
# Название проекта и проверка доступности компиляторя с++
project( shared_lib CXX )
# Установка переменной со списком исходников
set( SOURCE_LIB example.cpp )
# Включение экспорта всех символов для создания динамической библиотеки
set ( CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON )
# Создание динамической библиотеки с именем example
add_library( example SHARED ${SOURCE_LIB} )
И убрать определение и использование макросов из кода:
DLL_<target_name>_EXPORT
Данное свойство автоматически создает module definition (.def) со всеми глобальными символами из .obj файла для динамической библиотеки на ОС Windows.
Далее данный файл (.def) передается компоновщику для создания .lib файла. На выходе на ОС Windows получается связка .lib + .dll
Итоги
Код стал более читабельным, нет лишних строчек. И вероятность появления ошибки во время неправильного написания блока условной компиляции и определения макроса среди разработчиков сведена к нулю. В CMakeLists файле всего одна дополнительная строчка.
Автор: 19as