diff --git a/wiki/Prog/Development/CMake управление проектом.adoc b/wiki/Prog/Development/CMake управление проектом.adoc deleted file mode 100644 index e727170..0000000 --- a/wiki/Prog/Development/CMake управление проектом.adoc +++ /dev/null @@ -1,960 +0,0 @@ -= CMake: управление проектом -:title-separator: {sp}| -:category: Программирование -:tags: программирование, cmake, -:toc: - -== Полезные ссылки - -* https://github.com/onqtam/awesome-cmake[Каталог ссылок] -* https://cgold.readthedocs.io/en/latest/index.html[CGold: The Hitchhiker’s Guide to the CMake] - -== Структура каталогов проекта - -Файлы проекта и результаты компиляции размещаются в каталогах: - -.... -└── project - ├── _build - │ ├── debug - │ │ ├── bin - │ │ ├── etc - │ │ ├── files - │ │ │ ├── data - │ │ │ ├── lib - │ │ │ └── log - │ │ ├── include - │ │ └── lib - │ └── release - ├── .git - ├── .gitlab-ci - ├── cmake - │ ├── cmlib - │ ├── doc - │ ├── etc - │ │ └── uncrustify - │ ├── find - │ └── generators - ├── doc - ├── files - │ ├── data - │ ├── etc - │ ├── lib - │ └── log - ├── l10n - ├── src - │ ├── app - │ └── lib - ├── thirdparty - └── tools -.... - -Назначение каталогов приведено в таблице. - -[cols="2,4",options="header",] -|=== -|Каталог | Назначение -|`_build` | Результаты компиляции -|`_build/debug` | Результаты компиляции в режиме отладки -|`_build/debug/bin` | Исполняемые файлы -|`_build/debug/etc` | Символическая ссылка на каталог `cmex/files/etc` -|`_build/debug/files/data` | Символическая ссылка на каталог `cmex/files/data` -|`_build/debug/files/lib` | Символическая ссылка на каталог `cmex/files/lib` -|`_build/debug/files/log` | Символическая ссылка на каталог `cmex/files/log` -|`_build/debug/include` | Заголовочные файлы копируемые и генерируемые во время сборки -|`_build/debug/lib` | Статические и динамические библиотеки -|`_build/release` | Результаты компиляции в режиме выпуска (иерархия аналогична `debug`) -|`.git` | Системные файлы репозитория git -|`.gitlab.ci` | Шаблон правил для автоматической сборки на сервере Gitlab -|`cmake` | Файлы с дополнительными функциями для CMake -|`cmake/cmlib` | Библиотека функций для CMake -|`cmake/doc` | Правила для автоматической генерации документации -|`cmake/etc` | Файлы настроек, используемые в CMake -|`cmake/etc/uncrustify` | Файл настройки для программы автоматического форматирования исходных текстов -|`cmake/find` | Модули CMake для поиска внешних программ и библиотек -|`cmake/generators` | Генераторы проектов -|`doc` | Документация для проекта -|`files` | Каталог для дополнительных файлов -|`files/etc` | Каталог для файлов настроек проекта -|`files/data` | Каталог для неизменяемых файлов -|`files/lib` | Каталог для изменяемых файлов -|`files/log` | Каталог для журналов -|`l10n` | Файлы переводов -|`src` | Исходные тексты -|`src/app` | Исходные тексты программы -|`src/lib` | Исходные тексты библиотеки -|`thirdparty` | Исходные тексты дополнительных и сторонних проектов -|`tools` | Дополнительные утилиты -|=== - -Каталог `_build` создаётся, чтобы избежать попадания создаваемых во время -сборки файлов в иерархию основного проекта. Запись результатов сборки -проекта внутрь иерархии каталогов с исходными текстами приводит к -засорению формируемыми на этапе сборки файлами, которые затрудняют -разработку, поиск в оригинальных файлах и мешают ориентироваться в -проекте. При работе с несколькими типами сборки, например, отладка и -выпуск, появляется необходимость корректного полного удаления -результатов предыдущего тип сборки. - - -[[base-project]] -== Базовый проект - -Проект, в котором выполнены приведённые в данном разделе действия, -можно посмотреть https://git.246060.ru/f1x1t/cmlib-example-base[здесь] -или сделать его копию командой: - -[source,sh] ----- -git clone --recursive https://git.246060.ru/f1x1t/cmlib-example-base ----- - -=== Инициализация подмодулей - -Для начала нужно создать каталог для проекта, перейти в него и -инициализировать репозиторий git: - -[source,sh] ----- -mkdir cmlib-example-base -cd cmlib-example-base -git init ----- - -Для подключения основных подмодулей, содержащих дополнительные функции -для работы с проектом, и фиксации произведённого изменения нужно выполнить: - -[source,sh] ----- -git submodule add https://git.246060.ru/f1x1t/cmlib.git cmake/cmlib -git submodule add https://git.246060.ru/f1x1t/cmake-find.git cmake/find -git submodule add https://git.246060.ru/f1x1t/cmake-generators.git cmake/generators -git submodule add https://git.246060.ru/f1x1t/cmake-doc.git cmake/doc -git submodule add https://git.246060.ru/f1x1t/uncrustify-config.git cmake/etc/uncrustify -git commit -a -m "Начало проекта" ----- - -Отправить изменения в проекте на сервер и сделать ветку `master` основной -(можно пропустить): - -[source,sh] ----- -git remote add origin АДРЕС_РЕПОЗИТОРИЯ_НА_СЕРВЕРЕ -git push -u origin master ----- - -Загрузить шаблоны для автоматической сборки проекта в разных вариантах -программных окружений и зафиксировать изменения: - -[source,sh] ----- -mkdir .gitlab-ci -wget -O .gitlab-ci/scheduled.yml https://git.246060.ru/f1x1t/gitlab-ci/raw/branch/master/.gitlab-ci/scheduled.yml -wget -O .gitlab-ci.yml https://git.246060.ru/f1x1t/gitlab-ci/raw/branch/master/.gitlab-ci.yml -git add .gitlab-ci.yml .gitlab-ci/scheduled.yml -git commit -m "Настройка автосборки" ----- - -Загрузить файл настройки для анализатора Clang-Tidy: - -[source,sh] ----- -wget https://git.246060.ru/f1x1t/clang-tidy-config/raw/branch/master/.clang-tidy -git add .clang-tidy -git commit -m "Настройка Clang-Tidy" ----- - -Создать стандартные файлы и каталоги: - -[source,sh] ----- -mkdir -p doc/breathe -touch doc/breathe/index.md.in -mkdir -p files/etc -touch files/etc/.keep-directory -mkdir -p files/data -touch files/data/.keep-directory -mkdir -p files/lib -touch files/lib/.keep-directory -mkdir -p files/log -touch files/log/.keep-directory -git add doc files -git commit -m "Стандартные файлы и каталоги" ----- - -Создать файл `.gitignore` для исключения каталогов и файлов из-под контроля git: - -[source,sh] ----- -wget https://git.246060.ru/f1x1t/cmlib-gitignore/raw/branch/master/.gitignore -git add .gitignore -git commit -m "Шаблон для игнорирования каталогов и файлов" ----- - - -=== Базовые инструкции в CMake - -В корневом каталоге проекта нужно создать файл `CMakeLists.txt`: - -[source,cmake] ----- -# Минимальная версия CMake -cmake_minimum_required(VERSION 3.3) - -# Предпочтительно следовать стандартам принятым в указанном диапазоне версий -cmake_policy(VERSION 3.0.2..3.7) - -# Название и версия проекта и используемые языки программирования -project(cmlib-example-base VERSION 0.2.0 LANGUAGES C CXX) ----- - -Значение версии следует формировать согласно правилам -https://semver.org/lang/ru/[семантического версионирования]. - -Для подключения функций для CMake из библиотеки CMLib, нужно добавить -в файл `CMakeLists.txt` строки: - -[source,cmake] ----- -# В каталоге cmake/cmlib находятся файлы с библиотечными функциями -if(IS_DIRECTORY ${CMAKE_SOURCE_DIR}/cmake/cmlib) - list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_SOURCE_DIR}/cmake/cmlib) -else() - message(FATAL_ERROR "CMake library directory does not exist") -endif() -list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/find) - -include(CMLibCommon) ----- - -[[variables-cmake]] -В каталоге `cmake/etc` требуется создать файл `Variables.cmake`, -в котором должны быть определены переменные, используемые -библиотекой CMLib для архивирования исходных текстов, автоматического -создания пакетов, генерации документации: - -[source,cmake] ----- -set(ORGANIZATION_NAME "org") -set(AUTHOR_NAME "John Doe") - -set(DOXYGEN_PROJECT_TITLE "Пример проекта (начало)") -set(DOXYGEN_GENERATE_LATEX YES) -set(DOXYGEN_GENERATE_HTML YES) - -set(CPACK_GENERATOR "TXZ;DEB") -set(CPACK_PACKAGE_CONTACT "John Doe ") -set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "CMake project example") -set(CPACK_DEBIAN_PACKAGE_SECTION "misc") -set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional") -set(CPACK_SOURCE_IGNORE_FILES - ${CMAKE_BINARY_DIR} - .git/ - .git$ - .gitlab-ci/ - _output/ - files/lib - files/log - .clang-tidy - .cmake-format - .gitignore - .gitmodules - .gitlab-ci.yml - CMakeLists.txt.user.* - ~$ - \\\\..*\\\\.swp$) ----- - -Произведённые изменения можно зафиксировать: - -[source,sh] ----- -git add cmake/etc/Variables.cmake CMakeLists.txt -git commit -m "Подключение библиотеки CMLib" ----- - -Чтобы проверить корректность подключения CMLib, можно выполнить команду: - -[source,sh] ----- -(mkdir -p _build && cd _build && cmake .. && make && echo OK) ----- - -Если последней строкой вывода будет `OK`, то настройка завершена верно. - - -== Поиск системных библиотек - -Поиск программ, библиотек и заголовочных файлов, установленных в системе, можно -выполнять с помощью программы https://en.wikipedia.org/wiki/Pkg-config[`pkg-config`] -или функции CMake `find_package`. В любом случае для указания того, -что наличие искомого объекта обязательно для сборки, используется -параметр `REQUIRED`. - -=== Поиск с помощью программы `pkg-config` - -Программа `pkg-config` хранит базу данных параметров (обычно в каталогах -`/usr/share/pkgconfig`, `/usr/lib/pkgconfig` и `/usr/lib/x86_64-linux-gnu/pkgconfig`), -содержащую флаги компиляции для поиска заголовочных файлов и компоновки -библиотек, установленных в систему. Для использования в CMake сначала -необходимо выполнить проверку наличия программы `pkg-config` в системе -и подключить определённую в модуле `PkgConfig` функцию `pkg_check_modules`. -Например, для поиска библиотек `gsl`, `fftw3` и `udev` можно написать -в файле `CMakeLists.txt`: - -[source,cmake] ----- -# Поиск библиотек с помощью pkgconfig -find_package(PkgConfig REQUIRED) -pkg_check_modules(GSL REQUIRED gsl) -pkg_check_modules(FFTW3 REQUIRED fftw3) -pkg_check_modules(UDEV udev) ----- - -=== Поиск с помощью функции `find_package` - -Если системная библиотека поставляется без файла описания для `pkg-config` -или необходимо произвести более сложный поиск, например, включающий поиск -исполняемого файла, то может быть написан специальный модуль для `CMake`, -который вызывается функцией `find_package`. Примеры вызова функции: - -[source,cmake] ----- -# Поиск с помощью функции find_package -find_package(LibXml2) -find_package(CURL REQUIRED) ----- - - -== Автоматически генерируемый заголовочный файл - -На этапе конфигурирования проекта можно сгенерировать файл, в который -будут записаны собранные значения параметров. В библиотеке CMLib -присутствует функция `cmlib_config_hpp_generate()`, создающая файл -`${CMAKE_BINARY_DIR}/include/cmlib_private_config.hpp`, в который -записывается информация о имени и версии проекта, дате и типе сборки. - -[source,cmake] ----- -# Автоматически генерируемый заголовочный файл -cmlib_config_hpp_generate() ----- - - -== Удаление установленных файлов - -В библиотеку CMLib добавлена цель `uninstall`, позволяющая удалить файлы, -которые могут быть установлены в результате выполнения цели `install`: - -[source,sh] ----- -cd _build/debug -make install -make uninstall ----- - - -== Архивирование проекта - -Стандартный модуль `CPack` предназначен для архивирования исходных -текстов проекта и создания пакетов для установки в целевую систему. -Необходимые переменные устанавливаются в файле `cmake/etc/Variables.cmake` -<>. - -По умолчанию цель для упаковки исходных текстов называется `package_source`. -В библиотеке CMLib определены значения основных параметров, -а также дополнительная цель `dist`. - -Для создания бинарных пакетов нужно выполнить в каталоге сборки команду `cpack`. - -[source,sh] ----- -cd _build/debug -make dist -cpack ----- - - -== Примеры библиотек и приложений - - -=== Базовая библиотека - -Проект с базовой библиотекой реализован на основе <>. -Исходные тексты содержат комментарии, объясняющие назначение используемых функций. -Проект можно посмотреть https://git.246060.ru/f1x1t/cmlib-example-library[здесь] -или сделать его копию командой: - -[source,sh] ----- -git clone --recursive https://git.246060.ru/f1x1t/cmlib-example-library ----- - -В файл `CMakeLists.txt`, находящийся в корневом каталоге проекта, нужно добавить: - -[source,cmake] ----- -# Поиск библиотеки Boost -set(Boost_USE_STATIC_LIBS ON) -set(Boost_USE_MULTITHREADED OFF) -set(Boost_USE_STATIC_RUNTIME ON) -find_package(Boost 1.55.0 REQUIRED COMPONENTS headers) - -# Автоматически генерируемый заголовочный файл -cmlib_config_hpp_generate() - -# Каталог с исходными текстами библиотеки -add_subdirectory(src/cmlib-example) - -# Документация -add_subdirectory(cmake/doc) - -# Создание вспомогательных символических ссылок -add_dependencies(cmlib-example create_auxilary_symlinks) ----- - - -В подкаталоге `src/cmlib-example` нужно создать файл `CMakeLists.txt`: - -[source,cmake] ----- -# Название основной цели и имя библиотеки в текущем каталоге -set(TRGT cmlib-example) - -# Список файлов исходных текстов -set(TRGT_sources - ${CMAKE_CURRENT_SOURCE_DIR}/init.cpp) - -# Список заголовочных файлов (используется для установки) -set(TRGT_headers - ${CMAKE_CURRENT_SOURCE_DIR}/init.hpp) - -# Функция для создания цели, результатом которой будет сборка библиотеки -add_common_library(TARGET ${TRGT} SOURCES ${TRGT_sources}) -common_target_properties(${TRGT}) - -# Добавление к пути поиска заголовочных файлов -target_include_directories(${TRGT} SYSTEM PUBLIC ${Boost_INCLUDE_DIRS}) - -# Цель, используемая только для установки -# заголовочных файлов без компиляции проекта -add_custom_target( - ${TRGT}-install-headers - COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=headers -P - "${CMAKE_BINARY_DIR}/cmake_install.cmake") - -# Установка статической библиотеки -install(TARGETS ${TRGT}_static - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) - -# Установка динамической библиотеки -if(BUILD_SHARED_LIBS) - install(TARGETS ${TRGT}_shared - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) -endif() - -# Установка заголовочных файлов -install( - FILES ${TRGT}_headers - COMPONENT headers - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${TRGT}) - -# Установка файла для pkg-config -install(FILES ${CMAKE_BINARY_DIR}/${TRGT}.pc - DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) ----- - - -файл `init.hpp`: - -[source,cpp] ----- -#ifndef CMLIB_EXAMPLE_HPP_ -#define CMLIB_EXAMPLE_HPP_ - -#include - -int32_t cmlib_example_init(int32_t i); - -#endif // CMLIB_EXAMPLE_HPP_ ----- - -и файл `init.cpp`: - -[source,cpp] ----- -#include "init.hpp" - -#include - -int32_t cmlib_example_init(int32_t i = 0) -{ - int32_t s = 0; - for ( auto r : boost::counting_range( 1, i ) ) - { - s += r; - } - return s; -} ----- - - - -ПИШУ ЗДЕСЬ!!! - - - -=== Базовое приложение - -Проект с базовым приложением реализован на основе <>. -Исходные тексты содержат комментарии, объясняющие назначение используемых функций. -Проект можно посмотреть https://git.246060.ru/f1x1t/cmlib-example-application[здесь] -или сделать его копию командой: - -[source,sh] ----- -git clone --recursive https://git.246060.ru/f1x1t/cmlib-example-application ----- - -В файл `CMakeLists.txt`, находящийся в корневом каталоге проекта, нужно добавить: - - - - - - - - - - - - -В файле `cmex/CMakeLists.txt` должна быть строка, включающая поиск файла -`CMakeLists.txt` в подкаталоге `src/cmex`: - -[source,cmake] ----- -add_subdirectory(src/cmex) ----- - -В каталоге `cmex/src/cmex` нужно создать файл `main.cpp`: - -[source,cpp] ----- -#include "compiler_features.hpp" -#include "cmlib_config.hpp" - -#include - -#include "cmex.hpp" - -int main(int argc, char **argv) { - std::cout << CMEX_COMPILER_VERSION_MAJOR << std::endl; // Значение из compiler_features.hpp - std::cout << BUILD_TYPE << std::endl; // Значение из cmlib_config.hpp - std::cout << CMEX_VERSION_STR << std::endl; // Значение из cmlib_config.hpp - std::cout << cmex_init(4) << std::endl; // Функция из внутренней библиотеки - return 0; -} ----- - -и файл `CMakeLists.txt`: - -[source,cmake] ----- -# Название основной цели в текущем каталоге -set(current_target cmex_app) - -# Список файлов исходных текстов -set(current_target_sources - ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp - ) - -# Цель для создания исполняемого файла -add_executable(${current_target} ${current_target_sources}) -common_target_properties(${current_target}) - -# Зависимость от библиотеки из текущего проекта -add_dependencies(${current_target} cmex) - -# Добавление внутреннего каталога src/libcmex к списку путей для поиска заголовочных файлов -target_include_directories(${current_target} PUBLIC - $) - -# Имя выходного файла для цели (параметр OUTPUT_NAME) -set_target_properties(${current_target} - PROPERTIES - OUTPUT_NAME cmex - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR} - ) - -# Путь поиска библиотек внутри проекта -link_directories(${CMAKE_INSTALL_LIBDIR}) - -# Сначала внутренние статические библиотеки -target_link_libraries(${current_target} cmex_static) - -# Правила для установки -install(TARGETS ${current_target} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) ----- - - - -== Подключение внешнего проекта - -В каталоге `cmex/thirdparty` нужно создать каталог `cmext` с проектом, -состоящим из файла `cmext.hpp`: - -[source,c] ----- -#ifndef CMEXT_CMEXT_HPP_ -#define CMEXT_CMEXT_HPP_ - -#include - -int32_t cmext_init(int32_t i); - -#endif ----- - -файла `cmext.cpp`: - -[source,c] ----- -#include "cmext.hpp" - -int32_t cmext_init(int32_t i = 0) { - return i; -} ----- - -и файла `CMakeLists.txt`: - -[source,cmake] ----- -cmake_minimum_required(VERSION 3.3) -project(cmext) - -include(GNUInstallDirs) -add_library(cmext cmext.cpp) -install(TARGETS cmext ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) -install(FILES cmext.hpp COMPONENT headers DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${CMAKE_PROJECT_NAME}) ----- - -В файле `cmex/CMakeLists.txt` нужно подключить стандартный модуль -`ExternalProject` и описать правила для его загрузки, настройки, -компиляции и установки для сопряжения с текущим проектом: - -[source,cmake] ----- -# Подключение внешних проектов -include(ExternalProject) - -ExternalProject_Add(cmext - EXCLUDE_FROM_ALL TRUE - SOURCE_DIR ${CMAKE_SOURCE_DIR}/thirdparty/cmext - INSTALL_DIR ${CMAKE_BINARY_DIR} - DOWNLOAD_COMMAND "" - BUILD_BYPRODUCTS /lib/libcmext.a - CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH= -DCMAKE_BUILD_TYPE=Release - ) ----- - -Вызовы этих функций нужно сделать до функций `add_subdirectories`, чтобы -в подключенных подкаталогах можно было использовать цель `cmext` для -определения зависимостей. - -В файле `cmex/src/cmex/CMakeLists.txt` нужно подключить внешний проект -`cmext`: - -[source,cmake] ----- -# Зависимость от библиотеки из внешнего проекта проекта -add_dependencies(${current_target} cmext) ----- - -[source,cmake] ----- -# Добавление каталога, в который устанавливаются заголовочные файлы от внешнего -# проекта cmext, к списку путей для поиска заголовочных файлов -target_include_directories(${current_target} PUBLIC - $) ----- - -[source,cmake] ----- -# Библиотека из внешнего проекта cmext -target_link_libraries(${current_target} ${CMAKE_BINARY_DIR}/lib/libcmext.a) ----- - -Для проверки работоспособности в файле `cmex/src/cmex/main.cpp` нужно -вызвать функцию `cmext_init` из библиотеки, предоставляемой внешним -проектом. Например, можно заменить его содержимое на: - -[source,cpp] ----- -#include "compiler_features.hpp" -#include "cmlib_config.hpp" - -#include -#include - -#include "cmex.hpp" - -QTextStream& qStdOut() -{ - static QTextStream ts(stdout); - return ts; -} - -int main(int argc, char **argv) { - // Значение из compiler_features.hpp - qStdOut() << QObject::tr("Compiler version: ") << CMEX_COMPILER_VERSION_MAJOR << endl; - // Значение из cmlib_config.hpp - qStdOut() << QObject::tr("Project version: ") << CMEX_VERSION_STR << endl; - // Значение из cmlib_config.hpp - qStdOut() << QObject::tr("Build type: ") << BUILD_TYPE << endl; - // Функция из внутренней библиотеки - qStdOut() << QObject::tr("libcmex function call: ") << cmex_init(4) << endl; - // Функция из внешней библиотеки - qStdOut() << QObject::tr("libcmext function call: ") << cmext_init(9) << endl; - - return 0; -} ----- - -== Qt5 - -Для поиска необходимых компонентов Qt5 нужно в файл `cmex/CMakeLists.txt` -перед вызовом функции `cmlib_config_hpp_generate()` нужно добавить строку: - -[source,cmake] ----- -find_package(Qt5 COMPONENTS Core Network Gui Widgets DBus Concurrent Sql REQUIRED) ----- - -Библиотека CMLib автоматически подключает вызов препроцессора `moc` и -компилятора ресурсов `rcc`, если цель использует модуль `Core`, и -вызывает компилятор файлов описания интерфейса, если цель использует -модуль `Widgets`. - -== Консольное приложение - -В файл `cmex/src/cmex/CMakeLists.txt` добавить строки: - -[source,cmake] ----- -# Qt5 -qt_translation(TARGET ${current_target} TS_DIR ${CMAKE_SOURCE_DIR}/l10n LANGUAGES ru_RU) -target_include_directories(${current_target} SYSTEM PUBLIC ${Qt5Core_INCLUDE_DIRS}) -target_compile_options(${current_target} PUBLIC "${Qt5Core_EXECUTABLE_COMPILE_FLAGS}") - -target_link_libraries(${current_target} Qt5::Core) ----- - -Для проверки работоспособности подключения Qt5 файл -`cmex/src/cmex/main.cpp` нужно заменить на: - -[source,cpp] ----- -#include "compiler_features.hpp" -#include "cmlib_config.hpp" - -#include -#include -#include - -#include "cmex.hpp" - -QTextStream& qStdOut() -{ - static QTextStream ts(stdout); - return ts; -} - -int main(int argc, char **argv) { - QCoreApplication app(argc, argv); - QTranslator translator; - - if (translator.load(QLocale(), "cmex_app", QLatin1String("_"), QLatin1String(":/qm"))) - { - app.installTranslator(&translator); - } - // Значение из compiler_features.hpp - qStdOut() << QObject::tr("Compiler version: ") << CMEX_COMPILER_VERSION_MAJOR << endl; - // Значение из cmlib_config.hpp - qStdOut() << QObject::tr("Project version: ") << CMEX_VERSION_STR << endl; - // Значение из cmlib_config.hpp - qStdOut() << QObject::tr("Build type: ") << BUILD_TYPE << endl; - // Функция из внутренней библиотеки - qStdOut() << QObject::tr("libcmex function call: ") << cmex_init(4) << endl; - // Функция из внешней библиотеки - qStdOut() << QObject::tr("libcmext function call: ") << cmext_init(9) << endl; - - return 0; -} ----- - -После сборки проекта в каталоге `cmex/l10n` появится файл -`cmex_app_ru_RU.ts`, в котором нужно отредактировать переводы с помощью -программы `linguist`. После сохранения переводов проект нужно -пересобрать, файл переводов в скомпилированном виде будет встроен в -исполняемый файл `cmex`, а доступ к нему будет осуществляться с помощью -кода: - -[source,cpp] ----- - if (translator.load(QLocale(), "cmex_app", QLatin1String("_"), QLatin1String(":/qm"))) - { - app.installTranslator(&translator); - } ----- - -== Графическое приложение - -Для создания минимального графического приложения нужно создать файл -описания интерфейса `cmex/src/cmex/my_main_window.ui`: - -[source,xml] ----- - - - MyMainWindow - - - - 0 - 0 - 678 - 415 - - - - Main Window - - - - - - ----- - -заголовочный файл `cmex/src/cmex/my_main_window.hpp`: - -[source,cpp] ----- -#ifndef CMEX_MY_MAIN_WINDOW_HPP_ -#define CMEX_MY_MAIN_WINDOW_HPP_ - -#include -#include "ui_my_main_window.h" - -class MyMainWindow : public QWidget, private Ui::MyMainWindow { - Q_OBJECT - public: - MyMainWindow(QWidget* parent = 0); - virtual ~MyMainWindow(); -}; - -#endif /* CMEX_MY_MAIN_WINDOW_HPP_ */ ----- - -и файл с реализацией конструктора и деструктора -`cmex/src/cmex/my_main_window.cpp`: - -[source,cpp] ----- -#include "my_main_window.hpp" - -MyMainWindow::MyMainWindow(QWidget* parent) { - -} - -MyMainWindow::~MyMainWindow() { - -} ----- - -Для отображения графического окна нужно заменить файл -`cmex/src/cmex/main.cpp` на: - -[source,cpp] ----- -#include "compiler_features.hpp" -#include "cmlib_config.hpp" - -#include -#include -#include -#include - -#include "cmex.hpp" -#include "my_main_window.hpp" - -QTextStream& qStdOut() -{ - static QTextStream ts(stdout); - return ts; -} - -int main(int argc, char **argv) { - QApplication app(argc, argv); - QTranslator translator; - - if (translator.load(QLocale(), "cmex_app", QLatin1String("_"), QLatin1String(":/qm"))) - { - app.installTranslator(&translator); - } - - // Значение из compiler_features.hpp - qStdOut() << QObject::tr("Compiler version: ") << CMEX_COMPILER_VERSION_MAJOR << endl; - // Значение из cmlib_config.hpp - qStdOut() << QObject::tr("Project version: ") << CMEX_VERSION_STR << endl; - // Значение из cmlib_config.hpp - qStdOut() << QObject::tr("Build type: ") << BUILD_TYPE << endl; - // Функция из внутренней библиотеки - qStdOut() << QObject::tr("libcmex function call: ") << cmex_init(4) << endl; - // Функция из внешней библиотеки - qStdOut() << QObject::tr("libcmext function call: ") << cmext_init(9) << endl; - - MyMainWindow* mmw = new MyMainWindow(); - mmw->show(); - return app.exec(); -} ----- - -В файле `cmex/src/cmex/CMakeLists.txt` добавить новые файлы к списку -файлов, используемых для компиляции: - -[source,cmake] ----- -set(current_target_sources - ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/my_main_window.cpp - ) - -set(current_target_uis - ${CMAKE_CURRENT_SOURCE_DIR}/my_main_window.ui - ) ----- - -[source,cmake] ----- -# Цель для создания исполняемого файла -add_executable(${current_target} ${current_target_sources} ${current_target_uis}) ----- - -и добавить строки для подключения графических библиотек Qt5 и -соответствующих им заголовочных файлов: - -[source,cmake] ----- -target_include_directories(${current_target} SYSTEM PUBLIC ${Qt5Gui_INCLUDE_DIRS}) -target_include_directories(${current_target} SYSTEM PUBLIC ${Qt5Widgets_INCLUDE_DIRS}) -target_link_libraries(${current_target} Qt5::Gui) -target_link_libraries(${current_target} Qt5::Widgets) ----- - -Во время сборки проекта в файл переводов `cmex/l10n/cmex_app_ru_RU.ts` -будут добавлены новые строки, их нужно перевести с помощью `linguist` и -снова скомпилировать проект. -