Forgot to commit ChangeLog
[mcs.git] / build / README.makefiles
blob7460e88ff3809814d549e1afa40688e98d08e1dd
1 The MCS makefiles (-*- outline -*-)
2 Peter Williams <peter@newton.cx>
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:
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
19 ** Makefile structure
21 A general makefile looks like this:
23 ========================================
24 thisdir = class/Mono.My.Library
25 SUBDIRS =
26 include ../../build/rules.make
28 all-local:
29         do some stuff
31 install-local:
32         $(MKINSTALLDIRS) $(DESTDIR)$(prefix)/share/
33         $(INSTALL_DATA) myfile.txt $(DESTDIR)$(prefix)/share/myfiledir
35 clean-local:
36         rm -f my-generated-file
38 test-local: my_test_program.exe
40 run-test-local:
41         $(RUNTIME) my_test_program.exe
43 run-test-ondotnet-local:
44         $(RUNTIME) my_test_program.exe
46 DISTFILES = myfile.txt my_test_source.cs
48 dist-local: dist-default
50 my_test_program.exe: my_test_source.cs
51         $(CSCOMPILE) /target:exe /out:$@ $<
52 ========================================
54 Each makefile follows the same pattern: it does some setup, includes
55 the standard make rules, and provides rules for seven standard targets:
56 all, install, test, run-test, clean, and dist.
58 "Some setup" is defining two variables: $(thisdir) and
59 $(SUBDIRS). $(thisdir) is the directory that the makefile lives in,
60 relative to the top directory (ie, class/corlib) and $(SUBDIRS)
61 defines the subdirectories that should be built in.
63 The seven targets do the following:
65         * all-local builds whatever someone would expect to be built
66 when they just type 'make'. Most likely Foo.dll or Foo.exe
68         * install-local installs whatever got built by all-local.
70         * test-local _builds_ the test programs or libraries but does
71 _not_ run them.
73         * run-test-local actually runs the tests. It shouldn't
74 necessarily exit in an error if the test fails, but should make that
75 situation obvious. It should only run tests that take care of
76 themselves automatically; interactive tests should have an individual
77 target. The idea is that 'make run-test' from the toplevel should be
78 able to proceed unsupervised and test everything that can be tested in
79 such a manner.
81         * 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         * clean-local removes built files; 'make clean' should leave
84 only files that go into a distribution tarball. (But it is not necessarily
85 true that all files that go into a tarball need to be left after a make clean.)
87         * dist-local copies files into the distribution tree, which is
88 given by the variable $(distdir). dist-local always depends on the
89 target 'dist-default'. See ** 'make dist' below.
95 ** Build configuration
97 In general, MCS needs to be able to build relying only on the
98 existence of a runtime and core libraries (corlib, System,
99 System.Xml). So there shouldn't be any checking for libraries or
100 whatnot; MCS should be able to build out of the box. We try to keep
101 platform detection and feature testing (ie, for HP/UX echo) inside
102 the makefiles; right now, there's no configuration script, and it'd
103 be nice to keep it that way. (I am told that some people build on
104 both Windows and Linux in the same tree, which would be impossible to
105 do if we cached platform-related configury values.)
107 That being said, it's very convenient for developers to be able to
108 customize their builds to suit their needs. To allow this, the
109 Makefile rules are set up to allow people to override pretty much any
110 important variable.
112 Configuration variables are given defaults in `config-default.make';
113 `rules.make' optionally includes `$(topdir)/build/config.make', so you
114 can customize your build without CVS trying to commit your modified
115 `config-default.make' all the time.  Platform-specific variables are
116 defined in `$(topdir)/build/platforms/$(PLATFORM).make', where
117 $(PLATFORM) is detected in config-default.make. (Currently, the only
118 choices are linux.make and win32.make.)
120 The best way to learn what the configuration variables are is to read
121 `config.make' and `platform.make'. There aren't too many and hopefully
122 they should be self-explanatory; see the numerous examples below for
123 more information if you're confused.
130 ** Recommendations for platform specifics
132 If you find yourself needing a platform-specific customization, try
133 and express it in terms of a feature, rather than a platform test. In
134 other words, this is good:
136 ========================================
137 run-test-local: my-test.exe
138 ifdef PLATFORM_NEEDS_CRAZY_CRAP
139         crazy-crap
140 endif
141         $(RUNTIME) my-test.exe
142 ========================================
144 and this is bad:
146 ========================================
147 run-test-local: my-test.exe
148 ifdef WINDOWS
149         crazy-crap
150 else
151 ifdef AMIGA
152         crazy-crap
153 endif
154 endif
155         $(RUNTIME) my-test.exe
156 ========================================
158 The latter accumulates and gets unpleasant and it sucks. Granted,
159 right now we only have two platforms, so it's not a big deal, but it's
160 good form to get used to and practice. Anyway, take a look at how we
161 do the various corlib building hacks for examples of how we've done
162 platform-specificity. It certainly isn't pretty, but at least it's a
163 little structured.
170 ** Saving effort
172         The point of the build system is to abstract things and take
173 care of all the easy stuff. So if you find yourself writing a
174 Makefile, know that there's probably already infrastructure to do what
175 you want. Here are all the common cases I can think of ...
182 * Compiling C# code? use:
184 ========================================
185 my-program.exe: my-source.cs
186          $(CSCOMPILE) /target:exe /out:$@ $^
187 ========================================
189         or
191 ========================================
192 my-lib.dll: my-source.cs
193          $(CSCOMPILE) /target:library /out:$@ $^
194 ========================================
196 Note the '$@' and '$^' variables. The former means "the name of the
197 file that I am trying to make" and the latter means "all the
198 dependencies of the file I am trying to make." USE THESE VARIABLES
199 AGGRESSIVELY. Say that you add a new source to your program:
201 ========================================
202 my-program.exe: my-source.cs my-new-source.cs
203          $(CSCOMPILE) /target:exe /out:$@ $^
204 ========================================
206 Because of the $^ variable, you don't need to remember to add another
207 file to the command line. Similarly, if you rename your program, you
208 won't need to remember to change the rule:
210 ========================================
211 MonoVaporizer.exe: my-source.cs my-new-source.cs
212          $(CSCOMPILE) /target:exe /out:$@ $^
213 ========================================
215 will still work. Another useful variable is $<, which means "the first
216 dependency of whatever I'm building." If you order your dependencies
217 carefully it can be extremely useful.
223 * Just building an executable? use:
225 ========================================
226 PROGRAM = myprogram.exe
227 LOCAL_MCS_FLAGS = /r:System.Xml.dll
229 include ../build/executable.make
230 ========================================
232 executable.make builds a program in the current directory. Its name is
233 held in $(PROGRAM), and its sources are listed in the file
234 $(PROGRAM).sources. It might seem to make more sense to just list the
235 program's sources in the Makefile, but when we build on Windows we
236 need to change slashes around, which is much easier to do if the
237 sources are listed in a file. The variable $(LOCAL_MCS_FLAGS) changes
238 the flags given to the compiler; it is included in $(CSCOMPILE) so you
239 don't need to worry about it.
241 executable.make does a lot for you: it builds the program in 'make
242 all-local', installs the program in $(prefix)/bin, distributes the
243 sources, and defines empty test targets. Now, if your program has a
244 test, set the variable HAS_TEST:
246 ========================================
247 PROGRAM = myprogram.exe
248 LOCAL_MCS_FLAGS = /r:System.Xml.dll
249 HAS_TEST = yes
250 include ../build/executable.make
252 test-local: mytester.exe
254 run-test-local: mytester.exe
255         $(RUNTIME) $<
257 mytester.exe: mytester.cs
258         $(CSCOMPILE) /target:exe /out:$@ mytester.cs
259 ========================================
261 If your program has 'built sources', that is, source files generated
262 from other files (say, generated by jay), define a variable called
263 BUILT_SOURCES and do *not* list the sources in $(PROGRAM).sources:
265 ========================================
266 PROGRAM = myprogram.exe
267 LOCAL_MCS_FLAGS = /r:System.Xml.dll
268 BUILT_SOURCES = parser.cs
269 CLEAN_FILES = y.output
271 include ../build/executable.make
273 parser.cs: parser.jay
274         $(topdir)/jay/jay $< > $@
275 ========================================
277 executable.make will automatically delete the $(BUILT_SOURCES) files
278 on 'make clean'. Since this situation is a common occurrence and jay
279 happens to leave behind y.output files, you can also define a variable
280 called $(CLEAN_FILES) that lists extra files to be deleted when 'make clean' is
281 called. (That's in addition to your executable and the built sources).
288 * Buildling a library? Use
290 ========================================
291 LIBRARY = Mono.MyLib.dll
292 LIB_MCS_FLAGS = /unsafe
293 TEST_MCS_FLAGS = /r:System.Xml.dll
295 include ../../build/library.make
296 ========================================
298 Where you library is called $(LIBRARY); it will be put into
299 $(topdir)/class/lib. LIB_MCS_FLAGS is the set of MCS flags to use when
300 compiling the library; in addition, a global set of flags called
301 $(LIBRARY_FLAGS) is added (that variable is defined in
302 config-defaults.make), as well as the usual $(LOCAL_MCS_FLAGS).
304 As in executable.make, the sources for your library are listed in
305 $(LIBRARY).sources. Note: these source lists should have Unix forward
306 slashes and Unix newlines (\n, not \r\n.) If you get an error about
307 "touch: need a filename", that means your .sources file doesn't end in
308 a newline. It should.
310 Now library.make also assumes that your library has an NUnit2 test
311 harness. The files should be in a subdirectory called Test/, and if
312 your library is called Mono.Foo.dll, they should be listed in
313 Mono.Foo_test.dll.sources. The names in that files should *not* have
314 the Test/ prefix. 'make test' will build Mono.Foo_test.dll in the
315 current directory, automatically supplying the flags to reference the
316 original library and NUnit.Framework.dll. 
318 If you don't have a test, just do this:
320 ========================================
321 LIBRARY = Mono.MyLib.dll
322 LIB_MCS_FLAGS = /unsafe
323 NO_TEST = yes
325 include ../../build/library.make
326 ========================================
328 and feel ashamed. Every good library has a test suite!
330 Extra flags needed to compile the test library should be listed in
331 $(TEST_MCS_FLAGS); often you will have a line like this:
333 ========================================
334 TEST_MCS_FLAGS = $(LIB_MCS_FLAGS)
335 ========================================
337 Again, library.make does a lot for you: it builds the dll, it
338 generates makefile fragments to track the dependencies, it installs
339 the library, it builds the test dll on 'make test', it runs
340 $(TEST_HARNESS) on it on 'make run-test', it removes the appropriate
341 files on 'make clean', and it distributes all the source files on
342 'make dist'. (TEST_HARNESS defaults to be nunit-console.exe but it may
343 be overridden to, say, nunit-gtk). If you have extra files to
344 distribute when using either library.make or executable.make, use the
345 variable $(EXTRA_DISTFILES):
347 ========================================
348 EXTRA_DISTFILES = \
349         Test/testcase1.in               \
350         Test/testcase1.out              \
351         README
352 ========================================
354 Again, library.make and executable.make do the right things so that we
355 can build on Windows, doing some trickery to invert slashes and
356 overcome command-line length limitations. Use them unless you have a
357 really good reason not to. If you're building a bunch of small
358 executables, check out tools/Makefile or tools/security/Makefile; if
359 all the files are in the current directory, changing slashes isn't a
360 big deal, and command-line lengths won't be a problem, so
361 executable.make isn't necessary (and indeed it won't work, since it
362 can only build one .exe in a directory).
364 If you're building a library, library.make is highly recommended; the
365 only DLL that doesn't use it is corlib, because building corlib is a
366 fair bit more complicated than it should be. Oh well.
373 * Running a C# program? Use $(RUNTIME)
375 ========================================
376 run-test-local: myprog.exe
377         $(RUNTIME) myprog.exe
378 ========================================
380 $(RUNTIME) might be empty (if you're on windows), so don't expect to
381 be able to give it any arguments. If you're on a platform which has an
382 interpreter or jitter, $(RUNTIME_FLAGS) is included in $(RUNTIME), so
383 set that variable.
385 $(TEST_RUNTIME) is the runtime to use when running tests. Right now it's
386 just "mono --debug".
390 * Calling the compiler directly? Use $(MCS).
392 Really, you should use $(CSCOMPILE) whenever possible, but $(MCS) is
393 out there. $(BOOTSTRAP_MCS) is the C# compiler that we use to build
394 mcs.exe; on Linux, we then use mcs.exe to build everything else, but
395 on Windows, we use csc.exe to build everything. Only use
396 $(BOOTSTRAP_MCS) if you know what you're doing.
402 * Compiling C code? Use $(CCOMPILE)
404 To give it flags, set $(LOCAL_CFLAGS). As with compiling C#, the
405 variable $(CFLAGS) will automatically be included on the command line.
411 * Installing files? Use $(MKINSTALLDIRS), $(INSTALL_DATA) or
412 $(INSTALL_BIN), $(prefix), and $(DESTDIR).
414 Every time a file is installed the commands should look like this:
416 ========================================
417 install-local:
418         $(MKINSTALLDIRS) $(DESTDIR)$(prefix)/my/dir
419         $(INSTALL_DATA) myfile $(DESTDIR)$(prefix)/my/dir
420 ========================================
422 This way the directory is created recursively if needed (admittedly, we could
423 probably rely on mkdir -p), the file is given the correct permissions,
424 the user can override $(MKINSTALLDIRS) and $(INSTALL) if they need to,
425 and we can support $(DESTDIR) installs. We use $(DESTDIR) to make
426 monocharge tarballs, and it's useful otherwise, so try and use it
427 consistently.
433 * 'make dist'? Use $(DISTFILES)
435 The 'dist-default' target will copy the files listed in $(DISTFILES)
436 into the distribution directory, as well as Makefile and ChangeLog if
437 they exist. This is almost always all that you need, so ideally your
438 make dist support should only be:
440 ========================================
441 DISTFILES = README Test/thoughts.txt
443 dist-local: dist-default
444 ========================================
446 DISTFILES will cope correctly with files in subdirectories, by the
447 way. Note that if you put a nonexistant file or a directory in
448 DISTFILES it will *not* complain; it will just ignore it.
450 If you want to test your 'make dist' code, you can try
452 ========================================
453 $ cd class/Mono.MyClass
454 $ make dist-local distdir=TEST
455 ========================================
457 And your files should be copied into TEST/ in the current directory.
458 There is a toplevel 'make distcheck' target, which will build a dist
459 tarball, try to build it, install files to a temporary prefix, make
460 clean it, make a distribution, and compare the files left over to the
461 files originally in the tarball: they should be the same. But this
462 takes about 15 minutes to run on my 1.1 Ghz computer, so it's not for
463 the faint of heart.
469 * Lots of files? Use $(wildcard *.foo)
471 When specifying the sources to a library or executable, wildcards are
472 not encouraged; in fact they're not allowed if you use library.make or
473 executable.make. But there are times when they're useful, eg:
475 ========================================
476 DISTFILES = $(wildcard Test/*.in) $(wildcard Test/*.out)
477 ========================================
479 Just so you know that 'make' has this feature.
486 * Referencing files in other directories? Use $(topdir).
488 $(topdir) is the path to the top directory from the current build
489 directory. Basically it's a sequence of ../.. computed from the value
490 that you give $(thisdir) at the top of your Makefile. Try to reference
491 things from $(topdir), so your code can be moved or cut-and-pasted
492 around with a minimum of fuss.
499 * Conditional building? Use ifdef/ifndef/endif
501 Now in general we want to avoid conditional building, but sometimes
502 something doesn't work on Linux or already exists on Windows or
503 whatnot. (See below on recommended form for how to build
504 platform-specifically.) GNU Make supports the following construction:
506 ========================================
507 BUILD_EXPERIMENTAL = yes
509 ifdef BUILD_EXPERIMENTAL
510 experimental_stuff = my-experiment.exe
511 else
512 experimental_stuff = 
513 endif
515 all-local: my-sane.exe $(experimental_stuff)
516 ========================================
518 'ifdef' means 'if the variable is set to nonempty', so you could have 
520 ========================================
521 BUILD_EXPERIMENTAL = colorless green ideas sleep furiously
522 ========================================
524 and Make would be happy. I hope that the meaning of 'ifndef' should be
525 obvious. If you want to only sometimes build a target, the above
526 construction is the recommended way to go about it; it's nice to have
527 the rules exist in a Makefile even if they aren't invoked.
529 If you want to see why conditionals aren't nice, take a look at
530 library.make or class/corlib/Makefile.
536 * 'Private' directories that shouldn't be built by default? Use DIST_ONLY_SUBDIRS
538 Several of the MCS class libraries have demo or experimental
539 implementations that depend on things not included with MCS (say,
540 Gtk#). We don't want to build them by default, because the user might
541 not have those dependencies installed, but it's nice to have a
542 Makefile for them to be built nicely.
544 First of all, there's nothing stopping you from writing a Makefile for
545 such a directory; just don't put it in the SUBDIRS line of its parent
546 directory. That way, you can do all the normal build things like 'make
547 all' or 'make clean' in that directory, but people trying to bootstrap
548 their system won't run into problems.
550 At the same time you probably want to include this directory in the
551 distribution so that people can use your demo or experimental code if
552 they know what they're doing. Hence the variable
553 $(DIST_ONLY_SUBDIRS). As you might guess, it's like the SUBDIRS
554 variable: it lists subdirectories that a regular shouldn't recurse
555 into, but should have their 'make dist' rules invoked. 
557 Say you've written Mono.MyFancyLib.dll and you have
558 a demo app using Gtk# called MyFancyDemo. The Makefile rules might
559 look like this:
561 class/Mono.MyFancyLib/Makefile
562 ========================================
563 thisdir = class/Mono.MyFancyLib
564 SUBDIRS =
565 DIST_ONLY_SUBDIRS = MyFancyDemo
566 include ../../build/rules.make
568 LIBRARY = Mono.MyFancyLib.dll
569 LIB_MCS_FLAGS = /r:System.dll
570 TEST_MCS_FLAGS = $(LIB_MCS_FLAGS)
572 include ../../build/library.make
573 ========================================
575 class/Mono.MyFancyLib/MyFancyDemo/Makefile
576 ========================================
577 thisdir = class/Mono.MyFancyLib/MyFancyDemo
578 SUBDIRS =
579 include ../../../build/rules.make
581 PROGRAM = FancyDemo.exe
582 LOCAL_MCS_FLAGS = /r:gtk-sharp.dll
584 include ../../../build/executable.make
585 ========================================
590 * Special recursion needs?
592 By default, rules.make defines the all, install, clean, etc. targets
593 to look something like this:
595    all: all-recursive
596         $(MAKE) all-local
598 Sometimes that doesn't cut it; say for example you want to check for
599 something before doing a lengthy recursive build (see
600 $(topdir)/Makefile) or you have a something like this
602         class/MyLibrary:
603                 Build MyLibrary.dll
604         class/MyLibrary/Test:
605                 Build TestMyLibrary.exe
607 'make clean test' will fail here, because the build will happen in
608 the Test subdirectory first, so there will be no MyLibrary.dll to link
609 against. (Unless you write a nasty evil relative path rule which is
610 strongly discouraged.)
612 Anyway, to solve this problem you can do
614 ========================================
615 thisdir = class/MyLibrary
616 SUBDIRS = Test
617 include ../../build/rules.make
619 # Normally, make runs 'all-recursive' first, and then 'all-local'
620 # With this, we ensure that 'all-local' is executed first.
621 all-recursive: all-local
623 test-recursive: test-local
625 ========================================
631 ** A few implementation details
633 The way rules.make does its recursion is very standard; it maps
634 {all,install,clean, dist,test} to $@-recursive, which executes that rule
635 in each directory in $(SUBDIRS), and then calls $@-local in the current
636 directory. So something that gets built in a subdirectory cannot rely on
637 something that gets built in its parent directory. If this is a problem,
638 see the previous section.  Note that the recursive rule for 'dist' is
639 different; it makes dist-recursive in subdirectories, so you at least
640 have to define that rule.
642 Note that even a directory that doesn't, for example, have any tests
643 must still define test-local; otherwise 'make test' run from the
644 toplevel directory will break.
651 ** Flags for Tools
653 We want to make it so that the user can specify certain flags to
654 always be given to a tool, so there's a general way of implementing
655 FLAGS variables:
657         * $(foo_FLAGS) remains unset or defaulted to something
658           sensible; the user can provide overrides this way.
660         * $(LOCAL_foo_FLAGS) is set in a specific Makefile to
661           provide necessary values.
663         * $(PLATFORM_foo_FLAGS) is set in the platform configuration
664           to provide platform-specific values.
666         * $(PROFILE_foo_FLAGS) is set in the profile configuration
667           to provide profile-specific values.
669         * $(USE_foo_FLAGS) is defined to be the combination of all of
670           the above, and it's what is actually passed to $(foo).
672 $(MCS_FLAGS) and $(CFLAGS) follow this model. If you end up finding
673 that another tool is used commonly (hm, jay...), please follow this form.
680 ** Portability tips
682 Always use the icky Windows /argument way of passing parameters to the C#
683 compiler so that csc can be used.
685 Always use /r:foo.dll, not /r:foo. Windows requires the former.
687 Use /r:$(corlib), not /r:corlib.
689 If you're writing shell script code as part of a make rule, remember
690 that Windows has command-line length limits. So something like
692 ========================================
693 mytool $(all_the_sources_to_corlib)
694 ========================================
696 Is probably going to cause problems. As I understand it, 
698 ========================================
699 for f in  $(all_the_sources_to_corlib) ; do ...
700 ========================================
702 is ok, since the shell itself doesn't have those limitations. Other
703 than that, you should still try to write fairly portable shell
704 script. Linux and Cygwin both use the GNU utilities, but there's at
705 least one hardy soul trying to build Mono on HP/UX, and no doubt there
706 will be ports to more Unices as time goes on.
713 ** Misc
715 We still don't use /d:NET_1_1 ; it causes some build problems right
716 now.
718 There's a hack in class/System.Data/Makefile to work around a very
719 strange crash in the runtime with some custom attribute stuff. It'd be
720 nice to fix it.
722 Also, there's a /lib:$(prefix)/lib in the System.dll Makefile, which
723 is for some reason necessary if System.Xml.dll hasn't been built yet.
724 (Well, it's necessary because of the /r:System.Xml.dll, but that
725 should be in the search path, it seems.)
727 A lot of the weird targets in the old makefiles have been dropped; I
728 have a feeling that a lot of them are archaic and not needed anymore.
730 I'd really like to write a build tool in C#. It would be nice to have
731 something really extensible and well-designed and clean. NAnt is,
732 IMHO, an apalling abomination and a tragically bad attempt at solving
733 the software building problem. Just so you know.
735 (On the other hand, NUnit is really neat.)
737 Peter