File: Makefile.pamphlet

package info (click to toggle)
axiom 20170501-4
  • links: PTS
  • area: main
  • in suites: buster
  • size: 1,048,504 kB
  • sloc: lisp: 3,600; makefile: 505; cpp: 223; ansic: 138; sh: 96
file content (869 lines) | stat: -rw-r--r-- 33,047 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
\documentclass{article}
\usepackage{axiom}
\begin{document}
\title{\$SPAD/src/interp Makefile}
\author{Timothy Daly}
\maketitle
\begin{abstract}
\end{abstract}
\eject
\tableofcontents
\eject
\section{Notes}
Notes for understanding this makefile:

IMPORTANT: all source file names in this Makefile must be lowercase
This is for cross-platform compatibility and also makes getting
them into Lisp much easier at the Makefile level.

\section{The Environment}
We define 4 directories for this build. The first three are
the traditional {\bf IN}, which is where the source pamphlets are,
{\bf MID} which is where we will put the compiled intermediates and
{\bf OUT} which is where we will put the binaries.

In this case the {\bf IN} files are usually written in {\bf boot} \cite{2}.
These will be compiled in a {\bf BOOTSYS} image to translate from
{\bf boot} to Common Lisp. Since the Common Lisp code is 
system independent and machine generated code the {\bf MID} directory
is built in the {\bf \$SPAD/int} subtree. See the 
{\bf \$SPAD/Makefile.pamphlet} \cite{1} file for more details.

The Common Lisp code will be compiled from the {\bf MID} directory
into the {\bf OUT} directory. This is system-dependent,
machine-generated code and belongs in the {\bf \$SPAD/obj} subtree.

The dvi files will be generated from the pamphlet files in the
final ship doc/src/ directory. Since they are system independent 
but machine generated and part of the final ship they will exist 
in {\bf \$SPAD/mnt/sys/doc/src/interp}.

\begin{chunk}{environment}
IN=${SRC}/interp
MID=${INT}/interp
OUT=${OBJ}/${SYS}/interp
DOC=${MNT}/${SYS}/doc/src/interp
BOOK=${MNT}/${SYS}/doc

\end{chunk}

In order to minimize the size of the Axiom image at load time
we put some of the compiled files into a separate directory
that will be autoloaded on demand. This directory of code
will be shipped with the final system and so it belongs in
the {\bf \$SPAD/mnt} subtree.
\begin{chunk}{environment}
AUTO=${MNT}/${SYS}/autoload

\end{chunk}

We need a raw lisp image that we can use as a base to construct
the other images. This is called {\bf LISPSYS} and is 
system-dependent and machine-generated.
It belongs in the {\bf \$SPAD/obj} subtree.
\begin{chunk}{environment}
LISPSYS= ${OBJ}/${SYS}/bin/lisp

\end{chunk}

We need to extract the Numerics chunk from bookvol10.5. We do 
this using the tangle function in the lisp image.
\begin{chunk}{environment}
LISPTANGLE= ${OBJ}/${SYS}/bin/lisp

\end{chunk}

Most of the interpreter is written in {\bf boot} \cite{2}.
Thus we need a program to translate {\bf boot} to Common
Lisp. This is called the {\bf BOOTSYS} image (because the
translator is written in {\bf boot} and needs to translate
itself to bootstrap the system). This image is assumed to
have been built by a previous step in the make process.
\begin{chunk}{environment}
BOOTSYS= ${OBJ}/${SYS}/bin/bootsys    

\end{chunk}

Some of the Common Lisp code we compile uses macros which
are assumed to be available at compile time. The {\bf DEPSYS}
image is created to contain the compile time environment
and saved. We pipe compile commands into this environment
to compile from Common Lisp to machine dependent code.

\begin{chunk}{environment}
DEPSYS=	${OBJ}/${SYS}/bin/depsys

\end{chunk}

The {\bf DEP} variable contains the list of files that
will be loaded into {\bf DEPSYS}. Notice that these files
are loaded in interpreted form. We are not concerned about
the compile time performance so we can use interpreted code.
We do, however, care about the macros as these will be
expanded in later compiles. All macros are assumed to be
in this list of files.
\begin{chunk}{environment}
DEP= ${MID}/vmlisp.lisp

\end{chunk}

Once we've compile all of the Common Lisp files we fire up
a clean lisp image called {\bf LOADSYS}, load all of the
final executable code and save it out as {\bf SAVESYS}.
The {\bf SAVESYS} image is copied to the \verb|${MNT}/${SYS}/bin|
subdirectory and becomes the axiom executable image.
\begin{chunk}{environment}
LOADSYS= ${OBJ}/${SYS}/bin/lisp
SAVESYS= ${OBJ}/${SYS}/bin/interpsys
AXIOMSYS= ${MNT}/${SYS}/bin/AXIOMsys

\end{chunk}

Occasionally we need to really get into the system internals.
The best way to do this is to run almost all of the lisp code
interpreted rather than compiled (note that cfuns.lisp and sockio.lisp
still need to be loaded in compiled form as they depend on the 
loader to link with lisp internals). This image is nothing more
than a load of the file src/interp/debugsys.lisp.pamphlet. If
you need to make test modifications you can add code to that
file and it will show up here.
\begin{chunk}{environment}
DEBUGSYS=${OBJ}/${SYS}/bin/debugsys

\end{chunk}

These are the files that need to be compiled (in {\bf BOOTSYS}),
loaded into a clean lisp image ({\bf LOADSYS}) and saved as
a runnable Axiom interpreter ({\bf SAVESYS}) usually named
{\bf interpsys}. Most of these files
are translated from {\bf boot} to Common Lisp and then 
compiled. There are two exceptions, {\bf bootfuns.lisp}
and {\bf setq.lisp}. The {\bf bootfuns.lisp} \cite{3} file
contains forward references for {\bf boot} code. The {\bf setq.lisp}
file contains constant initialization code which gains nothing
by being compiled.

The file http.lisp contains code to enable browser-based hyperdoc
and graphics.
\begin{chunk}{environment}
OBJS= ${OUT}/vmlisp.${O}      \
      ${OUT}/buildom.${O} \
      ${OUT}/cattable.${O}    \
      ${OUT}/cfuns.${O} \
      ${OUT}/clam.${O}        ${OUT}/clammed.${O} \
      ${OUT}/compress.${O} \
      ${OUT}/format.${O} \
      ${OUT}/g-boot.${O}      ${OUT}/g-cndata.${O} \
      ${OUT}/g-error.${O}     \
      ${OUT}/g-timer.${O}     ${OUT}/g-util.${O} \
      ${OUT}/http.${O} \
      ${OUT}/hypertex.${O}    ${OUT}/i-analy.${O} \
      ${OUT}/i-code.${O}      ${OUT}/i-coerce.${O} \
      ${OUT}/i-coerfn.${O}    ${OUT}/i-eval.${O} \
      ${OUT}/i-funsel.${O}    ${OUT}/bookvol5.${O} \
      ${OUT}/bookvol9.${O}    ${OUT}/bookvol10.5.${O}\
      ${OUT}/i-intern.${O}    ${OUT}/i-map.${O} \
      ${OUT}/i-output.${O}    ${OUT}/i-resolv.${O} \
      ${OUT}/i-spec1.${O}    \
      ${OUT}/i-spec2.${O}    \
      ${OUT}/i-util.${O} \
      ${OUT}/lisplib.${O}  \
      ${OUT}/match.${O}    \
      ${OUT}/msgdb.${O}    \
      ${OUT}/newfort.${O} \
      ${OUT}/nrunfast.${O} \
      ${OUT}/nrungo.${O}      ${OUT}/nrunopt.${O} \
      ${OUT}/posit.${O}       \
      ${OUT}/record.${O}      \
      ${OUT}/rulesets.${O} \
      ${OUT}/server.${O}    \
      ${OUT}/simpbool.${O}    ${OUT}/slam.${O} \
      ${OUT}/sockio.${O}      \
      ${OUT}/template.${O}    ${OUT}/termrw.${O} \
      ${OUT}/fortcall.${O} \
      ${OUT}/parsing.${O}  \
      ${OUT}/c-util.${O}      ${OUT}/profile.${O}  \
      ${OUT}/category.${O}    \
      ${OUT}/functor.${O}  \
      ${OUT}/info.${O}        ${OUT}/iterator.${O} \
      ${OUT}/nruncomp.${O} 

\end{chunk}

\begin{verbatim}
      sfsfun.lisp.pamphlet contains 0F1 code
\end{verbatim}

Before we save the {\bf SAVESYS} image we need to run some
initialization code. These files perform initialization
for various parts of the system. The {\bf patches.lisp} \cite{5}
file contains last-minute changes to various functions and
constants.
\begin{chunk}{environment}
INOBJS=	 ${OUT}/patches.${O}

\end{chunk}

Certain functions do not need to be in the running system.
If the running image never calls the compiler or does not
use the hypertex browser we will never call the functions
in these files. The code that calls these functions in the
running system will autoload the appropriate files the
first time they are called. Loading the files overwrites
the autoload function call and re-calls the function. 
Any subsequent calls will run the compiled code.

The {\bf OPOBJS} list contains files from the old parser. The use of
``old'' is something of a subtle concept as there were several
generations of ``old'' and all meaning of the term is lost.

\begin{chunk}{environment}
# These are autloaded old parser files
OPOBJS=	
\end{chunk}

The {\bf OCOBJS} list contains files from the old compiler. Again,
``old'' is meaningless. These files should probably be autoloaded.
\begin{chunk}{environment}tpdhere
OCOBJS=	
\end{chunk}

The {\bf BROBJS} list contains files only used by the hypertex
browser. These files should probably be autoloaded.
\begin{chunk}{environment}
BROBJS=	${AUTO}/br-con.${O}	\
	${AUTO}/topics.${O}     

\end{chunk}

The {\bf NAGBROBJS} list contains files used to access the 
Numerical Algorithms Group (NAG) fortran libraries. 
These files should probably be autoloaded.
Note that \verb|${AUTO}/nag-e02a.${O}| is not included in this
list as it is a subset of \verb|${AUTO}/nag-e02.${O}|.
\begin{chunk}{environment}
NAGBROBJS= ${AUTO}/nag-c02.${O}   ${AUTO}/nag-c05.${O} \
           ${AUTO}/nag-c06.${O}   ${AUTO}/nag-d01.${O} \
           ${AUTO}/nag-d02.${O}   ${AUTO}/nag-d03.${O} \
           ${AUTO}/nag-e01.${O}   ${AUTO}/nag-e02.${O} \
           ${AUTO}/nag-e04.${O}   ${AUTO}/nag-f01.${O} \
           ${AUTO}/nag-f02.${O}   ${AUTO}/nag-f04.${O} \
           ${AUTO}/nag-f07.${O}   ${AUTO}/nag-s.${O} 

\end{chunk}
The {\bf ASCOMP} list contains files used by the {\bf Aldor}
\cite{5} compiler. These files should probably be autoloaded.
\begin{chunk}{environment}
ASCOMP= ${OUT}/hashcode.${O}

\end{chunk}

Axiom versions are given as a string of the form:
"Sunday September 21, 2003 at 20:38:05 "
which describe the day, date, and time of the build.
This is used for reporting bugs. It is only partially useful
in identifying which source code was used. Ideally we could create
a tar file of all of the date/time stamps of all of the source files
and use the MD5 hash of that file as the version stamp. Ultimately
though, this would be chasing the elusive "perfect information" idea.

A new variable \verb|boot::*build-version*| is set and used by the
{\tt yearweek} function to display the version number of the Axiom build.
This information is set by hand in the top level Makefile.
\begin{chunk}{environment}
TIMESTAMP=${MNT}/${SYS}/timestamp
YEARWEEK=(progn (setq timestamp "${TIMESTAMP}") \
                (setq boot::*build-version* "${VERSION}") \
                (yearweek))

\end{chunk}
The {\bf .PRECIOUS} setting will keep make from deleting these
images if the build is stopped. Since once they are built they
are likely to be useable we don't need to redo the work if they
exist.
\begin{chunk}{environment}

.PRECIOUS:	${BOOTSYS}
.PRECIOUS:	${DEPSYS}
.PRECIOUS:	${SAVESYS}
.PRECIOUS:	${AXIOMSYS}

\end{chunk}
\section{Proclaim optimization}
GCL, and possibly other common lisps, can generate much better
code if the function argument types and return values are proclaimed.

In theory what we should do is scan all of the functions in the system
and create a file of proclaim definitions. These proclaim definitions
should be loaded into the image before we do any compiles so they can
allow the compiler to optimize function calling.

GCL has an approximation to this scanning which we use here. 

The first step is to build a version of GCL that includes \verb|gcl_collectfn|.
This file contains code that enhances the lisp compiler and creates a
hash table of structs. Each struct in the hash table describes information
that about the types of the function being compiled and the types of its
arguments. At the end of the compile-file this hash table is written out
to a ".fn" file. 

The second step is to build axiom images (depsys, interpsys, AXIOMsys)
which contain the \verb|gcl_collectfn| code.

The third step is to build the system. This generates a .fn file for 
each lisp file that gets compiled.

The fourth step is to build the proclaims.lisp files. There is one
proclaims.lisp file for 
boot (boot-proclaims.lisp), 
interp (interp-proclaims.lisp), and 
algebra (algebra-proclaims.lisp).

To build the proclaims file (e.g. for interp) we:
\begin{verbatim}
(a) cd to obj/linux/interp
(b) (yourpath)/axiom/obj/linux/bin/lisp
(c) (load "sys-pkg.lsp") 
(d) (mapcar #'load (directory "*.fn"))
(e) (with-open-file 
     (out "interp-proclaims.lisp" :direction :output) 
      (compiler::make-proclaims out))
\end{verbatim}
Note that step (c) is only used for interp, not for boot.

The fifth step is to copy the newly constructed proclaims file back
into the src/interp diretory (or boot, algebra).

In order for this information to be used during compiles we define
\begin{chunk}{environment}
PROCLAIMS=(progn (load "${OUT}/sys-pkg.lsp") \
                 (load "${IN}/interp-proclaims.lisp"))

\end{chunk}

\section{The warm.data file}
This is a file of commands that will be loaded into interpsys
at the last minute. It execute functions that will likely be
used in a running system so all of the required routines will
be in the lisp image thus minimizing their startup time.
\begin{chunk}{warm.data.stanza}
${INT}/algebra/warm.data: 
	@ echo si001 building warm.data
	@ ${BOOKS}/tanglec ${IN}/Makefile.pamphlet warm.data >${INT}/algebra/warm.data

\end{chunk}
\begin{chunk}{warm.data}
(in-package 'boot)
(setq |$topicHash| (make-hash-table))
(setf (gethash '|basic| |$topicHash|) 2)
(setf (gethash '|algebraic| |$topicHash|) 4)
(setf (gethash '|miscellaneous| |$topicHash|) 13)
(setf (gethash '|extraction| |$topicHash|) 6)
(setf (gethash '|conversion| |$topicHash|) 7)
(setf (gethash '|hidden| |$topicHash|) 3)
(setf (gethash '|extended| |$topicHash|) 1)
(setf (gethash '|destructive| |$topicHash|) 5)
(setf (gethash '|transformation| |$topicHash|) 10)
(setf (gethash '|hyperbolic| |$topicHash|) 12)
(setf (gethash '|construct| |$topicHash|) 9)
(setf (gethash '|predicate| |$topicHash|) 8)
(setf (gethash '|trignometric| |$topicHash|) 11)

\end{chunk}
\section{Building DEPSYS}
The depsys image proceeds all else. it is the compile-time environment
for all interpreter code. 

The ``:oldboot'' symbol is pushed on the features list 
because there is a function
in util.lisp that emulates the new boot parser command BOOTTOCL. since
we eventually plan to move to the new boot parser this function (and
the push) should disappear.

The load of postpar and parse (without extensions) allows the 
\verb+.${LISP}+
form to be loaded in a virgin system. However, if depsys is recreated then
the compiled form will get loaded.

This file contained the only mention of the AKCLDIR variable which
gives the path to the version of AKCL. Now that the system is running
on GCL this variable has been renamed to GCLDIR. This cannot be eliminated
entirely because the system uses this variable to look up a file 
called collectfn.lsp which is part of the GCL distribution. This
file lookup is in conditional lisp code so other lisps will not 
see the file load. The collectfn.lsp code is used by GCL to generate
the ``.fn'' files which are used to optimize function calling.

\subsection{save depsys image}
Once the appropriate commands are in the \verb|${OUT}/makedep.lisp| file
we can load the file into a fresh image and save it. At least that's
how it used to work. In freebsd we cannot do this so we have to use
a much more complicated procedure.
This code used to read:
\begin{verbatim}
\begin{chunk}{save depsys image}
	@ (cd ${MNT}/${SYS}/bin ; \
	   echo '(progn (load "${OUT}/makedep.lisp")' \
                '(spad-save "${DEPSYS}"))' | ${LISPSYS})
\end{chunk}
\end{verbatim}

Now game is much more difficult. 
\begin{verbatim}

 '(progn \

\end{verbatim}

\verb|si::*collect-binary-modules*| instructs GCL to build a list of 
binary object modules loaded into the current session with (load ...)
The list will be stored in \verb|si::*binary-modules*|.
\begin{verbatim}

	       (setq si::*collect-binary-modules* t) \
	       (load "${OUT}/makedep.lisp") \

\end{verbatim}

\verb|compiler::link| is a lisp interface to the ``ld'' C-based system linker.
The first argumet is a list of .o binary object modules to link into a
fresh gcl image. The second argument is the name of the new output
image.  The third argument is a string containing an initialization
command to run in the new image to reinitialize the heap.  The fourth
argument is a list of external C libraries, either static or dynamic,
that one wishes to link into the fresh image.  The last argument is a
flag which indicates whether GCL should initialize all of the freshly
linked in new lisp modules, or whether it should transparently
redirect load calls in the new image to initialization calls for the
already linked in module.

Some lisp systems, such as acl2, have a complex heap initialization,
in which load calls must be interspersed with other form evaluation
comprising the logic of the heap construction.  Others, such as
maxima, have no such complex initialization sequence.
\begin{verbatim}
  (compiler::link \
\end{verbatim}
\verb|si::*binary-modules*| here has the list of compiled lisp binary module
.o files loaded by makedep.lsp above.
\begin{verbatim}
   (remove-duplicates si::*binary-modules* \
                      :test (quote equal)) \
\end{verbatim}

The name of the output image.
\begin{verbatim}
   "$(DEPSYS)" \
\end{verbatim}

This will be run in the newly linked sub-image.
\begin{verbatim}
    (format nil "\
\end{verbatim}

Collect loaded binary modules again to make sure that there are none,
as all should be already linked in via ld.  For error checking
purposes.
\begin{verbatim}
     (setq si::*collect-binary-modules* t) \
\end{verbatim}

We need to find \verb|gcl_collectfn.lsp|, so set the *load-path*, and make
sure the source, not the binary, form is loaded here, as we're only
using this entire sequence on machines which cannot load binary object
modules and preserve them in saved images.
\begin{verbatim}
     (let ((si::*load-path* (cons ~S si::*load-path*))\
           (si::*load-types* ~S))\
\end{verbatim}

Turn on function analyzation and autoload thereby \verb|gcl_collectfn.lsp|.
\begin{verbatim}
      (compiler::emit-fn t))\
\end{verbatim}

Load the heap creation sequence again in the fresh new image, this
time transparently redirecting all calls to load of binary modules
invoked thereby into initialization calls for the already linkned in
module.

Load has code in it to recognize when a module is already linked in,
and to forgo in this case the actual load and replace with a mere
initialization call instead.
\begin{verbatim}
      (load \"$(OUT)/makedep.lisp\")\
      (gbc t)\
\end{verbatim}

It is an error to load a binary module. Calling load will not
reload them but only run initialization.
Throw an error if we've actually loaded any binary modules.
\begin{verbatim}
     (when si::*binary-modules* \
       (error si::*binary-modules*))\
\end{verbatim}

Unset the binary module collection flags.
\begin{verbatim}
    (setq si::collect-binary-modules* nil \xo
          si::*binary-modules* nil)\
    (gbc t)\
\end{verbatim}

We need to forget the build time system paths per Camm Maguire's email
on July 14th, 2011
\begin{verbatim}
     (si::reset-sys-paths)
\end{verbatim}

Turn on SGC (Stratified Garbage Collection) in the final image.  This
is a optional gbc algorithm which is suitable for images which will
not grow much further.  It marks a large fraction of the heap
read-only, eliminating such pages from the time-consuming gbc
processing.  When writes are actually made to such pages, a segfault
is triggered which is handled by a function which remarks the pages
read-write and continues.
\begin{verbatim}
   (when (fboundp (quote si::sgc-on)) (si::sgc-on t))\
\end{verbatim}

This is a flag which instructs the GCL compiler to make unique
initialzation function C names.  This is necessary when using ld, as
all function names must be unique.
\begin{verbatim}
   (setq compiler::*default-system-p* t)\
\end{verbatim}
si::*system-directory* goes into the *load-path*, and .lsp in the *load-types*.
\begin{verbatim}
 " si::*system-directory* (quote (list ".lsp")))\
\end{verbatim}
No C libraries to link in here.
\begin{verbatim}
   "" \
\end{verbatim}

Do not run the initialization code for the newly linked in lisp
modules ``by hand'', but rather rely on the transparent load redirection
described above to initialize at the proper moment in the heap
initialization sequence.
\begin{verbatim}
     nil))' | $(LISPSYS))
\end{verbatim}

The save depsys image was supposed to read:
\begin{verbatim}
 @ (cd ${OBJ}/${SYS}/bin ; \
   echo '(progn' \
    '(setq si::*collect-binary-modules* t)' \
    '(load "${OUT}/makedep.lisp")' \
    '(compiler::link' \
      '(remove-duplicates si::*binary-modules*' \
                        ':test (quote equal))' \
      '"$(DEPSYS)"' \
      '(format nil' \
	 '"(setq si::*collect-binary-modules* t)' \
	  '(let ((si::*load-path* (cons ~S si::*load-path*))' \
	          '(si::*load-types* ~S))' \
	  	  '(compiler::emit-fn t))' \
	  '(load \"$(OUT)/makedep.lisp\")' \
	  '(gbc t)' \
	  '(when si::*binary-modules*' \
                '(error si::*binary-modules*))' \
	  '(setq si::collect-binary-modules* nil' \
                'si::*binary-modules* nil)' \
	  '(gbc t)' \
          '(si::reset-sys-paths)' \
	  '(when (fboundp (quote si::sgc-on)) (si::sgc-on t))' \
	  '(setq compiler::*default-system-p* t)"' \
         'si::*system-directory* (quote (list ".lsp")))'\
       '""' \
       'nil))' | $(LISPSYS))
\end{verbatim}

This scheme does not work. It fails during loading with multiple messages
of the form:
\begin{verbatim}
/home/axiom33/obj/linux/interp/parse.o(.text+0x5660): 
 In function `init_code':
  : multiple definition of `init_code'
/home/axiom33/obj/linux/interp/postpar.o(.text+0x4e78): 
  first defined here
\end{verbatim}
\begin{chunk}{depsys}
${DEPSYS}:	${DEP} ${OUT}/sys-pkg.${LISP} ${OUT}/nocompil.${LISP} \
	        ${OUT}/bookvol5.${LISP} ${OUT}/bookvol9.${LISP} \
                ${OUT}/util.${LISP} \
	        ${OUT}/parsing.${LISP} \
	        ${OUT}/g-boot.lisp ${OUT}/c-util.lisp \
	        ${OUT}/g-util.lisp \
	        ${OUT}/clam.lisp \
	        ${OUT}/slam.lisp ${LOADSYS}
	@ echo si002 making ${DEPSYS} 
	@ echo '${PROCLAIMS}' > ${OUT}/makedep.lisp
	@ echo '(push :oldboot *features*)' >>${OUT}/makedep.lisp
	@ echo '(load "${OUT}/nocompil")' >> ${OUT}/makedep.lisp
	@ echo '(load "${OUT}/bookvol5")' >> ${OUT}/makedep.lisp
	@ echo '(load "${OUT}/bookvol9")' >> ${OUT}/makedep.lisp
	@ echo '(load "${OUT}/util")' >> ${OUT}/makedep.lisp
	@ echo '(in-package "BOOT")' >> ${OUT}/makedep.lisp
	@ echo '(build-depsys (quote ($(patsubst %, "%", ${DEP})))' \
          '"${SPAD}" "${GCLDIR}" "${SRC}" "${INT}" "${OBJ}" "${MNT}"' \
          '"${SYS}")' >> ${OUT}/makedep.lisp
	@ echo '(unless (probe-file "${OUT}/parsing.${O}")' \
          '(compile-file "${OUT}/parsing.${LISP}"' \
          ':output-file "${OUT}/parsing.${O}"))' >> ${OUT}/makedep.lisp
	@ echo '(load "${OUT}/parsing")' >> ${OUT}/makedep.lisp
	@ echo '(unless (probe-file "${OUT}/clam.${O}")' \
          '(compile-file "${OUT}/clam.lisp"' \
          ':output-file "${OUT}/clam.${O}"))' >> ${OUT}/makedep.lisp
	@ echo '(load "${OUT}/clam")' >> ${OUT}/makedep.lisp
	@ echo '(unless (probe-file "${OUT}/slam.${O}")' \
          '(compile-file "${OUT}/slam.lisp"' \
          ':output-file "${OUT}/slam.${O}"))' >> ${OUT}/makedep.lisp
	@ echo '(load "${OUT}/slam")' >> ${OUT}/makedep.lisp
	@ echo '(unless (probe-file "${OUT}/g-boot.${O}")' \
          '(compile-file "${OUT}/g-boot.lisp"' \
          ':output-file "${OUT}/g-boot.${O}"))' >> ${OUT}/makedep.lisp
	@ echo '(load "${OUT}/g-boot")' >> ${OUT}/makedep.lisp
	@ echo '(unless (probe-file "${OUT}/c-util.${O}")' \
          '(compile-file "${OUT}/c-util.lisp"' \
          ':output-file "${OUT}/c-util.${O}"))' >> ${OUT}/makedep.lisp
	@ echo '(load "${OUT}/c-util")' >> ${OUT}/makedep.lisp
	@ echo '(unless (probe-file "${OUT}/g-util.${O}")' \
          '(compile-file "${OUT}/g-util.lisp"' \
          ':output-file "${OUT}/g-util.${O}"))' >> ${OUT}/makedep.lisp

	@ echo '(load "${OUT}/g-util")' >> ${OUT}/makedep.lisp
\getchunk{save depsys image}
	@ echo si003 ${DEPSYS} created

\end{chunk}
\section{Building SAVESYS and AXIOMSYS}
GCL likes to tell you when it has replaced a function call by a 
tail-recursive call. This happens when the last form in a function
is a call to the same function. In general, we don't care so we set
compiler::*suppress-compiler-notes* to true in order to reduce the noise.
\begin{chunk}{savesys}
${SAVESYS}:	${DEPSYS} ${OBJS} ${OUT}/bookvol5.${O} ${OUT}/util.${O} \
                ${OUT}/nocompil.${LISP} ${OUT}/sys-pkg.${LISP} \
	        ${OUTINTERP} ${BROBJS} \
		${OUT}/database.date ${INOBJS} ${ASCOMP} \
		${NAGBROBJS} \
	        ${LOADSYS} \
		${SRC}/doc/msgs/s2-us.msgs \
	        ${INT}/algebra/warm.data
	@ echo si004 invoking make in `pwd` with parms:
	@ echo SYS= ${SYS} 
	@ echo LSP= ${LSP} 
	@ echo PART= ${PART} 
	@ echo SPAD= ${SPAD} 
	@ echo SRC= ${SRC} 
	@ echo INT= ${INT}
	@ echo MID= ${MID} 
	@ echo OUT= ${OUT}
	@ echo OBJ= ${OBJ} 
	@ echo MNT= ${MNT} 
	@ echo O=${O} LISP=${LISP} BYE=${BYE}
	@ cp -p ${OUT}/*.fn ${MID}
	@ cp -p ${SRC}/doc/msgs/s2-us.msgs ${SPAD}/doc/msgs
	@ echo '${PROCLAIMS}' > ${OUT}/makeint.lisp
	@ echo '(load "${OUT}/nocompil")' >> ${OUT}/makeint.lisp
	@ echo '(load "${OUT}/bookvol5")' >> ${OUT}/makeint.lisp
	@ echo '(load "${OUT}/util")' >> ${OUT}/makeint.lisp
	@ echo '(in-package "BOOT")' >> ${OUT}/makeint.lisp
	@ touch ${TIMESTAMP}
	@ echo '${YEARWEEK}' >> ${OUT}/makeint.lisp
	@ echo '(build-interpsys (append' \
          '(quote ($(patsubst %, "%", ${OBJS})))'  \
          '(quote ($(patsubst %, "%", ${ASCOMP})))'  \
          '(quote ($(patsubst %, "%", ${INOBJS}))))' \
          '(quote ($(patsubst %, "%", ${BROBJS})))'  \
          '(quote ($(patsubst %, "%", ${NAGBROBJS})))'  \
          '"${SPAD}"  "${LSP}" "${SRC}" "${INT}"' \
          '"${OBJ}" "${MNT}" "${SYS}")' >> ${OUT}/makeint.lisp
	@ echo '(in-package "SCRATCHPAD-COMPILER")' >> ${OUT}/makeint.lisp
	@ echo '(boot::set-restart-hook)' >> ${OUT}/makeint.lisp
	@ echo '(in-package "BOOT")' >> ${OUT}/makeint.lisp
	@ echo '(load "${INT}/algebra/warm.data")' >> ${OUT}/makeint.lisp
	@ echo '(|clearClams|)' >> ${OUT}/makeint.lisp
	@ echo '#+:akcl (setq compiler::*suppress-compiler-notes* t)' \
                >> ${OUT}/makeint.lisp
	@ echo '#+:akcl (si::gbc-time 0)' >> ${OUT}/makeint.lisp
	@ echo '#+:akcl (setq si::*system-directory* "${SPAD}/bin/")' \
               >> ${OUT}/makeint.lisp
	@ (cd ${OBJ}/${SYS}/bin ; \
	  echo '(progn (gbc t) (load "${OUT}/makeint.lisp")' \
                 '(gbc t) (user::spad-save "${SAVESYS}"))' | ${LISPSYS} )
	@ echo si005 ${SAVESYS} created
	@ cp ${SAVESYS} ${AXIOMSYS}
	@ echo si006 ${AXIOMSYS} created

\end{chunk}

\section{Building debugsys}
Note that we assume you've already built interpsys so all of the
files are known to exist and be up to date. We don't list any of
the preconditions here. 
\begin{chunk}{debugsys}
${DEBUGSYS}: ${MID}/debugsys.lisp
	@ echo si007 building debugsys
	@ (cd ${OBJ}/${SYS}/bin ; \
	  echo '(progn (gbc t) (load "${MID}/debugsys.lisp")' \
                 '(user::spad-save "${DEBUGSYS}"))' | ${LISPSYS} )
	@ echo si008 ${DEBUGSYS} created

\end{chunk}

\section{The Interpreter files}

\subsection{debugsys.lisp \cite{14}}
The {\bf debugsys.lisp} file is used to create a {\bf debugsys} runnable image.
This image contains almost all of the lisp code that make up the axiom
interpreter in lisp form. It is useful for deep system debugging but
otherwise worthless. This file is certain to drift over time as changes
are made elsewhere to add or remove files. It is assumed that you know
what you are doing if you change this file or use debugsys.

This file is basically the same as the one created during the build of
interpsys. See the echo lines in the {\bf SAVESYS} block above. These
are echoed into a temporary file which gets loaded into the lisp image.
We simply captured that temporary file, replaced the .o files with .lisp
files (or .lsp or .clisp) and saved it here.
\begin{chunk}{debugsys.lisp (MID from IN)}
${MID}/debugsys.lisp: ${IN}/debugsys.lisp.pamphlet
	@ echo si011 making ${MID}/debugsys.lisp from ${IN}/debugsys.lisp.pamphlet
	@ (cd ${MID} ; \
          echo '(tangle "${IN}/debugsys.lisp.pamphlet" "*" "debugsys.lisp")' \
        | ${OBJ}/${SYS}/bin/lisp  1>/dev/null 2>/dev/null)

\end{chunk}

\section{The databases}
\subsection{autoload dependencies}
If you are adding a file which is to be autoloaded the following step
information is useful. There are 2 cases:
\begin{enumerate}
\item adding files to currently autoloaded parts\\
(as of 2/92: browser old parser and old compiler)
\item adding new files
\begin{itemize}
\item case 1:
\item [(a)] you have to add the file to the list of files currently there
(e.g. see BROBJS above)
\item [(b)] add an autolaod rule
(e.g. ${AUTO}/parsing.${O}: ${OUT}/parsing.${O})
\item [(c)] edit util.lisp to add the 'external' function (those that
should trigger the autoload
\end{itemize}
\item case 2:\\
     build-interpsys (in util.lisp) needs an extra argument for the
     new autoload things and several functions in util.lisp need hacking.
\end{enumerate}
database.date is a marker file used to force a rebuild of interpsys if the
database is rebuilt (src/algebra/Makefile).
\begin{chunk}{databases}
${OUT}/database.date:
	@ echo 617 the database was updated...remaking interpsys
	@ touch ${OUT}/database.date

\end{chunk}

\section{The Makefile}
\begin{chunk}{*}

\getchunk{environment}

all: announce ${SAVESYS} # ${DEBUGSYS} 
	@echo 618 finished ${IN}

announce:
	@ echo =====================================
	@ echo src/interp BUILDING INTERPRETER FILES
	@ echo =====================================

clean:
	@echo 619 cleaning ${SRC}/interp

\getchunk{savesys}
\getchunk{depsys}
\getchunk{debugsys}
\getchunk{databases}

\getchunk{debugsys.lisp (MID from IN)}

\getchunk{warm.data.stanza}

${MID}/bookvol5.${LISP}: ${IN}/bookvol5.pamphlet
	@ echo si125 making ${MID}/bookvol5.${LISP} from ${IN}/bookvol5.pamphlet
	@ (cd ${MID} ; \
  echo '(tangle "${IN}/bookvol5.pamphlet" "Interpreter" "bookvol5.${LISP}")' \
        | ${OBJ}/${SYS}/bin/lisp )  1>/dev/null 2>/dev/null

${MID}/bookvol9.${LISP}: ${IN}/bookvol9.pamphlet
	@ echo si128 making ${MID}/bookvol9.${LISP} from ${IN}/bookvol9.pamphlet
	@ (cd ${MID} ; \
     echo '(tangle "${IN}/bookvol9.pamphlet" "Compiler" "bookvol9.${LISP}")' \
        | ${OBJ}/${SYS}/bin/lisp ) 1>/dev/null 2>/dev/null

${MID}/bookvol10.5.${LISP}: ${IN}/bookvol10.5.pamphlet
	@ echo si131 making ${MID}/bookvol10.5.${LISP} from ${IN}/bookvol10.5.pamphlet
	@ (cd ${MID} ; \
        echo '(tangle "${IN}/bookvol10.5.pamphlet" "Numerics" "bookvol10.5.${LISP}")'\
         | ${LISPTANGLE} ) 1>/dev/null 2>/dev/null

${MID}/http.lisp: ${IN}/http.lisp
	@ echo si110 making ${MID}/http.lisp from ${IN}/http.lisp
	@( cp ${IN}/http.lisp ${MID}/http.lisp )

${OUT}/%.${LISP}: ${MID}/%.${LISP}
	@ echo siOUTfromMID2 making ${OUT}/$*.${LISP} from ${MID}/$*.${LISP}
	@cp ${MID}/$*.${LISP} ${OUT}/$*.${LISP}

${OUT}/%.${LISP}: ${MID}/%.lisp
	@ echo siOUTfromMID1 making ${OUT}/$*.lisp from ${MID}/$*.lisp
	@cp ${MID}/$*.lisp ${OUT}/$*.${LISP}

${OUT}/%.lisp: ${IN}/%.lisp.pamphlet
	@ echo siOUTfromIN making ${OUT}/$*.lisp from ${IN}/$*.lisp.pamphlet
	@ rm -f ${OUT}/$*.${O}
	@( cd ${OUT} ; \
          echo '(tangle "${IN}/$*.lisp.pamphlet" "*" "$*.lisp")' \
        | ${OBJ}/${SYS}/bin/lisp ) 1>/dev/null 

${OUT}/%.o: ${MID}/%.lisp
	@ echo siOUTfromMID making ${OUT}/$*.o from ${MID}/$*.lisp
	@ if [ -z "${NOISE}" ] ; then \
	   (cd ${MID} ; \
	    echo "(let ((compiler::*cc* (concatenate 'string compiler::*cc* \" -I ${INC} -I ../lib\")))  (compile-file \"$*.lisp\" :output-file \"${OUT}/$*.o\") (${BYE}))" | ${DEPSYS} ) ; \
	   else \
	    (cd ${MID} ; \
	     echo "(let ((compiler::*cc* (concatenate 'string compiler::*cc* \" -I ${INC} -I ../lib\")))  (compile-file \"$*.lisp\" :output-file \"${OUT}/$*.o\") (${BYE}))" | ${DEPSYS} ) \
              1>$$(echo "$(NOISE)" | $(AWK) '{print $$2}') 2>&1 ; \
	   fi 

${MID}/%.lisp: ${IN}/%.lisp.pamphlet
	@ echo siMIDfromIN making ${MID}/$*.lisp from ${IN}/$*.lisp.pamphlet
	@ (cd ${MID} ; \
          ( echo '(tangle "${IN}/$*.lisp.pamphlet" "*" "$*.lisp")' \
          | ${OBJ}/${SYS}/bin/lisp 1>/dev/null ) )

${AUTO}/%.${O}: ${OUT}/%.${O}
	@ echo siAUTOfromOUT making ${AUTO}/$*.${O} from ${OUT}/$*.${O}
	@ cp ${OUT}/$*.${O} ${AUTO}

${OUT}/%.${O}: ${MID}/%.${LISP}
	@ echo si123 making ${OUT}/$*.${O} from ${MID}/$*.${LISP}
	@  if [ -z "${NOISE}" ] ; then \
	 (cd ${MID} ; \
	    echo "(let ((compiler::*cc* (concatenate 'string compiler::*cc* \" -I ${INC} -I ../lib\")))  (compile-file \"$*.${LISP}\" :output-file \"${OUT}/$*.${O}\") (${BYE}))" | ${DEPSYS} ) ; \
	  else \
	  (cd ${MID} ; \
	    echo "(let ((compiler::*cc* (concatenate 'string compiler::*cc* \" -I ${INC} -I ../lib\")))  (compile-file \"$*.${LISP}\" :output-file \"${OUT}/$*.${O}\") (${BYE}))" | ${DEPSYS} ) ; \
              1>$$(echo "$(NOISE)" | $(AWK) '{print $$2}') 2>&1 ; \
	  fi 

\end{chunk}
\eject
\begin{thebibliography}{99}
\end{thebibliography}
\end{document}