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 537 - (view) (download)

1 : blume 537 Compiler Hacker's Guide to the new CM...
2 :     ========================================
3 : monnier 416
4 : blume 537 Last change: 2/2000
5 :    
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 :     * basis.cm - The SML'97 basis library
23 :     - cm-hook.cm - an internal library for organizational purposes
24 :     - cm-lib.cm - the library that implements CM's functionality
25 :     * comp-lib.cm - a helper library for the compiler, MLRISC, and CM
26 : monnier 498 * full-cm.cm - the library that exports the public interface to
27 : monnier 416 the compilation manager (i.e., structure CM)
28 : monnier 498 * minimal-cm.cm - exports a reduced version of structure CM;
29 :     this one is pre-registered at the top level
30 : monnier 416 * host-cmb.cm - the library that exports the public interface to
31 :     the bootstrap compiler (i.e., structure CMB)
32 :     - host-compiler-0.cm
33 :     - an internal library for organizational purposes
34 :     * host-compiler.cm
35 :     - the library that exports the public interface to
36 :     the visible compiler (i.e., structure Compiler)
37 :     - intsys.cm - an internal library for organizational purposes
38 :     (In fact, its the "root" of the main hierarchy.)
39 :     * ml-yacc-lib.cm - needs no further comment
40 :     * smlnj-lib.cm - needs no further comment
41 : monnier 498 * <arch>-compiler.cm - exports the Compiler structure for the
42 :     given architecture (<Arch>Compiler).
43 :     * <arch>-<os>.cm - exports <Arch><OS>CMB for the given architecture-
44 :     OS combination.
45 : monnier 416 * target-compilers.cm
46 :     - library exporting target-specific versions of
47 : monnier 498 structure Compiler and of structure CMB.
48 :     This is a summary of all the <arch>-compiler.cm
49 :     and <arch>-<os>.cm libraries above.
50 :     (The existence of these libraries is the moral
51 : monnier 416 equivalent of "CMB.retarget" in the old CM.)
52 : monnier 498 * viscomp-core.cm - library that implements the machine-independent
53 :     core of the compiler.
54 :     * viscomp-<arch>.cm - library that implements the visible compiler
55 :     for a given architecture.
56 : monnier 416
57 :     * Before you can use the bootstrap compiler (CMB)...
58 :     ----------------------------------------------------
59 :    
60 :     To be able to use CMB at all, you must first say
61 :    
62 :     CM.autoload "host-cmb.cm";
63 :    
64 :     after you start sml.
65 :    
66 :     * Compiling the compiler -- a two-step procedure
67 :     ------------------------------------------------
68 :    
69 :     Until now (with the old CM), once we managed to run CMB.make() to
70 :     completion we had a directory full of binfiles that were ready to be
71 :     used by the boot procedure. This is no longer the case.
72 :    
73 :     The boot procedure now wants to use stable libraries (except for the
74 :     part that makes up the pervasive environment). Having stable
75 :     libraries around during development of these very libraries would be a
76 :     bit annoying because if CM sees a stable library it will no longer
77 :     bother to check the corresponding source files -- even if they have
78 :     changed. Therefore, libraries are not stabilized until you think you
79 :     are ready for that. Thus, you should run:
80 :    
81 :     CMB.make ();
82 :    
83 :     until you no longer get compile errors. CMB.make will return true in
84 :     this case. Then you say:
85 :    
86 :     CMB.deliver ();
87 :    
88 :     This command creates a second directory parallel to the "bin"
89 :     directory -- the "boot" directory. It will hold everything necessary
90 :     to bootstrap a new heap image. You will probably find that
91 :     CMB.deliver() compiles a number of additional files even though
92 :     CMB.make completed successfully. This is because CMB.make compiles
93 :     just those modules that will actually go into the heap image, but
94 :     CMB.deliver must also build the remaining files -- files that are part
95 :     of libraries to be stabilized but which are not used by the compiler.
96 :    
97 : monnier 498 You can reduce the number of extra files compiled and stabilized
98 :     during CMB.deliver at the expense of not building any cross-compilers.
99 :     For that, say
100 :     #set (CMB.symval "LIGHT") (SOME 1);
101 :     before running CMB.deliver.
102 :    
103 : monnier 416 After you have made the boot directory, if you want to continue
104 :     developing the compiler (i.e., make changes to some sources,
105 :     recompile, etc.), you must first get rid of that boot directory.
106 :     Running the "makeml" script (see below) will automatically remove the
107 :     boot directory.
108 :    
109 :     The names of "bin" and "boot" directories are
110 :    
111 :     <prefix>.bin.<arch>-<os>
112 :    
113 :     and
114 :    
115 :     <prefix>.boot.<arch>-<os>
116 :    
117 : monnier 498 respectively, with "sml" being the default for <prefix>. To change
118 : monnier 416 the prefix, use CMB.make' and CMB.deliver' with the new prefix
119 :     provided as the optional string argument to these functions.
120 :    
121 :     * Making the heap image
122 :     -----------------------
123 :    
124 :     The heap image is made by running the "makeml" script that you find
125 :     here in this directory. By default it will try to refer to the
126 : monnier 498 sml.boot.<arch>-<os> directory. You can change this using the -boot
127 : monnier 416 argument (which takes the full name of the boot directory to be used).
128 :    
129 :     The "feel" of using makeml should be mostly as it used to. However,
130 :     internally, there are some changes that you should be aware of:
131 :    
132 :     1. The script will make a heap image and also move its associated
133 :     libraries into a separate directory.
134 :    
135 :     2. There is no "-full" option anymore. This functionality should
136 :     eventually be provided by a library with a sufficiently rich export
137 :     interface.
138 :    
139 :     3. No image will be generated if you use the -rebuild option.
140 :     Instead, the script quits after making new bin and new boot
141 :     directories. You must re-invoke makeml with a suitable "-boot"
142 :     option to actually make the image. The argument to "-rebuild"
143 :     is the <prefix> for the new bin and boot directories (see above).
144 :    
145 :     4. Unless you use "-rebuild", makeml will delete the boot directory
146 :     (thus readying you for further "CMB.make();" runs).
147 :    
148 :     * Testing a newly generated heap image
149 :     --------------------------------------
150 :    
151 :     If you use a new heap image by saying "sml @SMLload=..." then things
152 :     will not go as you may expect because along with the new heap image
153 :     should go those new stable libraries, but unless you do something
154 :     about it, the new CM will look for its stable libraries in places
155 :     where you stored your _old_ stable libraries.
156 :    
157 :     After you have made the new heap image, the new libraries are in a
158 :     separate directory whose name is derived from the name of the heap
159 : monnier 429 image. The "testml" script that you also find here will run the heap
160 : monnier 416 image and instruct it to look for its libraries in that new library
161 :     directory.
162 :    
163 : monnier 498 "testml" takes the <prefix> of the heap image as its first
164 :     argument. All other arguments are passed verbatim to the ML process.
165 :    
166 :     The <prefix> is the same as the one used when you did "makeml". If
167 :     you run "testml" without arguments, <prefix> defaults to "sml".
168 :     Thus, if you just said "makeml" without argument you can also say
169 :     "testml" without argument. (Note that you _must_ supply the <prefix>
170 :     argument if you intend to pass any additional arguments.)
171 :    
172 : monnier 416 * Installing a heap image for more permanent use
173 :     ------------------------------------------------
174 :    
175 : monnier 498 You can "install" a newly generated heap image by replacing the old
176 :     image with the new one _AND AT THE SAME TIME_ replacing the old stable
177 :     libaries with the new ones. To do this, run the "installml" script.
178 : monnier 416
179 : monnier 498 Like "testml", "installml" also expects the <prefix> as its first
180 :     argument. <prefix> defaults to "sml" if no argument is specified.
181 :    
182 :     "installml" patches the ../../lib/pathconfig file to reflect any
183 :     changes or additions to the path name mapping.
184 :    
185 :     Thus, after a successful CMB.deliver, you should say
186 :    
187 :     ./makeml
188 :    
189 :     to make the new heap image + libraries, then
190 :    
191 :     ./testml
192 :    
193 :     to make sure everything works, and finally
194 :    
195 :     ./installml
196 :    
197 :     to replace your existing compiler with the one you just built and tested.
198 :    
199 : monnier 416 * Cross-compiling
200 :     -----------------
201 :    
202 :     All cross-compilers live in the "target-compilers.cm" library. You
203 :     must first say
204 :    
205 :     CM.autoload "target-compilers.cm";
206 :    
207 :     before you can access them. (This step corresponds to the old
208 :     CMB.retarget call.) After that, _all_ cross-compilers are available
209 :     at the same time. However, the ones that you are not using don't take
210 :     up any undue space because they only get loaded once you actually
211 :     mention them at the top-level. The names of the structures currently
212 :     exported by target-compilers.cm are:
213 :    
214 :     structure Alpha32UnixCMB
215 :     structure HppaUnixCMB
216 :     structure PPCMacOSCMB
217 :     structure PPCUnixCMB
218 :     structure SparcUnixCMB
219 :     structure X86UnixCMB
220 :     structure X86Win32CMB
221 :    
222 :     structure Alpha32Compiler
223 :     structure HppaCompiler
224 :     structure PPCCompiler
225 :     structure SparcCompiler
226 :     structure X86Compiler
227 :    
228 :     (PPCMacOSCMB is not very useful at the moment because there is no
229 :     implementation of the basis library for the MacOS.)
230 :    
231 : monnier 498 Alternatively, you can select just the one single structure that you
232 :     are interested in by auto-loading <arch>-compiler.cm or <arch>-<os>.cm.
233 :     <arch> currently ranges over "alpha32", "hppa", "ppc", "sparc", and "x86.
234 :     <os> can be either "unix" or "macos" or "win32".
235 :     (Obviously, not all combinations are valid.)
236 :    
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 :     and then:
342 :    
343 : monnier 429 rm -r ../../lib/*.cm
344 :     mv <image>.libs/*.cm ../../lib
345 : monnier 416
346 : monnier 429 For convenience, there is a script called "installml" that automates
347 :     this task. Using the script has the added advantage that it will not
348 :     clobber libraries that belong to other than the current architecture.
349 :     (The rather heavy-handed "rm/mv" approach above will delete all stable
350 : monnier 498 libraries for all architectures.) "installml" also patches the
351 :     ../../lib/pathconfig file as necessary.
352 : monnier 429
353 : monnier 416 Of course, you can organize things differently for yourself -- the
354 :     path configuration mechanism should be sufficiently flexible.
355 :    
356 :     * Libraries vs. Groups
357 :     ----------------------
358 :    
359 :     With the old CM, "group" was the primary concept while "library" and
360 :     "stabilization" could be considered afterthoughts. This has changed.
361 :     Now "library" is the primary concept, "stabilization" is semantically
362 :     significant, and "groups" are a secondary mechanism.
363 :    
364 :     Libraries are used to "structure the world"; groups are used to give
365 :     structure to libraries. Each group can be used either in precisely
366 :     one library (in which case it cannot be used at the interactive
367 :     toplevel) or at the toplevel (in which case it cannot be used in any
368 :     library). In other words, if you count the toplevel as a library,
369 :     then each group has a unique "owner" library. Of course, there still
370 :     is no limit on how many times a group can be mentioned as a member of
371 :     other groups -- as long as all these other groups belong to the same
372 :     owner library.
373 :    
374 :     If you want to take a collection of files whose purpose fits that of a
375 :     library, then, please, make them into a library (i.e., not a group!).
376 :     The purpose of groups is to deal with name-space issues _within_
377 :     libraries.
378 :    
379 :     Aside from the fact that I find this design quite natural, there is
380 :     actually a technical reason for it: when you stabilize a library
381 :     (groups cannot be stabilized), then all its sub-groups (not
382 :     sub-libraries!) get "sucked into" the stable archive of the library.
383 :     In other words, even if you have n+1 CM description files (1 for the
384 :     library, n for n sub-groups), there will be just one file representing
385 :     the one stable archive (per architecture/os) for the whole thing. For
386 :     example, I structured the standard basis into one library with two
387 :     sub-groups, but once you compile it (CMB.deliver) there is only one
388 :     stable file that represents the whole basis library. If groups were
389 :     allowed to appear in more than one library, then stabilization would
390 :     duplicate the group (its code, its environment data structures, and
391 :     even its dynamic state).
392 :    
393 :     There is a small change to the syntax of group description files: they
394 :     must explicitly state which library they belong to. CM will verify
395 :     that. The owner library is specified in parentheses after the "group"
396 :     keyword. If the specification is missing (that's the "old" syntax),
397 :     then the the owner will be taken to be the interactive toplevel.
398 :    
399 : blume 537 * Pervasive environment, core environment, the init group "init.cmi"
400 : monnier 416 -------------------------------------------------------------------------
401 :    
402 : blume 537 CMB.make (or CMB.deliver) starts out by building and compiling the
403 :     "init group". This group cannot be described in the "usual" way
404 :     because it uses "magic" in three ways:
405 :     - it is used to later tie in the runtime system
406 :     - it builds the "core" environment
407 :     - it builds the "pervasive" environment
408 : monnier 416
409 : blume 537 The pervasive environment no longer includes the entire basis library
410 :     but only non-modular bindings (top-level bindings of variables and
411 :     types).
412 :    
413 :     CM cannot automatically determine dependencies for the init group
414 : monnier 416 source files, but it still does use its regular cutoff recompilation
415 :     mechanism. Therefore, dependencies must be given explicitly. This is
416 :     done by a special description file which currently lives in
417 :     Init/init.cmi. See the long comment at the beginning of that file for
418 :     more details.
419 :    
420 : blume 537 After it is built, init.cmi can be used as an "ordinary" library by
421 :     other libraries. (This is done, for example, by the implementation of
422 :     the Basis library.) Access to "init.cmi" is protected by the
423 :     privilege named "primitive".
424 :    
425 : monnier 416 * Autoloader
426 :     ------------
427 :    
428 :     The new system heavily relies on the autoloader. As a result, almost
429 :     no static environments need to get unpickled at bootstap time. The
430 :     construction of such environments is deferred until they become
431 :     necessary. Because of this, I was able to reduce the size of the heap
432 :     image by more than one megabyte (depending on the architecture). The
433 :     downside (although not really terribly bad) is that there is a short
434 :     wait when you first touch an identifier that hasn't been touched
435 :     before. (I acknowledge that the notion of "short" may depend on your
436 :     sense of urgency. :-)
437 :    
438 :     The reliance on the autoloader (and therefore CM's library mechanism)
439 :     means that in order to be able to use the system, your paths must be
440 :     properly configured.
441 :    
442 :     Two libraries get pre-registered at bootstap time: the basis library
443 : monnier 498 ("basis.cm") and CM itself ("minimal-cm.cm"). The latter is crucial:
444 : monnier 416 without it one wouldn't be able to register any other libraries
445 :     via CM.autoload. The registration of basis.cm is a mere convenience.
446 :    
447 :     Here are some other useful libraries that are not pre-registered but
448 :     which can easily be made accessible via CM.autoload (or, non-lazily,
449 :     via CM.make):
450 :    
451 : monnier 498 full-cm.cm - provides the actual ("full") structure CM
452 :     as described in the CM manual
453 : monnier 416 host-compiler.cm - provides "structure Compiler"
454 :     host-cmb.cm - provides "structure CMB"
455 :     target-compilers.cm - provides "structure <Arch>Compiler" and
456 :     "structure <Arch><OS>CMB" for various
457 :     values of <Arch> and <OS>
458 :     smlnj-lib.cm - the SML/NJ library
459 :    
460 :     * Internal sharing
461 :     ------------------
462 :    
463 :     Dynamic values of loaded modules are shared. This is true even for
464 :     those modules that are used by the interactive compiler itself. If
465 :     you load a module from a library that is also used by the interactive
466 :     compiler, then "loading" means "loading the static environmnent" -- it
467 :     does not mean "loading the code and linking it". Instead, you get to
468 :     share the compiler's dynamic values (and therefore the executable
469 :     code as well).
470 :    
471 :     Of course, if you load a module that hasn't been loaded before and
472 :     also isn't used by the interactive system, then CM will get the code
473 :     and link (execute) it.
474 :    
475 :     * Access control
476 :     ----------------
477 :    
478 :     In some places, you will find that the "group" and "library" keywords
479 :     in description files are preceeded by certain strings, sometimes in
480 :     parentheses. These strings are the names of "privileges". Don't
481 :     worry about them too much at the moment. For the time being, access
482 :     control is not enforced, but the infrastructure is in place.
483 :    
484 :     * Preprocessor
485 :     --------------
486 :    
487 :     The syntax of expressions in #if and #elif clauses is now more ML-ish
488 :     instead of C-ish. (Hey, this is ML after all!) In particular, you
489 :     must use "andalso", "orelse", and "not" instead of "&&", "||" and "!".
490 :     Unary minus is "~".
491 :    
492 :     A more interesting change is that you can now query the exports of
493 :     sources/subgroups/sublibraries:
494 :    
495 :     - Within the "members" section of the description (i.e., after "is"):
496 :     The expression
497 :     defined(<namespace> <name>)
498 :     is true if any of the included members preceeding this clause exports
499 :     a symbol "<namespace> <name>".
500 :     - Within the "exports" section of the description (i.e., before "is):
501 :     The same expression is true if _any_ of the members exports the
502 :     named symbol.
503 :     (It would be more logical if the exports section would follow the
504 :     members section, but for esthetic reasons I prefer the exports
505 :     section to come first.)
506 :    
507 :     Example:
508 :    
509 :     +--------------------------+
510 :     |Library |
511 :     | structure Foo |
512 :     |#if defined(structure Bar)|
513 :     | structure Bar |
514 :     |#endif |
515 :     |is |
516 :     |#if SMLNJ_VERSION > 110 |
517 :     | new-foo.sml |
518 :     |#else |
519 :     | old-foo.sml |
520 :     |#endif |
521 :     |#if defined(structure Bar)|
522 :     | bar-client.sml |
523 :     |#else |
524 :     | no-bar-so-far.sml |
525 :     |#endif |
526 :     +--------------------------+
527 :    
528 :     Here, the file "bar-client.sml" gets included if SMLNJ_VERSION is
529 :     greater than 110 and new-foo.sml exports a structure Bar _or_ if
530 :     SMLNJ_VERSION <= 110 and old-foo.sml exports structure Bar. Otherwise
531 :     "no-bar-so-far.sml" gets included instead. In addition, the export of
532 :     structure Bar is guarded by its own existence. (Structure Bar could
533 :     also be defined by "no-bar-so-far.sml" in which case it would get
534 :     exported regardless of the outcome of the other "defined" test.)
535 :    
536 :     Some things to note:
537 :    
538 :     - For the purpose of the pre-processor, order among members is
539 :     significant. (For the purpose of dependency analysis, order continues
540 :     to be not significant).
541 :     - As a consequence, in some cases pre-processor dependencies and
542 :     compilation-dependencies may end up to be opposites of each other.
543 :     (This is not a problem; it may very well be a feature.)
544 :    
545 :     * The Basis Library is no longer built-in
546 :     -----------------------------------------
547 :    
548 :     The SML'97 basis is no longer built-in. If you want to use it, you
549 :     must specify "basis.cm" as a member of your group/library.
550 :    
551 :     * No more aliases
552 :     -----------------
553 :    
554 :     The "alias" feature is no longer with us. At first I thought I could
555 :     keep it, but it turns out that it causes some fairly fundamental
556 :     problems with the autoloader. However, I don't think that this is a
557 :     big loss because path anchors make up for most of it. Moreover,
558 :     stable libraries can now easily be moved to convenient locations
559 :     without having to move large source trees at the same time. (See my
560 :     new build/install.sh script for examples of that.)
561 :    
562 :     * Don't use relative or absolute pathnames to refer to libraries
563 :     ----------------------------------------------------------------
564 :    
565 :     Don't use relative or absolute pathnames to refer to libraries. If
566 :     you do it anyway, you'll get an appropriate warning at the time when
567 :     you do CMB.deliver(). If you use relative or absolute pathnames to
568 :     refer to library B from library A, you will be committed to keeping B
569 :     in the same relative (to A) or absolute location. This, clearly,
570 :     would be undesirable.

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