diff options
Diffstat (limited to 'src/Projects')
-rw-r--r-- | src/Projects/DotnetProject.cs | 38 | ||||
-rw-r--r-- | src/Projects/DotnetProjectDom.cs | 60 | ||||
-rw-r--r-- | src/Projects/LeafProject.cs | 37 | ||||
-rw-r--r-- | src/Projects/ModuleProject.cs | 118 | ||||
-rw-r--r-- | src/Projects/NativeProjectDom.cs | 57 |
5 files changed, 310 insertions, 0 deletions
diff --git a/src/Projects/DotnetProject.cs b/src/Projects/DotnetProject.cs new file mode 100644 index 0000000..5ee1ed0 --- /dev/null +++ b/src/Projects/DotnetProject.cs @@ -0,0 +1,38 @@ + +using System; +using System.IO; +using System.Threading.Tasks; + +using VNLib.Tools.Build.Executor.Model; + +namespace VNLib.Tools.Build.Executor.Projects +{ + + internal sealed class DotnetProject : ModuleProject + { + public override IProjectData ProjectData { get; } + + + public DotnetProject(FileInfo projectFile, string projectName):base(projectFile, projectName) + { + //Create the porject dom + ProjectData = new DotnetProjectDom(); + } + + ///<inheritdoc/> + public override async Task LoadAsync(TaskfileVars vars) + { + //Load project dom + await base.LoadAsync(vars); + + //Set .NET specific vars + TaskVars.Set("TARGET_FRAMEWORK", ProjectData["TargetFramework"] ?? string.Empty); + TaskVars.Set("PROJ_ASM_NAME", ProjectData["AssemblyName"] ?? string.Empty); + } + + public override string ToString() => ProjectName; + + public override void Dispose() + { } + } +}
\ No newline at end of file diff --git a/src/Projects/DotnetProjectDom.cs b/src/Projects/DotnetProjectDom.cs new file mode 100644 index 0000000..9b44747 --- /dev/null +++ b/src/Projects/DotnetProjectDom.cs @@ -0,0 +1,60 @@ + +using System; +using System.IO; +using System.Xml; +using System.Collections.Generic; + +using VNLib.Tools.Build.Executor.Model; + +namespace VNLib.Tools.Build.Executor.Projects +{ + + internal sealed class DotnetProjectDom : IProjectData + { + private readonly XmlDocument _dom; + + public DotnetProjectDom() + { + _dom = new(); + } + + public void Load(Stream stream) + { + _dom.Load(stream); + } + + private XmlNode? project => _dom["Project"]; + + public string? Description => GetProperty("Description"); + public string? Authors => GetProperty("Authors"); + public string? Copyright => GetProperty("Copyright"); + public string? VersionString => GetProperty("Version"); + public string? CompanyName => GetProperty("Company"); + public string? Product => GetProperty("Product"); + public string? RepoUrl => GetProperty("RepositoryUrl"); + + public string? this[string index] => GetProperty(index); + + public string? GetProperty(string name) => GetItemAtPath($"PropertyGroup/{name}"); + + public string? GetItemAtPath(string path) => project!.SelectSingleNode(path)?.InnerText; + + public string[] GetProjectRefs() + { + //Get the item group attr + XmlNodeList? projectRefs = project?.SelectNodes("ItemGroup/ProjectReference"); + + if (projectRefs != null) + { + List<string> refs = new(); + foreach (XmlNode projRef in projectRefs) + { + //Get the project ref via its include attribute + refs.Add(projRef.Attributes["Include"].Value!); + } + return refs.ToArray(); + } + return Array.Empty<string>(); + } + } +}
\ No newline at end of file diff --git a/src/Projects/LeafProject.cs b/src/Projects/LeafProject.cs new file mode 100644 index 0000000..9b155cf --- /dev/null +++ b/src/Projects/LeafProject.cs @@ -0,0 +1,37 @@ +using System.IO; +using System.Threading.Tasks; + +using VNLib.Tools.Build.Executor.Constants; +using VNLib.Tools.Build.Executor.Model; + +namespace VNLib.Tools.Build.Executor.Projects +{ + internal sealed class LeafProject(BuildConfig config, FileInfo projectFile) : ModuleProject(projectFile) + { + ///<inheritdoc/> + public override IProjectData ProjectData { get; } = new NativeProjectDom(); + + ///<inheritdoc/> + protected override FileInfo? PackageInfoFile => new(Path.Combine(WorkingDir.FullName, "package.json")); + + public override async Task LoadAsync(TaskfileVars vars) + { + await base.LoadAsync(vars); + + //Set the project name to the product name if set, otherwise use the working dir name + ProjectName = ProjectData.Product ?? WorkingDir.Name; + + //Get the binary dir from the project file, or use the default + string? binaryDir = ProjectData["output_dir"] ?? ProjectData["output"] ?? config.ProjectBinDir; + + //Overide the project name from the pacakge file if set + TaskVars.Set("PROJECT_NAME", ProjectName); + TaskVars.Set("BINARY_DIR", binaryDir); + } + + public override string ToString() => ProjectName; + + public override void Dispose() + { } + } +}
\ No newline at end of file diff --git a/src/Projects/ModuleProject.cs b/src/Projects/ModuleProject.cs new file mode 100644 index 0000000..4643aa0 --- /dev/null +++ b/src/Projects/ModuleProject.cs @@ -0,0 +1,118 @@ +using System; +using System.IO; +using System.Threading.Tasks; + +using VNLib.Tools.Build.Executor.Model; +using VNLib.Tools.Build.Executor.Extensions; + +namespace VNLib.Tools.Build.Executor.Projects +{ + internal abstract class ModuleProject : IProject + { + ///<inheritdoc/> + public FileInfo ProjectFile { get; } + + ///<inheritdoc/> + public string ProjectName { get; protected set; } + + ///<inheritdoc/> + public abstract IProjectData ProjectData { get; } + + ///<inheritdoc/> + public bool UpToDate { get; set; } + + ///<inheritdoc/> + public DirectoryInfo WorkingDir { get; protected set; } + + ///<inheritdoc/> + public TaskfileVars TaskVars { get; protected set; } + + ///<inheritdoc/> + public string? TaskfileName { get; protected set; } + + /// <summary> + /// Gets the package info file for the project + /// </summary> + protected virtual FileInfo? PackageInfoFile { get; } + + public ModuleProject(FileInfo projectFile, string? projectName = null) + { + ProjectFile = projectFile; + + //Default project name to the file name + ProjectName = projectName ?? Path.GetFileNameWithoutExtension(ProjectFile.Name); + + //Default up-to-date false + UpToDate = false; + + //Default working dir to the project file's directory + WorkingDir = ProjectFile.Directory!; + + TaskVars = null!; + } + + ///<inheritdoc/> + public virtual async Task LoadAsync(TaskfileVars vars) + { + TaskVars = vars; + + await LoadProjectDom(); + + //Set some local environment variables + + //Set local environment variables + TaskVars.Set("PROJECT_NAME", ProjectName); + TaskVars.Set("PROJECT_DIR", WorkingDir.FullName); + TaskVars.Set("IS_PROJECT", bool.TrueString); + + //Store project vars + TaskVars.Set("PROJ_VERSION", ProjectData.VersionString ?? string.Empty); + TaskVars.Set("PROJ_DESCRIPTION", ProjectData.Description ?? string.Empty); + TaskVars.Set("PROJ_AUTHOR", ProjectData.Authors ?? string.Empty); + TaskVars.Set("PROJ_COPYRIGHT", ProjectData.Copyright ?? string.Empty); + TaskVars.Set("PROJ_COMPANY", ProjectData.CompanyName ?? string.Empty); + TaskVars.Set("RPOJ_URL", ProjectData.RepoUrl ?? string.Empty); + + TaskVars.Set("SAFE_PROJ_NAME", this.GetSafeProjectName()); + } + + /// <summary> + /// Loads the project's XML dom from its msbuild project file + /// </summary> + /// <returns>A task that resolves when the dom is built</returns> + public async Task LoadProjectDom() + { + using MemoryStream ms = new(); + + FileInfo dom = ProjectFile; + + if (PackageInfoFile?.Exists == true) + { + dom = PackageInfoFile; + } + + try + { + //Get the project file + await using (FileStream projData = dom.OpenRead()) + { + await projData.CopyToAsync(ms); + } + + //reset stream + ms.Seek(0, SeekOrigin.Begin); + + //Load the project dom + ProjectData.Load(ms); + } + catch (Exception ex) + { + throw new Exception($"Failed to load project dom file {dom.FullName}", ex); + } + } + + public abstract void Dispose(); + + public override string ToString() => ProjectName; + } +}
\ No newline at end of file diff --git a/src/Projects/NativeProjectDom.cs b/src/Projects/NativeProjectDom.cs new file mode 100644 index 0000000..f23a4a5 --- /dev/null +++ b/src/Projects/NativeProjectDom.cs @@ -0,0 +1,57 @@ +using System; +using System.IO; +using System.Text.Json; +using System.Collections.Generic; + +using VNLib.Tools.Build.Executor.Model; + +namespace VNLib.Tools.Build.Executor.Projects +{ + internal sealed class NativeProjectDom : IProjectData + { + private Dictionary<string, string> _properties; + + internal NativeProjectDom() + { + _properties = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); + } + + public string? this[string index] => _properties.GetValueOrDefault(index); + + public string? Description => this["description"]; + public string? Authors => this["author"]; + public string? Copyright => this["copyright"]; + public string? VersionString => this["version"]; + public string? CompanyName => this["company"]; + public string? Product => this["name"]; + public string? RepoUrl => this["repository"]; + public string? OutputDir => this["output_dir"]; + + public string[] GetProjectRefs() + { + return Array.Empty<string>(); + } + + public void Load(Stream stream) + { + //Read the json file + using JsonDocument doc = JsonDocument.Parse(stream, new JsonDocumentOptions + { + CommentHandling = JsonCommentHandling.Skip, + AllowTrailingCommas = true, + }); + + //Clear old properties + _properties.Clear(); + + //Load new properties that are strings only + foreach (JsonProperty prop in doc.RootElement.EnumerateObject()) + { + if(prop.Value.ValueKind == JsonValueKind.String) + { + _properties[prop.Name] = prop.Value.GetString() ?? string.Empty; + } + } + } + } +}
\ No newline at end of file |