Itiviti / gradle-msbuild-plugin

Gradle plugin for msbuild execution, supports C# project files for now
Apache License 2.0
102 stars 57 forks source link

XBuild resolver problem with Mono on OSX #46

Closed novabyte closed 8 years ago

novabyte commented 8 years ago

I think I've stumbled upon a resolution error with the XBuildResolver code. I have Mono installed on OSX via Homebrew:

$ brew info mono
mono: stable 4.2.0.179 (bottled)
Cross platform, open source .NET development framework
http://www.mono-project.com/
/usr/local/Cellar/mono/4.2.0.179 (1010 files, 184M) *
  Poured from bottle
From: https://github.com/Homebrew/homebrew/blob/master/Library/Formula/mono.rb
==> Caveats
To use the assemblies from other formulae you need to set:
  export MONO_GAC_PREFIX="/usr/local"

If I use which I can see:

$ which xbuild
/usr/local/bin/xbuild

xbuild is a "POSIX shell script text executable". The file itself looks like:

#!/bin/sh
exec /usr/local/Cellar/mono/4.2.0.179/bin/mono $MONO_OPTIONS /usr/local/Cellar/mono/4.2.0.179/lib/mono/xbuild/12.0/bin/xbuild.exe "$@"

At the moment with my simple test project I get the following output when run with --info level:

 $ gradle msbuild --info
Starting Build
Settings evaluated using settings file '/master/settings.gradle'.
Projects loaded. Root project using build file '/Users/novabyte/Projects/TestMSBuild/build.gradle'.
Included projects: [root project 'TestMSBuild']
Evaluating root project 'TestMSBuild' using build file '/Users/novabyte/Projects/TestMSBuild/build.gradle'.
All projects evaluated.
Selected primary task 'msbuild' from project :
Tasks to be executed: [task ':msbuild']
:msbuild (Thread[main,5,main]) started.
:msbuild
Executing task ':msbuild' (up-to-date check took 0.0 secs) due to:
  Task has not declared any outputs.
Resolved xbuild to: /usr/local/lib/mono/xbuild/14.0/bin/xbuild.exe
Starting process 'command '/usr/local/lib/mono/xbuild/14.0/bin/xbuild.exe''. Working directory: /Users/novabyte/Projects/TestMSBuild Command: /usr/local/lib/mono/xbuild/14.0/bin/xbuild.exe /nologo /Users/novabyte/Projects/TestMSBuild/TestMSBuild.csproj /t:Build /v:normal /p:Project=TestMSBuild /p:IntermediateOutputPath=/Users/novabyte/Projects/TestMSBuild/build/msbuild/obj\ /p:OutputPath=/Users/novabyte/Projects/TestMSBuild/build/msbuild/bin\
Successfully started process 'command '/usr/local/lib/mono/xbuild/14.0/bin/xbuild.exe''
/usr/local/lib/mono/xbuild/14.0/bin/xbuild.exe: /usr/local/lib/mono/xbuild/14.0/bin/xbuild.exe: cannot execute binary file
:msbuild FAILED
:msbuild (Thread[main,5,main]) completed. Took 0.278 secs.

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':msbuild'.
> Process 'command '/usr/local/lib/mono/xbuild/14.0/bin/xbuild.exe'' finished with non-zero exit value 126

* Try:
Run with --stacktrace option to get the stack trace. Run with --debug option to get more log output.
BUILD FAILED
Total time: 3.7 secs

I believe the problem is that the plugin is trying to invoke xbuild.exe directly on OSX which does not work without being called by the Mono runtime. I think the plugin should use the xbuild POSIX script to execute a build.

timotei commented 8 years ago

Do you also have the "normal" mono runtime installed, without using macports or brew or fink? Because it seems you also have it installed in /usr/local/lib.

Just tested this particular case and indeed, seems it's better to parse the contents of the xbuild file to detect the root of the current xbuild.

novabyte commented 8 years ago

Hi @timotei. Thanks for getting back to me. I installed the standard Mono runtime using brew install mono with Homebrew. I also have Unity Editor installed as well as Xamarin. It may be that another installation is being used to look up the path to the Mono runtime.

novabyte commented 8 years ago

@timotei Is there some way I can override the XBuildResolver and supply my own implementation with the plugin?

timotei commented 8 years ago

Sorry @novabyte, was pretty busy and couldn't look at it. I'll do it after 13th of September if not solved by then :)

With regards to the resolver, the msbuild plugin has the resolver property which you can set to an implementation of IExecutableResolver.

novabyte commented 8 years ago

@timotei Perfect. I'll work around it with my own implementation of IExecutableResolver. :smile:

timotei commented 8 years ago

If you feel that you can contribute it back (and is general enough), feel free to open a Pull Request ;)

novabyte commented 8 years ago

@timotei If I get some time I'll generalise the IExecutableResolver for xbuild and submit a PR but right now I've completely hacked the project together to move forwards quickly with:

class CustomXBuildResolver implements IExecutableResolver {

  ProcessBuilder executeDotNet(File exe) {
    return new ProcessBuilder("mono", exe.toString());
  }

  void setupExecutable(Msbuild msbuild) {
    msbuild.executable = "xbuild";
    msbuild.msbuildDir = "/usr/local/bin"; // hardcode path 
  }

}

It is of course no use at all in the general case.

timotei commented 8 years ago

First problem is that on Mac OS X we can't "associate" .exe files to the mono runtime, like we can on Linux. Also for some reason the test is failing but it wasn't at the time I implemented the support.

@novabyte Could you maybe check my pr https://github.com/Ullink/gradle-msbuild-plugin/pull/47 here?

novabyte commented 8 years ago

@timotei Sure. I'll take a look tomorrow morning - I'm away from the laptop atm. :smiley:

timotei commented 8 years ago

@novabyte Any update?

novabyte commented 8 years ago

Hi @timotei Sorry I've not gotten back to you sooner. Things have been very busy (as always). Everything works very well; I tested with the latest 2.11 release. No more need for my workaround. :smiley: