Conditional compilation symbol for a .NET Core class library
Asked Answered
H

3

15

I have created a .NET Core R2 class library and have some common code that I use for several different platforms.

Some of the code is not valid in the .NET Core platform and so I wish to wrap it around a conditional compilation symbol. I first searched the Internet to see if I could find a built-in symbol (like SILVERLIGHT for Silverlight applications and WINFX_CORE for Windows 8 applications), but I was not able to find any information, so I decided to create my own symbol. This also does not seem to work.

From everything I read, adding and using a symbol should be easy. Just add a value to the conditional compilation symbols in the project properties → Build tab. I did that, but it does not seem to work. Here are a couple of screenshots...

Enter image description here

Enter image description here

Notice that I added a NET_CORE value in the conditional compilation symbol, but when I use it in code the code is not being ignored.

  1. Is there is a built-in symbol for the .NET Core platform (I am using R2)?

  2. If there is not one, what am I doing wrong creating my own symbol?

The .xproj file:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
    <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
  </PropertyGroup>
  <Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
  <PropertyGroup Label="Globals">
    <ProjectGuid>253184d7-9b42-4233-a871-8cfa3ee9e83e</ProjectGuid>
    <RootNamespace>Linq2Db.NetCore</RootNamespace>
    <BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
    <OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
    <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
    <SccProjectName>SAK</SccProjectName>
    <SccProvider>SAK</SccProvider>
    <SccAuxPath>SAK</SccAuxPath>
    <SccLocalPath>SAK</SccLocalPath>
  </PropertyGroup>
  <PropertyGroup>
    <SchemaVersion>2.0</SchemaVersion>
  </PropertyGroup>
  <Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

UPDATE: I was able to resolve this using the link in the provided answer. Here are the details...

Originally the project.json file looked like this...

{
  "dependencies": {
        "NETStandard.Library": "1.5.0-rc2-24027"
  },
  "frameworks": {
    "netstandard1.5": {
      "imports": "dnxcore50"
    }
  },
  "buildOptions": {
    "defines": [ "NET_CORE" ]
  }
}

I resolved the issue by changing it to this...

{
  "frameworks": {
    "netstandard1.5": {
      "imports": "dnxcore50",
      "dependencies": {
        "NETStandard.Library": "1.5.0-rc2-24027"
      },
      "buildOptions": {
        "define": [ "NET_CORE" ]
      }
    }
  }
}
Heptastich answered 26/6, 2016 at 16:10 Comment(2)
the conditional compilation symbol might be limited to a certain build configuration/platform. Inspect the configuration manager and build properties "(All configurations/platforms)"Barri
Possible duplicate of How to set .NET Core in #if statement for compilationSelie
H
4

Conditional variables should be defined in your project.json file for RC2, and I have a sample project here,

Port #SNMP from .NET Core RC1 to RC2

But there are also predefined ones from this article,

Developing Libraries with Cross Platform Tools

Husbandman answered 27/6, 2016 at 2:2 Comment(0)
K
19

Since xproj was discontinued, here is how it is done in the new Visual Studio 2017 .csproj files.

<PropertyGroup Condition="'$(TargetFramework)' == 'netstandard1.3' Or '$(TargetFramework)' == 'netstandard1.6' ">
    <DefineConstants>NET_CORE</DefineConstants>
</PropertyGroup>

Then instead of:

private TypeInfo GetTypeInfo(Type type)
{
    #if NETSTANDARD1_3 || NETSTANDARD1_6
        // Core
    #else
        // Full framework
    #endif
}

You can do:

private TypeInfo GetTypeInfo(Type type)
{
    #if NET_CORE
        // Core
    #else
        // Fullframework
    #endif
}

See here for more details on multi-targeting: Developing Libraries with Cross Platform Tools, How to Multitarget

Koski answered 30/8, 2017 at 14:58 Comment(0)
H
4

Conditional variables should be defined in your project.json file for RC2, and I have a sample project here,

Port #SNMP from .NET Core RC1 to RC2

But there are also predefined ones from this article,

Developing Libraries with Cross Platform Tools

Husbandman answered 27/6, 2016 at 2:2 Comment(0)
D
4

There is a bug in the .NET Core xproj project type. When you define a conditional compilation symbol through the project settings, it defines the element as "defines", but this is incorrect. It should create an element called "define". You can work around the issue by editing the project.json manually.

I have logged this bug with Microsoft in two places. Please take the time to register your annoyance with Microsoft so that they eventually get around to fixing it and not causing this grief for others.

This thread has a detailed explanation of the problem with steps to repro, and screenshots: https://github.com/dotnet/cli/issues/4022#issuecomment-238777946

This is the Microsoft Connect bug report: https://connect.microsoft.com/VisualStudio/feedbackdetail/view/2983351/conditional-compilation-symbols-broken-in-net-core-projects#tabs

Descendent answered 10/8, 2016 at 23:45 Comment(2)
The last link is (effectively) broken: "Microsoft Connect Has Been Retired"Phidippides
FWIW, Visual Studio 2022 version 17.3.6, .NET 6.0 / Core, and conditional compilation is still broken.Nolan

© 2022 - 2024 — McMap. All rights reserved.