简体   繁体   中英

How can a project be built as a portable or a normal class library depending on the selected configuration?

Context: We have a common library project called 'THEPROJECT' that is shared with a Xamarin mobile solution and a web project in visual studio. This shared library is a PCL Profile259 due to restrictions in Xamarin. In our web application solution we would like to mark the data models with the appropriate attributes for DataContext to work correctly (as we want to use LinqToSql).

Attempted Solution: We decided to look into the project for 'THEPROJECT' and change the msbuild in a way that would allow it to exist in a state of portable library / normal class library depending on the selected configuration in visual studio.

We have looked at the solution in this post however it is only part of the solution. We can get the project to exist as one or the other, however it requires a manual change to the project file. Now we get the error loading the following project. The for a portable project must be '.NETPortable'.

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <Configuration Condition=" '$(Configuration)' == '' ">DebugDesktop</Configuration>
        <Platform Condition="'$(Platform)' == ''">AnyCPU</Platform>
        <ProjectGuid>{426E7BD8-9DA8-4E15-9512-72E7C632B037}</ProjectGuid>
        <OutputType>Library</OutputType>
        <AppDesignerFolder>Properties</AppDesignerFolder>
        <RootNamespace>THEPROJECT</RootNamespace>
        <AssemblyName>THEPROJECT</AssemblyName>
        <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
        <MinimumVisualStudioVersion>10.0</MinimumVisualStudioVersion>
        <BuildMode>Desktop</BuildMode>
    </PropertyGroup>

    <!-- Define the Build Configurations -->
    <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugDesktop|AnyCPU' ">
        <DebugSymbols>true</DebugSymbols>
        <DebugType>full</DebugType>
        <Optimize>false</Optimize>
        <OutputPath>bin\Desktop\Debug\</OutputPath>
        <DefineConstants>TRACE;DEBUG;</DefineConstants>
        <ErrorReport>prompt</ErrorReport>
        <WarningLevel>4</WarningLevel>
        <ConsolePause>false</ConsolePause>
        <BuildMode>Desktop</BuildMode>
    </PropertyGroup>
    <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseDesktop|AnyCPU' ">
        <DebugType>pdbonly</DebugType>
        <Optimize>true</Optimize>
        <OutputPath>bin\Desktop\Release\</OutputPath>
        <DefineConstants>TRACE</DefineConstants>
        <ErrorReport>prompt</ErrorReport>
        <WarningLevel>4</WarningLevel>
        <BuildMode>Desktop</BuildMode>
    </PropertyGroup>
    <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugPCL|AnyCPU' ">
        <DebugSymbols>true</DebugSymbols>
        <DebugType>full</DebugType>
        <Optimize>false</Optimize>
        <OutputPath>bin\PCL\Debug\</OutputPath>
        <DefineConstants>TRACE;DEBUG;</DefineConstants>
        <ErrorReport>prompt</ErrorReport>
        <WarningLevel>4</WarningLevel>
        <ConsolePause>false</ConsolePause>
        <BuildMode>Portable</BuildMode>
    </PropertyGroup>
    <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleasePCL|AnyCPU' ">
        <DebugType>pdbonly</DebugType>
        <Optimize>true</Optimize>
        <OutputPath>bin\PCL\Release\</OutputPath>
        <DefineConstants>TRACE</DefineConstants>
        <ErrorReport>prompt</ErrorReport>
        <WarningLevel>4</WarningLevel>
        <BuildMode>Portable</BuildMode>
    </PropertyGroup>

    <!-- Determine the correct properties for PCL/Desktop -->
    <Choose>
        <When Condition=" '$(BuildMode)' == 'Portable' ">
            <PropertyGroup>
                <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
                <TargetFrameworkProfile>Profile259</TargetFrameworkProfile>
                <TargetFrameworkIdentifier>.NETPortable</TargetFrameworkIdentifier>
                <DynamicImportPath>$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets</DynamicImportPath>
            </PropertyGroup>
        </When>
        <When Condition=" '$(BuildMode)' == 'Desktop' ">
            <PropertyGroup>
                <FileAlignment>512</FileAlignment>
                <TargetFrameworkProfile />
                <DynamicImportPath>$(MSBuildToolsPath)\Microsoft.CSharp.targets</DynamicImportPath>
            </PropertyGroup>
            <ItemGroup>
                <Reference Include="System.Data.Linq" />
            </ItemGroup>
        </When>
    </Choose>

    <ItemGroup>
        <Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
            <HintPath>..\..\mobileapplication\packages\Newtonsoft.Json.8.0.2\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll</HintPath>
            <Private>True</Private>
        </Reference>
        <Reference Include="System" />
        <Reference Include="System.Core" />
        <Reference Include="System.Xml.Linq" />
        <Reference Include="Microsoft.CSharp" />
        <Reference Include="System.Xml" />
    </ItemGroup>
    <ItemGroup>
        <ProjectReference Include="..\..\sqlite-net-extensions\SQLiteNetExtensions\SQLiteNetExtensions-PCL.csproj">
            <Project>{f723017d-ede5-49cc-a84f-881c067c6004}</Project>
            <Name>SQLiteNetExtensions-PCL</Name>
        </ProjectReference>
        <ProjectReference Include="..\..\sqlitenetpcl\src\SQLite.Net\SQLite.Net.csproj">
            <Project>{4971d437-0694-4297-a8cc-146ce08c3bd9}</Project>
            <Name>SQLite.Net</Name>
        </ProjectReference>
    </ItemGroup>

    <Import Project="$(DynamicImportPath)" />

    <!-- Source/Resx etc... -->
</Project>

To answer the question about making a project be "Portable" or "Normal" depending on the configuration, when the error that pops up is something about the <TargetFrameworkIdentifier> must be .NETPortable :

Remove all the <ProjectTypeGuids> from the configuration.

Those project type GUIDs give Visual Studio some GUI things that have to do with portable projects only, so when the configuration is not portable it causes the error you got. But since you're comfortable editing the XML, you obviously don't need that stuff. Plus you can continue to use the GUI to edit project properties with the project type GUIDs removed.

At least as of Visual Studio 2015.

When you create a Portable Class Library you need to create your library as a Windows 8.1 Portable Library you can't use Universal Libraries for this, which it sounds like you did by the constraints of Xamarin. The Windows 8.1 Portable Library is a kind of hybrid library that allows classic .net to communicate with the new lightweight versions of .net.

The issue with the Portable Class Library is it can't reference aa Classic Class Library via project reference, you can only reference it via DLL reference. You do not need to mess around with the XML if you are uncomfortable editing that file just find the compiled DLL and add the reference manually. If you choose to do this you will need to manually update the build dependencies or you may have broken references.

It seems like the issue isn't entirely in your .csproj but it is also in your project.json. I have been noticing visual studio not generating the proper project.json file. I have to tinker with the targets in the UI to get it to generate correctly. Once I get the initial project.json to generate I have no other issues.

Prior to doing anything we need to wire up our Portable Class Library to handle a Classic Class Library. The first step is updating the target framework from the properties to target .net 4.5 or whatever version you prefer.

Once you do this confirm that the project.json file looks something like this:

{
  "supports": {},
  "dependencies": {},
  "frameworks": {
    ".NETPortable,Version=v4.5,Profile=Profile259": {}
  }
}

Once your Portable Class Library is targeting the correct version you can then add a DLL reference to the compiled .net 4.5 assembly. I have made no additional changes to the csproj file for the portable class library but here is the source to that so you can take a look.

Notice how the ClassLibrary1 is referenced:

    <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>{7C4EB968-4C17-438C-B981-97EDC865F312}</ProjectGuid>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>PortableLibrary</RootNamespace>
    <AssemblyName>PortableLibrary</AssemblyName>
    <DefaultLanguage>en-US</DefaultLanguage>
    <FileAlignment>512</FileAlignment>
    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
    <TargetFrameworkProfile>Profile259</TargetFrameworkProfile>
    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <ItemGroup>
    <Compile Include="Class1.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
  </ItemGroup>
  <ItemGroup>
    <Reference Include="ClassLibrary1">
      <HintPath>..\ClassLibrary1\bin\Debug\ClassLibrary1.dll</HintPath>
    </Reference>
  </ItemGroup>
  <ItemGroup>
    <None Include="project.json" />
  </ItemGroup>
  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->
</Project>

This should eliminate issues assuming your web project is ASP.NET Core 1.0. If you are running a Classic ASP.NET application you may still have to create the build rules.

TLDR:

Looks like there is an issue with your project.json file, make sure it is getting generated correctly and you can't directly reference .net 4.5 via project reference you have to reference the DLL.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM