Visual studio conditional compilation for os
Asked Answered
R

2

12

I know that there is a way to conditionally compile for target frameworks eg #if net461 ....#elif .... But is there a way to conditionally compile for specific os Like target _os_MAC or target_os_win

If there is can someone guide me to the documentations or tutorials to how to implement it?

Part 2: Also , is there a way to create a custom tag so that I do not have to change every tag whenever there is a change to the new target os or framework .eg from net461 to net471

Rufford answered 19/4, 2018 at 1:23 Comment(6)
no there is not :)Duster
And who told you that you can change .Net frame work version from code ?Duster
@zackraiyan You've completely misunderstood the question. OP is asking about preprocessor directives.Clue
@SimonWhitehead , where did OP mention it ? And i don't understand the term Conditionally compile for targeted framework , is this even possible? As far my knowledge , this can only be done during the build within the IDE , right ?Please correct me if i am wrongDuster
@zackraiyan "conditionally compile" can mean anything "at compile time". Either via your IDE or via the command line compiler. Preprocessor directives exist for this purpose ... they happen before compilation.Clue
@SimonWhitehead , i know... maybe the question made stumped me for a while.....specially the If and ElseIf he included in the question .... ANyway, i guess i really misunderstoodDuster
C
3

This answer assumes you're asking about custom pre-processor symbols (that is how I have interpreted it - do correct me if I am wrong.

You could use a custom build configuration:

Start by going into the build Configuration Manager..

Configuration Manager

Next, create a new build configuration. You can copy the configuration from an existing one:

Create new configuration

Then, right click on your Project and go to Properties. Under the build tab, define a conditional compilation symbol:

Conditional compilation symbol

Do the same for Windows.

Then you can write conditional steps like the below:

    class Program
{
    static void Main(string[] args)
    {
#if MACOS
        Console.WriteLine("OSX");
#elif WINDOWS
        Console.WriteLine("Windows");
#endif

        Console.Read();
    }

Depending on your chosen build configuration .. you'll either get:

OSX:

OSX

Windows:

Windows

Clue answered 19/4, 2018 at 1:40 Comment(7)
The idea is there. However, wouldn't i need to change the configuration whenever i change machine. I am trying to get my application to be cross platform so it needs to be able to automatically detect it is a windows or macos machine and run the cosresponding code. Maybe there is a missing step somewhere to this solution.Rufford
Well this is all done at compile time ... you could write a build script that chooses your configuration (MSBuild /p:Configuration) ... or you could simply switch the build configuration (its a dropdown in Visual Studio) on your development machines.Clue
Given you're now saying "cross platform" and "auto detect" - do you want this to happen at compile time or runtime? I'm confused about your requirements now.Clue
sorry for the misunderstanding. I was abit confuse about this matter but now i am clear after discussion with my team. I am trying to do this at compile time. so i guess this method will work. Thank you so much.Rufford
Is there a need for me to create 4 configurations in total?. i.e MACOS Debug/Release, Windows Debug/ReleaseRufford
Just a short comment to say that if you don't use Visual Studio, the answer from @Dusen might be much better to follow.Halla
The answer from @Dusen unfortunately does not work if the conditional definitions should depend on the target OS at runtime. For instance if having a cross-platform .NET 6 application and choosing WSL as target, it still detects "Windows" as OS. Is there any solution for conditional definitions depending on the runtime OS?Briticism
D
21

It's an old question, but if someone comes here now, there's a better option.

You do not need to have different configurations and select manually which configuration to use.

You can use System.Runtime.InteropServices.RuntimeInformation. https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.runtimeinformation?view=netframework-4.8

There's a good manual here: https://blog.magnusmontin.net/2018/11/05/platform-conditional-compilation-in-net-core/ Minimal info from the link: Change your .csproj file

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

This will conditionally define constants. Which you later use like so:

#if Linux
    Console.WriteLine("Built on Linux!"); 
#elif Windows
    Console.WriteLine("Built in Windows!"); 
#endif
Dusen answered 26/1, 2020 at 8:42 Comment(1)
Thanks for the link; it's still working well for .NET 6.0 (macOS & Linux at least).Halla
C
3

This answer assumes you're asking about custom pre-processor symbols (that is how I have interpreted it - do correct me if I am wrong.

You could use a custom build configuration:

Start by going into the build Configuration Manager..

Configuration Manager

Next, create a new build configuration. You can copy the configuration from an existing one:

Create new configuration

Then, right click on your Project and go to Properties. Under the build tab, define a conditional compilation symbol:

Conditional compilation symbol

Do the same for Windows.

Then you can write conditional steps like the below:

    class Program
{
    static void Main(string[] args)
    {
#if MACOS
        Console.WriteLine("OSX");
#elif WINDOWS
        Console.WriteLine("Windows");
#endif

        Console.Read();
    }

Depending on your chosen build configuration .. you'll either get:

OSX:

OSX

Windows:

Windows

Clue answered 19/4, 2018 at 1:40 Comment(7)
The idea is there. However, wouldn't i need to change the configuration whenever i change machine. I am trying to get my application to be cross platform so it needs to be able to automatically detect it is a windows or macos machine and run the cosresponding code. Maybe there is a missing step somewhere to this solution.Rufford
Well this is all done at compile time ... you could write a build script that chooses your configuration (MSBuild /p:Configuration) ... or you could simply switch the build configuration (its a dropdown in Visual Studio) on your development machines.Clue
Given you're now saying "cross platform" and "auto detect" - do you want this to happen at compile time or runtime? I'm confused about your requirements now.Clue
sorry for the misunderstanding. I was abit confuse about this matter but now i am clear after discussion with my team. I am trying to do this at compile time. so i guess this method will work. Thank you so much.Rufford
Is there a need for me to create 4 configurations in total?. i.e MACOS Debug/Release, Windows Debug/ReleaseRufford
Just a short comment to say that if you don't use Visual Studio, the answer from @Dusen might be much better to follow.Halla
The answer from @Dusen unfortunately does not work if the conditional definitions should depend on the target OS at runtime. For instance if having a cross-platform .NET 6 application and choosing WSL as target, it still detects "Windows" as OS. Is there any solution for conditional definitions depending on the runtime OS?Briticism

© 2022 - 2024 — McMap. All rights reserved.