Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Targets improvements #175

Merged
merged 7 commits into from
Jan 23, 2024
Merged
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
20 changes: 10 additions & 10 deletions Mono.TextTemplating.Build/Mono.TextTemplating.Build.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net48;net6.0</TargetFrameworks>
Expand All @@ -14,15 +14,15 @@
<PackageReadmeFile>readme.md</PackageReadmeFile>
</PropertyGroup>

<Target Name="AddTargetsFilesToPack" BeforeTargets="GenerateNuspec">
<ItemGroup>
<_PackageFiles Include="T4.BuildTools.props" PackagePath="build\$(PackageId).props" Pack="true" />
<_PackageFiles Include="T4.BuildTools.targets" PackagePath="build\$(PackageId).targets" Pack="true" />
<_PackageFiles Include="multitargeting.props" PackagePath="buildMultiTargeting\$(PackageId).props" Pack="true" />
<_PackageFiles Include="multitargeting.targets" PackagePath="buildMultiTargeting\$(PackageId).targets" Pack="true" />
<_PackageFiles Include="T4.BuildTools.targets.buildschema.json" PackagePath="build\$(PackageId).targets.buildschema.json" Pack="true" />
</ItemGroup>
</Target>
<ItemGroup>
<None Update="T4.BuildTools.props" PackagePath="build\$(PackageId).props" Pack="true" />
<None Update="T4.BuildTools.targets" PackagePath="build\$(PackageId).targets" Pack="true" />
<None Update="multitargeting.props" PackagePath="buildMultiTargeting\$(PackageId).props" Pack="true" />
<None Update="multitargeting.targets" PackagePath="buildMultiTargeting\$(PackageId).targets" Pack="true" />
<None Update="T4.BuildTools.targets.buildschema.json" PackagePath="build\$(PackageId).targets.buildschema.json" Pack="true" />
<None Update="T4PropertyPage.xaml" PackagePath="build\T4PropertyPage.xaml" Pack="true" />
<None Update="T4PropertySchema.xaml" PackagePath="build\T4PropertyPageSchema.xaml" Pack="true" />
</ItemGroup>

<Target Name="AddCopyLocalToPack" BeforeTargets="_GetBuildOutputFilesWithTfm" DependsOnTargets="ReferenceCopyLocalPathsOutputGroup">
<ItemGroup>
Expand Down
29 changes: 18 additions & 11 deletions Mono.TextTemplating.Build/T4.BuildTools.props
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
<Project>
<PropertyGroup>
<TransformOnBuild Condition="'$(TransformOnBuild)'==''">false</TransformOnBuild>
<TransformOutOfDateOnly Condition="'$(TransformOutOfDateOnly)'==''">true</TransformOutOfDateOnly>
</PropertyGroup>

<!-- hide T4 key/value pairs and other non-file items from the solution tree -->
<ItemDefinitionGroup>
<!-- hide T4 key/value pairs and other non-file items from the solution tree -->
<T4ParameterValues>
<Visible>False</Visible>
</T4ParameterValues>
Expand All @@ -24,18 +19,30 @@
<T4AssemblyReference>
<Visible>False</Visible>
</T4AssemblyReference>
<!-- transform on save in VS -->
</ItemDefinitionGroup>

<!-- transform on save in VS -->
<ItemDefinitionGroup>
<T4Transform>
<Generator>MSBuild:TransformAll</Generator>
<Generator>MSBuild:TransformTemplates</Generator>
</T4Transform>
<T4Preprocess>
<Generator>MSBuild:TransformAll</Generator>
<Generator>MSBuild:TransformTemplates</Generator>
</T4Preprocess>
</ItemDefinitionGroup>

<!-- make these items show up as a build action in VS -->
<!--
Make these items show up as a build action in VS.
The PropertyPageSchema also seems to be necessary to make Generator metadata work.
-->
<ItemGroup>
<AvailableItemName Include="T4Transform" />
<PropertyPageSchema Include="$(MSBuildThisFileDirectory)T4PropertyPage.xaml">
<Context>Project</Context>
</PropertyPageSchema>
<PropertyPageSchema Include="$(MSBuildThisFileDirectory)T4PropertySchema.xaml">
<Context>File;BrowseObject</Context>
</PropertyPageSchema>
<AvailableItemName Include="T4Preprocess" />
<AvailableItemName Include="T4Transform" />
</ItemGroup>
</Project>
37 changes: 22 additions & 15 deletions Mono.TextTemplating.Build/T4.BuildTools.targets.buildschema.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
}
},
"T4Argument": {
"description": "T4 template argument, optionally scoped to a directive and/or directive processor. The value, processor and directive may be provided using the `Value, `Processor` and `Directive metadata, or encoded into the `Include` with the syntax `name=value`, `directive!name!value` or `processor!directive!name!value`.",
"description": "T4 template argument, optionally scoped to a directive and/or directive processor. The value, processor and directive may be provided using the `Value, `Processor` and `Directive metadata, or encoded into the `Include` with the format `name=value`, `directive!name!value` or `processor!directive!name!value`.",
"includeDescription": "T4 argument name",
"metadata": {
"Value": "The T4 argument value. Overrides any value encoded in the `Include`.",
Expand Down Expand Up @@ -55,15 +55,15 @@
"type": "file"
},
"T4RequiredAssemblies": {
"description": "After running the TransformTemplates target, the assemblies that must be referenced to compile the preprocessed templates",
"description": "After running the `TransformTemplates` target, the assemblies that must be referenced to compile the preprocessed templates",
"type": "file"
},
"GeneratedTemplates": {
"description": "After running the TransformTemplates target, the output of all transformed templates",
"description": "After running the `TransformTemplates` target, the output of all transformed templates",
"type": "file"
},
"PreprocessedTemplates": {
"description": "After running the TransformTemplates target, the output of all preprocessed templates",
"description": "After running the `TransformTemplates` target, the output of all preprocessed templates",
"type": "file"
}
},
Expand All @@ -79,6 +79,18 @@
"description": "Overrides the output filename for a T4 template. Note that Visual Studio does not respect this.",
"type": "file"
}
},
{
"$appliesTo": [ "GeneratedTemplates", "PreprocessedTemplates" ],
"InputFile": {
"description": "The original template file that generated this file",
"type": "file"
},
"Dependencies": {
"description": "The files that the template depends on",
"type": "file",
"isList": true
}
}
],
"properties": {
Expand All @@ -93,20 +105,20 @@
"defaultValue": "true"
},
"TransformFile": {
"description": "The T4 files to transform when running the Transform target",
"description": "The T4 files to transform when running the `Transform` target",
"type": "file",
"isList": true
},
"BeforeTransform": {
"description": "Targets to run before the T4 Transform target",
"type": "target-name",
"deprecationMessage": "Use `BeforeTargets=\"TransformTemplatesCore\" for target ordering`",
"deprecationMessage": "Use `BeforeTargets=\"TransformTemplatesCore\"` for target ordering.",
"isList": true
},
"AfterTransform": {
"description": "Targets to run after the T4 Transform target",
"type": "target-name",
"deprecationMessage": "Use `AfterTargets=\"TransformTemplatesCore\" for target ordering`",
"deprecationMessage": "Use `AfterTargets=\"TransformTemplatesCore\"` for target ordering.",
"isList": true
},
"IncludeFolders": {
Expand All @@ -122,20 +134,15 @@
"PreprocessTemplateDefaultNamespace": {
"description": "Default namespace for preprocessed templates",
"defaultValue": "$(RootNamespace)",
"deprecationMessage": "Legacy alternative to`$(T4DefaultNamespace)`"
"deprecationMessage": "Legacy alternative to `$(T4DefaultNamespace)`"
},
"UseLegacyT4Preprocessing": {
"description": "Place preprocessed templates beside the templates instead of dynamically injecting them into the build.",
"type": "bool"
},
"T4Arguments": {
"description": "Semicolon-separated list of values to convert to `@(T4Argument)` items. Intended to be used from command-line invocations only.",
"isList": true,
"type": {
"description": "Key-value pair",
"allowUnknownValues": true,
"values": {}
}
"description": "Used to pass arguments when invoking on the CLI. This is a semicolon-separated list and uses the same format as encoded `T4Argument` items: `name=value`, `directive!name!value` or `processor!directive!name!value`.",
"isList": true
}
},
"targets": {
Expand Down
39 changes: 39 additions & 0 deletions Mono.TextTemplating.Build/T4PropertyPage.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8" ?>
<Rule Name="Build"
OverrideMode="Extend"
Description="Specifies properties that control how the project builds."
DisplayName="Build"
PageTemplate="generic"
xmlns="http://schemas.microsoft.com/build/2009/properties">

<Rule.Categories>
<Category Name="T4Templates"
DisplayName="T4 Templates" />
</Rule.Categories>

<Rule.DataSource>
<DataSource Persistence="ProjectFile"
SourceOfDefaultValue="AfterContext"
HasConfigurationCondition="False" />
</Rule.DataSource>

<BoolProperty Name="TransformOnBuild"
DisplayName="Transform on build"
Description="Transform T4 templates when building the project."
Category="T4Templates" />

<StringProperty Name="T4DefaultNamespace"
DisplayName="T4 Default Namespace"
Description="Default namespace for preprocessed T4 templates."
Category="T4Templates" />

<BoolProperty Name="TransformOutOfDateOnly"
DisplayName="Transform out-of-date templates only"
Description="When transforming T4 templates, skip ones that are already up to date."
Category="T4Templates" />

<BoolProperty Name="UseLegacyT4Preprocessing"
DisplayName="Use legacy T4 preprocessing"
Description="Place the output files of preprocessed templates beside the template files instead of dynamically injecting them into the build."
Category="T4Templates" />
</Rule>
23 changes: 23 additions & 0 deletions Mono.TextTemplating.Build/T4PropertySchema.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<ProjectSchemaDefinitions xmlns="http://schemas.microsoft.com/build/2009/properties">

<ContentType
Name="T4Transform"
DisplayName="T4 template"
ItemType="T4Transform">
<NameValuePair Name="DefaultMetadata_Generator" Value="MSBuild:TransformTemplates" />
</ContentType>

<ContentType
Name="T4Preprocess"
DisplayName="T4 runtime template"
ItemType="T4Preprocess">
<NameValuePair Name="DefaultMetadata_Generator" Value="MSBuild:TransformTemplates" />
</ContentType>

<ItemType Name="T4Transform" DisplayName="T4 template"/>
<ItemType Name="T4Preprocess" DisplayName="T4 runtime template"/>

<FileExtension Name=".tt" ContentType="T4 template" />

</ProjectSchemaDefinitions>
18 changes: 16 additions & 2 deletions Mono.TextTemplating.Build/TextTransform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -135,14 +135,16 @@ public override bool Execute ()
if (buildState.TransformTemplates != null) {
TransformTemplateOutput = new ITaskItem[buildState.TransformTemplates.Count];
for (int i = 0; i < buildState.TransformTemplates.Count; i++) {
TransformTemplateOutput[i] = new TaskItem (buildState.TransformTemplates[i].OutputFile);
var template = buildState.TransformTemplates[i];
TransformTemplateOutput[i] = ConstructOutputItem (template.OutputFile, template.InputFile, template.Dependencies);
}
}

if (buildState.PreprocessTemplates != null) {
PreprocessedTemplateOutput = new ITaskItem[buildState.PreprocessTemplates.Count];
for (int i = 0; i < buildState.PreprocessTemplates.Count; i++) {
PreprocessedTemplateOutput[i] = new TaskItem (buildState.PreprocessTemplates[i].OutputFile);
var template = buildState.PreprocessTemplates[i];
PreprocessedTemplateOutput[i] = ConstructOutputItem (template.OutputFile, template.InputFile, template.Dependencies);
}
}

Expand All @@ -159,6 +161,18 @@ public override bool Execute ()
return success;
}

static TaskItem ConstructOutputItem (string outputFile, string inputFile, List<string> itemDependencies)
{
var item = new TaskItem (outputFile);
item.SetMetadata ("InputFile", inputFile);

if (itemDependencies?.Count > 0) {
item.SetMetadata ("Dependencies", string.Join (";", itemDependencies));
}

return item;
}

bool AddParameters (TemplateBuildState buildState)
{
bool success = true;
Expand Down
5 changes: 3 additions & 2 deletions Mono.TextTemplating.Build/TextTransformProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ public static bool Process (TaskLoggingHelper taskLog, TemplateBuildState previo
var pt = LoadTemplate (generator, inputFile, out var inputContent);
TemplateSettings settings = TemplatingEngine.GetSettings (generator, pt);

settings.RelativeLinePragmas = true;
settings.RelativeLinePragmasBaseDirectory = Path.GetDirectoryName (preprocess.OutputFile);

settings.CodeGenerationOptions.UseRemotingCallContext = buildState.PreprocessTargetRuntimeIdentifier == ".NETFramework";

// FIXME: make these configurable, take relative path into account
Expand Down Expand Up @@ -208,8 +211,6 @@ static MSBuildTemplateGenerator CreateGenerator (TemplateBuildState buildState)
}
}

generator.UseRelativeLinePragmas = true;

return generator;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@ enum CSharpLangVersion
v10_0,
v11_0,
v12_0,
v13_0,
Latest = 1024 // make sure value doesn't change as we add new C# versions
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public static bool IsLangVersionArg (string arg) =>
//https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-version-history
public static CSharpLangVersion FromNetCoreSdkVersion (SemVersion sdkVersion)
=> sdkVersion switch {
{ Major: 9 } => CSharpLangVersion.v13_0,
{ Major: 8 } => CSharpLangVersion.v12_0,
{ Major: 7 } => CSharpLangVersion.v11_0,
{ Major: 6 } => CSharpLangVersion.v10_0,
Expand All @@ -73,6 +74,7 @@ public static CSharpLangVersion FromNetCoreSdkVersion (SemVersion sdkVersion)
CSharpLangVersion.v10_0 => "10.0",
CSharpLangVersion.v11_0 => "11.0",
CSharpLangVersion.v12_0 => "12.0",
CSharpLangVersion.v13_0 => "13.0",
CSharpLangVersion.Latest => "latest",
_ => throw new ArgumentException ($"Not a valid value: '{version}'", nameof (version))
};
Expand Down
5 changes: 1 addition & 4 deletions Mono.TextTemplating/Mono.TextTemplating.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,7 @@
<!-- limit to 6.0 so that the MSBuild task can load on .NET 6.0 -->
<PackageReference Include="System.CodeDom" Version="6.0.0" Condition="'$(TargetFramework)'!='net472'" />
<None Include="readme.md" Pack="true" PackagePath="\" />
<None Include="package\Mono.TextTemplating.targets" Pack="true" PackagePath="buildTransitive\net461\Mono.TextTemplating.targets" />
<None Include="package\_._" Pack="true" PackagePath="buildTransitive\net472\_._" />
<None Include="package\Mono.TextTemplating.targets" Pack="true" PackagePath="buildTransitive\netcoreapp2.0\Mono.TextTemplating.targets" />
<None Include="package\_._" Pack="true" PackagePath="buildTransitive\net6.0\_._" />
<None Include="package\Mono.TextTemplating.targets" Pack="true" PackagePath="buildTransitive\Mono.TextTemplating.targets" />
</ItemGroup>

<ItemGroup>
Expand Down
6 changes: 6 additions & 0 deletions Mono.TextTemplating/Mono.TextTemplating/TemplateSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ public TemplateSettings ()
public string GetFullName () => string.IsNullOrEmpty (Namespace) ? Name : Namespace + "." + Name;

internal CodeGenerationOptions CodeGenerationOptions { get; } = new CodeGenerationOptions ();

/// <summary>
/// Base directory for calculation of relative line pragmas.
/// Internal until we clean up the settings API.
/// </summary>
internal string RelativeLinePragmasBaseDirectory { get; set; }
}

public class CustomDirective
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,16 @@ public static CodeCompileUnit GenerateCompileUnit (ITextTemplatingEngineHost hos

static void GenerateTransformMethod (CodeTypeDeclaration templateType, TemplateSettings settings, ParsedTemplate pt, string templateFile, bool isOverride)
{
string baseDirectory = Path.GetDirectoryName (templateFile);
string pragmasRelativeToDirectory = null;

if (settings.RelativeLinePragmas) {
if (!string.IsNullOrEmpty (settings.RelativeLinePragmasBaseDirectory)) {
pragmasRelativeToDirectory = Path.GetFullPath (settings.RelativeLinePragmasBaseDirectory);
}
if (pragmasRelativeToDirectory is null && templateFile is not null) {
pragmasRelativeToDirectory = Path.GetDirectoryName (Path.GetFullPath (templateFile));
}
}

var transformMeth = Declare.Method ("TransformText").Returns<string> ().AsVirtual ();

Expand All @@ -87,16 +96,16 @@ static void GenerateTransformMethod (CodeTypeDeclaration templateType, TemplateS
CodeStatement st = null;
CodeLinePragma location = null;
if (!settings.NoLinePragmas) {
var f = seg.StartLocation.FileName ?? templateFile;
if (!string.IsNullOrEmpty (f)) {
// FIXME: we need to know where the output file will be to make this work properly
if (settings.RelativeLinePragmas) {
f = FileUtil.AbsoluteToRelativePath (baseDirectory, f);
} else {
f = Path.GetFullPath (f);
var filename = seg.StartLocation.FileName ?? templateFile;
if (!string.IsNullOrEmpty (filename)) {
if (!settings.RelativeLinePragmas) {
filename = Path.GetFileName (filename);
} else if (pragmasRelativeToDirectory is not null) {
filename = Path.GetFullPath (filename);
filename = FileUtil.AbsoluteToRelativePath (pragmasRelativeToDirectory, filename);
}
}
location = new CodeLinePragma (f, seg.StartLocation.Line);
location = new CodeLinePragma (filename, seg.StartLocation.Line);
}
switch (seg.Type) {
case SegmentType.Block:
Expand Down
Loading
Loading