【问题标题】:msbuild overriding my pdbmsbuild 覆盖我的 pdb
【发布时间】:2013-07-16 18:06:15
【问题描述】:

我正在使用 Mono 的 Mono.Cecil 包,当我从自定义 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>

我不确定创建 pdb 的目标 msbuild 调用是什么。我以为它是 AfterBuild,但事实并非如此。

任何建议都会有所帮助。

【问题讨论】:

  • 通常编译器会生成 pdb。所以对 CSC 的调用会生成它。
  • 嗨,是的,我已经在http://msdn.microsoft.com/en-us/library/ms171479%28v=vs.90%29.aspx 进行了调查。在我看来,它发生在构建目标中。但是,当我将值“DependsOnTargets”更改为 Build 时,我仍然遇到同样的问题。编辑我在构建后更改 dll。
  • 作为参考,您可能想看看 PostSharp 如何设置它的构建目标,因为它也进行编织。您还可以打开详细或诊断构建输出以查看 pdb 何时被写入/覆盖。
  • 我设法弄明白了。任务没有更新。因此,当我在构建后事件中运行我的 exe 时,它​​正在工作并且我可以调试。但是当我尝试使用该任务时,它什么也没做。我重新启动了我的视觉工作室....并且它起作用了。 (-_-) 谢谢大家!

标签: .net msbuild msbuild-task mono.cecil


【解决方案1】:

如果你想应用自定义重写,覆盖 obj 文件夹中的目标文件很重要。

这是至关重要的,因为 msbuild 从这里复制这些文件。

看我的回答HERE

在我的示例中,除了重写任务之外,我还使用 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 文件夹中创建 pre transform 文件夹
  2. 将所有文件从 obj/ 复制到文件夹中
  3. 创建后转换文件夹
  4. 将所有文件从 obj/ 复制到文件夹中
  5. 使用反射检查类型:
    • 加载输出程序集的引用程序集
    • 过滤继承 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
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-19
    相关资源
    最近更新 更多