diff options
-rw-r--r-- | mcs/build/Makefile | 22 | ||||
-rw-r--r-- | mcs/build/README.configury | 23 | ||||
-rw-r--r-- | mcs/build/README.makefiles | 696 | ||||
-rw-r--r-- | mcs/build/README.platforms | 41 | ||||
-rw-r--r-- | mcs/build/config-default.make | 30 | ||||
-rw-r--r-- | mcs/build/executable.make | 71 | ||||
-rw-r--r-- | mcs/build/library.make | 134 | ||||
-rw-r--r-- | mcs/build/platforms/linux.make | 44 | ||||
-rw-r--r-- | mcs/build/platforms/win32.make | 21 | ||||
-rw-r--r-- | mcs/build/profiles/bootstrap.make | 18 | ||||
-rw-r--r-- | mcs/build/profiles/default.make | 14 | ||||
-rw-r--r-- | mcs/build/profiles/net_1_0.make | 15 | ||||
-rw-r--r-- | mcs/build/rules.make | 119 |
13 files changed, 1248 insertions, 0 deletions
diff --git a/mcs/build/Makefile b/mcs/build/Makefile new file mode 100644 index 00000000000..6d8e4b60493 --- /dev/null +++ b/mcs/build/Makefile @@ -0,0 +1,22 @@ +thisdir = build +SUBDIRS = +include ../build/rules.make + +all-local install-local test-local run-test-local clean-local: + +DISTFILES = \ + README.makefiles \ + README.platforms \ + README.configury \ + config-default.make \ + executable.make \ + library.make \ + rules.make \ + platforms/linux.make \ + platforms/win32.make \ + profiles/default.make \ + profiles/bootstrap.make \ + profiles/net_1_0.make + +dist-local: dist-default + mkdir $(distdir)/deps diff --git a/mcs/build/README.configury b/mcs/build/README.configury new file mode 100644 index 00000000000..52732e6bdad --- /dev/null +++ b/mcs/build/README.configury @@ -0,0 +1,23 @@ +Configuring the build (-*- outline -*-) +Peter Williams <peter@newton.cx> + +** Configuring the build + +It's pretty easy. You can create two files in this directory to tweak +settings: pre-config.make and config.make. + +pre-config.make is included before $(PLATFORM).make and +$(PROFILE).make, so you can set either of these variables if you want +to change the default. + +Just about any other change should go in config.make, which is +included after $(PLATFORM).make and $(PROFILE).make, so you can use +the values defined in those files if you wish. For example, + + MCS_FLAGS = $(DEFAULT_MCS_FLAGS) /my-experimental-optimizer-flag + +or something. + +(You shouldn't need to edit any of the existing Makefiles for +site-specific hacks. CVS would complain at you and `make dist' +wouldn't be happy.) diff --git a/mcs/build/README.makefiles b/mcs/build/README.makefiles new file mode 100644 index 00000000000..fedda941b00 --- /dev/null +++ b/mcs/build/README.makefiles @@ -0,0 +1,696 @@ +The MCS makefiles (-*- outline -*-) +Peter Williams <peter@newton.cx> + +The new makefiles try to abstract building on Windows and Linux. They +try to provide a consistent set of ways to express the things that our +build system needs to let us do, specifically: + + * Build recursively + * Build libraries and executables easily + * Let developers use different runtimes and class libaries + * Make distributions easily + * Provide a framework for testing + * Build platform-independently whenever possible + + + + + +** Makefile structure + +A general makefile looks like this: + +======================================== +thisdir = class/Mono.My.Library +SUBDIRS = +include ../../rules.make + +all-local: + do some stuff + +install-local: + $(MKINSTALLDIRS) $(DESTDIR)$(prefix)/share/ + $(INSTALL_DATA) myfile.txt $(DESTDIR)$(prefix)/share/myfiledir + +clean-local: + rm -f my-generated-file + +test-local: my_test_program.exe + +run-test-local: + $(RUNTIME) my_test_program.exe + +DISTFILES = myfile.txt my_test_source.cs + +dist-local: dist-default + +my_test_program.exe: my_test_source.cs + $(CSCOMPILE) /target:exe /out:$@ $< +======================================== + +Each makefile follows the same pattern: it does some setup, includes +the standard make rules, and provides rules for six standard targets: +all, install, test, run-test, clean, and dist. + +"Some setup" is defining two variables: $(thisdir) and +$(SUBDIRS). $(thisdir) is the directory that the makefile lives in, +relative to the top directory (ie, class/corlib) and $(SUBDIRS) +defines the subdirectories that should be built in. + +The six targets do the following: + + * all-local builds whatever someone would expect to be built +when they just type 'make'. Most likely Foo.dll or Foo.exe + + * install-local installs whatever got built by all-local. + + * test-local _builds_ the test programs or libraries but does +_not_ run them. + + * run-test-local actually runs the tests. It shouldn't +necessarily exit in an error if the test fails, but should make that +situation obvious. It should only run tests that take care of +themselves automatically; interactive tests should have an individual +target. The idea is that 'make run-test' from the toplevel should be +able to proceed unsupervised and test everything that can be tested in +such a manner. + + * clean-local removes built files; 'make clean' should leave +only files that go into a distribution tarball + + * dist-local copies files into the distribution tree, which is +given by the variable $(distdir). dist-local always depends on the +target 'dist-default'. See ** 'make dist' below. + + + + + +** Build configuration + +In general, MCS needs to be able to build relying only on the +existence of a runtime and core libraries (corlib, System, +System.Xml). So there shouldn't be any checking for libraries or +whatnot; MCS should be able to build out of the box after only +'./configure linux' or './configure win32'. + +That being said, it's very convenient for developers to be able to +customize their builds to suit their needs. To allow this, the +Makefile rules are set up to allow people to override pretty much any +important variable. + +Configuration variables are given defaults in `config-default.make'; +`rules.make' optionally includes `$(topdir)/config.make', so you can +customize your build without CVS trying to commit your modified +`config-default.make' all the time. Platform-specific variables are +defined in `$(topdir)/platform.make', which should be a copy of one of +the appropriate platform-specific makefiles. (Currently, the only +choices are linux.make and win32.make.) + +The best way to learn what the configuration variables are is to read +`config.make' and `platform.make'. There aren't too many and hopefully +they should be self-explanatory; see the numerous examples below for +more information if you're confused. + + + + + + +** Recommendations for platform specifics + +If you find yourself needing a platform-specific customization, try +and express it in terms of a feature, rather than a platform test. In +other words, this is good: + +======================================== +run-test-local: my-test.exe +ifdef PLATFORM_NEEDS_CRAZY_CRAP + crazy-crap +endif + $(RUNTIME) my-test.exe +======================================== + +and this is bad: + +======================================== +run-test-local: my-test.exe +ifdef WINDOWS + crazy-crap +else +ifdef AMIGA + crazy-crap +endif +endif + $(RUNTIME) my-test.exe +======================================== + +The latter accumulates and gets unpleasant and it sucks. Granted, +right now we only have two platforms, so it's not a big deal, but it's +good form to get used to and practice. Anyway, take a look at how we +do the various corlib building hacks for examples of how we've done +platform-specificity. It certainly isn't pretty, but at least it's a +little structured. + + + + + + +** Saving effort + + The point of the build system is to abstract things and take +care of all the easy stuff. So if you find yourself writing a +Makefile, know that there's probably already infrastructure to do what +you want. Here are all the common cases I can think of ... + + + + + + +* Compiling C# code? use: + +======================================== +my-program.exe: my-source.cs + $(CSCOMPILE) /target:exe /out:$@ $^ +======================================== + + or + +======================================== +my-lib.dll: my-source.cs + $(CSCOMPILE) /target:library /out:$@ $^ +======================================== + +Note the '$@' and '$^' variables. The former means "the name of the +file that I am trying to make" and the latter means "all the +dependencies of the file I am trying to make." USE THESE VARIABLES +AGGRESSIVELY. Say that you add a new source to your program: + +======================================== +my-program.exe: my-source.cs my-new-source.cs + $(CSCOMPILE) /target:exe /out:$@ $^ +======================================== + +Because of the $^ variable, you don't need to remember to add another +file to the command line. Similarly, if you rename your program, you +won't need to remember to change the rule: + +======================================== +MonoVaporizer.exe: my-source.cs my-new-source.cs + $(CSCOMPILE) /target:exe /out:$@ $^ +======================================== + +will still work. Another useful variable is $<, which means "the first +dependency of whatever I'm building." If you order your dependencies +carefully it can be extremely useful. + + + + + +* Just building an executable? use: + +======================================== +PROGRAM = myprogram.exe +LOCAL_MCS_FLAGS = /r:System.Xml.dll + +include ../executable.make +======================================== + +executable.make builds a program in the current directory. Its name is +held in $(PROGRAM), and its sources are listed in the file +$(PROGRAM).sources. It might seem to make more sense to just list the +program's sources in the Makefile, but when we build on Windows we +need to change slashes around, which is much easier to do if the +sources are listed in a file. The variable $(LOCAL_MCS_FLAGS) changes +the flags given to the compiler; it is included in $(CSCOMPILE) so you +don't need to worry about it. + +executable.make does a lot for you: it builds the program in 'make +all-local', installs the program in $(prefix)/bin, distributes the +sources, and defines empty test targets. Now, if your program has a +test, set the variable HAS_TEST: + +======================================== +PROGRAM = myprogram.exe +LOCAL_MCS_FLAGS = /r:System.Xml.dll +HAS_TEST = yes +include ../executable.make + +test-local: mytester.exe + +run-test-local: mytester.exe + $(RUNTIME) $< + +mytester.exe: mytester.cs + $(CSCOMPILE) /target:exe /out:$@ mytester.cs +======================================== + +If your program has 'built sources', that is, source files generated +from other files (say, generated by jay), define a variable called +BUILT_SOURCES and do *not* list the sources in $(PROGRAM).sources: + +======================================== +PROGRAM = myprogram.exe +LOCAL_MCS_FLAGS = /r:System.Xml.dll +BUILT_SOURCES = parser.cs +CLEAN_FILES = y.output + +include ../executable.make + +parser.cs: parser.jay + $(topdir)/jay/jay $< > $@ +======================================== + +executable.make will automatically delete the $(BUILT_SOURCES) files +on 'make clean'. Since this situation is a common occurrence and jay +happens to leave behind y.output files, you can also define a variable +called $(CLEAN_FILES) that lists extra files to be deleted when 'make clean' is +called. (That's in addition to your executable and the built sources). + + + + + + +* Buildling a library? Use + +======================================== +LIBRARY = Mono.MyLib.dll +LIB_MCS_FLAGS = /unsafe +TEST_MCS_FLAGS = /r:System.Xml.dll + +include ../../library.make +======================================== + +Where you library is called $(LIBRARY); it will be put into +$(topdir)/class/lib. LIB_MCS_FLAGS is the set of MCS flags to use when +compiling the library; in addition, a global set of flags called +$(LIBRARY_FLAGS) is added (that variable is defined in +config-defaults.make), as well as the usual $(LOCAL_MCS_FLAGS). + +As in executable.make, the sources for your library are listed in +$(LIBRARY).sources. Note: these source lists should have Unix forward +slashes and Unix newlines (\n, not \r\n.) If you get an error about +"touch: need a filename", that means your .sources file doesn't end in +a newline. It should. + +Now library.make also assumes that your library has an NUnit2 test +harness. The files should be in a subdirectory called Test/, and if +your library is called Mono.Foo.dll, they should be listed in +Mono.Foo_test.dll.sources. The names in that files should *not* have +the Test/ prefix. 'make test' will build Mono.Foo_test.dll in the +current directory, automatically supplying the flags to reference the +original library and NUnit.Framework.dll. + +If you don't have a test, just do this: + +======================================== +LIBRARY = Mono.MyLib.dll +LIB_MCS_FLAGS = /unsafe +NO_TEST = yes + +include ../../library.make +======================================== + +and feel ashamed. Every good library has a test suite! + +Extra flags needed to compile the test library should be listed in +$(TEST_MCS_FLAGS); often you will have a line like this: + +======================================== +TEST_MCS_FLAGS = $(LIB_MCS_FLAGS) +======================================== + +Again, library.make does a lot for you: it builds the dll, it +generates makefile fragments to track the dependencies, it installs +the library, it builds the test dll on 'make test', it runs +$(TEST_HARNESS) on it on 'make run-test', it removes the appropriate +files on 'make clean', and it distributes all the source files on +'make dist'. (TEST_HARNESS defaults to be nunit-console.exe but it may +be overridden to, say, nunit-gtk). If you have extra files to +distribute when using either library.make or executable.make, use the +variable $(EXTRA_DISTFILES): + +======================================== +EXTRA_DISTFILES = \ + Test/testcase1.in \ + Test/testcase1.out \ + README +======================================== + +Again, library.make and executable.make do the right things so that we +can build on Windows, doing some trickery to invert slashes and +overcome command-line length limitations. Use them unless you have a +really good reason not to. If you're building a bunch of small +executables, check out tools/Makefile or tools/security/Makefile; if +all the files are in the current directory, changing slashes isn't a +big deal, and command-line lengths won't be a problem, so +executable.make isn't necessary (and indeed it won't work, since it +can only build one .exe in a directory). + +If you're building a library, library.make is highly recommended; the +only DLL that doesn't use it is corlib, because building corlib is a +fair bit more complicated than it should be. Oh well. + + + + + + +* Running a C# program? Use $(RUNTIME) + +======================================== +run-test-local: myprog.exe + $(RUNTIME) myprog.exe +======================================== + +$(RUNTIME) might be empty (if you're on windows), so don't expect to +be able to give it any arguments. If you're on a platform which has an +interpreter or jitter, $(RUNTIME_FLAGS) is included in $(RUNTIME), so +set that variable. + + + + + +* Calling the compiler directly? Use $(MCS). + +Really, you should use $(CSCOMPILE) whenever possible, but $(MCS) is +out there. $(BOOTSTRAP_MCS) is the C# compiler that we use to build +mcs.exe; on Linux, we then use mcs.exe to build everything else, but +on Windows, we use csc.exe to build everything. Only use +$(BOOTSTRAP_MCS) if you know what you're doing. + + + + + +* Compiling C code? Use $(CCOMPILE) + +To give it flags, set $(LOCAL_CFLAGS). As with compiling C#, the +variable $(CFLAGS) will automatically be included on the command line. + + + + + +* Installing files? Use $(MKINSTALLDIRS), $(INSTALL_DATA) or +$(INSTALL_BIN), $(prefix), and $(DESTDIR). + +Every time a file is installed the commands should look like this: + +======================================== +install-local: + $(MKINSTALLDIRS) $(DESTDIR)$(prefix)/my/dir + $(INSTALL_DATA) myfile $(DESTDIR)$(prefix)/my/dir +======================================== + +This way the directory is created recursively if needed (admittedly, we could +probably rely on mkdir -p), the file is given the correct permissions, +the user can override $(MKINSTALLDIRS) and $(INSTALL) if they need to, +and we can support $(DESTDIR) installs. We use $(DESTDIR) to make +monocharge tarballs, and it's useful otherwise, so try and use it +consistently. + + + + + +* 'make dist'? Use $(DISTFILES) + +The 'dist-default' target will copy the files listed in $(DISTFILES) +into the distribution directory, as well as Makefile and ChangeLog if +it exists. This is almost always all that you need, so ideally your +make dist support should only be: + +======================================== +DISTFILES = README Test/thoughts.txt + +dist-local: dist-default +======================================== + +DISTFILES will cope correctly with files in subdirectories, by the +way. Note that if you put a nonexistant file or a directory in +DISTFILES it will *not* complain; it will just ignore it. + +If you want to test your 'make dist' code, you can try + +======================================== +$ cd class/Mono.MyClass +$ make dist-local distdir=TEST +======================================== + +And your files should be copied into TEST/ in the current directory. +There is a toplevel 'make distcheck' target, which will build a dist +tarball, try to build it, install files to a temporary prefix, make +clean it, make a distribution, and compare the files left over to the +files originally in the tarball: they should be the same. But this +takes about 15 minutes to run on my 1.1 Ghz computer, so it's not for +the faint of heart. + + + + + +* Lots of files? Use $(wildcard *.foo) + +When specifying the sources to a library or executable, wildcards are +not encouraged; in fact they're not allowed if you use library.make or +executable.make. But there are times when they're useful, eg: + +======================================== +DISTFILES = $(wildcard Test/*.in) $(wildcard Test/*.out) +======================================== + +Just so you know that 'make' has this feature. + + + + + + +* Referencing files in other directories? Use $(topdir). + +$(topdir) is the path to the top directory from the current build +directory. Basically it's a sequence of ../.. computed from the value +that you give $(thisdir) at the top of your Makefile. Try to reference +things from $(topdir), so your code can be moved or cut-and-pasted +around with a minimum of fuss. + + + + + + +* Conditional building? Use ifdef/ifndef/endif + +Now in general we want to avoid conditional building, but sometimes +something doesn't work on Linux or already exists on Windows or +whatnot. (See below on recommended form for how to build +platform-specifically.) GNU Make supports the following construction: + +======================================== +BUILD_EXPERIMENTAL = yes + +ifdef BUILD_EXPERIMENTAL +experimental_stuff = my-experiment.exe +else +experimental_stuff = +endif + +all-local: my-sane.exe $(experimental_stuff) +======================================== + +'ifdef' means 'if the variable is set to nonempty', so you could have + +======================================== +BUILD_EXPERIMENTAL = colorless green ideas sleep furiously +======================================== + +and Make would be happy. I hope that the meaning of 'ifndef' should be +obvious. If you want to only sometimes build a target, the above +construction is the recommended way to go about it; it's nice to have +the rules exist in a Makefile even if they aren't invoked. + +If you want to see why conditionals aren't nice, take a look at +library.make or class/corlib/Makefile. + + + + + +* 'Private' directories that shouldn't be built by default? Use DIST_ONLY_SUBDIRS + +Several of the MCS class libraries have demo or experimental +implementations that depend on things not included with MCS (say, +Gtk#). We don't want to build them by default, because the user might +not have those dependencies installed, but it's nice to have a +Makefile for them to be built nicely. + +First of all, there's nothing stopping you from writing a Makefile for +such a directory; just don't put it in the SUBDIRS line of its parent +directory. That way, you can do all the normal build things like 'make +all' or 'make clean' in that directory, but people trying to bootstrap +their system won't run into problems. + +At the same time you probably want to include this directory in the +distribution so that people can use your demo or experimental code if +they know what they're doing. Hence the variable +$(DIST_ONLY_SUBDIRS). As you might guess, it's like the SUBDIRS +variable: it lists subdirectories that a regular shouldn't recurse +into, but should have their 'make dist' rules invoked. + +Say you've written Mono.MyFancyLib.dll and you have +a demo app using Gtk# called MyFancyDemo. The Makefile rules might +look like this: + +class/Mono.MyFancyLib/Makefile +======================================== +thisdir = class/Mono.MyFancyLib +SUBDIRS = +DIST_ONLY_SUBDIRS = MyFancyDemo +include ../../rules.make + +LIBRARY = Mono.MyFancyLib.dll +LIB_MCS_FLAGS = /r:System.dll +TEST_MCS_FLAGS = $(LIB_MCS_FLAGS) + +include ../../library.make +======================================== + +class/Mono.MyFancyLib/MyFancyDemo/Makefile +======================================== +thisdir = class/Mono.MyFancyLib/MyFancyDemo +SUBDIRS = +include ../../../rules.make + +PROGRAM = FancyDemo.exe +LOCAL_MCS_FLAGS = /r:gtk-sharp.dll + +include ../../../executable.make +======================================== + + + + + + +** A few implementation details + +The way rules.make does its recursion is very standard; it maps +{all,install,clean, dist,test} to $@-recursive, which executes that +rule in each directory in $(SUBDIRS), and then calls $@-local in the +current directory. So something that gets built in a subdirectory +cannot rely on something that gets built in its parent directory; so +far, this hasn't really been a problem, and I hope it won't be. One +crappy solution would be: + +======================================== +thisdir = directory/subdir +SUBDIRS = +include ../../rules.make + +all-local: myfoo.exe + +myfoo.exe: ../libfoo.dll + $(CSCOMPILE) ... + +../libfoo.dll: + cd .. && $(MAKE) libfoo.dll +======================================== + +Alternatively, I think I could add support so that you could do this: + +======================================== +thisdir = directory +SUBDIRS = . subdir # <-- look at this +include ../../rules.make + +all-local: libfoo.dll + +libfoo.dll: + $(CSCOMPILE) ... +======================================== + +But that would get into some really nasty shell script so I'd rather +not have to do that. + +Note that even a directory that doesn't, for example, have any tests +must still define test-local; otherwise 'make test' run from the +toplevel directory will break. + + + + + + +** Flags + +We want to make it so that the user can specify certain flags to +always be given to a tool, so there's a general way of implementing +FLAGS variables: + + * $(foo_FLAGS) remains unset or defaulted to something + sensible; the user can provide overrides this way. + + * $(LOCAL_foo_FLAGS) is set in a specific Makefile to + provide necessary values. + + * $(USE_foo_FLAGS) is defined to be the combination of + $(LOCAL_foo_FLAGS) and $(foo_FLAGS), and it's what is + actually passed to $(foo). + +$(MCS_FLAGS) and $(CFLAGS) follow this model. If you end up finding +that another tool is used commonly (hm, jay...), please follow this form. + + + + + + +** Portability tips + +Always use the icky Windows /argument way of passing parameters to the C# +compiler so that csc can be used. + +Always use /r:foo.dll, not /r:foo. Windows requires the former. + +Use /r:$(corlib), not /r:corlib. Windows wants mscorlib.dll and Linux +wants corlib.dll; eventually, the Mono runtime is supposed to accept +mscorlib.dll too, but in the meantime, use the variable. + +If you're writing shell script code as part of a make rule, remember +that Windows has command-line length limits. So something like + +======================================== +for f in $(all_the_sources_to_corlib) ; do .... +======================================== + +Is probably going to cause problems. Other than that, you can rely on +fairly advanced (ie, GNU) behaviors from the standard shell utilities, +since both Cygwin and Linux will be using them. + + + + + + +** Misc + +$(LIBRARY_FLAGS) would be a good place to add /d:DOT_NET_1_1 or whatever +it is. + +A lot of the weird targets in the old makefiles have been dropped; I +have a feeling that a lot of them are archaic and not needed anymore. + +I'd really like to write a build tool in C#. It would be nice to have +something really extensible and well-designed and clean. NAnt is, +IMHO, an apalling abomination and a tragically bad attempt at solving +the software building problem. Just so you know. + +(On the other hand, NUnit is really neat.) + +Peter diff --git a/mcs/build/README.platforms b/mcs/build/README.platforms new file mode 100644 index 00000000000..a323ae7e418 --- /dev/null +++ b/mcs/build/README.platforms @@ -0,0 +1,41 @@ +A platform makefile should define the following variables: + +PLATFORM_DEBUG_FLAGS + The flags to pass to the C# compiler to generate appropriate + debug information + +PLATFORM_MCS_FLAGS + Flags that are always passed to the C# compiler + +PLATFORM_RUNTIME + The system runtime for executing CLR programs. Blank on Win32, + probably $(RUNTIME) (the Mono runtime) on everything else. + +PLATFORM_MAKE_CORLIB_CMP + Define it to something nonempty if corlib_cmp.dll should be built + on this platform. Only should be done if the platform provides its + own non-Mono runtime that we can compare corlibs with. + +PLATFORM_TWEAK_CORLIB_SOURCES + A command to futz around with the sources to corlib.dll. See linux.make + and win32.make for examples. Should be 'cat' unless you know what you're + doing. + +PLATFORM_CHANGE_SEPARATOR_CMD + A command to change filename separators given on stdin. Leave undefined + if Unixy filenames will work. See win32.make. + +BOOTSTRAP_MCS + The C# compiler used to compile mcs/mcs.exe, and possibly other + assemblies if the user is doing a standalone build (that is, not + a bootstrap). + +corlib + The name of corlib.dll. corlib.dll for the Mono runtime, mscorlib.dll + on Win32. + +hidden_prefix, hidden_suffix + Prefix and suffix for hidden/temporary files. Unused right now, I think. + +platform-check: + A target to make sure that we can build on this platform. diff --git a/mcs/build/config-default.make b/mcs/build/config-default.make new file mode 100644 index 00000000000..3dde4399ded --- /dev/null +++ b/mcs/build/config-default.make @@ -0,0 +1,30 @@ +# -*- makefile -*- +# +# This makefile fragment has (default) configuration +# settings for building MCS. +# +# Instead of editing this file, create config.make +# and override settings there. + +RUNTIME_FLAGS = +TEST_HARNESS = $(topdir)/nunit20/nunit-console/nunit-console.exe +MCS_FLAGS = $(PLATFORM_DEBUG_FLAGS) /nowarn:1595 /nowarn:0169 \ + /nowarn:0109 /nowarn:0067 /nowarn:0649 /nowarn:0679 +LIBRARY_FLAGS = /noconfig +CFLAGS = -g -O2 +INSTALL = /usr/bin/install +RUNTIME = mono $(RUNTIME_FLAGS) +TEST_RUNTIME=MONO_PATH="$(topdir)/class/lib:.:$$MONO_PATH" $(RUNTIME) --debug +prefix = /usr + +# In case you want to add MCS_FLAGS, this lets you not have to +# keep track of the default value + +DEFAULT_MCS_FLAGS := $(MCS_FLAGS) + +# You shouldn't need to set these but might on a +# weird platform. + +# CC = cc +# SHELL = /bin/sh +# MAKE = gmake diff --git a/mcs/build/executable.make b/mcs/build/executable.make new file mode 100644 index 00000000000..48ed195fd94 --- /dev/null +++ b/mcs/build/executable.make @@ -0,0 +1,71 @@ +# -*- makefile -*- +# +# The rules for building a program. + +# I'd rather not create a response file here, +# but since on Win32 we need to munge the paths +# anyway, we might as well. + +sourcefile = $(PROGRAM).sources +ifdef PLATFORM_CHANGE_SEPARATOR_CMD +response = $(depsdir)/$(PROGRAM).response +else +response = $(sourcefile) +endif +stampfile = $(depsdir)/$(PROGRAM).stamp +makefrag = $(depsdir)/$(PROGRAM).makefrag + +all-local: $(PROGRAM) + +install-local: + $(MKINSTALLDIRS) $(DESTDIR)$(prefix)/bin + $(INSTALL_BIN) $(PROGRAM) $(DESTDIR)$(prefix)/bin + +clean-local: + -rm -f *.exe $(BUILT_SOURCES) $(CLEAN_FILES) $(stampfile) $(makefrag) +ifdef PLATFORM_CHANGE_SEPARATOR_CMD + -rm -f $(response) +endif + +ifndef HAS_TEST +test-local: $(PROGRAM) + +run-test-local: +endif + +DISTFILES = $(sourcefile) $(EXTRA_DISTFILES) + +dist-local: dist-default + cat $(sourcefile) |xargs -n 20 \ + $(SHELL) -c 'for f in $$* ; do \ + dest=`dirname $(distdir)/$$f` ; \ + $(MKINSTALLDIRS) $$dest && cp $$f $$dest || exit 1 ; \ + done' dollar0 + +# Changing makefile probably means changing the +# sources, so let's be safe and add a Makefile dep + +$(PROGRAM): $(makefrag) $(response) $(stampfile) + $(CSCOMPILE) /target:exe /out:$@ $(BUILT_SOURCES) @$(response) + +$(makefrag): $(sourcefile) + @echo Creating $@ ... + @echo "HAVE_MAKEFRAG = yes" >$@.new + @echo "$(stampfile): $(BUILT_SOURCES) \\" >>$@.new + @cat $< |sed -e 's,\.cs[ \t]*$$,\.cs \\,' >>$@.new + @cat $@.new |sed -e '$$s, \\$$,,' >$@ + @echo -e "\ttouch \$$@" >>$@ + @rm -rf $@.new + +ifdef PLATFORM_CHANGE_SEPARATOR_CMD +$(response): $(sourcefile) + cat $< |$(PLATFORM_CHANGE_SEPARATOR_CMD) >$@ +endif + +-include $(makefrag) + +ifndef HAVE_MAKEFRAG +$(stampfile): + touch $@ +endif + diff --git a/mcs/build/library.make b/mcs/build/library.make new file mode 100644 index 00000000000..60623bbe096 --- /dev/null +++ b/mcs/build/library.make @@ -0,0 +1,134 @@ +# -*- makefile -*- +# +# The rules for building our class libraries. +# +# The NO_TEST stuff is not too pleasant but whatcha +# gonna do. + +# All the dep files now land in the same directory so we +# munge in the library name to keep the files from clashing. + +sourcefile = $(LIBRARY).sources +ifdef PLATFORM_CHANGE_SEPARATOR_CMD +response = $(depsdir)/$(LIBRARY).response +else +response = $(sourcefile) +endif +makefrag = $(depsdir)/$(LIBRARY).makefrag +stampfile = $(depsdir)/$(LIBRARY).stamp +the_lib = $(topdir)/class/lib/$(LIBRARY) + +ifndef NO_TEST +test_lib = $(patsubst %.dll,%_test.dll,$(LIBRARY)) +test_sourcefile = $(test_lib).sources +test_response = $(depsdir)/$(test_lib).response +test_makefrag = $(depsdir)/$(test_lib).makefrag +test_stampfile = $(depsdir)/$(test_lib).stamp +test_flags = /r:$(the_lib) /r:$(topdir)/class/lib/NUnit.Framework.dll $(TEST_MCS_FLAGS) +endif + +all-local: $(the_lib) + +install-local: $(the_lib) + $(MKINSTALLDIRS) $(DESTDIR)$(prefix)/lib + $(INSTALL_LIB) $(the_lib) $(DESTDIR)$(prefix)/lib + +clean-local: + -rm -f $(the_lib) $(makefrag) $(test_lib) \ + $(test_makefrag) $(test_response) \ + $(stampfile) $(test_stampfile) \ + TestResult.xml +ifdef PLATFORM_CHANGE_SEPARATOR_CMD + -rm -rf $(response) +endif + +ifndef NO_TEST +test-local: $(the_lib) $(test_lib) + +run-test-local: + $(TEST_RUNTIME) $(TEST_HARNESS) $(test_lib) + +else +test-local: $(the_lib) + +run-test-local: +endif + +DISTFILES = $(sourcefile) $(test_sourcefile) $(EXTRA_DISTFILES) + +# just in case you ever wanted to know how to copy a list of 800 +# files without excessively long commandlines... +# +# We need dollar0 because $(SHELL) -c interprets arguments as +# +# $(SHELL) -c 'the script' $0 $1 $2 .... +# +# Ideally we wouldn't use $(test_response) (it'd be nice to make dist +# with an unbuilt tree), but the -include lines generate the makefrags +# anyway, so we might as well use them. + +dist-local: dist-default $(test_response) + cat $(sourcefile) $(test_response) |xargs -n 20 \ + $(SHELL) -c 'for f in $$* ; do \ + dest=`dirname $(distdir)/$$f` ; \ + $(MKINSTALLDIRS) $$dest && cp $$f $$dest || exit 1 ; \ + done' dollar0 + +# Fun with dependency tracking + +$(the_lib): $(makefrag) $(stampfile) $(response) + $(CSCOMPILE) $(LIBRARY_FLAGS) $(LIB_MCS_FLAGS) /target:library /out:$@ @$(response) + +$(makefrag): $(sourcefile) + @echo Creating $@ ... + @echo "HAVE_MAKEFRAG = yes" >$@.new + @echo "$(stampfile): \\" >>$@.new + @cat $< |sed -e 's,\.cs[ \t]*$$,\.cs \\,' >>$@.new + @cat $@.new |sed -e '$$s, \\$$,,' >$@ + @echo -e "\ttouch \$$@" >>$@ + @rm -rf $@.new + +ifdef PLATFORM_CHANGE_SEPARATOR_CMD +$(response): $(sourcefile) + cat $< |$(PLATFORM_CHANGE_SEPARATOR_CMD) >$@ +endif + +-include $(makefrag) + +ifndef HAVE_MAKEFRAG +$(stampfile): + touch $@ +endif + +# for now, don't give any /lib flags or set MONO_PATH, since we +# give a full path to the assembly. + +ifndef NO_TEST +$(test_lib): $(test_makefrag) $(the_lib) $(test_response) $(test_stampfile) + $(CSCOMPILE) /target:library /out:$@ $(test_flags) @$(test_response) + +$(test_response): $(test_sourcefile) + @echo Creating $@ ... +ifdef PLATFORM_CHANGE_SEPARATOR_CMD + @cat $< |sed -e 's,^\(.\),Test/\1,' |$(PLATFORM_CHANGE_SEPARATOR_CMD) >$@ +else + @cat $< |sed -e 's,^\(.\),Test/\1,' >$@ +endif + +$(test_makefrag): $(test_response) + @echo Creating $@ ... + @echo "HAVE_TEST_MAKEFRAG = yes" >$@.new + @echo "$(test_stampfile): \\" >>$@.new + @cat $< |sed -e 's,\.cs[ \t]*$$,\.cs \\,' >>$@.new + @cat $@.new |sed -e '$$s, \\$$,,' >$@ + @echo -e "\ttouch \$$@" >>$@ + @rm -rf $@.new + +-include $(test_makefrag) +endif + +ifndef HAVE_TEST_MAKEFRAG +$(test_stampfile): + touch $@ +endif + diff --git a/mcs/build/platforms/linux.make b/mcs/build/platforms/linux.make new file mode 100644 index 00000000000..7bcd93c6443 --- /dev/null +++ b/mcs/build/platforms/linux.make @@ -0,0 +1,44 @@ +# -*- makefile -*- +# +# Platform-specific makefile rules. This one's for linux. +# + +PLATFORM_DEBUG_FLAGS = -g +PLATFORM_MCS_FLAGS = +PLATFORM_RUNTIME = $(RUNTIME) + +BOOTSTRAP_MCS = mcs +corlib = corlib.dll + +# Define this if this ever will work on Linux +# PLATFORM_MAKE_CORLIB_CMP = yes + +# This is for the security permission attribute problem +# on windows +PLATFORM_TWEAK_CORLIB_SOURCES = cat + +# This is for changing / to \ on windows +# Don't define it so we don't needlessly copy the sources +# file. This command is handy for testing: +# +# PLATFORM_CHANGE_SEPARATOR_CMD=sed -e 's,/,/./,g' + +hidden_prefix = . +hidden_suffix = + +platform-check: + @if ! type $(BOOTSTRAP_MCS) >/dev/null 2>&1 ; then \ + echo "*** You need a C# compiler installed to build MCS." ; \ + echo "*** Read README.building for information on how to bootstrap" ; \ + echo "*** a Mono installation." ; \ + exit 1 ; \ + fi + + +# I tried this but apparently Make's version strings aren't that +# ... consistent between releases. Whatever. +# +# @if ! $(MAKE) --version |grep '^GNU Make version 3' 1>/dev/null 2>&1 ; then \ +# echo "*** You need to build MCS with GNU make. Try \`gmake'" ; \ +# exit 1 ; \ +# fi diff --git a/mcs/build/platforms/win32.make b/mcs/build/platforms/win32.make new file mode 100644 index 00000000000..26ef3cbc682 --- /dev/null +++ b/mcs/build/platforms/win32.make @@ -0,0 +1,21 @@ +# -*- makefile -*- +# +# Win32 platform-specific makefile rules. +# + +PLATFORM_DEBUG_FLAGS = /debug+ /debug:full +PLATFORM_MCS_FLAGS = /nologo /optimize +PLATFORM_RUNTIME = + +BOOTSTRAP_MCS = csc.exe +MCS = $(BOOTSTRAP_MCS) +corlib = mscorlib.dll + +PLATFORM_MAKE_CORLIB_CMP = yes +PLATFORM_TWEAK_CORLIB_SOURCES=cat - corlib.dll.win32-excludes |sort |uniq -u +PLATFORM_CHANGE_SEPARATOR_CMD=tr '/' '\\\\' + +hidden_prefix = +hidden_suffix = .tmp + +platform-check: diff --git a/mcs/build/profiles/bootstrap.make b/mcs/build/profiles/bootstrap.make new file mode 100644 index 00000000000..c7c09a13565 --- /dev/null +++ b/mcs/build/profiles/bootstrap.make @@ -0,0 +1,18 @@ +# -*- makefile -*- +# +# A bootstrap profile -- builds with the internal MCS, even if +# we're on Windows. + +# Note that we have sort of confusing terminology here; BOOTSTRAP_MCS +# is what allows us to bootstrap ourselves, but when we are bootstrapping, +# we use INTERNAL_MCS. + +# When bootstrapping, compile against our new assemblies. +# (MONO_PATH doesn't just affect what assemblies are loaded to +# run the compiler; /r: flags are by default loaded from whatever's +# in the MONO_PATH too). + +MCS = MONO_PATH="$(topdir)/class/lib:$$MONO_PATH" $(INTERNAL_MCS) + +# Causes some build errors +#PROFILE_MCS_FLAGS = /d:NET_1_1 diff --git a/mcs/build/profiles/default.make b/mcs/build/profiles/default.make new file mode 100644 index 00000000000..51763f3c3af --- /dev/null +++ b/mcs/build/profiles/default.make @@ -0,0 +1,14 @@ +# -*- Makefile -*- +# +# The default profile. + +# In this profile we compile everything relative to the already-installed +# runtime, so we use the bootstrap (external) compiler for everything and +# don't set MONO_PATH. + +MCS = $(BOOTSTRAP_MCS) + +# Causes some build errors +#PROFILE_MCS_FLAGS = /d:NET_1_1 + +# Exciting, no? diff --git a/mcs/build/profiles/net_1_0.make b/mcs/build/profiles/net_1_0.make new file mode 100644 index 00000000000..32c5f1bce87 --- /dev/null +++ b/mcs/build/profiles/net_1_0.make @@ -0,0 +1,15 @@ +# -*- Makefile -*- +# +# Only build .NET 1.0 classes. +# +# If we want to combine this with, say, the bootstrap profile, +# we should create 'bs-net_1_0.make' which includes both. +# +# Ideally you could say 'make PROFILE="bootstrap net_1_0"' but +# that would be pretty hard to code. + +include $(topdir)/build/profiles/default.make + +PROFILE_MCS_FLAGS = /d:NET_1_0 + +# done diff --git a/mcs/build/rules.make b/mcs/build/rules.make new file mode 100644 index 00000000000..9d882424827 --- /dev/null +++ b/mcs/build/rules.make @@ -0,0 +1,119 @@ +# -*- makefile -*- +# +# This is the makefile fragment with default rules +# for building things in MCS +# +# To customize the build, you should edit config.make. +# If you need to edit this file, that's a bug; email +# peter@newton.cx about it. + +# Some more variables. The leading period in the sed expression prevents +# thisdir = . from being changed into '..' for the toplevel directory. + +dots := $(shell echo $(thisdir) |sed -e 's,[^./][^/]*,..,g') +topdir := $(dots) + +VERSION = 0.25.99 + +USE_MCS_FLAGS = $(LOCAL_MCS_FLAGS) $(PLATFORM_MCS_FLAGS) $(PROFILE_MCS_FLAGS) $(MCS_FLAGS) +USE_CFLAGS = $(LOCAL_CFLAGS) $(CFLAGS) +CSCOMPILE = $(MCS) $(USE_MCS_FLAGS) +CCOMPILE = $(CC) $(USE_CFLAGS) +BOOT_COMPILE = $(BOOTSTRAP_MCS) $(USE_MCS_FLAGS) +INSTALL_DATA = $(INSTALL) -m 644 +INSTALL_BIN = $(INSTALL) -m 755 +INSTALL_LIB = $(INSTALL_DATA) +MKINSTALLDIRS = $(SHELL) $(topdir)/mkinstalldirs +INTERNAL_MCS = $(RUNTIME) $(topdir)/mcs/mcs.exe + +depsdir = $(topdir)/build/deps +distdir = $(dots)/$(package)/$(thisdir) + +# Make sure these propagate if set manually + +export PLATFORM +export PROFILE +export MCS +export MCS_FLAGS +export CC +export CFLAGS +export INSTALL +export MKINSTALLDIRS +export TEST_HARNESS +export BOOTSTRAP_MCS +export DESTDIR + +# Get this so the platform.make platform-check rule doesn't become the +# default target + +default: all + +# Get initial configuration. pre-config is so that the builder can +# override PLATFORM or PROFILE + +include $(topdir)/build/config-default.make +-include $(topdir)/build/pre-config.make + +# Default PLATFORM and PROFILE if they're not already defined. + +ifndef PLATFORM +ifeq ($(OS),Windows_NT) +PLATFORM = win32 +else +PLATFORM = linux +endif +endif + +ifndef PROFILE +PROFILE = default +endif + +# Rest of the configuration + +include $(topdir)/build/platforms/$(PLATFORM).make +include $(topdir)/build/profiles/$(PROFILE).make +-include $(topdir)/build/config.make + +# Simple rules + +%-recursive: + @for d in $(SUBDIRS) ; do \ + (cd $$d && $(MAKE) $*) || exit 1 ; \ + done + +# note: dist-local dep, extra subdirs, $* has become $@ + +dist-recursive: dist-local + @for d in $(SUBDIRS) $(DIST_ONLY_SUBDIRS) ; do \ + (cd $$d && $(MAKE) $@) || exit 1 ; \ + done + +# We do this manually to not have a make[1]: blah message (That is, +# instead of using a '%: %-recursive %-local' construct.) + +all: all-recursive all-local + +install: install-recursive install-local + +test: test-recursive test-local + +run-test: run-test-recursive run-test-local + +clean: clean-recursive clean-local + +# Can only do this from the top dir +# ## dist: dist-recursive dist-local + +# We invert the test here to not end in an error +# if ChangeLog doesn't exist. +# +# Note that we error out if we try to dist a nonexistant +# file. Seems reasonable to me. + +dist-default: + -mkdir $(distdir) + test '!' -f ChangeLog || cp ChangeLog $(distdir) + for f in Makefile $(DISTFILES) ; do \ + dest=`dirname $(distdir)/$$f` ; \ + $(MKINSTALLDIRS) $$dest && cp $$f $$dest || exit 1 ; \ + done |