SCons for Java; Is there an analog for env.Program()? - java

I need to create an executable file, run, that will call # java for my classes
I am compiling my java project with SCons:
libFiles = "lib/myLibs.jar"
# Build the environment
env = Environment(JAVACLASSPATH = libFiles, JAVASOURCEPATH = '.')
env.Java(target = 'classes', source = 'src')
All of the classes are stored in folder classes/ and all the source files are in /src . To run the program, I have to
# cd classes/
# java -cp . myProg
Is there a way to have SCons create an executable in the root directory so it can call java by itself? I looked at an existing project that used env.Program() but that was only for C++.
Thanks!

You may use the Jar builder. The following SCons example does what you want.
jar = java_env = Jar(target='Observer',
source=['Observer.java',
'Manifest.txt'])
Note that if you want the Manifest.txt file to work as well it must have the following first line:
Manifest-Version: 1.0
You should only use the Java builder if you want to generate the .class files.

Related

JRuby, Warbler, and Java's CLASSPATH

I've been developing applications in JRuby lately and really enjoying it, but I've been running into a wall when it comes to packaging my project into a JAR file when it includes external Java libraries. If the project does not depend on any external Java library JAR files, I run into no problems.
Below is an example application. This code works perfectly fine when running the ./bin/my_proj executable. But, when I package it into a JAR file, the external Java library cannot be loaded because it is not found on the CLASSPATH.
When I unpackage my application's JAR file, I can see that it includes all of my code as well as the vendor directory containing the external Java library. So, everything's where it should be.
lib/my_proj/application.rb
java_import 'com.somecompany.somejavalibrary.SomeJavaLibraryClass'
module MyProj
class Application < SomeJavaLibraryClass
# Some code implementing SomeJavaLibraryClass
end
end
lib/my_proj.rb
require 'pathname'
module MyProj
def root
Pathname.new(__FILE__).join('..', '..').expand_path
end
def start
setup_environment
Application.new
end
def setup_environment
#setup ||= false
unless #setup
#setup = true
require 'java'
$CLASSPATH << root.join('vendor').to_s # Setup Java CLASSPATH
$LOAD_PATH << root.join('lib').to_s # Setup Ruby LOAD_PATH
require 'some_java_library' # Load the external Java library from it's JAR
require 'my_proj/application'
end
end
extend self
end
bin/my_proj
#!/usr/bin/env ruby
$:.unshift File.expand_path( File.join('..', '..', 'lib'), __FILE__ )
require 'my_proj'
MyProj.start
config/warble.rb
Warbler::Config.new do |config|
config.features = %w(gemjar compiled)
config.autodeploy_dir = 'pkg'
config.dirs = %w(assets bin config lib)
config.java_libs += FileList['vendor/*.jar']
end
vendor/some_java_library.jar
# This is the external Java library
The external jars should be in the lib folder.
You can add them in code by doing something like
$CLASSPATH << "vendor/some_java_library.jar" #or loop the directory for all jars and add them
Or you can create a META-INF/MANIFEST.MF file and specifiy the CLASSPATH jars
and adding a line like
Class-Path: vendor/some_java_library.jar jar2-name directory-name/jar3-name
http://docs.oracle.com/javase/tutorial/deployment/jar/downman.html

Java: Setting Classpath

I have a project due soon and everything is coming together really nicely, but java classpaths are getting seriously in the way. I'll try to explain the situation as clearly and thoroughly as I can.
So we are using Javacc to write a programming language. The javacc file compiles into several java files. The Parser.java file includes references and calls to the other generated java files. So, after generation, we compile the Parser.java file. The problem is we get many errors, including not being able to recognize the calls to the other java files as well as our own files. We asked on a classroom discussion board about our problem and the professor responded with "you need to have the class files in your classpath". Ok, great, so the question is, how do we do that? Basically we have a single directory with the generated java files and our other helper files.
So, what have we tried?
I have tried changing my .bashrc (Ubuntu) file to include the correct classpath but that doesn't work. i.e.
CLASSPATH=Home/project
(something like that I had the syntax right in the file)
I've tried on compilation executing
javac -cp . Parser.java
and
javac -cp "." Parser.java
neither works.
I have tried to edit the xml (I think xml) .classpath file in the directory of our files. Still doesn't work.
Somehow, I was able to compile Parser.java in one of the directories I have (we ended up making multiple directories with the same files in it in a futile effort to make something work) but when I try to run
java -cp . Parser.java
or
java Parser.java
It says it can not find the main and throws (I believe, its on my other computer) ClassNotFound or ClassNotDefined exception (something like that, it cannot find the main in the Parser file eventhough it IS there).
We have tried adding packages deceleration and import statements to our file, nothing seems to work.
BASICALLY: How can I successfully change the Classpath so that my java files (all in one directory and not jarred) can be compiled and run on my machine?
Thank you for your help. I greatly appreciate it.
I highly suggest you look into Ant. A simple build file can solve all these problems for you.
You don't need to edit your .bashrc or CLASSPATH.
From the command line you need to build ALL the java files together. I am not sure if JavaCC needs javacc.jar after it's generated your Lexer and Parser. But let's assume it does for some generic AST support.
javacc.jar is located in ~/javacc-5.0/lib/javacc.jar
Scenario 1: Simple directory structure, all Java files are in the root folder with no package.
root
| Parser.java
| Lexer.java
| Program.java
To compile these I need to run:
javac -cp ~/javacc-5.0/lib/javacc.jar Parser.java Lexer.java Program.java
then I can execute Program like so if Program has main
java -cp ~/javacc-5.0/lib/javacc.jar:. Program
Scenario 2: Medium directory structure, code in root but with packages.
root
| org
| myproject
| Parser.java
| Lexer.java
| Program.java
then you need to execute javac like so:
javac -cp ~/javacc-5.0/lib/javacc.jar org/myproject/Parser.java org/myproject/Lexer.java org/myproject/Program.java
and to execute
java -cp ~/javacc-5.0/lib/javacc.jar:. org.myproject.Program
Scenario 3: Complex directory structure, specific source directory with packages.
root
| src
| org
| myproject
| Parser.java
| Lexer.java
| Program.java
then you need to execute javac like so:
javac -cp ~/javacc-5.0/lib/javacc.jar -sourcepath src src/org/myproject/Parser.java src/org/myproject/Lexer.java src/org/myproject/Program.java
and to execute
java -cp ~/javacc-5.0/lib/javacc.jar:src org.myproject.Program
There is a difference between javac and java . You try to use them in wrong way. javac is a compiler which produces *.class files (in your case Parser.class). This *.class file must be then run by java.
So if I have file Parser.java
class Parser {
public static void main(String[] args) {
System.out.println("Hi");
}
}
I would go the directory where this files resides and run in shell:
javac Parser.java
Than run the compiled file
java Parser
And that's it. Note that the name of the class in java file must be same as the name of the file.
Create a Jar file of all your compiled classes. Refer to this tutorial on how to create a jar file.
Start you program with this command
java -classpath pathToJarFile com.abc.MainClass

Problem in adding jar library in JNI

How to add a folder that contain jar files in jni c++. for example i have a folder "MyLib" that contains "Math.jar","Stats.jar" and "Temp.jar". I want to add "MyLib" to classpath insted of adding all the jar files like
options[0].optionString = "-Djava.class.path=c:\myjni\MyLib";
instead of
options[0].optionString = "-Djava.class.path=c:\myjni\MyLib\Math.jar ; c:\myjni\MyLib\Stats.jar ; \c:\myjni\MyLib\Temp.jar" ;
Well you cant do that. You are allowed only to add JAR files or directories with class files to the classpath.
You could extract all jars to a directory and add this directory to the classpath.
Actully there IS a trick. Java from version 6.0 by Sun adds a possibility to expand globs. This should work in Java 6+:
java -cp lib/*.jar
So you could try this:
options[0].optionString = "-Djava.class.path=c:\myjni\MyLib\*.jar";
I am not sure if it works with -D classpath setting. If you can provide the classpath cia -cp option do that. Please note the expansion is in the JVM has some limitations:
http://javahowto.blogspot.com/2006/07/jdk-6-supports-in-classpath-but-be.html

CLASSPATH 101... (on Windows)

I'm new to working with Java from the command line and I don't get it. I read previous CLASSPATH questions but still didn't get my problem to work.
I have the following class in C:\Temp\a\b\c
package a.b.c;
public class Hello
{
public static void main(String args[])
{
System.out.println("Hello World!");
}
}
The package name is intentional.
I compiled it fine and I put the Hello.class file inside C:\Temp\a\target
Now in the command line I go to C:\Temp\ and execute the following:
java -cp .\a\target a.b.c.Hello
It complains that it cannot find the class a.b.c.Hello
Thanks in advance!!
and I put the Hello.class file inside C:\Temp\a\target
This is wrong. It should be placed in the same folder as the .java file. The source code itself is declared to be in the package a.b.c; so, the .class file should really be kept in \a\b\c folder.
Then, to execute it just do:
C:\Temp>java -cp . a.b.c.Hello
Avoid "putting" the classfiles anywhere. The following should work:
javac -d c:\temp c:\temp\a\b\c\Hello.java
# creates Hello.class in c:\temp\a\b\c
java -cp c:\temp a.b.c.Hello
To expand on BalusC's point: the classpath defines a "root". When java is looking for your classes, it will start at each root (or jar) in your class path and drill down through the directories to match the package strucutre. You still need to have you class in a directory structure that matches its package name. In your case, to execute
java -cp .\a\target a.b.c.Hello
you would move the file to
.\a\target\a\b\c\Hello.class
Years ago, I too found this baffling.
Java will try to search for a directory structure a\b\c from starting in target and as you notice, it wont work.
Move the whole directory into target and you'll be fine, it should look like:
C:\Temp\a\target\a\b\c\Hello.class
You may compile it with the -d option which tall the compiler where to put the class file.
Many project structures are like this.
C:\whatever\projectname\src
C:\whatever\projectname\classes
C:\whatever\projectname\bin
C:\whatever\projectname\lib
C:\whatever\projectname\doc
That way you can always step on your project directory and type:
javac -d classes src\*.java
Which will compile all the sources in the src directory and will place them in the classes directory.
Then execute your program:
java -cp classes a.b.c.Hello
You may optionally place required jars in lib
This works pretty fine for small programs ( < 10 src files and 2 - 3 jar libraries ) If it grows beyond that, you could probably use an IDE or ant
The good thing about following this project structure is that some IDES ( as IntellJ idea ) just pick them very easily when you create a new project. You select "Create project from existing sources" and then you can continue from there.
I like compiling and editing at the command line a lot!!

Package not found; javac

This is annoying.
I have a directory structure like this
-lib
--some jar files
-packageName
--Main.java
--SomeOtherPackage
--SomeOtherJavaClass.java
Main.java imports SomeOtherPackage. And both java files uses jars in the lib.
What I do is add the jar files independently in the CLASSPATH. And then run as:
javac packageName/Main.java
but it gives the error that Package not found SomeOtherPackage . Shouldn't it automatically realize the dependency and build SomeOtherPackage as well? What would be the javac command and the classpath for the above case?
Thanks
The normal practice is to add the package root to the classpath.
When you're already in the package root, use -cp .. E.g.
cd /path/to/all/packages
javac -cp . packageName/Main.java
If you want to include JAR files as well, use the ; (or in *nix, the :) as classpath path separator:
javac -cp .;lib/file.jar packageName/Main.java
To save the time in repeating all the typing of shell commands, use a .bat (or in *nix a .sh) file. Or just an IDE if you're already familiar with java/javac and so on.
You need to add packageName to the CLASSPATH so it can find SomeOtherPackage

Categories

Resources