Why does headless PDE Build omit directories I've specified in build.properties's bin.includes? - eclipse-plugin

One of my Eclipse plug-ins (OSGi bundles) is supposed to contain a directory (Database Elements) of .sql files. My build.properties shows:
bin.includes = META-INF/,\
.,\
Database Elements/
(...which looks right to me.)
When I build and run from within my interactive Eclipse IDE, everything works fine: calls to Bundle.getEntry(String) and Bundle.findEntries(String, String, bool) return valid URL objects; my tests are happy; my code is happy.
When I build via headless ant script (using PDE Build), those same calls end up returning null. My tests break; my code breaks. I find that Database Elements is quietly but simply missing from my plug-in's JAR package. (META-INF and the built classes still make it in there fine.) I scoured the build log (even eventually invoking ant -verbose on the relevant portion of the build script) but saw no mention of anything helpful.
What gives?

It appears there was a bug (though I was unable to search up a Bugzilla citation) in the PDE Build ant-script generation process as of 3.2 that produced an ant build.xml script fragment like this from the bin.includes:
<copy todir="${destination.temp.folder}/my_plugin" failonerror="true" overwrite="false">
<fileset dir="${basedir}" includes="META-INF/,Database Elements/" />
</copy>
The relevant Ant documentation says that includes contains a "comma- or space-separated list of patterns". Thus (since my directory name contains a space and was copied literally into the includes attribute value) I think the copy task was trying to include a file named Database and a directory named Elements/. Neither existed, so they were quietly ignored. I suspect the same problem would have bitten if I had a comma in my directory name, but I did not test this.
Since I use Eclipse 3.5 interactively, I decided to finally decouple my headless build's Eclipse instance from my target platform (which remains at 3.2 for the moment) and to update my headless PDE Build to 3.5 (by attempting to produce a minimal PDE Build configuration from my interactive instance's plug-ins). Now, the generated build.xml contains this instead:
<copy todir="${destination.temp.folder}/my_plugin" failonerror="true" overwrite="true">
<fileset dir="${basedir}">
<include name="META-INF/"/>
<include name="Database Elements/"/>
</fileset>
</copy>
The relevant Ant documentation this time indicates that the only special characters in an individual include are * and ?. Indeed, the bug seems to have been fixed sometime between 3.2 and 3.5: my 3.5-based headless PDE Build now produces a plugin that contains Database Elements; my tests are happy; my code is happy; I'm happy.

Related

How do I import classes from one project's testpackages to another project's testpackages in netbeans?

In netbeans I can setup several classpaths for a project: compile, processor, run, compile tests, run tests.
In compile tests I added another project. I can now use that other project's src packaged classes, in my own project's test packages.
But I can't use that other project's test packaged classes.
How can I make this happen?
(Do I need to use maven projects instead of regular projects?)
I have found some solutions for this problem here. Suppose that you have a project B using the test classes of project A.
You can include {project A}/build/test/classes/ in the test compilation
classpath for project B.
An other option is to automatically create JAR file from the test classes of project A with this code in build.xml:
<target name="jar-tests" depends="compile-test">
<jar jarfile="testdist/tests.jar">
<fileset dir="${build.test.classes.dir}"/>
</jar>
</target>
Then you can add the JAR to the test compilation
classpath for project B.
The test compilation process can be extended with test JAR generation with this code inserted into build.xml:
<target name="-post-compile-test">
<jar jarfile="testdist/tests.jar">
<fileset dir="${build.test.classes.dir}"/>
</jar>
</target>
It updates the tests.jar every time you compile (or run) the tests.
In the Projects window you can expand the project that you are working on. Right Click on Libraries and select Add Project.... You will get a dialog allowing you to select another Netbeans Project with the Java classes that you wish to use.
OR
When you build the java project in netbeans it creates a jar file on the dist folder in the current project directory. You can use this jar file for the other project as a package by adding this as ADD jar in the next project.

Parallel MSBUILD - critical sections?

My organization has some huge builds that run on build servers, building lots and and lots of MSBUILD projects that are linked with ProjectReferences. We need to be able to build projects and configurations in parallel with msbuild /m.
My problem is that I have a project that is referenced from a large number of other projects, but the project itself is not reentrant. If more that two or more nodes try to build that project in parallel, it will fail.
How can I wrap this one Project, or it's Target, inside a critical section?
What I really need to do is something like this:
<Target>
<EnterCriticalSection ID=$(ProjectGuid) />
<Exec something />
<LeaveCriticalSection ID=$(ProjectGuid) />
</Target>
The idea being that if multiple MSBUILD nodes tried to build this project in parallel, only one of the nodes could do the execution, and the rest of the nodes would have to wait (or go do something else).
I suppose I could write custom MSBUILD tasks to do this, but isn't there some way of doing this built into the MSBUILD system?
=== EDIT 4/5/13. To clarify, the project is building a 3rd-party library with the build script provided for it. Completely rewriting their build script to make it reentrant -- by insuring that each build used a different set of folders for intermediate files, etc. -- is possible in theory, but not a practical solution. For one thing, all that work would would have to be redone on each new release of that library.
=== EDIT 4/6/13. On further reflection, I don't think it's even theoretically possible to insure a project is reentrant. Let me explain:
Suppose project XYZ is set up to use different temporary directories depending on platform and configuration in the usual way:
XYZ.proj:
<PropertyGroup>
<MyWorkingDir>tmp.$(Platform).$(Configuration)</MyWorkingDir>
</PropertyGroup>
Now suppose some other project GraphicsWindow references project XYZ, either through ProjectReferences or MSBuild tasks. And suppose the GraphicsWindow project can be built to use various graphics APIs. I.e., there's an OpenGL version, a DirectX 9 version, a DirectX 10, version...
So somewhere there's a .proj or .targets file containing a target to build all four versions:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ProjectToBuild Include="GraphicsWindow.proj">
<Properties>GraphicsApi=OpenGL</Properties>
</ProjectToBuild>
<ProjectToBuild Include="GraphicsWindow.proj">
<Properties>GraphicsApi=D3D9</Properties>
</ProjectToBuild>
<ProjectToBuild Include="GraphicsWindow.proj">
<Properties>GraphicsApi=D3D10</Properties>
</ProjectToBuild>
<ProjectToBuild Include="GraphicsWindow.proj">
<Properties>GraphicsApi=D3D11</Properties>
</ProjectToBuild>
</ItemGroup>
<Target Name="All">
<MSBuild Projects="#(ProjectToBuild)" BuildInParallel="true" />
</Target>
</Project>
or the equivalent using batching.
Now MSBuild will build the XYZ project 4 times with the same Platform|Configuration combination and the same working directory.
This will work fine as long as you build without the /m option and MSBuild runs a single thread. Depending on how the XYZ project is written, the 2nd, 3rd, and 4th builds might do nothing because the outputs are up-to-date, or it might do some redundant work, but the final result will be correct and the build will succeed.
But as soon as you start using parallel MSBuild, this build is broken! There is now a race condition where multiple threads can enter the XYZ project's target(s) concurrently, and start building using the same working directories, which will fail.
Irrespective of how you execute MSBuild, with multi-proc option /m or without, it is guaranteed to execute a project once for every configuration requested by the build. Here is a quote from MSDN:
When the Microsoft Build Engine encounters a project-to-project (P2P) reference while it is using parallel builds to build a project, it builds the reference only one time. If two projects have the same P2P reference, the reference is not rebuilt for each project. Instead, the build engine returns the same P2P reference to both projects that depend on it. Future requests in the session for the same target are provided the same P2P reference.
If you see the same project built more than once, it means it was referenced in two (or more) different configurations. By configuration here I mean a set of parameters that was passed to the project, e.g. project platform (x86, x64, AnyCPU, etc.,) flavor(debug/retail), localization language, any other parameters you might use.
More often than not, this is problem with mixture of project platforms. For example, you have project A built for x64, project B built for AnyCPU, and both A and B reference C. Now C has to be built twice -- for x64 and AnyCPU. If C correctly handles both platforms by cleanly separating outputs into separate directories, there is no problem. However if C treats x64 and AnyCPU as the same, it will fail randomly in multi-proc build.
Start by inspecting your solution configuration dialog. Make sure all projects have consistent set of platform/configuration parameters. If you have a need to build same project in different configuraions, make sure it puts output into separate locations.

MSBuild - Project-specific targets for solution does not work

I have a solution that has multiple projects in it, including a web application. I want MSBuild to execute "WebPublish" target against the web application project and "default target" for all other projects in the solution.
This MSDN article says that I can do it specifying the command line
msbuild SlnFolders.sln /t:NotInSlnfolder:Rebuild;NewFolder\InSolutionFolder:Clean
But I never could make it work - MSBuild return an error, something like "NotInSlnFolder:Rebuild" target does not exist. It does not matter what target to specify, Build, Rebuild or Clean - it does not work in any case.
How can I achieve my goal of specifying project-specific targets for a solution?
The MSDN documentation does not work. Or have I missed something?
NOTE: This workaround is not officially supported by Microsoft, so there is no guarantee that it will work forever.
Short Answer
In folder with the SLN file, create the file before.{YourSolution}.sln.targets, with the following content: (Replace what in curly brackets to whatever you need.)
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="{MyCompany_MyProduct_WebApp:WebPublish}">
<MSBuild
Condition="'%(ProjectReference.Identity)' == '{$(SolutionDir)MyCompany.MyProduct.WebApp\MyCompany.MyProduct.WebApp.csproj}'"
Projects="#(ProjectReference)"
Targets="{WebPublish}"
BuildInParallel="True"
ToolsVersion="4.0"
Properties="BuildingSolutionFile=true; CurrentSolutionConfigurationContents=$(CurrentSolutionConfigurationContents); SolutionDir=$(SolutionDir); SolutionExt=$(SolutionExt); SolutionFileName=$(SolutionFileName); SolutionName=$(SolutionName); SolutionPath=$(SolutionPath)"
SkipNonexistentProjects="%(ProjectReference.SkipNonexistentProjects)" />
</Target>
</Project>
After that you can execute the command line:
msbuild {YourSolution}.sln /t:{MyCompany_MyProduct_WebApp:WebPublish}
Long Answer
If you add environment variable MSBUILDEMITSOLUTION, setting its value to 1, MSBuild will not delete temporary files generated for the solution and projects.
This will allow you to find {YourSolution}.sln.metaproj and {YourSolution}.sln.metaproj.tmp files generated in the solution folder, which are just standard MSBuild project files.
For MSBuild 3.5, the generated file is {YourSolution}.sln.cache and is retained regardless of environment variables. Analyzing those files, you will understand low-level details of the process and to see the customization opportunities available.
After executing MSBuild with some project-specific target in the .Metaproj file you will find out that the list of project-specific targets is hardcoded and only standard targets are supported (Build, Rebuild, Clean, Compile, Publish; note: Publish and WebPublish are not the same). MSBuild 3.5 only generates Clean, Rebuild and Publish targets as well as a target with just the project's name that means "Build".
You also can see that NotInSlnfolder:Rebuild is just a name of an autogenerated target. In reality MSBuild does not parse it and does not care about project names and location. Also note that the autogenerated target names specify the project name with solution folders hierarchy if it's in one, e.g. SolFolder\SolSubfolder\ProjectName:Publish.
One more critically important thing you will find: The MSBuild Target Name does not support dots. All dots in project names are replaced with underscores. For example, for a project named MyCompany.MyProduct.Components you will have to specify in the command line:
/t:MyCompany_MyProduct_Components:Rebuild
That's why even standard project-specific target Build didn't work - my project name contained dots.
Analyzing file {YourSolution}.sln.metaproj.tmp, you will find out that at runtime it tries to import targets from file named before.{YourSolution}.sln.targets and after.{YourSolution}.sln.targets, if those files exist. This has a key to the workaround for this MSBuild limitation/bug.
You can open your solution file in text editor and check whether following line is exist or not if not then you can add
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> inside the <Project> tag.
Hope this help you.

Using Aspects in a java application - when javac/ajc?

I think about using AspectJ in an existing project.
I have several pure Java Eclipse projects and I like to create an AOP project.
I'm not quite sure about when ajc is needed and when optional. We use Ant (with javac) as our main build and I would like to avoid changing the build.
Is the following possible:
I have a AspectJ enabled Eclipse and create my aspect project. I create a jar from this and include this jar with the aspectj jar in the normal eclipse workspace with the other projects.
The build includes my aspect jar and the aspectj jar as dependency jars with javac.
Is this enough for working with the aspects ?
Or do every project of the application needs to be compiled with ajc ?
The main goal is to keep the current structure of Eclipse setup and build environment as as much as possible as it is now.
Or is this only possible with the annotation style ? (if so can someone link me some information about the weaver and how to do this at runtime ?)
Thank you
If you want to weave your aspect into your codebase, you must use AJC. If you only use javac, even with the annotation, your code won't be weaved by your aspects.
That being said, you don't have to add a lot to your ant build.
something like that should do the job:
<path id="ajclasspath">
<path refid="classpath"/>
<pathelement location="${scm.home}/ant_libs/aspectjrt.jar"/>
</path>
<iajc inpath="${classes.dir}" destDir="${classes.dir}" fork="true" maxmem="${aspectj.maxmem}">
<argfiles refid="aspectj.argfiles.path"/>
<classpath refid="ajclasspath"/>
</iajc>
In fact, you just build like normal and you add a step with the iajc taking your output dir of the javac compile as the inpath and you put the result in the same directory.
You can also take a jar as input to iajc and produce a jar with all your stuff weaved inside.
Edit: Or you can use runtime weaving, if your app is a web application, it is not too bad. If not, i do not recommand runtime weaving, since each time you will start your app, it might be a lot longer to start. I don't have a lot of experience with runtime weaving, but you can check it out. I know you need a aop.xml to define your aspects.
Regards

Ant scripts cccheckin/cccheckout using the CCRC plugin to eclipse?

Is it possible to use Ant scripts to checkin/checkout source code elements while using the CCRC plugin to eclipse? I am getting an error message saying that the element the script is attempting to check out is not part of the VOB, but of course it is there and I can check it out manually.
It should be possible to use those Ant ClearCase tasks with CCRC views ("web views" which are anologous to snapshot views)
A script like this one should work:
<project name="Testing ClearCase " default="CC" basedir=".">
<target name="CC">
<property name="FileSrc" value="MyView/MyVob/MyDir"/>
<property name="dist" value="dist"/>
<cccheckout viewpath="${FileSrc}/myFile"
reserved="false"
nowarn="true"
comment="Auto Build from script"
failonerr="false" />
<copy file="${dist}/myFile" tofile="${FileSrc}/myFile"/>
<cccheckin viewpath="${FileSrc}/myFile"
comment="Checked in by myFile.xml ANT script"
nowarn="false"
failonerr="false"
identical="true"/>
</target>
</project>
But you need to make sure your current directory is (in this script) just above where you update your web CCRC view "myView".
The only issues I know of are:
if CCRC try to checkout a file of a replicated Vob.
if the parent directory of a file to be checked-in was renamed from another view
The Ant ClearCase tasks in VonC's answer use the cleartool command (getClearToolCommand() in org.apache.tools.ant.taskdefs.optional.clearcase.ClearCase.java). When I invoke a cleartool operation, even from within or above the CCRC view, I get the error message from the question.
Now (as some years have passed since VonC's answer) there is a CCRC CLI that can be used instead (http://www-01.ibm.com/support/docview.wss?uid=swg24021929, setting CCSHARED to your top level \eclipse directory). The commands are similar to those provided by cleartool, although as it appears not to support UCM to solve your problem of doing a check out I first had to set an activity on the stream using the CCRC eclipse plugin.
To get the CCRC CLI to work with the ant ClearCase tasks would require changing the task to:
Call rcleartool rather than cleartool.
Since cleartool points to an .exe and rcleartool is a bat for loading a jar, ProcessBuilder won't be able to process the new command (I tested with rcleartool.bat and cmd \c rcleartool.bat) unless you convert the jar to an exe.