@halospv3/hce.shared-config
Version:
Automate commit message quality, changelogs, and CI/CD releases. Its `main` entry point is a Semantic Release config. Functions and classes are exposed for customization. An ESLint config, a Commitlint config, and addl. resources for .NET projects are als
515 lines (514 loc) • 23.9 kB
JavaScript
import _debug from "../debug.mjs";
import { CaseInsensitiveMap } from "../CaseInsensitiveMap.mjs";
import { isError } from "../utils/isError.mjs";
import { execAsync } from "../utils/execAsync.mjs";
import { MSBuildProjectProperties } from "./MSBuildProjectProperties.mjs";
import { NPPGetterNames, NugetProjectProperties } from "./NugetProjectProperties.mjs";
import { warn } from "node:console";
import { type } from "arktype";
import path from "node:path";
import { hash } from "node:crypto";
import { readdir, realpath, stat } from "node:fs/promises";
import { tmpdir } from "node:os";
import { setTimeout } from "node:timers/promises";
//#region src/dotnet/MSBuildProject.ts
const debug_MSBP = _debug.extend("MSBuildProject");
debug_MSBP.enabled = _debug.enabled;
const debug_MSBP_PPTMSBP = debug_MSBP.extend("PackableProjectsToMSBuildProjects");
debug_MSBP_PPTMSBP.enabled = _debug.enabled;
const debug_MSBP_Evaluate = debug_MSBP.extend("Evaluate");
debug_MSBP_Evaluate.enabled = _debug.enabled;
const temporaryDirectoryNamespace = path.join(tmpdir(), "HCE.Shared", ".NET");
/**
* See [MSBuild well-known item metadata](https://learn.microsoft.com/en-us/visualstudio/msbuild/msbuild-well-known-item-metadata).
* Additional string-type properties may be present (e.g. `{ SubType: "designer" }`).
*/
const interface_ItemMetadataBuiltIn = type({
"[string]": "string",
/** @example "c:\\source\\repos\\ConsoleApp1\\ConsoleApp1\\bin\\Debug\\net6.0\\ConsoleApp1.dll" */
Identity: "string",
/** @example "Designer" */
"SubType?": "string",
/** @example ".NETCoreApp" */
"TargetFrameworkIdentifier?": "string",
"TargetPlatformMoniker?": "string",
/** @example "c:\\source\\repos\\ConsoleApp1\\ConsoleApp1\\obj\\Debug\\net6.0\\ConsoleApp1.csproj.CopyComplete" */
"CopyUpToDateMarker?": "string",
"TargetPlatformIdentifier?": "string",
/** @example "6.0" */
"TargetFrameworkVersion?": "string",
/** @example "c:\\source\\repos\\ConsoleApp1\\ConsoleApp1\\obj\\Debug\\net6.0\\ref\\ConsoleApp1.dll" */
"ReferenceAssembly?": "string",
/** @example "c:\\source\\repos\\ConsoleApp1\\ConsoleApp1\\bin\\Debug\\net6.0\\ConsoleApp1.dll" */
FullPath: "string",
/** @example "c:\\" */
RootDir: "string",
/** @example "ConsoleApp1" */
Filename: "string",
/** @example ".dll" */
Extension: "string",
/** @example "c:\\source\\repos\\ConsoleApp1\\ConsoleApp1\\bin\\Debug\\net6.0\\" */
RelativeDir: "string",
/** @example "source\\repos\\ConsoleApp1\\ConsoleApp1\\bin\\Debug\\net6.0\\" */
Directory: "string",
RecursiveDir: "string",
/** @example "2023-11-30 13:38:06.5084339" */
ModifiedTime: "string",
/** @example "2023-11-30 13:38:06.9308716" */
CreatedTime: "string",
/** @example "2023-11-30 13:38:06.9318732" */
AccessedTime: "string",
/** @example "C:\\Program Files\\Microsoft Visual Studio\\2022\\Preview\\MSBuild\\Current\\Bin\\amd64\\Microsoft.Common.CurrentVersion.targets" */
DefiningProjectFullPath: "string",
/** @example "C:\\Program Files\\Microsoft Visual Studio\\2022\\Preview\\MSBuild\\Current\\Bin\\amd64\\" */
DefiningProjectDirectory: "string",
/** @example "Microsoft.Common.CurrentVersion" */
DefiningProjectName: "string",
/** @example ".targets" */
DefiningProjectExtension: "string"
});
const targetSuccess = type({
Result: "'Success'",
Items: interface_ItemMetadataBuiltIn.array()
});
const targetFailure = type({
Result: "'Failure'",
Items: "never[]"
});
const msbuildEvaluationOutput = type({
"Properties?": type({ "[string]": "string" }),
"Items?": type({ "[string]": interface_ItemMetadataBuiltIn.array() }),
"TargetResults?": type({ "[string]": targetSuccess.or(targetFailure) })
});
var MSBuildEvaluationOutput = class {
/**
* The specified properties and their values as evaluated by MSBuild Core.
* `-getProperty:{propertyName,...}`
*/
Properties;
/**
* The specified items and their values and associated metadata as evaluated
* by MSBuild Core.
* `-getItem:{itemName,...}`
*/
Items;
/**
* The specified Targets and their output values as evaluated by MSBuild
* Core.
* `-getTargetResult:{targetName,...}`
*/
TargetResults;
/**
* @param rawMSBuildEvaluation The output of a CLI MSBuild project evaluation.
* May be the UTF-8 string-encoded JSON or the object decoded from that JSON.
*/
constructor(rawMSBuildEvaluation) {
/** `.assert` instead of `.from` to allow `unknown` JSON.parse return type */
const knownObject = msbuildEvaluationOutput.assert(typeof rawMSBuildEvaluation === "string" ? JSON.parse(rawMSBuildEvaluation) : rawMSBuildEvaluation);
this.Properties = knownObject.Properties;
this.Items = knownObject.Items;
this.TargetResults = knownObject.TargetResults;
}
};
const EvaluationOptions = Object.freeze(type({
/**
* The project file's full path.
*/
FullName: "string",
/**
* User-defined Properties and their values.
* { Configuration: "Release" } will cause the MSBuild to first set the
* Configuration property to Release before evaluating the project
* or the project's Target(s).
* ```txt
* -property:<n>=<v> Set or override these project-level properties. <n> is
* the property name, and <v> is the property value. Use a
* semicolon or a comma to separate multiple properties, or
* specify each property separately. (Short form: -p)
* Example:
* -property:WarningLevel=2;OutDir=bin\Debug\
* ```
*/
Property: type({ "[string]": "string" }).as().partial(),
/**
* The MSBuild Targets to run for evaluation. ["Pack"] is recommended.
* Property values may be changed by Targets such as those provided by
* dependencies.
*
* ```txt
* -target:<targets> Build these targets in this project. Use a semicolon or a
* comma to separate multiple targets, or specify each
* target separately. (Short form: -t)
* Example:
* -target:Resources;Compile
* ```
* @default []
*/
Targets: type.string.array().readonly().or("string[]"),
/**
* MSBuild Items to evaluate. `["Compile"]` will result in the MSBuild output
* including {@link MSBuild}
*/
GetItem: type.string.array().readonly().or("string[]"),
GetProperty: type.string.array().readonly().or("string[]"),
GetTargetResult: type.string.array().readonly().or("string[]")
}));
var MSBuildProject = class MSBuildProject {
/**
* Properties for multi-targeting `dotnet publish` outputs.
* These are included in {@link NPPGetterNames.InstanceGettersRecursive}.
*/
static MatrixProperties = Object.freeze([
"TargetFramework",
"TargetFrameworks",
"RuntimeIdentifier",
"RuntimeIdentifiers"
]);
/**
* @param projectPath The full path of the project file or its directory. A
* relative path may be passed, but will resolve relative to the current
* working directory.
* @param includeNonPublic Include conventionally internal/private MSBuild
* targets in the result.
* @returns A string array of the project's MSBuild targets.
* @todo consider 'file' of -targets[:file]
* Prints a list of available targets without executing the
* actual build process. By default the output is written to
* the console window. If the path to an output file
* is provided that will be used instead.
* (Short form: -ts)
* Example:
* -ts:out.txt
*/
static async GetTargets(projectPath, includeNonPublic = false) {
const targets = (await execAsync(`dotnet msbuild ${projectPath} -targets`, true)).stdout.split("\n").filter((v, index) => v !== "" && index !== 0).map((v) => v.replaceAll("\r", "")).sort((a, b) => a.localeCompare(b));
return includeNonPublic ? targets : targets.filter((v) => !v.startsWith("_"));
}
/**
* Evaluate {@link Items}, {@link Properties}, and {@link TargetResults},
* returning them as an instance of {@link MSBuildProject}.\
* Note: MSBuild will probably fail if Restore is skipped and another
* target is specified. If you choose Pack, you must do ['Restore', 'Pack'].
* @param options The result of {@link EvaluationOptions.from}.
* @returns A promised {@link MSBuildProject} instance.
* @throws {Error} if the exec command fails -OR- the JSON parse fails -OR-
* MSBuildProject's constructor fails.
* @see {@link PackableProjectsToMSBuildProjects} for most use-cases.
*/
static async Evaluate(options) {
if (options.GetProperty.length === 0 && options.GetItem.length === 0 && options.GetTargetResult.length === 0) throw new Error("No MSBuild Property, Item, or TargetResult queries were provided.");
const shortHashName = `options_SHA3-256_${hash("SHA3-256", JSON.stringify(options)).slice(0, 7)}`;
const debug_MSBP_Evaluate_hashed = debug_MSBP_Evaluate.extend(shortHashName);
debug_MSBP_Evaluate_hashed.enabled = _debug.enabled;
/** Update {@link typeof_ArtifactsPath} if this changes */
options.Property.ArtifactsPath = path.join(temporaryDirectoryNamespace, path.basename(options.FullName, path.extname(options.FullName)), shortHashName) + "/";
options.FullName = MSBuildProjectProperties.GetFullPath(options.FullName);
options.Property.GeneratePackageOnBuild = "false";
const _pairs = Object.entries(options.Property).filter((p) => typeof p[1] === "string");
const string_target = options.Targets.length === 0 ? "" : `"-t:${options.Targets.join(";")}"`;
const string_getItem = options.GetItem.length === 0 ? "" : `"-getItem:${options.GetItem.join(",")}"`;
const string_getProperty = options.GetProperty.length === 0 ? "" : `"-getProperty:${options.GetProperty.join(",")}"`;
const string_getTargetResult = options.GetTargetResult.length === 0 ? "" : `"-getTargetResult:${options.GetTargetResult.join(",")}"`;
const string_property_array = _pairs.map(([key, value]) => `"-p:${key}=${value}"`);
const isTargetPack = string_target.toLocaleLowerCase().replaceAll("\"", "") == `-t:pack`;
const output = await loopTryDotnetCommand({
commandLine: [
"dotnet",
isTargetPack ? "pack" : "msbuild",
`"${options.FullName}"`,
"-restore",
isTargetPack ? "" : string_target,
string_getItem,
string_getProperty,
string_getTargetResult,
...string_property_array
].filter((v) => v !== "").join(" "),
customDebugger: debug_MSBP_Evaluate_hashed,
projectName: path.basename(options.FullName, path.extname(options.FullName)),
taskVerb: "evaluate",
timeoutMilliseconds: 36e4
});
/**
* The following issues have triggered this code path:
* - BaseIntermediateOutputPath must use Unix path separators ('/') on all
* platforms. Even Windows. Otherwise, MSBuild/dotnet will error-exit with
* "The BaseIntermediateOutputPath must end with a trailing slash".
*/
if (output.stdout.startsWith("MSBuild version")) {
warn(output.stdout);
throw new Error("dotnet msbuild was expected to output JSON, but output its version header instead.");
}
let rawOutput;
if (output.stdout.startsWith("{"))
/** stdout is JSON string */
rawOutput = output.stdout;
else if (options.GetProperty.length > 0 && options.GetProperty[0] !== void 0) rawOutput = { Properties: { [options.GetProperty[0]]: String(JSON.parse(output.stdout)) } };
else throw new Error("Dotnet/MSBuild evaluation output is not a string nor JSON object or array.");
const evaluation = new MSBuildEvaluationOutput(rawOutput);
debug_MSBP_Evaluate_hashed(`Getting MSBuild Targets of "${options.FullName}"...`);
const projTargets = await this.GetTargets(options.FullName);
debug_MSBP_Evaluate_hashed(`Returning new MSBuildProject instance for "${options.FullName}"...`);
return new MSBuildProject({
fullPath: options.FullName,
projTargets,
evaluation
});
}
/**
* Evaluate multiple project paths with some default Evaluate options.
* @async
* @param projectsToPackAndPush An array of MSBuild projects' full file
* paths. If a path is a directory, files in that directory are filtered for
* `.csproj`, `.fsproj`, and `.vbproj` project files.
* See https://github.com/dotnet/sdk/blob/497f334b2862bdf98b30c00ede2fd259ea5f624d/src/Cli/dotnet/Commands/New/MSBuildEvaluation/MSBuildEvaluationResult.cs#L19-L32.\
* @returns A promised array of {@link MSBuildProject} instances.
* All known MSBuild and NuGet properties are evaluated.
* If applicable, a project's "Pack" target is evaluated.
*/
static async PackableProjectsToMSBuildProjects(projectsToPackAndPush) {
debug_MSBP_PPTMSBP("Mapping projects to Dirent instances...");
const directoryEntriesPromise = await toDirectoryEntries(typeof projectsToPackAndPush === "string" ? [projectsToPackAndPush] : projectsToPackAndPush);
debug_MSBP_PPTMSBP("Converting Dirent instances to MSBuildProject instances...");
return directoryEntriesPromise.map((element) => convertDirentToMSBuildProject(element));
/**
* Map an array of filesystem paths to {@link Dirent} instances representing project files.
* @param projectsToPackAndPush An array of MSBuild projects' full file
* paths. If a path is a directory, files in that directory are filtered for
* `.csproj`, `.fsproj`, and `.vbproj` project files. See
* https://github.com/dotnet/sdk/blob/497f334b2862bdf98b30c00ede2fd259ea5f624d/src/Cli/dotnet/Commands/New/MSBuildEvaluation/MSBuildEvaluationResult.cs#L19-L32.\
* @returns An promised array of Dirent instances for discovered project files.
*/
async function toDirectoryEntries(projectsToPackAndPush) {
return (await Promise.all(projectsToPackAndPush.map(async (proj) => {
debug_MSBP_PPTMSBP(`Getting absolute path of "${proj}"...`);
proj = await realpath(makeAbsolute(proj));
debug_MSBP_PPTMSBP(`Getting filesystem stats of "${proj}"...`);
const stats = await stat(proj);
let entries;
if (stats.isFile()) {
debug_MSBP_PPTMSBP(`"${proj}" is a file. Returning Dirent instance...`);
entries = await readdir(path.dirname(proj), { withFileTypes: true });
const dirent = entries.find((v) => path.join(("path" in v ? v.path : void 0) ?? v.parentPath, v.name) === proj);
if (dirent) return dirent;
throw new Error(`file "${proj}" not found. It may have been moved or deleted.`);
}
if (!stats.isDirectory()) throw new Error(`"${proj}" is not a file or directory`);
debug_MSBP_PPTMSBP(`"${proj}" is a directory. Searching for files ending with ".csproj", ".fsproj", or ".vbproj"...`);
entries = await readdir(proj, { withFileTypes: true });
return entries.filter((v) => v.isFile() && (v.name.endsWith(".csproj") || v.name.endsWith(".fsproj") || v.name.endsWith(".vbproj")));
}))).flat();
}
/**
* Map a {@link Dirent} instance to an {@link MSBuildProject} instance.
* @param dirent A {@link Dirent} instance. This instance should be an MSBuild project file.
* @returns An instance of {@link MSBuildProject} evaluated with the `Pack` target result, if applicable. Evaluated properties will be those whose names are returned by {@link NPPGetterNames.InstanceGettersRecursive}.
*/
async function convertDirentToMSBuildProject(dirent) {
const fullPath = path.join(("path" in dirent ? dirent.path : void 0) ?? dirent.parentPath, dirent.name);
debug_MSBP_PPTMSBP(`Getting MSBuild targets of "${fullPath}"...`);
const evalTargets = (await MSBuildProject.GetTargets(fullPath)).includes("Pack") ? ["Pack"] : [];
const propertiesToEvaluate = NPPGetterNames.InstanceGettersRecursive;
const withTargets = evalTargets.length === 0 ? "" : ` with target(s) ${evalTargets.join(", ").replace(/, ([^,]+)$/, ", and ${0}")}`;
debug_MSBP_PPTMSBP(`Evaluating "${fullPath}" for properties${withTargets}...`);
return await MSBuildProject.Evaluate(EvaluationOptions.from({
FullName: fullPath,
GetItem: [],
GetProperty: propertiesToEvaluate,
GetTargetResult: [],
Property: {},
Targets: evalTargets
}));
}
}
static fromJSON(json) {
const parsed = T_PseudoMSBPInstance.assert(JSON.parse(json));
type.true.assert(Reflect.setPrototypeOf(parsed, this.prototype));
type.true.assert(Reflect.setPrototypeOf(parsed.Properties, NugetProjectProperties.prototype));
parsed.Properties = T_NPP.assert(parsed.Properties);
return T_MSBuildProject.assert(parsed);
}
Items;
Properties;
Targets;
/**
* Allows appending subsequent target results.
*/
TargetResults;
/**
* Creates an instance of MSBuildProject.
* @param opts The order-independent arguments for this constructor.
* Properties may be added or moved around in this definition without
* breaking compatibility.
* @param opts.fullPath The full path of the MSBuild project's file. This
* should have a '.csproj', '.fsproj', or '.vbproj' file extension.
* @param opts.projTargets A list of MSBuild Targets supported by the project.
* @param opts.evaluation The output of an MSBuild project evaluation. This
* comprises MSBuild Properties, Items, and Target results.
*/
constructor(opts) {
this.Items = opts.evaluation.Items ?? {};
this.Properties = new NugetProjectProperties(opts.fullPath, new CaseInsensitiveMap(Object.entries(opts.evaluation.Properties ?? {})));
this.Targets = opts.projTargets;
this.TargetResults = opts.evaluation.TargetResults === void 0 ? [] : [opts.evaluation.TargetResults];
}
};
const T_MSBuildProject = type.instanceOf(MSBuildProject);
const T_NPP = type.instanceOf(NugetProjectProperties);
const T_PseudoMSBPInstance = type({
Items: type({ "[string]": type({
"[string]": "string",
Identity: "string",
FullPath: "string",
RootDir: "string",
Filename: "string",
Extension: "string",
RelativeDir: "string",
Directory: "string",
RecursiveDir: "string",
ModifiedTime: "string",
CreatedTime: "string",
AccessedTime: "string",
DefiningProjectFullPath: "string",
DefiningProjectDirectory: "string",
DefiningProjectName: "string",
DefiningProjectExtension: "string",
"SubType?": " string | undefined",
"TargetFrameworkIdentifier?": "string | undefined",
"TargetPlatformMoniker?": "string | undefined",
"CopyUpToDateMarker?": "string | undefined",
"TargetPlatformIdentifier?": "string | undefined",
"TargetFrameworkVersion?": "string | undefined",
"ReferenceAssembly?": "string | undefined"
}).array() }),
Properties: type.Record("string", "string").or(T_NPP),
Targets: type.string.array(),
TargetResults: msbuildEvaluationOutput.get("TargetResults").exclude("undefined").array()
});
/**
* ArkType type definitions for internal usage, but may be re-used elsewhere
* @internal
*/
const _InternalMSBuildEvaluationTypes = type.scope({ msbuildEvaluationOutput });
/**
* Resolve a path if it is not already absolute.
* @param _path A filesystem path.
* @returns A full path to a filesystem entry. The path is unchecked for whether or not the path (or its parts) exist.
*/
function makeAbsolute(_path) {
return path.isAbsolute(_path) ? _path : path.resolve(_path);
}
/**
* Use this in your catch statement or .catch call to return `undefined` when
* a "file in use by another process" (i.e. EBUSY/ERROR_SHARING_VIOLATION) error is reported.
* @param error Probably an Error object
* @returns `undefined` if file in use by another process
*/
function catchEBUSY(error) {
if (isError(error)) {
if ("stderr" in error && typeof error.stderr === "string") {
const normalizedStderr = error.stderr.normalize("NFKC");
const hasErrorMessagePattern = /The process cannot access the file '[^']+' because it is being used by another process\./gm.test(normalizedStderr);
const isCS2012 = /^CSC ?:.+CS2012:/gm.test(normalizedStderr);
const isAVLN9999 = /AVLN9999:/gm.test(normalizedStderr) && hasErrorMessagePattern;
if (isCS2012 || isAVLN9999 || hasErrorMessagePattern) return void 0;
throw error;
}
/**
* some known warnings/errors:
* - warning MSB3073:
* The command "dotnet tool list kuinox.nupkgdeterministicator"
* exited with code 145.
* > $ dotnet tool list kuinox.nupkgdeterministicator
* > The command could not be loaded, possibly because:
* > * You intended to execute a .NET application:
* > The application 'tool' does not exist.
* > * You intended to execute a .NET SDK command:
* > No .NET SDKs were found.
* >
* > Download a .NET SDK:
* > https://aka.ms/dotnet/download
* >
* > Learn about SDK resolution:
* > https://aka.ms/dotnet/sdk-not-found
*/
throw error;
}
throw new Error("unknown error", { cause: error });
}
/**
*
* Use this in your catch statement or .catch call to return `undefined` when
* MSBuild error CSC2012 (e.g. "file in use by another process") is reported.
* @param error Probably an Error object
* @returns `undefined` if CSC2012 (file in use by another process) occurs
* @deprecated Use {@link catchEBUSY}.
*/
function catchCsc2012(error) {
if (isError(error)) {
if ("stderr" in error && typeof error.stderr === "string" && /^CSC ?:.+CS2012:/gm.test(error.stderr.normalize("NFKC"))) return;
/**
* some known warnings/errors:
* - warning MSB3073:
* The command "dotnet tool list kuinox.nupkgdeterministicator"
* exited with code 145.
* > $ dotnet tool list kuinox.nupkgdeterministicator
* > The command could not be loaded, possibly because:
* > * You intended to execute a .NET application:
* > The application 'tool' does not exist.
* > * You intended to execute a .NET SDK command:
* > No .NET SDKs were found.
* >
* > Download a .NET SDK:
* > https://aka.ms/dotnet/download
* >
* > Learn about SDK resolution:
* > https://aka.ms/dotnet/sdk-not-found
*/
throw error;
}
throw new Error("unknown error", { cause: error });
}
/**
*
* @returns A Promise of execAsync's output object.
* @param root0 structured parameters object
* @param root0.commandLine The command line to try and retry
* @param root0.taskVerb Used in debug messages e.g. ```
* const debug_MSBP = debug.extend('MSBuildProject');
* debug_MSBP.enabled = debug.enabled;
* const output = await loopTryDotnetCommand({ customDebugger: debug_MSBP, ... });
* ```
* @param root0.customDebugger e.g. `debug.extend('Evaluate)`
* @param root0.projectName The filename (sans extension) or AssemblyName of the project e.g. `path.basename(fullPath, path.extname(fullPath))`
* @param root0.timeoutMilliseconds The maximum time spent (re)trying the command.
* Warning! {@link totalMilliseconds} may be significantly greater than {@link timeoutMilliseconds}!
* e.g.
* `325_000 <=300_000` (5m25s vs 5m)
* `378_000 <=360_000` (6m18s vs 6m),
* `630_000 <=600_000` (10m30s vs 10m)
* `1225_000 <=1200_000` (20m25s vs 20m)
* `2415_000 <=2400_000` (40m15s vs 40m)
* `2556_000 <=2485_000` (42m36s vs 41m25s; 71 seconds over)
* @throws {Error} when retry limit is reached or an unhandled exception occurs.
* File-in-use errors are _supposed_ to be ignored and retried.
*/
async function loopTryDotnetCommand({ commandLine, customDebugger, projectName, taskVerb, timeoutMilliseconds: maximumTime }) {
let output;
let totalMilliseconds = 0;
let delay = 0;
taskVerb ??= "<undefined>";
customDebugger(`Beginning try/retry loop to ${taskVerb} "${projectName}"...`);
while (output === void 0) try {
await setTimeout(delay, void 0);
output = await execAsync(commandLine, true);
} catch (error) {
if (totalMilliseconds > maximumTime) throw new Error(`Unable to ${taskVerb} "${projectName}": Retry limit hit. ~${(totalMilliseconds / 1e3).toString()} seconds spent retrying.`, { cause: error });
catchEBUSY(error);
totalMilliseconds += delay += 1e3;
customDebugger(`A file needed by "${projectName}" is locked by another process. Retrying after ${(delay / 1e3).toString()} seconds...`);
}
return output;
}
//#endregion
export { EvaluationOptions, MSBuildEvaluationOutput, MSBuildProject, _InternalMSBuildEvaluationTypes, catchCsc2012, catchEBUSY, loopTryDotnetCommand };
//# sourceMappingURL=MSBuildProject.mjs.map