fsprojects / fsprojects/Paket

<Choose> order for native

Open
#1,973 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug msbuild proj sdk: verbose sdk
Dominant language
F#
Stars
2.1k
Forks
528
Avg merge
1d 12m
Merged PRs (30d)
54

Description

Description

The context is a solution repo with two types of projects - C# and C++ - and both consume a library package that contains both managed and native versions of the library. This packags has a lib folder with the managed library and a build folder with targets for both the native and framework platforms ("native" and "portable-net45+win+MonoAndroid10+xamarinios10+MonoTouch10"). Each folder has a .targets file and extra native dlls (runtime dependencies) to be copied through tasks in the .targets file.

When importing the package with native build targets AND other framework version build targets, a item is added to the .csproj, file with two When Conditions. The first is always true and points to the targets in the build/native folder; the second when works out all the framework versions and profiles.

Because the first is true, the native .targets gets included in the C# project.
Because the first is true, the native .targets gets included (as expected) in the C++ project.

Expected behavior

The expected behaviour is:

  1. the lib-based reference and the framework specific ,targets file imported to the C# project
  2. the native .targets file imported into the C++ project
Actual behavior
  1. the C# project gets a reference to the lib-based library AND the native .targets file
  2. the C++ project gets the native references
Known workarounds

The workaround is a manual edition of the choose condition in the csproj file and vcxproj file.

In the csproj file, the that determines the .targets path is changed from

<Choose>
    <When Condition="true">
      <PropertyGroup>
        <__paket__LibraryName_targets>native\LibraryName</__paket__LibraryName_targets>
      </PropertyGroup>
    </When>
    <When Condition="($(TargetFrameworkIdentifier) == 'WindowsPhoneApp') Or ($(TargetFrameworkIdentifier) == '.NETCore') Or ($(TargetFrameworkIdentifier) == '.NETStandard' And ($(TargetFrameworkVersion) == 'v1.1' Or $(TargetFrameworkVersion) == 'v1.2' Or $(TargetFrameworkVersion) == 'v1.3' Or $(TargetFrameworkVersion) == 'v1.4' Or $(TargetFrameworkVersion) == 'v1.5' Or $(TargetFrameworkVersion) == 'v1.6')) Or ($(TargetFrameworkIdentifier) == '.NETCoreApp' And $(TargetFrameworkVersion) == 'v1.0') 
Or ($(TargetFrameworkIdentifier) == '.NETFramework' 
   And ($(TargetFrameworkVersion) == 'v4.5' 
      Or $(TargetFrameworkVersion) == 'v4.5.1' 
      Or $(TargetFrameworkVersion) == 'v4.5.2' 
      Or $(TargetFrameworkVersion) == 'v4.5.3' 
      Or $(TargetFrameworkVersion) == 'v4.6' 
      Or $(TargetFrameworkVersion) == 'v4.6.1' 
      Or $(TargetFrameworkVersion) == 'v4.6.2' 
      Or $(TargetFrameworkVersion) == 'v4.6.3')) 
Or ($(TargetFrameworkIdentifier) == 'MonoAndroid') Or ($(TargetFrameworkIdentifier) == 'MonoTouch') Or ($(TargetFrameworkIdentifier) == 'Xamarin.iOS') Or ($(TargetFrameworkIdentifier) == 'Xamarin.Mac') Or ($(TargetFrameworkProfile) == 'Profile7') Or ($(TargetFrameworkProfile) == 'Profile44')">
      <PropertyGroup>
        <__paket__LibraryName_targets>portable-net45+win+MonoAndroid10+xamarinios10+MonoTouch10\LibraryName</__paket__LibraryName_targets>
      </PropertyGroup>
    </When>

to

<Choose>
    <When Condition="($(TargetFrameworkIdentifier) == 'WindowsPhoneApp') Or ($(TargetFrameworkIdentifier) == '.NETCore') Or ($(TargetFrameworkIdentifier) == '.NETStandard' And ($(TargetFrameworkVersion) == 'v1.1' Or $(TargetFrameworkVersion) == 'v1.2' Or $(TargetFrameworkVersion) == 'v1.3' Or $(TargetFrameworkVersion) == 'v1.4' Or $(TargetFrameworkVersion) == 'v1.5' Or $(TargetFrameworkVersion) == 'v1.6')) Or ($(TargetFrameworkIdentifier) == '.NETCoreApp' And $(TargetFrameworkVersion) == 'v1.0') 
    Or ($(TargetFrameworkIdentifier) == '.NETFramework' 
      And ($(TargetFrameworkVersion) == 'v4.5' 
        Or $(TargetFrameworkVersion) == 'v4.5.1' 
        Or $(TargetFrameworkVersion) == 'v4.5.2' 
        Or $(TargetFrameworkVersion) == 'v4.5.3' 
        Or $(TargetFrameworkVersion) == 'v4.6' 
        Or $(TargetFrameworkVersion) == 'v4.6.1' 
        Or $(TargetFrameworkVersion) == 'v4.6.2' 
        Or $(TargetFrameworkVersion) == 'v4.6.3')
      And $(TargetFrameworkProfile) != '') 
    Or ($(TargetFrameworkIdentifier) == 'MonoAndroid') 
      Or ($(TargetFrameworkIdentifier) == 'MonoTouch') 
      Or ($(TargetFrameworkIdentifier) == 'Xamarin.iOS') 
      Or ($(TargetFrameworkIdentifier) == 'Xamarin.Mac') 
      Or ($(TargetFrameworkProfile) == 'Profile7') Or ($(TargetFrameworkProfile) == 'Profile44')">
      <PropertyGroup>
        <__paket__LibraryName_targets>portable-net45+win+MonoAndroid10+xamarinios10+MonoTouch10\FARO.Math</__paket__LibraryName_targets>
      </PropertyGroup>
    </When>
    <Otherwise>
      <PropertyGroup>
        <__paket__LibraryName_targets>native\LibraryName</__paket__LibraryName_targets>
      </PropertyGroup>
    </Otherwise>
  </Choose>

Here the at the beginning is replaced with a tag at the end of the Choose element. This will give the compiler the chance to verify the complex condition first.

Also, when testing for the .NETFramework identifies, I also check for an empty profile. I'm not sure if this is always as such, but in the case of the C++ project, (verified in the verbose build output) $(TargetFrameworkProfile) is an empty string.

I can create a repo, but first I just want of understand if my reasoning here is valid. Does the above make sense?

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Inspect the generated .csproj and .vcxproj Choose blocks, along with the native and framework-specific .targets imports. Reproduce the project generation with both native and framework targets, then verify that C# selects the framework targets while C++ selects the native targets without manual project edits.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, csharp
Domain
build-system
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.