Java Forum / First Aid / August 2005
Im getting frustrated and angry!
pete_abel@hotmail.com - 22 Jun 2005 03:02 GMT hello everyone,
Ive been using C/C++/VC++ for a long time. And recently I attempted to check java out, web-programming in specifc, well so far, it was NOT a good experience.
What Im trying to do is very simple and straighforward, an applet and a servlet. The applet sends a simple serialized object, and the servlet replies(Acknowledges) with a string. and to have the connection available for many other transfers until the session is over.
Ive looked all over the internet, and all I found was pathetic! Only code snippets here and there, nothing complete. I really dont know why didnt anybody write a FULLY working example that does a STRAIGHTFORWARD communication.
I would really appreciate it if any of you can give me a SIMPLE, working example of what Im trying to do.
Thanks guys.
Regards, Pete
p.s. Im using "MyJavaServer" for development, and I think tomcat is installed on it, isnt it?
HansF - 22 Jun 2005 03:14 GMT > Ive been using C/C++/VC++ for a long time. And recently I attempted to > check java out, web-programming in specifc, well so far, it was NOT a > good experience. How many of the Java Tutorials at http://java.sun.com have you worked? How about the Code Camps from the same site?
Or the stuff from the JavaRanch.com? Oracle's complete examples at their TechNet site (albeit database oriented)? IBM's samples at http://www.developer.ibm.com/isv/tech/sampjava.html? Tutorials and samples at http://javaboutique.internet.com/javasource/?
You might have some luck with the O'Reilly Nutshell books - 'Java in a Nutshell' and 'Java Examples in a Nutshell' (java.oreilly.com)
 Signature Hans
pete_abel@hotmail.com - 22 Jun 2005 03:51 GMT Thanks for ur reply.
Ive Googled for the following keywords: applet <send> serialized object servlet. And for 2 days now, Ive been thru 30 or 40 of those links. The links covered java.sun.com, JavaRanch and javaboutique... And Im not sure at this point if I want to buy books when, supposedly, Java has a very wide base of online community support.
Best regards, Pete
HansF - 22 Jun 2005 04:07 GMT > sure at this point if I want to buy books when, supposedly, Java has a > very wide base of online community support. Books have a slight advantage - you can take 'em to bed with you. <g>
The two I mentioned are in my reference library and are well worn, in spite of my fairly reasonable Google skills.
Never the less - I get the feeling you have not had a serious look at the tutorials. Sure, you can skip the basic language stuff (but there is enough to open the eyes of someone with your skills - 'gotcha' differences with C++), but you really gotta get aquainted with the API libraries which is where your question is answered. The tutorials take you there in quick order.
Aside from that, I think the requirement of 'serializable' in your search is causing some serious side-tracking. Consider simplifying to "applet servlet communication"
 Signature Hans Forbrich
HansF - 22 Jun 2005 04:16 GMT > Aside from that, I think the requirement of 'serializable' in your > search is causing some serious side-tracking. Consider simplifying to > "applet servlet communication" Also, I seriously question whether there is much call for applets these days. I find that pure HTML front end with JSP/Servlet middle tier is becoming quite the rage, and applets are nowhere to be found - in the communities I see.
Finally - I really think you want to be looking at the RMI libraries to answer your serialization issues.
And soon - welcome to full-blown J2EE and http://theserverside.com (and a strong recommendation to read O'Reilly "Better, Faster, Lighter Java")
 Signature Hans Forbrich
pete_abel@hotmail.com - 22 Jun 2005 04:21 GMT OK. Following is a listing of the servlet code that, despite its simplicity, is not working(i.e. is not creating the file myobject.data on the server). Comments are appreciated.
/* * Servlet */
import java.awt.*; import java.awt.event.*; import java.net.*; import java.io.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*;
public class receiver extends HttpServlet { ObjectInputStream inputFromClient; Foo theData = null;
public void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { try { inputFromClient = new ObjectInputStream(req.getInputStream()); theData = (Foo) inputFromClient.readObject(); } catch (ClassNotFoundException cnfE) { cnfE.printStackTrace(); }
//************************************************************* // Write to disk with FileOutputStream FileOutputStream fout = new FileOutputStream("myobject.data");
// Write object with ObjectOutputStream ObjectOutputStream s = new ObjectOutputStream (fout);
// Write object out to disk s.writeObject ( theData ); s.flush(); //************************************************************* inputFromClient.close(); } // end doPost }
Alan Krueger - 22 Jun 2005 05:10 GMT > OK. Following is a listing of the servlet code that, despite its > simplicity, is not working(i.e. is not creating the file myobject.data > on the server). Comments are appreciated. [...]
> public class receiver extends HttpServlet Just a nitpick, class names in Java are by convention Capitalized.
> { > ObjectInputStream inputFromClient; > Foo theData = null; Why are these out here and not in the doPost method? One instance of the servlet object may be used to service multiple threads, and putting these here is definitely not thread-safe.
> public void doPost (HttpServletRequest req, HttpServletResponse > resp) throws ServletException, IOException [quoted text clipped - 19 lines] > s.writeObject ( theData ); > s.flush(); Is an IOException being thrown by any of the above? Where do you expect the myobject.data file to be placed? You might be trying to write it to an inappropriate spot. Try using fully-specified path to a definitely-writeable directory.
> //************************************************************* > inputFromClient.close(); > } // end doPost > } pete_abel@hotmail.com - 22 Jun 2005 17:55 GMT Im going to rephrase my questions.
QUESTIONS:
Q1) Is there something in this code thats causing the problem of not creating the file "myobject.data" by the servlet? Q2) What are the ways to see whether the servlet has actually received the serialized object or not? Q3) What path should be stored in ServletPath: the directory of the servlet or the the name of the servlet added to that path?
COMMENTS:
C1) When executing the code, no exceptions are caught, and the servlet doesnt create the file. C2) As far as the notation is concerned, I reserve that for C++/VC++ (where class names start with a 'C' e.g. "CMyClass", and methd names are capitalized e.g. "SendData()", and member variables start with "m_" e.g. "m_nIterations". In java, I really dont care ;)
CODE:
/******************************** * Applet */ import java.applet.Applet; import java.awt.Graphics; import java.io.*; import java.awt.*; import javax.swing.*; import java.net.*;
public class sender extends Applet { String m_MyOutputString; Foo MyFoo; URL url = null; URLConnection conn = null; ObjectOutputStream toServlet; String ServletPath = "http://myjavaserver.com/~shaiian/receiver";
public void init() { try { url=new URL(ServletPath); conn=url.openConnection(); conn.setDoInput(true); conn.setDoOutput(true); conn.setUseCaches(false); conn.setDefaultUseCaches(false);
conn.setRequestProperty("Content-Type","application/octet-stream"); toServlet=new ObjectOutputStream(conn.getOutputStream()); }
catch (IOException ioe) { JOptionPane.showMessageDialog(null,"IOException caught"); }
MyFoo=new Foo(); }
public void SendData() { try { toServlet.writeObject(MyFoo); }
catch (SecurityException e) { JOptionPane.showMessageDialog(null,"Caught a security exception\n\n" + e.getMessage()); }
catch (IOException ioe) { JOptionPane.showMessageDialog(null,"IOException caught"); } }
public void destroy() { try { toServlet.flush(); toServlet.close(); }
catch (IOException ioe) { JOptionPane.showMessageDialog(null,"IOException caught"); } } }
/************************** * Servlet */
import java.awt.*; import java.awt.event.*; import java.net.*; import java.io.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*;
public class receiver extends HttpServlet { ObjectInputStream inputFromClient; Foo theData = null;
public void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { try { inputFromClient = new ObjectInputStream(req.getInputStream()); theData = (Foo) inputFromClient.readObject(); } catch (ClassNotFoundException cnfE) { cnfE.printStackTrace(); }
//************************************************************* // Write to disk with FileOutputStream FileOutputStream fout = new FileOutputStream("myobject.data");
// Write object with ObjectOutputStream ObjectOutputStream s = new ObjectOutputStream (fout);
// Write object out to disk s.writeObject ( theData ); s.flush(); //************************************************************* inputFromClient.close(); } // end doPost }
Alan Krueger - 22 Jun 2005 23:08 GMT > QUESTIONS: > > Q1) Is there something in this code thats causing the problem of not > creating the file "myobject.data" by the servlet? Where were you looking for that file? Did you look anywhere else? You've specified a relative pathname to the FileOutputStream. Do you know for *certain* where that will go? Is that directory writeable by the servlet engine? Try using a full path to a file in a temp directory or something.
> Q2) What are the ways to see whether the servlet has actually received > the serialized object or not? Using a debugger, trace output, dumping to file, etc.
> Q3) What path should be stored in ServletPath: the directory of the > servlet or the the name of the servlet added to that path? Depends on how your servlet is configured to be invoked. I think you should probably work through some tutorials on servlets.
> COMMENTS: > > C1) When executing the code, no exceptions are caught, and the servlet > doesnt create the file. Do you know for certain that the servlet is even being invoked? What's calling the SendData method on your applet? You've expressed a lack of confidence that you've got the right URL for your applet, so you should make sure of that, too.
pete_abel@hotmail.com - 22 Jun 2005 20:07 GMT Let me rephrase my questions.
QUESTIONS:
Q1) After looking at the code at the end of this post, is there a problem with it thats causing the servlet not to create the file "myobject.dat"? Q2) What are the possible ways to check if a servlet has received a serialized object? Q3) Which path should be stored in "ServletPath": the path of the directory containing the servlet or the path of the servlet itself?
COMMENTS:
C1) The code runs with no exceptions. The only problem is that the file "myobject.data" is not created by the servlet C2) I thought that if an absolute path was not given for the output file, the file will be created in the directory of the servlet, hmmm. C3) As far as the notation of class names is concerned, class names start with 'C' (e.g. "CMyClass"), method names, capitalized (e.g. "SendData()"), member-variable names start with "m_" (e.g. "m_nInterations"). Thats in C++/VC++. In Java, I really dont care ;)
Regards, Pete
CODE:
/******************************************** * The Applet */
import java.applet.Applet; import java.awt.Graphics; import java.io.*; import java.awt.*; import javax.swing.*; import java.net.*;
public class sender extends Applet { Foo MyFoo; URL url = null; URLConnection conn = null; ObjectOutputStream toServlet; String ServletPath = "http://myjavaserver.com/~shaiian/receiver";
public void init() { try { url=new URL(ServletPath); conn=url.openConnection(); conn.setDoInput(true); conn.setDoOutput(true); conn.setUseCaches(false); conn.setDefaultUseCaches(false); conn.setRequestProperty("Content-Type","application/octet-stream"); toServlet=new ObjectOutputStream(conn.getOutputStream()); }
catch (IOException ioe) { JOptionPane.showMessageDialog(null,"IOException caught..."); }
MyFoo=new Foo(); }
public void SendData() { try { // assuming that MyFoo member variables have been set toServlet.writeObject(MyFoo);
} catch (SecurityException e) { JOptionPane.showMessageDialog(null,"Caught a security exception\n\n" + e.getMessage()); }
catch (IOException ioe) { JOptionPane.showMessageDialog(null,"IOException caught..."); } }
public void destroy() { try { toServlet.flush(); toServlet.close(); }
catch (IOException ioe) { JOptionPane.showMessageDialog(null,"IOException caught..."); } } }
/******************************************** * The Servlet */
import java.awt.*; import java.awt.event.*; import java.net.*; import java.io.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*;
public class receiver extends HttpServlet { ObjectInputStream inputFromClient; Foo theData = null;
public void init() { inputFromClient = new ObjectInputStream(req.getInputStream()); }
public void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { try { theData = (Foo) inputFromClient.readObject(); } catch (ClassNotFoundException cnfE) { cnfE.printStackTrace(); }
//************************************************************* // Write to disk with FileOutputStream FileOutputStream fout = new FileOutputStream("myobject.data");
// Write object with ObjectOutputStream ObjectOutputStream s = new ObjectOutputStream (fout);
// Write object out to disk s.writeObject ( theData ); s.flush(); //************************************************************* inputFromClient.close(); } // end doPost }
hiwa - 23 Jun 2005 07:27 GMT >Let me rephrase my questions. > Hi Pete, I could write an example code for you but I didn't have enough time to do so. My example code would be based on the description from:
http://pdf.coreservlets.com/
This is the free download of Marty Hall's Core Servlets and JavaServer Pages , first edition.
For your applet-servlet communications issue, read chapter 17 of the book. Especially for sending serialized object from applet to server, the description from 17.5 and 17.6 will help.
And beware that the exact URL of the servlet depends on your web.xml file entries.
Hope this helps. Good luck.
Patricia Shanahan - 22 Jun 2005 15:06 GMT > Thanks for ur reply. > [quoted text clipped - 6 lines] > Best regards, > Pete I think you would do better by splitting the job into three pieces, applet writing, servlet writing, and serialization. Learn to do each of those first, and then combine them.
There are many options for how each of those concepts can be used, so you are very unlikely to find any example that does exactly the combination you want. You should be able to find good examples of each of them done separately.
I think you are making a big mistake in ignoring books. Community support and books are not substitutes for each other. They are much more powerful used in combination. Use books for big building blocks of knowledge. Use community support when you need individual help.
Is Java your second programming language, counting C/C++ as one language? If so, expect to find it difficult and frustrating. I try to encourage new programmers to learn another language or so as early as possible, rather than working for years in one language before learning another. The first language mindset can become entangled into one's general programming skills.
Patricia
Thomas G. Marshall - 22 Jun 2005 23:46 GMT Patricia Shanahan coughed up:
>> Thanks for ur reply. >> [quoted text clipped - 27 lines] > learning another. The first language mindset can become entangled > into one's general programming skills. I think that is very true. There are many who believe, for instance, that a language must have curly braces. Or that there need to be static types.
 Signature Unix users who vehemently argue that the "ln" command has its arguments reversed do not understand much about the design of the utilities. "ln arg1 arg2" sets the arguments in the same order as "mv arg1 arg2". Existing file argument to non-existing argument. And in fact, mv itself is implemented as a link followed by an unlink.
Onkell Wang - 24 Jun 2005 09:08 GMT Would you please recommend a second programming language?
Onkell
>> Thanks for ur reply. >> [quoted text clipped - 29 lines] > > Patricia Patricia Shanahan - 24 Jun 2005 12:05 GMT > Would you please recommend a second programming language? Almost anything that embodies different assumptions from your first language. Forth is interesting, and properly mind-stretching for someone whose first language is Java. Assembly languages are good for learning about what goes on under the hood.
Of course, if you have some reason to expect to need a particular language in the future, that is the one to learn next.
>>Is Java your second programming language, counting C/C++ as one >>language? If so, expect to find it difficult and frustrating. I try to [quoted text clipped - 4 lines] >> >>Patricia Thomas G. Marshall - 07 Aug 2005 04:23 GMT Patricia Shanahan coughed up:
>>> Is Java your second programming language, counting C/C++ as one >>> language? If so, expect to find it difficult and frustrating. I try [quoted text clipped - 9 lines] > Almost anything that embodies different assumptions from your first > language. If the goal is to be exposed to different things, then prolog is one of the weirder, yet useful, ones. It is a blurring of what-is-data and what-is-code, since it is entirely a set of relationships. Like an executable BNF of sorts. Is it data or code?
But I suspect your (Patricia's) latter (snipped) comment is the most appropos. (OP), go with what you are likely to need in the future.
...[rip]...
 Signature If I can ever figure out how, I hope that someday I'll succeed in my lifetime goal of creating a signature that ends with the word "blarphoogy".
Stefan Schulz - 07 Aug 2005 09:59 GMT > If the goal is to be exposed to different things, then prolog is one of the > weirder, yet useful, ones. It is a blurring of what-is-data and > what-is-code, since it is entirely a set of relationships. Like an > executable BNF of sorts. Is it data or code? Speaking of it, if you think you understood prolog and imperative coding, take a look at Haskell, and find your assumptions challenged again. Beautiful language, but if you try to think about flow of execution (as is easy to do even in Prolog), you won't get far.
 Signature You can't run away forever, But there's nothing wrong with getting a good head start. --- Jim Steinman, "Rock and Roll Dreams Come Through"
Thomas G. Marshall - 07 Aug 2005 14:41 GMT Stefan Schulz coughed up:
>> If the goal is to be exposed to different things, then prolog is one >> of the weirder, yet useful, ones. It is a blurring of what-is-data [quoted text clipped - 5 lines] > again. Beautiful language, but if you try to think about flow of > execution (as is easy to do even in Prolog), you won't get far. Perhaps the very first introduction to absurd-flow of execution are makefiles. They are god-awfully tough for the newbie to figure out. Even very seasoned programmers end up going "huh" once in a while. GnuMake made things much more sane with a few very select changes that made the world better, but it still a fairly strong hammer to the top to bottom intuitions.
 Signature Framsticks. 3D Artificial Life evolution. You can see the creatures that evolve and how they interact, hunt, swim, etc. (Unaffiliated with me). http://www.frams.alife.pl/
Dale King - 10 Aug 2005 06:01 GMT > Perhaps the very first introduction to absurd-flow of execution are > makefiles. They are god-awfully tough for the newbie to figure out. Even > very seasoned programmers end up going "huh" once in a while. GnuMake made > things much more sane with a few very select changes that made the world > better, but it still a fairly strong hammer to the top to bottom intuitions. I'll second that. I've spent many, many hours over the past week refinig the makefiles for a C/C++ project being sure that my make is non-recursive (see Recursive make considered harmful), and that it works when run using the -j option to build in parallel, and dealing with bugs in gnu make (that have not been fixed in a release of gnu make even though it was fixed 3 years ago). I ended up using many of the advanced options of gnu make (target and pattern specific variables, order only prerequisites, etc.)
 Signature Dale King
Kenneth P. Turvey - 10 Aug 2005 07:16 GMT > I'll second that. Third! What was with the invisible tab character being all important in the syntax of the language. It was a bad design.
Although I've used ant I haven't really gotten down to the nitty gritty of it. The tool, Netbeans, mostly hides ant from me.
 Signature Kenneth P. Turvey <kt@squeakydolphin.com>
blmblm@myrealbox.com - 11 Aug 2005 01:58 GMT >> I'll second that. > >Third! What was with the invisible tab character being all important in the >syntax of the language. It was a bad design. Even the inventor may think so. A while back I came across the following, said to be a paraphrase from an article by Brian Kernighan on the origins of Unix:
The tab in makefile was one of my worst decisions, but I just wanted to do something quickly. By the time I wanted to change it, twelve (12) people were already using it, and I didn't want to disrupt so many people.
"FWIW", maybe.
[ snip ]
| B. L. Massingill | ObDisclaimer: I don't speak for my employers; they return the favor.  Signature -- blm
Thomas G. Marshall - 11 Aug 2005 02:41 GMT blmblm@myrealbox.com coughed up:
>>> I'll second that. >> [quoted text clipped - 9 lines] > to change it, twelve (12) people were already using it, > and I didn't want to disrupt so many people. LOL. TWELVE PEOPLE!
Oh man. Good thing he didn't make the thing more sensible---he could have ruined the productivity of a dozen people for maybe 10 minutes.
 Signature Sometimes life just sucks and then you live.
Dale King - 12 Aug 2005 03:19 GMT >>I'll second that. > > Third! What was with the invisible tab character being all important in the > syntax of the language. It was a bad design. While it is a bit of nuisance, in practice it isn't that big of a deal. Make will usually tell you.
> Although I've used ant I haven't really gotten down to the nitty gritty of > it. The tool, Netbeans, mostly hides ant from me. There is very little realationship between make and Ant in my opinion. Ant is much closer to batch files than make. Make is all about dependencies between files and making sure things get built built in the right order and that no more than is necessary is rebuilt. Ant has almost none of that. A good makefile should always guarantee a good build (as long as you abide by the assumption of make that files only get newer and can never get older). It is trivial to have Ant tell you everything is built when it doesn't build all that it needs to.
Unfortunately, Java is a different environment than older language. Make doesn't work well with Java because Java can have circular dependencies which require compiling more than one file at a time and compiling a single file can produce many files.
There is no good command line build system for Java.
 Signature Dale King
Thomas G. Marshall - 10 Aug 2005 14:56 GMT Dale King coughed up:
>> Perhaps the very first introduction to absurd-flow of execution are >> makefiles. They are god-awfully tough for the newbie to figure out. [quoted text clipped - 11 lines] > the advanced options of gnu make (target and pattern specific > variables, order only prerequisites, etc.) I often thought that perhaps make was a good /very/ simple idea that grew an inch at a time into an unwieldy multi-ton high inertia rolling pile of steaming crap. (You've just rekindled some very bitter memories with your story.) I'm sure there has been more than a few engineers out there who have punted and "rolled their own" builder out of some shell script.
<idle thought> I wonder if a make->csh converter (or make->perl, etc.) would produce anything more intuitive? </idle>
 Signature "It's easier to be terrified by an enemy you admire." -Thufir Hawat, Mentat and Master of Assassins to House Atreides
Tor Iver Wilhelmsen - 10 Aug 2005 15:27 GMT > I'll second that. I've spent many, many hours over the past week > refinig the makefiles for a C/C++ project being sure that my make is > non-recursive May I suggest installing Ant and use that for the C compilation? Ant is "make" done right.
Dale King - 12 Aug 2005 03:25 GMT >>I'll second that. I've spent many, many hours over the past week >>refinig the makefiles for a C/C++ project being sure that my make is >>non-recursive > > May I suggest installing Ant and use that for the C compilation? Ant > is "make" done right. Hardly! Ant is a glorified batch file. It's a very nice batch file but is nothing like make. It's OK for distributing a project where someone is just going to build your stuff from scratch. For day to day development I sure wouldn't trust Ant.
Unfortunately, there's not really an ideal solution for command line builds of Java. There's JavaMake which is pretty good, but I don't think works with 1.5.
 Signature Dale King
Tor Iver Wilhelmsen - 12 Aug 2005 15:16 GMT > Hardly! Ant is a glorified batch file. Nonsense, and actually using Ant, with filesets, depends and everything would tell you this.
Though using the bare minimum tasks instead of all the possibilities can lead you to such a conclusion.
Dale King - 13 Aug 2005 14:43 GMT >>Hardly! Ant is a glorified batch file. > [quoted text clipped - 3 lines] > Though using the bare minimum tasks instead of all the possibilities > can lead you to such a conclusion. No the conclusion is still valid.
Depends does not work in all cases. I think you meant dependset not fileset, but all it does is delete files.
It's nice that Ant got rid of using tabs, that it created standardized cross-platform actions so you don't have to rely on going out to the shell to perform most actions, and that it is easily extendible with your own cross-platform actions. But they threw away the basic expression of how files depend on each other. They bolted on some hit-and-miss ad-hoc dependency checks. Some of the tasks will check if they need to be rebuilt, others do not.
The fundamental abstraction of Ant are actions to perform (just like a batch file). The fundamental absraction of make are the dependency relationships among the actual artifacts.
Of course I am not saying that everyone should switch to make for building Java. Make doesn't work for Java. Java is a difficult build problem.
But Ant definitely does not deserve being called "make" done right. It's a nice form of cross platform batch file. You can build using batch files and in fact the one time I need command line building the solution was to use a batch file and build clean every time.
The best build advice right now is to use an IDE like Eclipse, but that really only addresses the Java compilation.
 Signature Dale King
Thomas G. Marshall - 13 Aug 2005 18:17 GMT Dale King coughed up:
>>> Hardly! Ant is a glorified batch file. >> [quoted text clipped - 20 lines] > batch file). The fundamental absraction of make are the dependency > relationships among the actual artifacts. Which is *precisely* the problem. That relationship does not lend itself to intuitive control flow. Make and top-down execution are strangers to each other. Add to that variable passing, and you have a huge mess.
The fact that you refer to ant as a glorified batch file is to me one of the greatest compliments you can give it.
...[rip]...
 Signature http://www.allexperts.com is a nifty way to get an answer to just about /anything/.
Dale King - 15 Aug 2005 02:40 GMT > Dale King coughed up: > [quoted text clipped - 26 lines] > intuitive control flow. Make and top-down execution are strangers to each > other. Add to that variable passing, and you have a huge mess. That's because the problem of knowing what to build and the order to build it does not lend itself to "control flow".
> The fact that you refer to ant as a glorified batch file is to me one of the > greatest compliments you can give it. As long as you're happy with a build system that will build things that don't need to be rebuilt and will sometimes not rebuild things that need to be built then more power to you. Just don't try to fool people into thinking that Ant is "make done right".
In my opinion if your build system requires you to sometimes do a "make clean" in order to get a correct build then your build system is broken. The only way to guarantee a correct build with Ant (and batch files) is to always rebuild everything.
 Signature Dale King
Tor Iver Wilhelmsen - 14 Aug 2005 08:28 GMT > But they threw away the basic expression of how files depend on each > other. That's because such dependencies (I assume you mean the file extension mappings like .c to .o) aren't necessarily the same for all source files in more complex projects, where make requires multiple makefiles to use different compiler flags etc.
So the expression is not basic.
> They bolted on some hit-and-miss ad-hoc dependency checks. They leave dependency checking to the particular task; e.g. the docs for the javac task says: "Only Java files that have no corresponding .class file or where the class file is older than the .java file will be compiled."
> Some of the tasks will check if they need to be rebuilt, others do > not. Exactly; so it's a choice the task writer makes. Make needs to check dependencies because the C compiler doesn't. And which tasks other than javac do you feel would need to check a dependency?
> The fundamental abstraction of Ant are actions to perform (just like a > batch file). Not just like a batch file, since a batch file consists of invocation of multiple independent programs that take varying options, parameters etc.
Ant has a framework that unifies how you deal with paths, filesets, directories and other elements.
> The fundamental absraction of make are the dependency relationships > among the actual artifacts. You are focusing on the one feature make has that Ant lacks, but it's not as useful (for Java development) as you believe it is, and looks more like a workaround for a deficiency in the C compiler. Yes, an author of a C-compiler task would need to add code to check dependencies. But Ant has several advantages that more than make up for the lack of this automated dependency checking.
> Of course I am not saying that everyone should switch to make for > building Java. Make doesn't work for Java. Java is a difficult build > problem. No, it's not: It just adds the package-to-path dependency that C++/C# etc. avoids.
Make is unsuited to Java because Make is there to add "smartness" to dumb old compilers (including the use of makedepend/mkdep to find preprocessor dependencies), and otherwise act as a "glorified batch file". Make is for people who thought #ifdef __SYSV__ is a good idea.
Ant however is there to provide a framework for cross-platform development with smart compilers.
> But Ant definitely does not deserve being called "make" done right. > It's a nice form of cross platform batch file. Not any more than make is. Unless you only use "exec"-type tasks to run command-line programs.
Thomas G. Marshall - 15 Aug 2005 01:34 GMT Tor Iver Wilhelmsen coughed up:
>> But they threw away the basic expression of how files depend on each >> other. [quoted text clipped - 19 lines] > dependencies because the C compiler doesn't. And which tasks other > than javac do you feel would need to check a dependency? Javac isn't perfect either (think public static final id's), but your assessment is correct.
>> The fundamental abstraction of Ant are actions to perform (just like >> a batch file). [quoted text clipped - 11 lines] > You are focusing on the one feature make has that Ant lacks, but it's > not as useful (for Java development) as you believe it is, Dale doesn't seem particularly thrilled with make for java either. I understand that position. Lacking all else, I've used make in the distant past, but they are /very/ small makefiles, and I absolutely loathe having to maintain makefiles that have been written by others willing to develop multi-page monstrosities.
I go further though, in that I firmly believe that most engineers believe that there is an intrinsic value to make that is not entirely summed up in speed-to-compile. That is, I think that most miss the point (or outright disagree for some reason) that if compilation time was 0 seconds, make would never have existed at all, and everyone would be compiling everything, top to bottom, every time.
Make has /no/ value other than this. I've been told emphatically by an engineer before "you're wrong, it gives you a way to organize your sources." It does not. Such organization that you might perceive is only there to save compilation time.
Compilation time is still an issue these days however, I'm not denying this. But computing speed has IMO fairly well outraced the increased number of source modules. I remember back when things were rotten how long it might take to compile an application of merely 70 C modules. {author shudders}.
> and looks > more like a workaround for a deficiency in the C compiler. Yes, an [quoted text clipped - 22 lines] > Not any more than make is. Unless you only use "exec"-type tasks to > run command-line programs.
 Signature If I can ever figure out how, I hope that someday I'll succeed in my lifetime goal of creating a signature that ends with the word "blarphoogy".
Dale King - 15 Aug 2005 14:34 GMT > Tor Iver Wilhelmsen coughed up: > [quoted text clipped - 16 lines] > Dale doesn't seem particularly thrilled with make for java either. I > understand that position. As I've said the model of Java compilation is incompatible with make's model. But that doesn't mean I am willing to accept another build system that discards the correctness and efficiency that make provides.
> Lacking all else, I've used make in the distant > past, but they are /very/ small makefiles, and I absolutely loathe having to > maintain makefiles that have been written by others willing to develop > multi-page monstrosities. The make system I developed was for a very large system with 20 developers and hundreds of object files. The makefiles are not that large. They are only difficult to understand due to make's cryptic syntax and workarounds for bugs in gnu make. I won't deny make has huge warts.
> I go further though, in that I firmly believe that most engineers believe > that there is an intrinsic value to make that is not entirely summed up in > speed-to-compile. That is, I think that most miss the point (or outright > disagree for some reason) that if compilation time was 0 seconds, make would > never have existed at all, and everyone would be compiling everything, top > to bottom, every time. I agree with you there. The necessary characteristics of a build system are correctness and efficiency. Any system that achieves that is acceptable. If building from scratch were efficient (it already guarantees correctness) then that would be the way to go. And it would not have to be zero. As long as it is fast enough that I don't divert my attention elsewhere that is good enough.
In fact the one time I cared about building from the command line for Java (when I originally looked at Ant due to the hype about it being make done right) I eventually settled on using batch files and building from scratch. This was for delivering demos to a partner. Day to day development was in Visual Age for Java.
> Make has /no/ value other than this. I've been told emphatically by an > engineer before "you're wrong, it gives you a way to organize your sources." > It does not. Such organization that you might perceive is only there to > save compilation time. I'll agree with you. But remember that make is for efficient *AND* correct builds.
> Compilation time is still an issue these days however, I'm not denying this. > But computing speed has IMO fairly well outraced the increased number of > source modules. I remember back when things were rotten how long it might > take to compile an application of merely 70 C modules. {author shudders}. And the C/C++ application where you told me to use Ant takes 7-8 minutes to build from scratch.
And you seem to ignore the correctness aspect of the build system. Computing speed has little benefit if it quickly generates a bad build.
Once again Ant guarantees neither correctness nor efficiency.
 Signature Dale King
Thomas G. Marshall - 15 Aug 2005 17:27 GMT Dale King coughed up:
...[rip]...
>> Compilation time is still an issue these days however, I'm not >> denying this. But computing speed has IMO fairly well outraced the [quoted text clipped - 4 lines] > And the C/C++ application where you told me to use Ant takes 7-8 > minutes to build from scratch. I did not tell you to use anything. Nor, fwiw, did I ever say that ant was "make done right".
Are you confusing me with someone else here?
> And you seem to ignore the correctness aspect of the build system. No.
The "correctness" that you refer to is what I consider to be something that goes without saying. If it is not correct enough to use, then it's not part of this conversation. make and (I assume) ant are correct enough to use, so it's not sensible to add another variable-axis of complexity to our discussion. I can vouche for make to be correct enough---I've used it. I just hate the thing, for the reasons already described.
Actually, I don't even have, nor have I claimed to have, any real experience with ant. My entire contribution concerning ant here was to point out that if you called ant a glorified batch file, that it was an appealing attribute, not a condemning one. For example, I often speculate just how many times make has been abandoned for some scripting language concoction.
...[rip]...
 Signature "Well, ain't this place a geographical oddity! Two weeks from everywhere!"
Dale King - 16 Aug 2005 12:57 GMT > Dale King coughed up: > [quoted text clipped - 13 lines] > > Are you confusing me with someone else here? Oops, sorry that was Tor. Got the T's confused.
>>And you seem to ignore the correctness aspect of the build system. > [quoted text clipped - 6 lines] > discussion. I can vouche for make to be correct enough---I've used it. I > just hate the thing, for the reasons already described. Then you assume incorrectly. For something like C with a well-written makefile correctness is guaranteed (if you abide by the rule that files can only get newer).
For ant that correctness is not guaranteed at all. That comes about by making the dependency checking ad-hoc.
For Java compilation in Ant specifically the javac task only gives you the correctness of javac which is not good enough. They added a depends task to try to make up for the lack of dependency checking, but it has limitations and will fail to rebuild dependencies on constants. There is the JavaMake program that has an ant task which does guarantee correctness, but at a sacrifice of efficiency.
> Actually, I don't even have, nor have I claimed to have, any real experience > with ant. And the problem is there is a lot of hype with Ant that isn't true. People here that Ant is a better make and believe it.
> My entire contribution concerning ant here was to point out that > if you called ant a glorified batch file, that it was an appealing > attribute, not a condemning one. For example, I often speculate just how > many times make has been abandoned for some scripting language concoction. It would not be appealing to anyone that has actually used a batch file for day-to-day building.
 Signature Dale King
Thomas G. Marshall - 16 Aug 2005 15:07 GMT Dale King coughed up:
>> Dale King coughed up: >> [quoted text clipped - 34 lines] > For ant that correctness is not guaranteed at all. That comes about by > making the dependency checking ad-hoc. You said "well-written makefile". Does not ant require something "well-written" as well? If make is not "well-written", it does not guarantee anything either.
> For Java compilation in Ant specifically the javac task only gives you > the correctness of javac which is not good enough. They added a > depends task to try to make up for the lack of dependency checking, > but it has limitations and will fail to rebuild dependencies on > constants. There is the JavaMake program that has an ant task which > does guarantee correctness, but at a sacrifice of efficiency. I'll be glad to take your word for it here. That sacrifice for efficiency can't possibly be all that much, or can it?
>> Actually, I don't even have, nor have I claimed to have, any real >> experience with ant. [quoted text clipped - 10 lines] > It would not be appealing to anyone that has actually used a batch > file for day-to-day building. That's a stretched assumption. I had a home grown set of csh scripts that I used for over 5 1/2 years, and loved it. I had used make prior, and have since, but I miss my concoction.
kevindotcar@gmail.com - 17 Aug 2005 19:15 GMT [---]
> That's a stretched assumption. I had a home grown set of csh scripts that I > used for over 5 1/2 years, and loved it. I had used make prior, and have > since, but I miss my concoction. Sorry, but one question I just have to ask;
Do you miss it because it's frozen?
kDot
Andrew Thompson - 17 Aug 2005 19:27 GMT > Sorry, but one question I just have to ask; Please ask it on c.l.j.advocacy, where this matter seems to have originated. <http://groups.google.com/group/talk.bizarre/msg/64bffd268aa7896e>
Oh, and stop setting the headers on posts to c.l.j.help, as cross-posts to other groups. Newsgroups reset to c.l.j.help only.
Do your trolling elsewhere.
 Signature Andrew Thompson physci.org 1point1c.org javasaver.com lensescapes.com athompson.info "I know what I want but I just don't know ..how to go about gettin' it." Jimi Hendrix 'Manic Depression'
Andrew Thompson - 17 Aug 2005 19:37 GMT >> Sorry, but one question I just have to ask; > > Please ask it on c.l.j.advocacy, where this matter > seems to have originated. > <http://groups.google.com/group/talk.bizarre/msg/64bffd268aa7896e> Got it now. Having not contributed to the thread I observed on c.l.j.advocacy, I had not noticed you (or someone) were x-posting/trolling there as well..
(shrugs) The posters to c.l.j.a. are big enough and ugly enough to look after themselves, but keep this crap off c.l.j.help.
 Signature Andrew Thompson physci.org 1point1c.org javasaver.com lensescapes.com athompson.info "The rich getting richer, the poor get the picture." Midnight Oil 'Read About It'
Dale King - 18 Aug 2005 12:50 GMT > Dale King coughed up: > [quoted text clipped - 40 lines] > "well-written" as well? If make is not "well-written", it does not > guarantee anything either. You and Tor have both mentioned this now and I fail to see the point. Yes you can write bad make files and bad Ant scripts that do not work correctly. You can write good make files that guarantee correctness and efficiency. However you *cannot* write Ant scripts that guarantee both.
If you are interested in a formal theory on the necessary conditions for a makefile to achieve this see:
http://ep.lib.cbs.dk/download/ISBN/x648032182.pdf
>>For Java compilation in Ant specifically the javac task only gives you >>the correctness of javac which is not good enough. They added a [quoted text clipped - 5 lines] > I'll be glad to take your word for it here. That sacrifice for efficiency > can't possibly be all that much, or can it? Well the sacrifice using JavaMake is first that if you change a public static final constant everything is rebuilt. That is the only way it guarantee correctness because it has no idea who might have used that constant. In the same situation with Ant using the depends task you just get a bad build.
It is also a little slower in general because it does a more thorough analysis of the classfiles. It parses them and saves information about them. On the next run if they change it actually figures out what changed and who depended on that. So on the good side if you change a comment it doesn't recompile other things, but on the bad side all that extra analysis slows things down.
I was going to point you to the web pages for JavaMake that talked about it, but it appears it may have been a victim of the worm.
That extra analysis is why it would be really nice to truly have a smart compiler that integrated the logic of JavaMake. The compiler already has all the information that JavaMake gets from analyzing the class files and more.
>>> My entire contribution concerning ant here was to point out that >>>if you called ant a glorified batch file, that it was an appealing [quoted text clipped - 8 lines] > used for over 5 1/2 years, and loved it. I had used make prior, and have > since, but I miss my concoction. I was thinking more of the inefficiency of the batch files recompiling things that don't need to be recompiled.
 Signature Dale King
hawat.thufir@gmail.com - 18 Aug 2005 19:38 GMT ...
> >>>The "correctness" that you refer to is what I consider to be > >>>something that goes without saying. If it is not correct enough to [quoted text clipped - 7 lines] > >>makefile correctness is guaranteed (if you abide by the rule that > >>files can only get newer). ...
> You and Tor have both mentioned this now and I fail to see the point. > Yes you can write bad make files and bad Ant scripts that do not work [quoted text clipped - 5 lines] > > http://ep.lib.cbs.dk/download/ISBN/x648032182.pdf ...
What's meant by correctness?
-Thufir
Dale King - 24 Aug 2005 14:15 GMT > .... > [quoted text clipped - 23 lines] > > What's meant by correctness? It's in the paper I linked to which calls it "safeness", but to summarize it basically means that if I change some files and invoke the builder then it must give you the same result as you would have gotten by building from scratch.
Ant using just the javac task definitely does not achieve that and it is trivial to produce a case that shows this as I have done in this thread.
Using the depends task will handle some more modifications but doesn't handle changes in static final constants.
Using the JavaMake task does achieve "correctness" at the expense of efficency. In cases like public static final constant being changed it punts and rebulds from scratch.
I saw in another thread that the Eclipse compiler can be run as a separate tool and has an Ant task. I need to investigate how it performs.
 Signature Dale King
Dale King - 15 Aug 2005 13:31 GMT >>But they threw away the basic expression of how files depend on each >>other. [quoted text clipped - 5 lines] > > So the expression is not basic. And such dependencies don't have to be the same for all source files. The project I am working on is a complex project. The make file system we have allow you to have different settings per directory. Each directory has a kind of makefile, but that makefile is nothing more than setting of variables. It is included into the master make file.
Perhaps you aren't aware of static pattern rules, target specific variables, and pattern specific variables.
>>They bolted on some hit-and-miss ad-hoc dependency checks. > > They leave dependency checking to the particular task; e.g. the docs > for the javac task says: "Only Java files that have no corresponding > ..class file or where the class file is older than the .java file will > be compiled." That is why I called it ad-hoc.
>>Some of the tasks will check if they need to be rebuilt, others do >>not. > > Exactly; so it's a choice the task writer makes. Make needs to check > dependencies because the C compiler doesn't. And which tasks other > than javac do you feel would need to check a dependency? Thus why it is hit-and-miss. One task might always do its task whether it needs to or not and another might decide that it doesn't need to yet it really did need to.
The correctness of building is not something to be left to the whim of those writing the tasks.
>>The fundamental abstraction of Ant are actions to perform (just like a >>batch file). > > Not just like a batch file, since a batch file consists of invocation > of multiple independent programs that take varying options, parameters > etc. And that differs from Ant in what way?
> Ant has a framework that unifies how you deal with paths, filesets, > directories and other elements. As I said it is a very nice batchfile.
>>The fundamental absraction of make are the dependency relationships >>among the actual artifacts. > > You are focusing on the one feature make has that Ant lacks, Because it is the most important feature for doing builds that are correct (builds everything that needs to be built) and efficient (don't build more than needs to be built). Ant achieves neither. A well written makefile for something like C does both.
> but it's > not as useful (for Java development) as you believe it is, I've been very clear that make does not work for Java. This particular subthread was started with Thomas suggesting I should use Ant for C compilation because "Ant is make done right". Ant is definitely not make done right!
> and looks > more like a workaround for a deficiency in the C compiler. Yes, an > author of a C-compiler task would need to add code to check > dependencies. No, the reason it works for C and not Java is not that C is deficient. It is that the two have different compilation models.
The dependencies in C always look like this:
foo.o ----> foo.c ----> header files
Java is not that simple. First one source file can produce more than one class file. Secondly, compilation does not depend on text header files, but on other class files. Thirdly, Java allows circular dependencies which can only be resolved by compiling the source files at the same time.
Those rules are incompatible with make's DAG.
The only truly correct way to do efficient and correct builds in Java is to get into the compiler. That is what Eclipse does for instance. They have their own compiler from which they extract the necessary dependencies.
There are class-file analysis tools that try to figure out the dependencies from the class files. The problem is that some dependencies are not expressed in the class file (e.g. dependencies only on a constant).
One is the Ant depends task, which doesn't work if the dependency is not in the classfile. There is another tool called JavaMake (which has an Ant task) that sacrifices efficiency for correctness. It maintains state of what it analyzed in the class files last time and compares it with the current contents of the class file. It can detect that a constant changes, but if one does it recompiles any class that could have depended on it. For a public constant that means recompiling everything.
> But Ant has several advantages that more than make up > for the lack of this automated dependency checking. In other words, if you are willing to sacrificed correctness of builds and efficiency of builds then it has some nice window dressing to make expressing those inefficent, incorrect builds.
I used to live in a world of incorrect builds when developing under Windows CE Platform builder. It was routine to have a build not work, rebuild from scratch and then have it work. And at one time a build from scratch took 30 minutes (when we got new machines it went to 10 minutes). A build where there was nothing to do would also take minutes as it did work that wasn't necessary.
Believe me that is not a fun world to develop in. I get a little skeptical of people telling me that build correctness and build efficiency are not that important.
>>Of course I am not saying that everyone should switch to make for >>building Java. Make doesn't work for Java. Java is a difficult build >>problem. > > No, it's not: It just adds the package-to-path dependency that C++/C# > etc. avoids. See above. The difference is the compilation model.
> Make is unsuited to Java because Make is there to add "smartness" to > dumb old compilers (including the use of makedepend/mkdep to find > preprocessor dependencies), and otherwise act as a "glorified batch > file". Make is for people who thought #ifdef __SYSV__ is a good idea. Dependencies are always there in building programs. You can't just assert your bias against C/C++ development and assume that it all was because of stupid people. Java didn't get rid of dependencies, it just moved those dependencies from being dependent only on source files to being dependent on the output of the compilation for other source files. That leads to circular dependencies that can only be solved by the fact that Java can sort it out if the files are compiled at the same time.
> Ant however is there to provide a framework for cross-platform > development with smart compilers. What smart compilers are these? Javac is a pretty dumb compiler.
>>But Ant definitely does not deserve being called "make" done right. >>It's a nice form of cross platform batch file. > > Not any more than make is. Unless you only use "exec"-type tasks to > run command-line programs. No make was created to ensure efficent builds that were also correct. A correctly written makefile can guarantee that.
Java however breaks the model of make. The make model assumes:
- No circular dependencies. Make uses a directed *acyclic* graph. Dependencies in Java are routinely cyclic. Dependencies in C/C++ are never cyclic. - Artifacts can be built independent of each other. There are cases in Java where you cannot compile A.java and B.java separately. You have to compile them at the same time. In C/C++ you can always compile separately. - One set of commands produces one output. Make has some support for this but only in pattern rules. Compiling one Java source file can produce many class files. In C/C++ one source file produces one object file. It can also produce dependencies and other listing files. To express that in make requires a pattern rule.
So there is a difference between make and Ant. Make guarantees correct and efficient builds if your build fits in its model. Ant guarantees neither. Ant's guarantees are no greater than using a batch file which is why I call it one. Make is an expert system. You give it the rules and it applies the rules.
 Signature Dale King
Tor Iver Wilhelmsen - 15 Aug 2005 15:19 GMT > The dependencies in C always look like this: > > foo.o ----> foo.c ----> header files Yes, prior to linking, they are that simple. Javac, however, resolves the "link relationships" at compile time.
> Java is not that simple. First one source file can produce more than > one class file. Yes, but in a deterministic location.
> Secondly, compilation does not depend on text header > files, but on other class files. Correct: The horrid header files, an artifact of when disk space was scarce, were abandoned when they made Java.
> Thirdly, Java allows circular dependencies which can only be > resolved by compiling the source files at the same time. Only if the "object files" (.class files) don't exist at compile time. Again, this is a direct consequence of the C compiler leaving much of what javac does to the later linking step.
And you forgot to complain about the dynamic dependencies made possible by Class.forName() and the like.
> Those rules are incompatible with make's DAG. So make is unsuited for Java. We get that. But why the attack on Ant?
> They have their own compiler from which they extract the necessary > dependencies. Yes, they compile everything "at once" and references the compiled state. Other IDEs do things close to that, e.g. JBuilder.
> In other words, if you are willing to sacrificed correctness of > builds and efficiency of builds then it has some nice window > dressing to make expressing those inefficent, incorrect builds. Ant, just like make, depends on the "makefile" author to express what sourcefiles they want built. How can a tool be blamed for the errors of its users?
Do you have a definition of this "correctness of builds" your whole argument seems to rest on?
> Believe me that is not a fun world to develop in. I get a little > skeptical of people telling me that build correctness and build > efficiency are not that important. I find it very efficient. And correct, in the sense it does what the developer tells it to do.
> Dependencies are always there in building programs. You can't just > assert your bias against C/C++ development and assume that it all > was because of stupid people. Not stupid people, stupid technology. Objective-C tried to fix the most glaring problem with header files - multiple inclusion - by adding #import, but by then the workaround of using #ifndef __SOMETHING__ #define __SOMETHING__
...
#endif
had been established as a common practice.
> Java didn't get rid of dependencies, it just moved those > dependencies from being dependent only on source files to being > dependent on the output of the compilation for other source files. As is C/C++ when it comes to link time.
> That leads to circular dependencies that can only be solved by the > fact that Java can sort it out if the files are compiled at the same > time. But if c/c++ does not have circular dependencies between files, why does make have checks against them?
> No make was created to ensure efficent builds that were also > correct. A correctly written makefile can guarantee that. It depends on the user just as much as Ant, then.
> - No circular dependencies. Make uses a directed *acyclic* graph. Make still has code to detect circular dependencies.
> Dependencies in Java are routinely cyclic. Dependencies in C/C++ are > never cyclic. Dependencies between make targets can be.
> - Artifacts can be built independent of each other. There are cases > in Java where you cannot compile A.java and B.java separately. Because javac does "link-time lookups" when compiling. You avoid this problem in your praise of make.
> You have to compile them at the same time. In C/C++ you can always > compile separately. Only if you compile to (intermediate) object files.
> - One set of commands produces one output. Make has some support for > this but only in pattern rules. Compiling one Java source file can > produce many class files. Yes, this is a consequence of the language. NOT ANT! If I use Ant to build Python projects, it seems half your arguments go away?
> Make is an expert system. You give it the rules and it applies the > rules. Why, it's the same thing as Ant does then. Only it doesn't run command-line programs like a batch file would - that is make's way.
Dale King - 17 Aug 2005 13:50 GMT >>The dependencies in C always look like this: >> >> foo.o ----> foo.c ----> header files Actually that should really be:
foo.o ---> foo.c + header files
> Yes, prior to linking, they are that simple. Javac, however, resolves > the "link relationships" at compile time. And they are that simple after linking. The important point I was making was that the dependencies were all one direction and acyclic. foo.o is never dependent on bar.o thus there cannot be circular dependencies.
>>Java is not that simple. First one source file can produce more than >>one class file. > > Yes, but in a deterministic location. Assuming that your source files are organized according to package. But the point is in C the compiler will only produce a single object.
>>Secondly, compilation does not depend on text header >>files, but on other class files. > > Correct: The horrid header files, an artifact of when disk space was > scarce, were abandoned when they made Java. I think you grossly mischaracterize why header files were used. First off don't confuse #include with all the other parts of the preprocessor. Just because many atrocities have been commited with conditional compilation and macros is not a reason to condemn the use of header files.
There basically are two models of compilation, the C way where everything is in textual source code or the Java way where the compiler uses the output of the compilation of other sources rather than the text itself.
There are a number of issues if C had gone the latter way. We have talked about the complexity of circular dependencies. They wanted to be able to link with existig libraries in other languages. To do it requires an output format that allows you to encode the necessary format. What was in exiestence was the object file which did not allow that kind of specification. There's no way they could drive a new standard to replace object files. They were stuck with them.
Sun could make their own standard because they didn't care about any of that compatibility.
So it really had little to do with disk space. Given the constraints it was the only sensible choice.
>>Thirdly, Java allows circular dependencies which can only be >>resolved by compiling the source files at the same time. > > Only if the "object files" (.class files) don't exist at compile time. Well the class files can only exist by resolving them by compiling at the same time at least once.
> Again, this is a direct consequence of the C compiler leaving much of > what javac does to the later linking step. No, it isn't. Linking has nothing to do with it. It is the difference in compilation models.
> And you forgot to complain about the dynamic dependencies made > possible by Class.forName() and the like. That's really out of the scope of the build tool and in general an unsolvable problem.
>>Those rules are incompatible with make's DAG. > > So make is unsuited for Java. We get that. But why the attack on Ant? Because Ant improves on some syntax elements but is a major step backwards in terms of build correctness. Yet people hype Ant like it is better than make in all ways.
The trouble is there needs to be a real build tool for Java that has the niceness of expression of Ant, but not losing any of the fundamental properties of make (and possibly even improve on them).
I for one see what should be done, but don't have the time or the great need any more to do it. At one time I started a sourceforge project to work on it, but never took it anywhere.
So while I can't point you to a tool that is better than Ant other than an IDE like Eclipse, I can definitely show that better tools than Ant can and should exist. For non-java development, make *IS* better than Ant.
>>They have their own compiler from which they extract the necessary >>dependencies. > > Yes, they compile everything "at once" and references the compiled > state. Other IDEs do things close to that, e.g. JBuilder. And that would be the ideal way to a solution, to get dependency information from the compiler. The dependencies would not be in make file format, but as long as they can be produced in some readable format then you can build a tool to guarantee correctness and efficiency for building Java code.
>>In other words, if you are willing to sacrificed correctness of >>builds and efficiency of builds then it has some nice window [quoted text clipped - 3 lines] > sourcefiles they want built. How can a tool be blamed for the errors > of its users? We're not talking about errors in the "makefile".
With Ant it is not possible to write a build script that will give you the same guarantees of correctness and efficiency that make gives for C compilation.
Essentially, there is no way to have an "error-free" Ant script.
> Do you have a definition of this "correctness of builds" your whole > argument seems to rest on? Actually, there is a very good paper I found a few years ago that echoed my thoughts and provides a very formal definition of make "safeness" and what characteristics are necessary to achieve it is:
http://webhotel.ruc.dk/nielsj/research/papers/make.pdf
The short form of the result is:
"Safeness of make-based incremental compilation, the key result of this paper, can be stated as follows: Suppose we build a program brute-force, and then edit the source files, and possibly the makefile as well. Then under certain assumptions about the makefile rules and the kind of editing performed, the result of make-based incremental recompilation is equivalent to the result of a (second) brute force build."
>>Believe me that is not a fun world to develop in. I get a little >>skeptical of people telling me that build correctness and build >>efficiency are not that important. > > I find it very efficient. And correct, in the sense it does what the > developer tells it to do. But may result in incorrect builds. It's probably good enough for most people with the depends task, but I'd guess the majority don't use depends. Without depends you're really living dangerously.
>>Java didn't get rid of dependencies, it just moved those >>dependencies from being dependent only on source files to being >>dependent on the output of the compilation for other source files. > > As is C/C++ when it comes to link time. The key issue is circularity of dependence. It's OK for the linked executable or library to be dependent ot the output of the compiler. The situation with Java is that one output of the compiler is dependent on other outputs of the compiler causing circular dependencies.
So we can have long chains of dependencies, just not circular ones. Make cannot deal with circular ones.
>>That leads to circular dependencies that can only be solved by the >>fact that Java can sort it out if the files are compiled at the same >>time. > > But if c/c++ does not have circular dependencies between files, why > does make have checks against them? Because humas are expressing the dependencies and make is not just for C/C++. You can have a makefile like this:
A : B cat B > A B : A cat A > B
There is no way to build this. The way make works is that it finds the order to build things. Without some check for circular dependencies the above would become an infinite loop of traversing the dependencies and make would hang. What make actually does is throw away one of the rules and gives you warning to know that it did.
>>No make was created to ensure efficent builds that were also >>correct. A correctly written makefile can guarantee that. > > It depends on the user just as much as Ant, then. Sure you have to write it correctly, but the difference is that with make (and languages with a similar compilation model to C) it is possible to write it correctly. With Ant and Java there is nothing the user can do to achieve both correctness and efficiency. You can only get one at the cost of the other.
>>- No circular dependencies. Make uses a directed *acyclic* graph. > > Make still has code to detect circular dependencies. Only so it doesn't hang when you give it one.
>>Dependencies in Java are routinely cyclic. Dependencies in C/C++ are >>never cyclic. > > Dependencies between make targets can be. Yes and make cannot deal with them and thus it cannot deal with Java. Circular dependencies cannot be dealt with in a general way. It requires more specific knowledge of how to resolve it.
>>- Artifacts can be built independent of each other. There are cases >>in Java where you cannot compile A.java and B.java separately. > > Because javac does "link-time lookups" when compiling. You avoid this > problem in your praise of make. I have no idea what you mean by link-time lookups, but that has nothing to do with it. The difference is the compilation model. You could theoretically have Java that used a C compilation model.
Consider if you have A.java and it produces A.class. Now we are going to compile B.java and it has a reference to what is defined in A.java. Where does it get the information? There are two choices leading to the two compilation models:
- It can read A.class. This is what Java actually does. The advantages are that it leads to faster compilation, consistent results because the compiler only reads a piece of source once, greater type checking because you are looking at what the compiler actually produced, and the ability to compile a library without requiring any source code. The disadvantage is that it complicates the build process because it causes circular dependencies and you can no longer compile each source file indepently of others. - It can read A.java. This is the C model. The advantages are that it has simple build procedure with no circular dependencies and allows separate compilation. It also allows you to use a very simple output format for the compiler that is compatible with other languages. The disadvantages are of course the flip side of the advantages of the Java model.
Neither is the "correct" model. They both have advantages and disadvantages. If you look at the constraints of C, needing compatibility with other languages and a relatively dumb object format, then its choice of model is a no-brainer.
>>You have to compile them at the same time. In C/C++ you can always >>compile separately. > > Only if you compile to (intermediate) object files. What's that supposed to mean. Of course it compiles to something. The difference is that output is never also the input of another compilation, thus no circularity.
>>- One set of commands produces one output. Make has some support for >>this but only in pattern rules. Compiling one Java source file can >>produce many class files. > > Yes, this is a consequence of the language. NOT ANT! If I use Ant to > build Python projects, it seems half your arguments go away? And the point of this section was why make cannot be used Java and why Java is a more difficult build problem. I wasn't talking about Ant at all in this portion. What I was addressing was the claim that C had a dumb compiler. The difference is not smartness and dumbness but choice of compilation model.
I don't know about Python's compilation model. Is it like C or Java. Of course there is still the issue of other tasks and their ad-hoc dependency checking.
>>Make is an expert system. You give it the rules and it applies the >>rules. > > Why, it's the same thing as Ant does then. Only it doesn't run > command-line programs like a batch file would - that is make's way. No. Ant is a list of commands to run just like a batch file. Other than providing names to groups of commands and allowing you to specify a fixed ordering for the groups of commands The only logic is to execute the next command in sequence. So the ordering is fixed at the time of writing the Ant file.
Make is a set of rules telling the system under what circumstances to run the commands. It dynamically decides what order to do things based on the current state. It is making decisions about sequence unlike Ant.
 Signature Dale King
Tor Iver Wilhelmsen - 17 Aug 2005 17:16 GMT > And they are that simple after linking. The important point I was > making was that the dependencies were all one direction and acyclic. > foo.o is never dependent on bar.o thus there cannot be circular > dependencies. But that's because if foo.c and bar.c reference each other's fields or methods, the C compiler will happily delay resolving them.
Java has namespace concerns that C lacks. Everything belongs somewhere, not in some global scope.
> But the point is in C the compiler will only produce a single > object. Per compilation unit. But that's because unlike Java, that object is not a namespace - except for the case of static variables. And the C compiler can do it because it does not have a "package" concept.
> There basically are two models of compilation, the C way where > everything is in textual source code or the Java way where the > compiler uses the output of the compilation of other sources rather > than the text itself. Again you are ignoring the quite important linking step. Everything _isn't_ in textual source code at that point; everything is in object files.
> What was in exiestence was the object file which did not allow that > kind of specification. There's no way they could drive a new > standard to replace object files. They were stuck with them. Sort of correct: It would eventually end up as object files, but they could have another intermediate dependency-aware format before that. (Digital had a generic three-address code output you could get from their MIPS Ultrix C compiler for instance.)
Java .class files (or C# executables) are also an "intermediate" step before Hotspot/JIT turns it into native code at runtime.
> Sun could make their own standard because they didn't care about any > of that compatibility. Yes, but that holds for every virtual machine language, from p-code and WAM via Perl and Python to Java and the .Net CIL.
> So it really had little to do with disk space. Given the constraints > it was the only sensible choice. Well, it seems to be more a case of separating "interface" (the symbols available to the compiler) and "implementation" (the actual locations available to the linker).
> Well the class files can only exist by resolving them by compiling > at the same time at least once. Yes, but you could conceivably have a javac flag that disabled the resolution; After all, what is put in the class file are just strings in the constant pool. After all, I can take a .class file out of its "context" (or one with different classes) and try runnig it: I am then likely to get various runtime exceptions and errors, including NoClassDefFoundError and NoSuchMethodError. But the symbols were available at
The problems arise with wildcard imports and same-package implicit imports. These need to know what package a given "symbol" (class) exists in. Not to mention references to superclass methods and fields.
(So C/C++ in may ways uses header files for exactly the same purposes the Java compiler uses .class files.)
> No, it isn't. Linking has nothing to do with it. It is the > difference in compilation models. Again: It has everything to do with it. The difference is that the "linker" is not involved in cc -c a.c but it is involved in javac a.java
> Because Ant improves on some syntax elements but is a major step > backwards in terms of build correctness. I think the issue here is that Ant's Java compilation task is supposed to "build everything you need". So it may be inefficient but as long as the build file actually include all source files in its file set, it should be a
|
|