* executable.make: Support HAS_NUNIT_TEST variable; if set, will build
[mono.git] / mcs / build / README.makefiles
1 The MCS makefiles (-*- outline -*-)
2 Peter Williams <peter@newton.cx>
3
4 The new makefiles try to abstract building on Windows and Linux. They
5 try to provide a consistent set of ways to express the things that our
6 build system needs to let us do, specifically:
7
8       * Build recursively
9       * Build libraries and executables easily
10       * Let developers use different runtimes and class libaries
11       * Make distributions easily
12       * Provide a framework for testing
13       * Build platform-independently whenever possible
14       * Generate, update, and build monodoc documentation.
15
16
17
18
19
20 ** Makefile structure
21
22 A general makefile looks like this:
23
24 ========================================
25 thisdir = class/Mono.My.Library
26 SUBDIRS =
27 include ../../build/rules.make
28
29 all-local:
30         do some stuff
31
32 install-local:
33         $(MKINSTALLDIRS) $(DESTDIR)$(prefix)/share/
34         $(INSTALL_DATA) myfile.txt $(DESTDIR)$(prefix)/share/myfiledir
35
36 clean-local:
37         rm -f my-generated-file
38
39 test-local: my_test_program.exe
40
41 run-test-local:
42         $(RUNTIME) my_test_program.exe
43
44 run-test-ondotnet-local:
45         $(RUNTIME) my_test_program.exe
46
47 DISTFILES = myfile.txt my_test_source.cs
48
49 dist-local: dist-default
50
51 doc-update-local:
52
53 my_test_program.exe: my_test_source.cs
54         $(CSCOMPILE) /target:exe /out:$@ $<
55 ========================================
56
57 Each makefile follows the same pattern: it does some setup, includes
58 the standard make rules, and provides rules for eight standard targets:
59 all, install, test, run-test, clean, dist, and doc-update.
60
61 "Some setup" is defining two variables: $(thisdir) and
62 $(SUBDIRS). $(thisdir) is the directory that the makefile lives in,
63 relative to the top directory (ie, class/corlib) and $(SUBDIRS)
64 defines the subdirectories that should be built in.
65
66 The eight targets do the following:
67
68         * all-local builds whatever someone would expect to be built
69 when they just type 'make'. Most likely Foo.dll or Foo.exe
70
71         * install-local installs whatever got built by all-local.
72
73         * test-local _builds_ the test programs or libraries but does
74 _not_ run them.
75
76         * run-test-local actually runs the tests. It shouldn't
77 necessarily exit in an error if the test fails, but should make that
78 situation obvious. It should only run tests that take care of
79 themselves automatically; interactive tests should have an individual
80 target. The idea is that 'make run-test' from the toplevel should be
81 able to proceed unsupervised and test everything that can be tested in
82 such a manner.
83
84         * run-test-ondotnet-local is a variant of run-test-local. It is used only to validate if our tests themselves works fine under Microsoft runtime (on Windows). Basically, in this target, we should not use $(TEST_RUNTIME) to test our libraries.
85
86         * clean-local removes built files; 'make clean' should leave
87 only files that go into a distribution tarball. (But it is not necessarily
88 true that all files that go into a tarball need to be left after a make clean.)
89
90         * dist-local copies files into the distribution tree, which is
91 given by the variable $(distdir). dist-local always depends on the
92 target 'dist-default'. See ** 'make dist' below.
93
94         * doc-update-local should generate or update monodoc documentation,
95 if appropriate.  This is usually only appropriate for libraries.  It's
96 defined as a standard target so that it can easily be run recursively
97 across all libraries within the module.
98
99
100
101
102
103 ** Build configuration
104
105 In general, MCS needs to be able to build relying only on the
106 existence of a runtime and core libraries (corlib, System,
107 System.Xml). So there shouldn't be any checking for libraries or
108 whatnot; MCS should be able to build out of the box. We try to keep
109 platform detection and feature testing (ie, for HP/UX echo) inside
110 the makefiles; right now, there's no configuration script, and it'd
111 be nice to keep it that way. (I am told that some people build on
112 both Windows and Linux in the same tree, which would be impossible to
113 do if we cached platform-related configury values.)
114
115 That being said, it's very convenient for developers to be able to
116 customize their builds to suit their needs. To allow this, the
117 Makefile rules are set up to allow people to override pretty much any
118 important variable.
119
120 Configuration variables are given defaults in `config-default.make';
121 `rules.make' optionally includes `$(topdir)/build/config.make', so you
122 can customize your build without CVS trying to commit your modified
123 `config-default.make' all the time.  Platform-specific variables are
124 defined in `$(topdir)/build/platforms/$(PLATFORM).make', where
125 $(PLATFORM) is detected in config-default.make. (Currently, the only
126 choices are linux.make and win32.make.)
127
128 The best way to learn what the configuration variables are is to read
129 `config.make' and `platform.make'. There aren't too many and hopefully
130 they should be self-explanatory; see the numerous examples below for
131 more information if you're confused.
132
133
134
135
136
137
138 ** Recommendations for platform specifics
139
140 If you find yourself needing a platform-specific customization, try
141 and express it in terms of a feature, rather than a platform test. In
142 other words, this is good:
143
144 ========================================
145 run-test-local: my-test.exe
146 ifdef PLATFORM_NEEDS_CRAZY_CRAP
147         crazy-crap
148 endif
149         $(RUNTIME) my-test.exe
150 ========================================
151
152 and this is bad:
153
154 ========================================
155 run-test-local: my-test.exe
156 ifdef WINDOWS
157         crazy-crap
158 else
159 ifdef AMIGA
160         crazy-crap
161 endif
162 endif
163         $(RUNTIME) my-test.exe
164 ========================================
165
166 The latter accumulates and gets unpleasant and it sucks. Granted,
167 right now we only have two platforms, so it's not a big deal, but it's
168 good form to get used to and practice. Anyway, take a look at how we
169 do the various corlib building hacks for examples of how we've done
170 platform-specificity. It certainly isn't pretty, but at least it's a
171 little structured.
172
173
174
175
176
177
178 ** Saving effort
179
180         The point of the build system is to abstract things and take
181 care of all the easy stuff. So if you find yourself writing a
182 Makefile, know that there's probably already infrastructure to do what
183 you want. Here are all the common cases I can think of ...
184
185
186
187
188
189
190 * Compiling C# code? use:
191
192 ========================================
193 my-program.exe: my-source.cs
194          $(CSCOMPILE) /target:exe /out:$@ $^
195 ========================================
196
197         or
198
199 ========================================
200 my-lib.dll: my-source.cs
201          $(CSCOMPILE) /target:library /out:$@ $^
202 ========================================
203
204 Note the '$@' and '$^' variables. The former means "the name of the
205 file that I am trying to make" and the latter means "all the
206 dependencies of the file I am trying to make." USE THESE VARIABLES
207 AGGRESSIVELY. Say that you add a new source to your program:
208
209 ========================================
210 my-program.exe: my-source.cs my-new-source.cs
211          $(CSCOMPILE) /target:exe /out:$@ $^
212 ========================================
213
214 Because of the $^ variable, you don't need to remember to add another
215 file to the command line. Similarly, if you rename your program, you
216 won't need to remember to change the rule:
217
218 ========================================
219 MonoVaporizer.exe: my-source.cs my-new-source.cs
220          $(CSCOMPILE) /target:exe /out:$@ $^
221 ========================================
222
223 will still work. Another useful variable is $<, which means "the first
224 dependency of whatever I'm building." If you order your dependencies
225 carefully it can be extremely useful.
226
227
228
229
230
231 * Just building an executable? use:
232
233 ========================================
234 PROGRAM = myprogram.exe
235 LOCAL_MCS_FLAGS = /r:System.Xml.dll
236
237 include ../build/executable.make
238 ========================================
239
240 executable.make builds a program in the current directory. Its name is
241 held in $(PROGRAM), and its sources are listed in the file
242 $(PROGRAM).sources. It might seem to make more sense to just list the
243 program's sources in the Makefile, but when we build on Windows we
244 need to change slashes around, which is much easier to do if the
245 sources are listed in a file. The variable $(LOCAL_MCS_FLAGS) changes
246 the flags given to the compiler; it is included in $(CSCOMPILE) so you
247 don't need to worry about it.
248
249 executable.make does a lot for you: it builds the program in 'make
250 all-local', installs the program in $(prefix)/bin, distributes the
251 sources, and defines empty test targets. Now, if your program has a
252 test, set the variable HAS_TEST:
253
254 ========================================
255 PROGRAM = myprogram.exe
256 LOCAL_MCS_FLAGS = /r:System.Xml.dll
257 HAS_TEST = yes
258 include ../build/executable.make
259
260 test-local: mytester.exe
261
262 run-test-local: mytester.exe
263         $(RUNTIME) $<
264
265 mytester.exe: mytester.cs
266         $(CSCOMPILE) /target:exe /out:$@ mytester.cs
267 ========================================
268
269 If your program has NUnit tests, set the variable HAS_NUNIT_TEST:
270
271 ========================================
272 PROGRAM = myprogram.exe
273 LOCAL_MCS_FLAGS = /r:System.Xml.dll
274 HAS_NUNIT_TEST = yes
275 include ../build/executable.make
276 ========================================
277
278 HAS_NUNIT_TEST tests follow library.make NUnit test conventions: 
279 the files should be in a subdirectory called Test/, and if
280 your program is called myprogram.exe, they should be listed in
281 myprogram_test.dll.sources. The names in that files should *not* have
282 the Test/ prefix. 'make test' will build myprogram_test_$(PROFILE).dll 
283 in the current directory, automatically supplying the flags to 
284 reference the original program and NUnit.Framework.dll. 
285
286 If your program has 'built sources', that is, source files generated
287 from other files (say, generated by jay), define a variable called
288 BUILT_SOURCES and do *not* list the sources in $(PROGRAM).sources:
289
290 ========================================
291 PROGRAM = myprogram.exe
292 LOCAL_MCS_FLAGS = /r:System.Xml.dll
293 BUILT_SOURCES = parser.cs
294 CLEAN_FILES = y.output
295
296 include ../build/executable.make
297
298 parser.cs: parser.jay
299         $(topdir)/jay/jay $< > $@
300 ========================================
301
302 executable.make will automatically delete the $(BUILT_SOURCES) files
303 on 'make clean'. Since this situation is a common occurrence and jay
304 happens to leave behind y.output files, you can also define a variable
305 called $(CLEAN_FILES) that lists extra files to be deleted when 'make clean' is
306 called. (That's in addition to your executable and the built sources).
307
308
309
310
311
312
313 * Buildling a library? Use
314
315 ========================================
316 LIBRARY = Mono.MyLib.dll
317 LIB_MCS_FLAGS = /unsafe
318 TEST_MCS_FLAGS = /r:System.Xml.dll
319
320 include ../../build/library.make
321 ========================================
322
323 Where you library is called $(LIBRARY); it will be put into
324 $(topdir)/class/lib. LIB_MCS_FLAGS is the set of MCS flags to use when
325 compiling the library; in addition, a global set of flags called
326 $(LIBRARY_FLAGS) is added (that variable is defined in
327 config-defaults.make), as well as the usual $(LOCAL_MCS_FLAGS).
328
329 As in executable.make, the sources for your library are listed in
330 $(LIBRARY).sources. Note: these source lists should have Unix forward
331 slashes and Unix newlines (\n, not \r\n.) If you get an error about
332 "touch: need a filename", that means your .sources file doesn't end in
333 a newline. It should.
334
335 Now library.make also assumes that your library has an NUnit2 test
336 harness. The files should be in a subdirectory called Test/, and if
337 your library is called Mono.Foo.dll, they should be listed in
338 Mono.Foo_test.dll.sources. The names in that files should *not* have
339 the Test/ prefix. 'make test' will build Mono.Foo_test.dll in the
340 current directory, automatically supplying the flags to reference the
341 original library and NUnit.Framework.dll. 
342
343 If you don't have a test, just do this:
344
345 ========================================
346 LIBRARY = Mono.MyLib.dll
347 LIB_MCS_FLAGS = /unsafe
348 NO_TEST = yes
349
350 include ../../build/library.make
351 ========================================
352
353 and feel ashamed. Every good library has a test suite!
354
355 Extra flags needed to compile the test library should be listed in
356 $(TEST_MCS_FLAGS); often you will have a line like this:
357
358 ========================================
359 TEST_MCS_FLAGS = $(LIB_MCS_FLAGS)
360 ========================================
361
362 Again, library.make does a lot for you: it builds the dll, it
363 generates makefile fragments to track the dependencies, it installs
364 the library, it builds the test dll on 'make test', it runs
365 $(TEST_HARNESS) on it on 'make run-test', it removes the appropriate
366 files on 'make clean', and it distributes all the source files on
367 'make dist'. (TEST_HARNESS defaults to be nunit-console.exe but it may
368 be overridden to, say, nunit-gtk). If you have extra files to
369 distribute when using either library.make or executable.make, use the
370 variable $(EXTRA_DISTFILES):
371
372 ========================================
373 EXTRA_DISTFILES = \
374         Test/testcase1.in               \
375         Test/testcase1.out              \
376         README
377 ========================================
378
379 Again, library.make and executable.make do the right things so that we
380 can build on Windows, doing some trickery to invert slashes and
381 overcome command-line length limitations. Use them unless you have a
382 really good reason not to. If you're building a bunch of small
383 executables, check out tools/Makefile or tools/security/Makefile; if
384 all the files are in the current directory, changing slashes isn't a
385 big deal, and command-line lengths won't be a problem, so
386 executable.make isn't necessary (and indeed it won't work, since it
387 can only build one .exe in a directory).
388
389 If you're building a library, library.make is highly recommended; the
390 only DLL that doesn't use it is corlib, because building corlib is a
391 fair bit more complicated than it should be. Oh well.
392
393 library.make also automatically supports generating and updating 
394 monodoc documentation.  Documentation is stored within the 
395 Documentation directory (a sibling to the Test directory), and is 
396 generated/updated whenever the doc-update target is executed.  
397 Assembling of the documentation so that the monodoc browser can
398 display the documentation is handled separately within the mcs/docs
399 all-local target; see mcs/docs/Makefile for details.
400
401
402
403
404
405
406 * Running a C# program? Use $(RUNTIME)
407
408 ========================================
409 run-test-local: myprog.exe
410         $(RUNTIME) myprog.exe
411 ========================================
412
413 $(RUNTIME) might be empty (if you're on windows), so don't expect to
414 be able to give it any arguments. If you're on a platform which has an
415 interpreter or jitter, $(RUNTIME_FLAGS) is included in $(RUNTIME), so
416 set that variable.
417
418 $(TEST_RUNTIME) is the runtime to use when running tests. Right now it's
419 just "mono --debug".
420
421
422
423 * Calling the compiler directly? Use $(MCS).
424
425 Really, you should use $(CSCOMPILE) whenever possible, but $(MCS) is
426 out there. $(BOOTSTRAP_MCS) is the C# compiler that we use to build
427 mcs.exe; on Linux, we then use mcs.exe to build everything else, but
428 on Windows, we use csc.exe to build everything. Only use
429 $(BOOTSTRAP_MCS) if you know what you're doing.
430
431
432
433
434
435 * Compiling C code? Use $(CCOMPILE)
436
437 To give it flags, set $(LOCAL_CFLAGS). As with compiling C#, the
438 variable $(CFLAGS) will automatically be included on the command line.
439
440
441
442
443
444 * Documentation-related needs? Use $(MDOC)
445
446 $(MDOC) is a front-end to the monodoc documentation system, supporting
447 documentation generation, updating, importing from Microsoft XML
448 Documentation and ECMA documentation formats, assembling documentation
449 for use within the monodoc documentation browser, and exporting
450 documentation to various other output formats such as static HTML.
451
452 It is currently only used for library.make's doc-update-local target
453 and for assembling documentation within $topdir/docs.
454
455
456
457
458
459 * Installing files? Use $(MKINSTALLDIRS), $(INSTALL_DATA) or
460 $(INSTALL_BIN), $(prefix), and $(DESTDIR).
461
462 Every time a file is installed the commands should look like this:
463
464 ========================================
465 install-local:
466         $(MKINSTALLDIRS) $(DESTDIR)$(prefix)/my/dir
467         $(INSTALL_DATA) myfile $(DESTDIR)$(prefix)/my/dir
468 ========================================
469
470 This way the directory is created recursively if needed (admittedly, we could
471 probably rely on mkdir -p), the file is given the correct permissions,
472 the user can override $(MKINSTALLDIRS) and $(INSTALL) if they need to,
473 and we can support $(DESTDIR) installs. We use $(DESTDIR) to make
474 monocharge tarballs, and it's useful otherwise, so try and use it
475 consistently.
476
477
478
479
480
481 * 'make dist'? Use $(DISTFILES)
482
483 The 'dist-default' target will copy the files listed in $(DISTFILES)
484 into the distribution directory, as well as Makefile and ChangeLog if
485 they exist. This is almost always all that you need, so ideally your
486 make dist support should only be:
487
488 ========================================
489 DISTFILES = README Test/thoughts.txt
490
491 dist-local: dist-default
492 ========================================
493
494 DISTFILES will cope correctly with files in subdirectories, by the
495 way. Note that if you put a nonexistant file or a directory in
496 DISTFILES it will *not* complain; it will just ignore it.
497
498 If you want to test your 'make dist' code, you can try
499
500 ========================================
501 $ cd class/Mono.MyClass
502 $ make dist-local distdir=TEST
503 ========================================
504
505 And your files should be copied into TEST/ in the current directory.
506 There is a toplevel 'make distcheck' target, which will build a dist
507 tarball, try to build it, install files to a temporary prefix, make
508 clean it, make a distribution, and compare the files left over to the
509 files originally in the tarball: they should be the same. But this
510 takes about 15 minutes to run on my 1.1 Ghz computer, so it's not for
511 the faint of heart.
512
513
514
515
516
517 * Lots of files? Use $(wildcard *.foo)
518
519 When specifying the sources to a library or executable, wildcards are
520 not encouraged; in fact they're not allowed if you use library.make or
521 executable.make. But there are times when they're useful, eg:
522
523 ========================================
524 DISTFILES = $(wildcard Test/*.in) $(wildcard Test/*.out)
525 ========================================
526
527 Just so you know that 'make' has this feature.
528
529
530
531
532
533
534 * Referencing files in other directories? Use $(topdir).
535
536 $(topdir) is the path to the top directory from the current build
537 directory. Basically it's a sequence of ../.. computed from the value
538 that you give $(thisdir) at the top of your Makefile. Try to reference
539 things from $(topdir), so your code can be moved or cut-and-pasted
540 around with a minimum of fuss.
541
542
543
544
545
546
547 * Conditional building? Use ifdef/ifndef/endif
548
549 Now in general we want to avoid conditional building, but sometimes
550 something doesn't work on Linux or already exists on Windows or
551 whatnot. (See below on recommended form for how to build
552 platform-specifically.) GNU Make supports the following construction:
553
554 ========================================
555 BUILD_EXPERIMENTAL = yes
556
557 ifdef BUILD_EXPERIMENTAL
558 experimental_stuff = my-experiment.exe
559 else
560 experimental_stuff = 
561 endif
562
563 all-local: my-sane.exe $(experimental_stuff)
564 ========================================
565
566 'ifdef' means 'if the variable is set to nonempty', so you could have 
567
568 ========================================
569 BUILD_EXPERIMENTAL = colorless green ideas sleep furiously
570 ========================================
571
572 and Make would be happy. I hope that the meaning of 'ifndef' should be
573 obvious. If you want to only sometimes build a target, the above
574 construction is the recommended way to go about it; it's nice to have
575 the rules exist in a Makefile even if they aren't invoked.
576
577 If you want to see why conditionals aren't nice, take a look at
578 library.make or class/corlib/Makefile.
579
580
581
582
583
584 * 'Private' directories that shouldn't be built by default? Use DIST_ONLY_SUBDIRS
585
586 Several of the MCS class libraries have demo or experimental
587 implementations that depend on things not included with MCS (say,
588 Gtk#). We don't want to build them by default, because the user might
589 not have those dependencies installed, but it's nice to have a
590 Makefile for them to be built nicely.
591
592 First of all, there's nothing stopping you from writing a Makefile for
593 such a directory; just don't put it in the SUBDIRS line of its parent
594 directory. That way, you can do all the normal build things like 'make
595 all' or 'make clean' in that directory, but people trying to bootstrap
596 their system won't run into problems.
597
598 At the same time you probably want to include this directory in the
599 distribution so that people can use your demo or experimental code if
600 they know what they're doing. Hence the variable
601 $(DIST_ONLY_SUBDIRS). As you might guess, it's like the SUBDIRS
602 variable: it lists subdirectories that a regular shouldn't recurse
603 into, but should have their 'make dist' rules invoked. 
604
605 Say you've written Mono.MyFancyLib.dll and you have
606 a demo app using Gtk# called MyFancyDemo. The Makefile rules might
607 look like this:
608
609 class/Mono.MyFancyLib/Makefile
610 ========================================
611 thisdir = class/Mono.MyFancyLib
612 SUBDIRS =
613 DIST_ONLY_SUBDIRS = MyFancyDemo
614 include ../../build/rules.make
615
616 LIBRARY = Mono.MyFancyLib.dll
617 LIB_MCS_FLAGS = /r:System.dll
618 TEST_MCS_FLAGS = $(LIB_MCS_FLAGS)
619
620 include ../../build/library.make
621 ========================================
622
623 class/Mono.MyFancyLib/MyFancyDemo/Makefile
624 ========================================
625 thisdir = class/Mono.MyFancyLib/MyFancyDemo
626 SUBDIRS =
627 include ../../../build/rules.make
628
629 PROGRAM = FancyDemo.exe
630 LOCAL_MCS_FLAGS = /r:gtk-sharp.dll
631
632 include ../../../build/executable.make
633 ========================================
634
635
636
637
638 * Special recursion needs?
639
640 By default, rules.make defines the all, install, clean, etc. targets
641 to look something like this:
642
643    all: all-recursive
644         $(MAKE) all-local
645
646 Sometimes that doesn't cut it; say for example you want to check for
647 something before doing a lengthy recursive build (see
648 $(topdir)/Makefile) or you have a something like this
649
650         class/MyLibrary:
651                 Build MyLibrary.dll
652         class/MyLibrary/Test:
653                 Build TestMyLibrary.exe
654
655 'make clean test' will fail here, because the build will happen in
656 the Test subdirectory first, so there will be no MyLibrary.dll to link
657 against. (Unless you write a nasty evil relative path rule which is
658 strongly discouraged.)
659
660 Anyway, to solve this problem you can do
661
662 ========================================
663 thisdir = class/MyLibrary
664 SUBDIRS = Test
665 include ../../build/rules.make
666
667 # Normally, make runs 'all-recursive' first, and then 'all-local'
668 # With this, we ensure that 'all-local' is executed first.
669 all-recursive: all-local
670
671 test-recursive: test-local
672 ...
673 ========================================
674
675
676
677
678
679 ** A few implementation details
680
681 The way rules.make does its recursion is very standard; it maps
682 {all,install,clean, dist,test} to $@-recursive, which executes that rule
683 in each directory in $(SUBDIRS), and then calls $@-local in the current
684 directory. So something that gets built in a subdirectory cannot rely on
685 something that gets built in its parent directory. If this is a problem,
686 see the previous section.  Note that the recursive rule for 'dist' is
687 different; it makes dist-recursive in subdirectories, so you at least
688 have to define that rule.
689
690 Note that even a directory that doesn't, for example, have any tests
691 must still define test-local; otherwise 'make test' run from the
692 toplevel directory will break.
693
694
695
696
697
698
699 ** Flags for Tools
700
701 We want to make it so that the user can specify certain flags to
702 always be given to a tool, so there's a general way of implementing
703 FLAGS variables:
704
705         * $(foo_FLAGS) remains unset or defaulted to something
706           sensible; the user can provide overrides this way.
707
708         * $(LOCAL_foo_FLAGS) is set in a specific Makefile to
709           provide necessary values.
710
711         * $(PLATFORM_foo_FLAGS) is set in the platform configuration
712           to provide platform-specific values.
713
714         * $(PROFILE_foo_FLAGS) is set in the profile configuration
715           to provide profile-specific values.
716
717         * $(USE_foo_FLAGS) is defined to be the combination of all of
718           the above, and it's what is actually passed to $(foo).
719
720 $(MCS_FLAGS) and $(CFLAGS) follow this model. If you end up finding
721 that another tool is used commonly (hm, jay...), please follow this form.
722
723
724
725
726
727
728 ** Portability tips
729
730 Always use the icky Windows /argument way of passing parameters to the C#
731 compiler so that csc can be used.
732
733 Always use /r:foo.dll, not /r:foo. Windows requires the former.
734
735 Use /r:$(corlib), not /r:corlib.
736
737 If you're writing shell script code as part of a make rule, remember
738 that Windows has command-line length limits. So something like
739
740 ========================================
741 mytool $(all_the_sources_to_corlib)
742 ========================================
743
744 Is probably going to cause problems. As I understand it, 
745
746 ========================================
747 for f in  $(all_the_sources_to_corlib) ; do ...
748 ========================================
749
750 is ok, since the shell itself doesn't have those limitations. Other
751 than that, you should still try to write fairly portable shell
752 script. Linux and Cygwin both use the GNU utilities, but there's at
753 least one hardy soul trying to build Mono on HP/UX, and no doubt there
754 will be ports to more Unices as time goes on.
755
756
757
758
759
760
761 ** Misc
762
763 We still don't use /d:NET_1_1 ; it causes some build problems right
764 now.
765
766 There's a hack in class/System.Data/Makefile to work around a very
767 strange crash in the runtime with some custom attribute stuff. It'd be
768 nice to fix it.
769
770 Also, there's a /lib:$(prefix)/lib in the System.dll Makefile, which
771 is for some reason necessary if System.Xml.dll hasn't been built yet.
772 (Well, it's necessary because of the /r:System.Xml.dll, but that
773 should be in the search path, it seems.)
774
775 A lot of the weird targets in the old makefiles have been dropped; I
776 have a feeling that a lot of them are archaic and not needed anymore.
777
778 I'd really like to write a build tool in C#. It would be nice to have
779 something really extensible and well-designed and clean. NAnt is,
780 IMHO, an apalling abomination and a tragically bad attempt at solving
781 the software building problem. Just so you know.
782
783 (On the other hand, NUnit is really neat.)
784
785 Peter