.NET探索平臺條件編譯

前言

今天偶然機會,翻了一下大學期間的書籍《C程序設計》,好吧,當我翻着翻着,翻到了符號常量(#define指令)中,是啊,這是一個預處理器指令,記得在Magicodes.IE中針對平臺選擇不一樣的庫,哈哈,這是一個典型的根據平臺進行條件處理,好吧,根據這些內容,讓我感受在今天,我須要對#define指令以及在.NET中的平臺條件處理,以及平臺的條件編譯進行記錄一下。html

file

define

咱們可經過define來定義符號,而後將符號用在#if指令表達式中,以下所示:git

#define PI

經過上面這些內容可能很難去了解這該如何使用,其實#define在咱們的編碼過程當中也是不多去使用的,咱們繼續往下看。github

其實對於預處理器,在咱們調試以及運行時的做用是比較大的,好比說對某些代碼限制編譯,另外一方變其實還能夠對代碼進行環境或者版本的控制,這些都是Ok的,最後咱們結合着控制語句#if來看一下:post

#define PI
using System;

namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
            #if (PI)
            Console.WriteLine("PI is defined");
            #else
            Console.WriteLine("PI is not defined");
            #endif
            Console.ReadKey();
        }
    }
}

當咱們的頭部聲明#define PI時,咱們也能夠看到編譯的感知功能能夠爲咱們將控制語句進行切換,是啊,咱們能夠在頭部進行聲明。測試

條件編譯符號

對於上面咱們能夠直接經過#define去進行條件編譯,而對於在.cs文件中咱們去定義它達到的只是局部的使用,咱們若是說想全局的控制,全局的應用該如何操做?其實咱們是能夠經過DefineConstants屬性進行操做。ui

file

咱們能夠打開項目文件進行查看,屬性以下所示:編碼

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5</TargetFramework>
  </PropertyGroup>

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
    <DefineConstants>TRACE;PI</DefineConstants>
  </PropertyGroup>
</Project>

固然了,咱們一方面是可經過VS對項目的屬性進行編輯,而另外一方面,咱們是可經過直接對項目文件進行修改編輯操做.這樣其實達到了一個可控制性.spa

RuntimeInformation

對於代碼中也是能夠進行平臺的邏輯判斷的,在.NET Core 1.0的時候其實已經添加了System.Runtime.InteropServices.RuntimeInformation對於這個類的添加,使咱們能夠動態的去判斷當前的操做系統(OS),以及咱們可經過這些動態判斷爲咱們的業務邏輯進行不一樣的處理行爲。操作系統

判斷當前操做系統以下所示:設計

if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
    Console.WriteLine("Running on Linux!");
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
    Console.WriteLine("Running on macOS!");
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
    Console.WriteLine("Running on Windows!");

MSBuild & RuntimeInformation

對於條件編譯,以前咱們已經手動的操做過一次了,是咱們能夠根據不一樣的環境值進行對代碼編譯內容的控制,若是說我想根據當前的操做系統(OS)動態的進行條件編譯,該如何進行操做。

其實咱們在項目文件中進行調用System.Runtime.InteropServices.RuntimeInformation進行咱們的條件處理。下面咱們看一下在MSBuild中如何調用System.Runtime.InteropServices.RuntimeInformation以下所示:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5</TargetFramework>
    <IsWindows Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">true</IsWindows>
    <IsOSX Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">true</IsOSX>
    <IsLinux Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">true</IsLinux>
  </PropertyGroup>

  <Target Name="PrintRID" BeforeTargets="Build">
    <Message Text="IsWindows $(IsWindows)" Importance="high" />
    <Message Text="IsOSX $(IsOSX)" Importance="high" />
    <Message Text="IsLinux $(IsLinux)" Importance="high" />
  </Target>

</Project>

咱們是能夠經過visual studio或者說經過CLI直接運行構建命令dotnet build,咱們在Windows操做系統中測試一下,輸出結果以下所示:

C:\Users\hueif\source\repos\ConsoleApp2\ConsoleApp2>dotnet build
用於 .NET 的 Microsoft (R) 生成引擎版本 16.8.0+126527ff1
版權全部(C) Microsoft Corporation。保留全部權利。

  正在肯定要還原的項目…
  全部項目均是最新的,沒法還原。
  你正在使用 .NET 的預覽版。請查看 https://aka.ms/dotnet-core-preview
  ConsoleApp2 -> C:\Users\hueif\source\repos\ConsoleApp2\ConsoleApp2\bin\Debug\net5\ConsoleApp2.dll
  IsWindows true
  IsOSX
  IsLinux

能夠看出,在IsWindows中對應着true,說明咱們的操做生效了,那麼咱們繼續修改咱們的程序,看看如何使用條件編譯,去控制咱們的代碼,咱們在項目文件中添加以下片斷:

<PropertyGroup Condition="'$(IsWindows)'=='true'">
    <DefineConstants>Windows</DefineConstants>
  </PropertyGroup>
  <PropertyGroup Condition="'$(IsOSX)'=='true'">
    <DefineConstants>OSX</DefineConstants>
  </PropertyGroup>
  <PropertyGroup Condition="'$(IsLinux)'=='true'">
    <DefineConstants>Linux</DefineConstants>
  </PropertyGroup>

經過如上語句,咱們能夠對DefineConstants屬性進行條件判斷,條件性處理,一樣咱們在代碼中也是經過該值進行判斷,以下所示:

static void Main(string[] args)
        {
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
                Console.WriteLine("Running on Linux!");
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
                Console.WriteLine("Running on macOS!");
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                Console.WriteLine("Running on Windows!");

            #if Linux
                    Console.WriteLine("Build on Linux!"); 
            #elif OSX
                    Console.WriteLine("Build on macOS!"); 
            #elif Windows
            Console.WriteLine("Build in Windows!");
            #endif
            Console.ReadKey();
        }

下面咱們來驗證一下結果,是否跟咱們想象中的同樣

Running on Windows!
Build in Windows!

結果沒問題,已達到預期的效果。

References

https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/preprocessor-directives/preprocessor-define

https://blog.walterlv.com/post/how-to-define-preprocessor-symbols.html

相關文章
相關標籤/搜索