Skip to content
Closed

. #7

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 23 additions & 3 deletions CommandLineOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ public class CommandLineOptions
{
public string[] Projects { get; set; } = [];
public string[] Solutions { get; set; } = [];
public string[] DirsProjs { get; set; } = [];

public string? Project => Projects.Length == 1 ? Projects[0] : null;
public string? Solution => Solutions.Length == 1 ? Solutions[0] : null;
public string? DirsProj => DirsProjs.Length == 1 ? DirsProjs[0] : null;
public string Configuration { get; set; } = "Debug";
public string Platform { get; set; } = "x64";
public string? VsPath { get; set; }
Expand All @@ -33,6 +35,7 @@ public class CommandLineOptions
public bool EmitCCppProperties { get; set; }
public bool EmitDefaults { get; set; }
public bool MergeDefaults { get; set; }
public bool FollowProjectReferences { get; set; }
public Dictionary<string, string> MsBuildProperties { get; set; } = new(StringComparer.OrdinalIgnoreCase);
public Dictionary<string, string> MsBuildEnv { get; set; } = new(StringComparer.OrdinalIgnoreCase);
public string MsBuildLauncher { get; set; } = "auto";
Expand All @@ -54,6 +57,12 @@ public static CommandLineOptions Parse(string[] args)
AllowMultipleArgumentsPerToken = true
};

var dirsProjOption = new Option<string[]>("--dirs-proj")
{
Description = "Path to an MSBuild traversal dirs.proj (Sdk=\"Microsoft.Build.Traversal\"); recurses into nested dirs.proj and extracts every referenced .vcxproj. Can be specified multiple times.",
AllowMultipleArgumentsPerToken = true
};

var configOption = new Option<string>("--configuration", "-c")
{
Description = "Build configuration",
Expand Down Expand Up @@ -216,9 +225,16 @@ public static CommandLineOptions Parse(string[] args)
};
includePathOrderOption.AcceptOnlyFromAmong("auto", "prepend", "append");

var followProjectReferencesOption = new Option<bool>("--follow-project-references")
{
Description = "Also extract projects reachable via .vcxproj <ProjectReference> edges (transitive). Only plain relative references are followed; MSBuild-property references ($(..)) are skipped, so cross-tree/package references do not pull in the whole dependency graph. Useful for wrapper+Lib layouts where the referenced *Lib project carries the source.",
DefaultValueFactory = _ => false
};

var rootCommand = new RootCommand("Extract compile_commands.json from Visual C++ MSBuild projects");
rootCommand.Options.Add(projectOption);
rootCommand.Options.Add(solutionOption);
rootCommand.Options.Add(dirsProjOption);
rootCommand.Options.Add(configOption);
rootCommand.Options.Add(platformOption);
rootCommand.Options.Add(vsPathOption);
Expand Down Expand Up @@ -247,6 +263,7 @@ public static CommandLineOptions Parse(string[] args)
rootCommand.Options.Add(msbuildEnvOption);
rootCommand.Options.Add(msbuildLauncherOption);
rootCommand.Options.Add(includePathOrderOption);
rootCommand.Options.Add(followProjectReferencesOption);

rootCommand.Validators.Add(commandResult =>
{
Expand All @@ -256,9 +273,10 @@ public static CommandLineOptions Parse(string[] args)

var projects = commandResult.GetValue(projectOption) ?? [];
var solutions = commandResult.GetValue(solutionOption) ?? [];
var dirsProjs = commandResult.GetValue(dirsProjOption) ?? [];

if (projects.Length == 0 && solutions.Length == 0)
commandResult.AddError("At least one --project or --solution must be specified.");
if (projects.Length == 0 && solutions.Length == 0 && dirsProjs.Length == 0)
commandResult.AddError("At least one --project, --solution, or --dirs-proj must be specified.");

if (commandResult.GetValue(cCppPropertiesOption) && commandResult.GetValue(formatOption) == "rich")
commandResult.AddError("--c-cpp-properties cannot be used with --format rich (rich format does not produce compile_commands.json).");
Expand All @@ -270,6 +288,7 @@ public static CommandLineOptions Parse(string[] args)
{
Projects = parseResult.GetValue(projectOption) ?? [],
Solutions = parseResult.GetValue(solutionOption) ?? [],
DirsProjs = parseResult.GetValue(dirsProjOption) ?? [],
Configuration = parseResult.GetValue(configOption)!,
Platform = parseResult.GetValue(platformOption)!,
VsPath = parseResult.GetValue(vsPathOption),
Expand Down Expand Up @@ -297,7 +316,8 @@ public static CommandLineOptions Parse(string[] args)
MsBuildProperties = ParseKeyValuePairs(parseResult.GetValue(msbuildPropertyOption), "--msbuild-property"),
MsBuildEnv = ParseKeyValuePairs(parseResult.GetValue(msbuildEnvOption), "--msbuild-env"),
MsBuildLauncher = parseResult.GetValue(msbuildLauncherOption)!,
IncludePathOrder = parseResult.GetValue(includePathOrderOption)!
IncludePathOrder = parseResult.GetValue(includePathOrderOption)!,
FollowProjectReferences = parseResult.GetValue(followProjectReferencesOption)
};
});

Expand Down
28 changes: 27 additions & 1 deletion InProcessExtractor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1069,10 +1069,36 @@ private string ResolveToolPath(string toolPath)
public static List<CompileCommand> ExtractCompileCommandsFromSolution(
string solutionPath, string configuration = "Debug", string platform = "x64",
bool enableLogger = false, string? vcToolsInstallDir = null,
bool emitDefaults = false, bool mergeDefaults = false)
bool emitDefaults = false, bool mergeDefaults = false, bool followProjectReferences = false)
{
var solutionDir = Path.GetDirectoryName(Path.GetFullPath(solutionPath))!;
var projects = ProjectDiscovery.GetVcProjectsFromSolution(solutionPath);
return ExtractCompileCommandsFromProjects(
projects, solutionDir, configuration, platform, enableLogger,
vcToolsInstallDir, emitDefaults, mergeDefaults, followProjectReferences);
}

public static List<CompileCommand> ExtractCompileCommandsFromDirsProj(
string dirsProjPath, string configuration = "Debug", string platform = "x64",
bool enableLogger = false, string? vcToolsInstallDir = null,
bool emitDefaults = false, bool mergeDefaults = false, bool followProjectReferences = false)
{
// The dirs.proj directory plays the same role as SolutionDir for $(SolutionDir).
var baseDir = Path.GetDirectoryName(Path.GetFullPath(dirsProjPath))!;
var projects = ProjectDiscovery.GetVcProjectsFromDirsProj(dirsProjPath);
return ExtractCompileCommandsFromProjects(
projects, baseDir, configuration, platform, enableLogger,
vcToolsInstallDir, emitDefaults, mergeDefaults, followProjectReferences);
}

public static List<CompileCommand> ExtractCompileCommandsFromProjects(
List<VcProject> projects, string? solutionDir, string configuration, string platform,
bool enableLogger, string? vcToolsInstallDir, bool emitDefaults, bool mergeDefaults,
bool followProjectReferences = false)
{
if (followProjectReferences)
projects = ProjectDiscovery.ExpandWithProjectReferences(projects);

var allCommands = new List<CompileCommand>();

foreach (var project in projects)
Expand Down
43 changes: 42 additions & 1 deletion OutOfProcessExtractor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1126,10 +1126,51 @@ public static List<CompileCommand> ExtractCompileCommandsFromSolution(
MsBuildLauncher launcher = MsBuildLauncher.Auto,
IncludePathOrder includePathOrder = IncludePathOrder.Auto,
bool emitDefaults = false,
bool mergeDefaults = false)
bool mergeDefaults = false,
bool followProjectReferences = false)
{
var solutionDir = Path.GetDirectoryName(Path.GetFullPath(solutionPath))!;
var projects = ProjectDiscovery.GetVcProjectsFromSolution(solutionPath);
return ExtractCompileCommandsFromProjects(
msbuildPath, projects, solutionDir, configuration, platform, enableLogger,
vcToolsInstallDir, vcTargetsPath, clPath, msbuildProperties, msbuildEnv,
launcher, includePathOrder, emitDefaults, mergeDefaults, followProjectReferences);
}

public static List<CompileCommand> ExtractCompileCommandsFromDirsProj(
string msbuildPath, string dirsProjPath, string configuration = "Debug",
string platform = "x64", bool enableLogger = false,
string? vcToolsInstallDir = null, string? vcTargetsPath = null,
string? clPath = null,
IReadOnlyDictionary<string, string>? msbuildProperties = null,
IReadOnlyDictionary<string, string>? msbuildEnv = null,
MsBuildLauncher launcher = MsBuildLauncher.Auto,
IncludePathOrder includePathOrder = IncludePathOrder.Auto,
bool emitDefaults = false,
bool mergeDefaults = false,
bool followProjectReferences = false)
{
// The dirs.proj directory plays the same role as SolutionDir for $(SolutionDir).
var baseDir = Path.GetDirectoryName(Path.GetFullPath(dirsProjPath))!;
var projects = ProjectDiscovery.GetVcProjectsFromDirsProj(dirsProjPath);
return ExtractCompileCommandsFromProjects(
msbuildPath, projects, baseDir, configuration, platform, enableLogger,
vcToolsInstallDir, vcTargetsPath, clPath, msbuildProperties, msbuildEnv,
launcher, includePathOrder, emitDefaults, mergeDefaults, followProjectReferences);
}

public static List<CompileCommand> ExtractCompileCommandsFromProjects(
string msbuildPath, List<VcProject> projects, string? solutionDir,
string configuration, string platform, bool enableLogger,
string? vcToolsInstallDir, string? vcTargetsPath, string? clPath,
IReadOnlyDictionary<string, string>? msbuildProperties,
IReadOnlyDictionary<string, string>? msbuildEnv,
MsBuildLauncher launcher, IncludePathOrder includePathOrder,
bool emitDefaults, bool mergeDefaults, bool followProjectReferences = false)
{
if (followProjectReferences)
projects = ProjectDiscovery.ExpandWithProjectReferences(projects);

var allCommands = new List<CompileCommand>();

foreach (var project in projects)
Expand Down
Loading
Loading