Сборка и установка разделяемой (shared) библиотеки С++ с помощью CMake. Библиотеки С++ и CMake. Часть 3
Разделяемые (shared) библиотеки широко применяются в рамках любой операционной системы будь то Linux или Windows. Их широкое использование позволяет серьезно экономить дисковое пространство и оперативную память, позволяя загружать только востребованный код и использовать одни и те же библиотеки во многих приложениях. Некоторые такие библиотеки и вовсе обязательно используются всеми приложениями, запускаемыми операционной системой.
В прошлой статье мы рассмотрели сборку и установку статической библиотеки C++ с помощью CMake. Сегодня мы пойдем дальше и рассмотрим сборку и установку разделяемой (shared) библиотеки C++ с помощью CMake как в отдельную папку, так и в системные папки Msys2.
Вносим изменения в проект для сборки библиотеки C++ как разделяемой (shared)
Откроем папку с библиотекой:
cd C:\projects\colorconsolelibТак как мы будем вносить серьёзные изменения в конфигурацию CMake обязательно удалим папку build:
rmdir /S/Q .\buildОбратите внимание! При внесении таких изменений удаление папки build обязательно и делать это надо до запуска VSCode!
Откроем VSCode:
code .Изменим файл CmakeLists.txt
cmake_minimum_required(VERSION 3.14)
# Имя оно же target проекта, его описание и язык
project(colorconsole
VERSION 0.1.0
DESCRIPTION "Библиотека для вывода цветного текста в консоль"
LANGUAGES CXX)
### Инициализация
# Требования к версии C++ и поддержки стандарта
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Загружаем данные о путях до папок в которые установлены библиотеки C++
include(GNUInstallDirs)
# Задаем переменные для использования
# Задаем версию для сборки static или shared
set("LIB_LINK_TYPE" "shared")
# Включаем сборку разделяемой (shared) библиотеки
option(BUILD_SHARED_LIBS "True when building a shared library" True)
# Задаем пространство имен
set("MAIN_NAMESPACE" "ccon")
set("PROJECT_NAMESPACE" "colorconsole")
# Префикс который используется для файлов конфигурации cmake
set("MY_CMAKE_PREFIX" "colorconsole")
# Имя файла для библиотеки к нему автоматически будет добавлено lib
set("MY_LIB_OUTPUT_NAME" "colorconsole")
# Задаем путь для установки CMake-файлов проекта
set("COLORCONSOLE_INSTALL_CMAKEDIR" "${CMAKE_INSTALL_LIBDIR}/cmake/${MY_CMAKE_PREFIX}" CACHE STRING
"Install path for colorconsole package-related CMake files"
)
# Имена файлов, содержащие исходный код библиотеки
set(sources
src/colorconsole.cpp
src/colorconsole.h
)
# Имя файла с настройками для статической сборки библиотеки
set(targets_file "${MY_CMAKE_PREFIX}-${LIB_LINK_TYPE}-targets.cmake")
### Основная часть
# Инициализируем проект как библиотеку
add_library(${PROJECT_NAME} SHARED)
# Инициализируем пространство имен и алиас
add_library(${MAIN_NAMESPACE}::${PROJECT_NAMESPACE} ALIAS ${PROJECT_NAME})
# Загружаем модули CMake
include(GenerateExportHeader)
include(CMakePackageConfigHelpers)
# Добавляем файлы с исходным кодом к нашему проекту
target_sources(${PROJECT_NAME} PRIVATE ${sources})
# Добавляем папку src к нашему проекту
target_include_directories(${PROJECT_NAME}
PRIVATE
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>"
)
# Если библиотека используется как папка, открываем доступ к заголовочным файлам
target_include_directories(${PROJECT_NAME}
PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
)
# Создаем файл конфигурации и указываем папку для его установки
configure_package_config_file(cmake/${MY_CMAKE_PREFIX}-config.cmake.in colorconsole-config.cmake
INSTALL_DESTINATION "${COLORCONSOLE_INSTALL_CMAKEDIR}"
)
# Создаем файл конфигурации с указанием версии нашей библиотеки и указываем папку для его установки
write_basic_package_version_file(${MY_CMAKE_PREFIX}-config-version.cmake
COMPATIBILITY SameMajorVersion
VERSION ${PACKAGE_VERSION}
)
# Создаем правила для установки проекта
install(TARGETS ${PROJECT_NAME}
EXPORT lib_export
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
)
# Указываем что нужно скопировать содержимое каталога ./include и что это заголовочные файлы
install(DIRECTORY include/
TYPE INCLUDE
)
# Создаем правила установки файла *-static-targets.cmake
install(EXPORT lib_export
FILE "${targets_file}"
DESTINATION "${COLORCONSOLE_INSTALL_CMAKEDIR}"
NAMESPACE "${MAIN_NAMESPACE}::"
)
# Создаем правила для установки файлов *-config.cmake и *-config-version.cmake
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/${MY_CMAKE_PREFIX}-config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/${MY_CMAKE_PREFIX}-config-version.cmake"
DESTINATION "${COLORCONSOLE_INSTALL_CMAKEDIR}"
)
# Имя файла библиотеки. К нему автоматически будет добавлено lib
set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "${MY_LIB_OUTPUT_NAME}")
Здесь мы добавили две настройки:
# Задаем версию для сборки static или shared
set("LIB_LINK_TYPE" "shared")и
# Принудительно включаем сборку разделяемой (shared) библиотеки
option(BUILD_SHARED_LIBS "True when building a shared library" True)Изменили строку, но это на будущее:
# Имя файла с настройками для статической сборки библиотеки
set(targets_file "${MY_CMAKE_PREFIX}-${LIB_LINK_TYPE}-targets.cmake")Пока что мы не будем вносить больше изменений в этот файл, но в следующих статьях напишем универсальный файл CMakeLists.tx, который позволит собирать и статические и разделяемые версии библиотек.
Самое главное здесь, мы указали что теперь наша библиотека разделяемая (shared):
# Инициализируем проект как библиотеку
add_library(${PROJECT_NAME} SHARED)Изменим файл cmake\colorconsole-config.cmake.in:
# CMake package config file for colorconsole library.
#
# The following target is imported:
#
# ccon:colorconsole
#
# Запускаем инициализацию
@PACKAGE_INIT@
#Устанавливаем тип библиотеки - статическая
set(type "shared")
# Указываем включить файл конфигурации созданный в основном файле CMakeLists.txt
include("${CMAKE_CURRENT_LIST_DIR}/colorconsole-${type}-targets.cmake")
# Проверяем что все требуемые компоненты найдены
check_required_components(colorconsole)
# Выводим строку при конфигурировании проекта использующего наше библиотеку
message("-- Found ${type} colorconsole (version ${${CMAKE_FIND_PACKAGE_NAME}_VERSION})")Здесь мы поменяли строку:
set(type "shared")Запустим конфигурирование:
cmake -S . -B buildЗапустим сборку:
cmake --build build[2/2] Linking CXX shared library libcolorconsole.dllНа этот раз у нас был собран файл динамической библиотеки Windows:
libcolorconsole.dllУстановка разделяемой (shared) библиотеки в папку
Установим библиотеку в папку:
cmake --install build --prefix=C:\projects\libcolorconsole-shared-- Install configuration: "Debug"
-- Installing: C:\projects\libcolorconsole-shared/lib/libcolorconsole.dll.a
-- Installing: C:\projects\libcolorconsole-shared/bin/libcolorconsole.dll
-- Installing: C:\projects\libcolorconsole-shared/include
-- Installing: C:\projects\libcolorconsole-shared/include/colorconsole.h
-- Installing: C:\projects\libcolorconsole-shared/lib/cmake/colorconsole/colorconsole-shared-targets.cmake
-- Installing: C:\projects\libcolorconsole-shared/lib/cmake/colorconsole/colorconsole-shared-targets-debug.cmake
-- Installing: C:\projects\libcolorconsole-shared/lib/cmake/colorconsole/colorconsole-config.cmake
-- Installing: C:\projects\libcolorconsole-shared/lib/cmake/colorconsole/colorconsole-config-version.cmakeОбратите внимание, мы указываем папку отдельную папку для статической версии библиотеки - libcolorconsole-shared это важно. На данном этапе наша библиотека заточена только под разделяемую версию библиотеки, универсальную версию конфигурации мы рассмотрим в будущих статьях.
Так же в папке помимо .dll есть файл .dll.a он тоже необходим для сборки программы, так как содержит необходимую информацию об экспортируемых .dll файлом символах. Но при запуске программы он нам не понадобится!
На этом сборка статической версии библиотеки закончена.
Настройка проекта CMake для использования разделяемой (shared) библиотеки
Перейдем в папку с проектом:
cd c:\projects\colorconsole Так как мы будем вносить серьезные изменения в конфигурацию сборки обязательно удалим папку build:
rmdir /S/Q .\buildОбратите внимание! Удаление папки build обязательно!
Откроем VSCode:
code .Изменим файл CMakeLists.txt:
cmake_minimum_required(VERSION 3.16)
project(colorconsoleapp VERSION 0.1 LANGUAGES CXX)
list(APPEND CMAKE_PREFIX_PATH "../libcolorconsole-shared/lib/cmake/colorconsole")
find_package(colorconsole CONFIG REQUIRED)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_executable(${PROJECT_NAME})
target_sources(${PROJECT_NAME}
PRIVATE
main.cpp
)
include(GNUInstallDirs)
target_link_libraries(${PROJECT_NAME} ccon::colorconsole)Здесь мы добавили строку:
list(APPEND CMAKE_PREFIX_PATH "../libcolorconsole-shared/lib/cmake/colorconsole")Она указывает путь по которому у нас установлена разделяемая библиотека.
Запустим конфигурирование:
cmake -S . -B buildЕсли вы получили такой вывод:
-- Found static colorconsole (version 0.1.0)
-- Configuring done (0.4s)
-- Generating done (0.2s)
-- Build files have been written to: C:/projects/colorconsole/buildЗначит вы забыли удалить папку build!
Поэтому нужно обязательно закрыть все окна VSCode и запустить:
cd c:\projects\colorconsole
rmdir /S/Q .\buildЕсли всё прошло успешно мы получим вывод:
-- Found shared colorconsole (version 0.1.0)
-- Configuring done (0.3s)
-- Generating done (0.1s)
-- Build files have been written to: C:/projects/colorconsole/buildСтрока:
-- Found shared colorconsole (version 0.1.0)Уже на этом этапе подскажет нам, что мы собираем наш проект с разделяемой библиотекой!
Запустим сборку
cmake --build build[2/2] Linking CXX executable colorconsoleapp.exeПопробуем запустить:
.\build\colorconsoleapp.exeИ, ничего не произошло. Почему?
При запуске из консоли cmd мы можем получить ошибку:
Запустим:
ldd .\build\colorconsoleapp.exe ntdll.dll => /c/Windows/SYSTEM32/ntdll.dll (0x7ff81b290000)
KERNEL32.DLL => /c/Windows/System32/KERNEL32.DLL (0x7ff81a0e0000)
KERNELBASE.dll => /c/Windows/System32/KERNELBASE.dll (0x7ff818b50000)
msvcrt.dll => /c/Windows/System32/msvcrt.dll (0x7ff819600000)
libstdc++-6.dll => /mingw64/bin/libstdc++-6.dll (0x7ff800e90000)
libgcc_s_seh-1.dll => /mingw64/bin/libgcc_s_seh-1.dll (0x7ff808f20000)
libwinpthread-1.dll => /mingw64/bin/libwinpthread-1.dll (0x7ff8138a0000)
libcolorconsole.dll => not foundОбратите внимание на строку:
libcolorconsole.dll => not foundМы собрали проект с разделяемой библиотекой, но у нас папках в переменной PATH, а так же в папке с самим файлом
colorconsoleapp.exeнет файла с библиотекой:
libcolorconsole.dllДавайте скопируем его:
cd c:\projects\colorconsole
copy ..\libcolorconsole-shared\bin\*.dll .\build..\libcolorconsole-shared\bin\libcolorconsole.dll
Скопировано файлов: 1.Запустим:
.\build\colorconsoleapp.exeНа этот раз программа отработала как ожидалось.
Еще раз запустим:
ldd .\build\colorconsoleapp.exe ntdll.dll => /c/Windows/SYSTEM32/ntdll.dll (0x7ff81b290000)
KERNEL32.DLL => /c/Windows/System32/KERNEL32.DLL (0x7ff81a0e0000)
KERNELBASE.dll => /c/Windows/System32/KERNELBASE.dll (0x7ff818b50000)
msvcrt.dll => /c/Windows/System32/msvcrt.dll (0x7ff819600000)
libcolorconsole.dll => /c/projects/colorconsole/build/libcolorconsole.dll (0x7ff813b30000)
libstdc++-6.dll => /mingw64/bin/libstdc++-6.dll (0x7ff800e90000)
libwinpthread-1.dll => /mingw64/bin/libwinpthread-1.dll (0x7ff8138a0000)
libgcc_s_seh-1.dll => /mingw64/bin/libgcc_s_seh-1.dll (0x7ff808f20000)На этот раз строка
libcolorconsole.dll => /c/projects/colorconsole/build/libcolorconsole.dll (0x7ff813b30000)Указывает на полный путь к файлу
libcolorconsole.dllУстановка разделяемой (shared) библиотеки в системные папки Msys2
На всякий случай удалим всё установленные файлы библиотеки:
del C:\msys64\mingw64\lib\libcolorconsole.a
del C:\msys64\mingw64\include\colorconsole.h
rmdir /S/Q C:\msys64\mingw64\lib\cmake\colorconsoleУстановим библиотеку в папку Msys2:
cd C:\projects\colorconsolelib
cmake --install build --prefix=C:\msys64\mingw64-- Install configuration: "Debug"
-- Installing: C:\msys64\mingw64/lib/libcolorconsole.dll.a
-- Installing: C:\msys64\mingw64/bin/libcolorconsole.dll
-- Up-to-date: C:\msys64\mingw64/include
-- Installing: C:\msys64\mingw64/include/colorconsole.h
-- Installing: C:\msys64\mingw64/lib/cmake/colorconsole/colorconsole-shared-targets.cmake
-- Installing: C:\msys64\mingw64/lib/cmake/colorconsole/colorconsole-shared-targets-debug.cmake
-- Installing: C:\msys64\mingw64/lib/cmake/colorconsole/colorconsole-config.cmake
-- Installing: C:\msys64\mingw64/lib/cmake/colorconsole/colorconsole-config-version.cmakeНастройка проекта CMake для использования разделяемой (shared) библиотеки установленной в папку Msys2
Обязательно удалим папку build:
cd C:\projects\colorconsole
rmdir /S/Q .\build
code .Изменим файл CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(colorconsoleapp VERSION 0.1 LANGUAGES CXX)
find_package(colorconsole CONFIG REQUIRED)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_executable(${PROJECT_NAME})
target_sources(${PROJECT_NAME}
PRIVATE
main.cpp
)
include(GNUInstallDirs)
target_link_libraries(${PROJECT_NAME} ccon::colorconsole)Здесь мы удалили строку:
list(APPEND CMAKE_PREFIX_PATH "../libcolorconsole-shared/lib/cmake/colorconsole")Так как библиотека у нас теперь установлена в системные папки Msys2 и компилятор с линковщиком с помощью CMake сами смогут её найти.
Запустим конфигурирование:
cmake -S . -B build-- Found shared colorconsole (version 0.1.0)
-- Configuring done (0.3s)
-- Generating done (0.1s)
-- Build files have been written to: C:/projects/colorconsole/buildЗапустим сборку:
cmake --build build[2/2] Linking CXX executable colorconsoleapp.exeЗапустим:
.\build\colorconsoleapp.exeПрограмма отработала без проблем.
Проверим какие библиотеки используются:
ldd .\build\colorconsoleapp.exe ntdll.dll => /c/Windows/SYSTEM32/ntdll.dll (0x7ff81b290000)
KERNEL32.DLL => /c/Windows/System32/KERNEL32.DLL (0x7ff81a0e0000)
KERNELBASE.dll => /c/Windows/System32/KERNELBASE.dll (0x7ff818b50000)
msvcrt.dll => /c/Windows/System32/msvcrt.dll (0x7ff819600000)
libstdc++-6.dll => /mingw64/bin/libstdc++-6.dll (0x7ffff31f0000)
libcolorconsole.dll => /mingw64/bin/libcolorconsole.dll (0x7ff805b40000)
libwinpthread-1.dll => /mingw64/bin/libwinpthread-1.dll (0x7ff805b20000)
libgcc_s_seh-1.dll => /mingw64/bin/libgcc_s_seh-1.dll (0x7ff8059a0000)Теперь мы используем разделяемую (shared) библиотеку из системной папки Msys2:
libcolorconsole.dll => /mingw64/bin/libcolorconsole.dll (0x7ff805b40000)Заключение
Сегодня мы рассмотрели сборку и установку разделяемой (shared) библиотеки с помощью CMake:
Удалили папку build в папке с библиотекой;
Внесли изменения в файл CMakeLIsts.txt;
Добавили содержимое для файла make\colorconsole-config.cmake.in;
Установили разделяемую библиотеку в отдельную папку;
Настроили наш проект на использование разделяемой библиотеки;
Удалили папку build в папке с проектом;
Собрали проект и рассмотрели причины неработоспособности, в случае недоступности файла с разделяемой библиотекой;
Установили библиотеку в системные папки Msys2;
Настроили наш проект на использование разделяемой библиотеки в системной папке Msys2;
Собрали проект и проверили работоспособность.
В следующей статье мы рассмотрим создание универсального файла CMakeLIsts.txt, который будет обеспечивать сборку и установку и статической и разделяемой библиотек.
Добавить комментарий