# Сборка и распаковка

## Распаковка файла 1С
из командной строки:

    v8unpack.exe -E d:/sample.cf d:/unpack

из python:

```python
import v8unpack

if __name__ == '__main__':
    v8unpack.extract('d:/sample.cf', 'd:/unpack')
```

## Сборка из исходников

из командной строки:

    v8unpack.exe -B d:/unpack d:/repacked.cf

из python:

```python
import v8unpack

if __name__ == '__main__':
    v8unpack.build('d:/unpack', 'd:/repacked.cf')
```

Параметр1 - Путь до папки с исходниками, может быть указан относительный путь.

Параметр2 - Путь до бинарного файла, включая его имя

Дополнительные именованные параметры:

* temp- путь до временной папки')
* index - путь до json файла с словарем копирования
* descent - включает режим наследования при сборке и разборке,четырех значный формат 3.0.75.100 (не более 3 знаков на каждый разряд)"
    подробности в инструкции - раздел разработка расширений")
* auto_include - Если указан содержимое метаданных собирается динамически в зависимости 
   от наличия файлов в каталоге, а при разборке оглавление не сохраняется, 
   например вы можете подкинуть файлы метаданных в каталог из другого проекта
   минусом является, что вложенные ресурсы всегда сортируются по алфавиту. 
   Если не указан, то сборщик не трогает оглавление, вы добавляете и убираете
   вложенные объекты всегда через конфигуратор

## Обновление индекса

из командной строки:

    v8unpack.exe -I src --index index.json --core core

из python:

```python
import v8unpack

if __name__ == '__main__':
    v8unpack.update_index('d:/unpack', index)
```

## Дополнительные именованные параметры сборки и разборки

Дополнительные параметры могут быть указаны через одноименные ключи как при запуске из командной строки,
так и при запуске из python

### version

## Пакетная сборка и разборка
Если из репозитория требуется собирать несколько продуктов, например расширения под все конфигурации
и желательно чтобы командный файл разработчика совпадал с командным кодом системы сборки реализован
пакетный запуск в котором список всех продуктов и параметров их сборки задается в специальном файле
json файле (например product.json)

```python   
  {  
     "saby_vo3_83_uf": {                # идентификатор собираемого продукта
      "src": "src",                     # каталог с исходниками
      "bin": "bin/saby_vo3_83_uf.epf",  # имя файла бинарника
      "temp": "temp",                   # временная парка с этапи сборки находится в этой же папке
      "index": "index.json",            # путь до индексного файла
      "disable": false,                 # собирать или нет сборщику                  
      "options": {                     
         "descent": null,               # под какую версию конфигурации собираем расширение
         "auto_include": true           # автоматически генерировать оглавление или использовать существующее 
      }
     }
  }

```

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


    v8unpack.exe -EA product.json --index saby_vo3_83_uf
    v8unpack.exe -BA product.json --index saby_vo3_83_uf

где product.json файл со списком продуктов и параметрами их сборки / разборки, 
saby_vo3_83_uf - идентификатор продукта в этом файле


#### Внешние обработки
При разборке не используется. 

При сборке указывает под какую платформу собирается обработка: допустимые значения 801, 802, 803

#### Расширения конфигурации
При разборке указывает каким значением затереть версию режима совместимости - может быть полезно,
чтобы не прыгала при работе с различными версия. 

При сборке указывает какое значение версии режима совместимости установить. Заполняется по формату
XYYZZ, например 8.3.6 = 80306 

#### Конфигурации
Пока не используется, работает только со значением по умолчанию.


### temp
Путь до временной папки, если указан то будет использована указанная папка, а временные файлы
не будут удалены по завершении операции. Папка в любом случае очищается перед началом распаковки.


### core

Относительный путь к папке с общими исходникам.  

Данный параметр имеет значение только в режиме обновления файла индекса. 

Если он указан, то пути новых общих файлов будут заполняться относительно этой папки, а не 
папки с исходниками. 


# Переиспользование

Первичной целью проекта была сборка разных продуктов 1С из одних и тех же исходников. 

Общий для разных продуктов программный код и объекты метаданных (далее общие файлы)
предполагается разместить в отдельных репозиториях (git submodules).

Общий для разных объектов метаданных код может быть вынесен в один файл, правя его
в одном месте и пересобрав продукт вы обновите его во всех используемых местах.

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


## Переиспользование кода

Разбиение кода на несколько файлов делается с помощью областей имеющих в названии
ключевое слово include: 

    #Область include_[путь до файла]
    #КонецОбласти 

Для версий 82 и 81 все директивы компилятора автоматически экранируются 
в комментарий //v8unpack {#директива...}. ВАЖНО. Есть маленькое допущение сильно
упрощающее жизнь - код не может начинаться с директивы (замена происходит 
по \n# - просто отступите строку в начале кода)

    //v8unpack #Область include_[путь до файла]
    //v8unpack #КонецОбласти 


При разборке модуля код внутри include области вырезается и сохраняется в
отдельный файл, при сборке происходит обратная процедура.


"Путь до файла" - это путь относительно родительского каталога папки распаковки 
(корня репозитория при рекомендованной структуре), где в качестве разделителя 
используется символ подчеркивания.

Например, в нижеследующем примере рядом с папкой сборки будет создана папка "core",а 
в ней папка "form3" с файлом "test.1с" содержащий весь код внутри области. В исходном 
файле формы останется только описание области.

    #Область include_core_form3_test
    ПримерКода = 1;
    #КонецОбласти

Если область include содержат другие вложенные области include они будут так же вынесены в 
отдельные папки. Путь рассчитывается так же как и для области верхнего уровня.
 
Области include могут содержать обычные области.

Пустое значение в имени include области трактуется как переход к папке верхнего уровня.

Если в include указано только имя файла (одно значение), он будет распаован в ту же папку где
и находился исходный файл на момент распаковки.

Применение такого подхода содержит проблему. Если один и тот же код содержится в нескольких
местах, то его можно редактировать либо в исходниках, либо в конфигураторе во всех местах сразу. 
Это связано с тем, что каждое место будет пытаться сохранить эту область и кто будет последним
не известно т.к. порядок распаковки файлов произвольный. Эту проблему можно решить с помошью
использования вместо include - includr, Области описанные с её помощью при разборке не
обновляют исходники. Таким образом Вы можете одну область поменить как include, а остальные
как includr (нужно было слово той же длинны, долго не думая: r - read, e - edit)

## Динамические директивы
Дает возможность определения директивы выполнения кода при вставке области с кодом.

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

Данная возможность доступна только внутри области include, чтобы установить директивы
внутри области этого достаточно к её названию добавить комментарий содержащий директиву.

Затем в содержимое области, во все места где эту директиву требуется установить 
добавить комментарий //DynamicDirective.

Сборщик при заходе в область определяет имя директивы и добавляет её перед всем комментариями //DynamicDirective.

Если вложенная область не содержит комментария, то на неё распространяется вышестоящая динамическая директива.

При разборке удаляются все директивы перед комментарием  //DynamicDirective

Например у вас есть файл XXX с универсальными функциями
```
//DynamicDirective
Функция HelloWorld()
КонецФункции
```
И вы хотите добавить на свою форму все функции из этого файла с директивой НаКлиенте.
Для этого в коде формы добавляете соответствующую область с динамической директивой.

```
#Область include_XXX //&НаКлиенте
#КонецОбласти
```
Сборщик при добавлении кода области заменит внутри себя все стоки начинающиеся с //DynamicDirective на &НаКлиенте //DynamicDirective
и в результате в коде формы вы получите
```
#Область include_XXX //&НаКлиенте
&НаКлиенте //DynamicDirective
Функция HelloWorld()
КонецФункции
#КонецОбласти
```

   

## Переиспользование групп элементов форм
Разбиение элементов формы на несколько файлов делается при помощи добавление в имя корневого 
элемента префикса include. После этого он и все подчиненные элементы при разборке выделятся в 
отдельный файл. Правила именования после префикса, а так же возможность перемещения файла с помощью
файла оглавления такие же как и для кода. Поддерживается includr.

Важно:
* На форме куда вставляется группа элементов должны быть задекларированы все необходимые этим элементам
свойства
* Вложенные include для элементов форм не поддерживаются.
 

# Файл оглавления
Чтобы иметь более широкие возможности переиспользования кода и элементов можно использовать
файл оглавления. Смысл этого файла собрать все необходимые файлы в каталоге сборки перед сборкой
или наоборот переместить их из каталога после разборки. Основной профит возможность
использовать субмодули в нескольких проектах.

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


Через index.json можно переопределять области, для этого в корне файла
требуется создать служебный элемент "Области include" в содержимом которого указать
новое имена областям кода - {имя исходной области}:{новое имя области}. Тем самым
можно организовать выбор реализации в зависимости от типа приложения или конфигурации
```   
  "Области include": {
      "core_Область1": "core_Область2"
  }
```
При помощи этой возможности можно реализовать следующий кейс. Например способ получения данных
отличается в обработке и расширении.  Оборачиваем функцию получения данных в область, 
а в индексах описываем какую реализацию использовать в том или ином продукте.  

Исключением является ключ "index.json" в значении которого лежит массив путей
до файла index.json. Данная механика нужна чтобы в сабмодулях держать свои файлы оглавлений.

Наибоее типовой является следующая структура:
* {submodule}
  * index.json - пути для раскаладывания файлов сабмодуля
* cmd
  * {код конфигурации}
    * index.json - основное оглавление содержащих пути файлов нужных этой конфигурации
                   и ссылки на остальные файлы оглавления. Файл будет содержать
```
   "index.json": [
       "{submodule}/index.json", 
       "cmd/index.json"
   ]
```                   
                   
  * index.json  - пути для раскаладывания файлов одинаковых для всех конфигураций




## Переиспользование макетов и форм
Важно: для совместимостис linux в индекс файле в путях используйте обычную косую (не двойную обратную).

На последнем шаге разбора утилита копирует файлы по указанным папкам - соответственно
после редактирования файла нужно разобрать чтобы файлы легли на нужные месте. 

```json

  {
    "ExternalDataProcessor.1c": "core/ExternalDataProcessor.1c",
    "ExternalDataProcessor.data83.json": "core/ExternalDataProcessor.data83.json",
    "ExternalDataProcessor.json": "core/ExternalDataProcessor.json",
    "Form": {
      "API.1c": "core/Form/API.1c",
      "API.form83.json": "core/Form/API.form83.json"
    }
  }
 ```

Если требуется перенсти все файлы в папке используйте * 
```json
  "Form": {
    "Форма1": {
      "*": "base/Форма1"
    }
  }
```
Все файлы описанный до * являются исключениями. Можно описать какие файлы не трогать, а какие переместить 
в другое место

```json
{
  "Form": {
    "Форма1": {
      "Form.id.json": null,   останется на месте
      "Form.obj.bsl": "base/Форма2.bsl",  будет перемещен по указанному пути 
      "*": "base/Форма1" - будут перемещены все файлы кроме 2 -  тех что описаны до *
    }
  }
}
```

Чтобы не набивать руками есть генератор оглавления, который добавляет в имеющийся
файл все чего там нет.

    v8unpack.exe -I src --index index.json --core core
    
параметры 
* src - папка с исходниками
* index.json - путь до файла индекса 
* core - каталог с общими модулями по умолчанию, если указан в index.json значения 
  заполнятся если симметричными путями начинающимися с него, а если не указать 
  заполнит пустыми значениями

Важно! Все пути указанные в индексе не должны вести внутрь папаки с исходниками.

# Обновление

Версия модуля строится по шаблону {мажор}.{минор}.{патч}

Смена номера мажорной или минорной версии говорит об обратной несовместимости.

Собирать исходники разобранные утилитой с другой мажорной+минорной версией нельзя!

Порядок обновления:
1. Соберите бинарник старой версией.
2. Обновите утилиту.
3. Разберите бинарник новой версией.
4. Закоммитьте изменения.


# Рекомендации

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

* Установите плагин подстветки синтаксиса 1С для вашего текстового редактора.

Через меню Notepad++ Синтаксисы >> Польз.Синтаксис >> Открыть папку синтаксисов...
- откроется папка с синтасисами, скопируйте файл туда 
[файл настроек подсветки для Notepad++](highlight_notepad.xml)и перезапустите Notepad++.

# Разработка расширений конфигурации

## Методика работы по сборка расширений под разные конфигурации 1С и разные их версии.

Входные условия: у нас есть расширение, которое сделано для нескольких конфигураций и
мы поддерживаем его для различных версий этих конфигураций.

Проблема: конфигурации и платформа периодически меняется, меняется и само расширение.

Задачи:
1. При изменении платформы или конфигурации легко узнавать о необходимости вносить 
изменения в расширение.

2. Обеспечить минимальную зависимость основного функционала от версии платформы и
конфигурации. Особенности версий конфигурации отделены от основного функционала 
расширения.

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

Поскольку на конец 2021 мы не нашли способов решений этих задач, предлагается решить
эти задачи при помощи saby v8unpack следующим образом:


## Отслеживание изменеий конфигурации
Автоматизации пока нет, руками прокликиваем все объекты и обновляем то что поменялось,
если в итоге решаем что хотим выпустить версию, то разбираем расширение указав компилятору
номер версии конфигурации, который он будет использовать в качестве суфикса. 

## Рекоммендуемая технология работы
Определяем минимальную версию конфигурации начиная с которой работает наше расширение и всю разработку
делаем на этой версии. 

Для каждой конфигурации создаем эталонную тестовую базу для тестирования расширения конфигурации.

Разборку и сборку расширения осуществляем с параметром descent в котором 
указываем версию нашей конфигурации.

В этом режиме v8unpack при разборке добавляет суфикс с номером версии конфигурации ко всем
файлам внутри каталога назначения, {имя файла}.{номер версии конфигурации}.{расширение файла}

При появлении новой версии конфигурации создаем копию тестовой базы и обновляем её до новой версии.

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

Если требуются доработки делаем их. Если доработки делаются по конкретно эту версию и не могут быть
применены к ранним версиям, то оставляем эту базу и разбираем исходники с указанием этой 
версии конфигурации в параметре descent. v8unpack распакует в исходники только файлы отличающиеся
от предыдущей версии - одинаковые файлы распакованы не будут.

При сборке версии v8unpack составит список файлов без учета суфикса, и возмет в сборку файлы
подходящии к версии указанной в параметре descent.

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

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


Ограничения: Предполагается, что у конфигурации четырехзначная нумерация версий, каждый 
разряд номера версии занимает не более 3 знаков (не встречали 4 знака, не стали делать 
чтобы имена файлов были по проще). Суффикс в имени файла указывается в виде числа, 
где каждый разряд, кроме первого, дополняется ведущими нулями. Суффиксы 
формируются автоматически при разборе конфигурации.



```
   > 1C
      > Platform
         > {XYYZZZ} - версия платформы
     > TestBase
         > {Код конфигурации} - БУХ3, УТ10 и т.п.
            > {XYYYZZZ} - версия конфигурации
               файлы конфигурации
     > {Название расширения}
        > bin - папка куда будут собираться бинарники расширения
          {Название расширения}.{Код конфигурации}.{Версия конфигурации с которой можно применять}.cfe
        > ..?????.. - submodule для общих с другими продуктами ресурсов
        > base - общие файлы этого расширения, структура идентична струтуре расширения
        > src
            > {код конфигурации}- папка содержит файлы актуальные для этой конфигурации 1С
        > cmd
            > {код конфигурации}- папка содержит коммандные файлы для версий этой конфигурации 1С
                build.XYYYZZZ.cmd        - запускалка сборки версии 
                extract.XYYYZZZ.cmd      - запускалка разборки версии
                update_index.XYYYZZZ.cmd - формирования и обновления индекса
                index.XYYYZZZ.json       - словарь общих файлов
                build.cmd              - запускалка сборки всех версий
                extract.cmd            - запускалка разборки версий
        build.cmd        - запускалка сборки всех расширений
        extract.cmd      - запускалка разборки всех расширений

```



* -XYYYZZZ - версия конфигурации 1C, первые три разряда с ведущими нулями (чертвертый разряд
игнорируется, т.к. не должно быть существенных изменений в каком то билде. 3 знака, потому что
 не встречали четырехзначных номеров. Первый разряд может быть любой длинны.

При сборке целевая версия режима совместимости задается через параметр version сборщика.

Версия режима совместимости указывается в формате 1C (XYYZZ), например 8.3.6 = 80306.
Указанная версия добавляется как есть. Если указать версию при разборке, она заменит
версию указанную в исходниках, это может быть полезно чтобы при коммитах версия не 
скакала.



### Распаковка файла расширения 1С
из командной строки:

    v8unpack.exe -E d:/sample.cf d:/unpack --index index.json --descent 4100200


### Сборка расширения из исходников

из командной строки:

    v8unpack.exe -B d:/unpack d:/repacked.cf --index index.json --descent 4100200 --version 803012



