Compiling a Mex file for Java - java

I found a java based TCP-IP system for matlab which might fix many problems I've been having with multiple and uninterruptible connections. However I'm stumped on how to get it working. I have compiled code under linux plenty of times but never on windows.
The code I'm trying to compile is located here and it states:
Build
Compile MEX files and Java helpers by the attached Makefile.
make
The question is how? I thought of using Visual studio command prompt but I end up getting an error:
makefile(8) : fatal error U1036: syntax error : too many names to left of '='
Which suggests either I have to edit the makefile or I'm using the wrong compiler. And I have no knowledge of Java so I don't even know where to begin when compiling it.
edit: Updating to show what code is in the makefile
MATLABDIR ?= /usr/local/matlab
MATLAB := $(MATLABDIR)/bin/matlab
MEX := $(MATLABDIR)/bin/mex
MEXEXT := $(shell $(MATLABDIR)/bin/mexext)
MEXSOURCES := $(wildcard private/*.cc)
MEXTARGETS := $(patsubst %.cc,%.$(MEXEXT),$(MEXSOURCES))
CLASSPATH := java
JAVASOURCES := $(wildcard java/matlab_tcpip/*.java)
JAVATARGETS = $(patsubst %.java,%.class,$(JAVASOURCES))
JARFILE = java/matlab_tcpip.jar
all: $(JARFILE) $(MEXTARGETS)
%.$(MEXEXT):%.cc
$(MEX) $< -output $#
$(JARFILE): $(JAVATARGETS)
jar cvf $# -C java matlab_tcpip/
jar i $#
%.class:%.java
javac -cp $(CLASSPATH) $<
test: $(JARFILE)
echo "run test/runServer.m" | $(MATLAB) -nodisplay & \
echo "run test/runClient.m" | $(MATLAB) -nodisplay
clean:
rm $(MEXTARGETS) java/matlab_tcpip/*.class $(JARFILE)

Related

How to cross compile my C code containing JNI?

Previously I asked a question related to calling java function at
Calling Java functions from C language
Somehow I did with that.
Now I am planning to cross compile that.
I am facing an issue.
Before cross compiling ( means compiling in the same pc for the same pc)
I used the commands
gcc -I /usr/lib/jvm/java-6-openjdk-amd64/include -I /usr/lib/jvm/java-6-openjdk-amd64/include/linux -L /usr/bin/java -L /usr/lib/jvm/java-6-openjdk-amd64/jre/lib/amd64/server MyC.c -ljvm ;
That created well.
But now I am trying to cross compile the same for my target arm-none-eabi-
My makefile
CROSS_COMPILE =arm-none-eabi-
JAVA_HOME =/usr/lib/jvm/java-7-openjdk-amd64/
test:
javac -d ./ MyJava.java
$(CROSS_COMPILE)gcc -I $(JAVA_HOME)include \
-I $(JAVA_HOME)include/linux \
-L $(JAVA_HOME)jre/lib/amd64/server \
MyC.c -ljvm
This returning error
arm-none-eabi/bin/ld: warning: library search path "/usr/lib/jvm/java-7-openjdk-amd64/jre/lib/amd64/server" is unsafe for cross-compilation
/usr/lib/jvm/java-7-openjdk-amd64/jre/lib/amd64/server/libjvm.so: file not recognized: File format not recognized
collect2: ld returned 1 exit status
make: *** [test] Error 1

Java compilation error : /bin/ld:cannot find -ljvm

I am trying to build a java project http://sourceforge.net/projects/fuse-j/?source=typ_redirect on fedora machine. The compilation fails while compiling JNI bindings.
MakeFile
include ../build.conf
include ../jvm_ldpath.def
SRCS := javafs.c javafs_bindings.c
HDRS := javafs.h javafs_bindings.h
LIB_SO := libjavafs.so
INCLUDES := -I${FUSE_HOME}/include -I${JDK_HOME}/include -I${JDK_HOME}/include/linux
LDPATH := ${LDPATH} -L${FUSE_HOME}/lib
all: ${LIB_SO}
${LIB_SO}: ${SRCS} ${HDRS}
gcc -fPIC -shared -D_FILE_OFFSET_BITS=64 -o ${LIB_SO} ${INCLUDES} ${LDPATH} -ljvm -lfuse -lpthread ${SRCS}
clean:
rm -f ${LIB_SO}
Error:
/bin/ld: cannot find -ljvm
collect2: error: ld returned 1 exit status
Makefile:17: recipe for target 'libjavafs.so' failed
make[1]: *** [libjavafs.so] Error
JDK_HOME ,FUSE_HOME are correctly set. Can you suggest what can be wrong here?
The jvm shared library will be found in a path under $JDK_HOME, however, you are not adding that path to your LDPATH make variable. You need to add -L${JDK_HOME}/lib to LDPATH (or wherever libjvm.so is found).

GCC option not found while constructing .dll

I'm trying to create a .dll while following this tutorial (http://www3.ntu.edu.sg/home/ehchua/programming/java/JavaNativeInterface.html) to use JNI in my eclipse project. There's an issue with my makefile however that may be unrelated to all the JNI stuff.
I'm getting "unknown option: --add-stdcall-alias" when I build (make all). I'm using the Mac GCC Compiler. Here's my console log and make file:
EDIT: So i removed the option that is giving me the error and my build worked. However, I feel unsafe just removing a line of code that I am clueless about. Any one want to tell me the implications of removing this code?
console output:
18:05:33 ** Build of configuration Default for project HPA* Testing *
make all
javah -classpath ../bin HPAProgram
gcc -Wl,--add-stdcall-alias -shared -o hpaprogram.dll HPAProgram.o
ld: unknown option: --add-stdcall-alias
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: ** [hpaprogram.dll] Error 1
18:05:34 Build Finished (took 823ms)
makefile:
# Define a variable for classpath
CLASS_PATH = ../bin
# Define a virtual path for .class in the bin directory
vpath %.class $(CLASS_PATH)
all : hpaprogram.dll
# $# matches the target, $< matches the first dependancy
hpaprogram.dll : HPAProgram.o
gcc -Wl,--add-stdcall-alias -shared -o $# $<
# $# matches the target, $< matches the first dependancy
HPAProgram.o : HPAProgram.c++ HPAProgram.h
gcc -I /System/Library/Frameworks/JavaVM.framework/Versions/A/Headers/ -c $< -o $#
# $* matches the target filename without the extension
HPAProgram.h : HPAProgram.class
javah -classpath $(CLASS_PATH) $*
clean :
rm HPAProgram.h HPAProgram.o hpaprogram.dll
I practiced by following the same tutorial, it turned out that it's OK to get rid of "-Wl,--add-stdcall-alias".
BTW, in Mac, you have to use ".dylib" instead of ".so", otherwise you will get error saying "java.lang.UnsatisfiedLinkError: no hello in java.library.path".

Solution for error ClassDefNotFound in Java

I have five class files Servant.class, Server.class, Client.class, TransferRequest.class and TransferResponse.class. My Makefile is at the below. I have this error for any of my class file:
Error occurred during initialization of VM
java/lang/NoClassDefFoundError: java/lang/Object
Makefile:11: recipe for target 'TransferRequest.class' failed
How can I cope with this error? I really tried all solutions which was written here such changing path or sth. This makefile is also 5th or 6 th one. The other well known makefiles gave same error too. I am on Windows machine I use cygwin.
Makefile:
JAVAC=javac
sources = $(wildcard *.java)
classes = $(sources:.java=.class)
all: $(classes)
clean :
rm -f *.class
%.class : %.java
$(JAVAC) $<
Add a classpath (with the -cp) option to your javac.
JAVAC=javac -cp "$CLASSPATH"
Or you could change
$(JAVAC) $<
to add the classpath
$(JAVAC) -cp "$CLASSPATH" $<
This is a problem with javac. Either something is missing from your make file or your java installation is broken.
Find out if you can compile a file by hand with javac to narrow it down.

Creating a jar file from a Scala file

I'm new to Scala and don't know Java. I want to create a jar file out of a simple Scala file. So I have my HelloWorld.scala, generate a HelloWorld.jar.
Manifest.mf:
Main-Class: HelloWorld
In the console I run:
fsc HelloWorld.scala
jar -cvfm HelloWorld.jar Manifest.mf HelloWorld\$.class HelloWorld.class
java -jar HelloWorld.jar
=> "Exception in thread "main" java.lang.NoClassDefFoundError: HelloWorld/jar"
java -cp HelloWorld.jar HelloWorld
=> Exception in thread "main" java.lang.NoClassDefFoundError: scala/ScalaObject
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:675)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:260)
at java.net.URLClassLoader.access$100(URLClassLoader.java:56)
at java.net.URLClassLoader$1.run(URLClassLoader.java:195)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:316)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:280)
at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:374)
at hoppity.main(HelloWorld.scala)
Sample directory structure:
X:\scala\bin
X:\scala\build.bat
X:\scala\MANIFEST.MF
X:\scala\src
X:\scala\src\foo
X:\scala\src\foo\HelloWorld.scala
HelloWorld.scala:
//file: foo/HelloWorld.scala
package foo {
object HelloWorld {
def main(args: Array[String]) {
println("Hello, world!")
}
}
}
MANIFEST.MF:
Main-Class: foo.HelloWorld
Class-Path: scala-library.jar
build.bat:
#ECHO OFF
IF EXIST hellow.jar DEL hellow.jar
IF NOT EXIST scala-library.jar COPY %SCALA_HOME%\lib\scala-library.jar .
CALL scalac -sourcepath src -d bin src\foo\HelloWorld.scala
CD bin
jar -cfm ..\hellow.jar ..\MANIFEST.MF *.*
CD ..
java -jar hellow.jar
In order to successfully use the -jar switch, you need two entries in the META-INF/MANIFEST.MF file: the main class; relative URLs to any dependencies. The documentation notes:
-jar
Execute a program encapsulated in a
JAR file. The first argument is the
name of a JAR file instead of a
startup class name. In order for this
option to work, the manifest of the
JAR file must contain a line of the
form Main-Class: classname. Here,
classname identifies the class having
the public static void main(String[]
args) method that serves as your
application's starting point. See the
Jar tool reference page and the Jar
trail of the Java Tutorial for
information about working with Jar
files and Jar-file manifests.
When you use this option, the JAR file
is the source of all user classes,
and other user class path settings are ignored.
java command line usage
manifest spec
(Notes: JAR files can be inspected with most ZIP applications; I probably neglect handling spaces in directory names in the batch script; Scala code runner version 2.7.4.final .)
For completeness, an equivalent bash script:
#!/bin/bash
if [ ! $SCALA_HOME ]
then
echo ERROR: set a SCALA_HOME environment variable
exit
fi
if [ ! -f scala-library.jar ]
then
cp $SCALA_HOME/lib/scala-library.jar .
fi
scalac -sourcepath src -d bin src/foo/HelloWorld.scala
cd bin
jar -cfm ../hellow.jar ../MANIFEST.MF *
cd ..
java -jar hellow.jar
Because Scala scripts require the Scala libraries to be installed, you will have to include the Scala runtime along with your JAR.
There are many strategies for doing this, such as jar jar, but ultimately the issue you're seeing is that the Java process you've started can't find the Scala JARs.
For a simple stand-alone script, I'd recommend using jar jar, otherwise you should start looking at a dependency management tool, or require users to install Scala in the JDK.
I ended up using sbt assembly, it is really simple to use. I added a file called assembly.sbt into the project/ directory at the root of the project with a one liner (Note your version might need to be changed).
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.11.2")
Then just run the assembly task in sbt:
> assembly
Or just 'sbt assembly' in project root directory
$ sbt assembly
It will first run your tests and then it will generate the new jar into the target/ directory (given that my build.sbt already lists all my dependencies).
In my case, I just make that .jar file executable, rename to remove the extension and it is ready to ship!
Also, if you are doing a command line tool, don't forget to add a man page (I hate scripts without proper manpages or with multi-page plain text documentation that is not even piped into a pager for you).
You can also use maven and the maven-scala-plugin. Once you set up maven, you can just do mvn package and it will create your jar for you.
I tried to reproduce MyDowell's method. Finally I could make it work. However I find that the answer though correct a bit too complicated for a novice ( in particular the directory structure is unnecessarily complicated ).
I can reproduce this result with very simplistic means. To start with there is only one directory which contains three files:
helloworld.scala
MANIFEST.MF
scala-library.jar
helloworld.scala
object HelloWorld
{
def main(args: Array[String])
{
println("Hello, world!")
}
}
MANIFEST.MF:
Main-Class: HelloWorld
Class-Path: scala-library.jar
first compile helloworld.scala:
scalac helloworld.scala
then create the jar:
\progra~1\java\jdk18~1.0_4\bin\jar -cfm helloworld.jar MANIFEST.MF .
now you can run it with:
java -jar helloworld.jar
I found this simple solution because the original one did not work. Later I found out that not because it is wrong, but because of a trivial error: if I don't close the second line in MANIFEST.MF with a newline, then this line will be ignored. This took me an hour to find out and I tried all other things before, in the process finding this very simple solution.
I don't want to write why's and how's rather just show the solution which worked in my case (via Linux Ubuntu command line):
1)
mkdir scala-jar-example
cd scala-jar-example
2)
nano Hello.scala
object Hello extends App { println("Hello, world") }
3)
nano build.sbt
import AssemblyKeys._
assemblySettings
name := "MyProject"
version := "1.0"
scalaVersion := "2.11.0"
3)
mkdir project
cd project
nano plugins.sbt
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.9.1")
4)
cd ../
sbt assembly
5)
java -jar target/target/scala-2.11/MyProject-assembly-1.0.jar
>> Hello, world
I modified the bash script adding some intelligence including auto-manifest generation.
This script assumes that the main object is named the same as the file it is in (case sensitive). Also, either the current directory name must equal to the main object name or the main object name should be provided as a command line parameter. Launch this script from the root directory of your project. Modify the variables at the top as required.
Be aware that the script will generate the bin and dist folders and will ERASE any existing contents in bin.
#!/bin/bash
SC_DIST_PATH=dist
SC_SRC_PATH=src
SC_BIN_PATH=bin
SC_INCLUDE_LIB_JAR=scala-library.jar
SC_MANIFEST_PATH=MANIFEST.MF
SC_STARTING_PATH=$(pwd)
if [[ ! $SCALA_HOME ]] ; then
echo "ERROR: set a SCALA_HOME environment variable"
exit 1
fi
if [[ ! -f $SCALA_HOME/lib/$SC_INCLUDE_LIB_JAR ]] ; then
echo "ERROR: Cannot find Scala Libraries!"
exit 1
fi
if [[ -z "$1" ]] ; then
SC_APP=$(basename $SC_STARTING_PATH)
else
SC_APP=$1
fi
[[ ! -d $SC_DIST_PATH ]] && mkdir $SC_DIST_PATH
if [[ ! -d $SC_BIN_PATH ]] ; then
mkdir "$SC_BIN_PATH"
else
rm -r "$SC_BIN_PATH"
if [[ -d $SC_BIN_PATH ]] ; then
echo "ERROR: Cannot remove temp compile directory: $SC_BIN_PATH"
exit 1
fi
mkdir "$SC_BIN_PATH"
fi
if [[ ! -d $SC_SRC_PATH ]] || [[ ! -d $SC_DIST_PATH ]] || [[ ! -d $SC_BIN_PATH ]] ; then
echo "ERROR: Directory not found!: $SC_SRC_PATH or $SC_DIST_PATH or $SC_BIN_PATH"
exit 1
fi
if [[ ! -f $SC_DIST_PATH/$SC_INCLUDE_LIB_JAR ]] ; then
cp "$SCALA_HOME/lib/$SC_INCLUDE_LIB_JAR" "$SC_DIST_PATH"
fi
SCALA_MAIN=$(find ./$SC_SRC_PATH -name "$SC_APP.scala")
COMPILE_STATUS=$?
SCALA_MAIN_COUNT=$(echo "$SCALA_MAIN" | wc -l)
if [[ $SCALA_MAIN_COUNT != "1" ]] || [[ ! $COMPILE_STATUS == 0 ]] ; then
echo "Main source file not found or too many exist!: $SC_APP.scala"
exit 1
fi
if [[ -f $SC_DIST_PATH/$SC_APP.jar ]] ; then
rm "$SC_DIST_PATH/$SC_APP.jar"
if [[ -f $SC_DIST_PATH/$SC_APP.jar ]] ; then
echo "Unable to remove existing distribution!: $SC_DIST_PATH/$SC_APP.jar"
exit 1
fi
fi
if [[ ! -f $SC_MANIFEST_PATH ]] ; then
LEN_BASE=$(echo $(( $(echo "./$SC_SRC_PATH" |wc -c) - 0 )))
SC_MAIN_CLASS=$(echo $SCALA_MAIN |cut --complement -c1-$LEN_BASE)
SC_MAIN_CLASS=${SC_MAIN_CLASS%%.*}
SC_MAIN_CLASS=$(echo $SC_MAIN_CLASS |awk '{gsub( "/", "'"."'"); print}')
echo $(echo "Main-Class: "$SC_MAIN_CLASS) > $SC_MANIFEST_PATH
echo $(echo "Class-Path: "$SC_INCLUDE_LIB_JAR) >> $SC_MANIFEST_PATH
fi
scalac -sourcepath $SC_SRC_PATH -d $SC_BIN_PATH $SCALA_MAIN
COMPILE_STATUS=$?
if [[ $COMPILE_STATUS != "0" ]] ; then
echo "Compile Failed!"
exit 1
fi
cd "$SC_BIN_PATH"
jar -cfm ../$SC_DIST_PATH/$SC_APP.jar ../$SC_MANIFEST_PATH *
COMPILE_STATUS=$?
cd "$SC_STARTING_PATH"
if [[ $COMPILE_STATUS != "0" ]] || [[ ! -f $SC_DIST_PATH/$SC_APP.jar ]] ; then
echo "JAR Build Failed!"
exit 1
fi
echo " "
echo "BUILD COMPLETE!... TO LAUNCH: java -jar $SC_DIST_PATH/$SC_APP.jar"
echo " "
One thing which may cause a similar problem (although it's not the problem in the initial question above) is that the Java vm seems to demand that the main method returns void. In Scala we can write something like (observe the =-sign in the definition of main):
object MainProgram {
def main(args: Array[String]) = {
new GUI(args)
}
}
where main actually returns a GUI-object (i.e. it's not void), but the program will run nicely when we start it using the scala command.
If we package this code into a jar-file, with MainProgram as the Main-Class, the Java vm will complain that there's no main function, since the return type of our main is not void (I find this complaint somewhat strange, since the return type is not part of the signature).
We would have no problems if we left out the =-sign in the header of main, or if we explicitly declared it as Unit.
If you do not wish to use sbt facilities I recommend the use of a makefile.
Here is an example where foo package is replaced by foo.bar.myApp for completeness.
makefile
NAME=HelloWorld
JARNAME=helloworld
PACKAGE=foo.bar.myApp
PATHPACK=$(subst .,/,$(PACKAGE))
.DUMMY: default
default: $(NAME)
.DUMMY: help
help:
#echo "make [$(NAME)]"
#echo "make [jar|runJar]"
#echo "make [clean|distClean|cleanAllJars|cleanScalaJar|cleanAppJar]"
.PRECIOUS: bin/$(PATHPACK)/%.class
bin/$(PATHPACK)/%.class: src/$(PATHPACK)/%.scala
scalac -sourcepath src -d bin $<
scala-library.jar:
cp $(SCALA_HOME)/lib/scala-library.jar .
.DUMMY: runjar
runJar: jar
java -jar $(JARNAME).jar
.DUMMY: jar
jar: $(JARNAME).jar
MANIFEST.MF:
#echo "Main-Class: $(PACKAGE).$(NAME)" > $#
#echo "Class-Path: scala-library.jar" >> $#
$(JARNAME).jar: scala-library.jar bin/$(PATHPACK)/$(NAME).class \
MANIFEST.MF
(cd bin && jar -cfm ../$(JARNAME).jar ../MANIFEST.MF *)
%: bin/$(PATHPACK)/%.class
scala -cp bin $(PACKAGE).$#
.DUMMY: clean
clean:
rm -R -f bin/* MANIFEST.MF
cleanAppJar:
rm -f $(JARNAME).jar
cleanScalaJar:
rm -f scala-library.jar
cleanAllJars: cleanAppJar cleanScalaJar
distClean cleanDist: clean cleanAllJars

Categories