[Wasm] Fix memory override in mono_wasm_add_assembly
[mono-project.git] / mcs / build / README.makefiles.md
blob974a6472bb1166b0c3e80e52bb45b90d935f3b28
1 # The MCS makefiles
3 Author: Peter Williams <peter@newton.cx>
5 The new makefiles try to abstract building on Windows and Linux. They
6 try to provide a consistent set of ways to express the things that our
7 build system needs to let us do, specifically:
9 * Build recursively
10 * Build libraries and executables easily
11 * Let developers use different runtimes and class libaries
12 * Make distributions easily
13 * Provide a framework for testing
14 * Build platform-independently whenever possible
15 * Generate, update, and build monodoc documentation.
17 Makefile structure
18 ==================
20 A general makefile looks like this:
22 ```
23 thisdir = class/Mono.My.Library
24 SUBDIRS =
25 include ../../build/rules.make
27 all-local:
28         do some stuff
30 install-local:
31         $(MKINSTALLDIRS) $(DESTDIR)$(prefix)/share/
32         $(INSTALL_DATA) myfile.txt $(DESTDIR)$(prefix)/share/myfiledir
34 clean-local:
35         rm -f my-generated-file
37 test-local: my_test_program.exe
39 run-test-local:
40         $(RUNTIME) my_test_program.exe
42 run-test-ondotnet-local:
43         $(RUNTIME) my_test_program.exe
45 DISTFILES = myfile.txt my_test_source.cs
47 dist-local: dist-default
49 doc-update-local:
51 my_test_program.exe: my_test_source.cs
52         $(CSCOMPILE) /target:exe /out:$@ $<
53 ```
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`.
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.
64 The eight targets do the following:
66 * `all-local` builds whatever someone would expect to be built
67   when they just type `make'` Most likely `Foo.dll` or `Foo.exe`
69 * `install-local` installs whatever got built by `all-local`.
71 * `test-local` _builds_ the test programs or libraries but does
72   _not_ run them.
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.
82 * `run-xunit-test-local` this is a variation of the above, but it runs the
83   tests that were built with Xunit instead of NUnit.
85 * `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.
87 * `clean-local` removes built files; `make clean` should leave
88   only files that go into a distribution tarball. (But it is not
89   necessarily true that all files that go into a tarball need to be left
90   after a make clean.)
92 * `dist-local` copies files into the distribution tree, which is
93   given by the variable `$(distdir)`. `dist-local` always depends on the
94   target `dist-default`.  See ** `make dist` below.
96 * `doc-update-local` should generate or update monodoc documentation,
97   if appropriate.  This is usually only appropriate for libraries.  It's
98   defined as a standard target so that it can easily be run recursively
99   across all libraries within the module.
101 Build configuration
102 ===================
104 In general, MCS needs to be able to build relying only on the
105 existence of a runtime and core libraries (`mscorlib`, `System`,
106 `System.Xml`).  So there shouldn't be any checking for libraries or
107 whatnot; MCS should be able to build out of the box. We try to keep
108 platform detection and feature testing (ie, for HP/UX echo) inside
109 the makefiles; right now, there's no configuration script, and it'd
110 be nice to keep it that way. (I am told that some people build on
111 both Windows and Linux in the same tree, which would be impossible to
112 do if we cached platform-related configury values.)
114 That being said, it's very convenient for developers to be able to
115 customize their builds to suit their needs. To allow this, the
116 Makefile rules are set up to allow people to override pretty much any
117 important variable.
119 Configuration variables are given defaults in `config-default.make`;
120 `rules.make` optionally includes `$(topdir)/build/config.make`, so you
121 can customize your build without CVS trying to commit your modified
122 `config-default.make` all the time.  Platform-specific variables are
123 defined in `$(topdir)/build/platforms/$(BUILD_PLATFORM).make`, where
124 `$(BUILD_PLATFORM)` is detected in `config-default.make`. (Currently, the only
125 choices are `linux.make` and `win32.make`)
127 The best way to learn what the configuration variables are is to read
128 `config.make` and `platform.make`. There aren't too many and hopefully
129 they should be self-explanatory; see the numerous examples below for
130 more information if you're confused.
132 Recommendations for platform specifics
133 --------------------------------------
135 If you find yourself needing a platform-specific customization, try
136 and express it in terms of a feature, rather than a platform test. In
137 other words, this is good:
140 run-test-local: my-test.exe
141 ifdef PLATFORM_NEEDS_CRAZY_CRAP
142         crazy-crap
143 endif
144         $(RUNTIME) my-test.exe
147 and this is bad:
150 run-test-local: my-test.exe
151 ifdef WINDOWS
152         crazy-crap
153 else
154 ifdef AMIGA
155         crazy-crap
156 endif
157 endif
158         $(RUNTIME) my-test.exe
161 The latter accumulates and gets unpleasant and it sucks. Granted,
162 right now we only have two platforms, so it's not a big deal, but it's
163 good form to get used to and practice. Anyway, take a look at how we
164 do the various corlib building hacks for examples of how we've done
165 platform-specificity. It certainly isn't pretty, but at least it's a
166 little structured.
168 Saving effort
169 =============
171 The point of the build system is to abstract things and take
172 care of all the easy stuff. So if you find yourself writing a
173 Makefile, know that there's probably already infrastructure to do what
174 you want. Here are all the common cases I can think of.
176 Compiling C# code? use:
177 -----------------------
180 my-program.exe: my-source.cs
181          $(CSCOMPILE) /target:exe /out:$@ $^
187 my-lib.dll: my-source.cs
188          $(CSCOMPILE) /target:library /out:$@ $^
191 Note the `$@` and `$^` variables. The former means "the name of the
192 file that I am trying to make" and the latter means "all the
193 dependencies of the file I am trying to make." USE THESE VARIABLES
194 AGGRESSIVELY. Say that you add a new source to your program:
197 my-program.exe: my-source.cs my-new-source.cs
198          $(CSCOMPILE) /target:exe /out:$@ $^
201 Because of the $^ variable, you don't need to remember to add another
202 file to the command line. Similarly, if you rename your program, you
203 won't need to remember to change the rule:
206 MonoVaporizer.exe: my-source.cs my-new-source.cs
207          $(CSCOMPILE) /target:exe /out:$@ $^
210 will still work. Another useful variable is $<, which means "the first
211 dependency of whatever I'm building." If you order your dependencies
212 carefully it can be extremely useful.
214 Just building an executable? 
215 ----------------------------
217 Then use:
220 PROGRAM = myprogram.exe
221 LOCAL_MCS_FLAGS = /r:System.Xml.dll
223 include ../build/executable.make
226 executable.make builds a program in the current directory. Its name is
227 held in `$(PROGRAM)`, and its sources are listed in the file
228 `$(PROGRAM).sources`. It might seem to make more sense to just list the
229 program's sources in the Makefile, but when we build on Windows we
230 need to change slashes around, which is much easier to do if the
231 sources are listed in a file. The variable `$(LOCAL_MCS_FLAGS)` changes
232 the flags given to the compiler; it is included in `$(CSCOMPILE)` so you
233 don't need to worry about it.
235 `executable.make` does a lot for you: it builds the program in 'make
236 all-local', installs the program in `$(prefix)/bin`, distributes the
237 sources, and defines empty test targets. Now, if your program has a
238 test, set the variable `HAS_TEST`:
241 PROGRAM = myprogram.exe
242 LOCAL_MCS_FLAGS = /r:System.Xml.dll
243 HAS_TEST = yes
244 include ../build/executable.make
246 test-local: mytester.exe
248 run-test-local: mytester.exe
249         $(RUNTIME) $<
251 mytester.exe: mytester.cs
252         $(CSCOMPILE) /target:exe /out:$@ mytester.cs
255 If your program has NUnit tests, set the variable `HAS_NUNIT_TEST`:
258 PROGRAM = myprogram.exe
259 LOCAL_MCS_FLAGS = /r:System.Xml.dll
260 HAS_NUNIT_TEST = yes
261 include ../build/executable.make
264 `HAS_NUNIT_TEST` tests follow `library.make` NUnit test conventions: 
265 the files should be in a subdirectory called `Test/`, and if
266 your program is called `myprogram.exe`, they should be listed in
267 `myprogram_test.dll.sources`. The names in that files should *not* have
268 the `Test/` prefix. `make test'`will build `myprogram_test_$(PROFILE).dll` 
269 in the current directory, automatically supplying the flags to 
270 reference the original program and `NUnit.Framework.dll`.
272 If your program has 'built sources', that is, source files generated
273 from other files (say, generated by jay), define a variable called
274 `BUILT_SOURCES` and do *not* list the sources in `$(PROGRAM).sources`:
277 PROGRAM = myprogram.exe
278 LOCAL_MCS_FLAGS = /r:System.Xml.dll
279 BUILT_SOURCES = parser.cs
280 CLEAN_FILES = y.output
282 include ../build/executable.make
284 parser.cs: parser.jay
285         $(topdir)/jay/jay $< > $@
288 `executable.make` will automatically delete the `$(BUILT_SOURCES)` files
289 on `make clean`. Since this situation is a common occurrence and jay
290 happens to leave behind y.output files, you can also define a variable
291 called `$(CLEAN_FILES)` that lists extra files to be deleted when
292 `make clean` is called. (That's in addition to your executable and the built sources).
294 Buildling a library? Use
295 ------------------------
298 LIBRARY = Mono.MyLib.dll
299 LIB_MCS_FLAGS = /unsafe
300 TEST_MCS_FLAGS = /r:System.Xml.dll
302 include ../../build/library.make
305 Where you library is called `$(LIBRARY)`; it will be put into
306 `$(topdir)/class/lib`. `LIB_MCS_FLAGS` is the set of MCS flags to use when
307 compiling the library; in addition, a global set of flags called
308 `$(LIBRARY_FLAGS)` is added (that variable is defined in
309 `config-defaults.make`), as well as the usual `$(LOCAL_MCS_FLAGS)`.
311 As in `executable.make`, the sources for your library are listed in
312 `$(LIBRARY).sources`. Note: these source lists should have Unix forward
313 slashes and Unix newlines (\n, not \r\n.) If you get an error about
314 "touch: need a filename", that means your .sources file doesn't end in
315 a newline. It should.
317 Now `library.make` also assumes that your library has an NUnit2 test
318 harness. The files should be in a subdirectory called `Test/`, and if
319 your library is called `Mono.Foo.dll`, they should be listed in
320 `Mono.Foo_test.dll.sources`. The names in that files should *not* have
321 the `Test/` prefix. `make test` will build `Mono.Foo_test.dll` in the
322 current directory, automatically supplying the flags to reference the
323 original library and `NUnit.Framework.dll`.
325 If you don't have a test, just do this:
328 LIBRARY = Mono.MyLib.dll
329 LIB_MCS_FLAGS = /unsafe
330 NO_TEST = yes
332 include ../../build/library.make
335 and feel ashamed. Every good library has a test suite!
337 Extra flags needed to compile the test library should be listed in
338 $(TEST_MCS_FLAGS); often you will have a line like this:
341 TEST_MCS_FLAGS = $(LIB_MCS_FLAGS)
344 Again, `library.make` does a lot for you: it builds the dll, it
345 generates makefile fragments to track the dependencies, it installs
346 the library, it builds the test dll on `make test`, it runs
347 `$(TEST_HARNESS)` on it on `make run-test`, it removes the appropriate
348 files on 'make clean', and it distributes all the source files on
349 `make dist`. (`TEST_HARNESS` defaults to be `nunit-console.exe` but it may
350 be overridden to, say, `nunit-gtk`). If you have extra files to
351 distribute when using either `library.make` or `executable.make`, use the
352 variable `$(EXTRA_DISTFILES)`:
355 EXTRA_DISTFILES = \
356         Test/testcase1.in               \
357         Test/testcase1.out              \
358         README
361 Again, `library.make` and `executable.make` do the right things so that we
362 can build on Windows, doing some trickery to invert slashes and
363 overcome command-line length limitations. Use them unless you have a
364 really good reason not to. If you're building a bunch of small
365 executables, check out `tools/Makefile` or `tools/security/Makefile`; if
366 all the files are in the current directory, changing slashes isn't a
367 big deal, and command-line lengths won't be a problem, so
368 executable.make isn't necessary (and indeed it won't work, since it
369 can only build one .exe in a directory).
371 If you're building a library, `library.make` is highly recommended; the
372 only DLL that doesn't use it is corlib, because building corlib is a
373 fair bit more complicated than it should be. Oh well.
375 `library.make` also automatically supports generating and updating 
376 monodoc documentation.  Documentation is stored within the 
377 Documentation directory (a sibling to the Test directory), and is 
378 generated/updated whenever the doc-update target is executed.  
379 Assembling of the documentation so that the monodoc browser can
380 display the documentation is handled separately within the mcs/docs
381 all-local target; see mcs/docs/Makefile for details.
383 Running a C# program? Use $(RUNTIME)
384 ------------------------------------
387 run-test-local: myprog.exe
388         $(RUNTIME) myprog.exe
391 `$(RUNTIME)` might be empty (if you're on windows), so don't expect to
392 be able to give it any arguments. If you're on a platform which has an
393 interpreter or jitter, $(RUNTIME_FLAGS) is included in $(RUNTIME), so
394 set that variable.
396 $(TEST_RUNTIME) is the runtime to use when running tests. Right now it's
397 just "mono --debug".
401 Calling the compiler directly? Use $(MCS).
402 ------------------------------------------
404 Really, you should use $(CSCOMPILE) whenever possible, but $(MCS) is
405 out there. $(BOOTSTRAP_MCS) is the C# compiler that we use to build
406 mcs.exe; on Linux, we then use mcs.exe to build everything else, but
407 on Windows, we use csc.exe to build everything. Only use
408 $(BOOTSTRAP_MCS) if you know what you're doing.
410 Compiling C code? Use $(CCOMPILE)
411 ---------------------------------
413 To give it flags, set $(LOCAL_CFLAGS). As with compiling C#, the
414 variable $(CFLAGS) will automatically be included on the command line.
417 Compiling resources with resgen
418 -------------------------------
420 If you have a resource that should be compiled with resgen and
421 included in your assembly, you can use the RESOURCES_DEFS variable.
422 This variable can contain lists of pairs that are separated by comma
423 to represent the resource ID as embedded in the assembly followed by
424 the file name, like this:
426 RESOURCE_DEFS = Messages,TextResources.resx Errors,ErrorList.txt
429 Documentation-related needs? Use $(MDOC)
430 ----------------------------------------
432 $(MDOC) is a front-end to the monodoc documentation system, supporting
433 documentation generation, updating, importing from Microsoft XML
434 Documentation and ECMA documentation formats, assembling documentation
435 for use within the monodoc documentation browser, and exporting
436 documentation to various other output formats such as static HTML.
438 It is currently only used for library.make's doc-update-local target
439 and for assembling documentation within $topdir/docs.
441 Installing files? Use $(MKINSTALLDIRS), $(INSTALL_DATA) or $(INSTALL_BIN), $(prefix), and $(DESTDIR).
442 -----------------------------------------------------------------------------------------------------
444 Every time a file is installed the commands should look like this:
447 install-local:
448         $(MKINSTALLDIRS) $(DESTDIR)$(prefix)/my/dir
449         $(INSTALL_DATA) myfile $(DESTDIR)$(prefix)/my/dir
452 This way the directory is created recursively if needed (admittedly, we could
453 probably rely on mkdir -p), the file is given the correct permissions,
454 the user can override $(MKINSTALLDIRS) and $(INSTALL) if they need to,
455 and we can support $(DESTDIR) installs. We use $(DESTDIR) to make
456 monocharge tarballs, and it's useful otherwise, so try and use it
457 consistently.
459 'make dist'? Use $(DISTFILES)
460 -----------------------------
462 The 'dist-default' target will copy the files listed in $(DISTFILES)
463 into the distribution directory, as well as Makefile and ChangeLog if
464 they exist. This is almost always all that you need, so ideally your
465 make dist support should only be:
468 DISTFILES = README Test/thoughts.txt
470 dist-local: dist-default
473 DISTFILES will cope correctly with files in subdirectories, by the
474 way. Note that if you put a nonexistant file or a directory in
475 DISTFILES it will *not* complain; it will just ignore it.
477 If you want to test your 'make dist' code, you can try
480 $ cd class/Mono.MyClass
481 $ make dist-local distdir=TEST
484 And your files should be copied into TEST/ in the current directory.
485 There is a toplevel 'make distcheck' target, which will build a dist
486 tarball, try to build it, install files to a temporary prefix, make
487 clean it, make a distribution, and compare the files left over to the
488 files originally in the tarball: they should be the same. But this
489 takes about 15 minutes to run on my 1.1 Ghz computer, so it's not for
490 the faint of heart.
492 Lots of files? Use $(wildcard *.foo)
493 ------------------------------------
495 When specifying the sources to a library or executable, wildcards are
496 not encouraged; in fact they're not allowed if you use library.make or
497 executable.make. But there are times when they're useful, eg:
500 DISTFILES = $(wildcard Test/*.in) $(wildcard Test/*.out)
503 Just so you know that `make` has this feature.
505 Referencing files in other directories? Use $(topdir).
506 ------------------------------------------------------
508 $(topdir) is the path to the top directory from the current build
509 directory. Basically it's a sequence of ../.. computed from the value
510 that you give $(thisdir) at the top of your Makefile. Try to reference
511 things from $(topdir), so your code can be moved or cut-and-pasted
512 around with a minimum of fuss.
514 Conditional building? Use ifdef/ifndef/endif
515 --------------------------------------------
517 Now in general we want to avoid conditional building, but sometimes
518 something doesn't work on Linux or already exists on Windows or
519 whatnot. (See below on recommended form for how to build
520 platform-specifically.) GNU Make supports the following construction:
523 BUILD_EXPERIMENTAL = yes
525 ifdef BUILD_EXPERIMENTAL
526 experimental_stuff = my-experiment.exe
527 else
528 experimental_stuff = 
529 endif
531 all-local: my-sane.exe $(experimental_stuff)
534 'ifdef' means 'if the variable is set to nonempty', so you could have 
537 BUILD_EXPERIMENTAL = colorless green ideas sleep furiously
540 and Make would be happy. I hope that the meaning of 'ifndef' should be
541 obvious. If you want to only sometimes build a target, the above
542 construction is the recommended way to go about it; it's nice to have
543 the rules exist in a Makefile even if they aren't invoked.
545 If you want to see why conditionals aren't nice, take a look at
546 library.make or class/corlib/Makefile.
549 'Private' directories that shouldn't be built by default? Use DIST_ONLY_SUBDIRS
550 --------------------------------------------------------------------------------
552 Several of the MCS class libraries have demo or experimental
553 implementations that depend on things not included with MCS (say,
554 Gtk#). We don't want to build them by default, because the user might
555 not have those dependencies installed, but it's nice to have a
556 Makefile for them to be built nicely.
558 First of all, there's nothing stopping you from writing a Makefile for
559 such a directory; just don't put it in the SUBDIRS line of its parent
560 directory. That way, you can do all the normal build things like 'make
561 all' or 'make clean' in that directory, but people trying to bootstrap
562 their system won't run into problems.
564 At the same time you probably want to include this directory in the
565 distribution so that people can use your demo or experimental code if
566 they know what they're doing. Hence the variable
567 $(DIST_ONLY_SUBDIRS). As you might guess, it's like the SUBDIRS
568 variable: it lists subdirectories that a regular shouldn't recurse
569 into, but should have their 'make dist' rules invoked. 
571 Say you've written Mono.MyFancyLib.dll and you have
572 a demo app using Gtk# called MyFancyDemo. The Makefile rules might
573 look like this:
575 class/Mono.MyFancyLib/Makefile
577 thisdir = class/Mono.MyFancyLib
578 SUBDIRS =
579 DIST_ONLY_SUBDIRS = MyFancyDemo
580 include ../../build/rules.make
582 LIBRARY = Mono.MyFancyLib.dll
583 LIB_MCS_FLAGS = /r:System.dll
584 TEST_MCS_FLAGS = $(LIB_MCS_FLAGS)
586 include ../../build/library.make
589 class/Mono.MyFancyLib/MyFancyDemo/Makefile
591 thisdir = class/Mono.MyFancyLib/MyFancyDemo
592 SUBDIRS =
593 include ../../../build/rules.make
595 PROGRAM = FancyDemo.exe
596 LOCAL_MCS_FLAGS = /r:gtk-sharp.dll
598 include ../../../build/executable.make
604 Special recursion needs?
605 ------------------------
607 By default, rules.make defines the all, install, clean, etc. targets
608 to look something like this:
611    all: all-recursive
612         $(MAKE) all-local
615 Sometimes that doesn't cut it; say for example you want to check for
616 something before doing a lengthy recursive build (see
617 $(topdir)/Makefile) or you have a something like this
620         class/MyLibrary:
621                 Build MyLibrary.dll
622         class/MyLibrary/Test:
623                 Build TestMyLibrary.exe
626 `make clean test` will fail here, because the build will happen in
627 the Test subdirectory first, so there will be no `MyLibrary.dll` to link
628 against. (Unless you write a nasty evil relative path rule which is
629 strongly discouraged.)
631 Anyway, to solve this problem you can do
634 thisdir = class/MyLibrary
635 SUBDIRS = Test
636 include ../../build/rules.make
638 # Normally, make runs 'all-recursive' first, and then 'all-local'
639 # With this, we ensure that 'all-local' is executed first.
640 all-recursive: all-local
642 test-recursive: test-local
647 A few implementation details
648 ----------------------------
650 The way rules.make does its recursion is very standard; it maps
651 `{all,install,clean,dist,test}` to `$@-recursive`, which executes that rule
652 in each directory in `$(SUBDIRS)`, and then calls `$@-local` bin the current
653 directory. So something that gets built in a subdirectory cannot rely on
654 something that gets built in its parent directory. If this is a problem,
655 see the previous section.  Note that the recursive rule for 'dist' is
656 different; it makes dist-recursive in subdirectories, so you at least
657 have to define that rule.
659 Note that even a directory that doesn't, for example, have any tests
660 must still define test-local; otherwise 'make test' run from the
661 toplevel directory will break.
663 Flags for Tools
664 ---------------
666 We want to make it so that the user can specify certain flags to
667 always be given to a tool, so there's a general way of implementing
668 FLAGS variables:
670 * `$(foo_FLAGS)` remains unset or defaulted to something
671   sensible; the user can provide overrides this way.
673 * `$(LOCAL_foo_FLAGS)` is set in a specific Makefile to
674   provide necessary values.
676 * `$(PLATFORM_foo_FLAGS)` is set in the platform configuration
677   to provide platform-specific values.
679 * `$(PROFILE_foo_FLAGS)` is set in the profile configuration
680   to provide profile-specific values.
682 * `$(USE_foo_FLAGS)` is defined to be the combination of all of
683   the above, and it's what is actually passed to $(foo).
685 `$(MCS_FLAGS)` and `$(CFLAGS)` follow this model. If you end up finding
686 that another tool is used commonly (hm, jay...), please follow this form.
688 Portability tips
689 ----------------
691 Always use the icky Windows /argument way of passing parameters to the C#
692 compiler so that csc can be used.
694 Always use `/r:foo.dll`, not `/r:foo`. Windows requires the former.
696 Use `/r:$(corlib)`, not `/r:corlib`.
698 If you're writing shell script code as part of a make rule, remember
699 that Windows has command-line length limits. So something like
702 mytool $(all_the_sources_to_corlib)
705 Is probably going to cause problems. As I understand it, 
708 for f in  $(all_the_sources_to_corlib) ; do ...
711 is ok, since the shell itself doesn't have those limitations. Other
712 than that, you should still try to write fairly portable shell
713 script. Linux and Cygwin both use the GNU utilities, but there's at
714 least one hardy soul trying to build Mono on HP/UX, and no doubt there
715 will be ports to more Unices as time goes on.
722 Misc
723 ----
725 We still don't use `/d:NET_1_1`; it causes some build problems right
726 now.
728 There's a hack in class/System.Data/Makefile to work around a very
729 strange crash in the runtime with some custom attribute stuff. It'd be
730 nice to fix it.
732 Also, there's a /lib:$(prefix)/lib in the System.dll Makefile, which
733 is for some reason necessary if System.Xml.dll hasn't been built yet.
734 (Well, it's necessary because of the /r:System.Xml.dll, but that
735 should be in the search path, it seems.)
737 A lot of the weird targets in the old makefiles have been dropped; I
738 have a feeling that a lot of them are archaic and not needed anymore.
740 I'd really like to write a build tool in C#. It would be nice to have
741 something really extensible and well-designed and clean. NAnt is,
742 IMHO, an apalling abomination and a tragically bad attempt at solving
743 the software building problem. Just so you know.
745 (On the other hand, NUnit is really neat.)
747 Peter