Creating Java Manifest Files with Eclipse-or-anything-else

Discussion in 'Mac Programming' started by fishinatree, Jun 17, 2008.

  1. macrumors newbie

    Joined:
    Jun 7, 2008
    Location:
    Santa Rosa, CA
    #1
    I'm trying to create a .jar file for a small Java program that I wrote, but I cannot get it to execute. I know that I need to create a manifest file, but I cannot find a tutorial anywhere that tells me how to do it clearly enough...
    I created a folder called META-INF and inside have a file called MANIFEST.MF, which contains the lines:

    Manifest-Version: 1.0
    Created-By: 1.6.0 (Sun Microsystems Inc.)
    Main-Class: gabe.ScanningApp

    where gabe is the package name, and ScanningApp is the name of the class with the main method. I cd to where the files are, then use the terminal:

    jar cfm gabe.jar META-INF/MANIFEST.MF *.class

    i get the jar file, and when i use jar tf gabe.jar, I get a list of everything, but when I double click it, I get

    java.lang.NoClassDefFoundError: ibbabble/src/gabe/ScanningApp

    Should I have kept everything in that directory path instead of moving it to the desktop to package it in a .jar file? I'm very confused here...

    |fishinatree|
     
  2. macrumors 6502a

    Joined:
    Sep 3, 2005
    Location:
    Cramlington, UK
    #2
    Hi, you can get Eclipse to create the manifest file for you when it creates your Jar file. Right click on a package and select Export, Jar file. From there you get a dialog and various options, some of which are to do with selecting your main class, saving the process as a Jar description file etc.


    b e n
     
  3. macrumors regular

    Joined:
    Apr 29, 2008
    #3
    Short answer with Eclipse:
    1. Right-click the src directory of the project (so that you export all its packages)
    2. Choose Export, and select "JAR file" under "Java"
    3. Click Next to the third (last) page
    4. Select "Generate the manifest file"
    5. At the bottom, browse for the "Main class" (it shows only those classes with a main method)
    6. Finish

    Long answer with command line tools if you want to sort of understand how this works:

    The first warning sign is that you used *.class at the end of the jar create command. That would only work on class files in the current directory, and put them at the root of the JAR. (A JAR is a ZIP, and all ZIPs have their own directory structure.) But since you put your class in a package -- as you should -- the class should be under the gabe directory in the JAR. What you must do is tell the jar utility to start JARing at the directory that contains the gabe directory.

    You don't need to put the manifest in a file named MANIFEST.MF -- the jar utility will put any file you specify as META-INF/MANIFEST.MF. Therefore, you also don't need to put it anywhere special.

    Because you want to tell the jar utility to JAR a directory, that directory must contain only class files (and other resources like images) -- no source files, otherwise they would go in the JAR too. The common practice is to put them in a bin directory. So in the directory ibbabble, your current directory, you should have this (bin is empty, javac will not create it):

    bin/
    src/
    src/gabe/
    src/gabe/ScanningApp.java

    javac is not exactly straightforward in supporting this structure. You have to do something like this:

    Code:
    javac -d bin -sourcepath src src/gabe/ScanningApp.java
    What this means is:
    • put the class files under the proper directories under bin
    • look for other source files in the proper directories under src
    • start compiling with the file src/gabe/ScanningApp.java

    Because in this case you are only compiling one file, you really don't need the -sourcepath. But if for example, ScanningApp extended another class, javac would (or should) find it through the sourcepath; you don't have to list them all. But even if you do specify a sourcepath, you have to explicitly point to the file to compile (partly because the sourcepath can contain more than one directory).

    After the compile, you should have:

    bin/
    bin/gabe/
    bin/gabe/ScanningApp.class
    src/
    src/gabe/
    src/gabe/ScanningApp.java

    Create the manifest file somewhere convenient, like the current directory. You could call it scanning.mf:

    scanning.mf
    bin/
    bin/gabe/
    bin/gabe/ScanningApp.class
    src/
    src/gabe/
    src/gabe/ScanningApp.java

    Now the command would be:

    Code:
    jar cvfm gabe.jar scanning.mf -C bin .
    • v for verbose, if you want to see what it's doing
    • use the scanning.mf file in the current directory
    • then change to the bin directory
    • and include the contents of that directory (the dot) recursively

    Note that the directory change happens inside the program only; the current directory of the shell does not change. If you then list the contents of the JAR with jar tf:

    META-INF/
    META-INF/MANIFEST.MF
    gabe/
    gabe/ScanningApp.class

    That's what you want. The class is in exactly the right place. What if you had done:

    Code:
    jar cvfm gabe.jar scanning.mf bin
    You would get:

    META-INF/
    META-INF/MANIFEST.MF
    bin/
    bin/gabe/
    bin/gabe/ScanningApp.class

    That's wrong. See the difference?
     
  4. macrumors 6502a

    Joined:
    Sep 3, 2005
    Location:
    Cramlington, UK
    #4
    ^^^ An excellent reply. Worth reading for the mention of the -C option alone!
    b e n
     
  5. macrumors 6502a

    Joined:
    Dec 4, 2006
    Location:
    Katy, Texas
    #5
    Thanks so much for this thread. I've been wanting to learn how to do this. You guys ROCK!

    Todd
     
  6. thread starter macrumors newbie

    Joined:
    Jun 7, 2008
    Location:
    Santa Rosa, CA
    #6
    I tried this, but i got
    as an error on the Console. What am I doing wrong? I'll try compiling with the command line next, but I'd really prefer to be able to do it with Eclipse. Thanks for your input, everybody!

    |fishinatree|

    Edit: hazmatzak, you specified the code
    Code:
    javac -d bin -sourcepath src src/gabe/ScanningApp.java
    , but what does -sourcepath mean? Do I type out the sourcepath "-something/someting/something/etc", or does -sourcepath refer to something else?
     
  7. macrumors regular

    Joined:
    Apr 29, 2008
    #7
    When posting Java exceptions, include the first line, which says what the problem is, and the first few lines that follow (which start with "at"). If the exception stack has scrolled off, make the scroll buffer of the console bigger.

    The -sourcepath is one or more directories in which to look for source. It's the same idea as the OS/shell's path: one or more directories to look for programs to run when you type their name. However, for the sourcepath, having only one directory is fairly common, since you often "root" all your source for a project in a single directory.

    Compare it to the -classpath in the javac examples at the bottom of: http://java.sun.com/j2se/1.3/docs/tooldocs/win32/javac.html

    You can point to each directory using its relative or absolute location. For example, if the source directory is /home/fish/ibbabble/src, you can always use that. If your current directory is /home/fish/ibbabble, you can use "src"; if the current directory is /home/fish, you can use "ibbabble/src"
     
  8. macrumors 6502a

    Joined:
    Jan 15, 2007
    #8
    Apache ant and the jar task

    Ant is built into eclipse, so you don't need other tools, and you can customize it to your hearts content. Better yet, after you have the antfile done, its trivial to do your compile/jar building distribution in one step on the command line.

    We do this at work and it saves TONS of time.
     

Share This Page