В проекте (C#, собирается под разные платформы) образовалась критическая масса однотипных resx-файлов.
Отличия в сведениях о целевой платформе.
Решил все эти файлы гененировать в процессе компиляции, используя шаблон и препроцессор m4.
В перспективе нужно будет прикручивать другие правила, например простое копирование.
Задачу осилил, но кажется как-то криво.
Может кто подскажет лучший вариант. Ну или сам, описав проблему, допру как поправить
--- текущее решение
В проектный файл добавил описания дополнительных свойств для ресурсов
<ItemDefinitionGroup>
<EmbeddedResource>
<LCPI_TemplateSource></LCPI_TemplateSource>
<LCPI_TemplateRule></LCPI_TemplateRule>
</EmbeddedResource>
</ItemDefinitionGroup>
в LCPI_TemplateSource будет указываться файл с шаблоном
в LCPI_TemplateRule будет указывать правило обработки шаблона
Откорректировал описание ресурсов, файлы которых будут генерироваться в процессе компиляции:
<EmbeddedResource Include="$(LCPI_BUILD_CFG__FOLDER__GEN)reg.resx" Link="resources\reg.resx">
<LCPI_TemplateSource>template\reg.resx.m4</LCPI_TemplateSource>
<LCPI_TemplateRule>M4</LCPI_TemplateRule>
</EmbeddedResource>
<EmbeddedResource Include="$(LCPI_BUILD_CFG__FOLDER__GEN)reg.ru.resx" Link="resources\reg.ru.resx">
<LCPI_TemplateSource>template\reg.ru.resx.m4</LCPI_TemplateSource>
<LCPI_TemplateRule>M4</LCPI_TemplateRule>
</EmbeddedResource>
Физически они будут находиться в каталоге $(LCPI_BUILD_CFG__FOLDER__GEN). Этот путь генерируется с учетом целевой платформы и конфигурации проекта.
В дереве проекта они будут якобы находится в каталоге resources.
Указаны шаблоны и правило генерации 'M4'.
---
Далее определяем Target, формирующий список файлов, которые надо пропустить через M4
<Target Name="BuildGeneratedItemList__M4" BeforeTargets="ProcessGeneratedItemList__M4" Returns="@(GeneratedItem__M4)">
<ItemGroup>
<GeneratedItem__M4 Include="%(EmbeddedResource.Identity)" Condition="'%(EmbeddedResource.LCPI_TemplateSource)' != '' and '%(EmbeddedResource.LCPI_TemplateRule)' == 'M4'">
<LCPI_TemplateSource>%(EmbeddedResource.LCPI_TemplateSource)</LCPI_TemplateSource>
</GeneratedItem__M4>
</ItemGroup>
</Target>
И наконец Target, который будет запускать прогонять шаблоны через m4.exe и сохранять результат в финальном файле
<Target Name="ProcessGeneratedItemList__M4" BeforeTargets="CoreResGen">
<Message Importance="High" Text="HELLO FROM ProcessGeneratedItemList__M4! File: %(GeneratedItem__M4.Identity). Source: %(GeneratedItem__M4.LCPI_TemplateSource)."/>
<Exec
Command="m4.exe -D "M4_PROVIDER_PLATFORM=$(LCPI_UI_ProviderPlatform)" -D "M4_DDEX_PLATFORM=$(LCPI_UI_DDEXPlatform)" -D "M4_BUILD_CONFIGURATION=$(Configuration)" "%(GeneratedItem__M4.LCPI_TemplateSource)""
WorkingDirectory="$(ProjectDir)"
ConsoleToMsBuild="true"
StdOutEncoding="UTF-8">
<Output TaskParameter="ConsoleOutput" PropertyName="M4_OUTPUT" />
</Exec>
<WriteLinesToFile
File="%(GeneratedItem__M4.Identity)"
Lines="$(M4_OUTPUT)"
Overwrite="true"
WriteOnlyWhenDifferent="true" />
</Target>
Работает, но есть заковырка.
Если в проекте нет элементов EmbeddedResource с заполненными {LCPI_TemplateSource, LCPI_TemplateRule}, то BuildGeneratedItemList__M4 все равно возвращает один элемент с пустыми полями.
Это не есть хорошо.
Но как победить — пока не догоняю...
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Здравствуйте, Коваленко Дмитрий, Вы писали:
КД>Если в проекте нет элементов EmbeddedResource с заполненными {LCPI_TemplateSource, LCPI_TemplateRule}, то BuildGeneratedItemList__M4 все равно возвращает один элемент с пустыми полями.
КД>Это не есть хорошо.
КД>Но как победить — пока не догоняю...
Победил. И даже немного улучшил.
Нужно было посмотреть на количество элементов в GeneratedItem__M4 —
Condition="@(GeneratedItem__M4->Count())>0"
<ItemGroup>
<GeneratedItem__M4 Include="@(EmbeddedResource->WithMetadataValue('LCPI_TemplateRule','M4'))" />
</ItemGroup>
<Target Name="ProcessGeneratedItemList__M4" BeforeTargets="CoreResGen" Outputs="%(GeneratedItem__M4.Identity)" Condition="@(GeneratedItem__M4->Count())>0">
<Message Importance="High" Text="HELLO FROM ProcessGeneratedItemList__M4! File: %(GeneratedItem__M4.Identity). Source: %(GeneratedItem__M4.LCPI_TemplateSource)."/>
<Exec
Command="m4.exe -D "M4_PROVIDER_PLATFORM=$(LCPI_UI_ProviderPlatform)" -D "M4_DDEX_PLATFORM=$(LCPI_UI_DDEXPlatform)" -D "M4_BUILD_CONFIGURATION=$(Configuration)" "%(GeneratedItem__M4.LCPI_TemplateSource)""
WorkingDirectory="$(ProjectDir)"
ConsoleToMsBuild="true"
StdOutEncoding="UTF-8">
<Output TaskParameter="ConsoleOutput" PropertyName="M4_OUTPUT" />
</Exec>
<MakeDir
Directories="$([System.IO.Path]::GetDirectoryName(%(GeneratedItem__M4.Identity)))"/>
<WriteLinesToFile
File="%(GeneratedItem__M4.Identity)"
Lines="$(M4_OUTPUT)"
Overwrite="true"
WriteOnlyWhenDifferent="true" />
</Target>
Спасибо всем за помощь!
---
UPD1. Мне тут лайков за косячный код отсыпали
.
Поправил ProcessGeneratedItemList__M4 — у него нужно еще
Outputs="%(GeneratedItem__M4.Identity)" прописать, чтобы он правильно выполнял задачи над элементами. И
MakeDir тоже не помешает.
В более правильном варианте, пришлось заменить Exec (и, до кучи, WriteLinesToFile) на свой Task для вызова m4.exe. Внезапно обнаружилось что Exec
триммит результирующие строки, чем напрочь убивает форматирование.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Здравствуйте, Коваленко Дмитрий, Вы писали:
КД>Ну или сам, описав проблему, допру как поправить
Ну так мы так и не услышали саму проблему! Что именно такого неправильного в "однотипных файлах", что ты полез их препроцессить??
Здравствуйте, Kolesiki, Вы писали:
КД>>Ну или сам, описав проблему, допру как поправить
K>Ну так мы так и не услышали саму проблему! Что именно такого неправильного в "однотипных файлах", что ты полез их препроцессить??
Их количество — 38 (19x2) штук.
Заменил на 2 шаблона (english, russian).
| reg.resx для n4_5_0-n4_6_2-Debug |
| <data name="Provider_Description" xml:space="preserve">
<value>LCPI ADO.NET provider for OLE DB data source.
Use this provider for connect to Firebird and InterBase databases through LCPI.IBProvider [OLE DB].
Data provider platform: FW4.5.0. DDEX provider platform: FW4.6.2. Debug assemblies.</value>
</data>
<data name="Provider_DisplayName" xml:space="preserve">
<value>LCPI .NET Framework Data Provider for OLE DB [FW4.5.0][Debug]</value>
</data>
<data name="Provider_ShortDisplayName" xml:space="preserve">
<value>OLE DB [LCPI][FW4.5.0][Debug]</value>
</data>
|
| |
| reg.resx для s2_0-n4_8_0-Debug |
| <data name="Provider_Description" xml:space="preserve">
<value>LCPI ADO.NET provider for OLE DB data source.
Use this provider for connect to Firebird and InterBase databases through LCPI.IBProvider [OLE DB].
Data provider platform: .Net Standard 2.0. DDEX provider platform: FW4.8.0. Debug assemblies.</value>
</data>
<data name="Provider_DisplayName" xml:space="preserve">
<value>LCPI .NET Framework Data Provider for OLE DB [STD2.0][Debug]</value>
</data>
<data name="Provider_ShortDisplayName" xml:space="preserve">
<value>OLE DB [LCPI][STD2.0][Debug]</value>
</data>
|
| |
| reg.resx для s2_0-n4_8_0-Release |
| <data name="Provider_Description" xml:space="preserve">
<value>LCPI ADO.NET provider for OLE DB data source.
Use this provider for connect to Firebird and InterBase databases through LCPI.IBProvider [OLE DB].
Data provider platform: .Net Standard 2.0. DDEX provider platform: FW4.8.0.</value>
</data>
<data name="Provider_DisplayName" xml:space="preserve">
<value>LCPI .NET Framework Data Provider for OLE DB [STD2.0]</value>
</data>
<data name="Provider_ShortDisplayName" xml:space="preserve">
<value>OLE DB [LCPI][STD2.0]</value>
</data>
|
| |
| шаблон reg.resx.m4 |
| changequote([[, ]])
...
<data name="Provider_Description" xml:space="preserve">
<value>LCPI ADO.NET provider for OLE DB data source.
Use this provider for connect to Firebird and InterBase databases through LCPI.IBProvider [OLE DB].
Data provider platform: M4_PROVIDER_PLATFORM. DDEX provider platform: M4_DDEX_PLATFORM.ifelse(M4_BUILD_CONFIGURATION,[[Debug]],[[ Debug assemblies.]],)</value>
</data>
<data name="Provider_DisplayName" xml:space="preserve">
<value>LCPI .NET Framework Data Provider for OLE DB [M4_PROVIDER_PLATFORM__SHORT]ifelse(M4_BUILD_CONFIGURATION,[[Debug]],[Debug],)</value>
</data>
<data name="Provider_ShortDisplayName" xml:space="preserve">
<value>OLE DB [LCPI][M4_PROVIDER_PLATFORM__SHORT]ifelse(M4_BUILD_CONFIGURATION,[[Debug]],[Debug],)</value>
</data>
|
| |
-- Пользователи не приняли программу. Всех пришлось уничтожить. --