.NET Compilation conditions

Found out the hard way just leaving this here for anybody that encounters this.

DO NOT USE CONDITIONS FOR COMPILATION IN YOUR csproj FILE!

Stuff like for example:

<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>

And then properties for those to use later for compiler:

  <PropertyGroup Condition="'$(IsWindows)'=='true'">
    <DefineConstants>_WINDOWS</DefineConstants>
  </PropertyGroup>
  <PropertyGroup Condition="'$(IsLinux)'=='true'">
    <DefineConstants>_LINUX</DefineConstants>
  </PropertyGroup>

Godot doesn’t like this at all and it will brick your project! The symptoms of this look like it has nothing to do with it. You don’t see any issues at first. The project still compiles and runs fine. But you’ll see issues like unable to set any exported field in the editor or even see any of them set to anything you’ve set them to before.

Went through a huge PITA because of this.

Avoid doing this at all cost. I guess for detecting OS use the appropriate Godot object at runtime not during compilation. Or find other ways of avoiding compilation conditions.

Conditions themselves are fine, for example, something like this will work:

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ExportRelease|AnyCPU'">
    <Optimize>False</Optimize>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
    <Optimize>True</Optimize>
</PropertyGroup>

But what are you trying to achieve here exactly? Because I don’t think this is a godot issue, the code you have provided for the csproj file looks very unusual and likely won’t work in many cases the way you would expect.

Edit:
If you aboslutely need to define those constants, you can do so like this:

<PropertyGroup Condition="'$(RuntimeIdentifier)' == 'win-x64' Or '$(RuntimeIdentifier)' == 'win-x86'">
    <DefineConstants>_WINDOWS</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(RuntimeIdentifier)' == 'linux-x64'">
    <DefineConstants>_LINUX</DefineConstants>
</PropertyGroup>

Just use the pre-processor flag. Its all in the documentation:

Do you happen to know how to define something like GODOT_EDITOR, so i don’t have to go through `Engine.IsEditorHint()` ? It just leaves a bad taste in my mouth to use it.

If you are worried about code performance arising from the branch, you can use a static readonly field.

public static class Game {
    public static readonly bool IsGodotEditor = Engine.IsEditorHint();
}

JIT will treat this as a const field when generating code for the runtime, meaning code in the false side of the branch is entirely omitted from the resultant native code. Same effect as a static branch.

Example:


Assembly only generates the path that returns 1 in this case, since the field is false.

If you really do want to use a static branch, I’m not sure there’s any way to get an equivalent so cleanly.

1 Like

That’s very good to know, makes me feel a lot better