Skip to content

Commit 3e3a326

Browse files
committed
[Xamarin.Android.Build.Tasks] Fixed F# Resource Designer compilation issues
The latest release of F# removed support for static fields. As a result the Resource.Designer.fs file that wes being generated by our build system no longer compiled. This commit reworks the Designer.cs code to emit a C# assembly for F# projects rather than just the code. This has the benifit of us not having to produce F# code in the first place. The new system works as follows. 1) GenerateResourceDesigner Task generates a Resources.Designer.cs file as normal 2) If the target project is F# that file is then compiled into a Resource.Designer.dll 3) The new .dll is then included in the @ReferencePaths ItemGroup 4) The Resource.Designer.cs is removed from the @complie ItemGroup If the project is C# or VS the Designer file is just included as normal.
1 parent fbfd676 commit 3e3a326

File tree

2 files changed

+39
-36
lines changed

2 files changed

+39
-36
lines changed

src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesigner.cs

Lines changed: 17 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ public class GenerateResourceDesigner : Task
3838

3939
public ITaskItem[] References { get; set; }
4040

41+
42+
[Output]
43+
public bool BuildResourceAssembly { get; set; }
44+
4145
private Dictionary<string, string> resource_fixup = new Dictionary<string, string> (StringComparer.OrdinalIgnoreCase);
4246

4347
public override bool Execute ()
@@ -98,6 +102,11 @@ public override bool Execute ()
98102
bool isFSharp = string.Equals (language, "F#", StringComparison.OrdinalIgnoreCase);
99103
bool isCSharp = string.Equals (language, "C#", StringComparison.OrdinalIgnoreCase);
100104

105+
if (isFSharp) {
106+
language = "C#";
107+
}
108+
109+
BuildResourceAssembly = isFSharp;
101110
// Let VB put this in the default namespace
102111
if (isVB)
103112
Namespace = string.Empty;
@@ -125,31 +134,24 @@ public override bool Execute ()
125134
.CreateImportMethods (assemblies);
126135
}
127136

128-
AdjustConstructor (isFSharp, resources);
137+
AdjustConstructor (resources);
129138
foreach (var member in resources.Members)
130139
if (member is CodeTypeDeclaration)
131-
AdjustConstructor (isFSharp, (CodeTypeDeclaration) member);
140+
AdjustConstructor ((CodeTypeDeclaration) member);
132141

133142
// Write out our Resources.Designer.cs file
134143

135-
WriteFile (NetResgenOutputFile, resources, language, isFSharp, isCSharp);
144+
WriteFile (NetResgenOutputFile, resources, language, isCSharp);
145+
146+
Log.LogDebugMessage ($"[Output] BuildResourceAssembly : {BuildResourceAssembly}");
136147

137148
return !Log.HasLoggedErrors;
138149
}
139150

140151
// Remove private constructor in F#.
141152
// Add static constructor. (but ignored in F#)
142-
void AdjustConstructor (bool isFSharp, CodeTypeDeclaration type)
153+
void AdjustConstructor (CodeTypeDeclaration type)
143154
{
144-
if (isFSharp) {
145-
foreach (CodeTypeMember tm in type.Members) {
146-
if (tm is CodeConstructor) {
147-
type.Members.Remove (tm);
148-
break;
149-
}
150-
}
151-
}
152-
153155
var staticCtor = new CodeTypeConstructor () { Attributes = MemberAttributes.Static };
154156
staticCtor.Statements.Add (
155157
new CodeExpressionStatement (
@@ -162,11 +164,9 @@ void AdjustConstructor (bool isFSharp, CodeTypeDeclaration type)
162164
type.Members.Add (staticCtor);
163165
}
164166

165-
private void WriteFile (string file, CodeTypeDeclaration resources, string language, bool isFSharp, bool isCSharp)
167+
private void WriteFile (string file, CodeTypeDeclaration resources, string language, bool isCSharp)
166168
{
167-
CodeDomProvider provider =
168-
isFSharp ? new FSharp.Compiler.CodeDom.FSharpCodeProvider () :
169-
CodeDomProvider.CreateProvider (language);
169+
CodeDomProvider provider = CodeDomProvider.CreateProvider (language);
170170

171171
string code = null;
172172
using (var o = new StringWriter ()) {
@@ -201,23 +201,6 @@ private void WriteFile (string file, CodeTypeDeclaration resources, string langu
201201
provider.GenerateCodeFromCompileUnit(new CodeSnippetCompileUnit("#pragma warning restore 1591"), o, options);
202202

203203
code = o.ToString ();
204-
205-
// post-processing for F#
206-
if (isFSharp) {
207-
code = code.Replace ("\r\n", "\n");
208-
while (true) {
209-
int skipLen = " = class".Length;
210-
int idx = code.IndexOf (" = class");
211-
if (idx < 0)
212-
break;
213-
int end = code.IndexOf (" end");
214-
string head = code.Substring (0, idx);
215-
string mid = end < 0 ? code.Substring (idx) : code.Substring (idx + skipLen, end - idx - skipLen);
216-
string last = end < 0 ? null : code.Substring (end + " end".Length);
217-
code = head + @" () =
218-
static do Android.Runtime.ResourceIdManager.UpdateIdValues()" + mid + "\n" + last;
219-
}
220-
}
221204
}
222205

223206
var temp_o = Path.Combine (Path.GetDirectoryName (file), "__" + Path.GetFileName (file) + ".new");

src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -984,8 +984,15 @@ because xbuild doesn't support framework reference assemblies.
984984
<!-- Resource Build -->
985985

986986
<Target Name="UpdateAndroidResources"
987-
DependsOnTargets="$(CoreResolveReferencesDependsOn);_CheckForDeletedResourceFile;_ComputeAndroidResourcePaths;_UpdateAndroidResgen;_AddLibraryProjectsEmbeddedResourceToProject;_GenerateJavaDesignerForComponent" />
987+
DependsOnTargets="$(CoreResolveReferencesDependsOn);_CheckForDeletedResourceFile;_ComputeAndroidResourcePaths;_UpdateAndroidResgen;_UseCompiledDesignerAssembly;_AddLibraryProjectsEmbeddedResourceToProject;_GenerateJavaDesignerForComponent" />
988988

989+
<Target Name="_UseCompiledDesignerAssembly"
990+
Condition=" Exists ('$(IntermediateOutputPath)Resource.Designer.dll') ">
991+
<ItemGroup>
992+
<ReferencePath Include="$(IntermediateOutputPath)Resource.Designer.dll" />
993+
<Compile Remove="$(_AndroidResourceDesignerFile)" />
994+
</ItemGroup>
995+
</Target>
989996
<!-- Handle a case where the designer file has been deleted, but the flag file still exists -->
990997
<Target Name="_CheckForDeletedResourceFile">
991998
<Delete Files="$(_AndroidResgenFlagFile)"
@@ -1293,7 +1300,9 @@ because xbuild doesn't support framework reference assemblies.
12931300
AdditionalResourceDirectories="@(LibraryResourceDirectories)"
12941301
IsApplication="$(AndroidApplication)"
12951302
References="@(ReferencePath)"
1296-
/>
1303+
>
1304+
<Output TaskParameter="BuildResourceAssembly" PropertyName="_BuildResourceAssembly" />
1305+
</GenerateResourceDesigner>
12971306

12981307
<!-- Only copy if the file contents changed, so users only get Reload? dialog for real changes -->
12991308
<CopyIfChanged
@@ -1304,6 +1313,16 @@ because xbuild doesn't support framework reference assemblies.
13041313

13051314
<!-- Delete our temporary directory -->
13061315
<RemoveDirFixed Directories="$(ResgenTemporaryDirectory)" />
1316+
1317+
<Csc Condition=" '$(_BuildResourceAssembly)' == 'true' "
1318+
KeyFile="$(KeyFile)"
1319+
KeyContainer="$(KeyContainer)"
1320+
NoStandardLib="True"
1321+
TargetType="library"
1322+
References="@(ReferencePath);@(ReferenceDependencyPaths);$(_XATargetFrameworkDirectories)\Java.Interop.dll;$(_XATargetFrameworkDirectories)\mscorlib.dll"
1323+
Sources="$(_AndroidResourceDesignerFile)"
1324+
OutputAssembly="$(IntermediateOutputPath)Resource.Designer.dll"
1325+
/>
13071326

13081327
<!-- If there are no _AndroidResource items, create a blank file -->
13091328
<CreateAndroidResourceStamp
@@ -2497,6 +2516,7 @@ because xbuild doesn't support framework reference assemblies.
24972516
<Delete Files="$(_AndroidLibraryImportsCache)" />
24982517
<Delete Files="$(_AndroidStaticResourcesFlag)" />
24992518
<Delete Files="$(_AndroidLibraryProjectImportsCache)" />
2519+
<Delete Files="$(IntermediateOutputPath)Resource.Designer.dll" />
25002520
</Target>
25012521

25022522
<Target Name="_CollectMonoAndroidOutputs" DependsOnTargets="_ValidateAndroidPackageProperties">

0 commit comments

Comments
 (0)