I've used an older version of Google's Java to Objective-C (J2ObjC) converter previously (i.e. version 0.5.2) and it was straightforward to translate an entire folder of Java files to their equivalent Objective-C files (and to preserve the directory structure in doing so). I just had to run the following shell executable:
$ ./run.sh —-preservedirs <path to input folder>
I've just downloaded the latest version of J2ObjC (i.e. version 0.9.1) and it's not clear from the Getting Started page or elsewhere how I can translate an entire folder of Java files rather than just a single Java file using the j2obc executable. The only example provided in the Getting Started page is to translate a single Java file which has no dependencies or imports elsewhere as follows:
$ ./j2objc Hello.java
Can anyone provide me with an example of how to translate an entire package assuming I have a folder named input which contains my com package which contains all of the sub-packages and Java files that I want to translate?
To build a whole project, I add the source root(s) to the -sourcepath, then use the find command to locate all Java sources. For example, to build Square.com's Dagger library:
$ export J2OBJC=~/j2objc # change to wherever your distribution is
$ cd ~/src/dagger/core
$ $J2OBJC/j2objc -d build_output -sourcepath src/main/java \
-classpath $J2OBJC/lib/javax-inject.jar \
`find src/main/java -name '*.java'`
All the generated .h and .m files are now in the build_output directory, in subdirectories according to their package (like javac does). To compile all the .m files into a static library, I use:
$ cd build_output
$ j2objcc -c -I. `find . -name '*.m'`
$ libtool -static -o libdagger.a *.o
If there is no better way built into run.sh, you could use find's -exec flag:
find <path to input folder> -type f -exec --preservedirs ./run.sh {} \;
Or, you could use xargs to do multiple files at the same type:
find <path to input folder> -type f | xargs ./run.sh --preservedirs
(You might also need to add -name "*.java" to the find arguments if there are non-Java files in your directories).
I need to make a makefile for a Java project.
My project is basic. A package which contains my main file and some others packages.
Can someone help me to make a proper makefile for that kind of project ?
Sorry I have not tested so it is likely to fail...
Assuming that what you need is to generate a executable jar file the following should work but I have not tested it.
The Makefile below assumes that your sources are located under ./src and that you are happy to use ./build for intermediary files (which is totally obliterated by the clean target so be careful).
Then 'make' or 'make jar' should generate the jar file.
NAME=MyProject
MAIN_CLASS=MyMainClass
SRC_DIR=./src
CLS_DIR=./build/classes
MANIFEST_FILE=./build/META-INF.MF
JAR_FILE=./$(NAME).jar
SRC_FILES=$(shell find $(SRC_DIR) -iname "*.java")
CLS_FILES=$(patsubst $(SRC_DIR)/%,$(CLS_DIR)/%,$(patsubst %.java,%.class,$(SRC_FILES)))
.PHONY: jar run clean mrproper
jar : $(JAR_FILE)
run : $(JAR_FILE)
java -jar $(JAR_FILE)
$(JAR_FILE) : $(MANIFEST_FILE) $(CLS_FILES)
jar cmf $< $# $(CLS_DIR)
$(MANIFEST_FILE) :
mkdir -p $(dir $#)
echo Main-Class: $(MAIN_CLASS) > $#
$(CLS_DIR) :
mkdir -p $(CLS_DIR)
$(CLS_DIR)/%.class : $(SRC_DIR)/%.java $(CLS_DIR)
javac -d $(CLS_DIR) -sourcepath $(SRC_DIR) $<
clean :
rm -Rf ./build
mrproper : clean
rm -f $(JAR_FILE)
Each time you execute Make it performs a find operation to get the list of source files, that might cause some delay depending on how many files and how fast is the file-system.... but you said is is a small project so it should not be an issue.
The double patsubst might well be compressed into a single one but I did it in two steps just in case.
Also notice that this solution compiles each Java class separately. This can be quite costly and it might be advisable to have another target to compile all at once ideally by creating a file that contains the name of all src java files and passing it to javac.
I used to work with Eclipse but switched recently to CodeRunner. The Problem is I'm supposed to use Graphviz, Batik and a Package from my college in order to work on some projects.
As long as there was one .jar file I'll managed to use my own with a simple:
RunCommand: java -jar stopndrop.jar $compiler
Arguments:
$1 Filename of the source file
$2 Encoding of the source file
$3 Compilation flags set in CodeRunner
$4 Path of a temporary directory
javac "$1" -d "$4"/java-compiled -encoding ${enc[$2]} $3 -cp stopndrop.jar
But now there is the Batik and College Folder with a bunch of Classes that are supposed to be loaded when they r needed.
My Question is: How do I do that?
Suppose that you have the following folder structure:
lib/
a.jar
b.jar
classes/
com/
foo/
Bar.class
Baz.class
And you need to link with all of these things to compile some code. Then you would specify as your classpath:
-cp lib/a.jar:lib/b.jar:classes
I have a java project, and need to write makefile to let it run on Linux. My project includes external jar files and resource package(.txt resourses).I am really a newbie for Linux, and just learn how to write makefile.
I refer to some materials and write a makefile like this:
# Set the file name of your jar package:
JAR_PKG = ADBproject1.jar
# Set your entry point of your java app:
ENTRY_POINT = adb/Bing_WebResults/Run.java
# Need resource directory
RES_DIR = yes
SOURCE_FILES = \
adb/jsonModels/Metadata.java \
adb/jsonModels/Result.java \
adb/jsonModels/Data.java \
adb/jsonModels/DataContainer.java \
adb/models/Weight_ID.java \
adb/models/Pair.java \
adb/models/Document.java \
adb/models/Collections.java \
adb/Bing_WebResults/Bing_Search.java\
adb/Bing_WebResults/Run.java \
JAVAC = javac
JFLAGS = -encoding UTF-8
vpath %.class bin
vpath %.java src
# show help message by default
Default:
#echo "make new: new project, create src, bin, res dirs."
#echo "make build: build project."
#echo "make clean: clear classes generated."
#echo "make rebuild: rebuild project."
#echo "make run: run your app."
#echo "make jar: package your project into a executable jar."
build: $(SOURCE_FILES:.java=.class)
# pattern rule
%.class: %.java
$(JAVAC) -cp bin -d bin $(JFLAGS) $<
rebuild: clean build
.PHONY: new clean run jar
new:
ifeq ($(RES_DIR),yes)
mkdir -pv src bin res
else
mkdir -pv src bin
endif
clean:
rm -frv bin/*
run:
java -cp bin $(ENTRY_POINT)
jar:
ifeq ($(RES_DIR),yes)
jar cvfe $(JAR_PKG) $(ENTRY_POINT) -C bin . res
else
jar cvfe $(JAR_PKG) $(ENTRY_POINT) -C bin .
endif
But I don't know how to add those two external .jar files (gson.jar, commons.jar) into makefile. And I'm not quite sure, whether the file paths I wrote are correct.
javac has a -cp and -classpath argument:
-classpath <path> Specify where to find user class files and
annotation processors
-cp <path> Specify where to find user class files and
annotation processors
They seem to be equivalent as far as the documentation is concerned.
I solve the problem by adding all *.jar files to a new folder "lib".
Then
javac -sourcepath src/ -classpath lib/*.jar
will solve the external jar file problem.
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