Compile a Fantom project into a jar when it references java source code?

191 views Asked by At

I have a Fantom project that uses some native java files, and can successfully compile into a pod. However, I'm trying to compile it into a jar file instead to make it more portable for other users.

I've been trying to use the JarDist tool, but it takes a BuildScript as an input to the constructor, and I'm not sure what this script needs to be.

The closest I've gotten is with the below build script:

using build
class buildJar
{

  public static Void main(){
    jar := JarDist(Build())
    jar.mainMethod = "Market::Meta.main"
    jar.mainMethodArg = true
    jar.outFile = File(`/c:/Users/ccase/Market.jar`)
    jar.podNames = ["Market"]
    jar.run
  }


}

class Build : build::BuildPod
{
  new make()
  {
    podName = "Market"
    summary = ""
    srcDirs = [`fan/`]
    depends = ["sys 1.0+"]
  }
}

This produces the following error code

JarDist
  Pod [sys]
  Pod [Market]
    JStub to classfiles
  Exec [C:\Program Files (x86)\Java\jdk1.8.0_51\bin\java.exe -cp C:\fan\fantom-1.0.67\lib\java\sys.jar -Dfan.home=C:\Users\ccase\f4workspace\KeyGreen\bin\fan fanx.tools.Jstub -d C:\Users\ccase\f4workspace\KeyGreen\bin\fan\temp\jardist-b66da4d7bd01cae9 Market]
    Java Stub [Market]
Exception in thread "main" sys::Err: Load from [Market] ProcessRunner.Wrapper
    at fan.sys.Err.make(Err.java:78)
    at fan.sys.Err.make(Err.java:68)
    at fan.sys.Env.loadJavaType(Env.java:284)
    at fan.sys.Pod.type(Pod.java:481)
    at fan.sys.ClassType.map(ClassType.java:428)
    at fan.sys.ClassType.doReflect(ClassType.java:321)
    at fan.sys.ClassType.reflect(ClassType.java:282)
    at fan.sys.ClassType.emitToClassFiles(ClassType.java:672)
    at fanx.tools.Jstub.stub(Jstub.java:58)
    at fanx.tools.Jstub.run(Jstub.java:160)
    at fanx.tools.Jstub.main(Jstub.java:186)
ERR: Exec failed [C:\Program Files (x86)\Java\jdk1.8.0_51\bin\java.exe -cp C:\fan\fantom-1.0.67\lib\java\sys.jar -Dfan.home=C:\Users\ccase\f4workspace\KeyGreen\bin\fan fanx.tools.Jstub -d C:\Users\ccase\f4workspace\KeyGreen\bin\fan\temp\jardist-b66da4d7bd01cae9 Market]
build::FatalBuildErr: Exec failed [C:\Program Files (x86)\Java\jdk1.8.0_51\bin\java.exe -cp C:\fan\fantom-1.0.67\lib\java\sys.jar -Dfan.home=C:\Users\ccase\f4workspace\KeyGreen\bin\fan fanx.tools.Jstub -d C:\Users\ccase\f4workspace\KeyGreen\bin\fan\temp\jardist-b66da4d7bd01cae9 Market]
  build::Task.fatal (Task.fan:61)
  build::Task.fatal (Task.fan)
  build::Exec.run (Exec.fan:33)
  build::JarDist.podClasses (JarDist.fan:130)
  build::JarDist.run (JarDist.fan:41)
  fan.sys.List.each (List.java:588)
  build::JarDist.run (JarDist.fan:41)
  buildJar_0::buildJar.main (/C:/Users/ccase/f4workspace/Market/buildJar.fan:11)
  java.lang.reflect.Method.invoke (Unknown)
  fan.sys.Method.invoke (Method.java:559)
  fan.sys.Method$MethodFunc.callList (Method.java:198)
  fan.sys.Method.callList (Method.java:138)
  fanx.tools.Fan.callMain (Fan.java:173)
  fanx.tools.Fan.executeFile (Fan.java:98)
  fanx.tools.Fan.execute (Fan.java:37)
  fanx.tools.Fan.run (Fan.java:298)
  fanx.tools.Fan.main (Fan.java:336)

ProcessRunner.Wrapper is the java native file that I use in the Market pod.

1

There are 1 answers

2
Steve Eynon On BEST ANSWER

Following the stack trace, the program is dying because this command is failing (or returning a non-zero exit code):

"C:\Program Files (x86)\Java\jdk1.8.0_51\bin\java.exe" -cp C:\fan\fantom-1.0.67\lib\java\sys.jar -Dfan.home=C:\Users\ccase\f4workspace\KeyGreen\bin\fan fanx.tools.Jstub -d C:\Users\ccase\f4workspace\KeyGreen\bin\fan\temp\jardist-b66da4d7bd01cae9 Market

Try running it by itself to see if it gives you any more information.


While there is nothing wrong with your script, I believe the common usage of the JarDist task is like this:

using build

class Build : BuildPod {

    new make() {
        podName = "Market"
        summary = ""
        srcDirs = [`fan/`]
        depends = ["sys 1.0+"]
    }


    @Target { help = "Build my jar file" }
    Void buildJar() {
        JarDist(this) {
            mainMethod      = "Market::Meta.main"
            mainMethodArg   = true
            outFile         = File(`/c:/Users/ccase/Market.jar`)
            podNames        = ["Market"]
        }.run
    }
}

Which can be invoked with:

C:\> fan Build.fan buildJar

As a final note, if you're just trying to package up your application you could try the AppBuilder script as detailed in Create Standalone Fantom Apps in Seconds!.

It creates a .zip file containing a minimal (standalone) Fantom installation that just runs your Market pod.

This is all you need:

class Wotever {
    Void main() {
        AppBuilder("Market") {
            it.scriptArgs = "Market::Meta.main"
        }.build
    }
}

const class AppBuilder {
    ...
    ... Cut'n'Paste AppBuilder Script Here
    ...
}

Run it with:

C:\> fan Wotever.fan