This week's book giveaway is in the Agile and Other Processes forum.
We're giving away four copies of The Journey To Enterprise Agility and have Daryl Kulak & Hong Li on-line!
See this thread for details.
Win a copy of The Journey To Enterprise Agility this week in the Agile and Other Processes forum! And see the welcome thread for 20% off.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Jeanne Boyarsky
  • Liutauras Vilda
  • Campbell Ritchie
  • Tim Cooke
  • Bear Bibeault
Sheriffs:
  • Paul Clapham
  • Junilu Lacar
  • Knute Snortum
Saloon Keepers:
  • Ron McLeod
  • Ganesh Patekar
  • Tim Moores
  • Pete Letkeman
  • Stephan van Hulst
Bartenders:
  • Carey Brown
  • Tim Holloway
  • Joe Ess

Compiling multi-file projects  RSS feed

 
Ranch Hand
Posts: 40
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Suppose my project has 2 classes. Main and data. Each lives as a separate text file in the same directory on my hard drive. I import class data into class main. Then I make changes to class data. When I recompile main, does the compiler sense that class data has changed and automatically recompile it, or do I need to have my batch file explicitly process both fist data and then main?
 
Bartender
Posts: 1843
46
Eclipse IDE Google Web Toolkit Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well that's an interesting question. However, I believe the answer can be simply verified by writing a short 3 line code.

Can you try it and share your experience with us ?
 
Saloon Keeper
Posts: 1800
74
Android Chrome IntelliJ IDE Java MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This depends on what IDE you are using along with which plugins for said IDE and what framework you are using for the project that you are working on.

For instance there JRebel (not free) found here https://zeroturnaround.com/software/jrebel/ can do some (all?) of this.

If you are using Spring (from https://spring.io/) you can use the "dev starter pack" dependency to get some of the project updated when a compile time change occurs.
This has a limit as to what it can and cannot do.

Live Reload can be enabled on the project (once again in Spring at least) and it can track changes to web files. Best to use this with the Live Reload browser addon.

There may be other plugins for the IDE of your choice. As such I'd check the IDE plugin registry/repository.
 
salvin francis
Bartender
Posts: 1843
46
Eclipse IDE Google Web Toolkit Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Pete Letkeman wrote:This depends on what IDE you are using ...


I suspect (I may be wrong), the OP is manually compiling it with javac.
 
ras oscar
Ranch Hand
Posts: 40
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

salvin francis wrote:

Pete Letkeman wrote:This depends on what IDE you are using ...


I suspect (I may be wrong), the OP is manually compiling it with javac.



That is correct. I have written a batch file that changes to the current directory and then compiles the class containing main(). I have not yet been able to compile the program since splitting it and am trying to diagnose the problem. Was thinking that perhaps I need to compile both.
 
salvin francis
Bartender
Posts: 1843
46
Eclipse IDE Google Web Toolkit Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

ras oscar wrote:...I have written a batch file that changes to the current directory and then compiles the class containing main()...


Have you tried simply writing :

in your script ?
 
Pete Letkeman
Saloon Keeper
Posts: 1800
74
Android Chrome IntelliJ IDE Java MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Okay, I do think that you may want something a bit more then javac and batch files for this.

ras oscar wrote:I have not yet been able to compile the program since splitting it and am trying to diagnose the problem.


What are the error(s) that you are experiencing?
 
Marshal
Posts: 59742
188
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

salvin francis wrote:. . . the OP is manually compiling it with javac.

In which case the behaviour may differ depending on whether the two classes are in the same package or not.
 
Bartender
Posts: 19664
92
Android Eclipse IDE Linux
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:

salvin francis wrote:. . . the OP is manually compiling it with javac.

In which case the behaviour may differ depending on whether the two classes are in the same package or not.



Very definitely. And once you start compiling multi-package projects, a simple javac command or batch script doesn't really do the trick anymore. At that point, it's better to use a Java-specific build tool such as Ant, Maven, Gradle, or the like.
 
ras oscar
Ranch Hand
Posts: 40
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
when I was doing C++ many years ago, it seemed that the Microsoft IDE was invoking bat files in the background to build the application. I remember I got compiler errors and link errors. Does java not have an internal linker to resolve external dependencies?

FYI, the main() function is veeeeeery simple. It simply calls the starting point of the data class. I am doing it this way because I would like to eventually be able to use the data class in larger projects, and I thought this would be a good time to do the transition to multi class structures.
 
Sheriff
Posts: 5028
138
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If you want dependency resolution you should probably use Maven or Gradle.
 
Campbell Ritchie
Marshal
Posts: 59742
188
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

ras oscar wrote:when I was doing C++ many years ago, it seemed that the Microsoft IDE was invoking bat files in the background to build the application.

C++ is different from Java® and using an IDE is different from compiling at the command line, or .bat files. You cannot expect them to behave the same.

. . . . Does java not have an internal linker to resolve external dependencies?

Yes, if it knows where the dependencies are; that is what imports and the classpath are all about.

FYI, the main() function is veeeeeery simple. It simply calls the starting point of the data class. . . .

That is the normal way to write a main() method, despite what you see in some books and tutorials.
 
Tim Holloway
Bartender
Posts: 19664
92
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

ras oscar wrote:when I was doing C++ many years ago, it seemed that the Microsoft IDE was invoking bat files in the background to build the application. I remember I got compiler errors and link errors. Does java not have an internal linker to resolve external dependencies?



One of the biggest differences between C/C++ and Java is how they form programs.

In C (or C++), you compile your source files, link in external libraries, and get a (more or less) stand-alone executable file that can be directly loaded and run by the OS loader.

In Java, what's executed is the Java Virtual Machine (JVM), which is supplied with classes to execute. The classes may be loose (in a directory tree) and/or in Java Archive (JAR) files, which are actually just ZIP files full of classes plus one or more files of interest to Java (the META-INF directory). Incidentally, a JAR inside another JAR is not normally accessible to the Java class loader. Although some specialized run environments have exceptions to that rule.

While some JARs contain complete executable applications, Java often requires additional class resources. The totality of all the classes is the core classes in the JVM (stuff like java.lang.Object and java.lang.String) plus what's in your classpath. The classpath is like the PATH for executables except that the OS program loader knows nothing about it - it's used ONLY by the JVM to locate and load classes and class resources. The classpath locates the JVM internal classes plus additionally-specified class directory trees and/or JARs containing class resources. Actually, it's a concatenation of paths in most cases and in some systems there may be more than one classpath. For example webapp servers have a distinct classpath for each webapp, plus one or more for the internal processes of the webapp server (which is usually a Java Application).

You also need a classpath when compiling Java code, since unlike C (I'll assume this includes C++ for brevity going forward), there are no separate header and code files in Java. The "header" comes from referencing the compiled class itself. Note that at this level a Java Interface is itself a class, just in case you thought it was a header file.

So you have to have access to both your own source code and the compiled code of external class resources that your code needs. These are provided to the javac compiler via the classpath specified when you run javac (or when a tool such as Maven or Ant runs javac).

One of the reasons why Maven became popular was that instead of having to assemble all your external class references manually, you can indicate what classes you need in your Maven project's POM file. Maven will then go to the Internet and pull them from public repositories and cache them in a per-user local directory - which means that the slower network access is only done once. This cache is then available to all Maven compiles done for that user account, eliminating duplication of common resources and, incidentally ensuring that Maven-managed code is "write-once/compile anywhere". Ant doesn't normally do this, but the Ant Ivy extension does.
 
ras oscar
Ranch Hand
Posts: 40
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
ok, I've made a SCE that re-creates the error messages I'm experiencing:

DataMain.java contains:



Data.java contains:

import java.io.*;
import java.lang.*;


MainCompile.bat contains:



When I run the bat file the console output looks like this:

C:\Program Files (x86)\Notepad++>cd c:\java\Command Line\Data

c:\Java\Command Line\Data>javac Data.java

c:\Java\Command Line\Data>javac DataMain.java
DataMain.java:1: error: '.' expected
import Data;
           ^
DataMain.java:1: error: ';' expected
import Data;
            ^
DataMain.java:2: error: class, interface, or enum expected
import java.io.*;
       ^
3 errors

c:\Java\Command Line\Data>pause
Press any key to continue . . .

 
Ranch Hand
Posts: 423
2
Chrome Linux VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I bounce between javac and Android Studio.  I prefer using the command line, but sometimes you need something like AS.  This is a Makefile I use, which is better than a batch script.
 
Knute Snortum
Sheriff
Posts: 5028
138
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You don't need import Data; in DataMain.java; I would remove it.  In fact, remove all import statements in both programs.  Never import java.lang.*; that it imported for you automatically.
 
ras oscar
Ranch Hand
Posts: 40
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Knute Snortum wrote:You don't need import Data; in DataMain.java; I would remove it.  In fact, remove all import statements in both programs.  Never import java.lang.*; that it imported for you automatically.



So if I don't need to import Data into DataMain, how does DataMain know where to find the class file?
 
Knute Snortum
Sheriff
Posts: 5028
138
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I believe the JVM will always look in the current directory for class files.
 
Knute Snortum
Sheriff
Posts: 5028
138
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I found this statement in the Java docs:

The Java Docs wrote:For .class files in an unnamed package, the class path ends with the directory that contains the .class files.


 
ras oscar
Ranch Hand
Posts: 40
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I commented out all the import statements and re-ran the compile batch. Both files compiled without complaint and emitted a ".class" file. I ran the run batch and got the console output:


C:\Java\Command Line\Data>cd c:\java\Command Line\Data

C:\Java\Command Line\Data>java Data.class
Error: Could not find or load main class Data.class

C:\Java\Command Line\Data>pause
Press any key to continue . . .

so I appear to have shifted the error from the compile step to the run step.

I have been mucking around with the java command line -classpath options but have not yet hit the correct option. If that doesnt work I will start researching .jar files.
 
Knute Snortum
Sheriff
Posts: 5028
138
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The java tool takes a class name, not a file name, so...

java Data
 
Tim Holloway
Bartender
Posts: 19664
92
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Make is a really horrible tool to build Java classes with. Although it has a long and honorable history with C, C++, assembler and many other languages and utilities, it really can't properly follow how Java organizes things. If you like rule-based compiling use Ant. If you like the idea of just being able to put all the source in one directory and have all the classes magically pop out in another (with the option to build JARs, WARs, EARs and other artifacts), use Maven. If you want even more magic try Gradle. But I abandoned using Make for Java in the last millenium. Literally.

I'm pretty sure that the current directory is not in the java execution classpath. Or, actually even in the compiler classpath, although I think that source directories are, which would have the same effect if you compiled from the current directory.

In any event, to make the current directory be the classpath, use the following environment directive:

CLASSPATH=.

Or, if you prefer: "java -classpath=. Data" which you can abbreviate to simply "-cp".
 
Marshal
Posts: 5931
411
BSD
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Tim Holloway wrote:Or, if you prefer: "java -classpath=. Data" which you can abbreviate to simply "-cp".


Tim, I don't think it would go through.

In particular first one. I think (almost certain) it needs to be:
java -classpath . something

Meaning, without the = (equals) sign. Quotes aren't needed too, but I think you added these just to emphasize expression boundaries.

However, while I know -cp behaves same (read on various books) as -classpath, I don't know what is the actual story about them? Never found comprehensive explanation. Might be because "nearly half of a century back, there were created C, and..."?
 
Tim Holloway
Bartender
Posts: 19664
92
Android Eclipse IDE Linux
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This is what happens when you work with too many platforms. Some of them have command patterns that work one way, some have patterns that work another. I gave up long ago on trying to remember which was which, so I just type blind, hope, and if it doesn't work, retry with an alternate syntax (shrug).

The quotes were simply to indicate what the command line looked like without going to the effort of actually formatting a code block. They were not intended to be part of the command.

The jvm will take "-classpath" and "-cp" and interpret them identically. Like many command parsers, there's a long form and a short form, and the choice is yours. Long form is more self-documenting, short form is for when you've run out of patience for typing.

The equals sign came from the common Linux command option syntax which supports a very short form, a long form, and a truncated form (chop off as many letters from the tail of the long form as you can while remaining unambiguous). The Linux short form would be something like "-o value", the long form would be something like "--optionalvalue=value" - and note that there are TWO dashes there, and the equal sign would actually be optional. But that's not the command parser that Java uses internally, so I botched it. Oh well.
 
ras oscar
Ranch Hand
Posts: 40
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
is there a java system design reason why the compiler will look in the current directory but the run  application won't? I assume the "application deployment"  solution would be to combine all the required classes into a .jar file and run that. No?
 
Liutauras Vilda
Marshal
Posts: 5931
411
BSD
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

ras oscar wrote:is there a java system design reason why the compiler will look in the current directory but the run  application won't? I assume the "application deployment"  solution would be to combine all the required classes into a .jar file and run that. No?


Not sure I follow. Can you post [1] exact classes you have, [2] where they are,  and [3] in which directory you are when we talking. Then I'll write you how to compile and how to execute code.
Somehow lately I think that you confusing what the packages are and what the present working directory is, and perhaps what the classpath is.

Good that you trying to understand it though, it is really worthwhile time investment.
 
Tim Holloway
Bartender
Posts: 19664
92
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

ras oscar wrote:is there a java system design reason why the compiler will look in the current directory but the run  application won't? I assume the "application deployment"  solution would be to combine all the required classes into a .jar file and run that. No?



As I mentioned earlier, I'm pretty sure that it's not that the compiler will look in the current directory, but rather that it will look in the same director(ies) as the file(s) you are compiling.

The reason that the current directory isn't part of the classpath is the same as the reason that Unix-style OS's won't automatically look in the current directory for executable programs. Which is presumably to avoid possible conflicts or accidental executions by making you explicitly tell the system where the executable stuff is.
 
ras oscar
Ranch Hand
Posts: 40
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Liutauras Vilda wrote:

ras oscar wrote:is there a java system design reason why the compiler will look in the current directory but the run  application won't? I assume the "application deployment"  solution would be to combine all the required classes into a .jar file and run that. No?


Not sure I follow. Can you post [1] exact classes you have, [2] where they are,  and [3] in which directly you are when we talking. Then I'll write you how to compile and how to execute code.
Somehow lately I think that you confusing what the packages are and what the present working directory is, and perhaps what the classpath is.

Good that you trying to understand it though, it is really worthwhile time investment.



See post 14 in this thread. The only thing I have changed is to remove all the import statements from the top of the 2 files. The compiler runs without complaint and emits the 2 expected classes. The run program ( runner?) complains it can't find the data class. All files are located in the same directory, both .java and .class (And .bat, if it matters). The files are all located in c:\Java\Command Line\Data
 
Liutauras Vilda
Marshal
Posts: 5931
411
BSD
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

ras oscar wrote:See post 14 in this thread. The only thing I have changed is to remove all the import statements from the top of the 2 files. The compiler runs without complaint and emits the 2 expected classes. The run program ( runner?) complains it can't find the data class. All files are located in the same directory, both .java and .class (And .bat, if it matters). The files are all located in c:\Java\Command Line\Data


Then...

For compiling:
javac *.java

For executing:
java DataMain

Verified locally, works
 
ras oscar
Ranch Hand
Posts: 40
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
woo hoo. I feel like such an idiot. I was not running the file with the "main" function. Thanks.
 
ras oscar
Ranch Hand
Posts: 40
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Am I correct that if I wish to create a single runnable file out of my group of classes, I would compile each .java file into a class, then combine the classes in a .jar?
 
Knute Snortum
Sheriff
Posts: 5028
138
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Basically, yes, but creating a jar -- in particular a runnable jar -- is a little tricky.

If you use Eclipse you can use File -> Export, expand Java and select Runnable JAR File.  I'm sure IntelliJ has something similar. 
 
Tim Holloway
Bartender
Posts: 19664
92
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Actually, it's not that hard. But the jar has to be single-level. The Java classloader will not look for classes inside jars that are themselves inside jars. There's a way around that, but it requires some additional effort (for example a Maven build plugin).

To make a jar self-executing, you have to include a /META-INF/MANIFEST.MF file with a Main-Class directive in it like so:


If you do that you can run the application with this simple command:
 
ras oscar
Ranch Hand
Posts: 40
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
For anyone that is following this thread looking for answers to questions similar to mine, below are the 4 final functioning files:


Data.java:



DataMain.java:



MainCompile.bat



MainRun.bat




To use: copy the text of the 4 files to a reasonable directory. Edit the 2 .bat files to show the correct subdirectory. Run "MainCompile.bat", then "MainRun.bat"

Thanks for all your help, and for putting up with my silly questions. Hope this helps somebody else out there.
 
Consider Paul's rocket mass heater.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!