Bug 303960 - Ability to override javac task during pde builds
Summary: Ability to override javac task during pde builds
Status: RESOLVED FIXED
Alias: None
Product: PDE
Classification: Eclipse Project
Component: Build (show other bugs)
Version: 3.5.2   Edit
Hardware: Macintosh Mac OS X - Carbon (unsup.)
: P3 enhancement (vote)
Target Milestone: 3.6 M6   Edit
Assignee: pde-build-inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 147432 (view as bug list)
Depends on:
Blocks:
 
Reported: 2010-02-25 14:48 EST by Andrew Eisenberg CLA
Modified: 2010-11-22 12:51 EST (History)
4 users (show)

See Also:


Attachments
First attempt at patch (6.99 KB, patch)
2010-02-26 16:44 EST, Andrew Eisenberg CLA
no flags Details | Diff
new patch (10.89 KB, patch)
2010-02-26 17:51 EST, Andrew Niefer CLA
no flags Details | Diff
Test cases (2.61 KB, patch)
2010-02-28 22:25 EST, Andrew Eisenberg CLA
no flags Details | Diff
Updated test cases. (20.47 KB, patch)
2010-03-02 18:33 EST, Andrew Eisenberg CLA
aniefer: iplog+
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Andrew Eisenberg CLA 2010-02-25 14:48:39 EST
I posted this to the pde-dev mailing list and was asked to raise a bug, so here it is:

---

I am trying to work on the pde export facilities of AJDT (aspectj tool
support for Eclipse).  Currently, AJDT provides custom wizards for
exporting plugins, features, and products, as well as headless build
support.  The problem is that these wizards are essentially a copy of
pde export wizards.  And this is difficult to maintain for each new
release.

For the Helios release, I am considering a different approach for
aspectj aware pde export and pde builds.

Essentially, the requirement is that the pde build happens as normal,
except that the javac call should be replaced with a call to iajc
(with a few extra options).  I've been playing around a bit and I am
able to get this mostly working through a customBuildCallBack.xml
script and adding some ant commands to the @dot.post.compile task.  In
this task, I first delete the class files created by the javac call,
and then I call the iajc task.  There are some problems, however:

1. This feels hacky.  The code is compiled twice and the results of
the first compile is deleted.
2. The javac call will likely have some compile errors (expected
because javac cannot compile the aspects).  These errors will be
logged and can be confusing to users.
3. Source bundles will not include the *.aj files unless there is
something added to the customBuildCallBack.xml script (I think...I
haven't actually tried to fix this yet).

Note that I am having this problem with AspectJ-aware bundles, but I
know this is also a problem for Groovy-aware bundles.  And I expect
that scala-aware modules and any other Java-like language will have
the same problem.

Any ideas on a more graceful solution to the porblem?  I see:
https://bugs.eclipse.org/bugs/show_bug.cgi?id=105631 but I don't know
how relevant that is.
Comment 1 Andrew Eisenberg CLA 2010-02-25 15:09:03 EST
Responding to my initial comment, Andrew Neifer suggested that I look into overriding the ${build.compiler} property in the build.properties file of the plugin.  

However, when I tried this, it does not work.  I think the problem has to do with the following line in ModelBuildScriptGenerator.java (line 927 in 3.6M5):
		script.printProperty(PROPERTY_BUILD_COMPILER, JDT_COMPILER_ADAPTER);

PROPERTY_BUILD_COMPILER should be set according to what is in the build.properties file, rather than being fixed to JDT_COMPILER_ADAPTER.

I think it would be a fairly simple fix to get this property from build.properties rather than having it fixed.  I can submit a patch.

But, this is only part of the solution.  I need a way to pass in arbitrary compiler and vm arguments.  I also need a way to specify which file extensions are included in the source bundle.
Comment 2 Andrew Niefer CLA 2010-02-25 15:23:47 EST
I didn't meant to imply this works today, we will need to make changes to read the property from the bundle's build.properties.  We will actually need to set it directly as an attribute on the javac task.

Currently, build.compiler needs to be set by the top level build configuration.  You might be able to set it in your Ant -> Runtime -> Properties preferences to try things with export.
Comment 3 Andrew Eisenberg CLA 2010-02-25 22:44:01 EST
And presumably, the same would need to happen for the ${compilerArg} property.  This would allow the passing of an arbitrary command line.

As for source bundles, I think it would be sufficient to add a new property supported by build.properties (such as javaLikeFileExtensions), which contains a comma separated list of all recognized file extensions of Java-like files in the project (eg- *.java, *.groovy, *.aj, etc).  If omitted, this defaults to *.java.  The file extensions in javaLikeFileExtensions would have to be used in the generated build.xml whenever an ant fileset specifies **/*.java.

Again, this does not seem to be a big change to ModelBuildScriptGenerator.  I have not been able to try this out, but my guess is that this would be sufficient for what I need.  If you think this is a reasonable suggestion, I can submit a patch.
Comment 4 Andrew Niefer CLA 2010-02-26 08:54:11 EST
(In reply to comment #3)
> As for source bundles, I think it would be sufficient to add a new property
> supported by build.properties (such as javaLikeFileExtensions), which contains
> a comma separated list of all recognized file extensions of Java-like files in
> the project (eg- *.java, *.groovy, *.aj, etc).  If omitted, this defaults to
> *.java.  The file extensions in javaLikeFileExtensions would have to be used in
> the generated build.xml whenever an ant fileset specifies **/*.java.
> 
> Again, this does not seem to be a big change to ModelBuildScriptGenerator.  I
> have not been able to try this out, but my guess is that this would be
> sufficient for what I need.  If you think this is a reasonable suggestion, I
> can submit a patch.

This also would affect what gets copied into the binary bundles, currently, everything under the source folders that aren't *.java or package.html will be copied (this is generally *.properties files).  But if your sources are some other extension then they get copied into the binary bundle when you didn't intend them to.

How about "sourceFileExtensions" instead of "javaLike".
Comment 5 Andrew Eisenberg CLA 2010-02-26 15:16:13 EST
(In reply to comment #4)
> This also would affect what gets copied into the binary bundles, currently,
> everything under the source folders that aren't *.java or package.html will be
> copied (this is generally *.properties files).  But if your sources are some
> other extension then they get copied into the binary bundle when you didn't
> intend them to.
Yes.  I meant to say that, but neglected to mention it.

> How about "sourceFileExtensions" instead of "javaLike".
Sure.
Comment 6 Andrew Eisenberg CLA 2010-02-26 16:44:31 EST
Created attachment 160373 [details]
First attempt at patch

Here's a first go at the patch to allow javac to be overridden.  I allow for 3 new properties to be specified in build.properties:

build.compiler : the compiler adapter
sourceFileExtensions : list of file extensions of recognized source files
compilerArg : an argument line passed to the compiler

If any of these are missing, then they default to the current values (ie- org.eclipse.jdt.core.JDTCompilerAdapter, *.java, and "").

If this looks good to you, I can provide some tests as well.
Comment 7 Andrew Niefer CLA 2010-02-26 17:51:11 EST
Created attachment 160383 [details]
new patch

The file extension part was good.
For "build.compiler" and "compilerArg", both of those properties are likely to have been previously declared by the headless build environment for all bundles.  Ant properties don't change, so setting them here like this won't work.

Instead we basically generate the bundle's build.properties settings directly into the xml.  For the compiler adapter, we write the value directly into a <javac/> compiler attribute.
Similarly the value for the compilerArg is generated directly as a <compilerarg/> element in the xml.

Also, we are already passing some arguments to the compiler: the original ${compilerArg}, a "-log", and a "@" argument file.  It is likely that the global settings for compileArgs won't necessarily work in a different compiler adapter, so I left that being specific to the global ${build.compiler}.
for the log and the arg file, I added two more properties that the bundle can set if its custom compiler adapter will understand those options.

With this new patch, the properties are:
sourceFileExtensions : as before
compilerArg : as before

compilerAdapter : a custom compiler adapter to use
compilerAdapter.useLog : set to "true" to receive the -log argument
compilerAdapter.useArgFile : set to "true" to receive the '@' argument file

I haven't tested any of this.

Would there be any need for a bundle to use more than one compiler adapter (ie, some regular java + some aspect or groovy)?  We could do compilerAdapter.<library>, and allow setting a different adapter on each library.  You could then have a bundle something like:

my.bundle_1.0.0.jar:
   - META-INF/MANIFEST.MF:
            Bundle-Classpath: java/, groovy/
            Eclipse-BundleShape: jar
   - java/**/*.class
   - groovy/**/*.class  (assuming groovy generates class files)

build.properties
  src.java = src_java/
  src.groovy = src_groovy/
  compilerAdapter.groovy = myGroovyAdapter

We can't separate on source folder, only library.
Comment 8 Andrew Eisenberg CLA 2010-02-26 18:31:21 EST
Thanks for the quick response.  

(In reply to comment #7)
> compilerAdapter.useLog : set to "true" to receive the -log argument
> compilerAdapter.useArgFile : set to "true" to receive the '@' argument file
Any reason not to set these to true by default?  The compilers that I work with are basically JDT-derived and so should be able to accept all arguments that the jdt compiler accepts.  And I'd bet that compiler adapters that would not accept these arguments would just ignore them.  (This is a minor point though.)

> Would there be any need for a bundle to use more than one compiler adapter (ie,
> some regular java + some aspect or groovy)?  We could do
> compilerAdapter.<library>, and allow setting a different adapter on each
> library. 
I can't see why this would be useful.  All of these kinds of projects that I know of use a single builder/compiler that compile all kinds of source files (this is important to ensure integration with JDT).
Comment 9 Andrew Eisenberg CLA 2010-02-28 22:25:07 EST
Created attachment 160446 [details]
Test cases

Here are a few tests for the new functionality.  The tests just ensure that the proper parts of the build script are created when these new properties are set.
Comment 10 Andrew Eisenberg CLA 2010-02-28 23:35:25 EST
And I have successfully built aspectj-aware bundles and products with several kinds of settings.  So, I can say that the patch is sufficient for my purposes.  

What are the chances that this can get into 3.6 before the api freeze?  If this can make it into 3.6, then I can remove a massive amount of unmaintainable code from AJDT that includes 3 wizards that are essentially copies of pde.ui code (I know that Chris would be happy about this).

The only annoying part of this whole exercise has been the fact that org.apache.tools.ant.taskdefs.Javac is built to ignore any source files that do not end with .java.  Perhaps this can be changed in future versions of ant.
Comment 11 Andrew Niefer CLA 2010-03-01 18:26:59 EST
I changed the default for -log and @arg file to be true(In reply to comment #8)
> Thanks for the quick response.  
> 
> (In reply to comment #7)
> > compilerAdapter.useLog : set to "true" to receive the -log argument
> > compilerAdapter.useArgFile : set to "true" to receive the '@' argument file
> Any reason not to set these to true by default?  The compilers that I work with
> are basically JDT-derived and so should be able to accept all arguments that
> the jdt compiler accepts.  And I'd bet that compiler adapters that would not
> accept these arguments would just ignore them.  (This is a minor point though.)

I changed the default to true.  The thing to be careful is supporting comments in the argument file using '#'.  PDE/Build passes encoding and access rules to the jdt compiler adapter using comments that start with 
#ADAPTER#ACCESS# and #ADAPTER#ENCODING#.

I release my patch here for the I Build, but it looks like your test patch is incomplete.  Also, if possible can you write the test to use AntUtils to validate the ant script so that the tests don't break easily if the xml changes a little.  See ScriptGenerationTests#testSimpleClasspath and testBug238177 as examples.
Comment 12 Andrew Eisenberg CLA 2010-03-02 18:33:54 EST
Created attachment 160713 [details]
Updated test cases.

Updated test cases.  Added a few more, and now using AntUtils as described in the previous comment.
Comment 13 Andrew Niefer CLA 2010-03-03 11:10:37 EST
Comment on attachment 160713 [details]
Updated test cases.

patch released with minor changes
Comment 14 Andrew Niefer CLA 2010-03-03 11:38:59 EST
(In reply to comment #10)
> The only annoying part of this whole exercise has been the fact that
> org.apache.tools.ant.taskdefs.Javac is built to ignore any source files that do
> not end with .java.  Perhaps this can be changed in future versions of ant.

Andrew, do you guys have a work around for this?
It looks like the CompilerAdapter could get Javac#getSrcDir() and redo the source scan yourself.  It would be annoying having to scan a second time, but I think it would work.


For the record, Andrew raised
 https://issues.apache.org/bugzilla/show_bug.cgi?id=48829

I have released the tests, so I think this is done.
Comment 15 Andrew Eisenberg CLA 2010-03-03 12:17:35 EST
(In reply to comment #14)
> Andrew, do you guys have a work around for this?
I do have a workaround, but it's not particularly pretty.

Thanks for getting this resolved.
Comment 16 Andrew Niefer CLA 2010-03-26 13:27:52 EDT
*** Bug 147432 has been marked as a duplicate of this bug. ***
Comment 17 Alain CLA 2010-11-22 11:23:38 EST
Hi

I tried to just add the two lines to the build.properties of my plugin:

compilerAdapter=org.eclipse.ajdt.core.ant.AJDT_AjcCompilerAdapter
sourceFileExtensions=*.java, *.aj

But the .project contains still the lines:

...
<buildCommand>
	<name>org.eclipse.jdt.core.javabuilder</name>
	<arguments>
	</arguments>
</buildCommand>
...

If I now run the headless buckminster build, then the classes dont get woven.

Do you have any examples, on how to set the thins up usin eclipse 3.6?

Kind Regards, Alain.
Comment 18 Andrew Eisenberg CLA 2010-11-22 12:51:25 EST
I have not tried this out on Buckminster, and I know little about how it works, so I am not sure it this mechanism will be sufficient for Buckminster builds.

However, Buckminster relies on eclipse project natures and eclipse builders.  So, you need to make sure that your project is an AspectJ project and that the ajnature and builder are included in the ,project file.  I do not believe that Buckminster uses the build.properties file at all (but I may be mistaken about that).

(In reply to comment #17)
> Hi
> 
> I tried to just add the two lines to the build.properties of my plugin:
> 
> compilerAdapter=org.eclipse.ajdt.core.ant.AJDT_AjcCompilerAdapter
> sourceFileExtensions=*.java, *.aj
> 
> But the .project contains still the lines:
> 
> ...
> <buildCommand>
>     <name>org.eclipse.jdt.core.javabuilder</name>
>     <arguments>
>     </arguments>
> </buildCommand>
> ...
> 
> If I now run the headless buckminster build, then the classes dont get woven.
> 
> Do you have any examples, on how to set the thins up usin eclipse 3.6?
> 
> Kind Regards, Alain.