程序地带

.NET探索平台条件编译


前言

今天偶然机会,翻了一下大学期间的书籍《C程序设计》,好吧,当我翻着翻着,翻到了符号常量(#define指令)中,是啊,这是一个预处理器指令,记得在Magicodes.IE中针对平台选择不同的库,哈哈,这是一个典型的根据平台进行条件处理,好吧,根据这些内容,让我感觉在今天,我需要对#define指令以及在.NET中的平台条件处理,以及平台的条件编译进行记录一下。


file


define

我们可通过define来定义符号,然后将符号用在#if指令表达式中,如下所示:


#define PI

通过上面这些内容可能很难去了解这该如何使用,其实#define在我们的编码过程中也是很少去使用的,我们继续往下看。


其实对于预处理器,在我们调试以及运行时的作用是比较大的,比如说对某些代码限制编译,另一方变其实还可以对代码进行环境或者版本的控制,这些都是Ok的,最后我们结合着控制语句#if来看一下:


#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属性进行操作。


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对项目的属性进行编辑,而另一方面,我们是可通过直接对项目文件进行修改编辑操作.这样其实达到了一个可控制性.


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:Usershueifsource eposConsoleApp2ConsoleApp2>dotnet build
用于 .NET 的 Microsoft (R) 生成引擎版本 16.8.0+126527ff1
版权所有(C) Microsoft Corporation。保留所有权利。
正在确定要还原的项目…
所有项目均是最新的,无法还原。
你正在使用 .NET 的预览版。请查看 https://aka.ms/dotnet-core-preview
ConsoleApp2 -> C:Usershueifsource eposConsoleApp2ConsoleApp2inDebug et5ConsoleApp2.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


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/yyfh/p/14290640.html

随机推荐

关于论文可查阅的网站

直接搜索,免费查重,自动排版,各行各业的数据库1.煦航论文自动排版软件https://www.jb51.net/softs/653409.html本软件有三大...

hello_g06 阅读(204)

java基础 控制流程 switch

Java基础控制流程Switchswitch语句相当于ifelse的另一种表达方式注:每个表达式结束,都应该有一个break;//示例--判断季节importjava.util.Scan...

姚昂之~ 阅读(231)

mysql 显示用户_在Mysql中如何显示所有用户?

这是一个mysql初学者经常问到的一个问题,今天我们就带大家看看是如何在Mysql中显示所有用户的。通常我们在mysql中使用SHOWDATABASES可以显示所有的数据库,...

weixin_40008920 阅读(433)

mysql 预处理_MySQL的预处理技术

所谓的预处理技术,最初也是由MySQL提出的一种减轻服务器压力的一种技术!传统mysql处理流程1, 在客户端准备sql语句2, 发送sql语句...

Stone Mile 阅读(868)

mysql修改utf 8_mysql 修改 utf8 编码

注:mysql5.6,5.7默认使用utf-8编码,mysql8默认使用utfmb4编码。查看当前使用的编码可以使用以下命令:showvaria...

丁大噜 阅读(630)

两个mysql_一台服务器上启动两个mysql实例

操作环境:centos6.8有时由于服务器硬件资源紧张,而又需要新增mysql服务。这时我们可以采取在一台服务器上部署两个mysql实例,来解决。1、创建新的...

GDSL 阅读(284)

c3p0 mysql_【JavaWeb】c3p0连接池与MySQL

正文之前在之前的文章讲到了传统的JDBC连接MySQL的方式,但是这样的方式在进行多个连接时,就显得效率低下,明显不如连接池的效率,所以我们这次...

王少冬 阅读(223)