Generating Java Classes from a Swig Interface (.i) under Scons - java

When I attempt to run scons (2.3.0) to build a class from a SWIG interface file, scons fails to pick up all the generated files, either as being in the sourcepath, or to be included in the build (even with classpath set). Instead only two java files are attempted to be compiled, both of which fail because they are derived from other classes.
loc_env = env.Clone()
loc_env['JAVACLASSPATH']= ['build/$TARGET_ARCH/$TARGET_OS/.../java']
swig_j = loc_env.Java(target='.', source=['source_java.i']) #1
#swig_j = loc_env.Jar(target='.', source=['source_java.i']) #2
Both #1, and #2 fail to produce a result. #2 shows an error message that the source has not been accepted, and is a blank string, which I can accept, even with example code suggesting it should work.
For #1 The root cause seems to be in Scons/Tool/swig.py def _find_modules(src):, which has a regex to match all modules generated, but fails to account for any raw enums or other artefacts from wrapping up C code. When I had a hand-rolled makefile the classpath
For reference, The javac build instruction for #1 is:
javac -classpath build/x86_64/linux/.../java -d build/x86_64/linux/.../java/ -sourcepath build/x86_64/linux/.../java build/x86_64/linux/release/.../source.java build/x86_64/linux/release/.../sourceJNI.java
Is this a known bug (As part of SCONS' handling of 1->N mappings)? Is it a flaw in the Scons Parsing of .i files? or is it a more fundamental issue?

This is a bug in SCons. The changes slated for 2.5.0 fix the issue, by improving cross-language scanning. I look forwards to ripping out my hack sometime next year!

Related

Generating an AST report from Java source code without actually running it

So I spend the whole day trying to figure out how to work with ANTLR. I have a bunch of Java source code files. My goal is to use ANTLR in order to create an AST for each one of those files. In the end, the AST will be converted to JSON so it will be easier to parse each one of them with a dynamic language like python. The conversion will use the solution in this topic (although if someone have a better solution I will be glad to hear). I have managed to run the basic example in the getting-started page. Now I'm trying to figure out how to create an AST for one of my Java source code files. As it is said in the getting-started page, I can use the Java grammar for that. I have downloaded JavaParser.g4 and JavaLexer.g4. I tried to run:
java -Xmx500M -cp "/p/antlr-4.8-complete.jar:$CLASSPATH" org.antlr.v4.Tool JavaParser.g4
But I get the error:
JavaParser.g4:32:21: cannot find tokens file ./JavaLexer.tokens
I guess I need to create that file somehow but I could not understand how, from the docs. So I tried to find that file in Github and I found it here. I have downloaded it and it looked ok:
java -Xmx500M -cp "/p/antlr-4.8-complete.jar:$CLASSPATH" org.antlr.v4.Tool JavaParser.g4
javac JavaP*.java // Also tried javac Java*.java
java -Xmx500M -cp "/p/antlr-4.8-complete.jar:$CLASSPATH" org.antlr.v4.gui.TestRig JavaParser r -gui
But I get:
Exception in thread "main" java.lang.ClassCastException: class JavaParser
at java.lang.Class.asSubclass(Class.java:3404)
at org.antlr.v4.gui.TestRig.process(TestRig.java:135)
at org.antlr.v4.gui.TestRig.main(TestRig.java:119)
Not sure what I do wrong or whether I'm doing the right thing in order to solve my problem.
All I want to do is to create an AST of the file /tmp/file.java and I'm not even sure where I should include it in the commands.
So my questions are:
How do I create an AST for the file /tmp/file.java?
Is it possible to create an AST file without actually writing Java code? I saw many places where they suggest to write Java code and compile it wtih Maven or some other tool. I prefer not to do it if possible, rather use the command-line option.
It's been a while since the JSON topic (mentioned above) was updated. Have something changed? Is it possible to create a JSON report without actually running Java?
As you can see I'm really confused so I appreciate any help!
EDIT: A small clarification - I don't need the AST image, rather to create a JSON report. If there is no easy way to do it, I'm sure that ANTLR has some raw file with that info that I could parse and convert it into JSON. Although, where is that raw data located?
I hope your classpath is correct. It needs the current directory in addition to the ANTLR tool jar. So something like .;C:\...\antlr.jar. As for using ANTLR on the Java grammar, you can do this:
$ antlr4 JavaLexer.g4 JavaParser.g4
$ javac Java*.java
$ grun Java compilationUnit -tree -gui
-gui will pop a window which may take some time. Remember to send an EOF to the ANTLR runtime after you type something to stdin. (CTLR+Z on Windows, CTLR+D on Linux) Alternatively, you can input a file as an extra argument to grun.
From the two .g4 files, I couldn't tell that the grammar name was Java. I just guessed it out based on the context. compilationUnit is the name of the first grammar rule all java files start with. This can be deduced by opening the JavaParser.g4 and reading the first rule.
Here are the aliases I used on Git Bash.
$ alias
alias antlr4='java -Xmx500M org.antlr.v4.Tool'
alias grun='java -Xmx500M org.antlr.v4.gui.TestRig'

jpype simple jar import and run main()

I'm trying to open a jar file and execute it's main function, but jpype is throwing an error that doesn't make sense to me. Here is my code:
jpype.startJVM(jpype.getDefaultJVMPath(), '-Djava.class.path="%s"' % jar)
CommandLine = jpype.JPackage('phylonet').coalescent.CommandLine
CommandLine.main(['-i', input_file, '-o', output_file])
jpype.shutdownJVM()
I get this error:
TypeError: Package phylonet.coalescent.CommandLine.main is not Callable
I've provided the absolute path to the jar file, and I've gotten the main function from META-INF/MANIFEST.MF:
cat tmp/META-INF/MANIFEST.MF | grep Main-Class
Main-Class: phylonet.coalescent.CommandLine
The jar file I'm trying to open is called astral, from here: https://github.com/smirarab/ASTRAL
Calling it like this works as expected:
java -Djava.class.path="./astral.jar"
So why not when I call it with jpype?
First of all, I have tested your code on my own jarfile. Indeed, I was presented with such error:
TypeError: Package clip.frontend.Start.main is not Callable
Then, after reading the docs carefully, I've used another method.
import jpype
# I've used other set of parameters to JVM, and modified a bit your classpath setting.
jpype.startJVM(jpype.getDefaultJVMPath(), "-ea", "-Djava.class.path=clip.jar")
# Second difference, I decided to use JClass because it was more clear for me.
# Parameter array was kept empty.
jpype.JClass("clip.frontend.Start").main([])
jpype.shutdownJVM()
And the output was correct:
% python2 main.py
2 2
+>+[<[>>+>+<<<-]>>[<<+>>-]>[[-]>>>>>>+<<<<<<<<<[-]>[-]>>>>>>>>[<<<<<<<<+>+>>>>>>>-]
<<<<<<<[>>>>>>>+<<<<<<<-]>>>>>>>[-]<<<<<<]<<<[>>+>+<<<-]>>[<<+>>-]>[[-]>>>>>>++
[<<<<<+>>>>>>>>>>>>+<<<<<<<-]<<<<<[>>>>>+<<<<<-]>>>>>>>>>>>>>[>>]+<<[<<]>[>[>>]
<+<[<<]>-]<<<<<<<[-]++[<<<<<+>>>>>>>>>>>>+<<<<<<<-]<<<<<[>>>>>+<<<<<-]>>>>>>>>>>>>>
[>>]+<<[<<]>[>[>>]<+<[<<]>-]<<<<<<<[-]#JVM has been shutdown
Now, I decided to translate my solution to match your problem:
import jpype
jpype.startJVM(jpype.getDefaultJVMPath(), "-ea", "-Djava.class.path=astral.jar")
jpype.JClass("phylonet.coalescent.CommandLine").main([])
jpype.shutdownJVM()
And the code works correctly. More important than the actual solution is the fact, why doesn't your code work. You used wrong set of parameters and specified the classpath in the other way.
Replacing JClass with JPackage, the code still works.
import jpype
jpype.startJVM(jpype.getDefaultJVMPath(), "-ea", "-Djava.class.path=astral.jar")
jpype.JPackage('phylonet').coalescent.CommandLine.main([])
jpype.shutdownJVM()
As the way you extract classes from classpath is correct, the only possible cause is specifying invalid parameter set. After removing -ea the code still works, so mistake you made lies in this fragment of code.
'-Djava.class.path="%s"' % jar
And in fact, I've used this in opposition to my answer, and bam, the code yields this:
TypeError: Package phylonet.coalescent.CommandLine.main is not Callable
This means, the parameter contained following:
-Djava.class.path="astral.jar"
instead of following
-Djava.class.path=astral.jar
The quotes were misplaced and raised the error in result.
This was a classic issue with JPype. If the jar can't be loaded then JPackage will return another JPackage which is not callable. Common causes of a failure to load include
The JVM loaded does not support the version of the jar (Check that getDefaultJVMPath() is not some old version)
A jar dependency is missing.
The JVM could not find the Jar as the specified path.
The previous solution was to use java.lang.Class.forName which would print the diagnostics on the jar loading. Version 0.7.0 which is currently in available as a release candidate has addressed this.
Also it is recommended that you use jpype.imports or JClass rather than JPackage when importing a class. It is much safer as it will report a more meaningful error. For example:
import jpype
import jpype.imports
jpype.startJVM()
jpype.imports.registerDomain('phylonet') # This is required as phylonet is not a tld
from phylonet.coalescent import CommandLine
You can mark a package as being conforming (Classes start upper, packages are lower) to force an error.

Unix on the Mainframe: COB2 compiler, for Java calling COBOL

I've been working on trying to get COBOL and Java to interact with each other on the mainframe, and have run into trouble with specifically the cob2 compiler, which is the Unix on the mainframe equivalent.
I haven't seen many user experiences with this compiler online, so I was wondering if I asked a more direct question, people would reveal their insight.
IBM has several examples of Java calling COBOL DLL's either directly or indirectly, but they ultimately boil down to compile the COBOL as a dll, use System.load, compile Java and run. These examples haven't worked for me for the following reasons.
When using cob2 with the -c option, it is purported to generate a .o object file. This has not happened for me, although it did generate an empty .lst file. I was able to get around this by simply skipping the -c step and compiling and linking using this series of commands:
` sh ${COB2HOME}/bin/cob2 -o ${DIR}/c2jcr.o
-qdll,thread,case=mixed ${DIR}/c2jcr.cbl;
${COB2HOME}/bin/cob2
-o ${DIR}/libc2jcr.so
-bdll,case=mixed ${DIR}/c2jcr.o
${JAVAHOME}/bin/j9vm/libjvm.x
${COB2HOME}/lib/igzcjava.x `
This appears to provide the .so library that is required for link with the Java program, but upon investigation of the load, and during run, the system declares that the LE CSECT CEESTART is not there.
Am I missing something in my cob2 library that has these LE modules, or somewhere in my scripting? I tried pulling in loads from the mainframe compiled with the LE modules intact and ENTRY CEESTART explicitly stated in the link step, but could not get any further than "UnsatisfiedLinkError" with "Internal Error".
Any wisdom is greatly appreciated, especially if you've gone down a completely different route to call COBOL from Java. Thank you very much.
After conferring with IBM, it turns out I had a couple things missing.
You must have a STEPLIB environment field set to the location of your COBOL compiler on the mainframe, so it can find your IGYCRCTL module.
Second, like other COBOL 5+ compiling, you must allocate a gargantuan amount of space in order to compile. 2 GB is not enough. Since I don't have permission to reallocate this in Unix, I ran a BPXBATCH job with REGION=0M.
After those two changes, -c compiles came out as normally. The "workaround" I provided in the question is completely incorrect. You must use:
sh ${COB2HOME}/bin/cob2 -c -qdll,thread,case=mixed ${DIR}/${COBPROG}.cbl
as your compile step, and the rest is just linkage.

RemoteActorRefProvider ClassNotFound

I'm struggling trying to get remote actors setup in Scala. I'm running Scala 2.10.2 and Akka 2.2.1.
I compile using [I've shortened the paths on the classpath arg for clarity sake]:
$ scalac -classpath "akka-2.2.1/lib:akka-2.2.1/lib/scala-library.jar:akka-2.2.1/lib/akka:akka-2.2.1/lib/akka/scala-reflect-2.10.1.jar:akka-2.2.1/lib/akka/config-1.0.2.jar:akka-2.2.1/lib/akka/akka-remote_2.10-2.2.1.jar:akka-2.2.1/lib/akka/akka-kernel_2.10-2.2.1.jar:akka-2.2.1/lib/akka/akka-actor_2.10-2.2.1.jar:." [file.scala]
I've continuously added new libraries trying to debug this - I'm pretty sure all I really need to include is akka-remote, but the others shouldn't hurt.
No issues compiling.
I attempt to run like this:
$ scala -classpath "[same as above]" [application]
And I receive a NSM exception:
java.lang.NoSuchMethodException: akka.remote.RemoteActorRefProvider.<init>(java.lang.String, akka.actor.ActorSystem$Settings, akka.event.EventStream, akka.actor.Scheduler, akka.actor.DynamicAccess)
at java.lang.Class.getConstructor0(Class.java:2810)
at java.lang.Class.getDeclaredConstructor(Class.java:2053)
...
Looking into the source code, it appears that Akka 2.2.X's flavor of this constructor takes 4 arguments (the Scheduler is removed). But in Akka < 2.2.X, the constructor takes 5 args.
Thus, I'm thinking my classpath isn't setup quite right. At compile-time, Scala must be finding the <2.2.X flavor. I don't even know where it would be finding it, since I only have Akka 2.2.1 installed.
Any suggestions!? Thanks! (Please don't say to use SBT).
The problem here is that the Scala distribution contains akka-actor 2.1.0 and helpfully puts that in the boot class path for you. We very strongly recommend using a dependency manager like sbt or maven when building anything which goes beyond the most trivial projects.
As noted in another answer, the problem is that scala puts a different version of Akka into the bootclasspath.
To more directly answer your question (as you said you don't want to use sbt): you can execute your program with java instead of scala. You just have to put the appropriate Scala jars into the classpath.
Here is a spark-dev message about the problem. The important part is: "the workaround is to use java to launch the application instead of scala. All you need to do is to include the right Scala jars (scala-library and scala-compiler) in the classpath."

Running project in command prompt

I am running project in netbeans, and I want to run the same project on command prompt...
But during compilation the message comes
Note : filename.java uses or overrides
a deprecated API
Note : Recompile with
-Xlint:deprecation for details.
How can I compile and run the project in command prompt?
How can I remove this problem please tell me...
Try this at the command prompt:
javac -Xlint:deprecation filename.java
The message is telling you that you are using a deprecated API. A deprecated API means an API that you shouldn't be using because it has been replaced by something else. The code will still work for now but someday a future release may eliminate the deprecated API and then your code will break. It is a good idea to stay away from deprecated APIs. The message is telling you to invoke javac with the -Xlint:deprecation flag and it will tell you exactly what it is complaining about.
Note: even if you get this warning message when you compile, you can ignore it - your program still compiles and works.
You might as well try using the following annotation:
#SuppressWarnings("deprecation")
#SuppressWarnings—the
#SuppressWarnings annotation tells the
compiler to suppress specific warnings
that it would otherwise generate. In
the example below, a deprecated method
is used and the compiler would
normally generate a warning. In this
case, however, the annotation causes
the warning to be suppressed.
// use a deprecated method and tell
// compiler not to generate a warning
#SuppressWarnings("deprecation")
void useDeprecatedMethod() {
objectOne.deprecatedMethod(); //deprecation warning - suppressed
}
But you might end up leaving the deprecated code there forever. Best is for you to consider using the new API.
NetBeans by default will create an Ant project (although you can use Apache Maven, as well, with NetBeans). If you see a file named "build.xml" in your folder, then you should build with:
ant
If you see a file named "pom.xml" in your project folder, then you should build with:
mvn package
The warning message that you see is not an error, meaning that it did compile successfully, but you should probably deal with the warnings, since they indicate that you are using deprecated features. As to executing your project, simply invoke the java command with your JAR file. For example:
java -jar build/myproject.jar
Typically the resulting JAR is placed in the "build" directory; you will need to replace "build/myproject.jar" with the name of the actual JAR file. For some projects, the output directory may differ.

Categories