This content was created with assistance from AI.
Description
When NativeLib=Static is set (to have ILC produce a .a archive instead of a shared library), the LinkNative target in Microsoft.NETCore.Native.targets fails with:
Microsoft.NETCore.Native.targets(351,96): error MSB4086: A numeric comparison was attempted on "$(_LinkerVersion)" that evaluates to "" instead of a number, in condition '$(LinkerFlavor)' == 'lld' and '$(_LinkerVersion)' > '12'"
Root Cause
In Microsoft.NETCore.Native.Unix.targets, the _LinkerVersion detection is correctly skipped when NativeLib=Static:
<!-- Line ~332: version detection is skipped for static builds -->
<Exec Command=""$(CppLinker)" -fuse-ld=lld -Wl,--version"
Condition="'$(LinkerFlavor)' == 'lld' and '$(NativeLib)' != 'Static'" ...>
However, in Microsoft.NETCore.Native.targets, the CustomLinkerArg item group inside LinkNative evaluates _LinkerVersion without the same NativeLib guard:
<!-- Line ~351: no NativeLib guard on this condition -->
<CustomLinkerArg Include="-Wl,-T,"$(NativeIntermediateOutputPath)sections.ld""
Condition="'$(LinkerFlavor)' == 'lld' and '$(_LinkerVersion)' > '12'" />
The same issue exists on line ~368:
<WriteLinesToFile ... Condition="... '$(LinkerFlavor)' == 'lld' and '$(_LinkerVersion)' > '12'" />
Since _LinkerVersion is empty (detection was skipped), the numeric comparison '' > '12' causes MSBuild error MSB4086.
When This Triggers
This triggers when:
NativeLib=Static (so version detection is skipped), AND
LinkerFlavor=lld (set automatically for android, linux-bionic, and freebsd targets)
This combination occurs when Android or other platforms set NativeLib=Static to take ownership of the final native link step (producing their own shared library from the ILC .o output), following the same pattern used by xamarin-macios.
Suggested Fix
Add '$(NativeLib)' != 'Static' to the conditions on lines ~351 and ~368, consistent with the guard on the version detection itself:
<CustomLinkerArg Include="-Wl,-T,"$(NativeIntermediateOutputPath)sections.ld""
Condition="'$(LinkerFlavor)' == 'lld' and '$(NativeLib)' != 'Static' and '$(_LinkerVersion)' > '12'" />
Alternatively, the version detection could default _LinkerVersion to 0 when skipped, so the comparison always succeeds safely.
Workaround
Clear LinkerFlavor before LinkNative runs:
<PropertyGroup>
<LinkerFlavor />
</PropertyGroup>
This must be done inside a target (not a static PropertyGroup) because the ILC Unix targets set LinkerFlavor in a static PropertyGroup that evaluates after the consumer's import.
This content was created with assistance from AI.
Description
When
NativeLib=Staticis set (to have ILC produce a.aarchive instead of a shared library), theLinkNativetarget inMicrosoft.NETCore.Native.targetsfails with:Root Cause
In
Microsoft.NETCore.Native.Unix.targets, the_LinkerVersiondetection is correctly skipped whenNativeLib=Static:However, in
Microsoft.NETCore.Native.targets, theCustomLinkerArgitem group insideLinkNativeevaluates_LinkerVersionwithout the sameNativeLibguard:The same issue exists on line ~368:
Since
_LinkerVersionis empty (detection was skipped), the numeric comparison'' > '12'causes MSBuild error MSB4086.When This Triggers
This triggers when:
NativeLib=Static(so version detection is skipped), ANDLinkerFlavor=lld(set automatically forandroid,linux-bionic, andfreebsdtargets)This combination occurs when Android or other platforms set
NativeLib=Staticto take ownership of the final native link step (producing their own shared library from the ILC.ooutput), following the same pattern used by xamarin-macios.Suggested Fix
Add
'$(NativeLib)' != 'Static'to the conditions on lines ~351 and ~368, consistent with the guard on the version detection itself:Alternatively, the version detection could default
_LinkerVersionto0when skipped, so the comparison always succeeds safely.Workaround
Clear
LinkerFlavorbeforeLinkNativeruns:This must be done inside a target (not a static PropertyGroup) because the ILC Unix targets set
LinkerFlavorin a static PropertyGroup that evaluates after the consumer's import.