【问题标题】:Get source file location with DeterministicSourcePaths turned on打开 DeterministicSourcePaths 获取源文件位置
【发布时间】:2021-08-17 00:56:36
【问题描述】:

问题: 有没有办法在不使用CallerFilePath 属性的情况下获取调用者或当前帧源代码位置?

背景:

我定义了这个助手:

public class PathHelper
{
    public static string GetThisFilePath([CallerFilePath] string path = null)
    {
        return path;
    }
}

可以这样调用来获取用于构建二进制文件的源代码的位置:

var currentSourceFilePath = PathHelper.GetThisFilePath();

这很好用,除非我打开了DeterministicSourcePaths(通常通过 ContinuousIntegrationBuild msbuild 属性)。在这种情况下,返回的路径将被修剪为:

/_/MyRelativeSourcePath

因此,确定性路径似乎被注入到支持CallerFilePath 的编译器功能中,从而产生了这种行为。

我需要源代码位置以便能够对产品特定功能进行单元测试(这与检查构建过程有关),同时我仍然希望支持在 CI 机器上完全确定性构建。

【问题讨论】:

    标签: c# .net msbuild deterministic


    【解决方案1】:

    您可以尝试以下操作。请注意

    • 这只是一个想法,具体实现取决于您的环境

    • 如果您仅使用“默认构建输出路径”,这将起作用

    • 我没有测试过

        public static string GetThisFilePath([CallerFilePath] string path = null)
        {
            const string determenisticRoot = "/_/";
      
            if(!path.StartsWith(determenisticRoot))
            {
                return path;
            }
      
            // callerBinPath would be something like $(SolutionRoot)/.../MyProject.Tests/bin/Debug/net5.0
            var callerBinPath = Path.GetDirectoryName(Assembly.GetCallingAssembly().Location);
      
            // Traverse to $(TestProjectRoot) - testProjectRoot would be something like $(SolutionRoot)/.../MyProject.Tests
            var testProjectRoot = Path.Combine(callerExecutablePath, "../../..");
      
            // Combine projectRoot root with relative path from [CallerFilePath]
            return Path.Combine(testProjectRoot, path.Substring(determenisticRoot.Length));
        }
      

    【讨论】:

    • 感谢@Vladyslav 的想法。不幸的是,它可能给人一种可行的解决方案的印象,同时非常脆弱。现在,我最终在所有测试代码上禁用了确定性源路径 - 为我的场景提供了解决方法。那会是生产代码吗,应该重新设计/重新设计在运行时不需要构建时代码路径。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-03
    • 2015-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多