diff --git "a/Methodical_manual/09_PatchDiff/9. \320\240\320\260\320\261\320\276\321\202\320\260 \321\201\320\276 \321\201\321\202\320\276\321\200\320\276\320\275\320\275\320\270\320\274\320\270 \320\270\321\201\321\205\320\276\320\264\320\275\321\213\320\274\320\270 \321\202\320\265\320\272\321\201\321\202\320\260\320\274\320\270.md" "b/Methodical_manual/09_PatchDiff/9. \320\240\320\260\320\261\320\276\321\202\320\260 \321\201\320\276 \321\201\321\202\320\276\321\200\320\276\320\275\320\275\320\270\320\274\320\270 \320\270\321\201\321\205\320\276\320\264\320\275\321\213\320\274\320\270 \321\202\320\265\320\272\321\201\321\202\320\260\320\274\320\270.md" index f4ad2b2..e3e0170 100644 --- "a/Methodical_manual/09_PatchDiff/9. \320\240\320\260\320\261\320\276\321\202\320\260 \321\201\320\276 \321\201\321\202\320\276\321\200\320\276\320\275\320\275\320\270\320\274\320\270 \320\270\321\201\321\205\320\276\320\264\320\275\321\213\320\274\320\270 \321\202\320\265\320\272\321\201\321\202\320\260\320\274\320\270.md" +++ "b/Methodical_manual/09_PatchDiff/9. \320\240\320\260\320\261\320\276\321\202\320\260 \321\201\320\276 \321\201\321\202\320\276\321\200\320\276\320\275\320\275\320\270\320\274\320\270 \320\270\321\201\321\205\320\276\320\264\320\275\321\213\320\274\320\270 \321\202\320\265\320\272\321\201\321\202\320\260\320\274\320\270.md" @@ -3,22 +3,22 @@ Объект исследования --- -Представим ситуацию, что мы - не разработчик программного продукта, но работаем с его исходниками, хранящимися где-то в открытом доступе. Нередкой бывает ситуация, когда проект не заработает "из коробки". Причин у этого может быть множество: проект изначально писался под какую-то определённую систему, не совпадающую с нашей; в нём присутствуют ошибки, связанные с обновлением каких-то зависимых элементов. Или вариант позитивнее: мы хотим что-то добавить в проект, например, локализацию под нашу площадку, однако разработчики не принимают наши изменения в основной код. \ +Представим ситуацию, что мы — не разработчик программного продукта, но работаем с его исходниками, хранящимися где-то в открытом доступе. Нередкой бывает ситуация, когда проект не заработает "из коробки". Причин у этого может быть множество: проект изначально писался под какую-то определённую систему, не совпадающую с нашей; в нём присутствуют ошибки, связанные с обновлением каких-то зависимых элементов. Или вариант позитивнее: мы хотим что-то добавить в проект, например, локализацию под нашу площадку, однако разработчики не принимают наши изменения в основной код. \ В обоих случаях мы можем самостоятельно локально изменить исходники для наших нужд, но тогда непременно столкнёмся с ситуацией, когда у команды разработки продукта вышла новая версия без наших улучшений, и мы будем вынуждены заново всё настраивать. -Для упрощения этого бесконечного переписывания кода можно использовать механизм _патчей_. **Патч**(`patch` - "заплатка, накладка") - это сообщение специального формата, в котором описывается набор изменений объектов для их преобразования. +Для упрощения этого бесконечного переписывания кода можно использовать механизм _патчей_. **Патч**(`patch` — "заплатка, накладка") — это сообщение специального формата, в котором описывается набор изменений объектов для их преобразования. При использовании патчей работа со сторонними исходниками становится в разы легче.\ При создании первой версии изменений мы ***исправляем исходники***, как нам необходимо; ***оформляем*** эти ***исправления*** в виде патчей; ***сохраняем*** этот ***патч-сет***, а ***исправленную версию используем*** сами или выкладываем в открытый доступ в зависимости от нужд.\ -При обновлении исходников мы просто ***применяем наши патчи к новой версии*** (при этом часть может примениться сразу, а часть - отвалиться из-за изменений); ***адаптируем оставшиеся патчи*** для их применимости; ***сохраняем новый патч-сет*** и снова просто ***пользуемся нашими надстройками***. +При обновлении исходников мы просто ***применяем наши патчи к новой версии*** (при этом часть может примениться сразу, а часть — отвалиться из-за изменений); ***адаптируем оставшиеся патчи*** для их применимости; ***сохраняем новый патч-сет*** и снова просто ***пользуемся нашими надстройками***. -Работа с патчами, вообще говоря, не базовая грамотность, однако на практике встречается очень часто. Кроме того, именно патчирование было основным способом синхронизации при совместной разработке до массового использования систем контроля версий. А где-то остаётся вообще единственным вариантом такой разработки. +Работа с патчами, вообще говоря, не базовая грамотность, однако на практике встречается очень часто. Кроме того, именно патчи были основным инструментом синхронизации при совместной разработке до массового использования систем контроля версий. А где-то остаётся вообще единственным вариантом такой разработки. -Технология патчирования +Как создавать и накладывать патчи --- Разберёмся, на чём вообще основана технология создания патчей. Для начала нужно научиться находить различия в программах.\ -Рассмотрим пример, в котором реализована функция открытия файла спомощью системного вызова `open`, но с параметром прав доступа из функции `fopen`: +Рассмотрим пример, в котором реализована функция открытия файла с помощью системного вызова `open`, но с параметром прав доступа из функции `fopen`: `ffopen1.c` ```c @@ -102,11 +102,11 @@ admin@localhost:~/LinuxAppDev/09_PatchDiff/Lection> diff ffopen.c ffopen_new.c > case 'x': m = O_RDWR | O_CREAT | O_TRUNC; break; /* w+ */ ``` -`Diff` явно описал, что необходимо сделать с первым файлом, чтобы получить из него второй: удалить 17ю строку, которая выглядит, как показано на экране, а после на 17 строку записать новую, также указанную. +`Diff` явно описал, что необходимо сделать с первым файлом, чтобы получить из него второй: удалить 17-ю строку, которая выглядит, как показано на экране, а после на 17 строку записать новую, также указанную. -Некоторые флаги `diff`позволяют получить этуже информацию в других форматах: +Некоторые флаги `diff`позволяют получить эту же информацию в других форматах: -`-e` - в виде скрипта для текстового однострочного редактора `ed`: +`-e` — в виде скрипта для текстового построчного редактора `ed`: ```console admin@localhost:~/LinuxAppDev/09_PatchDiff/Lection> diff -e ffopen.c ffopen_new.c 17c @@ -114,7 +114,7 @@ admin@localhost:~/LinuxAppDev/09_PatchDiff/Lection> diff -e ffopen.c ffopen_new. . ``` -`-c` - для указания изменения вместе с контекстом, где оно проведено (ДО и ПОСЛЕ): +`-c` — для указания изменения вместе с контекстом, где оно проведено (ДО и ПОСЛЕ): ```console admin@localhost:~/LinuxAppDev/09_PatchDiff/Lection> diff -c ffopen.c ffopen_new.c *** ffopen.c 2024-11-12 16:32:10.603958261 +0300 @@ -138,7 +138,7 @@ admin@localhost:~/LinuxAppDev/09_PatchDiff/Lection> diff -c ffopen.c ffopen_new. } ``` -`-u` - для единого контекстного блока с указанными изменениями +`-u` — для единого контекстного блока с указанными изменениями ```console admin@localhost:~/LinuxAppDev/09_PatchDiff/Lection> diff -u ffopen.c ffopen_new.c --- ffopen.c 2024-11-12 16:32:10.603958261 +0300 @@ -223,7 +223,7 @@ admin@localhost:~/LinuxAppDev/09_PatchDiff/Lection> `Diff` собрал для нас изменения и для каждого написал свой блок контекста и изменений -На самом деле, формат вывода `diff -u` это и есть формат оформления патчей. Поэтому просто сохранив его в виде файла, можно делиться патчем и использовать его для преобразования неизменённых исходников +На самом деле любой вариант вывода `diff` может применяться как патч. Принято использовать `diff -u` — в нём указывается достаточно контекста, и при этом он лаконичнее `diff -c`. Поэтому просто сохранив его в виде файла, можно делиться патчем и использовать его для преобразования неизменённых исходников ```console admin@localhost:~/LinuxAppDev/09_PatchDiff/Lection> diff -u ffopen.c ffopen_new.c > p0.patch @@ -284,7 +284,7 @@ admin@localhost:~/LinuxAppDev/09_PatchDiff/Lection> --- Так как мы собираемся накладывать патчи на обновляющуюся версию исходников, надо разобрать случай, когда наш контекст изменяется. -Возьмём те же самые патчи и применим их к слегка изменённой программе. При этом одно изменение будет попадать в контекст, а другое - нет. +Возьмём те же самые патчи и применим их к слегка изменённой программе. При этом одно изменение будет попадать в контекст, а другое — нет. `ffopen3.c` ```c @@ -386,7 +386,7 @@ admin@localhost:~/LinuxAppDev/09_PatchDiff/Lection> ./a.out /usr/bin/bzcat admin@localhost:~/LinuxAppDev/09_PatchDiff/Lection> ``` -Как мы видим из информации патча, оба изменения применились с неточностью какого-то уровня (у нас это уровень 2). В зависимости от того, как сильно обновление изменило контекст, для неточности рассчитывается этот самый уровень, и с какого-то уровня патч не применяется, как, например, в следующем примере +Как мы видим из информации патча, оба изменения применились с неточностью какого-то уровня (у нас это уровень 2). В зависимости от того, как сильно обновление изменило контекст, для неточности рассчитывается этот самый уровень, и с какого-то уровня патч не применяется, как в следующем примере `ffopen4.c` ```c @@ -448,7 +448,7 @@ admin@localhost:~/LinuxAppDev/09_PatchDiff/Lection> ``` -При этом создаётся `.rej`-файл для описания неприменённого патча, который мы будем изменять руками +При этом создаётся `.rej`-файл для описания ещё не применённого патча, который мы будем изменять руками ```console admin@localhost:~/LinuxAppDev/09_PatchDiff/Lection> cat ffopen4.c.rej @@ -470,7 +470,7 @@ admin@localhost:~/LinuxAppDev/09_PatchDiff/Lection> `diffutils` --- -Для удобной работы с патчами cуществует отдельный набор утилит `diffutils`. Рассмотрим его работу на примере работы с календарём +Для удобной работы с патчами существует отдельный набор утилит `diffutils`. Рассмотрим его работу на примере работы с календарём ```console admin@localhost:~/LinuxAppDev/09_PatchDiff/Lection/calend> LC_TIME=ru_RU.UTF-8 cal -y > calend @@ -592,7 +592,7 @@ admin@localhost:~/LinuxAppDev/09_PatchDiff/Lection/calend> cat p3.patch admin@localhost:~/LinuxAppDev/09_PatchDiff/Lection/calend> ``` -Отметим особенность работы утилиты `sed`, с помощью которой мы задавали изменения. С помощью флага `-i` можно задать постфикс для имени файла, в котором будет сохранена версия файла до изменения. Зачем нам это? Затем, что `patch` умеет применять патчи к итоговому файлу, указанному в его `output-namefile` +Отметим особенность работы утилиты `sed`, с помощью которой мы задавали изменения. С помощью флага `-i` можно задать окончание для имени файла, в котором будет сохранена версия файла до изменения. Зачем нам это? Затем, что `patch` умеет применять патчи к итоговому файлу, указанному в его `output-namefile` ```console admin@localhost:~/LinuxAppDev/09_PatchDiff/Lection/calend> cat p?.patch > pall.patch @@ -697,7 +697,7 @@ admin@localhost:~/LinuxAppDev/09_PatchDiff/Lection/calend> ##### `diffutils combinediff` `combinediff` объединяет патчи в единый блок, при этом по возможности объединяя последовательные действия. \ -Патчи - самостоятельные единицы, не зависящие сами по себе от исходников, и в рамках своих контекстов могут проводить преобразования. Поэтому возможны (теоретически) как ошибочные "склеивания", так и невыполненные объединения операций (отсюда небольшой совет - всегда при объединении указывать патчи в правильном (пусть и частичном) порядке) +Патчи — самостоятельные единицы, не зависящие сами по себе от исходников, и в рамках своих контекстов могут проводить преобразования. Поэтому возможны (теоретически) как ошибочные "склеивания", так и невыполненные объединения операций (отсюда небольшой совет — всегда при объединении указывать патчи в правильном (пусть и частичном) порядке) ```console admin@localhost:~/LinuxAppDev/09_PatchDiff/Lection/calend> combinediff p1.patch p2.patch @@ -728,8 +728,8 @@ diff -u calend calend 1 2 3 4 5 6 1 2 3 1 7 8 9 10 11 12 13 4 5 6 7 8 9 10 2 3 4 5 6 7 8 -admin@localhost:~/LinuxAppDev/09_PatchDiff/Lection/calend> combinediff p1.patch p2.patch | combinediff - p3.patch -# объединили 1й патч с 3м - убралось изменение про точки между 21 и 13 +stephen@localhost:~/LinuxAppDev/09_PatchDiff/Lection/calend> combinediff p1.patch p2.patch | combinediff — p3.patch +# объединили 1й патч с 3м — убралось изменение про точки между 21 и 13 diff -u calend calend --- calend 2024-11-12 17:10:11.596350457 +0300 +++ calend 2024-11-12 17:11:01.573216826 +0300 @@ -757,7 +757,7 @@ admin@localhost:~/LinuxAppDev/09_PatchDiff/Lection/calend> ##### `diffutils interdiff` -Если `combinediff` описывает объединение патчей, то `interdiff` наоборот - показывает операции, которые надо провести над файлом, запатченным только первым параметром, чтобы получить файл, запатченный только вторым параметром (Преобразование `base + patch1 -> base + patch2`) +Если `combinediff` описывает объединение патчей, то `interdiff` наоборот — показывает операции, которые надо провести над файлом, запатченным только первым параметром, чтобы получить файл, запатченный только вторым параметром (Преобразование `base + patch1 -> base + patch2`) ```console admin@localhost:~/LinuxAppDev/09_PatchDiff/Lection/calend> interdiff p1.patch p2.patch @@ -792,7 +792,7 @@ admin@localhost:~/LinuxAppDev/09_PatchDiff/Lection/calend> ##### `rediff` -Эта утилита поможет нам исправлять ошибки, которые мыдопустили при ручном исправлении патча. При этом редактирование всё также просто основывается на контексте самого патча и никак не зависит от исходников +Эта утилита поможет нам исправлять ошибки, которые мы допустили при ручном исправлении патча. При этом редактирование всё также просто основывается на контексте самого патча и никак не зависит от исходников `p1.patch` ``` @@ -857,7 +857,7 @@ Su Mo Tu We Th Fr Sa admin@localhost:~/test_repo> ``` -В `git` есть свой аналог утилиты `diff` - `git diff`. Он также описывает изменения, однако между коммитами (или, при отсутствии параметров, между последним коммитом и текущей версией программы) +В `git` есть свой аналог утилиты `diff` — `git diff`. Он также описывает изменения, однако между коммитами (или, при отсутствии параметров, между последним коммитом и текущей версией программы) ```console admin@localhost:~/test_repo> git diff -u > p1.patch @@ -887,7 +887,7 @@ admin@localhost:~/test_repo> git commit -m "2nd" admin@localhost:~/test_repo> ``` -Важная фишка `git diff` - если в репозитории есть данные о разработчике (имя и почта), можно прямо из репозитория по предварительно настроенному каналу отправлять письма с патчами. Собственно, именно таким способом разработчики раньше и обменивались изменениями - просто пересылали друг другу патчи. +Важная фишка `git diff` — если в репозитории есть данные о разработчике (имя и почта), можно прямо из репозитория по предварительно настроенному каналу отправлять письма с патчами. Собственно, именно таким способом разработчики раньше и обменивались изменениями — просто пересылали друг другу патчи. Для того, чтобы применить полученные патчи, необходимо воспользоваться функцией `git am` (буквально `"git apply mailbox"`, снова отсылающее нас к основному методу передачи патчей) @@ -922,7 +922,7 @@ Su Mo Tu We Th Fr Sa admin@localhost:~/test_repo> ``` -Патчирование в `git` более строгое, чем у `patch`, и даже при малейшем изменении контекста патча не позволит его применить, поскольку для совместной разработки это может быть критичным. +`Git` применяет только патчи с _полностью совпадающим_ контекстом, нечёткого поиска, как у `patch`, в нём нет. В совместной разработке важно чётко отличать область текста, с которой работал только один из участников, и область текста, которую одновременно модифицировало несколько человек — __конфликт__. Домашнее задание @@ -972,7 +972,7 @@ admin@localhost:~/test_repo> + Первый параметр — это строка из двух символов, «проход» и «стена» выводимого лабиринта, а второй — его размер + Первый параметр — начальное значение генератора псевдослучайных чисел (для воспроизведения лабиринта), второй и третий — «проход»-«стена» и размер соответственно. 4. Написать `Makefile` (или аналог), который будет - + генерировать три дополнительных исходника, соответствующх добавлению очередного патча + + генерировать три дополнительных исходника, соответствующих добавлению очередного патча + генерировать, соответственно, четыре бинарника + иметь цель `run`, которая запускает все четыре бинарника с заданными параметрами - + иметь цель `clean`, уничтожающую все генераты \ No newline at end of file + + иметь цель `clean`, уничтожающую все генераты diff --git "a/Methodical_manual/10_LibTesting/10. \320\221\320\270\320\261\320\273\320\270\320\276\321\202\320\265\320\272\320\270 \320\270 \321\202\320\265\321\201\321\202\320\270\321\200\320\276\320\262\320\260\320\275\320\270\320\265.md" "b/Methodical_manual/10_LibTesting/10. \320\221\320\270\320\261\320\273\320\270\320\276\321\202\320\265\320\272\320\270 \320\270 \321\202\320\265\321\201\321\202\320\270\321\200\320\276\320\262\320\260\320\275\320\270\320\265.md" index 192af07..b982ea2 100644 --- "a/Methodical_manual/10_LibTesting/10. \320\221\320\270\320\261\320\273\320\270\320\276\321\202\320\265\320\272\320\270 \320\270 \321\202\320\265\321\201\321\202\320\270\321\200\320\276\320\262\320\260\320\275\320\270\320\265.md" +++ "b/Methodical_manual/10_LibTesting/10. \320\221\320\270\320\261\320\273\320\270\320\276\321\202\320\265\320\272\320\270 \320\270 \321\202\320\265\321\201\321\202\320\270\321\200\320\276\320\262\320\260\320\275\320\270\320\265.md" @@ -3,11 +3,12 @@ Сборка библиотек --- -При работе с проектами мы встречаемся с разными проблемами при подключении библиотек. В случае динамических библиотек, например, нам в обязательном порядкенеобходимо вручную указывать места их расположения через `LD_PRELOAD` и `LD_LIBRARY_PATH`. Более того, само создание библиотек также требует отдельной компиляции и компоновки её исхоников, чем вручную заниматься тоже нет большого желания. +При работе с проектами мы встречаемся с разными проблемами при подключении библиотек. В случае динамических библиотек, например, нам в обязательном порядке необходимо вручную указывать места их расположения через `LD_PRELOAD` и `LD_LIBRARY_PATH`. Более того, само создание библиотек также требует отдельной компиляции и компоновки её исходников, чем вручную заниматься тоже нет большого желания. Разберём небольшой пример, в котором создадим собственную библиотеку и будем её использовать. -`main.c` - наша тестирующая программа библиотеки будет просто инкрементировать поступающее ей из аргументов командной строки число +`main.c` — наша тестирующая программа библиотеки будет просто инкрементировать +поступающее ей из аргументов командной строки число ```c #include #include @@ -28,7 +29,7 @@ int main(int argc, char *argv[]) { } ``` -`lib.c` - зададим функцию инкрементирования +`lib.c` — зададим функцию инкрементирования ```c #include "lib.h" @@ -37,13 +38,13 @@ int inc(int var) { } ``` -`libg.c` - укажем глобальную переменную для функции +`libg.c` — укажем глобальную переменную для функции ```c #include "lib.h" int inc_var = 1; ``` -`lib.h` - конечно же добавим заголовочный файл +`lib.h` — конечно же добавим заголовочный файл ```c int inc(int); extern int inc_var; @@ -78,7 +79,7 @@ admin@localhost:~/LinuxAppDev/10_LibTesting/Lection> ``` Всё отлично работает. -Таким созданием библиотек мы уже занимались, и, как мы вновь убедились, даже для такой небольшой и несложной иерархии файлов нам нужно провести немалое количество операций. Именно для этого нам инужны инструменты, которые сделают всё за нас +Таким созданием библиотек мы уже занимались, и, как мы вновь убедились, даже для такой небольшой и несложной иерархии файлов нам нужно провести немалое количество операций. Именно для этого нам и нужны инструменты, которые сделают всё за нас `libtool` --- @@ -108,10 +109,10 @@ clean: Разберём добавленные нами команды: + Не забываем про встроенные команды `make`, благодаря которым нам можно не описывать правила компиляции файлов, а воспользоваться встроенными рецептами и флагами `CFLAGS` - + Так как `libtool` - стандартная утилита работы с библиотеками, в `make` для неё существует своя переменная окружения `LTFLAGS`. При этом базовые флаги для работы сбиблиотеками (например, `-fPIC`) добавятся автоматически, мы же указываем специализированные, как, например, информацию о компиляторе + + Так как `libtool` — стандартная утилита работы с библиотеками, в `make` для неё существует своя переменная окружения `LTFLAGS`. При этом базовые флаги для работы с библиотеками (например, `-fPIC`) добавятся автоматически, мы же указываем специализированные, как, например, информацию о компиляторе + `libtool` для работы создаёт не совсем обычные объектные файлы, а так называемые `libtool objects` (`%.lo`). Для этого указывается специальный режим `compile` для создания объектных файлов, а также `%.lo`-файлов - + Далее `libtool` на основе указаных нами `lo`-файлов создаёт `libtool archive` (`.la`). Мы помним, что через `.a` у нас указывалась статическая библиотека, здесь же это основа сразу для статической и динамической библиотек. Для создания архива мы указываем режим компоновки `link`, а также стандартное место расположения библиотек (`-rpath`), куда будет помещены готовые библиотеки - + Для создания бинарного файла мы также в режиме компоновки объединяем нах архив с о-файлом тестирующей функции. Это, кстати, даёт нам возможность в тестирующем рецепте убрать явное указание места загрузки динамической библиотеки - `libtool` сам знает, куда положил библиотеку и сам её подключит + + Далее `libtool` на основе указанных нами `lo`-файлов создаёт `libtool archive` (`.la`). Мы помним, что через `.a` у нас указывалась статическая библиотека, здесь же это основа сразу для статической и динамической библиотек. Для создания архива мы указываем режим компоновки `link`, а также стандартное место расположения библиотек (`-rpath`), куда будет помещены готовые библиотеки + + Для создания бинарного файла мы также в режиме компоновки объединяем наш архив с о-файлом тестирующей функции. Это, кстати, даёт нам возможность в тестирующем рецепте убрать явное указание места загрузки динамической библиотеки — `libtool` сам знает, куда положил библиотеку и сам её подключит Сейчас наш `Makefile` даже увеличился и будто вовсе не упростил нам жизнь и работу с библиотекой. Проверим, что он хотя бы не разрушил её работоспособность @@ -177,7 +178,7 @@ admin@localhost:~/LinuxAppDev/10_LibTesting/Lection> LD_LIBRARY_PATH=`pwd`/.libs admin@localhost:~/LinuxAppDev/10_LibTesting/Lection> ``` -Внешний подтягивает библиотеку автоматически, внутренний - требует ручного подключения. +Внешний подтягивает библиотеку автоматически, внутренний — требует ручного подключения. А что из себя представляют `.lo`-файлы и `.la`-файлы? ```console @@ -239,8 +240,8 @@ libdir='/usr/lib64' admin@localhost:~/LinuxAppDev/10_LibTesting/Lection> ``` -Это, как и предполагалось, не обычные объектные файлы, а описания того, как строятся наши библиотеки - "старый" формат (статическая библиотека), информация о предзагрузках, расположение и версии библиотек. Сами же библиотеки хранятся в `.libs` и подгружаются оттуда.\ -Вообще говоря, и лежащий вне директориии `inc` это тоже непросто бинарный файл программы, а `shell`-скрипт, в котором и подключаются все зависимости: +Это, как и предполагалось, не обычные объектные файлы, а описания того, как строятся наши библиотеки — "старый" формат (статическая библиотека), информация о предзагрузках, расположение и версии библиотек. Сами же библиотеки хранятся в `.libs` и подгружаются оттуда.\ +Вообще говоря, и лежащий вне директории `inc` это тоже непросто бинарный файл программы, а `shell`-скрипт, в котором и подключаются все зависимости: ```sh admin@localhost:~/LinuxAppDev/10_LibTesting/Lection> cat inc @@ -268,7 +269,7 @@ admin@localhost:~/LinuxAppDev/10_LibTesting/Lection> Версионирование --- -Как мы видели в `.libs`, `libtool` создал нам три версии нашей библиотеки - без чисел, с одним числом и с тремя числами. +Как мы видели в `.libs`, `libtool` создал нам три версии нашей библиотеки — без чисел, с одним числом и с тремя числами. ```console admin@localhost:~/LinuxAppDev/10_LibTesting/Lection> cd .libs/ admin@localhost:~/LinuxAppDev/10_LibTesting/Lection/.libs> la -A *.so* @@ -278,14 +279,18 @@ lrwxrwxrwx 1 admin admin 15 Nov 25 07:55 libinc.so.0 -> libinc.so.0.0.0 admin@localhost:~/LinuxAppDev/10_LibTesting/Lection/.libs> ``` -Две из них - символьные ссылки на третью. Бесчисловая версия используется для создания зависимостей на библиотеку при работе зависящих утилит, мажорная ("основная", с одним числом) используется для указания на основную поддерживаемую версию, а последняя (единственная реальная библиотека) является самим рабочим объектом.\ -Что же означают числа в версии библиотеки? В случае с библиотеками версионирование описывается через изменение `ABI` - `Application Binary Interface`. Он задаёт низкоуровневые аспекты работы ПО на уровне машинного кода и инструкций процессора. \ +Две из них — символьные ссылки на третью.\ +Вариант совсем без чисел используется для создания зависимостей на библиотеку при сборке. Предполагается, что для сборки подходит _любая_ версия библиотеки, если в ней не изменилось API. Более точно — если изменения API не затронули те символы, которыми пользуется собираемый клиент этой библиотеки. Таким образом пересборка клиента после обновления библиотеки может вообще не поменяться, быть чуть ли не автоматической.\ +Мажорная ("основная", с одним числом) используется для указания на основную поддерживаемую версию. Предполагается, что увеличение мажорной версии делается только тогда, когда API библиотеки изменилось без обратной совместимости.\ +Последняя (единственная реальная библиотека) является самим рабочим объектом.\ +Что же означают числа в версии библиотеки? В случае с библиотеками версионирование описывается через изменение `ABI` — `Application Binary Interface`. Он задаёт низкоуровневые аспекты работы ПО на уровне машинного кода и инструкций процессора. \ В соответствии с [правилами версионирования библиотек](https://www.gnu.org/software/libtool/manual/libtool.html#Versioning) их нумерация определяется полями `current:revision:age` - + `current` описывает изменения `ABI`, влияющие на обратную совместимость библиотеки, и увеличивается при каждом вмешательстве в него + + `current` описывает любые изменения `ABI` библиотеки, и увеличивается при каждом вмешательстве в него + `revision` описывает изменения, не меняющие `ABI`, и увеличивается при внесении таких правок, устанавливаясь в 0 при каждом изменении `current` - + `age` описывает изменения `ABI`, не влияющие на обратную совместимость. Например, добавление нового поля в конец структуры при определённых дисциплинах программирования не будет ломать совместимость (`age` всегда должно быть не больше `current`) + + `age` описывает изменения `ABI`, не влияющие на обратную совместимость (добавление нового интерфейса). Например, добавление новой функции или даже нового поля в конец структуры (при определённых дисциплинах программирования это не будет ломать совместимость). `Age` всегда должно быть не больше `current`) и сбрасывается до 0, при всяким обратно несовместимом изменении ABI (удалении или изменении интерфейса). -Версионирование библиотек можно переложить на стандартный формат `version.minor.subminor` для описания основной, и двух меньших нумераций версий, меняющихся в зависимости от глобальности изменений файла, который будет вычисляться как `{current-age}.age.revision`, однако полноценно считать это версий неправильно, как минимум, из-за неравномерности роста `version`. Зато такое версионирование библиотек позволяет нам поддерживать сразу диапазон допустимых интерфейсов - от `current - age` до `current` +Версионирование библиотек можно переложить на стандартный формат `version.minor.subminor` для описания основной, и двух меньших нумераций версий, меняющихся в зависимости от глобальности изменений файла, который будет вычисляться как `{current - age}.age.revision`. Такой способ нумерации формально отвечает требованиям к понятию «версия» — он всегда только увеличивается, значительные изменения приводят к повышению первого числа в номере. Однако понятия «_следующая_ мажорная версия» не существует: пока изменения обратно совместимы, `{current - age}` будет постоянным, а после обратно несовместимого изменения это число увеличится сразу на `age + 1`.\ +Зато такое версионирование библиотек позволяет нам поддерживать сразу _диапазон_ допустимых интерфейсов — от `current - age` до `current`. ***Семантическое версионирование***, к которому мы привыкли, не может похвастаться таким диапазоном. Оно описывается значениями `MAJOR.MINOR.PATCH` и меняется по следующим правилам: + Обратно **не**совместимые изменения `ABI` (удаление / изменение)— `MAJOR++.MINOR=0.PATCH=0` @@ -299,15 +304,15 @@ admin@localhost:~/LinuxAppDev/10_LibTesting/Lection/.libs> Поговорим теперь про тестирование. То прекрасное время, когда все ошибки были только на уровне компиляции, к сожалению, бесповоротно прошло, компилятор проверяет лишь синтаксические ошибки кода. А для проверки семантики кода, а также того информационного пространства, которое этот код создаёт и с которым взаимодействует (глобальные переменные, макросы, переменные окружения) мы и создаёт тесты. Их прохождение, конечно, не гарантирует правильность работы функций, однако с большой долей вероятности не даст нам неработающий код оставить незамеченным. Выделяют 4 вида тестирования: - + **Модульное** - проверяет работу отдельных модулей написанного продукта - + **Системное** - проверяет работу всей системы изолированно от внешних зависимостей - + **Интеграционное** - проверяет работу в рамках среды, в которой она запускается, и на, вообще говоря, не нами задаваемых условиях среды - + **Приёмочное тестирование** - проверяет внешнее воздействие на проект, внесение невстроенных тестов и проверка поведения системы вообще на её взаимодействие с программами + + Модульное — проверяет работу отдельных модулей написанного продукта + + Системное — проверяет работу всей системы изолированно от внешних зависимостей + + Интеграционное — проверяет работу в рамках среды, в которой она запускается, и на, вообще говоря, не нами задаваемых условиях среды + + Приёмочное тестирование — проверяет внешнее воздействие на проект, внесение сторонних тестов и проверку поведения системы вообще на её взаимодействие с программами Мы будем обсуждать модульное тестирование `xUnit`, задающее собственный путь тестирования системы.\ -В рамках `Unit`-тестов определён `test Runner` - основная программа, запускающая тесты. Он отвечает за проверку подключаемости тестирующего кода (библиотека это или какой-то другой исполняемый объект), фильтрацию тестов, сбор информации по запускам и т.д.\ -Все тесты (`test`) объединены в отдельные тестирующие блоки (`case`), описывающие работу какой-то конкретной функции, а множества блоков, описывающих один раздел работы с проектом (например, _работа с файлами_) объединены в `test suite`. Для более точного понимания можно запомнить, что `suite` описывает "Какая функциональность сломалась?", `case` - "Какая функция сломалась?", `test` - "На каких даных сломалась?"\ -Следующий важный блок любого тестирования - подготовка и ликвидация тестируемого окружения - _фикстуры_. Они могут создаваться для каждого из уровней тестирования и описывать все необходимые зависимости и данные для проверки работоспособности системы.\ +В рамках `Unit`-тестов определён `test Runner` — основная программа, запускающая тесты. Он отвечает за проверку подключаемости тестирующего кода (библиотека это или какой-то другой исполняемый объект), фильтрацию тестов, сбор информации по запускам и т.д.\ +Все тесты (`test`) объединены в отдельные тестирующие блоки (`case`), описывающие работу какой-то конкретной функции, а множества блоков, описывающих один раздел работы с проектом (например, _работа с файлами_) объединены в `test suite`. Для более точного понимания можно запомнить, что `suite` описывает "Какая функциональность сломалась?", `case` — "Какая функция сломалась?", `test` — "На каких данных сломалась?"\ +Следующий важный блок любого тестирования — подготовка и ликвидация тестируемого окружения — _фикстуры_. Они могут создаваться для каждого из уровней тестирования и описывать все необходимые зависимости и данные для проверки работоспособности системы.\ Также в рамках тестирования считается специальный параметр `coverage`, описывающий полноту тестирования программы. Это может быть проверка как процент количества отработанных строк, описывающий тесты, так и проверка путей исполняемых тестов. Check @@ -1481,7 +1486,7 @@ admin@localhost:~/LinuxAppDev/10_LibTesting/Lection/fantasy/src> ``` -Начнём готовить тестировочную библиотеку. Пока что просто разобъём тесты и заголовочные данные из `header`-файла +Начнём готовить тестировочную библиотеку. Пока что просто разобьём тесты и заголовочные данные из `header`-файла `src/Makefile.am` ```make @@ -1781,7 +1786,7 @@ int namegen(char *, unsigned long, const char *, unsigned long *); ``` -Теперь непосредственно подключаем в проект `libtool` - из `libnamegen.c` теперь собирается динамическая библиотека, `configure.ac` теперь использует `libtool` (дополнительно мы запрещаем сборку статической библиотеки, она нам не нужна).\ +Теперь непосредственно подключаем в проект `libtool`: из `libnamegen.c` теперь собирается динамическая библиотека, `configure.ac` теперь использует `libtool` (дополнительно мы запрещаем сборку статической библиотеки, она нам не нужна).\ `src/Makefile.am` теперь настроен на использование `.la`-файлов и, как мы уже видели в начале, генерируемый в `src/namegen` теперь не бинарник, а сценарий на `shell`, автоматически притягивающий `LD_PRELOAD` для запуска, а библиотека и бинарник собираются в `src/.libs/` `configure.ac` @@ -1962,7 +1967,7 @@ int main(int argc, char *argv[]) { ``` -Как мы видим, для описания теста нам нужно довольно много описаний, при этом тест очень шаблонный - проверка наличия данных в `namegen`. Заменим такой длинный тест на который генерат с помощью утилиты `checkmk` +Как мы видим, для созданий теста нам нужно довольно много описаний, при этом тест очень шаблонный — проверка наличия данных в `namegen`. Заменим такой длинный тест на который генерат с помощью утилиты `checkmk` `tests/Makefile.am` ```make @@ -2221,7 +2226,7 @@ unsigned long rng[] = {0xd22bfb3b}; ``` -Всё работает, однако мы сталкиваемся с проблемой неинформативности и неразделяемости тестов. Как минимум, нам нужен тот самый параметр `coverage`, информирующий нас о покрываемости тестами нашей программы. Для этого добавим поддержку `gcov`, которая опишет нам результаты тестирования. +Всё работает, однако мы сталкиваемся с проблемой неинформативности и неразделяемости тестов. Как минимум, нам нужен тот самый параметр `coverage`, проверяющий, насколько плотно наша программа покрыта тестами. Для этого добавим поддержку `gcov`, которая опишет нам результаты тестирования. `Makefile.am` ```make diff --git "a/Methodical_manual/11_Documenting/11. \320\230\320\275\321\204\320\276\321\200\320\274\320\260\321\206\320\270\320\276\320\275\320\275\320\276\320\265 \320\277\321\200\320\276\321\201\321\202\321\200\320\260\320\275\321\201\321\202\320\262\320\276 \320\270 \320\264\320\276\320\272\321\203\320\274\320\265\320\275\321\202\320\270\321\200\320\276\320\262\320\260\320\275\320\270\320\265.md" "b/Methodical_manual/11_Documenting/11. \320\230\320\275\321\204\320\276\321\200\320\274\320\260\321\206\320\270\320\276\320\275\320\275\320\276\320\265 \320\277\321\200\320\276\321\201\321\202\321\200\320\260\320\275\321\201\321\202\320\262\320\276 \320\270 \320\264\320\276\320\272\321\203\320\274\320\265\320\275\321\202\320\270\321\200\320\276\320\262\320\260\320\275\320\270\320\265.md" index 1ed96ff..dba773a 100644 --- "a/Methodical_manual/11_Documenting/11. \320\230\320\275\321\204\320\276\321\200\320\274\320\260\321\206\320\270\320\276\320\275\320\275\320\276\320\265 \320\277\321\200\320\276\321\201\321\202\321\200\320\260\320\275\321\201\321\202\320\262\320\276 \320\270 \320\264\320\276\320\272\321\203\320\274\320\265\320\275\321\202\320\270\321\200\320\276\320\262\320\260\320\275\320\270\320\265.md" +++ "b/Methodical_manual/11_Documenting/11. \320\230\320\275\321\204\320\276\321\200\320\274\320\260\321\206\320\270\320\276\320\275\320\275\320\276\320\265 \320\277\321\200\320\276\321\201\321\202\321\200\320\260\320\275\321\201\321\202\320\262\320\276 \320\270 \320\264\320\276\320\272\321\203\320\274\320\265\320\275\321\202\320\270\321\200\320\276\320\262\320\260\320\275\320\270\320\265.md" @@ -2,28 +2,28 @@ Информационное пространство позволяет взаимодействующим с проектом людям ориентироваться в нём, разбираться с доступным функционалом проекта. -Для разработчиков основное инфопространство занимают описания внутренних элементов проекта - используемые функции, методы, типы и значения переменных. Для сообщества и пользователей основной является информация о возможностях самого продукта и о правилах взаимодействия с ним. При поддержке продукта основную часть инфопространства заполняет описание и струтуризация всех проводящихся изменений проекта. +Для разработчиков основное инфопространство занимают описания внутренних элементов проекта — используемые функции, методы, типы и значения переменных. Для сообщества и пользователей основной является информация о возможностях самого продукта и о правилах взаимодействия с ним. При поддержке продукта основную часть инфопространства заполняет описание и структуризация всех проводящихся изменений проекта. -В общем, информационное пространство - это огромный пласт разработки, охватывающий каждую её часть. Мы же в рамках этого раздела сделаем упор на техническое документирование проекта +В общем, информационное пространство — это огромный пласт разработки, охватывающий каждую её часть. Мы же в рамках этого раздела сделаем упор на техническое документирование проекта Источники информации --- Обсудим, как вообще в нашем проекте собирается информация по его внутреннему и внешнему функционалам. -Основной источник информации - документирование самих исходников. Его можно разбить на два основных типа документирования: - + ***Комментарии*** - Для оформления понятного информационного документа существует множество методик. Одна из самых популярных - [Literate Programming](https://ru.wikipedia.org/wiki/Грамотное_программирование) - была в 1981 предложена Дональном Кнутом. По его методике для проекта пишется большой информационный текст с описанием всех примеров, и туда добавляются вставки описываемого языка программирования; - + ***Документирование API*** - Очень важная часть документирования. В первую очередь продукт разраатывается для пользователей, иесли не сопроводить его информацией, как этим продуктом пользоваться, проект загнётся вне зависимости от всех его уникальностей и преимуществ. Документация это первое, что должно меняться при изменениях. - Документирование API может поддерживаться внутренними особенностями языка (например, в _Python_ поддерживается автодокументирование функций за счёт обработки "повисших" строк) или с помощью систем синтаксического разбора кода, причём как универсальных ([Sphinx](https://www.sphinx-doc.org/), [Doxygen](https://www.doxygen.nl/)), так и ориентированных на конкретный язык программирования +Основной источник информации — документирование самих исходников. Его можно разбить на два основных типа документирования: + + **Комментарии** — Для оформления понятного информационного документа существует множество методик. Одна из самых популярных — [Literate Programming](https://ru.wikipedia.org/wiki/Грамотное_программирование) — была в 1981 предложена Дональдом Кнутом. По его методике для проекта пишется большой информационный текст с описанием всех примеров, и туда добавляются вставки описываемого языка программирования; + + **Документирование API** — Очень важная часть документирования. В первую очередь продукт разрабатывается для пользователей, и если не сопроводить его информацией, как этим продуктом пользоваться, проект загнётся вне зависимости от всех его уникальностей и преимуществ. Документация это первое, что должно меняться при изменениях. + Документирование API может поддерживаться внутренними особенностями языка (например, в _Python_ поддерживается самодокументирование функций за счёт обработки "повисших" строк) или с помощью систем синтаксического разбора кода, причём как универсальных ([Sphinx](https://www.sphinx-doc.org/), [Doxygen](https://www.doxygen.nl/)), так и ориентированных на конкретный язык программирования -Не менее важным является обеспечение общего взаимодействия и унифицированное ведение документации в сообществе. Большую работу в этой сфере провёл [Роберт Мартин](https://ru.wikipedia.org/wiki/Мартин%2C_Роберт_%28инженер%29), выпустивший множество работ подисциплине разработки, стилю оформления проектов, структуре каталогов, наименованию и назначению файлов (классический пример оформления - [GNU Hello](https://git.savannah.gnu.org/cgit/hello.git/tree/)) +Не менее важным является обеспечение общего взаимодействия и унифицированное ведение документации в сообществе. Большую работу в этой сфере провёл [Роберт Мартин](https://ru.wikipedia.org/wiki/Мартин%2C_Роберт_%28инженер%29), выпустивший множество работ по дисциплине разработки, стилю оформления проектов, структуре каталогов, наименованию и назначению файлов (классический пример оформления — [GNU Hello](https://git.savannah.gnu.org/cgit/hello.git/tree/)) -Непосредственное оформление справочников с документацией также имеет свои особенности. Говоря об `offline`-справочниках, нельзя не упомянуть классические `help` и `man`, в которых подробно и без лишней информации описываются все основные параметры и результаты работы описываемых утилит. Ещё одним форматом справочника выступают разного рода генераты и гипертексты, полученные из документированных исходников. Систем документирования бесчисленное количество, каждыйиз них поддерживает разные форматы выходной документации, включая `LaTeX`, `HTML` и так далее. В `online`-документировании полученные справочники могут выкладываться самостоятельно с помощью выгнанной `HTML`-документации, с помощью специализированных движков (`wiki`, [`Pelican`](https://blog.getpelican.com/) и т.д.), сервисов совместной разработки (`README.md` на `Gitlab`/`Github`, `Github Pages` на `Github.io`...) или с помощью специализированных сервисов ([`ReadTheDocs`](https://readthedocs.com/), [`Git Book`](https://www.gitbook.com/) ...) +Непосредственное оформление справочников с документацией также имеет свои особенности. Говоря об `offline`-справочниках, нельзя не упомянуть классические `help` и `man`, в которых подробно и без лишней информации описываются все основные параметры и результаты работы описываемых утилит. Ещё одним форматом справочника выступают разного рода генераты и гипертексты, полученные из документированных исходников. Систем документирования бесчисленное количество, каждый из них поддерживает разные форматы выходной документации, включая `LaTeX`, `HTML` и так далее. В `online`-документировании полученные справочники могут выкладываться самостоятельно с помощью выгнанной `HTML`-документации, с помощью специализированных движков (`wiki`, [`Pelican`](https://blog.getpelican.com/) и т. д.), сервисов совместной разработки (`README.md` на `Gitlab`/`Github`, `Github Pages` на `Github.io`...) или с помощью специализированных сервисов ([`ReadTheDocs`](https://readthedocs.com/), [`Git Book`](https://www.gitbook.com/) ...) Doxygen --- -В данном курсе будем разбираться именно с этим документатором. [`Doxygen`](https://www.doxygen.nl/index.html) - многоязыковая система с кучей приятных бонусов и возможностей. Работает от по принципу синтаксического анализатора - комментарии специального вида прямо в коде считываются и обрабатываются системой. При этом `Doxygen` поддерживает форматные комментарии и другие дополнительные +В данном курсе будем разбираться именно с этим документатором. [`Doxygen`](https://www.doxygen.nl/index.html) — многоязыковая система с кучей приятных бонусов и возможностей. Работает от по принципу синтаксического анализатора — комментарии специального вида прямо в коде считываются и обрабатываются системой. При этом `Doxygen` поддерживает форматные комментарии и другие дополнительные ![](Attached_materials/doxygen.png) @@ -56,7 +56,7 @@ admin@localhost:~/LinuxAppDev/11_Documenting/Lection/namegen> cat Doxyfile.in | 2884 21302 129104 admin@localhost:~/LinuxAppDev/11_Documenting/Lection/namegen> ``` -Это наш базовый настройщик документации. Эти почти 3000 строк - в большинстве своём комментарии, описывающие параметры, которые мы можем менять. Вот некоторые поля из этого файла: +Это наш базовый настройщик документации. Эти почти 3000 строк — в большинстве своём комментарии, описывающие параметры, которые мы можем менять. Вот некоторые поля из этого файла: `Doxygen.in` ```sh @@ -663,8 +663,8 @@ dump('\0'.join(argz) + '\0', lambda v: ' 0 ' if v == '\0' else "'%c'" % v, 15) Документация поддерживает гиперссылки, а также (при предустановленной утилите [Graphviz](https://graphviz.org)) графики зависимостей наших файлов. -Отлично! Наша документация работает, однако сейчас не показывает главную страницу с документацией. Добавим для некоторых комментариев метку `@mainpage` для некоторых страниц, чтобы заполнить главный экран -Также мы хотим, чтобы нами генерируемая документация сохранялась при установке проекта извне. Поэтому соответсвующий рецепт указываем в `Makefile.am` +Отлично! Наша документация работает, однако сейчас оставляет пустой титульную страницу с документацией. Добавим для некоторых комментариев метку `@mainpage` для некоторых страниц, чтобы заполнить стартовую страницу. +Также мы хотим, чтобы нами генерируемая документация устанавливалась вместе с остальными компонентами. Поэтому соответствующий рецепт указываем в `Makefile.am` `Makefile.am` ```make @@ -694,13 +694,12 @@ http: doxygen-doc ![](Attached_materials/mainpage.png) -Теперь добавим генерацию других документов, например, [`man`](https://man7.org/linux/man-pages/man1/man.1.html) +Теперь добавим генерацию других документов, например, [`manpage`](https://man7.org/linux/man-pages/man1/man.1.html) — _руководство_. -Для создания Мана можно пользоваться макропакетами и спецформатами (например, [`troff`](https://liw.fi/manpages/)) или просто конвертировать текстовые исходники (с помощью `txt2man`, [`scdoc`](https://git.sr.ht/~sircmpwn/scdoc) и другие конверторы) +Руководство можно написать непосредственно на [`troff`](https://liw.fi/manpages/) (в этом формате manpages лежат в системе) или просто конвертировать текстовые исходники (с помощью `txt2man`, [`scdoc`](https://git.sr.ht/~sircmpwn/scdoc) и других конверторов) Мы же напишем `man` на нашем же `Doxygen`, он умеет создавать и такие генераты. - Для начала включаем параметр в `Doxyfile.in` ```patch @@ -2226,7 +2226,7 @@ RTF_EXTRA_FILES = @@ -844,34 +843,69 @@ http: doxygen-doc Проверим, что наш `man` (а с ним и какой-никакой `--help`) отлично генерируется и работает ```console -admin@localhost:~/LinuxAppDev/11_Documenting/Lection/namegen> man ./doxygen-doc/man/man1/namegen.c.1 - +stephen@localhost:~/LinuxAppDev/11_Documenting/Lection/namegen> man ./doxygen-doc/man/man1/namegen.1 -src/namegen.c(1) General Commands Manual src/namegen.c(1) +namegen(1) General Commands Manual namegen(1) NAME - src/namegen.c + namegen - Fantasy name generator SYNOPSIS - #include 'config.h' - #include 'namegen.h' - #include - #include - #include - #include - #include - - Functions - static unsigned long hash32 (unsigned long a) - int main (int argc, char **argv) - -Function Documentation - static unsigned long hash32 (unsigned long a) [static] - int main (int argc, char ** argv) -Author - Generated automatically by Doxygen for namegen from the source code. - -namegen Version 0.0.1 src/namegen.c(1) + namegen pattern [ number ] + +DESCRIPTION + Generate a fantasy name (or a number of names, if number is provided) + according to pattern. + + The compile() function creates a name generator based on an input pattern. The + letters s, v, V, c, B, C, i, m, M, D, and d represent different types of + random replacements. Everything else is emitted literally. + + · s - generic syllable + + · v - vowel + + · V - vowel or vowel combination + + · c - consonant + + · B - consonant or consonant combination suitable for beginning a word + + · C - consonant or consonant combination suitable anywhere in a word + + · i - insult + + · m - mushy name + + · M - mushy name ending + + · D - consonant suited for a stupid person's name + + · d - syllable suited for a stupid person's name (begins with a vowel) + + All characters between parenthesis () are emitted literally. For example, the + pattern 's(dim)', emits a random generic syllable followed by 'dim'. + + Characters between angle brackets <> emit patterns from the table above. + Imagine the entire pattern is wrapped in one of these. + + In both types of groupings, a vertical bar | denotes a random choice. Empty + groups are allowed. For example, '(foo|bar)' emits either 'foo' or 'bar'. The + pattern '' emits a constant, vowel, or nothing at all. + + An exclamation point ! means to capitalize the component that follows it. For + example, '!(foo)' will emit 'Foo' and 'v!s' will emit a lowercase vowel + followed by a capitalized syllable, like 'eRod'. + +AUTHORS + This library is based on + + · the RinkWorks Fantasy Name Generator + + · and subsequent Christopher Wellons Fantasy Name Generator header library + +namegen Version 0.0.1 namegen(1) + ``` @@ -889,4 +923,4 @@ namegen Version 0.0.1 src/namegen.c(1) ***Некоторые подробности*** + Титульную страничку придётся генерировать чем-то боле сложным, чем `LC_ALL=C ./number-game --help`. Например, научить саму программу чему-то вроде `--help-md` (в который она подставляет команды `Doxygen`) или обработать `--hеlp` чем-то ещё + Если ничего не поможет, забейте и тупо скопируйте. Ну не будет у вас титульная страница генератом, возможно, начнёт расходиться с `--help` и `man`, и что? -+ (необязательно, для тех, кто хочет поупражняться программировать на Си) Увеличить диапазон до `1…3999` \ No newline at end of file ++ (необязательно, для тех, кто хочет поупражняться программировать на Си) Увеличить диапазон до `1…3999` diff --git "a/Methodical_manual/12_InstallPackaging/12. \320\243\321\201\321\202\320\260\320\275\320\276\320\262\320\272\320\260 \320\270 \320\277\320\260\320\272\320\265\321\202\320\270\321\200\320\276\320\262\320\260\320\275\320\270\320\265.md" "b/Methodical_manual/12_InstallPackaging/12. \320\243\321\201\321\202\320\260\320\275\320\276\320\262\320\272\320\260 \320\270 \320\277\320\260\320\272\320\265\321\202\320\270\321\200\320\276\320\262\320\260\320\275\320\270\320\265.md" index 0615cba..01b8d25 100644 --- "a/Methodical_manual/12_InstallPackaging/12. \320\243\321\201\321\202\320\260\320\275\320\276\320\262\320\272\320\260 \320\270 \320\277\320\260\320\272\320\265\321\202\320\270\321\200\320\276\320\262\320\260\320\275\320\270\320\265.md" +++ "b/Methodical_manual/12_InstallPackaging/12. \320\243\321\201\321\202\320\260\320\275\320\276\320\262\320\272\320\260 \320\270 \320\277\320\260\320\272\320\265\321\202\320\270\321\200\320\276\320\262\320\260\320\275\320\270\320\265.md" @@ -12,36 +12,36 @@ --- Рассмотрим разные популярные варианты установки проектов в систему. -Самый классический вариант - ***установка в полном соответствии с `FHS` данных проекта в системные папки `/usr/bin`, `/usr/lib64` и т.д.*** Данный способ гарантирует работу всех систем, и, собственно, потому и является классическим, поскольку работа со всеми системными утилитами настроена под именно такое распределение файлов. Однако данный способ имеет одну большую проблему - установка в системные папки требует прав `root` при работе, а это, потенциально, даёт полный доступ к любым вторжениям в систему со стороны устанавливаемого ПО. И только разработчику известно, что установит или удалит в системе его `make install` (*знаменитое удаление французского языка из системы*). Кроме того, даже рабочее и безопасное ПО может конфликтовать с уже установленным ПО дистрибутива. +Самый классический вариант — ***установка в полном соответствии с `FHS` данных проекта в системные папки `/usr/bin`, `/usr/lib64` и т. д.*** Данный способ гарантирует работу всех систем, и, собственно, потому и является классическим, поскольку работа со всеми системными утилитами настроена под именно такое распределение файлов. Однако данный способ имеет одну большую проблему — установка в системные папки требует прав `root` при работе, а это, потенциально, даёт полный доступ к любым вторжениям в систему со стороны устанавливаемого ПО. И только разработчику известно, что установит или удалит в системе его `make install` (*знаменитое удаление французского языка из системы*). Кроме того, даже рабочее и безопасное ПО может конфликтовать с уже установленным ПО дистрибутива. -Для избежания конфликтов с системой появился ещё один метод установки - ***в специальные выделенные каталоги `/usr/local/bin`, `/usr/local/lib64` и т. д.*** Такая установка, вообще говоря, не соответствует `FHS`, она также требует `root`-прав для установки и, кроме того, вероятность конфликтов нового ПО с уже установленным более вероятен. Но данный способ не конфликтует с базовыми системами и поэтому используетсяв больших системах, подразумевающих установку огромного количества пакетов в неё. +Для избежания конфликтов с системой появился ещё один метод установки — ***в специальные выделенные каталоги `/usr/local/bin`, `/usr/local/lib64` и т. д.*** Такая установка, вообще говоря, не соответствует `FHS`, она также требует `root`-прав для установки и, кроме того, вероятность конфликтов нового ПО с уже установленным более вероятен. Но данный способ не конфликтует с базовыми системами и поэтому именно он обычно подразумевается по умолчанию в GNU workflow. Кроме того, операционные системы типа FreeBSD, состоящие из довольно большого монолитного репозитория всей базовой системы и «всех остальных пакетов» используют такую схему для этих пакетов. -Для установки проекта без прав `root`-а располагать файлы можно ***в директориях пути `$HOME/.local/`***. Такие установки являются локальными и доступными каждому пользователю по отдельности, отчего в нашей системе могут происходить установки одних и тех же приложений. Кроме того, "дополнительные действия" программ из-за зависимостей на локальные установки каждого пользователя могут не заработать. Такой способ установки полезен для систем, ориентированных на разработчика (поскольку для именно разработки требуется отдельное (а иногда и не одно) независимое пространство установки), а вот для пользователей работа с таким относительно изолированным пространством, для которого надо прописать все связи всех файлов отдельно, будет проблематичным +Для установки проекта без прав `root`-а располагать файлы можно ***в подкаталогах `bin`, `share`, `lib` и т. п. каталога `$HOME/.local/`***. Такие установки являются локальными и доступными каждому пользователю по отдельности, отчего в нашей системе могут происходить установки одних и тех же приложений. Кроме того, "дополнительные действия" программ из-за зависимостей на локальные установки каждого пользователя могут не заработать. Это способ самый простой (скачал, запустил, работает), но и самый неорганизованный — кажется, для Linux ещё не придумали аналога пакетного менеджера, который умел бы разбираться в содержимом `$HOME/.local/`. Нередко после многократных установок невесть чего приходится удалять этот самый `$HOME/.local/` со всем содержимым — нужным и ненужным — и устанавливать всё заново. -Гарантированно неконфликтующий ни с какими утилитами способ установки - ***под правами `root` в директорию `/opt/<приложение>/`***. Из минусов такой установки - нужно явно указывать в `$PATH` `/bin`-директорию нашего проекта, чтобы запускать его, а также проводить дополнительную настройку при старте (подтягивание всех зависимостей из нестандарных расположений), обычно - через `shell`-сценарии. Такая схема используется в сложных проектах, требующих притаскивания с собой разных библиотек и бинарников. +Гарантированно не конфликтующий ни с какими утилитами способ установки — ***под правами `root` в директорию `/opt/<приложение>/`***. Из минусов такой установки — нужно явно указывать в `$PATH` `/bin`-директорию нашего проекта, чтобы запускать его, а также проводить дополнительную настройку при старте (подтягивание всех зависимостей из нестандартных расположений, перегрузку `LD_LIBRARY_PATH` и т. п.), обычно — через `shell`-сценарии. Такая схема используется в сложных проектах, требующих притаскивания с собой разных библиотек и бинарников. Ею также пользуются проприетарное ПО, в котором такого добра обычно много. Все предыдущие схемы предполагали работу с динамическими библиотеками. Однако иногда удобнее в небольших проектах описывать статические зависимости на специфичные элементы. В таком случае используется ***гибридная система, подразумевающая статическую компоновку с частью библиотек, а затем одну из вышеперечисленных схем***. Однако все проблемы статической компоновки нас здесь сразу и настигнут (как минимум, огромные размеры итогового бинарника), а также такая схема может вызвать проблемы версионирования между статической составляющей и динамической зависимостью. -Самая непробиваемая и независимая ни от чего стратегия - ***полная статическая компоновка и установка его***. Такой бинарник не требует никаких прав `root`, зависимостей, правильных установок, поскольку буквально заработает из любого места системы. Статическая линковка подходит для либо очень больших, либо очень маленьких приложений, которые должны работать везде, лишь бы ядро ОС могло их исполнять. Кроме того, такой схемой можно удобно собирать разные версии приложений. +Самая непробиваемая и независимая ни от чего стратегия — ***полная статическая компоновка и установка единственного бинарника***. Такой бинарник не требует никаких прав `root`, зависимостей, правильных установок, поскольку буквально заработает из любого места системы. Статическая компоновка подходит для либо очень больших, либо очень маленьких приложений, которые должны работать везде, лишь бы ядро ОС могло их исполнять. Кроме того, такой схемой можно удобно собирать разные версии приложений. Некоторые инструментарии, например, `Qt`, имеют поддержку т. н. «ресурсов» — работу с файлами разного типа, инкорпорированными в этот бинарник по определённой схеме. Поддержка установки при сборке --- Обсудим способы установки при сборке наших проектов. -Классический способ - вручную задать создание установочных материалов. Такой способ часто используетсядля сборки статического бинарника. +Классический способ — вручную задать создание установочных материалов. Такой способ часто используется для сборки статического бинарника. Можно воспользоваться параметрами `autotools` для выбора установочных данных + Указывается макрос каталога итогового расположения данных `$DESTDIR` + Используются ключи `configure` для тонкой настройки выбора установочных данных + Статическая сборка требует сноровки при описании задаваемых параметров -Для тестовой установки после локальной сборки хорошо подойдут сценарии из `libtool`, поддерживающий установку со стороны окружения за счёт сценариев `.la`-сценариев и т.д. +Для тестовой установки после локальной сборки хорошо подойдут сценарии из `libtool`, поддерживающий установку со стороны окружения за счёт сценариев `.la`-сценариев и т. д. Введение в пакетирование @@ -49,13 +49,13 @@ Ручная (или с помощью сборочных сценариев) *установка* (любым из выше указанных методов)- это один из способов начала работы с готовым продуктом. Однако для разработки под `Linux` самым правильным является ***создание пакета***. -Пакетирование, как способ работы с проектами обязан во многом ***Свободному Лицензированию и Открытой разработке***. Именно они позволяют создавать огромные неконфликтующие инфраструктуры пакетов, основываясь на открытом исходном коде собираемых компонентов системы, для которой капет предназначается. +Пакетирование, как способ работы с проектами обязан во многом ***Свободному Лицензированию и Открытой разработке***. Именно они позволяют создавать огромные неконфликтующие инфраструктуры пакетов, основываясь на открытом исходном коде собираемых компонентов системы, для которой пакет предназначается. -Сам ***пакет*** - это архив с составляющими исходниками, которые раскладываются по основным директориям системы (под `root`-ом), при этом сборка и проверка данных, а также подключение библиотеки пред- и постустановочные сценарии проходят без `root`-а +Сам ***пакет*** — это архив с составляющими исходниками, которые раскладываются по основным директориям системы (под `root`-ом), при этом сборка и проверка данных, а также подключение библиотеки пред- и постустановочные сценарии проходят без `root`-а -Для проверки корректности сборки пакета используются специальные ***репозитории пакетов***. Туда отправляются исходники, а все сборки проводятся в изолированном пространстве репозитория. Это помогает исключить случай работоспособности пакета только в специфичном окружении разработчика. Все данные (исходники - разработчиком, сборка - сборщиком) подписываются, чтобы гарантировать безопасность работы с исходниками и исключить подмену данных при обработке. Также к сборке добавляются встроенные проверки на права доступа, работоспособность собранного проекта. +Для проверки корректности сборки пакета используются специальные ***репозитории пакетов***. Туда отправляются исходники, а все сборки проводятся в изолированном пространстве репозитория. Это помогает исключить случай работоспособности пакета только в специфичном окружении разработчика. Все данные (исходники — разработчиком, сборка — сборщиком) подписываются, чтобы гарантировать безопасность работы с исходниками и исключить подмену данных при обработке. Также к сборке добавляются встроенные проверки на права доступа, работоспособность собранного проекта. -Множество пакетов объединяется в ***дистрибутивы*** - срезы из общего множества пакетов работающих наборов, корректно взаимодействующих друг с другом и обеспечивающих функционал целой системы (приложения / ОС и т.д.) +Множество пакетов объединяется в ***дистрибутивы*** — срезы из общего множества пакетов работающих наборов, корректно взаимодействующих друг с другом и обеспечивающих функционал целой системы (приложения / ОС и т. д.) В следующем разделе мы кратко обсудим основные шаги пакетирования в `Linux`. @@ -72,4 +72,4 @@ + Выгонка документации из исходников + ***Внимание!*** Установка в систему от `root`-а и удаление оттуда (лучше сначала потренироваться на установке от пользователя в `/tmp/qq`) + Установленная программа должна работать в двух локалях, `man` должен читаться -+ Необязательно — в состав может входить библиотека \ No newline at end of file ++ Необязательно — в состав может входить библиотека