Thursday, July 30, 2009

Building with MSBuild/XBuild in MonoDevelop

I committed today very basic support for building projects using MSBuild / XBuild instead of MonoDevelop's own build system. Ankit has been doing a lot of progress in XBuild, and it is mature enough to build complex projects. XBuild support is for now disabled by default. To try it, you'll have to enable it in the Edit / Preferences / Build options panel.

The integration right now is simple because all it does is to launch the xbuild command in a separate process. That's not the best way of doing it, but the most straightforward. A more optimal option is to use the MSBuild API to load the project and launch the build. That's my next step, but there are some issues with it.

The main problem is that MonoDevelop now supports multiple target runtimes and frameworks. Multiple frameworks are not a problem because MSBuild already has support for that, but it doesn't have support for multiple runtimes.

Multiple runtimes means that for example when running MD on Windows, I can select either Mono or MS.NET as target runtime, and MD will build the project using the selected runtime. Each runtime has its own GAC and set of installed packages, even its own MSBuild version, so I can't use the MSBuild API to load and build the project. The only option in this case is to launch in an external process.

There is however and additional and more hard to fix problem. To get the list of assemblies referenced by a project (for example to do code completion), MonoDevelop right now just enumerates the reference elements defined in the project. When using MSBuild that's not fully correct anymore, since custom targets and tasks may inject references which are not explicitly set in the project. So the only way of getting the real list of references is by loading the MSBuild project and evaluating it, and that won't work when targeting a runtime other that then one running MD.

Anyway, this basic support we have now is good enough for many projects. I'll go step by step.

1 comments:

Stuart said...

Could you launch another process (for the case where the target runtime is different than the MonoDevelop runtime) and then invoke the MSBuild API on it by remoting? That way you can only start a second process when necessary (not when you're building for the same framework as MD is running in), but keep the code largely the same between the two scenarios.