3

There is some opensource project, which should be build on windows and on Linux. On Linux it should be built differently, and I want to use LINUX preprocessor constant in C# sources included to .csproj for that, i.e.

#if !LINUX
    // windows specific code (some TFS integration)
#else
    // linux specific code (absence of TFS integration)
#endif

but the same .csproj is used in both Windows and Linux builds, and I can't just add define to project settings in .csproj like this (because this define will be effective for both platforms):

-    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DefineConstants>DEBUG;TRACE;LINUX</DefineConstants>

It is possible to create 2 more separate configurations, and pass the configuration name to msbuild from command line. But this violates DRY principle (configurations are duplicated with no need to do that).

It is possible to determine OS authomatically during build, instead of passing this information from outside.

People recommended me to create and include script (for example operating_system.targets, or should it be operating_system.props?) and use it from projects, like this:

     <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
     <Import Project="$(SolutionDir)\.nuget\NuGet.targets" />
+    <Import Project="$(SolutionDir)\operating_system.targets" />

There are several ways to determine operating system, for example http://www.mono-project.com/docs/faq/technical/#how-to-detect-the-execution-platform

if (Type.GetType("Mono.Runtime") != null) 
    IsMono = true; // we're on Mono
else
    IsMono = false;

int p = (int) Environment.OSVersion.Platform;
if ((p == 4) || (p == 6) || (p == 128)) {
    IsUnix = true; // we're on Unix
} else {
    IsUnix = false;
}

public static bool IsLinux
{
    get {
        bool isLinux = System.IO.Path.DirectorySeparatorChar == '/';
        return isLinux;
    }
}

and there is also __MonoCS__ define - see How can I conditionally compile my C# for Mono vs. Microsoft .NET? (I can't use just __MonoCS__, because it will be defined while compiling with mono compiler on Windows)

So, I want an example of that operating_system.targets file, which will define LINUX constant for C# code when project compiles on linux.

Community
  • 1
  • 1
user1709408
  • 528
  • 4
  • 16
  • Two thoughts: 1) Create multiple configurations with different DefineConstants and filter the platform-specfic code in/out and out. This is simple but CIL assemblies are now platform-locked, testing become a nightmare,.... 2) The other thought is that platform-specfic CIL execution should be done via run-time checks (not compile time) and thus your CIL assemblies are portable even if they contain code that would not run on another platform. Mono dev list discussions about this and the answer is **always** go w/portable CILs, never compile time... thus your question go away, just compile once. – SushiHangover Nov 06 '15 at 10:08
  • This will require me to compile all windows assemblies on my OS, even if i don't need them (i.e. TFS integration) – user1709408 Nov 06 '15 at 10:17
  • Isolate your platform specific so that is never called / loaded... think like it is a PCL assembly that has contracts to platform specific code (native or CIL based), or actually just use PCL assemblies ... If that comes with a time/coding burden that you do not have, just create multiple DefineConstants and document your xbuild/msbuild configurations and stop there. – SushiHangover Nov 06 '15 at 10:27
  • multiple configurations lead to multiple project files (because users of different IDEs prefer not to interfere with each other), and these different .csproj files require synchronization between them. See NLog project for this (bad) example - https://github.com/NLog/NLog/pull/958 – user1709408 Nov 06 '15 at 11:25
  • Just one .csproj per assembly, different build configurations inside, and this project goes from Linux to OS-X to Windows and flips between XS/MD and VS, xbuild and msbuild, if not you are doing it wrong ;-) . People are doing it this way everyday, just because one OOS project does it another way does not mean that you have to.... – SushiHangover Nov 06 '15 at 14:54

0 Answers0