Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 362966

Summary: option to let BREE define the JDK we compile against
Product: z_Archived Reporter: Jan Sievers <jan.sievers>
Component: TychoAssignee: Jan Sievers <jan.sievers>
Status: RESOLVED FIXED QA Contact:
Severity: enhancement    
Priority: P3 CC: bernd.vogt, igor, kim.moir, stephan.herrmann, stephan.leichtvogt
Version: unspecified   
Target Milestone: ---   
Hardware: All   
OS: All   
See Also: https://bugs.eclipse.org/bugs/show_bug.cgi?id=461239
Whiteboard:
Bug Depends on:    
Bug Blocks: 407500    

Description Jan Sievers CLA 2011-11-05 07:00:18 EDT
We should have an option to let the "Bundle-RequiredExecutionEnvironment" MANIFEST header define the JDK to compile against. (compiler source and target level are already deduced from BREE).

One idea is to have maven properties

${J2SE-1.5}, ${JavaSE-1.6} etc. define the respective JAVA_HOME of the JDK matching the required execution environment.
These properties could be defined in settings.xml.

May also consider using maven toolchains to define the JDKs.

Originally reported as https://issues.sonatype.org/browse/TYCHO-547
Comment 2 Igor Fedorenko CLA 2011-11-09 14:41:55 EST
Can't build tycho on OSX after this change

java.lang.AssertionError: expected:<2> but was:<0>
	at org.junit.Assert.fail(Assert.java:91)
	at org.junit.Assert.failNotEquals(Assert.java:645)
	at org.junit.Assert.assertEquals(Assert.java:126)
	at org.junit.Assert.assertEquals(Assert.java:470)
	at org.junit.Assert.assertEquals(Assert.java:454)
	at org.eclipse.tycho.compiler.jdt.CompilerMainTest.testHandleBootclasspath(CompilerMainTest.java:53)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
	at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Comment 3 Jan Sievers CLA 2011-11-10 04:56:29 EST
right.

this is a problem in the test which does not take special handling of ../Classes folder on Mac OS into account

will fix.
Comment 5 Bernd Vogt CLA 2012-01-30 09:49:53 EST
There is still a problem...

The JDT compiler expects the home directory of a JRE and not of a JDK as input.

Configuring JDKs via the toolchains.xml ends in "The type java.lang.Object cannot be resolved" errors. The compiler is not able to find and link the rt.jar and others, because he expects them uner "<java_home>/lib/" where it is actually located under "<java_home>/jre/lib/".

As workaround I use JRE home directories in the toolchains.xml:

<?xml version="1.0" encoding="UTF8"?>
<toolchains>
  <toolchain>
     <type>jdk</type>
     <provides>
         <version>1.6</version>
         <id>JavaSE-1.6</id>
     </provides>
     <configuration>
        <jdkHome>D:\bin\java\jdk1.6.0_21\jre</jdkHome>
     </configuration>
  </toolchain>
  <toolchain>
     <type>jdk</type>
     <provides>
         <version>1.5</version>
         <id>J2SE-1.5</id>
     </provides>
     <configuration>
        <jdkHome>D:\bin\java\jdk1.5.0_22\jre</jdkHome>
     </configuration>
  </toolchain>
</toolchains>

P.S.: Nice solution to use the toolchains.xml!
Comment 6 Jan Sievers CLA 2012-01-30 10:34:36 EST
(In reply to comment #5)
> There is still a problem...
> 
> The JDT compiler expects the home directory of a JRE and not of a JDK as input.
> 
> Configuring JDKs via the toolchains.xml ends in "The type java.lang.Object
> cannot be resolved" errors. The compiler is not able to find and link the
> rt.jar and others, because he expects them uner "<java_home>/lib/" where it is
> actually located under "<java_home>/jre/lib/".

Not sure how to deal with this. You should have gotten a warning for an empty bootclasspath though, see

http://git.eclipse.org/c/tycho/org.eclipse.tycho.git/commit/?id=57d96722027bde31f2294eba3f9745d164aebac4

the problem here is that there is no spec I know of that says how to find the JRE home relative to the JDK home. IIRC it may be like this by default on windows but you could also choose entirely different installation locations for JDK and JRE.  No idea what happens on other platforms.

What about changing the warning in case of an empty boot classpath into a build error?
Comment 7 Jan Sievers CLA 2012-01-30 10:43:37 EST
(In reply to comment #6)
> What about changing the warning in case of an empty boot classpath into a build
> error?

forget it. The bootclasspath is not empty in this case, it just doesn't contain rt.jar (which is not called rt.jar on all platforms...).
The only thing I could think of is to check whether java.lang.Object can be loaded from a classloader initialized with the given bootclasspath, but this seems little over the top...
Comment 8 Bernd Vogt CLA 2012-01-31 02:48:19 EST
(In reply to comment #7)
> The only thing I could think of is to check whether java.lang.Object can be
> loaded from a classloader initialized with the given bootclasspath, but this
> seems little over the top...

I agree with you.. that sounds a bit oversized...

What do you think about making assumptions? Like the JDT does when investigating the installed JREs and Execution Environments (see org.eclipse.jdt.internal.launching.StandardVMType).

Because we assume that we have a jdk home configured in the toolchains.xml we could
1.) Look for a variable called "jreHome" in the toolchain configuration model (see snippet below)
2.) if not present, look for <home>/jre/lib/*.jar
3.) if empty, look for <home>/lib/rt.jar and collect all jar files in that folder if the rt.jar is present
4.) if we dont have any jars until here... fail with an appropriate error message

I think this approach will cover most cases out of the box. And if a users JRE actually is located somewhere else, he can configure them via the new variable "jreHome".


jreHome:

<toolchain>
     <type>jdk</type>
     <provides>
         <version>1.6</version>
         <id>JavaSE-1.6</id>
     </provides>
     <configuration>
        <jdkHome>D:\bin\jdks\jdk1.6.0_21\</jdkHome>
        <jreHome>D:\bin\jres\jre1.6.0_21\</jreHome>
     </configuration>
  </toolchain>
Comment 9 Jan Sievers CLA 2012-01-31 03:19:47 EST
(In reply to comment #8)
> What do you think about making assumptions? Like the JDT does when
> investigating the installed JREs and Execution Environments (see
> org.eclipse.jdt.internal.launching.StandardVMType).
> 
> Because we assume that we have a jdk home configured in the toolchains.xml we
> could
> 1.) Look for a variable called "jreHome" in the toolchain configuration model
> (see snippet below)
> 2.) if not present, look for <home>/jre/lib/*.jar
> 3.) if empty, look for <home>/lib/rt.jar and collect all jar files in that
> folder if the rt.jar is present
> 4.) if we dont have any jars until here... fail with an appropriate error
> message

I am not sure if jreHome will work with the toolchains API.
But first scanning <home>/jre/lib/*.jar and only if empty, fall back to scanning <home>/lib/*.jar is probably a good idea.
Comment 10 Bernd Vogt CLA 2012-01-31 03:41:49 EST
(In reply to comment #9)
> I am not sure if jreHome will work with the toolchains API.

It seems that the <configuration /> section of the toolchains uses the same generic approach like the maven plugin configuration sections. After casting the toolchain object to "ToolchainPrivate" it is accessible:

Xpp3Dom cfg = (Xpp3Dom) toolchainPrivate.getToolchainModel().getConfiguration();

> But first scanning <home>/jre/lib/*.jar and only if empty, fall back to
> scanning <home>/lib/*.jar is probably a good idea.

If we fall back from <home>/jre/lib to <home>/lib it should be a requirement that the rt.jar is contained in <home>/lib. Otherwise there is the danger that we pick up only the JDK jars (tools.jar,...) and run into "java.lang.Object
cannot be resolved" errors which makes it difficult for the user to find the actual problem.
Comment 11 Jan Sievers CLA 2012-01-31 04:10:10 EST
(In reply to comment #10)
> (In reply to comment #9)
Another option could be to do the same as JDT. They spawn a java process to print bootclasspath and ext/endorsed dirs based on systwm properties, see [1]. This seems more robust to me.

This topic needs some more investigation and I propose to open a new enhancement bug where this should be discussed.

[1] http://grepcode.com/file/repository.grepcode.com/java/eclipse.org/3.6/org.eclipse.jdt/launching/3.5.100/org/eclipse/jdt/internal/launching/support/LibraryDetector.java
Comment 12 Bernd Vogt CLA 2012-01-31 06:06:46 EST
(In reply to comment #11)
> Another option could be to do the same as JDT. They spawn a java process to

Yes, seems rather robust for me too. Unfortunately this solution depends on implementor specific proeprties (sun.boot.class.path, com.ibm.oti.system.class.path). Although... I also don't believe that the name of the rt.jar is specified in any specification?

The advantage of the "java process" approach is, that it allows us a finer grained detection of single jars... but then we have to configure the JDT compiler with single jars also (instead of the one java home directory).

We could also use the "java process" approach to determine the directory of the JRE that is related to our JDK via the "java.home" property and set this to the JDT compiler.

So, the question is, do you prefer a 99% correct solution which is more complex or a pragmatic one? :-) 

> This topic needs some more investigation and I propose to open a new
> enhancement bug where this should be discussed.

Your decision.. but I think we have most of the possible alternatives already mentioned :-)
Comment 13 Bernd Vogt CLA 2012-02-01 02:59:01 EST
Ok.. here's another possible alternative...

What about forking? Now that we are capable of detecting the java executable, it should be easy to start the compiler in its own process?
Comment 14 Stephan Leicht Vogt CLA 2012-11-14 09:38:59 EST
What happened to this thread. It seems that there are still open issues here, but nothing new since February.

Thanks for an update.
Greetings Stephan
Comment 15 Jan Sievers CLA 2012-11-14 09:42:31 EST
(In reply to comment #14)
> What happened to this thread. It seems that there are still open issues
> here, but nothing new since February.
> 
> Thanks for an update.
> Greetings Stephan

custom bootClassPath should be fixed in 0.17.0-SNAPSHOT, refer to bug 389856
Comment 16 Stephan Leicht Vogt CLA 2012-11-14 09:48:25 EST
Thank you Jan.
Comment 17 Tobias Oberlies CLA 2013-01-11 05:39:51 EST
(In reply to comment #14)
> What happened to this thread.
Discussions shouldn't happen on resolved/closed bugs. If the original problem persists, reopen the bug. If there is a related/follow-up problem, open a new bug.
Comment 18 Stephan Leicht Vogt CLA 2013-01-11 05:42:41 EST
That's ok. Thanks and greetings.
Stephan
Comment 19 Stephan Herrmann CLA 2017-12-11 18:17:37 EST
(In reply to Jan Sievers from comment #11)
> This topic needs some more investigation and I propose to open a new
> enhancement bug where this should be discussed.

Did this ever happen, or is everybody just happy with having to specify a JRE for <jdkHome>?
I seem to recall that this might create an incompatibility with other consumers of toolchains, but can't remember which.
Comment 20 Stephan Herrmann CLA 2017-12-11 18:56:05 EST
(In reply to Stephan Herrmann from comment #19)
> (In reply to Jan Sievers from comment #11)
> > This topic needs some more investigation and I propose to open a new
> > enhancement bug where this should be discussed.
> 
> Did this ever happen, or is everybody just happy with having to specify a
> JRE for <jdkHome>?
> I seem to recall that this might create an incompatibility with other
> consumers of toolchains, but can't remember which.

Found it: bug 461239. To use both tycho and xtend in a toolchains-aware project, you have to jump through hoops to reconcile the non-standard interpretation in tycho with the standard interpretation in xtend-maven-plugin.