msbuild переопределяет мой PDB

Я использую пакет Mono.Cecil от mono, и у меня возникает проблема, когда я вызываю следующее из настраиваемой задачи msbuild:

ModuleDefinition.Write(AssemblyFileName, new WriterParameters { WriteSymbols = true });

Сборка сохраняется нормально и делает именно то, что мне нужно. Если я изменил имя файла сборки, чтобы проверить, создан ли pdb, он есть, и при замене другим pdb он правильно отлаживается. Тем не менее, pdb сборки по-прежнему остается старым pdb, когда я собираю нормально. Я предполагаю, что mono создает pdb, а msbuild заменяет его старым.

Это цель, которую я пытаюсь импортировать в проект:

<PropertyGroup>
    <TaskAssemblyFileDir>$(SolutionDir)PropertyObserver.Tasks\$(OutDir)</TaskAssemblyFileDir>
    <TaskAssemblyFileUnescapeDir>$([MSBuild]::Unescape('$(TaskAssemblyFileDir)'))</TaskAssemblyFileUnescapeDir>
    <TaskAssemblyFile>$(TaskAssemblyFileUnescapeDir)PropertyObserver.Tasks.dll</TaskAssemblyFile>
</PropertyGroup>
<UsingTask TaskName="PropertyObserverTask" AssemblyFile="$(TaskAssemblyFile)" />
<Target Name="PropertyObserver" DependsOnTargets="AfterBuild">
    <PropertyObserverTask AssemblyPath="$(TargetPath)" />
</Target>

Я не уверен, что вызывает целевой файл msbuild для создания pdb. Я предположил, что это AfterBuild, но это не так.

Любые советы будут полезны.


person Willem Toerien    schedule 16.07.2013    source источник
comment
Обычно компилятор генерирует файл pdb. Таким образом, вызов в CSC сгенерирует его.   -  person jessehouwing    schedule 16.07.2013
comment
Привет, да, я изучил это на http://msdn.microsoft.com/en-us/library/ms171479%28v=vs.90%29.aspx. Мне показалось, что это происходит в таргете сборки. Однако, когда я меняю значение DependsOnTargets на Build, я по-прежнему сталкиваюсь с той же проблемой. ИЗМЕНИТЬ Я изменяю dll после того, как она была построена.   -  person Willem Toerien    schedule 16.07.2013
comment
Для справки вы можете посмотреть, как PostSharp настраивает цели сборки, поскольку он также выполняет переплетение. Вы также можете включить подробный или диагностический вывод сборки, чтобы увидеть, когда pdbs записываются / перезаписываются.   -  person Jay Walker    schedule 17.07.2013
comment
Мне удалось в этом разобраться. Задача не обновлялась. Поэтому, когда я запускал свой exe в событиях после сборки, он работал, и я мог отлаживать. Но в тот момент, когда я попытался использовать задачу, ничего не вышло. Я перезапустил свою визуальную студию ... и это сработало. (-_-) Спасибо, парни!   -  person Willem Toerien    schedule 17.07.2013


Ответы (1)


Если вы хотите применить настраиваемую перезапись, важно переопределить целевые файлы в папке obj.

Это очень важно, поскольку msbuild копирует эти файлы отсюда.

См. Мой ответ ЗДЕСЬ

В моем примере я использую PostSharp в дополнение к моей задаче переписывания.

Но в вашем случае это не проблема:

<PropertyGroup>
    <CompileDependsOn>
        $(CompileDependsOn);
        ApplyILRewriting
    </CompileDependsOn>
    <BuildDependsOn>
        $(BuildDependsOn);
        AfterILRewritingPostBuild
    </BuildDependsOn>
</PropertyGroup>

<Target Name="ApplyILRewriting">
    <ILTransformationTask IntermediateAssemblyPath="$(ProjectDir)$(BaseIntermediateOutputPath)$(Configuration)\$(TargetFileName)" />
</Target>
<!-- Override this target in another file. Build your nuget packages here for example. -->
<Target Name="AfterILRewritingPostBuild">
</Target>

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

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

Как видите, я передаю путь к сборке в папке obj. Мое решение работает следующим образом (я не хочу сейчас выпускать полный исходный код, извините):

  1. создать папку предварительного преобразования в папке obj
  2. скопировать все файлы из obj / в папку
  3. создать папку преобразования сообщений
  4. скопировать все файлы из obj / в папку
  5. inspect types using reflection:
    • load referenced assemblies of your output assembly
    • типы атрибутов фильтра, наследующие интерфейс ITransformation
    • найти типы, к которым применены эти типы атрибутов
  6. Загрузите соответствующие сборки и типы с помощью cecil из каталога пост-преобразования.
  7. выполнить метод Transform (ReflectionDeclaringType, cecilDeclaringTypeDefinition) для атрибутов, которые вы отразили в типах; Это момент, когда ваш собственный код cecil применяет переписывание с помощью интерфейса ITransformation.

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

Итак, у меня были ITypeTransformation и IAssemblyTranformation. Одна область видимости для сборки, а также только проходящее отражение и сборка cecil. ITypeTransformation передает отражение, сборку cecil и отражение, тип cecil

Примером преобразования может быть:

public class TestTypeTransformation : Attribute, ITypeTransformationAttribute
{
     public void ApplyTransformation(
            Assembly preTransformationReflectionAssembly, 
            AssemblyDefinition postTransformationCecilAssembly, 
            Type reflectionType, 
            TypeDefinition cecilType)
    {
        // Your custom rewriting here
    }
}
person Chris    schedule 25.06.2016