As far as I understand, Roslyn have introduced the concept of Workspaces. One implementation of Workspaces is the MsBuildWorkspace.
My question is, can I from within a custom build task access a Roslyn Workspace representing the project being built?
I suspect that this is the purpose of MsBuildWorkspace. If so, can I access this workspace from the Execute method in my custom task (derived from Microsoft.Build.Utilities.Task)?
In case you are wondering why, I need to traverse other aspects of the project being built.
It is not enough for me to have access to the specific input file of the task to generate the output.
I suspect that this is the purpose of MsBuildWorkspace
No.
The point of MsBuildWorkspace is to parse an MSBuild project or solution into a Roslyn workspace.
MSBuild itself (which is what actually runs your MSBuild task) does not use Roslyn at all (it just invokes the C# compilation task, which is implemented using Roslyn), so there is no existing MsBuildWorkspace that you could fetch.
You could create your own MsBuildWorkspace from the project file.
Related
My colleagues and I have user specific settings in csproj.user files. They are not checked into the repository. I would like for the build server to use its own set of csproj.user files, overriding certain properties, leaving the "base" project configuration at a decent developer default. But from the looks of it there is no such option in the msbuild command-line for doing that.
Is there really no way, other than copy csproj.user-files to where it'll be picked up by subsequent msbuild invocations?
While writing I realize I'm too much of a prude about these things and should just copy as a step prior build. Still posting in case someone knows a better way, for instance a way that does not modify the source tree.
Passing properties to the MSBuild command line overrides properties in the solution, including dependent projects. Here omitting debug information in build server, otherwise generated for release build to improve profiling:
msbuild MySolution.sln /p:DebugType=none ...
This does not work should I want different properties for different projects. Building projects individually should work nicely though.
Finally, passing arguments on command line can get messy, so to get a more "settings file"-like experience one may instead use #file arguments and MSBuild response files.
Suppose we have sequential build, i.e. a single node. msbuild parses the solution file, examines all the project dependencies and decides to build the projects in a certain order.
Is it possible to instruct msbuild just to output this order without actually building anything?
P.S.
I realize I can implement this logic myself using MSBuild API. I can read the solution file and all the projects and build the dependency graph myself. I am specifically curious if msbuild can do it, since it does this logic anyway already.
There are various diagnostic features in MSBuild but currently there isn't a feature that is like reporting a SQL execution plan or like PowerShell's -WhatIf parameter.
You could submit a feature request at dotnet/msbuild.
If you do submit a feature request, provide the link here.
I am building a project on Github written in Objective-C. It resolves MAC addresses down to manufacturer details. The lookup table is currently stored as text file manuf.txt (from the Wireshark project), which is parsed at run-time, which is costly. I would prefer to compile this down to archived objects at build-time, and load that instead.
I would like to amend the build phases such that I:
Build a simple compiler
Run the compiler, parsing manuf.txt and outputting archived objects
Build the framework
Copy the archived objects into the framwork
I am looking for wisdom on how to achieve steps 1 and 2 using Xcode v7.3 as Xcode provides only a Copy Files phase or a Run Script phase. An example of other projects achieving similar goals would be inspiring.
I suspect that what you are asking is possible, but tricky. The reason is that you will need to write a bunch of class files and then dynamically add them to the project.
Firstly you will need to employ a run script phase to run various tools from the command line to parse your file and generate a number of class files from it. I would suggest looking into various templating engines. For example appledoc uses moustache templates to generate API documentation files. You could use the same technique to generate header and implementation files.
Next, rather than generating archived objects an trying to import into a framework. I think you may be better off generating raw source code, adding it to a project and compiling into a framework. Probably simpler in the long run.
To automatically include the generated code I would look into (which means I haven't actually tried this :-) adding a folder reference to the project rather than an Xcode group. Folder references are an option in the 'Add files to ...' dialog.
Folder references refer to a directory and automatically add the entire contents of that directory to a project. So you can use one to point to the directory where you have generated the source code. This is a much better option than trying to manipulate the project or injecting things into an established framework.
I would prefer to parse the file at runtime. After launch you can look for an already existing output, otherwise parse it one time.
However, I have to do something similar at Objective-Cloud. I simply added a run script build phase and put the compiler call into it.
I'm currently working an Eclipse plug-in to provide iPOJO manipulation support.
The principle of iPOJO is to modify the .class files generated by the Java compiler to inject some methods and to add/update an entry to the Manifest.mf file.
Currently, my plug-in provides a project Nature and adds a Builder, added at the end of a project builder list, that calls the iPOJO Manipulator.
I use it on PDE projects.
The complete process works but I have a problem :
When my builder has finished its job (and the building process), the whole building process restarts, erasing the output folder and calling my builder again.
If I don't add a safety trick, it makes the building process loop over and over.
As I work on IResource, an IResourceDeltaEvent must be sent at the end of the building process, so I think the best way to avoid that kind of problem is to hide the fact that the resource has changed.
To be clear, I'm looking for a way to modify the class files after a PDE build, without inducing a new build, and without disabling the workspace auto-build property.
Thanks for answers.
I am a little unclear as to what you are describing.
You mention that you want this to work for PDE builds, but PDE builds happen largely outside of the workspace using ant scripts. They do not use IResource, Builder, or IResourceDeltaEvent.
I am guessing that you don't really mean PDE builds, but rather the building of plugin projects inside of the workspace.
In general, Eclipse (JDT in particular) expects that it has complete control over the output folders. However, there is an option in Preferences -> Java -> Building -> Output Folder called "Rebuild class files generated by others". Ensure that this is disabled. Eclipse should not try to rebuild class files that you touch. If your builder only touches class files then it will not trigger other builds after it changes the class files. The only thing is that you need to be careful not to compile things twice (and I think this is the problem that you are describing).
Alternatively, it may be easier for you to implement a CompilationParticipant (and the org.eclipse.jdt.core.compilationParticipant extension point). This will allow you to know exactly when JDT calls a compilation and exactly what it compiles.
Additionally, you will be notified of reconcile operations (ie- changes in working copies that have not been saved). This may be useful for you if you wanted to manipulate files as-you-type.
So I have a CommonAssemblyInfo.cs linked into all the projects in my solution and is dynamically generated by my rake/albacore scripts which is not checked into source control.
I also have a CommonAssemblyInfo.cs.local for use when there is no ruby available, mainly to be used by devs.
Is it possible to have a msbuild task or something that runs before any of the other project compilation that will copy CommonAssemblyInfo.cs.local to CommonAssemblyInfo.cs before trying to compile my solution? I hate having to have a command you have to just know about and type in order to open and buidl the solution in Visual Studio.
UPDATE
So I ended up using a batch file as a solution wide pre-build event as described here: Solution-wide pre-build event?, it checks to see if CommonAssemblyInfo.cs exists and if not copies CommonAssemblyInfo.cs.local to CommonAssemblyInfo.cs just using a simple batch file.
This is the solution I ended up with.
I have each project in the solution link to a CommonAssemblyInfo.cs which is automagically generated for me by my build scripts (rake + albacore).
Since I cannot check CommonAssemblyInfo.cs into source control, I create a CommonAssemblyInfo.cs.local.
Simple solution: create go.bat which copies CommonAssemblyInfo.cs.local to CommonAssemblyInfo.cs that devs must run the first time they check out the project before opening the solution in VS.
For purely political reasons, if I did this people would have had hissy fits about me doing "nonstandard" things. Complex solution follows:
I created a project in the solution called PreBuild which every project in the solution depends on. This forces the build order to be such that this project is built first. This project contains a pre-build event which calls the following batch file:
echo verifying CommonVersionInfo.cs exists
cd
IF NOT EXIST ..\..\..\CommonAssemblyInfo.cs COPY ..\..\..\CommonAssemblyInfo.cs.local ..\..\..\CommonAssemblyInfo.cs
So now any developers who choose to keep their heads in the sand may checkout the project and blissfully open it up in VS unaware that any build scripts exist at all.
Are you talking about compilation in the VS IDE, or compilation through team build? If you are talking about team build, then you can use the "AfterGet" event as a place to use the standard "copy" msbuild task. If you are talking about the VS IDE, then you can still use the "copy" msbuild task.