Home My Page Projects Code Snippets Project Openings SML/NJ
Summary Activity Forums Tracker Lists Tasks Docs Surveys News SCM Files

SCM Repository

[smlnj] Annotation of /sml/trunk/src/system/README
ViewVC logotype

Annotation of /sml/trunk/src/system/README

Parent Directory Parent Directory | Revision Log Revision Log


Revision 573 - (view) (download)

1 : blume 537 Compiler Hacker's Guide to the new CM...
2 :     ========================================
3 : monnier 416
4 : blume 573 Last change: 3/2000
5 : blume 537
6 : monnier 416 * Libraries
7 :     -----------
8 :    
9 :     The new way of building the compiler is heavily library-oriented.
10 :     Aside from a tiny portion of code that is responsible for defining the
11 :     pervasive environment, _everything_ lives in libraries. Building the
12 :     compiler means compiling and stabilizing these libraries first. Some
13 :     of the libraries exist just for reasons of organizing the code, the
14 :     other ones are potentially useful in their own right. Therefore, as a
15 :     beneficial side-effect of compiling the compiler, you will end up with
16 :     stable versions of these libraries.
17 :    
18 :     At the moment, the following libraries are constructed when compiling
19 :     the compiler ("*" means that I consider the library potentially useful
20 :     in its own right):
21 :    
22 : blume 573 * basis.cm SML'97 Basis Library (pre-loaded)
23 :     * smlnj-lib.cm SML/NJ Utility Library
24 :     * html-lib.cm SML/NJ HTML Library
25 :     * pp-lib.cm SML/NJ Pretty-print Library
26 : monnier 416
27 : blume 573 * ml-yacc-lib.cm SML/NJ ML-Yacc runtime library
28 :    
29 :     * smlnj/compiler/{alpha32,hppa,ppc,sparc,x86}.cm
30 :     cross-compiler libraries, exporting
31 :     structure <Arch>Compiler
32 :     * smlnj/compiler/current.cm structure Compiler (current arch)
33 :     * smlnj/compiler/all.cm all cross-compilers and all cross-CMBs
34 :    
35 :     * smlnj/cm/minimal.cm minimal CM (pre-loaded)
36 :     * smlnj/cm/full.cm full structure CM (see manual)
37 :     * smlnj/cm/tools.cm CM tools library
38 :    
39 :     * smlnj/cmb/{alpha32,hppa,ppc,sparc,x86}-unix.cm
40 :     cross-bootstrap-compilers for Unix
41 :     (structure <Arch>UnixCMB)
42 :     * smlnj/cmb/ppc-macos.cm ...for Mac (structure PPCMacosCMB)
43 :     * smlnj/cmb/x86-win32.cm ...for Windoze (structure X86Win32CMB)
44 :     * smlnj/cmb/current.cm structure CMB (current arch/os)
45 :    
46 :     * smlnj/compiler.cm abbrev. for smlnj/compiler/current.cm
47 :     * smlnj/cm.cm abbrev. for smlnj/cm/full.cm
48 :     * smlnj/cmb.cm abbrev. for smlnj/cmb/current.cm
49 :    
50 :     * comp-lib.cm Utility library for compiler
51 :    
52 :     - smlnj/viscomp/core.cm Compiler core functionality
53 :     - smlnj/viscomp/{alpha32,hppa,ppc,sparc,x86}.cm
54 :     Machine-specific parts of compiler
55 :    
56 :     - smlnj/internal/{intsys,cm-lib,cm-hook,host-compiler-0}.cm
57 :     Glue that holds the interactive system
58 :     together
59 :    
60 :     * MLRISC/{MLRISC,Control,Lib,ALPHA,HPPA,PPC,SPARC,IA32}.cm
61 :     Various MLRISC bits
62 :    
63 :     * {mlyacc,mllex,mlburg}-tool.cm CM plug-in libraries for common tools
64 :     * {grm,lex,burg}-ext.cm CM plug-in libraries for common file
65 :     extensions
66 :    
67 : monnier 416 * Before you can use the bootstrap compiler (CMB)...
68 :     ----------------------------------------------------
69 :    
70 :     To be able to use CMB at all, you must first say
71 :    
72 : blume 573 CM.autoload "smlnj/cmb.cm";
73 : monnier 416
74 : blume 569 after you start sml. Alternatively -- and perhaps more conveniently --
75 :     you can provide "host-cmb.cm" as a command-line argument to sml:
76 : monnier 416
77 : blume 573 $ sml smlnj/cmb.cm
78 : monnier 416
79 : blume 569 * Compiling the compiler
80 :     ------------------------
81 : monnier 416
82 : blume 569 We are now back to the old scheme where a call to CMB.make() suffices to
83 :     build a bootable set of files (libraries in our case). CMB.make maintains
84 :     two parallel hierarchies of derived files:
85 : monnier 416
86 : blume 569 1. the binfile hierarchy ("binfiles"), containing compiled objects for
87 :     each individual ML source file; this hierarchy is rooted at
88 :     <prefix>.bin.<arch>-<opsys>
89 :     2. the stable library hierarchy ("boot files"), containing library files
90 :     for each library that participates in building SML/NJ; this hierarchy
91 :     is rooted at
92 :     <prefix>.boot.<arch>-<opsys>
93 : monnier 416
94 : blume 569 The default for <prefix> is "sml". It can be changed by using
95 :     CMB.make' with the new <prefix> as the optional string argument.
96 : monnier 416
97 : blume 569 CMB.make uses bootfiles after it has verified that they are consistent
98 :     with their corresponding binfiles. Bootfiles do not need to be
99 :     deleted in order for CMB.make to work correctly.
100 : monnier 416
101 : blume 569 To bootstrap a new system (using the runtime system boot loader), the
102 :     bootfiles _must_ be present, the binfiles need not be present (but
103 :     their presence does not hurt either).
104 : monnier 416
105 : monnier 498 You can reduce the number of extra files compiled and stabilized
106 : blume 569 during CMB.make at the expense of not building any cross-compilers.
107 : monnier 498 For that, say
108 :     #set (CMB.symval "LIGHT") (SOME 1);
109 : blume 569 before running CMB.make.
110 : monnier 498
111 : monnier 416 * Making the heap image
112 :     -----------------------
113 :    
114 :     The heap image is made by running the "makeml" script that you find
115 :     here in this directory. By default it will try to refer to the
116 : monnier 498 sml.boot.<arch>-<os> directory. You can change this using the -boot
117 : monnier 416 argument (which takes the full name of the boot directory to be used).
118 :    
119 :     The "feel" of using makeml should be mostly as it used to. However,
120 :     internally, there are some changes that you should be aware of:
121 :    
122 : blume 569 1. The script will make a heap image and build a separate library directory
123 :     that contains links to the library files in the bootfile directory.
124 : monnier 416
125 :     2. There is no "-full" option anymore. This functionality should
126 :     eventually be provided by a library with a sufficiently rich export
127 :     interface.
128 :    
129 :     3. No image will be generated if you use the -rebuild option.
130 :     Instead, the script quits after making new bin and new boot
131 :     directories. You must re-invoke makeml with a suitable "-boot"
132 :     option to actually make the image. The argument to "-rebuild"
133 :     is the <prefix> for the new bin and boot directories (see above).
134 :    
135 : blume 569 Makeml will not destroy the bootfile directory.
136 : monnier 416
137 :     * Testing a newly generated heap image
138 :     --------------------------------------
139 :    
140 :     If you use a new heap image by saying "sml @SMLload=..." then things
141 :     will not go as you may expect because along with the new heap image
142 :     should go those new stable libraries, but unless you do something
143 : blume 569 about it, the newly booted system will look for its stable libraries
144 :     in places where you stored your _old_ stable libraries.
145 : monnier 416
146 :     After you have made the new heap image, the new libraries are in a
147 :     separate directory whose name is derived from the name of the heap
148 : blume 569 image. (Actually, only the directory hierachy is separate, the
149 :     library files themselves are hard links.) The "testml" script that you
150 :     also find here will run the heap image and instruct it to look for its
151 :     libraries in that new library directory.
152 : monnier 416
153 : monnier 498 "testml" takes the <prefix> of the heap image as its first
154 :     argument. All other arguments are passed verbatim to the ML process.
155 :    
156 :     The <prefix> is the same as the one used when you did "makeml". If
157 :     you run "testml" without arguments, <prefix> defaults to "sml".
158 :     Thus, if you just said "makeml" without argument you can also say
159 :     "testml" without argument. (Note that you _must_ supply the <prefix>
160 :     argument if you intend to pass any additional arguments.)
161 :    
162 : monnier 416 * Installing a heap image for more permanent use
163 :     ------------------------------------------------
164 :    
165 : monnier 498 You can "install" a newly generated heap image by replacing the old
166 :     image with the new one _AND AT THE SAME TIME_ replacing the old stable
167 :     libaries with the new ones. To do this, run the "installml" script.
168 : monnier 416
169 : monnier 498 Like "testml", "installml" also expects the <prefix> as its first
170 :     argument. <prefix> defaults to "sml" if no argument is specified.
171 :    
172 :     "installml" patches the ../../lib/pathconfig file to reflect any
173 :     changes or additions to the path name mapping.
174 :    
175 : blume 569 Thus, after a successful CMB.make, you should say
176 : monnier 498
177 :     ./makeml
178 :    
179 :     to make the new heap image + libraries, then
180 :    
181 :     ./testml
182 :    
183 :     to make sure everything works, and finally
184 :    
185 :     ./installml
186 :    
187 :     to replace your existing compiler with the one you just built and tested.
188 :    
189 : monnier 416 * Cross-compiling
190 :     -----------------
191 :    
192 : blume 573 All cross-compilers live in the "smlnj/compiler/all.cm" library. You
193 : monnier 416 must first say
194 :    
195 : blume 573 CM.autoload "smlnj/compiler/all.cm";
196 : monnier 416
197 :     before you can access them. (This step corresponds to the old
198 :     CMB.retarget call.) After that, _all_ cross-compilers are available
199 :     at the same time. However, the ones that you are not using don't take
200 :     up any undue space because they only get loaded once you actually
201 :     mention them at the top-level. The names of the structures currently
202 :     exported by target-compilers.cm are:
203 :    
204 :     structure Alpha32UnixCMB
205 :     structure HppaUnixCMB
206 :     structure PPCMacOSCMB
207 :     structure PPCUnixCMB
208 :     structure SparcUnixCMB
209 :     structure X86UnixCMB
210 :     structure X86Win32CMB
211 :    
212 :     structure Alpha32Compiler
213 :     structure HppaCompiler
214 :     structure PPCCompiler
215 :     structure SparcCompiler
216 :     structure X86Compiler
217 :    
218 :     (PPCMacOSCMB is not very useful at the moment because there is no
219 :     implementation of the basis library for the MacOS.)
220 :    
221 : monnier 498 Alternatively, you can select just the one single structure that you
222 : blume 573 are interested in by auto-loading smlnj/compiler/<arch>.cm or
223 :     smlnj/cmb/<arch>-<os>.cm.
224 : monnier 498 <arch> currently ranges over "alpha32", "hppa", "ppc", "sparc", and "x86.
225 :     <os> can be either "unix" or "macos" or "win32".
226 :     (Obviously, not all combinations are valid.)
227 :    
228 : blume 573 Again, as with smlnj/cmb.cm, you can specify the .cm file as an
229 : blume 569 argument to the sml command:
230 :    
231 : blume 573 $ sml smlnj/compiler/all.cm
232 : blume 569
233 :     or
234 :    
235 : blume 573 $ sml smlnj/cmb/alpha32-unix.cm
236 : blume 569
237 : monnier 416 * Path configuration
238 :     --------------------
239 :    
240 :     + Basics:
241 :    
242 :     One of the new features of CM is its handling of path names. In the
243 :     old CM, one particular point of trouble was the autoloader. It
244 :     analyzes a group or library and remembers the locations of associated
245 :     files. Later, when the necessity arises, those files will be read.
246 :     Therefore, one was asking for trouble if the current working directory
247 :     was changed between analysis- and load-time, or, worse, if files
248 :     actually moved about (as is often the case if build- and
249 :     installation-directories are different, or, to put it more generally,
250 :     if CM's state is frozen into a heap image and used in a different
251 :     environment).
252 :    
253 :     Maybe it would have been possible to work around most of these
254 :     problems by fixing the path-lookup mechanism in the old CM and using
255 :     it extensively. But path-lookup (as in the Unix-shell's "PATH") is
256 :     inherently dangerous because one can never be too sure what it will be
257 :     that is found on the path. A new file in one of the directories early
258 :     in the path can upset the program that hopes to find something under
259 :     the same name later on the path. Even when ignoring security-issues
260 :     like trojan horses and such, this definitely opens the door for
261 : monnier 498 various unpleasant surprises. (Who has never named a test version
262 : monnier 416 of a program "test" an found that it acts strangely only to discover
263 :     later that /bin/test was run instead?)
264 :    
265 :     Thus, the new scheme used by CM is a fixed mapping of what I call
266 :     "configuration anchors" to corresponding directories. The mapping can
267 :     be changed, but one must do so explicitly. In effect, it does not
268 :     depend on the contents of the file system. Here is how it works:
269 :    
270 :     If I specify a relative pathname in one of CM's description files
271 :     where the first component (the first arc) of that pathname is known to
272 :     CM as a configuration anchor, then the corresponding directory
273 :     (according to CM's mapping) is prepended to the path. Suppose the
274 :     path name is "a/foo.sml" and "a" is a known anchor that maps to
275 :     "/usr/lib/smlnj", then the resulting complete pathname is
276 :     "/usr/lib/smlnj/a/foo.sml". The pathname can be a single arc (but
277 :     does not have to be). For example, the anchor "basis.cm" is typically
278 :     mapped to the directory where the basis library is stored.
279 :    
280 :     Now, the important point is that one can change the mapping of the
281 :     anchor, and the path name will also change accordingly -- even very
282 :     late in the game. CM avoids "elaborating" path names until it really
283 :     needs them when it is time to open files. CM is also willing to
284 :     re-elaborate the same names if there is reason to do so. Thus, the
285 :     "basis.cm" library that was analyzed "here" but then moved "there"
286 :     will also be found "there" if the anchor has been re-set accordingly.
287 :    
288 :     + Different configurations at different times:
289 :    
290 :     During compilation of the compiler, CMB uses a path configuration that
291 :     is read from the file "pathconfig" located here in this directory.
292 :    
293 :     At bootstrap time, the same anchors are mapped to the corresponding
294 :     sub-directory of the "boot" directory: basis.cm is mapped to
295 : monnier 498 sml.boot.<arch>-<os>/basis.cm -- which means that CM will look for a
296 :     library named sml.boot.<arch>-<os>/basis.cm/basis.cm -- and so forth.
297 : monnier 416
298 :     By the way, you will perhaps notice that there is no file
299 : monnier 498 sml.boot.<arch>-<os>/basis.cm/basis.cm
300 : monnier 416 but there _is_ the corresponding stable archive
301 : monnier 498 sml.boot.<arch>-<os>/basis.cm/CM/<arch>-<os>/basis.cm
302 : monnier 416 CM always looks for stable archives first.
303 :    
304 :     This mapping (from anchors to names in the boot directory) is the one
305 :     that will get frozen into the generated heap image at boot time.
306 :     Thus, unless it is changed, CM will look for its libraries in the boot
307 : monnier 429 directory. The aforementioned "testml" script will make sure that
308 : monnier 416 the mapping is changed to the one specified in a new "pathconfig" file
309 :     which was created by makeml and placed into the test library
310 :     directory. It points all anchors to the corresponding entry in the
311 : monnier 429 test library directory. Thus, "testml" will let a new heap image run
312 : monnier 416 with its corresponding new libraries.
313 :    
314 :     Normally, however, CM consults other pathconfig files at startup --
315 :     files that live in standard locations. These files are used to modify
316 :     the path configuration to let anchors point to their "usual" places.
317 :     The names of the files that are read (if present) are configurable via
318 :     environment variables. At the moment they default to
319 :     /usr/lib/smlnj-pathconfig
320 :     and
321 :     $HOME/.smlnj-pathconfig
322 :     The first one is configurable via CM_PATHCONFIG (and the default is
323 :     configurable at boot time via CM_PATHCONFIG_DEFAULT); the last is
324 :     configurable via CM_LOCAL_PATHCONFIG and CM_LOCAL_PATHCONFIG_DEFAULT.
325 :     In fact, the makeml script sets the CM_PATHCONFIG_DEFAULT variable
326 :     before making the heap image. Therefore, heap images generated by
327 :     makeml will look for their global pathconfig file in
328 :    
329 : monnier 429 `pwd`/../../lib/pathconfig
330 : monnier 416
331 : monnier 429 For example, I always keep my "good" libraries in `pwd`/../../lib --
332 :     where both the main "install" script and the "installml" script (see
333 : monnier 498 above) also put them -- so I don't have to do anything special about
334 : monnier 429 my pathconfig file.
335 : monnier 416
336 :     Once I have new heap image and libraries working, I replace the old
337 :     "good" image with the new one:
338 :    
339 :     mv <image>.<arch>-<osvariant> ../../bin/.heap/sml.<arch>-<osvariant>
340 :    
341 : blume 573 After this you must also move all libraries from <image>.libs/* to their
342 :     corresponding position in ../../lib.
343 : monnier 416
344 : blume 573 Since this is cumbersome to do by hand, there is a script called
345 :     "installml" that automates this task. Using the script has the added
346 :     advantage that it will not clobber libraries that belong to other than
347 :     the current architecture. (A rather heavy-handed "rm/mv" approach
348 :     will delete all stable libraries for all architectures.)
349 :     "installml" also patches the ../../lib/pathconfig file as necessary.
350 : monnier 416
351 :     Of course, you can organize things differently for yourself -- the
352 :     path configuration mechanism should be sufficiently flexible.
353 :    
354 :     * Libraries vs. Groups
355 :     ----------------------
356 :    
357 :     With the old CM, "group" was the primary concept while "library" and
358 :     "stabilization" could be considered afterthoughts. This has changed.
359 :     Now "library" is the primary concept, "stabilization" is semantically
360 :     significant, and "groups" are a secondary mechanism.
361 :    
362 :     Libraries are used to "structure the world"; groups are used to give
363 :     structure to libraries. Each group can be used either in precisely
364 :     one library (in which case it cannot be used at the interactive
365 :     toplevel) or at the toplevel (in which case it cannot be used in any
366 :     library). In other words, if you count the toplevel as a library,
367 :     then each group has a unique "owner" library. Of course, there still
368 :     is no limit on how many times a group can be mentioned as a member of
369 :     other groups -- as long as all these other groups belong to the same
370 :     owner library.
371 :    
372 :     If you want to take a collection of files whose purpose fits that of a
373 :     library, then, please, make them into a library (i.e., not a group!).
374 :     The purpose of groups is to deal with name-space issues _within_
375 :     libraries.
376 :    
377 :     Aside from the fact that I find this design quite natural, there is
378 :     actually a technical reason for it: when you stabilize a library
379 :     (groups cannot be stabilized), then all its sub-groups (not
380 :     sub-libraries!) get "sucked into" the stable archive of the library.
381 :     In other words, even if you have n+1 CM description files (1 for the
382 :     library, n for n sub-groups), there will be just one file representing
383 :     the one stable archive (per architecture/os) for the whole thing. For
384 :     example, I structured the standard basis into one library with two
385 : blume 569 sub-groups, but once you compile it (CMB.make) there is only one
386 : monnier 416 stable file that represents the whole basis library. If groups were
387 :     allowed to appear in more than one library, then stabilization would
388 :     duplicate the group (its code, its environment data structures, and
389 :     even its dynamic state).
390 :    
391 :     There is a small change to the syntax of group description files: they
392 :     must explicitly state which library they belong to. CM will verify
393 :     that. The owner library is specified in parentheses after the "group"
394 :     keyword. If the specification is missing (that's the "old" syntax),
395 :     then the the owner will be taken to be the interactive toplevel.
396 :    
397 : blume 537 * Pervasive environment, core environment, the init group "init.cmi"
398 : monnier 416 -------------------------------------------------------------------------
399 :    
400 : blume 569 CMB.make starts out by building and compiling the
401 : blume 537 "init group". This group cannot be described in the "usual" way
402 :     because it uses "magic" in three ways:
403 :     - it is used to later tie in the runtime system
404 : blume 569 - it exports the "core" environment
405 :     - it exports the "pervasive" environment
406 : monnier 416
407 : blume 537 The pervasive environment no longer includes the entire basis library
408 :     but only non-modular bindings (top-level bindings of variables and
409 :     types).
410 :    
411 : blume 569 CM cannot automatically determine dependencies (or exports) for the
412 :     init group source files, but it still does use its regular cutoff
413 :     recompilation mechanism. Therefore, dependencies must be given
414 :     explicitly. This is done by a special description file which
415 : blume 573 currently lives in ../system/smlnj/init/init.cmi. See the long comment
416 :     at the beginning of that file for more details.
417 : monnier 416
418 : blume 573 After it is built, smlnj/init/init.cmi can be used as an "ordinary" library
419 :     by other libraries. (This is done, for example, by the implementation of
420 :     the Basis library.) Access to "smlnj/init/init.cmi" is protected by the
421 : blume 569 privilege named "primitive". Also, note that the .cmi-file is not
422 :     automatically recognized as as CM description file. Therefore, it
423 :     must be given an explicit member class:
424 : blume 537
425 : blume 573 smlnj/init/init.cmi : cm
426 : blume 569
427 : monnier 416 * Autoloader
428 :     ------------
429 :    
430 :     The new system heavily relies on the autoloader. As a result, almost
431 : blume 569 no static environments need to get unpickled at bootstrap time. The
432 : monnier 416 construction of such environments is deferred until they become
433 : blume 569 necessary. Thanks of this, it was possible to reduce the size of the
434 :     heap image by more than one megabyte (depending on the architecture).
435 :     The downside (although not really terribly bad) is that there is a
436 :     short wait when you first touch an identifier that hasn't been touched
437 : monnier 416 before. (I acknowledge that the notion of "short" may depend on your
438 :     sense of urgency. :-)
439 :    
440 :     The reliance on the autoloader (and therefore CM's library mechanism)
441 :     means that in order to be able to use the system, your paths must be
442 :     properly configured.
443 :    
444 :     Two libraries get pre-registered at bootstap time: the basis library
445 : monnier 498 ("basis.cm") and CM itself ("minimal-cm.cm"). The latter is crucial:
446 : monnier 416 without it one wouldn't be able to register any other libraries
447 :     via CM.autoload. The registration of basis.cm is a mere convenience.
448 :    
449 :     Here are some other useful libraries that are not pre-registered but
450 :     which can easily be made accessible via CM.autoload (or, non-lazily,
451 :     via CM.make):
452 :    
453 : blume 573 smlnj/cm.cm - provides the actual ("full") structure CM
454 : monnier 498 as described in the CM manual
455 : blume 573 smlnj/cm/full.cm - same as smlnj/cm.cm
456 :     smlnj/compiler.cm - provides "structure Compiler"
457 :     smlnj/compiler/current.cm - same as smlnj/compiler.cm
458 :     smlnj/cmb.cm - provides "structure CMB"
459 :     smlnj/cmb/current.cm - same as smlnj/cmb.cm
460 :     smlnj/compiler/all.cm - provides "structure <Arch>Compiler" and
461 : monnier 416 "structure <Arch><OS>CMB" for various
462 :     values of <Arch> and <OS>
463 :     smlnj-lib.cm - the SML/NJ library
464 :    
465 :     * Internal sharing
466 :     ------------------
467 :    
468 :     Dynamic values of loaded modules are shared. This is true even for
469 :     those modules that are used by the interactive compiler itself. If
470 :     you load a module from a library that is also used by the interactive
471 :     compiler, then "loading" means "loading the static environmnent" -- it
472 :     does not mean "loading the code and linking it". Instead, you get to
473 :     share the compiler's dynamic values (and therefore the executable
474 :     code as well).
475 :    
476 :     Of course, if you load a module that hasn't been loaded before and
477 :     also isn't used by the interactive system, then CM will get the code
478 :     and link (execute) it.
479 :    
480 :     * Access control
481 :     ----------------
482 :    
483 :     In some places, you will find that the "group" and "library" keywords
484 :     in description files are preceeded by certain strings, sometimes in
485 :     parentheses. These strings are the names of "privileges". Don't
486 :     worry about them too much at the moment. For the time being, access
487 :     control is not enforced, but the infrastructure is in place.
488 :    
489 :     * Preprocessor
490 :     --------------
491 :    
492 :     The syntax of expressions in #if and #elif clauses is now more ML-ish
493 :     instead of C-ish. (Hey, this is ML after all!) In particular, you
494 :     must use "andalso", "orelse", and "not" instead of "&&", "||" and "!".
495 :     Unary minus is "~".
496 :    
497 :     A more interesting change is that you can now query the exports of
498 :     sources/subgroups/sublibraries:
499 :    
500 :     - Within the "members" section of the description (i.e., after "is"):
501 :     The expression
502 :     defined(<namespace> <name>)
503 :     is true if any of the included members preceeding this clause exports
504 :     a symbol "<namespace> <name>".
505 :     - Within the "exports" section of the description (i.e., before "is):
506 :     The same expression is true if _any_ of the members exports the
507 :     named symbol.
508 :     (It would be more logical if the exports section would follow the
509 :     members section, but for esthetic reasons I prefer the exports
510 :     section to come first.)
511 :    
512 :     Example:
513 :    
514 :     +--------------------------+
515 :     |Library |
516 :     | structure Foo |
517 :     |#if defined(structure Bar)|
518 :     | structure Bar |
519 :     |#endif |
520 :     |is |
521 :     |#if SMLNJ_VERSION > 110 |
522 :     | new-foo.sml |
523 :     |#else |
524 :     | old-foo.sml |
525 :     |#endif |
526 :     |#if defined(structure Bar)|
527 :     | bar-client.sml |
528 :     |#else |
529 :     | no-bar-so-far.sml |
530 :     |#endif |
531 :     +--------------------------+
532 :    
533 :     Here, the file "bar-client.sml" gets included if SMLNJ_VERSION is
534 :     greater than 110 and new-foo.sml exports a structure Bar _or_ if
535 :     SMLNJ_VERSION <= 110 and old-foo.sml exports structure Bar. Otherwise
536 :     "no-bar-so-far.sml" gets included instead. In addition, the export of
537 :     structure Bar is guarded by its own existence. (Structure Bar could
538 :     also be defined by "no-bar-so-far.sml" in which case it would get
539 :     exported regardless of the outcome of the other "defined" test.)
540 :    
541 :     Some things to note:
542 :    
543 :     - For the purpose of the pre-processor, order among members is
544 :     significant. (For the purpose of dependency analysis, order continues
545 :     to be not significant).
546 :     - As a consequence, in some cases pre-processor dependencies and
547 :     compilation-dependencies may end up to be opposites of each other.
548 :     (This is not a problem; it may very well be a feature.)
549 :    
550 :     * The Basis Library is no longer built-in
551 :     -----------------------------------------
552 :    
553 :     The SML'97 basis is no longer built-in. If you want to use it, you
554 :     must specify "basis.cm" as a member of your group/library.
555 :    
556 :     * No more aliases
557 :     -----------------
558 :    
559 :     The "alias" feature is no longer with us. At first I thought I could
560 :     keep it, but it turns out that it causes some fairly fundamental
561 :     problems with the autoloader. However, I don't think that this is a
562 :     big loss because path anchors make up for most of it. Moreover,
563 :     stable libraries can now easily be moved to convenient locations
564 :     without having to move large source trees at the same time. (See my
565 :     new build/install.sh script for examples of that.)
566 :    
567 : blume 573 It is possible to simulate aliases (in a way that is safer than the
568 :     original alias mechanism). For example, the root.cm file (which is the
569 :     root of the whole system as far as CMB.make is concerned) acts as an
570 :     alias for smlnj/internal/intsys.cm. In this case, root.cm is a group
571 :     to avoid having a (trivial) stable library file built for it.
572 :    
573 :     A library can act as an "alias" for another library if it has a
574 :     verbatim copy of the export list and mentions the other library as its
575 :     only member. Examples for this are smlnj/cm.cm (for smlnj/cm/full.cm),
576 :     smlnj/compiler.cm (for smlnj/compiler/current.cm), etc.
577 :    
578 : monnier 416 * Don't use relative or absolute pathnames to refer to libraries
579 :     ----------------------------------------------------------------
580 :    
581 :     Don't use relative or absolute pathnames to refer to libraries. If
582 :     you do it anyway, you'll get an appropriate warning at the time when
583 : blume 569 you do CMB.make(). If you use relative or absolute pathnames to
584 : monnier 416 refer to library B from library A, you will be committed to keeping B
585 :     in the same relative (to A) or absolute location. This, clearly,
586 :     would be undesirable.

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0