2020-04-11 17:09:43 +00:00
|
|
|
|
= Программный проект и иерархия каталогов
|
|
|
|
|
:title-separator: {sp}|
|
|
|
|
|
:category: Программирование
|
2020-04-13 09:06:11 +00:00
|
|
|
|
:tags: Linux, файлы, каталоги, программирование, cmake
|
|
|
|
|
:toc:
|
2020-04-11 17:09:43 +00:00
|
|
|
|
|
|
|
|
|
Для операционных систем типа Linux принят стандарт
|
|
|
|
|
https://ru.wikipedia.org/wiki/FHS[FHS] («стандарт иерархии файловой
|
|
|
|
|
системы»), унифицирующий местонахождение файлов и каталогов с общим
|
|
|
|
|
назначением в файловой системе. Полная текущая версия стандарта
|
|
|
|
|
находится http://refspecs.linuxfoundation.org/fhs.shtml[здесь].
|
|
|
|
|
|
2020-04-13 07:00:26 +00:00
|
|
|
|
== Типы расположения проекта
|
|
|
|
|
|
2020-04-11 17:09:43 +00:00
|
|
|
|
В соответствии с данным стандартом, а также принятыми в ведущих
|
|
|
|
|
дистрибутивах правилами размещения исполняемых файлов в каталогах
|
|
|
|
|
пользователей, можно выделить следующие типы расположения:
|
|
|
|
|
|
|
|
|
|
* системная иерархия в каталоге `/usr` используется для установки
|
|
|
|
|
бинарных пакетов для данного дистрибутива;
|
|
|
|
|
|
|
|
|
|
* системная иерархия в каталоге `/usr/local` используется для установки
|
|
|
|
|
программного обеспечения системным администратором без использования
|
|
|
|
|
пакетов (не рекомендуется для использования из-за проблем поддержки
|
|
|
|
|
в актуальном состоянии);
|
|
|
|
|
|
|
|
|
|
* системная иерархия в каталоге `/opt` используется для установки
|
|
|
|
|
стороннего программного обеспечения. В рамках данной иерархии
|
|
|
|
|
предполагается, что каждый программный продукт располагается в
|
|
|
|
|
собственном каталоге. При таком типе сборки обычно используются
|
|
|
|
|
дополнительные методы (статическая компоновка, включение в состав
|
|
|
|
|
пакета своего набора динамических библиотек) для обеспечения работы
|
2020-04-11 20:09:16 +00:00
|
|
|
|
пакета в операционных системам с отличающимся составом библиотек
|
2020-04-11 17:09:43 +00:00
|
|
|
|
и другим циклом обновления;
|
|
|
|
|
|
|
|
|
|
* системная иерархия в домашнем каталоге пользователя не имеет
|
|
|
|
|
определённого стандарта, обычно производители дистрибутивов
|
|
|
|
|
предлагают использовать для исполняемых файлов каталоги
|
|
|
|
|
`$HOME/bin` или `$HOME/.local/bin`.
|
|
|
|
|
|
2020-04-13 09:31:59 +00:00
|
|
|
|
Система автоматизации сборки программного обеспечения https://cmake.org[CMake]
|
|
|
|
|
позволяет организовать окружение подобное перечисленным выше.
|
|
|
|
|
На этапе сборки проекта можно создать структуру каталогов,
|
|
|
|
|
которая будет отвечать требованиям по логическому разделению
|
|
|
|
|
файлов на исполняемые, заголовочные, библиотеки, файлы настроек и т.д.
|
2020-04-11 17:09:43 +00:00
|
|
|
|
|
2020-04-13 07:00:26 +00:00
|
|
|
|
== Автоматическая адаптация к текущему окружению
|
|
|
|
|
|
2020-04-11 20:58:43 +00:00
|
|
|
|
Для обеспечения единообразной работы вне зависимости от варианта
|
|
|
|
|
иерархии каталогов, в которой находится исполняемый файл, можно
|
|
|
|
|
выполнять автоматическую настройку на работу в текущем окружении.
|
|
|
|
|
|
2020-04-13 06:08:14 +00:00
|
|
|
|
В библиотеке https://git.246060.ru/f1x1t/myxlib[myxlib] реализован
|
|
|
|
|
класс, который анализирует расположение и окружение исполняемого
|
|
|
|
|
файла и предоставляет методы для получения имён каталогов,
|
|
|
|
|
соответствующих текущему окружению. Названия методов и описания
|
2020-04-13 09:31:59 +00:00
|
|
|
|
возвращаемых значений приведены в таблице.
|
2020-04-13 06:08:14 +00:00
|
|
|
|
|
2020-04-13 09:23:07 +00:00
|
|
|
|
.Имена методов и описания
|
2020-04-13 08:52:00 +00:00
|
|
|
|
[cols="2m,4",options="header"]
|
2020-04-13 06:08:14 +00:00
|
|
|
|
|===
|
|
|
|
|
| Метод | Описание
|
2020-04-13 07:33:11 +00:00
|
|
|
|
| homeDirectory() | Полный путь к домашнему каталогу текущего пользователя
|
|
|
|
|
| tempDirectory() | Полный путь к каталогу с временными файлами
|
2020-04-13 06:08:14 +00:00
|
|
|
|
| userConfigDirectory() | Полный путь к пользовательскому каталогу с файлами настройки
|
2020-04-13 07:33:11 +00:00
|
|
|
|
| userConstDataDirectory() | Полный путь к пользовательскому каталогу с неизменяемыми файлами
|
|
|
|
|
| userVarDataDirectory() | Полный путь к пользовательскому каталогу с изменяемыми файлами
|
|
|
|
|
| userLogDirectory() | Полный путь к пользовательскому каталогу с журналами работы
|
2020-04-13 08:05:48 +00:00
|
|
|
|
| executableFilePath() | Полный путь к исполняемому файлу
|
2020-04-13 06:08:14 +00:00
|
|
|
|
| systemConfigDirectory() | Полный путь к системному каталогу с файлами настройки
|
|
|
|
|
| systemConstDataDirectory() | Полный путь к системному каталогу с неизменяемыми файлами
|
2020-04-13 08:05:48 +00:00
|
|
|
|
| systemVarDataDirectory() | Полный путь к системному каталогу с изменяемыми файлами
|
2020-04-13 06:08:14 +00:00
|
|
|
|
| systemLogDirectory() | Полный путь к системному каталогу с журналами работы
|
2020-04-13 08:05:48 +00:00
|
|
|
|
| executableFileDirectory() | Полный путь к каталогу с исполняемым файлом
|
2020-04-13 06:08:14 +00:00
|
|
|
|
| executableFileName() | Имя исполняемого файла
|
2020-04-13 08:05:48 +00:00
|
|
|
|
| configFilePath() | Полный путь к файлу настройки
|
|
|
|
|
| configFileName() | Имя файла настройки
|
|
|
|
|
| projectName() | Имя подкаталога для проекта
|
2020-04-13 06:08:14 +00:00
|
|
|
|
|===
|
2020-04-13 06:11:58 +00:00
|
|
|
|
|
|
|
|
|
Пример использования:
|
|
|
|
|
|
|
|
|
|
[source,cpp]
|
|
|
|
|
----
|
|
|
|
|
#include <myx/filesystem/paths.hpp>
|
|
|
|
|
namespace MF = myx::filesystem;
|
|
|
|
|
|
2020-04-13 07:00:26 +00:00
|
|
|
|
MF::Paths& paths = MF::Paths::instance();
|
|
|
|
|
paths.init( QStringLiteral( "project_name" ), QStringLiteral( "conf" ) );
|
|
|
|
|
qDebug() << paths.systemConstDataDirectory().path();
|
2020-04-13 06:11:58 +00:00
|
|
|
|
----
|
2020-04-13 07:00:26 +00:00
|
|
|
|
|
2020-04-13 09:09:20 +00:00
|
|
|
|
== Правила выбора типа окружения
|
2020-04-13 07:00:26 +00:00
|
|
|
|
|
|
|
|
|
Класс `myx::filesystem::Paths` реализован в виде синглтона,
|
|
|
|
|
чтобы повторно не выполнять проверку окружения в разных частях программы.
|
|
|
|
|
Сначала определяются имена пользовательского и временного каталогов с
|
|
|
|
|
помощью вызовов функций https://doc.qt.io/qt-5/qdir.html#homePath[`QDir::homePath`]
|
|
|
|
|
и https://doc.qt.io/qt-5/qdir.html#tempPath[`QDir::tempPath`], затем
|
|
|
|
|
имена пользовательских каталогов для настроек, постоянных и изменяемых
|
2020-04-13 09:31:59 +00:00
|
|
|
|
данных и журналов. Эти значения не зависят от расположения исполняемого файла,
|
|
|
|
|
а определяются в соответствии со значениям переменных окружения `HOME`,
|
|
|
|
|
`TMPDIR`, `XDG_CONFIG_HOME` и `XDG_DATA_HOME`, либо устанавливаются значения,
|
|
|
|
|
принятые в стандартах. Пример имён каталогов для пользователя `user`
|
2020-04-13 07:00:26 +00:00
|
|
|
|
и проекта `project` приведён в таблице.
|
|
|
|
|
|
2020-04-13 09:31:59 +00:00
|
|
|
|
.Стандартные каталоги для текущего пользователя
|
2020-04-13 08:52:00 +00:00
|
|
|
|
[cols="4,4m,6m",options="header"]
|
2020-04-13 07:00:26 +00:00
|
|
|
|
|===
|
|
|
|
|
| Назначение каталога | Метод | Значение
|
|
|
|
|
| Домашний каталог | homeDirectory() | /home/user
|
|
|
|
|
| Временные файлы | tempDirectory() | /tmp
|
|
|
|
|
| Файлы настройки | userConfigDirectory() | /home/user/.config/project
|
|
|
|
|
| Неизменяемые файлы | userConstDataDirectory() | /home/user/.local/share/project/data
|
|
|
|
|
| Изменяемые файлы | userVarDataDirectory() | /home/user/.local/share/project/lib
|
|
|
|
|
| Журналы работы | userLogDirectory() | /home/user/.local/share/project/log
|
|
|
|
|
|===
|
|
|
|
|
|
2020-04-13 09:09:20 +00:00
|
|
|
|
=== Общая проверка
|
2020-04-13 07:33:11 +00:00
|
|
|
|
|
|
|
|
|
Для определения типа текущего окружения используется полный путь
|
|
|
|
|
к исполняемому файлу, если он находится в каталоге `bin`, то выполняются
|
2020-04-13 07:54:15 +00:00
|
|
|
|
проверки работы в одной из возможных вариантов иерархий,
|
|
|
|
|
иначе делается заключение о том, что файлы всех типов находятся
|
|
|
|
|
в одном каталоге с исполняемым и дальнейшие проверки не выполняются.
|
|
|
|
|
|
2020-04-13 09:09:20 +00:00
|
|
|
|
=== Проверка на работу в иерархии `/opt`
|
2020-04-13 07:54:15 +00:00
|
|
|
|
|
|
|
|
|
Если полный путь к исполняемому файлу начинается c `/opt` и
|
|
|
|
|
содержит в себе название текущего проекта, например
|
|
|
|
|
`/opt/org/project/bin/application`, то выполняется проверка
|
|
|
|
|
на наличие сопутствующих системных каталогов. Если они присутствуют,
|
|
|
|
|
то принимается решение, что окружение в иерархии `/opt` сформировано правильно,
|
|
|
|
|
иначе делается заключение о том, что файлы всех типов находятся
|
|
|
|
|
в одном каталоге с исполняемым и дальнейшие проверки не выполняются.
|
|
|
|
|
Пример правильной структуры каталогов для данной иерархии приведён в таблице.
|
|
|
|
|
|
|
|
|
|
|
2020-04-13 09:45:11 +00:00
|
|
|
|
.Каталоги в иерархии `/opt`
|
2020-04-13 08:52:00 +00:00
|
|
|
|
[cols="4,4m,5m",options="header"]
|
2020-04-13 08:19:37 +00:00
|
|
|
|
|===
|
2020-04-13 08:05:48 +00:00
|
|
|
|
| Назначение файла / каталога | Метод | Значение
|
2020-04-13 08:06:07 +00:00
|
|
|
|
| Исполняемый файл | executableFilePath() | /opt/org/project/bin/application
|
|
|
|
|
| Файлы настройки | systemConfigDirectory() | /opt/org/project/etc
|
|
|
|
|
| Неизменяемые файлы | systemConstDataDirectory() | /opt/org/project/files/data
|
|
|
|
|
| Изменяемые файлы | systemVarDataDirectory() | /opt/org/project/files/lib
|
|
|
|
|
| Журналы работы | systemLogDirectory() | /opt/org/project/files/log
|
2020-04-13 08:19:37 +00:00
|
|
|
|
|===
|
2020-04-13 07:54:15 +00:00
|
|
|
|
|
|
|
|
|
|
2020-04-13 09:09:20 +00:00
|
|
|
|
=== Проверка на работу в иерархии `/usr/local`
|
2020-04-13 07:54:15 +00:00
|
|
|
|
|
|
|
|
|
Если полный путь к исполняемому файлу начинается c `/usr/local`,
|
|
|
|
|
например `/usr/local/bin/application`, то выполняется проверка
|
|
|
|
|
на наличие сопутствующих системных каталогов. Если они присутствуют,
|
|
|
|
|
то принимается решение, что окружение в иерархии `/usr/local` сформировано правильно,
|
|
|
|
|
иначе делается заключение о том, что файлы всех типов находятся
|
|
|
|
|
в одном каталоге с исполняемым и дальнейшие проверки не выполняются.
|
|
|
|
|
Пример правильной структуры каталогов для данной иерархии приведён в таблице.
|
|
|
|
|
|
|
|
|
|
|
2020-04-13 09:45:11 +00:00
|
|
|
|
.Каталоги в иерархии `/usr/local`
|
2020-04-13 08:52:00 +00:00
|
|
|
|
[cols="4,4m,5m",options="header"]
|
2020-04-13 08:19:37 +00:00
|
|
|
|
|===
|
2020-04-13 08:05:48 +00:00
|
|
|
|
| Назначение файла / каталога | Метод | Значение
|
2020-04-13 08:06:07 +00:00
|
|
|
|
| Исполняемый файл | executableFilePath() | /usr/local/bin/application
|
|
|
|
|
| Файлы настройки | systemConfigDirectory() | /usr/local/etc/project
|
|
|
|
|
| Неизменяемые файлы | systemConstDataDirectory() | /usr/local/share/project
|
|
|
|
|
| Изменяемые файлы | systemVarDataDirectory() | /var/lib/project
|
|
|
|
|
| Журналы работы | systemLogDirectory() | /var/log/project
|
2020-04-13 08:19:37 +00:00
|
|
|
|
|===
|
2020-04-13 07:54:15 +00:00
|
|
|
|
|
|
|
|
|
|
2020-04-13 09:09:20 +00:00
|
|
|
|
=== Проверка на работу в иерархии `/usr`
|
2020-04-13 07:54:15 +00:00
|
|
|
|
|
|
|
|
|
Если полный путь к исполняемому файлу начинается c `/usr`,
|
|
|
|
|
например `/usr/bin/application`, то выполняется проверка
|
|
|
|
|
на наличие сопутствующих системных каталогов. Если они присутствуют,
|
|
|
|
|
то принимается решение, что окружение в иерархии `/usr` сформировано правильно,
|
|
|
|
|
иначе делается заключение о том, что файлы всех типов находятся
|
|
|
|
|
в одном каталоге с исполняемым и дальнейшие проверки не выполняются.
|
|
|
|
|
Пример правильной структуры каталогов для данной иерархии приведён в таблице.
|
|
|
|
|
|
|
|
|
|
|
2020-04-13 09:45:11 +00:00
|
|
|
|
.Каталоги в иерархии `/usr`
|
2020-04-13 08:52:00 +00:00
|
|
|
|
[cols="4,4m,5m",options="header"]
|
2020-04-13 08:19:37 +00:00
|
|
|
|
|===
|
2020-04-13 08:05:48 +00:00
|
|
|
|
| Назначение файла / каталога | Метод | Значение
|
2020-04-13 08:06:07 +00:00
|
|
|
|
| Исполняемый файл | executableFilePath() | /usr/bin/application
|
|
|
|
|
| Файлы настройки | systemConfigDirectory() | /etc/project
|
|
|
|
|
| Неизменяемые файлы | systemConstDataDirectory() | /usr/share/project
|
|
|
|
|
| Изменяемые файлы | systemVarDataDirectory() | /var/lib/project
|
|
|
|
|
| Журналы работы | systemLogDirectory() | /var/log/project
|
2020-04-13 08:19:37 +00:00
|
|
|
|
|===
|
|
|
|
|
|
|
|
|
|
|
2020-04-13 09:09:20 +00:00
|
|
|
|
=== Проверка на работу в домашнем каталоге
|
2020-04-13 08:19:37 +00:00
|
|
|
|
|
|
|
|
|
Если полный путь к исполняемому файлу начинается c `/home/user/bin` или
|
|
|
|
|
`/home/user/.local/bin`, например `/home/user/bin/application`, то выполняется
|
|
|
|
|
проверка на наличие сопутствующих системных каталогов. Если они присутствуют,
|
|
|
|
|
то принимается решение, что окружение в домашнем каталоге сформировано правильно,
|
|
|
|
|
иначе делается заключение о том, что файлы всех типов находятся
|
2020-04-13 08:31:26 +00:00
|
|
|
|
в одном каталоге с исполняемым и дальнейшие проверки не выполняются.
|
|
|
|
|
Пример правильной структуры каталогов для данной иерархии приведён в таблице.
|
|
|
|
|
|
|
|
|
|
|
2020-04-13 09:45:11 +00:00
|
|
|
|
.Каталоги при работе в домашнем каталоге
|
2020-04-13 08:35:56 +00:00
|
|
|
|
[cols="4,4m,6m",options="header"]
|
2020-04-13 08:31:26 +00:00
|
|
|
|
|===
|
|
|
|
|
| Назначение файла / каталога | Метод | Значение
|
|
|
|
|
| Исполняемый файл | executableFilePath() | /home/user/bin/application
|
|
|
|
|
| Файлы настройки | systemConfigDirectory() | /home/user/.config/project
|
|
|
|
|
| Неизменяемые файлы | systemConstDataDirectory() | /home/user/.local/share/project/data
|
|
|
|
|
| Изменяемые файлы | systemVarDataDirectory() | /home/user/.local/share/project/lib
|
|
|
|
|
| Журналы работы | systemLogDirectory() | /home/user/.local/share/project/log
|
|
|
|
|
|===
|
|
|
|
|
|
|
|
|
|
|
2020-04-13 09:09:20 +00:00
|
|
|
|
=== Проверка на работу в окружении для разработки
|
2020-04-13 08:31:26 +00:00
|
|
|
|
|
|
|
|
|
Если исполняемый файл находится в каталоге `bin` и при этом окружение не совпадает
|
|
|
|
|
ни с одним из перечисленных выше, то делается предположение, что исполняемый файл
|
2020-04-13 08:35:56 +00:00
|
|
|
|
запускается из окружения, сформированного системой управления проектом, и в данный
|
2020-04-13 09:06:11 +00:00
|
|
|
|
момент идёт разработка (отладка) приложения. В этом случае целесообразно считать
|
2020-04-13 08:35:56 +00:00
|
|
|
|
системными каталогами те, которые находятся внутри иерархии каталогов программного
|
2020-04-13 08:47:19 +00:00
|
|
|
|
проекта. Если присутствуют каталоги, созданные системой управления проекта,
|
|
|
|
|
то принимается решение, что окружение сформировано правильно,
|
2020-04-13 08:31:26 +00:00
|
|
|
|
иначе делается заключение о том, что файлы всех типов находятся
|
2020-04-13 08:47:19 +00:00
|
|
|
|
в одном каталоге с исполняемым и на этом проверки заканчиваются.
|
2020-04-13 08:19:37 +00:00
|
|
|
|
Пример правильной структуры каталогов для данной иерархии приведён в таблице.
|
|
|
|
|
|
|
|
|
|
|
2020-04-13 09:45:11 +00:00
|
|
|
|
.Каталоги при работе в окружении для разработки
|
2020-04-13 08:52:00 +00:00
|
|
|
|
[cols="4,4m,6m",options="header"]
|
2020-04-13 08:19:37 +00:00
|
|
|
|
|===
|
|
|
|
|
| Назначение файла / каталога | Метод | Значение
|
2020-04-13 08:52:00 +00:00
|
|
|
|
| Исполняемый файл | executableFilePath() | /home/user/work/project/_build/debug/bin/application
|
|
|
|
|
| Файлы настройки | systemConfigDirectory() | /home/user/work/project/_build/debug/etc/
|
|
|
|
|
| Неизменяемые файлы | systemConstDataDirectory() | /home/user/work/project/_build/debug/files/data
|
|
|
|
|
| Изменяемые файлы | systemVarDataDirectory() | /home/user/work/project/_build/debug/files/lib
|
|
|
|
|
| Журналы работы | systemLogDirectory() | /home/user/work/project/_build/debug/files/log
|
2020-04-13 08:19:37 +00:00
|
|
|
|
|===
|
2020-04-13 07:54:15 +00:00
|
|
|
|
|
2020-04-13 07:33:11 +00:00
|
|
|
|
|
2020-04-13 09:09:20 +00:00
|
|
|
|
=== Расположение в одном каталоге
|
2020-04-13 09:06:11 +00:00
|
|
|
|
|
|
|
|
|
Если в ходе перечисленных выше проверок не удалось найти правильно
|
|
|
|
|
сформированное окружение, то применяется настройка по умолчанию,
|
|
|
|
|
которая соответствует ситуации, когда все типы файлов расположены
|
|
|
|
|
в одном каталоге с исполняемым файлом. Пример для такого случая приведён в таблице.
|
|
|
|
|
|
2020-04-13 09:45:11 +00:00
|
|
|
|
|
|
|
|
|
.Каталоги в неопределённой иерархии
|
2020-04-13 09:06:11 +00:00
|
|
|
|
[cols="4,4m,6m",options="header"]
|
|
|
|
|
|===
|
|
|
|
|
| Назначение файла / каталога | Метод | Значение
|
|
|
|
|
| Исполняемый файл | executableFilePath() | /home/user/work/project/application
|
|
|
|
|
| Файлы настройки | systemConfigDirectory() | /home/user/work/project
|
|
|
|
|
| Неизменяемые файлы | systemConstDataDirectory() | /home/user/work/project
|
|
|
|
|
| Изменяемые файлы | systemVarDataDirectory() | /home/user/work/project
|
|
|
|
|
| Журналы работы | systemLogDirectory() | /home/user/work/project
|
|
|
|
|
|===
|