File: mmake.in

package info (click to toggle)
mmake 2.3-5
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 252 kB
  • ctags: 90
  • sloc: perl: 403; makefile: 316; sh: 152; java: 17
file content (863 lines) | stat: -rw-r--r-- 24,434 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
#!@PERL@ -w
#
# (c) 1998-2004 Jan-Henrik Haukeland, <hauk@tildeslash.com>
#

=head1 NAME

 mmake - generate a Java Makefile

=head1 SYNOPSIS

 mmake [ -d | -v ]

=head1 DESCRIPTION

This program will generate a Makefile for Java source files. Use the
I<-d> option to accept all defaults.

After running mmake, you will obtain a Makefile in the directory from
where you started the program. The Makefile will handle java files in
the current directory and in any sub-directories.

Use the generated Makefile with mmake as follows:

To compile Java files just type B<make>. It's also possible to run
make with one of the following targets: I<doc, clean, help, jar,
srcjar, bundle, install, uninstall, tags and depend> Where 'make doc'
runs javadoc on the source files, it will only work for files in a
package. The command 'make clean' removes class files and other
temporary files. The command 'make jar' creates a jar file with all
class files (and other files of your choice, see the JAR_OBJS variable
in the Makefile). The command 'make srcjar' creates a jar file with
all java files. The command 'make bundle' creates a Mac OS X
Application Bundle with all the jar file. The command 'make install'
will install a jar file, app bundle, class files and any shell
wrappers you have made. (A shell script must have the extension .sh to
be installed). Use 'make uninstall' to remove installed files. The
command 'make help', shows a help text with available targets. The
command 'make tags' will generate a tag file for Emacs. And finally
the command 'make depend' creates a dependency graph for the class
files. (The dependency graph will be put in a file called
I<makefile.dep>, which is included in the Makefile)

You don't have to run mmake each time you add a new java file to your
project. You can add as many new java files as you like, the Makefile
will find them. This is the case as long as you don't add a new
package. In that case, you must either run mmake again or update the
PACKAGE variable in the Makefile. This is because the Makefile uses
this variable to find directories with java files.

The program mmake is able to create a dependency graph for your java
files. To do this, it needs the I<jikes> compiler from IBM. Get jikes
from B<http://www.ibm.com/developerworks/oss/jikes/>.You would
probably be more content with jikes anyhow, since it is much faster
than javac. To create a dependencies graph, do a I<make clean> before
running I<make depend>.


=head1 A NOTE ON INSTALLATION

The Makefile created with mmake will do a fair job installing the
different files that makes up your system. It uses the following
Makefile variables when it conducts the install routine:

=over 4

=item * 

PREFIX

=item * 

CLASS_DIR

=item * 

JAR_DIR

=item * 

BUNDLE_DIR

=item * 

DOC_DIR

=item * 

SCRIPT_DIR

=back

=head2 PREFIX

This variable will be prepended to all other directory variables
above. It is used for grouping the other directories into one root
directory. If you don't want that, you may simply set the variable to
an empty string in the Makefile. If the variable is empty you could
still use it on the command line when you run make, for instance for a
one-shoot installation like: B<make PREFIX=/local/myproject/ install>

=head2 CLASS_DIR

This variable denotes the top directory from where all class files
will be installed. Its default value is B<classes>, which I believe is
a good value. B<Note:> If you I<don't> want to install any class files
(because you are, for example, only going to use a jar file), set this
variable to an empty string and no class files will be installed. 

Resource files will also be installed below this directory if such
files are present in a package structure. This is useful if you are
using e.g. ResourceBundles to Localize your application and have your
property files in it's own directory in the package structure.

=head2 JAR_DIR

This variable tells the Makefile where to install the jar file. The
default value is B<lib>, which is also a good default value.

=head2 BUNDLE_DIR

This variable tells the Makefile where to install the app bundle. The
default value is B<lib>, which is also a good default value.

=head2 DOC_DIR

When you run javadoc, all the html files will be put into this
directory. Its default value is B<doc/api-docs>. You should probably
keep that name, but then again, you may change it as you like.

=head2 SCRIPT_DIR

The Makefile uses this variable to install any shell wrapper-scripts
that you have created. If you write an application, it is always nice
for the user that you provide a wrapper script to start the
application. Its default value is B<bin>. (The Makefile will only
install shell-scripts that has the extension .sh. The mmake script
will tell the Makefile where to look for shell-scripts)


=head2 INSTALLATION SUMMARY

If you keep the default values you will get an installation tree that
looks like this:

 `-- PREFIX
     |-- bin
     |-- classes
     |   `-- package <--- Example of a sub-directory
     |       |-- sub-package1
     |       |-- sub-package2
     |       `-- sub-package3
     |-- doc
     |   `-- api-docs
     `-- lib


=head1 USING THE C-PREPROCESSOR

This is a excellent tool for managing projects with several different
versions. The idea behind using the C preprocessor with Java is to
better manage different versions more easily. This is done by using
CPP conditional statements in the source files. I would strongly
advise you not to use CPP to redefine the Java language itself.

To use the C preprocessor together with Java, you can change the name
of the source files that you want to preprocess -- from
<filename>.java to <filename>.xjava. The Makefile has a rule to build
.class files from .xjava files.

It is B<not> necesarry to change every file from .java to .xjava. The
Makefile will work well and consistently in an environment of both
.java and .xjava files. (E.g. 'make clean' will only remove .java
files that were created from a .xjava file. Other java files will, of
course, I<not> be removed.)

You can now use cpp Conditionals in Your Java-code, for example, as
follows:

    #ifdef JAVA1_1
       [code1]
    #else
       [code2]
    #endif

The JAVA1_1 label in the above example is tested against the
VERSION variable in the Makefile. That is, if the VERSION variable is
JAVA1_1, then [code1] would be compiled and [code2] left out. Likewise,
if VERSION is something else than JAVA1_1, then [code2] would be compiled and
[code1] left out of the resulting .class file.

=head1 NOTES

mmake will give you I<one> Makefile for managing your Java files.
Although it's easy to setup and use mmake in a recursive makefile
context, you don't want to do that. To see why, read the excellent
article: B<Recursive Make Considered Harmful> at
I<http://www.canb.auug.org.au/~millerp/rmch/recu-make-cons-harm.html>

=head1 DEPENDENCIES

mmake will need the following:

=over 4

=item * 

Perl 5.x

=item * 

Gnu make

=item * 

Gnu xargs (recommended)

=back

=head1 AUTHOR

Jan-Henrik Haukeland <hauk@tildeslash.com>

=cut

use strict;
use vars qw($opt_d $opt_v $opt_o);
use Getopt::Std;
require 5.000;                   # Need this perl version at least

# Prototypes
sub getline($$);
sub getdirline($$);
sub getpreviewline($$$);
sub do_get();
sub do_find($$);


my $REVISION= sprintf("%d.%02d", q$Revision: 1.13 $ =~ /(\d+)\.(\d+)/);

my $VERSION= "2.3";            # The program version
(my $PROG = $0)=~   s,.*/,,;     # This Program name (usually 'mmake')
my $M=             "Makefile";   # The Java Makefile
my @packages=      ();           # Array holding packages, i.e. subdirectories 
my @all_packages=  ();
my @scripts=       ();           # Array holding shell-script directories 
my @resources=     ();           # Array holding resource files
my $toplevel=      "";           # Defined if toplevel java files

# Parse command line options
getopts("dvo:") || die "Usage: $PROG [ -d | -v ]\n";

if ( defined $opt_v ) {
  print "This is mmake, version $VERSION\n";
  exit(0);
}

if ( defined $opt_o ) {
  $M = $opt_o;
}

# ---------------------
# Assign macro defaults
# ---------------------
my $javac=        "@JAVAC@"; 
my $jflags=       "";
my $javadoc=      "javadoc";
my $jdocflags=    "-version -author";
my $jar=          "jar";
my $jarflags=     "cvf0";
my $jarfile=      "";
my $appfile=      "";
my $prefixdir=    "";
my $docdir=       "doc/api-docs";
my $jardir=       "lib";
my $appdir=	  "lib";
my $classdir=     "classes";
my $bindir=       "bin";
my $cpp=          "cpp";
my $cppflags=     "-C -P";


if (-t and ( !$opt_d )) {
    # Let the user override the defaults
    print "Give Makefile variables or just type [enter] for default\n\n";
    $javac=         getline("JAVAC",   $javac);
    $jflags=        getline("JAVAC flags", $jflags);
    $javadoc=       getline("JAVADOC", $javadoc);
    $jdocflags=     getline("JAVADOC flags", $jdocflags);
    $jar=           getline("JAR", $jar);
    $jarflags=      getline("JAR flags", $jarflags);
    $jarfile=       getline("JAR File name (e.g. foobar.jar)", $jarfile);
    $appfile=       getline("APP Bundle name (e.g. foobar.app)", $appfile);

    $prefixdir=     getdirline("PREFIX dir. (Will be prepended to other ".
			       "install dir)",  $prefixdir);
    $docdir=        getpreviewline("INSTALL dir. for javadoc html-files.",
				   "$prefixdir$docdir", $docdir);
    $classdir=      getpreviewline("INSTALL dir. for class files", 
				   "$prefixdir$classdir", $classdir);
    $bindir=        getpreviewline("INSTALL dir. for shell-scripts",
				   "$prefixdir$bindir", $bindir);
    $jardir=        getpreviewline("INSTALL dir. for the jar file ",
				   "$prefixdir$jardir", $jardir);
    $appdir=        getpreviewline("INSTALL dir. for the app bundle ",
				   "$prefixdir$appdir", $appdir);

    if( getline("Use CPP [y|n] ?", "no") =~ /^y/i ) {
	$cpp=      getline("CPP", $cpp);
	$cppflags= getline("CPP flags", $cppflags);
    }

    print "\n";
}


# Locate the java files/packages
do_get();
die "No java source files found\n" unless @packages or $toplevel;

# If an old Makefile exists, rename it
if (-f $M) {
    rename($M, "$M.old") or
      die "$PROG: Cannot rename local Makefile.\n";
}

# Then create the new makefile
open(MAKEFILE, ">$M") || die "$PROG: Cannot create '$M': $!\n";


print MAKEFILE <<EOT;
#
# Makefile created at @{[scalar localtime]}, by $PROG
#

# Programs (with common options):
SHELL		= /bin/sh
CP		= cp
RM              = rm -f
MV              = mv -f
SED		= sed
ETAGS		= etags
XARGS		= xargs
CAT		= cat
FIND            = find
CPP		= $cpp $cppflags

INSTALL         = install
INSTALL_PROG    = \$(INSTALL) -m \$(MODE_PROGS)
INSTALL_FILE    = \$(INSTALL) -m \$(MODE_FILES)
INSTALL_DIR     = \$(INSTALL) -m \$(MODE_DIRS) -d

# Install modes 
MODE_PROGS      = 555
MODE_FILES      = 444
MODE_DIRS       = 2755

# Build programs
JAVAC           = $javac
JAVADOC         = $javadoc
JAR             = $jar

# Build flags
JAVAC_FLAGS     = $jflags
JAVADOC_FLAGS   = $jdocflags
JAR_FLAGS       = $jarflags
JIKES_DEP_FLAG	= +M

# ------------------------------------------------------------------- #

# Prefix for every install directory
PREFIX		= $prefixdir

# Where to start installing the class files. Set this to an empty value
#  if you dont want to install classes
CLASS_DIR	= \$(PREFIX)$classdir

# The directory to install the jar file in. Set this to an empty value
#  if you dont want to install a jar file
JAR_DIR	        = \$(PREFIX)$jardir

# The directory to install the app bundle in. Set this to an empty value
#  if you dont want to install an app bundle
BUNDLE_DIR      = \$(PREFIX)$appdir


# The directory to install html files generated by javadoc
DOC_DIR         = \$(PREFIX)$docdir

# The directory to install script files in
SCRIPT_DIR	= \$(PREFIX)$bindir

# ------------------------------------------------------------------- #

# The name of the jar file to install
JAR_FILE        = $jarfile

# 
# The VERSION variable below should be set to a value 
# that will be tested in the .xjava code and Info.plist. 
# 
VERSION		= CHANGE_ME

# ------------------------------------------------------------------- #

# The name of the OS X Application Bundle to install
BUNDLE_FILE	= $appfile

# Folder containing App Bundle resources (Info.plist, *.icns, etc.)
BUNDLE_RESOURCE_DIR = misc/macosx

# Items to copy to the Resources folder of the bundle
BUNDLE_RESOURCES = \$(addsuffix .icns, \$(basename \$(APP_FILE)) Document)

# Location of JavaApplicatonStub
JAVA_STUB	= /System/Library/Frameworks/JavaVM.framework/Resources/MacOS/JavaApplicationStub

# ------------------------------------------------------------------- #

# Resource files:
#  Extend the list to install other files of your choice
RESOURCE_SRC	:= *.properties *.gif *.au

# Objects that should go into the jar file. (find syntax)
JAR_OBJS	:= \\( -name '*.class' -o -name '*.gif' -o -name "*.au" \\
		       -o -name '*.properties' \\)

# Include the separate variables file if it exists
MAKEFILE_VARS	= makefile.vars
VARS	= \$(wildcard \$(MAKEFILE_VARS))
ifneq (\$(VARS),)
	include \$(MAKEFILE_VARS)
endif

EOT


# Print the packages 
print MAKEFILE "
# Packages we should compile
PACKAGES = ",
  @packages ? ("\\\n\t" . join(" \\\n\t", @packages)) : "",
  "\n\n";

print MAKEFILE "
# All packages that can be recursively compiled.
ALL_PACKAGES = ",
  ("\\\n\t".join(" \\\n\t", @all_packages, '$(PACKAGES)')),"\n\n";

print MAKEFILE "
# Packages to generate docs for.
JAVADOC_PACKAGES = \$(PACKAGES)

";

# Print the resource "packages"
print MAKEFILE "
# Resource packages
RESOURCES = ",
  @resources ? ("\\\n\t" . join(" \\\n\t", @resources)) : "",
  "\n\n";

# Print the script dir list
print MAKEFILE "
# Directories with shell scripts
SCRIPTS = ",
  @scripts ? ("\\\n\t" . join(" \\\n\t", @scripts)) : "",
  "\n\n";


print MAKEFILE <<EOT;
# ------------------------------------------------------------------- #

# A marker variable for the top level directory
TOPLEVEL	:= .

# Subdirectories with java files:
JAVA_DIRS	:= \$(subst .,/,\$(PACKAGES)) \$(TOPLEVEL)

# Subdirectories with only resource files:
RESOURCE_DIRS	:= \$(subst .,/,\$(RESOURCES))

# All the .xjava source files:
XJAVA_SRC	:= \$(foreach dir, \$(JAVA_DIRS), \$(wildcard \$(dir)/*.xjava))

# All the xjava files to build
XJAVA_OBJS	:= \$(XJAVA_SRC:.xjava=.java)

# Directory coresponding to a package
PACKAGE_DIR	= \$(subst .,/,\$(1))

# All the (x)java files in a package
PACKAGE_SRC	=  \$(shell \$(FIND) \$(PACKAGE_DIR) \\( -name '*.java' -or -name '*.xjava' \\) )

# All the classes to build in a package
PACKAGE_OBJS	= \$(patsubst %.java,%.class,\$(PACKAGE_SRC: %.xjava=%.java))

# All the .java source files:
JAVA_SRC	:= \$(foreach dir, \$(JAVA_DIRS), \$(wildcard \$(dir)/*.java))
JAVA_SRC	:= \$(XJAVA_OBJS) \$(JAVA_SRC)

# Dependency files:
DEPEND_OBJS	:= \$(JAVA_SRC:.java=.u)

# The intermediate java files and main classes we should build:
JAVA_OBJS	:= \$(XJAVA_OBJS) \$(JAVA_SRC:.java=.class)

#  Search for resource files in both JAVA_DIRS and RESOURCE_DIRS
RESOURCE_OBJS	:= \$(foreach dir, \$(JAVA_DIRS) \$(RESOURCE_DIRS), \\
		     \$(wildcard \$(foreach file, \$(RESOURCE_SRC), \\
		     \$(dir)/\$(file))))

# All the shell scripts source
SCRIPT_SRCS 	:= \$(foreach dir, \$(SCRIPTS), \$(wildcard \$(dir)/*.sh))
# All shell scripts we should install
SCRIPT_OBJS    	:= \$(SCRIPT_SRCS:.sh=)

# All the files to install into CLASS_DIR
INSTALL_OBJS	:= \$(foreach dir, \$(JAVA_DIRS), \$(wildcard \$(dir)/*.class))
# Escape inner class delimiter \$
INSTALL_OBJS	:= \$(subst \$\$,\\\$\$,\$(INSTALL_OBJS))
# Add the resource files to be installed as well
INSTALL_OBJS	:= \$(INSTALL_OBJS) \$(RESOURCE_OBJS)


# ------------------------------------------------------------------- #


define check-exit
|| exit 1

endef


# -----------
# Build Rules
# -----------

%.java: %.xjava
	\$(CPP) -D\$(VERSION) \$< \$@

%.class: %.java
	\$(JAVAC) \$(JAVAC_FLAGS) \$<

%.jar: \$(JAVA_OBJS) \$(RESOURCE_OBJS)
	\$(FIND) \$(TOPLEVEL) \$(JAR_OBJS) -print | \$(XARGS) \\
	\$(JAR) \$(JAR_FLAGS) \$(JAR_FILE) 

%.u: %.java
	\$(JAVAC) \$(JIKES_DEP_FLAG) \$<


# -------
# Targets
# -------

.PHONY: all jar install uninstall doc clean depend tags bundle \\
	help \$(ALL_PACKAGES)

all::	\$(JAVA_OBJS)

help:
	\@echo "Usage: make {all|jar|srcjar|bundle|install|uninstall|doc|clean|depend|tags|PACKAGE_NAME}"
	\@echo "	all: build all classes"
	\@echo "	jar: build jar file"
	\@echo "	srcjar: build source jar file"
	\@echo "	bundle: build OS X app bundle"
	\@echo "	install: install classes into \$(CLASS_DIR)"
	\@echo "		jar into \$(JAR_DIR)"
	\@echo "		bundle into \$(BUNDLE_DIR)"
	\@echo "		javadocs into \$(DOC_DIR)"
	\@echo "		scripts into \$(SCRIPT_DIR)"
	\@echo "	uninstall: remove installed files"
	\@echo "	doc: generate api docs from javadoc comments"
	\@echo "	clean: remove classes and temporary files"
	\@echo "	depend: build class dependency info using jikes"
	\@echo "	tags: build emacs tags file"
	\@echo "	PACKAGE_NAME: builds all classes in this package and any subpackages."

# Jar target
ifneq (\$(strip \$(JAR_FILE)),)
jar:  \$(JAR_FILE)
ifneq (\$(strip \$(JAR_DIR)),)
install:: \$(JAR_FILE)
	\@echo "===> [Installing jar file, \$(JAR_FILE) in \$(JAR_DIR)] "
	\$(INSTALL_DIR) \$(JAR_DIR) \$(check-exit)
	\$(INSTALL_FILE) \$(JAR_FILE) \$(JAR_DIR) \$(check-exit)
uninstall::
	\@echo "===> [Removing jar file, \$(JAR_FILE) from \$(JAR_DIR)] "
	\$(RM) \$(JAR_DIR)/\$(JAR_FILE)  \$(check-exit)
else
install::
	\@echo "No jar install dir defined"
endif
clean::
	\$(RM) \$(JAR_FILE)
else
jar:
	\@echo "No jar file defined"
endif

SRC_JAR_FILE := \$(basename \$(JAR_FILE))-src\$(suffix \$JAR_FILE)

# Source jar target
srcjar : \$(SRC_JAR_FILE)
\$(SRC_JAR_FILE): \$(JAVA_SRC) \$(RESOURCE_OBJS)
	\$(FIND) \$(TOPLEVEL) \$(JAR_OBJS: .class=.java) -print | \$(XARGS) \\
	\$(JAR) \$(JAR_FLAGS) \$\@

# Bundle target
ifneq (\$(strip \$(BUNDLE_FILE)),)
bundle:  \$(BUNDLE_FILE)
\$(BUNDLE_FILE) : \$(JAR_FILE)
	\$(INSTALL_DIR) \$(BUNDLE_FILE)/Contents/Resources/Java \$(check-exit)
	\$(INSTALL_DIR) \$(BUNDLE_FILE)/Contents/MacOS \$(check-exit)
	\$(INSTALL_PROG) \$(JAVA_STUB) \$(BUNDLE_FILE)/Contents/MacOS/ \\
		\$(check-exit)
	( \$(CAT) \$(BUNDLE_RESOURCE_DIR)/Info.plist | \$(SED) -e \\
		s/VERSION/\$(VERSION)/ >98762infoplist876 ) \$(check-exit)
	\$(INSTALL_FILE) 98762infoplist876 \\
		\$(BUNDLE_FILE)/Contents/Info.plist \$(check-exit)
	\$(RM) 98762infoplist876 \$(check-exit)
	\$(INSTALL_FILE) \$(JAR_FILE) \$(BUNDLE_FILE)/Contents/Resources/Java
	checkexit="";for f in \$(BUNDLE_RESOURCES); do \\
		\$(INSTALL_FILE) \$(BUNDLE_RESOURCE_DIR)\$\$f \$(BUNDLE_FILE)/Contents/Resources/ \\
		|| checkexit=\$?; \\
		done; test -z \$\$checkexit

ifneq (\$(strip \$(BUNDLE_DIR)),)
# This is probably bad, but I don't know how else to do it
install:: \$(BUNDLE_FILE)
	\@echo "===> [Installing app bundle, \$(BUNDLE_FILE) in \$(BUNDLE_DIR)] "
	\$(INSTALL_DIR) \$(BUNDLE_DIR) \$(check-exit)
	\$(CP) -R \$(BUNDLE_FILE) \$(BUNDLE_DIR) \$(check-exit)
	\$(INSTALL_FILE) \$(BUNDLE_FILE) \$(BUNDLE_DIR) \$(check-exit)
uninstall::
	\@echo "===> [Removing bundle file, \$(BUNDLE_FILE) from \$(BUNDLE_DIR)] "
	\$(RM) -r \$(BUNDLE_DIR)/\$(BUNDLE_FILE)  \$(check-exit)
else
install::
	\@echo "No bundle install dir defined"
endif
clean::
	\$(RM) -r \$(BUNDLE_FILE)
else
bundle:
	\@echo "No bundle file defined"
endif


# Install target for Classes and Resources 
ifneq (\$(strip \$(CLASS_DIR)),)
install:: \$(JAVA_OBJS)
	\@echo "===> [Installing classes in \$(CLASS_DIR)] "
	\$(INSTALL_DIR) \$(CLASS_DIR) \$(check-exit)
	\$(foreach dir, \$(JAVA_DIRS) \$(RESOURCE_DIRS), \\
		\$(INSTALL_DIR) \$(CLASS_DIR)/\$(dir) \$(check-exit))
	\$(foreach file, \$(INSTALL_OBJS), \\
		\$(INSTALL_FILE) \$(file) \$(CLASS_DIR)/\$(file) \\
	\$(check-exit))
uninstall::
	\@echo "===> [Removing class-files from \$(CLASS_DIR)] "
	\$(foreach file, \$(INSTALL_OBJS), \\
		\$(RM) \$(CLASS_DIR)/\$(file) \\
	\$(check-exit))
else
# Print a warning here if you like. (No class install dir defined)
endif



# Depend target
ifeq (\$(findstring jikes,\$(JAVAC)),jikes)
depend: \$(XJAVA_OBJS) \$(DEPEND_OBJS)
	( \$(CAT) \$(DEPEND_OBJS) |  \$(SED) -e '/\\.class\$\$/d' \\
	  -e '/.*\$\$.*/d' > \$(MAKEFILE_DEPEND); \$(RM) \$(DEPEND_OBJS); )
else
depend:
	\@echo "mmake needs the jikes compiler to build class dependencies"
endif



# Doc target
ifneq (\$(strip \$(JAVADOC_PACKAGES)),)
doc:	\$(JAVA_SRC)
	\@echo "===> [Installing java documentation in \$(DOC_DIR)] "
	\$(INSTALL_DIR) \$(DOC_DIR) \$(check-exit)
	\$(JAVADOC) \$(JAVADOC_FLAGS) -d \$(DOC_DIR) \$(JAVADOC_PACKAGES)
else
doc:
	\@echo "You must put your source files in a package to run make doc"
endif



# Script target
ifneq (\$(strip  \$(SCRIPT_OBJS)),)
all::	 \$(SCRIPT_OBJS)
ifneq (\$(strip \$(SCRIPT_DIR)),)
install:: \$(SCRIPT_OBJS)
	\@echo "===> [Installing shell-scripts in \$(SCRIPT_DIR)] "
	\$(INSTALL_DIR) \$(SCRIPT_DIR) \$(check-exit)
	\$(foreach file, \$(SCRIPT_OBJS), \\
		\$(INSTALL_PROG) \$(file) \$(SCRIPT_DIR) \$(check-exit))
uninstall:: 
	\@echo "===> [Removing shell-scripts from \$(SCRIPT_DIR)] "
	\$(foreach file, \$(SCRIPT_OBJS), \\
		\$(RM) \$(SCRIPT_DIR)/\$(file) \$(check-exit))
else
# Print a warning here if you like. (No script install dir defined)
endif
clean::
	rm -f \$(SCRIPT_OBJS)
endif



# Tag target
tags:	
	\@echo "Tagging"
	\$(ETAGS) \$(filter-out \$(XJAVA_OBJS), \$(JAVA_SRC)) \$(XJAVA_SRC)



# Various cleanup routines
clean::
	\$(FIND) . \\( -name '*~' -o -name '*.class' \\) -print | \\
	\$(XARGS) \$(RM) 
	\$(FIND) . -name '*.u' -print | \$(XARGS) \$(RM)

ifneq (\$(strip \$(XJAVA_SRC)),)
clean::
	\$(RM) \$(XJAVA_OBJS)
endif

# ----------------------------------------
# Include the dependency graph if it exist
# ----------------------------------------
MAKEFILE_DEPEND	= makefile.dep
DEPEND	= \$(wildcard \$(MAKEFILE_DEPEND))
ifneq (\$(DEPEND),)
	include \$(MAKEFILE_DEPEND)
endif

#package targets
EOT

# print package targets
foreach my $package (@all_packages,  @packages) {
  print MAKEFILE "$package : \$(call PACKAGE_OBJS,$package)\n";
}
print MAKEFILE "\n";

close(MAKEFILE);

print "'$M' created\n";

exit(0);

# ------------------------------------------------------------------------- #
# ----------------------------- Subroutines ------------------------------- #
# ------------------------------------------------------------------------- #

sub getline($$)
{
  my $key= shift;
  my $dir= shift;
  my $j;
  print "$key [$dir]: ";
  chomp($j= <STDIN>);

  return ($j =~ /\w/ ? $j : $dir);
}


sub getdirline($$)
{
  my $key= shift;
  my $dir= shift;
  my $j;
  print "$key [$dir]: ";
  chomp($j= <STDIN>);
  if ( $j =~ /(\w)|(^\.)/ ) {
    $j .="/" if ( substr($j, -1) ne "/" );
    return $j;
  }

  return $dir;
}


sub getpreviewline($$$)
{
  my $key=     shift;
  my $preview= shift;
  my $dir=     shift;
  my $j;
  print "$key [$preview]: ";
  chomp($j= <STDIN>);

  return ($j =~ /\w/ ? $j : $dir);
}


sub do_get()
{
  my $cmd;

  # Get directories with java files
  $cmd= q$find . \( -name "*.java" -o -name "*.xjava" \) $
       .q$-print 2>/dev/null |$;
  @packages= do_find("p", $cmd);
  return unless @packages or $toplevel;

  # Get directories with shell-script files
  $cmd= q$find . \( -name "*.sh" \) -print 2>/dev/null |$;
  @scripts= do_find("s", $cmd);

  # Get directories with *only* resource files
  $cmd= q$find . \( -name "*.properties" -o -name "*.gif" -o -name $
       .q$"*.au" \) -print 2>/dev/null |$;
  # A hash with package values
  my %p= map { ($_), $_ } @packages;
  my %ap=map { ($_), $_ } (map {get_parents($_);} @packages);
  # Set only elements located in a package and not
  # already in the packages array
  @resources= grep { ! $p{$_} && $_ =~ /\./ } do_find("p", $cmd);
  @all_packages= grep { ! $p{$_} } keys(%ap);
}


sub do_find($$)
{
  my $mode= shift; # p = use package syntax
  my $cmd= shift;
  my %unique= ();

  open(MYDIR, $cmd) or
    die "$PROG: Can't run the \"find(1)\" command: $!\n";

  # Get the directories
  while (<MYDIR>)
  {
    chomp;
    s,(.*)/.*,$1,;
    s,^./,,;
    s,/,.,g if ( $mode eq "p" );
    $unique{$_}= undef if $_ =~ /\w+/;
    $toplevel= "." if $_ =~ /\./;
  }
  close(MYDIR);

  return ( keys(%unique) ) ;
}

sub get_parents($) 
{
  my @a = split /\./,$_[0];
  my @ret = shift @a;
  push @ret, join '.', $ret[-1], $_ foreach @a;
  return @ret;
}