2010-09-22 2 views
3

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

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> 

Update 2:

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

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

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

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

+0

Вы решили вставить только символы, используемые из этого шрифта? Это всегда заставляет перестроить, когда он снова считывает весь текст, чтобы создать карту символов для вставки. Если бы вы могли опубликовать файл MSBuild (соответствующая часть с шрифтом), это было бы полезно. –

+0

@ Otaku: Это стандартный шрифт, встроенный в Blend 4. Я думаю, что есть возможность делать то, что вы говорите, но это, кажется, более широкий поднабор. Но в любом случае, даже если он был настроен для анализа используемых символов, почему это происходит, когда исходные файлы не изменились? – Egor

ответ

2

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

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

Основная идея здесь заключается в использовании целевых свойств ввода/вывода для 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

Я использовал ответ Егора, и это действительно помогло сократить время сборки, особенно при перестройке. Однако недавнее изменение нарушило ситуацию - мы перенесли наш шрифт из \ 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> 
+0

Только что увидел это - спасибо за публикацию обновления, рад, что мое решение помогло вам, ребята. – Egor

Смежные вопросы