Встраивание шрифтов заставляет проект Silverlight всегда перестраиваться - PullRequest
3 голосов
/ 22 сентября 2010

У меня странная проблема с моим проектом Silverlight 4, хотя я видел его раньше.По сути, встраивание шрифтов заставляет мое приложение Silverlight постоянно перестраивать, даже если все обновлено.Этот вид отстой, так как задача встраивания шрифта занимает много памяти и в конечном итоге приводит к сбою VS.Я хотел бы иметь возможность собрать проект из командной строки, но независимо от того, какие у меня локальные проекты устарели, поэтому команда «Выполнить» вызывает повторное построение.Я попытался извлечь часть соответствующей информации из моего журнала msbuild.

Project "D:\Projects\Test\Test.Web\Test.Web.csproj" (10) is building "D:\Projects\Test\Test.SL\Test.SL.csproj" (2:4) on node 1 (default targets).
Building with tools version "4.0".
// Build operation starts normally (well, the dependency set on the server project is forcing the SL application to build). 
...
Target "ResolveReferences" skipped. Previously built successfully.
// A bunch of tasks are skipped (like this one)
...
Target "SubsetFontsSilverlight" in file "C:\Program Files\MSBuild\Microsoft\Expression\Blend\Silverlight\v4.0\SubsetFontSilverlight.targets" from project "D:\Projects\Test\Test.SL\Test.SL.csproj" (target "PrepareResources" depends on it):
Using "SubsetFontsSilverlight" task from assembly "C:\Program Files\MSBuild\Microsoft\Expression\Blend\Silverlight\v4.0\SubsetFontTask.dll".
Task "SubsetFontsSilverlight"
Done executing task "SubsetFontsSilverlight".
Done building target "SubsetFontsSilverlight" in project "Test.SL.csproj".
// this task never gets skipped
...
Target "MainResourcesGeneration" in file "C:\Program Files\MSBuild\Microsoft\Silverlight\v4.0\Microsoft.Silverlight.Common.targets" from project "D:\Projects\Test\Test.SL\Test.SL.csproj" (target "PrepareResources" depends on it):
Building target "MainResourcesGeneration" completely.
Input file "obj\Debug\Fonts\Fonts.zip" is newer than output file "obj\Debug\Test.SL.g.resources".
// note that the Fonts.zip file now makes the resources file out of date
...
Target "CoreCompile" in file "C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\Microsoft.CSharp.Targets" from project "D:\Projects\Test\Test.SL\Test.SL.csproj" (target "Compile" depends on it):
Building target "CoreCompile" completely.
Input file "obj\Debug\Test.SL.g.resources" is newer than output file "obj\Debug\Test.SL.pdb".
// and the full recompile begins...

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

Обновление: образец шрифта из файла проекта.

<BlendEmbeddedFont Include="Fonts\MyriadPro-BoldIt.otf">
  <IsSystemFont>True</IsSystemFont>
  <All>True</All>
  <AutoFill>True</AutoFill>
  <Characters>
  </Characters>
  <Uppercase>True</Uppercase>
  <Lowercase>True</Lowercase>
  <Numbers>True</Numbers>
  <Punctuation>True</Punctuation>
</BlendEmbeddedFont>

Обновление 2:

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

  1. Создание приложения Sillverlight (Blend или VS, хотя вам нужно, чтобы Blend работал для этого в любом случае)

  2. Использовать шрифтДиспетчер (Инструменты -> Диспетчер шрифтов) в Blend, возможно, вам придется открыть MainPage.xaml, чтобы он стал активным.Вставьте шрифт «Tahoma».

Теперь, каждый раз, когда вы нажимаете «Rebuild», вы можете проверить, что csc.exe запускается каждый раз, независимо от того, было ли что-либо изменено.

Ответы [ 2 ]

2 голосов
/ 28 сентября 2010

Я решил эту проблему, немного взломав мой файл SubsetFontSilverlight.target. Это не полное исправление, и оно не обязательно будет работать для всех, но оно работает для меня.

Целевой файл можно найти в C: \ Program Files \ MSBuild \ Microsoft \ Expression \ Blend \ Silverlight \ v4.0, по крайней мере, на моем компьютере.

Основная идея здесь состоит в том, чтобы использовать целевые свойства Input / Ouput MSBUILD, чтобы увидеть, нужно ли обновлять промежуточный файл (ы) Font.zip. Я просто жестко запрограммировал путь к выходному файлу, потому что я всегда использую расположение шрифтов Blend по умолчанию, но его можно создать из отдельных файлов шрифтов.

Я установил условие, что задание должно быть пропущено, если файл Font.zip новее, чем файлы встроенных шрифтов и файл проекта. Таким образом, если вы добавляете / вычитаете шрифт или заменяете один из них, шрифты будут повторно встроены, но если нет никаких изменений (или только изменений кода), font.zip останется один.

Важно добавить fonts.zip в коллекцию ресурсов вручную, если шрифты не внедрены - таким образом, если код нужно перекомпилировать, но шрифты можно оставить в покое, msbuild не забывает включить файл шрифтов в ресурсы , Вот почему я добавил новую задачу для запуска после основной задачи встраивания.

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <UsingTask AssemblyFile="SubsetFontTask.dll" TaskName="Microsoft.Expression.SubsetFontTask.SubsetFontsSilverlight" />
    <UsingTask AssemblyFile="SubsetFontTask.dll" TaskName="Microsoft.Expression.SubsetFontTask.CleanSubsetFonts" />

    <ItemGroup Condition="'$(BuildingInsideVisualStudio)'=='true'">
        <AvailableItemName Include="BlendEmbeddedFont"/>
    </ItemGroup>

  <ItemGroup>
    <!-- Files that we specify as target inputs for msbuild target timestamp check -->
    <FontEmbedRelatedFile Include="$(MSBuildProjectFile)" />
    <FontEmbedRelatedFile Include="@(BlendEmbeddedFont)" />

    <!-- Anticipated font file locations -->
    <FontOutputFile Include="$(IntermediateOutputPath)\Fonts\Fonts.zip" />
  </ItemGroup>

  <!-- 
    this task runs after the main subset task - basically it checks if the task got skipped, and if so
    it adds the projected font output files to the resources collection
   -->
  <Target Name='AfterFontEmbed' AfterTargets="SubsetFontsSilverlight"
    Condition="'@(BlendEmbeddedFont)' != '' AND '@(BlendSubsettedFont)' == ''">
    <Message Text="Adding font files to the resource collection because Font embed was skipped" Importance="normal" />
    <ItemGroup>
      <Resource Include="@(FontOutputFile)" />
    </ItemGroup>
  </Target>

    <Target Name='SubsetFontsSilverlight'  
    Inputs="@(FontEmbedRelatedFile)" Outputs="@(FontOutputFile)"
    DependsOnTargets="$(SubsetFontsDependsOn)"  
    Condition="'@(BlendEmbeddedFont)' != ''">
    <Message Text="Embedding font subsets" Importance="normal" />
        <SubsetFontsSilverlight 
            Fonts="@(BlendEmbeddedFont)" XamlFiles="@(Page)" Resources="@(Resources)"
            IntermediateFilesDirectory="$(IntermediateOutputPath)"
            >
            <Output TaskParameter="SubsettedFonts" ItemName="Resource"/>
            <!-- save our list of embedded font files for later use -->
            <Output TaskParameter="SubsettedFonts" ItemName="BlendSubsettedFont"/>
        </SubsetFontsSilverlight>
    </Target>

    <Target Name='CleanSubsetFonts' DependsOnTargets="$(CleanSubsetFontsDependsOn)" Condition="'@(BlendEmbeddedFont)' != ''">
        <CleanSubsetFonts 
            Fonts="@(BlendEmbeddedFont)"
            IntermediateFilesDirectory="$(IntermediateOutputPath)"
            />
    </Target>

    <PropertyGroup>
        <PrepareResourcesDependsOn>
            SubsetFontsSilverlight;
            $(PrepareResourcesDependsOn);
        </PrepareResourcesDependsOn>
    </PropertyGroup>

    <PropertyGroup>
        <CleanDependsOn>
            $(CleanDependsOn);
            CleanSubsetFonts;
        </CleanDependsOn>
    </PropertyGroup>

</Project>

Visual Studio все еще не замечает того, что проекты обновлены, но когда она их строит, задача corecompile не будет запускаться каждый раз, и файл dll не будет перезаписываться без необходимости. Это означает, что вы можете запустить компилятор в командной строке, установить VS в «Never Build» при отладке, и при этом все равно иметь загруженные правильные символы отладки.

Я проверил это в большинстве ситуаций, о которых мог подумать (до / после очистки, пропущенных файлах, только изменениях кода, изменениях в проекте и т. Д.), И, кажется, все в порядке - это означает, что шрифты есть, а все нет. не всегда перекомпилируется.

1 голос
/ 26 января 2012

Я использовал ответ Егора, и он действительно помог сократить время сборки, особенно при перестройке. Однако недавнее изменение сломало вещи - мы переместили наш шрифт из \ Fonts в папке проекта в \ Assets \ Fonts. Файл целей пытался выполнить актуальную проверку для obj \ Debug \ Fonts \ Fonts.zip, но задачей было создание obj \ Debug \ Assets \ Fonts \ Fonts.zip.

Я изменил файл целей, чтобы проверить наличие файлов Fonts.zip в соответствующих относительных каталогах в промежуточном выходном пути. Этот целевой файл будет работать с несколькими шрифтами, включенными в разные папки.

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <!-- The Blend 4 SDK will always rebuild a xap that has font embedding, rather than
       playing nice and doing up-to-date checks. This targets file replaces the default
       target from the Blend SDK with one that does.
       It checks the input font file and the project file against the fonts.zip file.
       The project file is checked so that any added or removed fonts are picked up -->

  <ItemGroup>
    <!-- Files that we specify as target inputs for msbuild target timestamp check -->
    <FontEmbedRelatedFile Include="$(MSBuildProjectFile)" />
    <FontEmbedRelatedFile Include="@(BlendEmbeddedFont)" />

    <FontOutputFiles Include="@(BlendEmbeddedFont -> '$(IntermediateOutputPath)%(RelativeDir)Fonts.zip')" />
  </ItemGroup>

  <!-- This task runs after the main subset task - basically it checks if the task got skipped, and if so
       it adds the projected font output files to the resources collection -->
  <Target Name='AfterFontEmbed' AfterTargets="SubsetFontsSilverlight"
          Condition="'@(BlendEmbeddedFont)' != '' AND '@(_BlendSubsettedFont)' == ''">
    <ItemGroup>
      <Resource Include="@(FontOutputFiles)" />
    </ItemGroup>
  </Target>

  <Target Name='SubsetFontsSilverlight'
          Inputs="@(FontEmbedRelatedFile)" Outputs="@(FontOutputFiles -> Distinct())"
          DependsOnTargets="$(SubsetFontsDependsOn)" Condition="'@(BlendEmbeddedFont)' != ''">
    <SubsetFontsSilverlight Fonts="@(BlendEmbeddedFont)" 
                            XamlFiles="@(Page)" Resources="@(Resources)" 
                            IntermediateFilesDirectory="$(IntermediateOutputPath)">
      <Output TaskParameter="SubsettedFonts" ItemName="Resource"/>
      <Output TaskParameter="SubsettedFonts" ItemName="_BlendSubsettedFont"/>
    </SubsetFontsSilverlight>
  </Target>
</Project>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...