Пятница, 22.08.2025 19:00

Преобразуем проект C++ в библиотеку с помощью CMake. Библиотеки С++ и CMake. Часть 1

Преобразуем проект C++ в библиотеку с помощью CMake. Библиотеки С++ и CMake. Часть 1

Сегодня мы создадим библиотеку C++, а для для настройки проекта используем CMake

В прошлой статье  - мы создали класс ColorConsole. При написании консольных приложений для Windows он может быть очень полезен, но каждый раз копировать исходный код библиотеки в каждый новый проект не очень удобно. 

Создадим копию папки нашего проекта из прошлой статьи – https://blog.altuninvv.ru/яп/c/вывод-цветного-текста-в-консоль-на-с

cd c:\projects
xcopy colorconsole colorconsolelib\ /s /e /h

Удалим ненужные файлы и папки

cd colorconsolelib
del main.cpp
rmdir /S /Q build

Создадим новые файлы и папки:

mkdir cmake
type nul > cmake/colorconsole-config.cmake.in

Создадим папку для исходного кода и перенесем файлы:

mkdir src
move *.cpp src\
move *.h src\

Такой подход довольно удобен, так как позволяет отделить программный код от прочих файлов и предотвращает превращения корневой папки в мешанину из исходного кода, документации и файлов настроек CMake.

Откроем новую папку в vscode:

code .

Добавляем пространство имен

В C++ существует механизм пространства имен. Его использование позволяет избежать ситуации, когда, например, два программиста выбрали для своих классов или функций одинаковые имена. И когда их код попадает в проект, линковщик не может разобраться что и с чем связывать, и просто выдает ошибку.

При использовании пространства имён такой ситуации не случится, и даже если в проекте встретятся классы с одинаковыми именами, достаточно перед именем будет указать пространство имен!

В нашей библиотеке мы будем использовать пространство имен:

ccon

Это сокращение от:

C Console

Добавим в colorconsole.h перед:

    class ColorConsole

строки:

namespace ccon
{

И в самый конец файла, перед:

#endif

Добавим:

}

Добавим в colorconsole.cpp перед:

   ColorConsole::ColorConsole()

строки:

namespace ccon
{

И в самый конец файла:

}

Добавляем внешний заголовочный файл

Внешний заголовочный файл это еще одна из особенностей библиотек CMake. 

На самом деле их использование оправдано и полезно. При сборке проекта используется заголовочный файл находящийся в папке src. Для пользователей автор библиотеки может подготовить специальную версию, содержащую только необходимые для пользователей функции и классы и более подробную документацию.

Создадим папку для заголовочных файлов и скопируем заголовок:

mkdir include
copy src\*.h include\

CMakeFiles.txt для библиотеки C++

Для правильного создания библиотеки на с использованием Cmake необходимо,чтобы полученный проект соответствовал множеству условий. Это и структура папок и наличие в соответствующих папках файлов заголовков и файлов с настройками для CMake. 

Приведенный ниже файл содержит минимальный набор инструкций для создания библиотеки CMake отвечающей современным требованиям. В будущих статьях мы будем его модернизировать, когда будем рассматривать создание динамической библиотеки и преобразовывать нашу библиотеку в кроссплатформенную!

Создавая этот файл я старался сделать его максимально универсальным. Вы можете легко поменять имя библиотеки и пространство имён. При желании можно объединить три переменные в одну, так как в трех из них содержится одно и тоже имя, но я специально оставил место для маневра, если в будущем потребуется более точная настройка!

Заменим содержимое файла CMakeFiles.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)

# Задаем переменные для использования

# Задаем пространство имен
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}-static-targets.cmake")


### Основная часть

# Инициализируем проект как библиотеку
add_library(${PROJECT_NAME})
# Инициализируем пространство имен и алиас
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}")

Нажмем F1

Введем 

CMake

Выберем

CMake: Select a Kit

И выберем строку начинающуюся с:

GCC 15

Обратите внимание, мы создали пустой файл:

cmake/colorconsole-config.cmake.in

Данный файл в будущем будет содержать инструкции CMake для сборки статической и динамической версий библиотеки, но в данный момент он нам не нужен. Мы оставляем его как заглушку на будущее.

Запустим конфигурирование проекта, я буду использовать консоль, вы можете использовать панель CMake в VSCode:

В терминале запустим конфигурирование

cmake -S . -B build

Запустим сборку

cmake --build build
[ 50%] Building CXX object CMakeFiles/colorconsole.dir/src/colorconsole.cpp.obj
[100%] Linking CXX static library libcolorconsole.a
[100%] Built target colorconsole

Сборка успешна, будет создана папка build, а в ней файл с нашей библиотекой:

libcolorconsole.a

Установка библиотеки

Перед использованием библиотеку нужно установить.

Всего есть три способа установки:

1. Установка в отдельную папку

2. Установка в системную папку

3. Установка в папку проекта, который будет использовать библиотеку

Сегодня мы рассмотрим установку в папку проекта.

Подготовка проекта к установке библиотеки

Прежде чем продолжить, давайте очистим старый проект из статьи -  https://blog.altuninvv.ru/яп/c/вывод-цветного-текста-в-консоль-на-с от лишнего кода, папок и файлов.

Вернемся к нашему проекту в консоли cmd введем:

cd c:\projects\colorconsole

Удалим ненужные файлы:

del colorconsole.cpp colorconsole.h

Чтобы нам проще было возвращаться к чистому проекту создадим локальный репозиторий git.

В cmd запустим:

cd c:\projects\colorconsole
git init

Создадим файл:

type nul >  .gitignore

Добавим в него строки:

build/
.vscode/

Запустим в консоли cmd:

git add .
git commit -m "v1"
[master (root-commit) a070120] v1
 3 files changed, 85 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 CMakeLists.txt
 create mode 100644 main.cpp

Был создан первый коммит и наши изменения были зафиксированы в репозитории git, теперь при необходимости мы можем всегда вернуться к чистому проекту!

Добавляем библиотеку в наш проект

Самый простой способ подключить библиотеку к нашему проекту это добавить папку с библиотекой в папку нашего проекта. Этот способ лучше всего использовать при разработке самой библиотеки или если вам очень важно использовать фиксированную версию библиотеки по тем или иным причинам, например по причине обратной совместимости.

В следующих статьях мы рассмотрим обычный способ установки и использования библиотеки, при котором в отдельную папку устанавливаются заголовочные файлы, файл .a и файлы .cmake.

Создадим папку lib:

mkdir c:\projects\colorconsole\lib

Скопируем папку с библиотекой в эту папку:

xcopy c:\projects\colorconsolelib c:\projects\colorconsole\lib\colorconsolelib\ /s /e /h

Откроем проект вVSCode:

cd c:\projects\colorconsole
code .

Изменим содержимое CMakeFiles.txt:

cmake_minimum_required(VERSION 3.16)

project(colorconsoleapp VERSION 0.1 LANGUAGES CXX)

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)

add_subdirectory(lib/colorconsolelib)

Здесь мы просто включаем папку lib/colorconsolelib в наш проект и добавляем указания для CMake, что наш проект нужно собрать с библиотекой:

ccon::colorconsole

Так как в папке библиотеки уже есть специально сформированный для этих целей файл CMakeLists.txt то и со сборкой проблем не возникнет.

Прежде чем продолжить удалим из папки с библиотекой папку build:

del /F /Q c:\projects\colorconsole\lib\colorconsolelib\build

Она больше не понадобится, так как сборка всех необходимых компонентов будет происходить в папке build нашего проекта.

Запустим конфигурирование:

cmake -S . -B build
-- Building for: Ninja
-- The CXX compiler identification is GNU 15.1.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/msys64/mingw64/bin/c++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done (1.1s)
-- Generating done (0.0s)
-- Build files have been written to c:/projects/colorconsole/build

Запустим сборку:

cmake --build build

Получим много ошибок:

C:/projects/colorconsole/main.cpp: In function 'int main(int, char**)':
C:/projects/colorconsole/main.cpp:7:5: error: 'ColorConsole' has not been declared
   7 |     ColorConsole::init();
     |     ^~~~~~~~~~~~
C:/projects/colorconsole/main.cpp:8:5: error: 'ColorConsole' has not been declared
   8 |     ColorConsole::setConsStdOutColor(4);
     |     ^~~~~~~~~~~~
C:/projects/colorconsole/main.cpp:11:5: error: 'ColorConsole' has not been declared
  11 |     ColorConsole::setConsStdOutColor(ColorConsole::DARK_GREEN);
     |     ^~~~~~~~~~~~

Все от того, что мы забыли добавить пространство имен к имени класса. Мы можем поступить проще и объявить использование имени класса:

ccon::ColorConsole 

Из пространства имен ccon. 

Для этого в файл main.cpp перед:

int main(int argc, char *argv[])

Добавим:

using ccon::ColorConsole;

Запустим сборку:

cmake --build build
[build] [ 25%] Building CXX object lib/colorconsolelib/CMakeFiles/colorconsolelib.dir/src/colorconsole.cpp.obj
[build] [ 50%] Linking CXX static library libcolorconsole.a
[build] [ 50%] Built target colorconsolelib
[build] [ 75%] Building CXX object CMakeFiles/colorconsole.dir/main.cpp.obj
[build] [100%] Linking CXX executable colorconsole.exe
[build] [100%] Built target colorconsole
[driver] Build completed: 00:00:05.363
[build] Build finished with exit code 0

Обратите внимание, сборка нашей библиотеки произведена автоматически при сборке основного проекта. В папке сборки появилась папка:

build\lib\colorconsolelib\

С файлом нашей библиотеки:

libcolorconsole.a

Так же хочу обратить ваше внимание, что несмотря на том, что библиотека расположена в папке:

C:\projects\colorconsole\lib\colorconsolelib

А заголовочный файл colorconsole.h в папке:

C:\projects\colorconsole\lib\colorconsolelib\include

Нам не пришлось менять пути к заголовочному файлу:

#include "colorconsole.h"

Всё потому, что CMake и расширения для VSCode автоматически, на основании настроек в файлах CMakeLists.txt библиотеки и нашего проекта, нашли и подключили все нужные папки!

Запустим проект:

Изображение удалено.

Результат тот же. Но теперь у нас в программе используется библиотека.

Такой подход очень удобен для разработки самой библиотеки, так как у вас всегда есть доступ к любому файлу библиотеки, так как она является подпапкой основного проекта.

Откроем файл colorconsole.cpp

И внесем изменения в метод:

void ColorConsole::emptyLine()
{
    ColorConsole::setConsStdErrDefColor();
    std::cout << "{}" << std::endl;
}

Таким образом в конце строк мы будем добавлять {}

Запустим проект:

Изображение удалено.

Как видите, всё очень просто. Вы можете вносить изменения в саму библиотеку, а в проект добавлять код для тестирования самой библиотеки.

Заключение

Сегодня мы рассмотрели создание библиотеки C++ с использованием CMake:

Создали папку с копией проекта colorconsole;

Удалили ненужные папки и файлы;

Создали дополнительные файлы и папки и перенесли исходный код в папку src;

Добавили в исходный код пространство имен ccon;

Добавили папку с внешним заголовочным файлом;

Создали файл CMakeFiles.txt для нашей библиотеки;

Установили нашу библиотеку как папку в проект colorconsole удалив исходный код класса;

Собрали проект и внесли изменения для корректного использования библиотеки.

Категория C++
Теги Cpp CMAKE

Добавить комментарий

Простой текст

  • HTML-теги не обрабатываются и показываются как обычный текст
  • Строки и абзацы переносятся автоматически.
  • Адреса веб-страниц и email-адреса преобразовываются в ссылки автоматически.
Просмотров: 199