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