Is there a standard way to include jars/dlls in pods? Something based on simple conventions (supporting multiple platforms in the same pod) would be just great.
For DLLs, I'm referring to .NET DLLs above, but it would also be good to have a place to put native code (for different OSs/architectures) in each pod, too. Some of the native libraries would be used by both .NET and Java. Others would be specific to each of the high level platforms.
Thoughts?
brianWed 14 Jan 2009
The pod files are already used to store the Java classfiles, and that is pretty easy to control with classloaders. .NET isn't quite so clean - you have to store it to disk if you want to use pdb files to get line numbers which I personally think is design flaw. But still we could unpack them to disk.
Although this is really more a deployment issue, how do you package stuff up for installation - which kinds of leads to Fan's version of RubyGems/Maven.
A very simple solution might be to put an "unpack" directory into a pod which got extracted on startup to the file system.
tompalmerFri 23 Jan 2009
What I mean, is say I want to include a separate 3rd-party library as part of my pod, and it would be automatically added to the classpath (or to the native library path for OS-level libraries).
qualidafialThu 7 Oct 2010
Ping. Is there a way to do this? In F4 I can add e.g. the Mockito jar to the Java classpath which works fine when running tests from within Eclipse. However there is no equivalent that I can see in build::BuildPod, so cannot build from the command line.
Only alternative seems to be to include third-party sources in javaDirs inside the project and recompile from source.
yachrisThu 7 Oct 2010
Maybe I'm misunderstanding, but I put my Mockito jar in $fanhome/lib/java/ext/ and I can compile and run from the command line...
qualidafialThu 7 Oct 2010
@yachris: I'm looking for a solution where I can bundle the third party code with the pod itself, as an alternative to putting it in $FAN_HOME.
brianThu 7 Oct 2010
We already bundled Java classfiles in pods today, so much of that infrastructure is already in place. However, the FanClassLoader won't look in arbitrary pods for any old class - it only looks for classes in a given pod by naming convention ("fan.{pod}").
Then on the compiler side, I don't think it looks in pods for Java classes (assuming you need that too).
In order to make it all work, it would probably be something along the lines of:
maybe use some pod meta-data key to define which Java packages it contains
add something into BuildPod that would include a jar into the pod zip and insert the appropriate meta-data
enhance FanClassLoader to use that meta-data key in resolving classes
enhance compilerJava::ClassPath to do it too
The problem is that I do not want the runtime having to open up every pod every single time you run the VM. So the trick is how to do things fast, that is what makes this such a difficult feature.
qualidafialThu 7 Oct 2010
I'm approaching this from the perspective of jars that the pod depends on--not exporting the Jar's API from the pod.
so in theory, the class loader would only go looking up jars (dll's) when one of the fantom types inside the pod requests a java class.
I hope that made sense.. :)
qualidafialFri 8 Oct 2010
Just to clarify, the reason I want this is so that pods can be distributed inside a single .pod file, with all native dependencies included.
I could see the fwt pod being bundled this way. If the runtime wants to unpack those libraries for performance purposes the first time they're loaded, great. But it doesn't affect the distribution method.
brianFri 8 Oct 2010
Creating a pod internal dependency is actually a much simpler problem. Well at least from the java bytecode side (I don't fully understand how the native DLL stuff works, but I don't think that is commonly a JVM issue).
During the Env redesign one of the things I did (to make the OSGi runtime work) was to give each pod its own classloader. So theoretically we should be able to stick something into the pod's meta and then just tweak FanClassLoader.findClass to check for those packages.
Would you be interested in helping to figure out how that works? If so maybe you can try hacking it on your side which works for your use case. Then you can email me directly and we can get it into the next build.
kaushikMon 22 Nov 2010
Will be very useful once this is done. Can we track this as a ticket?
brianFri 26 Nov 2010
Promoted to ticket #430 and assigned to brian
Will be very useful once this is done. Can we track this as a ticket?
Yes this seems valuable enough that it should be targeted for 1.0. Think the only real thing that needs to happen is add a bit of meta-data into the pod that the FanClassLoader can use to decide what pod to look in for a class. Although there are tons of complications and boundary conditions with regard to dependencies that I doubt we should fully tackle. For example to start with, I think we should keep this a pod internal issue.
kaushikSat 27 Nov 2010
Thanks, internal to pod should be fine for this. Alongside, could we also allow better configuration of $FAN_CP(removing -d "$FAN_CP" in fanlaunch)? With that I can write a simple shell script to set the classpath before calling "fan".
brianSun 28 Nov 2010
Alongside, could we also allow better configuration of $FAN_CP
Not sure I follow this request. Right now the code is:
# Set FAN_CP classpath if not already set
if [ -z "$FAN_CP" -o ! -d "$FAN_CP" ] ; then
# always put sys.jar in classpath
FAN_CP="$FAN_HOME/lib/java/sys.jar"
fi
Do you want me to email a patch with how you would like it work?
kaushikSun 28 Nov 2010
Sent you a mail. Thanks.
brianThu 2 Dec 2010
As part of this discussion, I added support to pass $CLASSPATH through on the command line in the bash scripts - changeset
brianWed 5 Jan 2011
Renamed from Including jars/dlls in pods to Bundle Java classes in pod
brianWed 5 Jan 2011
Ticket resolved in 1.0.57
Okay made two tweaks: one to the runtime and one to the build tool.
First I enhanced the Java runtime so that the Fantom class loader will check its own pod for any Java class first. This will let you easily bundle non-Java classes into your pods and they will be visible to the native code in your pod (but they will not have visibility outside of the pod).
As part of this change I also discovered some legacy behavior regarding how Java native compilation worked. Previously it was generating lib/java/foo.jar and adding classfiles to the lib/fan/foo.pod file too. The runtime hasn't actually used lib/java in a long time. The only use for the lib/java files was support in javac to compile against dependencies. But since pods are effectively treated as jars by the runtime, I changed build scripts to have javac compiler use pods directly for the dependencies. This allows us to skip generating the lib/java files altogether.
I didn't create any build support to add a jar into the pod zip, however that should be easy to add to your own build scripts.
I also beefed up docs regaridng class loading, here is new section in Java FFI:
Deployment
During runtime on the JVM, the Fantom uses a classloader per pod. Classes are resolved as follows:
Classfile is contained in the pod zip:
Fantom type foo::Bar maps to precompiled classfile fan/foo/Bar.class"
Java type acme.foo.Bar maps to "acme/foo/Bar.class"
Search extension jars in "{fan.home}/lib/java/ext"
Search extension jars in "{fan.home}/lib/java/ext/{platform}" (see Env)
System classloader which typically includes "{java.home}/lib/ext"
You can bundle Java code in a pod zip file and it will be visible to classes within your pod. However other pods will only have visibility to your Fantom classes in that pod (not other Java classes).
qualidafialThu 6 Jan 2011
Per point 1A above, does this mean that a Fantom class is compiled to fcode, and precompiled to a Java .class? Because that would mean a Fantom .pod file could be used as a valid .jar, and be included in a plain old Java runtime classpath.
brianThu 6 Jan 2011
It is always been true that pods with Java natives have both fcode and precompiled classsfiles. And since pods are zip files they can be treated as just jars. But things don't work just off Java runtime classpath unless you using JarDistEnv. Although one could build a variation of JarDistEnv that worked with multiple jars, although it would be harder to implement things like Pod.list and some of the reflection stuff.
jhughesThu 5 Jan 2017
I didn't see it mentioned specifically anywhere but the question was asked about bundling jar files into a pod but I don't see the syntax to make that happen. Since i'm developing in F4 IDE, I would be interested in how this is accomplished within the confines of that enviornment. If it's not possible from within F4, then what are the extra steps to build a pod with all it's dependencies bundled (jars,pods,etc)?
brianThu 5 Jan 2017
The best thing to do is just map a Java jar into a Fantom pod and then treat it as a first class module. Its very easy, just create a pod with a build script and the jar you want to "wrap" in the same directory, and then in your build file make the jar one of your res:
resDirs = [`your-java.jar`]
Once the pod is compiled it is essentially both a jar and a Fantom pod, but has the Fantom meta to treat it as a first class module.
jhughesThu 12 Jan 2017
Since i'm developing within F4, as I assume most people are, prefering an IDE over command line, I have never had to build a buildScript. Looking at the docs, I don't really see how this is used or any examples of it being used so i'm still not sure how I would accomplish this.
How does one use this method to compile a pod with a jar?
SlimerDudeFri 13 Jan 2017
By buildscript, Brian is talking about the build.fan file - which every project has, even those in F4!
Thank you! i would also like to ask about Literals used by fantom...it is stated there that: "The three types Bool, Int, and Float are value-types. These types are not necessarily passed as object references, but rather passed by value on the call stack. When value types are coerced to/from reference types like Obj and Num, the compiler will generate boxing/unboxing operations."
What do you mean boxing/unboxing operations in that statement?
Ethan ReynoldsSun 17 Sep 2023
I am trying to include more than 1 jar as resources in a build (as shown in the Fri 13 Jan 2017 post above).
When I try to build this pod using F4_1.1.6 and Fantom_1.0.78, I get the following error:
I've hit that issue before and the workaround I used was to remove the /META-INF/MANIFEST-MF file from all the jars. Usually the information in that file is not important so it can be safely removed.
tompalmer Wed 14 Jan 2009
Is there a standard way to include jars/dlls in pods? Something based on simple conventions (supporting multiple platforms in the same pod) would be just great.
For DLLs, I'm referring to .NET DLLs above, but it would also be good to have a place to put native code (for different OSs/architectures) in each pod, too. Some of the native libraries would be used by both .NET and Java. Others would be specific to each of the high level platforms.
Thoughts?
brian Wed 14 Jan 2009
The pod files are already used to store the Java classfiles, and that is pretty easy to control with classloaders. .NET isn't quite so clean - you have to store it to disk if you want to use pdb files to get line numbers which I personally think is design flaw. But still we could unpack them to disk.
Although this is really more a deployment issue, how do you package stuff up for installation - which kinds of leads to Fan's version of RubyGems/Maven.
A very simple solution might be to put an "unpack" directory into a pod which got extracted on startup to the file system.
tompalmer Fri 23 Jan 2009
What I mean, is say I want to include a separate 3rd-party library as part of my pod, and it would be automatically added to the classpath (or to the native library path for OS-level libraries).
qualidafial Thu 7 Oct 2010
Ping. Is there a way to do this? In F4 I can add e.g. the Mockito jar to the Java classpath which works fine when running tests from within Eclipse. However there is no equivalent that I can see in
build::BuildPod
, so cannot build from the command line.Only alternative seems to be to include third-party sources in
javaDirs
inside the project and recompile from source.yachris Thu 7 Oct 2010
Maybe I'm misunderstanding, but I put my Mockito jar in $fanhome/lib/java/ext/ and I can compile and run from the command line...
qualidafial Thu 7 Oct 2010
@yachris: I'm looking for a solution where I can bundle the third party code with the pod itself, as an alternative to putting it in $FAN_HOME.
brian Thu 7 Oct 2010
We already bundled Java classfiles in pods today, so much of that infrastructure is already in place. However, the FanClassLoader won't look in arbitrary pods for any old class - it only looks for classes in a given pod by naming convention ("fan.{pod}").
Then on the compiler side, I don't think it looks in pods for Java classes (assuming you need that too).
In order to make it all work, it would probably be something along the lines of:
The problem is that I do not want the runtime having to open up every pod every single time you run the VM. So the trick is how to do things fast, that is what makes this such a difficult feature.
qualidafial Thu 7 Oct 2010
I'm approaching this from the perspective of jars that the pod depends on--not exporting the Jar's API from the pod.
so in theory, the class loader would only go looking up jars (dll's) when one of the fantom types inside the pod requests a java class.
I hope that made sense.. :)
qualidafial Fri 8 Oct 2010
Just to clarify, the reason I want this is so that pods can be distributed inside a single .pod file, with all native dependencies included.
I could see the
fwt
pod being bundled this way. If the runtime wants to unpack those libraries for performance purposes the first time they're loaded, great. But it doesn't affect the distribution method.brian Fri 8 Oct 2010
Creating a pod internal dependency is actually a much simpler problem. Well at least from the java bytecode side (I don't fully understand how the native DLL stuff works, but I don't think that is commonly a JVM issue).
During the Env redesign one of the things I did (to make the OSGi runtime work) was to give each pod its own classloader. So theoretically we should be able to stick something into the pod's meta and then just tweak FanClassLoader.findClass to check for those packages.
Would you be interested in helping to figure out how that works? If so maybe you can try hacking it on your side which works for your use case. Then you can email me directly and we can get it into the next build.
kaushik Mon 22 Nov 2010
Will be very useful once this is done. Can we track this as a ticket?
brian Fri 26 Nov 2010
Promoted to ticket #430 and assigned to brian
Yes this seems valuable enough that it should be targeted for 1.0. Think the only real thing that needs to happen is add a bit of meta-data into the pod that the FanClassLoader can use to decide what pod to look in for a class. Although there are tons of complications and boundary conditions with regard to dependencies that I doubt we should fully tackle. For example to start with, I think we should keep this a pod internal issue.
kaushik Sat 27 Nov 2010
Thanks, internal to pod should be fine for this. Alongside, could we also allow better configuration of $FAN_CP(removing -d "$FAN_CP" in fanlaunch)? With that I can write a simple shell script to set the classpath before calling "fan".
brian Sun 28 Nov 2010
Not sure I follow this request. Right now the code is:
Do you want me to email a patch with how you would like it work?
kaushik Sun 28 Nov 2010
Sent you a mail. Thanks.
brian Thu 2 Dec 2010
As part of this discussion, I added support to pass $CLASSPATH through on the command line in the bash scripts - changeset
brian Wed 5 Jan 2011
Renamed from Including jars/dlls in pods to Bundle Java classes in pod
brian Wed 5 Jan 2011
Ticket resolved in 1.0.57
Okay made two tweaks: one to the runtime and one to the build tool.
First I enhanced the Java runtime so that the Fantom class loader will check its own pod for any Java class first. This will let you easily bundle non-Java classes into your pods and they will be visible to the native code in your pod (but they will not have visibility outside of the pod).
As part of this change I also discovered some legacy behavior regarding how Java native compilation worked. Previously it was generating lib/java/foo.jar and adding classfiles to the lib/fan/foo.pod file too. The runtime hasn't actually used lib/java in a long time. The only use for the lib/java files was support in javac to compile against dependencies. But since pods are effectively treated as jars by the runtime, I changed build scripts to have javac compiler use pods directly for the dependencies. This allows us to skip generating the lib/java files altogether.
I didn't create any build support to add a jar into the pod zip, however that should be easy to add to your own build scripts.
I also beefed up docs regaridng class loading, here is new section in Java FFI:
Deployment
During runtime on the JVM, the Fantom uses a classloader per pod. Classes are resolved as follows:
foo::Bar
maps to precompiled classfile fan/foo/Bar.class"acme.foo.Bar
maps to "acme/foo/Bar.class"foo::Bar
is loaded as follows:Env
Env
)You can bundle Java code in a pod zip file and it will be visible to classes within your pod. However other pods will only have visibility to your Fantom classes in that pod (not other Java classes).
qualidafial Thu 6 Jan 2011
Per point 1A above, does this mean that a Fantom class is compiled to fcode, and precompiled to a Java .class? Because that would mean a Fantom .pod file could be used as a valid .jar, and be included in a plain old Java runtime classpath.
brian Thu 6 Jan 2011
It is always been true that pods with Java natives have both fcode and precompiled classsfiles. And since pods are zip files they can be treated as just jars. But things don't work just off Java runtime classpath unless you using JarDistEnv. Although one could build a variation of JarDistEnv that worked with multiple jars, although it would be harder to implement things like Pod.list and some of the reflection stuff.
jhughes Thu 5 Jan 2017
I didn't see it mentioned specifically anywhere but the question was asked about bundling jar files into a pod but I don't see the syntax to make that happen. Since i'm developing in F4 IDE, I would be interested in how this is accomplished within the confines of that enviornment. If it's not possible from within F4, then what are the extra steps to build a pod with all it's dependencies bundled (jars,pods,etc)?
brian Thu 5 Jan 2017
The best thing to do is just map a Java jar into a Fantom pod and then treat it as a first class module. Its very easy, just create a pod with a build script and the jar you want to "wrap" in the same directory, and then in your build file make the jar one of your res:
Once the pod is compiled it is essentially both a jar and a Fantom pod, but has the Fantom meta to treat it as a first class module.
jhughes Thu 12 Jan 2017
Since i'm developing within F4, as I assume most people are, prefering an IDE over command line, I have never had to build a buildScript. Looking at the docs, I don't really see how this is used or any examples of it being used so i'm still not sure how I would accomplish this.
How does one use this method to compile a pod with a jar?
SlimerDude Fri 13 Jan 2017
By buildscript, Brian is talking about the
build.fan
file - which every project has, even those in F4!You can find out more about
build.fan
in docTools::Build (fantom.org) and Inside a Fantom Build Script (alienfactory.co.uk)So by setting the (overloaded)
resDirs
field to include .jar files, those jars are merged with the resulting .pod file.Note that the location of the jar files should be relative to the
build.fan
file.Depending on what you're trying to accomplish, it may be easier for you to just copy the .jar files from one Fantom runtime environment to another.
Maru-chan Tue 7 Feb 2017
Do you have samples of codes using Fantom?
SlimerDude Tue 7 Feb 2017
Hi Maru-chan,
Do you mean an example build script that converts a java .jar file into a Fantom .pod?
If so then try this simple example that creates a
commons-lang
pod...Create a
build.fan
file:Assuming you have
commons-lang-2.6.jar
in the same directory, then run it as Fantom script:Maru-chan Fri 10 Feb 2017
Thank you! i would also like to ask about Literals used by fantom...it is stated there that: "The three types Bool, Int, and Float are value-types. These types are not necessarily passed as object references, but rather passed by value on the call stack. When value types are coerced to/from reference types like Obj and Num, the compiler will generate boxing/unboxing operations."
What do you mean boxing/unboxing operations in that statement?
Ethan Reynolds Sun 17 Sep 2023
I am trying to include more than 1 jar as resources in a build (as shown in the Fri 13 Jan 2017 post above).
When I try to build this pod using F4_1.1.6 and Fantom_1.0.78, I get the following error:
How do I get around this? or can I?
matthew Mon 18 Sep 2023
I've hit that issue before and the workaround I used was to remove the
/META-INF/MANIFEST-MF
file from all the jars. Usually the information in that file is not important so it can be safely removed.