File: pkg-spec.sgml

package info (click to toggle)
haskell98-report 20080907-4
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 2,144 kB
  • sloc: haskell: 4,075; makefile: 322
file content (1636 lines) | stat: -rw-r--r-- 72,932 bytes parent folder | download | duplicates (7)
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
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
<!DOCTYPE ARTICLE PUBLIC "-//OASIS//DTD DocBook V3.1//EN" [
<!entity  ghc         "<application>GHC</application>">
<!entity  nhc         "<application>Nhc98</application>">
<!entity  hugs        "<application>Hugs</application>">
<!entity  hps         "<application>Cabal</application>">
<!entity  tool        "<application>tool</application>">
<!entity  autoconf    "<application>autoconf</application>">
<!entity  impl        "Haskell Implementation">
<!entity  impls       "Haskell Implementations">
<!entity  distMod     "<className>Distribution</className> module">
<!entity  haskellConfig  "<application>haskell-config</application>">
<!entity  DistPackage  "<classname>Distribution.Package</classname>">
<!entity  DistBuild    "<classname>Distribution.Build</classname>">
<!entity  DistInstall  "<classname>Distribution.Install</classname>">
<!entity  DistConfigure   "<classname>Distribution.Config</classname>">
<!entity  hunit       "<application>HUnit</application>">
<!entity  distutils   "<application>Distutils</application>">
<!entity  cpan        "<application>CPAN</application>">
<!entity  xemacs      "<application>XEmacs</application>">
<!entity  hmake       "<application>hmake</application>">
<!entity  dpkg        "<application>dpkg</application>">
<!entity  rpm        "<application>rpm</application>">
<!entity  hc-pkg     "<command>hc-pkg</command>">
<!entity  pkg-desc     "<filename>Setup.description</filename>">
]>
 
<!-- Look for items marked "FIX" -->

<!-- ToDo: -->

<!-- Look at Package data types again and add the version information where -->
<!-- necessary. -->

<article id="hps">
  <artHeader>
    <date>2004-04-24</date>
    <title>The Haskell Cabal</title>
    <subtitle>A Common Architecture for Building Applications and Tools</subtitle>
    <author>
      <firstname>Isaac</firstname>
      <surname>Jones</surname>
    </author>
    <author>
      <firstname>Simon</firstname>
      <surname>Peyton Jones</surname>
    </author>
    <author>
      <firstname>Simon</firstname>
      <surname>Marlow</surname>
    </author>
    <author>
      <firstname>Malcolm</firstname>
      <surname>Wallace</surname>
    </author>
    <author>
      <firstname>Ross</firstname>
      <surname>Patterson</surname>
    </author>

    <address><email>ijones@syntaxpolice.org</email></address>
    <abstract>

      <para>The Haskell Library and Tools Infrastructure Project is an
      effort to provide a framework for developers to more effectively
      contribute their software to the Haskell community.  This
      document specifies the <emphasis>Common Architecture for
      Building Applications and Tools(&hps;)</emphasis>, which
      contributes to the goals of the Haskell Library and Tools
      Infrastructure Project.  </para>
      <para>Specifically, the &hps; describes what a Haskell 
	package is, how these packages interact with the language,
	and what Haskell implementations must to do to support packages.
	The &hps; also specifies some infrastructure (code) that makes
	it easy for &tool; authors to build and distribute conforming packages.
	</para>
      <para>The &hps; is only one contribution to the Library Infrastructure project.
	In particular, the &hps; says nothing about more global issues such as
	how authors decide where in the module name space their library should live;
	how users can find a package they want; how orphan packages find new owners;
	and so on.</para>
      <para> The &hps; has been discussed by the implementors of
	&ghc;, &nhc;, and &hugs;, all of whom are prepared to
	implement it.  The proposal is now open for wider
	debate. Please contribute by emailing
	<email>libraries@haskell.org</email>.</para>
    </abstract>
  </artheader>


<!-- Solution ------------------------------------------------- -->

<sect1 id=hli-goals><title>The Haskell Package System: goals</title>

<para>The Haskell Package System (&hps;) has the following main goal:
to specify a standard way in which a Haskell &tool; can be packaged, so that it is
easy for consumers to use it, or re-package it, 
regardless of the Haskell implementation or installation platform.</para>  

<para>The &hps; also
supports &tool; authors by providing an infrastructure that automates the
process of building and packaging simple &tool;s.  It is not necessary to use
this code&mdash;indeed complex libraries may exceed its abilities&mdash;but it should
handle many cases with no trouble.</para>

<sect2><title>Dramatis personae</title>

<para>The &hps; serves a number of people in different ways:

<itemizedlist>
<listitem><para>
 <emphasis>Joe User</emphasis> is simply a Haskell user.  He does not download new packages.  Nevertheless,
he needs to know about his Haskell compiler's <option>-package</option> flag (see <xref linkend="compiler-reqts">).
	    </para>
	  </listitem>
<listitem><para>
 <emphasis>Bob the Builder</emphasis> and <emphasis>Sam Sysadmin</emphasis> both download, build,
  and install new packages. The only difference between the two is that Sam has root permission,
  and can install packages in more globally-visible places.
	    </para>
	  </listitem>

<listitem><para><emphasis>Peter Packager</emphasis> builds operating
system specific install files (e.g. .msi .rpm .deb) from packages
supplied by Marcus or Angela.  We might also call him <emphasis>Roland
RPM</emphasis>, <emphasis>Donald Debian</emphasis>, and
<emphasis>Willie Windows</emphasis> who build Linux RPM, Debian, and
Windows installer packages respectively (this list is not exhaustive).
They do this as a service to their platform's community, and may know
little or nothing about the internal details of the Haskell packages
they are wrapping up.  </para> </listitem>

<listitem><para><emphasis>Isabella Installer</emphasis> installs
binary packages supplied by Peter or Angela, (or Rowland, Donald, and
Willie).  Isabella requires only a Haskell compiler/interpreter.  She
can use rpm to install packages by Rowland.  She cannot or will not
build the packages herself, so she relies on Peter to provide them.
She won't use the Setup script directly from Angela, but she might use
a layered tool like <application>haskell-install</application>, which does all
the work of downloading and installing simple
packages.</para></listitem>

<listitem><para>
 <emphasis>Angela Author</emphasis> wants to write a simple Haskell &tool;, and distribute it with 
minimum fuss, in such a way that all the above folk can easily use it.
	    </para>
	  </listitem>
<listitem><para>
 <emphasis>Marcus Makefile</emphasis> is like Angela, but more sophisticated.  He has a complicated &tool;,
and uses makefiles.  Still, he wants to arrange that Roland, Donald, Bob, Sam, and Joe don't need to know
about his internal complexity.
	    </para>
	  </listitem>
	</itemizedlist>

We describe Angela and Marcus as <emphasis>producers</emphasis> of
their packages, and all the others as package
<emphasis>consumers</emphasis>.
      </para>

<para>Note that though these users all have different names, it is very
common for their roles to overlap when it comes to real people.  For
instance, if Bob builds packages for himself, he becomes Joe once
they're built.  These personas are <emphasis>use cases</emphasis>, and
not meant to represent completely distinct individuals.</para>

    </sect2>

<sect2 id="example"><title>An example</title>

<para>To give the idea, here is a simple example.  Angela has written a couple of Haskell modules that
implement sets and bags; she wants to distribute them to Bob as a package called,
say, <literal>angela-coll</literal>.  Let's say that the modules are
<literal>Data.Set</literal>, <literal>Data.Bag</literal>, <literal>Angela.Internals</literal>.
(The &hps; says nothing about how Angela decides where in the name space to put her modules.)
Angela only wants to expose the first two to Bob; the <literal>Angela.Internals</literal> module is (as its
name suggests) internal to the package.
</para>
<para>Angela decides to use the simple build infrastructure that the &hps; provides.  She is working in
a directory <filename>~/coll</filename>.  In there she puts the modules, in sub-directories
driven by their module name: <filename>~/coll/Data/Set.hs</filename>,
 <filename>~/coll/Data/Bag.hs</filename>,
 and <filename>~/coll/Angela/Internals.hs</filename>.
Next, she writes
a <emphasis>package description</emphasis>, which she puts in <filename>~/coll/</filename>&pkg-desc;:
<programlisting>
Name: angela-coll
Version: 0.1.1.1.1-foo-bar-bang
License: LGPL
Copyright: Copyright (c) 2004, Angela Author
Exposed-Modules: A, B, B.C
</programlisting>
She also creates a small Haskell file <filename>~/coll/Setup.lhs</filename> as follows:
<programlisting>
  #! /usr/bin/env runhugs

  > module Main where
  > import Distribution.Simple( defaultMain )
  > main = defaultMain
</programlisting>

This library implements the &hps; simple build infrastructure.</para>

<para>The first line arranges that when Angela, (or Joe, or Sam, etc.)
executes <filename>Setup.lhs</filename> as a shell script, the shell
will invoke <command>runhugs</command>, which will in turn run
<literal>mainn</literal> imported from the library
<literal>Distribution.Simple</literal>.  </para>

<para>It is not necessary that the script be run this way, it is just
a convinient way to run it.  Sam or Joe may choose to compile the
setup script into an executable with NHC or GHC and then run it
directly (it is a literate Haskell script so that it can be compiled
without the first line causing a syntax error).  Another option is for
that first line to read <programlisting>!# /usr/bin/env runhaskell</programlisting>
where <command>runhaskell</command> is a symlink to
<command>runhugs</command>, <command>runghc</command>, or
<command>runnhc</command>.</para>


<para> Now she is ready to go. She types:
<programlisting>
  ./Setup.lhs configure --ghc
  ./Setup.lhs build
  ./Setup.lhs sdist
</programlisting>
The first line readies the system to build the &tool; using &ghc;; for example, it checks that &ghc; exists on the system.
The second line checks that
the &tool; does indeed build flawlessly.  (At this point she can write and execute tests, as we discuss later.)
The third line wraps up the package as a source distribution, making the file <filename>~/coll/angela-coll-1.tar.gz</filename>.
</para>
<para>
Angela emails the tar file to Bob, who untars it into <filename>tmp/coll</filename>.
He <command>cd</command>'s to that directory and types
<programlisting>
  ./Setup.lhs configure --ghc
  ./Setup.lhs build
  ./Setup.lhs install
</programlisting>
He's all done. Now in his Haskell programs, Bob can simply <literal>import</literal> the new
modules <literal>Data.Set</literal> and <literal>Data.Bag</literal>. He does not need to give extra flags
to &ghc; to tell it to look for Angela's modules; they are there automatically.
If Angela used the same module names as someone else, Bob may need finer control: see <xref linkend="compiler-reqts">.</para>
<para>
If Angela wrote her modules in a suitably portable variant of Haskell,
Bob could also have said <option>--hugs</option> or
<option>--nhc</option> in his <option>configure</option> line, and the
package would have been built and installed for those compilers
instead.
      </para>
    </sect2>
  </sect1>


<sect1 id=hli-overview><title>The Haskell Package System: overview</title>

<para>This section summarises the vocabulary and main features of the Haskell Package System.</para>

<sect2 id="package-descr"><title>Packages</title>

<para>A <emphasis>package</emphasis> is the unit of distribution for the &hps;.
Its purpose in life, when installed, is to make available some Haskell modules for
import by some other Haskell program.   However, a package may consist of 
much more than a bunch of Haskell
modules: it may also have C source code and header files, documentation, test cases, auxiliary 
tools and whatnot.</para>

<para>
Each package has:
<itemizedlist>
<listitem><para>A globally-unique <emphasis>package name</emphasis>, containing no spaces. Chaos will result
if two distinct packages with the same name are installed on the same system.  How unique package names are
handed out is not part of this specification, but there will presumably be some global web site where
package authors can go to register a package name. </para>
</listitem>
<listitem><para>A <emphasis>version</emphasis>, consisting of a sequence of one or more integers.
</para></listitem>

<listitem><para>
<emphasis>A list of explicit dependencies</emphasis> on other packages.  These are typically not exact; e.g. "I need <literal>hunit</literal> version
greater than 2.4".
	    </para>
	  </listitem>
<listitem><para>
<emphasis>A list of exposed modules</emphasis>.  Not all of the modules that comprise a package implementation are necessarily
exposed to a package client.
The ability to expose some, but not all, of the modules making up a package
is rather like using an explicit export list on a Haskell module.</para>
	  </listitem>
</itemizedlist>
The first two components can be combined to form a single text string called the <emphasis>package ID</emphasis>, 
using a hyphen to separate the version
from the name, and dots to separate the version components.  For example, "hunit-2.3".
</para>

</sect2>

<sect2 id="packages-and-haskell"><title>Packages and the Haskell language</title>
<para>A complete Haskell program will consist of one or more modules (including <literal>Main</literal>)
compiled against one or more packages (of which the Prelude is one).  These packages are not referred to
explicitly in the Haskell source; instead, the packages simply populate the hierarchical space of module names.
</para>
<para>Complete programs must obey the following invariant.  <emphasis>Consider all the Haskell modules that
constitute a complete program: no two modules must have the same module name.</emphasis></para>

<para>This invariant is conservative.  It preserves the existing semantics of Haskell, and is 
relatively easy to implement.  In particular, the the full name of an entity (type, class, function), which is
used to determine when two entities are the same, is simply a pair of the module name and the entity name.</para>

<para>The invariant is unsatisfactory, however, because it does not support abstraction at
the package level. For example, a module with an internal (hidden, non-exposed) module called <literal>Foo</literal>
cannot be used in the same program as another package with an unrelated internal module also called <literal>Foo</literal>.
Nor can a program use two packages, P and Q, which depend on different versions of the same underlying package R.
We considered more sophisticated schemes, in which (for example) the package name, or package ID, is implicitly
made part of every module name.  But (a) there is a big design space, and (b) it places new requirements on the
implementations.  Hence a conservative starting point.</para>
    </sect2>

<sect2><title>Packages and compilers</title>

<para>We use the term ``compiler'' to mean &ghc;, &hugs;, &nhc;, hbc, etc.  (Even though
&hugs; isn't really a compiler, the term is less clumsy than ``Haskell implementation''.)</para>

<para> The
&hps; requires that a conforming Haskell compiler is somewhat package aware.
In summary, the requirements are these:
<itemizedlist>
<listitem><para>Each compiler <command>hc</command> must provide an
associated package-management program &hc-pkg;.  A compiler user
installs a package by placing the package's supporting files
somewhere, and then using &hc-pkg; to make the compiler aware of the
new package.  This step is called <emphasis>registering the package
with the compiler</emphasis>.  </para></listitem> <listitem><para>To
register a package, &hc-pkg; takes as input an <emphasis>installed
package description (IPD)</emphasis>, which describes the installed
form of the package in detail.  The format of an IPD is given in <xref
linkend="ipd">.</para>
	  </listitem>

	  <listitem>
	    <para>Subsequent invocations of <command>hc</command>
            will include modules from the new package in the module
            name space (i.e. visible to <literal>import</literal>
            statements).</para>
	  </listitem>
	  <listitem>
	    <para>The compiler should support
            <option>-package</option> and
            <option>-hide-package</option> flags for finer-grain
            control of package visibility.</para>
	  </listitem>
	</itemizedlist>

        A complete specification of these requirements is given in
        <xref linkend="compiler-reqts">.</para>
    </sect2>

<sect2><title>Package distributions</title>

<para>A &hps; package can be distributed in several forms:
<itemizedlist>
<listitem><para>
A <emphasis>&hps; source distribution</emphasis> is a tree of files (tar-ball, zip file etc)
containing the &tool;'s sources, which may need to be
compiled before being installed.  The same source tarball may well be installable for several
Haskell implementations, OSs, and platforms.
	    </para>
<para>A source distribution may contain fewer files than appear in the developer's CVS repository; for example,
design notes may be omitted.  It may also contain some derived files, that do not appear in the
the developer's repository; for example, ones made by a somewhat exotic pre-processor where it
seems simpler to ship the derived file than to ensure that all consumers have the pre-processor.</para></listitem>
<listitem><para>
A <emphasis>&hps; binary distribution</emphasis> is a tree of files that contains a pre-compiled &tool;, ready
for installation.  The pre-compilation means that the distribution will be Haskell-compiler-specific, and certain 
"looser" dependencies (<literal>hunit > 2.3</literal>) will now be precisely fixed (<literal>hunit == 2.4</literal>).
	    </para>
	  </listitem>

<listitem><para>
The package may be wrapped up as an <emphasis>RPM</emphasis>, <emphasis>Debian</emphasis> package, 
or <emphasis>Windows installer</emphasis> (this list is not exhaustive).
In that case, the way it is installed is prescribed by the respective distribution mechanism;
the only role of the &hps; is to make it easy to construct such distributions. All three are
compiler-specific (indeed compiler-version-specific) binary distributions.
	    </para>
	  </listitem>
	</itemizedlist></para>
    </sect2>

<sect2><title>The Setup script</title>

<para>The key question is this: how should Angela Author present her &hps; package so that 
her consumers (Bob, Sam, Willie, etc) can conveniently use it?</para>

<para>Answer: she provides a tree of files, with two specific files in the
root directory of the tree:  
<itemizedlist>
<listitem><para>&pkg-desc; contains a short description of the package:
specifically, the package name, version, and dependencies.  It may also contain further information
specific to the particular build system.  The syntax of the package description file
is given in <xref linkend="pkg-desc">.
	    </para>
	  </listitem>
<listitem><para>
<filename>Setup.lhs</filename> is an executable Haskell program 
which conforms to a particular specification, given in detail in <xref linkend="setup">.
In summary, though, <filename>Setup.lhs</filename> allows a consumer to configure, build,
test, install, register, and unregister a package.  </para>
	  </listitem>
	</itemizedlist>

The Setup script is an <emphasis>interface</emphasis>.  It is meant to
give a standard look-and-feel to packages for the sake of Joe User,
Bob Builder, Peter Packager, Sam Sysadmin, and Rowland RPM, as well as for layered
software tools.  This interface provides an abstraction layer on top
of any implementation that Angela or Marcus prefers.</para>

<para>The &hps; allows a package author to write the setup script in any way
she pleases, provided it conforms to the specification of <xref
linkend="setup">.  However, many Haskell packages consist of little
more than a bunch of Haskell modules, and for these the &hps; provides
<emphasis>the simple build infrastructure</emphasis>, a Haskell
library that does all the work.  The simple build infrastructure,
which was used for the example in <xref linkend="example">, is
described in <xref linkend="sbi">.</para>

<!-- Why Haskell ---------------------------- -->

<para>In principle, the <literal>Setup</literal> script
could be written in any language; so why do we use Haskell?
<itemizedList>

<listItem><para>Haskell runs on all the systems of interest.</para></listItem>

<listItem><para>Haskell's standard libraries should include a rich set of operating
system operations needed for the task.  These can abstract-away the
differences between systems in a way that is not possible for
Make-based tools.</para></listItem>

<listItem><para>Haskell is a great language for many things, including tasks
typically relegated to languages like Python.  Building, installing,
and managing packages is a perfect proving ground for these tasks, and
can help us to discover weaknesses in Haskell or its libraries that
prevent it from breaking into this "market".  A positive side-effect
of this project might be to make Haskell more suitable for "scripting"
tasks.</para></listItem>

<listItem><para>Likewise, each piece of the project (Building, Installing, and
Packaging) can be leveraged elsewhere if we make them into
libraries.</para></listItem>

<listItem><para>Make is not particularly good for parsing, processing, and sharing
meta-information about packages.  The availability of this information
to Haskell systems (including compilers, interpreters, and other
tools) is useful.  Unlike Make, Haskell can also reuse unrelated
algorithms, parsers, and other libraries that have been developed in
the past.</para></listItem>

<listItem><para><emphasis>Dogfooding</emphasis>, the act of using the tools you
develop, is a healthy policy.</para></listItem>

</itemizedList>
It is convenient for consumers to execute <filename>Setup.lhs</filename> directly, thus:
<programlisting>
  ./Setup.lhs ...
</programlisting>
This can be achieved by starting <filename>Setup.lhs</filename> with "<literal>#! /usr/bin/env runhugs</literal>"
or "<literal>#! /usr/bin/env runghc</literal>" .
Since it's a literate Haskell script (<literal>.lhs</literal> file), the Haskell compiler will ignore
this line.
However, nothing stops a consumer from running the script interactively, or compiling it and running 
the compiled binary.  Any implementation of Haskell should suffice to run the script, provided 
the implementation has the &hps; libraries installed.  
	</para>
      </sect2>
  </sect1>

<!-- COMPILER REQUIREMENTS ---------------------------- -->

<sect1 id="compiler-reqts"><title>What the compilers must implement</title>

<para>The &hps; requires that the Haskell implementations be somewhat package-aware.
This section documents those requirements.</para>

<sect2><title>Building and registering a package</title>

<para>Installing a package ultimately involves these steps:
<itemizedlist>
<listitem> <para>
 <emphasis>Compiling the source files</emphasis>, by invoking the compiler.  Even &hugs; may require 
     some processing (e.g running cpp or cpphs).
</para></listitem>

<listitem> <para>
  <emphasis>Copying the compiled files into some permanent place</emphasis>.  Typically the compiler
     places no pre-conditions on where "some place" is; instead one
     usually follows the conventions of the host operating system.
</para></listitem>

<listitem> <para>
  <emphasis>Registering the package</emphasis>: telling the compiler about the 
     existence of the package, and where its files are.
  To register the package one invokes a compiler-specific program &hc-pkg; (i.e. <command>ghc-pkg</command>, 
  <command>hugs-pkg</command> etc), passing it an <emphasis>installed package description (IPD)</emphasis>
  describing the package.  The format of an IPD is given in <xref linkend="ipd">.
</para></listitem>
</itemizedlist>
</para>
<para>It must be possible to register many versions of the same package.</para>

<sect3><title>Global packages and user packages</title>

<para>
A package can be registered either as a <emphasis>global package</emphasis> or as a <emphasis>user package</emphasis>.
The former means that anyone invoking <command>hc</command> will see the new package.  The latter means
that only the user who installed the package will see it.
</para>
<para>
User packages <emphasis>shadow</emphasis> global packages, in the following sense:</para>
	<itemizedlist>
	  <listitem>
	    <para>A Haskell <literal>import</literal> for module M
	    will seek M in a user package first.</para>
	  </listitem>
	  <listitem>
	    <para>The &hc-pkg; commands that take package IDs will
	    look for a user package first.</para>
	  </listitem>
	</itemizedlist>

	<para>Each user has one package database per compiler and
	version.  That is, the user packages for GHC 6.2 are separate
	from those for GHC 6.2.1.  If there are multiple installations
	of a particular compiler version on the system, then they will
	all use the same user packages, so the user should refrain
	from using user packages with different installations of the
	same compiler version, unless they can guarantee that the
	different installations are binary compatible, such as if they
	were installed from identical binary distributions.</para>
        
        <para>For instance, lets say that Joe User mounts his home
        directory on his Linux machine and on his Solaris machine.  He
        also uses ghc-6.2 on both machines.  His user packages are
        installed in ~/ghc-6.2-packages (or something) and are
        compiled for Linux.  Now he had better not use these packages
        with the Solaris compiler, because they are in a spot where
        the Solaris compiler will find them!</para> </sect3>

<sect3><title>Exposed packages and hidden packages</title>

<para>
An installed package can be <emphasis>exposed</emphasis> or <emphasis>hidden</emphasis>.  An exposed package
populates the module name space, while a hidden package does not.  Hidden packages are nevertheless necessary.
For example, the user might use
package A-2.1 and B-1.0; 
but B-1.0 might depend on A-1.9. So the latter must be installed (else B-1.0 could not be installed), but
should be hidden, so that user imports see A-2.1. (However, note that the 
whole-program invariant described in <xref linkend="packages-and-haskell"> implies that a program using B-1.0 could
not also use A-2.1, because then both A-2.1 and A-1.9 would form part of the program, and they almost certainly 
use the same module names.)
</para>
<para>The registration program &hc-pkg; provides operations to expose or hide an 
already-installed package.  By default, installing a package installs it exposed, and hides any
existing installed package of the same name (and presumably different version).
	  </para>
<para>Hiding or exposing a package is an operation that can be performed, by &hc-pkg;,
on any package.  It is quite distinct from the question of which modules in a package are hidden or
exposed (see <xref linkend="package-descr">), which is a property of the package itself.  Only the exposed
modules of an exposed package populate the module name space seen by a Haskell <literal>import</literal> statement.
</para>
</sect3>

<sect3><title>Registration invariants</title>

<para>The registration program &hc-pkg; checks the following invariants:
<itemizedlist>
<listitem> <para>
Before registering a package P, check all the packages that P depends on are already registered.
If P is being registered as a global package, P's dependencies must also be global packages.
</para></listitem>

<listitem> <para> Before registering an exposed user package P, check
that the modules that are exposed by P do not have the same names (in
the hierarchical module name space) as any other module in an exposed
user package Q.  Similarly for system packages.  (However, one may
register a system package which exposes a module with the same name as
a user package, and vice-versa.)  </para></listitem>

<listitem> <para>
Before un-registering a package P, check that no package that depends on P is registered.
The exception is that when un-registering a global package, &hc-pkg; cannot
check that no user has a user package depending on P.</para>
	    </listitem>
</itemizedlist>
	</para>
      </sect3>
    </sect2

    <sect2>
      <title>The <option>-package</option> compiler flag</title>

      <para>By default, the module namespace is populated only by the
      exposed modules of exposed packages.  This can be overridden
      using the <option>-package</option> flag, which temporarily
      exposes a particular package, hiding any other packages of the
      same name.</para>

      <para>Later options override earlier ones, so that for example
      <literal>-package hunit-1.2 -package hunit-1.3</literal> will
      result in <literal>hunit-1.3</literal> being exposed.</para>

      <para>Additionally, compilers should provide a
      <option>-hide-package</option> flag, which does the opposite of
      <literal>-package</literal>: it temporarily hides a package for
      this run of the compiler.</para>

      <para>When all the <option>-package</option> and
      <option>-hide-package</option> flags on the compiler's command
      line have been processed, the resulting module namespace must
      not contain any overlapping modules; the compiler should check
      this and report any errors.</para>
    </sect2>

<sect2><title>The interface to &hc-pkg;</title>

<para>Registering a package with a compiler records the package information in some
implementation-specific way; how it does so is not constrained by the &hps;.
Much of an IPD is independent of the compiler, but it may also include compiler-specific
fields.</para>

<para>Each Haskell implementation <command>hc</command> must provide an associated program &hc-pkg; which 
allows a user to make a new package known to the compiler, and to ask what packages it knows. Here is a summary of its interface

<note><para>Some of these commands (unregister, hide, and describe) make sense for package IDs which offer a range, such as "hc-pkg unregister hunit&lt;2.3".</para></note>

     <table frame=all><title>&hc-pkg; interface</title>

     <tgroup cols=2 align=left colsep=1 rowsep=1>     <tbody>

     <row><Entry><cmdsynopsis><command>hc-pkg register</command> <group choice=req>
		      <arg><replaceable>filename</replaceable></arg>
		      <arg><option>-</option></arg></group>
		  <group choice=opt><arg>--user</arg><arg>--global</arg>
		    </group>
		</cmdsynopsis></entry>
                    <Entry><para>Register the package using the specified installed package description.
		  The syntax for the latter is given in <xref linkend="ipd">.</para></entry></row>


     <row><Entry><cmdsynopsis><command>hc-pkg unregister</command> 
		<arg><replaceable>pkg-id</replaceable></arg>
		  </cmdsynopsis></entry>
                    <Entry><para>Unregister the specified package.</para></entry></row>

     <row><Entry><cmdsynopsis><command>hc-pkg expose</command> 
		<arg><replaceable>pkg-id</replaceable></arg>
		  </cmdsynopsis></entry>
                    <Entry><para>Expose the specified package.</para></entry></row>

     <row><Entry><cmdsynopsis><command>hc-pkg hide</command> 
		<arg><replaceable>pkg-id</replaceable></arg>
		  </cmdsynopsis></entry>
                    <Entry><para>Hide the specified package.</para></entry></row>

     <row><Entry><command>hc-pkg list</command></entry>
                    <Entry><para>List all registered packages, both global and user, hidden and exposed. </para></entry></row>


     <row><Entry><cmdsynopsis><command>hc-pkg describe</command> <arg choice=req><replaceable>pkg-id</replaceable> </arg>
		  </cmdsynopsis></entry>
         <Entry><para>Give the registered description for the specified package.
		    The description is returned in precisely the syntax required by 
		    <command>hc-pkg register</command>.  
		</para></entry></row>

     <row><Entry><cmdsynopsis><command>hc-pkg field</command> <arg choice=req><replaceable>pkg-id</replaceable> </arg>
		<arg choice=req><replaceable>field</replaceable> </arg>
		  </cmdsynopsis></entry>

         <Entry><para>Extract the specified field of the package description for the specified package.
		</para></entry></row>

     </tbody></tgroup>
     </table>
     A <replaceable>pkg</replaceable> argument can be a package ID, such as "<literal>hunit-2.3</literal>", or just a package name, 
such as "<literal>hunit</literal>".  To determine which package is meant, &hc-pkg; searches first the
registered user packages and then the global packages.  If no such package exists, the command fails; that is, it does nothing, 
returning a non-zero error code.
If only a name is specified, &hc-pkg; fails
unless the name identifies a unique package among the user packages, or among the global packages.  As usual, the
user packages win.
      </para>
<note><para>Can we give the <option>--user</option> flag to <command>hide</command>, <command>expose</command>,
<command>describe</command>?  Can we register a package that is already registered?  What if it's registered
as a global package and we register it as a user package?</para>
      </note>
</sect2>

<sect2 id=ipd><title>Syntax of installed package description</title>

<note><para>...include the list of ``externally visible modules''.</para></note>
</sect2>
</sect1> <!-- End of compiler requirements --> 


<!-- Setup script -->

<sect1 id=setup><title>The setup script</title>

<para>
The sole requirement of an &hps; package is that it should contain,
in the root of its file structure, (a) a package description file &pkg-desc;,
and (b) a setup script, <filename>Setup.lhs</filename>.
This section
specifies the syntax of the package description, and the command-line interface for the setup script.
</para>

<sect2 id=pkg-desc><title>The package description</title>

<para>Here is a sample package description file:
<programlisting>-- Required
Name: Cabal
Version: 0.1.1.1.1-rain
License: LGPL
Copyright: Free Text String
-- Optional - may be in source?
Stability: Free Text String
Build-Depends: haskell-src, HUnit>=1.0.0-rain
Modules: Distribution.Package, Distribution.Version,
         Distribution.Simple.GHCPackageConfig
...</programlisting>

The Name, Version, License, and Copyright are compulsory.</para>

<para>The rest of the lines are optional.  Any fields the system
doesn't understand will be ignored (to allow addition of fields at a
later date, or to allow Setup script authors to provide their own
fields). Each field must begin with "Field-Name:".</para>

<para>Lines beginning with "--" will be considered comments and
ignored.</para>

<para>Each field must begin with "Field-Name:".  In order to allow for
long fields, any line that begins with whitespace will be considered
part of the previous field.  </para>

<para>As given, there should be no reason to have completely empty
lines (except perhaps for the last line in the file).  In the future,
if there is need to add more records, they will be separated by at
least one completely empty line.</para>

<para>For the &hps;-provided simple build infrastructure, the package
description fields and syntax are given in <xref
linkend="sbi-pkg-desc">.</para>

</sect2>

<sect2 id=setup-spec><title>The setup script specification</title>

<para>Here is the command-line interface the setup script must satisfy.
     <table frame=all><title>setup.lhs interface</title>

     <tgroup cols=2 align=left colsep=1 rowsep=1>     <tbody>

     <row><Entry><command>./Setup.lhs configure [flags] </command></entry>
         <Entry><para> Prepare to build the package.  Typically, this step checks
		that the target platform is capable of building the package, and
		discovers platform-specific features that are needed during the build. 
		</para></entry></row>


     <row><Entry><command>./Setup.lhs build</command></entry>
                    <Entry><para>Make this package ready for installation.  For a true compiler,
		  this step involves compiling the Haskell source code.  Even for an interpreter, however, 
		  it may involve running a pre-processor.</para></entry></row>


     <row><Entry><command>./Setup.lhs install [install-prefix]</command></entry>
                    <Entry><para>Copy the files into the install locations, and register
		  the package with the compiler.</para></entry></row>

     <row><Entry><cmdsynopsis>
		  <command>./Setup.lhs register</command><sbr>
		  <command>./Setup.lhs unregister</command>
	      </cmdsynopsis>
	      </entry>
                    <Entry><para>Register (or un-register) this package with the
                    compiler.  (NB: registration is also done automatically by <literal>install</literal>.)
		</para></entry></row>

     <row><Entry><command>./Setup.lhs clean</command></entry>
                    <Entry><para>Clean out the files created during the configure, build, or register steps.</para></entry></row>
     <row><Entry><command>./Setup.lhs test</command></entry>
                    <Entry><para>Run the package's test suite.</para></entry></row>

     </tbody></tgroup>
     </table>
    </para>

      <para>For wrapped make-based systems (for instance), a
      command-line parser that understands the standard
      <literal>Setup.lhs</literal> command-line syntax will be
      provided as a library.</para>

      <sect3>
	<title><option>configure</option></title>

	<para>The command <literal>./Setup.lhs configure</literal>
        prepares to build the package.  For sophisticated packages,
        the configure step may perform elaborate checks, to gather
        information about the target system.  It may write a file to
        record its results, but the name and format of this file are
        not part of the specification.</para>

<para>All flags are optional.  The flags are these:</para>
<itemizedlist>
<listitem><para><option>--with-compiler=</option><replaceable>path</replaceable>, 
<option>--ghc</option>, 
<option>--nhc</option>, 
<option>--hugs</option>: 
specifies which compiler to use.  At most one of the value of these flags may be specified.
The configure step checks
that the compiler is available, in a sufficiently up-to-date form for the package, and that the package
expects to work with that compiler.  If the compiler name
is not specified, <literal>Setup.lhs</literal> will choose one; some packages will come with one compiler baked in.
</para>
	  </listitem>
<listitem><para><option>--prefix=</option><replaceable>path</replaceable>: specifies where the installed files
for the package should be installed (ie the location of the files themselves).  Typically on Unix this will be <filename>/usr/local</filename> and
on Windows it will be <filename>Program Files</filename>.  The setup script will use a sensible default
(often platform-specific) if the flag is not specified.
	    </para>
	  </listitem>

<listitem><para>Unrecognized flags are errors in the default build system, but may be meaningful to wrapped make-based systems (for instance).  Therefore, the provided command-line parser will pass unrecognized command-line flags on to the wrapped system.</para></listitem>

        </itemizedlist>

	<para>It is OK for these flags to be "baked into" the compiled
        &tool;.  In particular, the build system may bake the
        installation path into the compiled files.  There is no
        provision for changing these baked-into values after
        configuration.</para> </sect3>

      <sect3><title><option>build</option></title>
	
 	<para>The command <literal>./Setup.lhs build</literal> makes
        this package ready for installation.  It takes no
        flags.</para>

      </sect3>

      <sect3><title><option>install</option></title>

	<para>The command <literal>./Setup.lhs install</literal>
        copies files from the built package to the right location for
        installed files, specified in the configure step.  Then it
        registers the new package with the compiler, using the
        &hc-pkg; command.</para>

	<itemizedlist>
	  <listitem>

	    <para><option>--install-prefix=</option><replaceable>path</replaceable>:
            specifies where the installed files for the package should
            be installed (ie the location of the files themselves).
            It has three effects.  First, it over-rides the
            <option>--prefix</option> flag specified in the
            <option>configure</option> step, providing an alternative
            location.  Second, it does not call &hc-pkg; to register
            the package.  Instead, third, it creates an installed
            package description file,
            <filename>installed-pkg-descr</filename>, which can later
            be fed to &hc-pkg;.  </para> </listitem>

	  <listitem>
	    <para><option>--user</option>: if present, this flag is
            passed to &hc-pkg; so that the package is registed for the
            current user only.  This flag has no effect if
            <option>--install-prefix</option> is used, because in
            that case &hc-pkg; is not called.</para>
	  </listitem>

          <listitem>
	    <para><option>--global</option>: if present, this flag is
            passed to &hc-pkg; so that the package is registed
            globally (this is the default if neither
            <option>--user</option> or <option>--global</option> are
            given). This flag has no effect if
            <option>--install-prefix</option> is used, because in
            that case &hc-pkg; is not called.</para>
	  </listitem>
	</itemizedlist>

	<para>The reason for the <option>--install-prefix</option>
        flag is that Roland RPM wants to create an exact installation
        tree, all ready to bundle up for the target machine,
        <emphasis>but in a temporary location</emphasis>. He cannot
        use this location for <option>--prefix</option> in the
        <option>configure</option> step, because that might bake
        the wrong path into some compiled files.  Nor does he want to
        register this temporary tree with the compiler on his
        machine. Instead, he bundles up the temporary installation
        tree, plus the <filename>installed-pkg-descr</filename>, and
        ships them all to the target machine.  When they are installed
        there, the post-installation script runs
        &hc-pkg; on the
        <filename>installed-pkg-descr</filename> file.
	    </para>

	<para>Note that there is no <command>uninstall</command>
        command in the setup script.  While it would be easy enough to
        implement in the simple build infrastructure, we don't want to
        require make-based build systems to implement <literal>make
        uninstall</literal>, which is fairly non-standard and
        difficult to get right.  In the majority of cases, we expect
        libraries to be installed via a package manager (eg. RPM,
        Debian APT), which already provide uninstallation
        services.</para>
      </sect3>

      <sect3>
	<title><option>register</option> and
	<option>unregister</option></title>

	<para>The command <literal>./Setup.lhs register</literal>
        registers the now-installed package with the compiler.
        Similarly, <literal>./Setup.lhs unregister</literal>
        un-registers the package.</para>

	<itemizedlist>
	  <listitem>
	    <para><option>--global</option>: registers/un-registers a
            package as global.  This is the default.</para>
	  </listitem>
	  <listitem>
	    <para><option>--user</option>: registers/un-registers a
            package for the current user only.</para>
	  </listitem>
	</itemizedlist>
      </sect3>
    </sect2>

<sect2><title>Examples</title>
<sect3><title>Bob the Builder and Sam Sysadmin</title>

<para>Bob the Builder can install a &hps; source distribution thus.
He downloads the source distribution and unpacks it into a temporary directory,
<literal>cd</literal>'s to that directory, and says
<programlisting>
  ./Setup.lhs configure --ghc
  ./Setup.lhs build
  ./Setup.lhs install --user
</programlisting>
Similarly, Sam Sysadmin does exactly the same, except that he says 
<programlisting>
  ./Setup.lhs install --global
</programlisting>
in the final step, so that the package is installed where all users will see it.
      </para>
<para>For a binary distribution, both Bob and Sam would omit the first two steps, and just do the install step.</para>
</sect3>

<sect3><title>System packagers (Debian, RPM etc)</title>

        <para>System packagers, such as Peter Packager or Donald
        Debian, will run the configure and build steps just like Bob
        and Sam.  A that point, Donald will say <programlisting>
        ./Setup.lhs install --install-prefix=/tmp/donald
        </programlisting> to construct a ready-to-zip tree of all the
        installed files, plus a file
        <filename>installed-pkg-descr</filename> that describes the
        installed package.  He arranges to deliver both these
        components to the target machine, and then feed
        <filename>installed-pkg-descr</filename> to &hc-pkg; on the
        target machine.  </para>

	<para>The file <filename>installed-pkg-descr</filename> also
        contains information he needs for building his Debian
        distribution, namely the package name, version, and (exact)
        dependencies.</para>

	<para>We expect there to be additional tools to help System
	Packagers to prepare the materials necessary to build their
	packages from a source distribution.  For example, an RPM tool
	could take a Haskell package source distribution and build an
	initial <literal>.spec</literal> file with as many of the
	fields as possible filled in automatically.  In most cases
	some intervention by the System Packager will be necessary;
	for example platform-specific dependencies may need to be
	specified.</para>


        <para>After Peter has constructed the package, Isabella can
        install it in a manner she is comfortable with.</para>


      </sect3>
   </sect2>
</sect1>

<sect1 id=sbi><title>The &hps; simple build infrastructure</title>

<para>A package author must fulfil the specification of <xref linkend=setup>.
In many cases, a Haskell package will consist of nothing more than a bunch of Haskell modules,
with perhaps the odd C file.  In that case, the &hps; provides a <emphasis>simple build infrastructure</emphasis> that
fulfils the specification of <xref linkend=setup>, and provides some modest further facilities besides.</para>
<para>This simple build infrastructure is meant to automate the common case.
(Think <command>hmake</command>.)  The emphasis is on ``simple'': 
if you want something more elaborate, you can (a) modify the simple build infrastructure (which is written in Haskell)
(b) use makefiles, or (c) implement something else entirely.
</para>

<sect2><title>Overview</title>
<para>
The simple build infrastructure works as follows.  First, Angela puts the following Haskell 
file <filename>Setup.lhs</filename> in the
root of her tree:
<programlisting>
  #! /usr/bin/env runghc

  > import Distribution.Simple
</programlisting>
Second, she writes a package description &pkg-desc; in the syntax of <xref linkend="sbi-pkg-desc">,
which describes the package and gives extra information to the simple build infrastructure.
</para><para>
Now Angela can build her package by saying
<programlisting>
  ./Setup.lhs configure
  ./Setup.lhs build
</programlisting>
She can even install it on her own machine by saying
<programlisting>
  ./Setup.lhs install
</programlisting>
She can build a &hps; source distribution:
<programlisting>
  ./Setup.lhs source-dist
</programlisting>
The full details are given in <xref linkend="sbi-setup">.  
</para><para>
It is no coincidence that the interface is very similar to that for the setup script
for an &hps; package distribution (<xref linkend="setup">).
In fact, <literal>Distribution.Simple.defaultMain</literal> conforms to the specification of <xref linkend="setup-spec">, and when it builds
a distribution, it includes <filename>./Setup.lhs</filename> in the tarball, ready to be run by Bob the Builder.
However, <literal>Distribution.Simple.defaultMain</literal> of course implements a richer interface than that required by
<xref linkend="setup-spec">, because it's intended to support Angela as well as Bob.
The full specification is in <xref linkend="sbi-setup">.
</para>
    </sect2>
<sect2 id=sbi-pkg-desc><title>Package description in the simple build infrastructure</title>

<para>When using the simple build infrastructure, the package
description file &pkg-desc; contains not only the name of the package,
its version and dependencies, but also a collection of information to
explain to the simple build infrastructure how to build the package.
This section gives the specific fields, and the syntax of those
fields.  For the general syntax of the file, please see <xref
linkend="pkg-desc">.</para>

<para>Here is a sample package description file with all the fields understood by the simple build infrastructure:
<programlisting>
        -- Required
        Name: Cabal
        Version: 0.1.1.1.1-rain
        License: LGPL
        Copyright: Free Text String
        -- Optional - may be in source?
        Stability: Free Text String
        Build-Depends: haskell-src, HUnit>=1.0.0-rain
        Modules: Distribution.Package, Distribution.Version,
                 Distribution.Simple.GHCPackageConfig
        C-Sources: not/even/rain.c, such/small/hands
        HS-Source-Dir: src
        Exposed-Modules: Distribution.Void, Foo.Bar
        Extensions: OverlappingInstances, TypeSynonymInstances
        Extra-Libs: libfoo, bar, bang
        Include-Dirs: your/slightest, look/will
        Includes: /easily/unclose, /me, "funky, path\\name"
        Options-ghc: -fTH -fglasgow-exts
        Options-hugs: +TH

        -- Next is an executable
        Executable: somescript
        Main-is: SomeFile.hs
        Modules: Foo1, Util, Main
        HS-Source-Dir: scripts
        Extensions: OverlappingInstances</programlisting>
The Name, Version, License, and Copyright are compulsory.</para>

<para>All other fields, such as dependency-related fields, will be
considered empty if they are absent.  Any fields that the system does
not understand will be ignored.</para>

<para>Note that in the future, though the Modules field will be
available, it will not be necessary to provide it for building
executables and libraries.  Instead, the user will provide only the
"Main-Is" field (for executables) and the "Exposed-Modules" field (for
libraries).  The system will chase down dependencies from those
modules and include them in the library or source
distributions.</para>

<para>The description file fields:
   <table frame=all><title>Description File Fields</title>
   <tgroup cols=4 align=left colsep=1 rowsep=1> <tbody>
      <row><entry>Field Name</entry>
           <entry>Description</entry>
           <entry>Example</entry>
           <entry>Notes</entry>
      </row>

      <row><entry>name</entry>
           <entry>[a-zA-Z][-a-zA-Z0-9]*</entry>
           <entry>haskell-cabal12345</entry></row>
      <row><entry>version</entry>
           <entry>[0-9.]+(-?)[-a-zA-Z]*: branch numbers, separated by dots, and optional tags separated by dashes.</entry>
           <entry>1.2.3.4.5-foo-bar-bang</entry>
      </row>
      <row><entry>copyright</entry>
           <entry>--FREE TEXT--</entry>
           <entry>(c) 2004 Isaac Jones</entry>
      </row>

      <row><entry>license</entry>
           <entry>GPL | LGPL | BSD3 | BSD4 | PublicDomain | AllRightsReserved</entry>
           <entry>BSD3</entry>
           <entry>If your license isn't on this list, use the
           <emphasis>license-file</emphasis> field.</entry>

      </row>

      <row><entry>license-file</entry>
           <entry>--PATH--</entry>
           <entry>doc/myLicense.txt</entry>
           <entry>Specify the license you use as a relative path from the root of the source tree.</entry>
      </row>

      <row><entry>maintainer</entry>
           <entry>--FREE TEXT--</entry>
           <entry>T.S. Elliot &lt;elliot@email.com> </entry>
      </row>

      <row><entry>stability</entry>
           <entry>--FREE TEXT--</entry>
           <entry>Don't hook this up to your coffee machine</entry>
      </row>

      <row><entry>executable</entry>
           <entry>--FREE TEXT--</entry>
           <entry>cpphs</entry>
           <entry>For this Executable stanza, what is the name of the produced executable.</entry>
      </row>

      <row><entry>main-is</entry>
           <entry>--PATH--</entry>
           <entry>/foo/bar/bang/Baz.hs</entry>
           <entry>The filename to look for the main module for this Executable stanza.</entry>
      </row>

      <row><entry>extra-libs</entry>
           <entry>comma list of --FREE TEXT-- and spaces</entry>
           <entry>libfoo, libbar  ,   libbang</entry>
           <entry>for non-haskell libraries that this package needs to link to</entry>
      </row>

      <row><entry>build-depends</entry>
           <entry>package name (== | < | > | <= | >=) version</entry>
           <entry>foo > 1.2, bar < 3.3.5, bang</entry>
           <entry>If the version isn't listed, it's assumed any version is OK.</entry>
      </row>

      <row><entry>c-sources</entry>
           <entry>--PATH--</entry>
           <entry>/foo/bar/bang</entry>
           <entry>C source files to build using the FFI.</entry>
      </row>

      <row><entry>include-dirs</entry>
           <entry>--PATH--</entry>
           <entry>"/foo/bar/  ,bang"</entry>
           <entry>Not Yet Used</entry>
      </row>

      <row><entry>includes</entry>
           <entry>--PATH--</entry>
           <entry>/foo/bar/bang</entry>
           <entry>Not Yet Used</entry>
      </row>

      <row><entry>hs-source-dir</entry>
           <entry>--PATH--</entry>
           <entry>src</entry>
           <entry>A relative path from the root of your source tree.  Look here for the Haskell modules.</entry>
      </row>

      <row><entry>modules</entry>
           <entry>--MODULE LIST--</entry>
           <entry>Foo.Bar, Bang.Baz, Boo</entry>
           <entry>May not be necessary in the future, since we'll
           chase dependencies from exposed modules and main
           module.</entry>
      </row>

      <row><entry>exposed-modules</entry>
           <entry>--MODULE LIST--</entry>
           <entry>Foo.Bar, Bang.Baz, Boo</entry>
           <entry>For a library package, which modules should be
           available for import by the end user?</entry>
      </row>

      <row><entry>extensions</entry>
           <entry>OverlappingInstances
               | RecursiveDo
               | ParallelListComp
               | MultiParamTypeClasses
               | NoMonomorphismRestriction
               | FunctionalDependencies
               | RankNTypes
               | PolymorphicComponents
               | ExistentialQuantification
               | ScopedTypeVariables
               | ImplicitParams
               | FlexibleContexts
               | FlexibleInstances
               | EmptyDataDecls

	       | TypeSynonymInstances
	       | TemplateHaskell
               | ForeignFunctionInterface
               | AllowOverlappingInstances
               | AllowUndecidableInstances
               | AllowIncoherentInstances
               | InlinePhase
               | ContextStack
               | Arrows
               | Generics
               | NoImplicitPrelude
               | NamedFieldPuns

               | ExtensibleRecords
               | RestrictedTypeSynonyms
               | HereDocuments
               | UnsafeOverlappingInstances</entry>
           <entry>ForeignFunctionInterface, Arrows</entry>
           <entry>Not all extensions are understood by all &impls;</entry>
      </row>

      <row><entry>options-ghc</entry>
           <entry>--OPTIONS--</entry>
           <entry>-fth -cpp</entry>
           <entry>For command-line options not covered under
           <emphasis>extensions</emphasis>, add them here, separated
           by whitespace.</entry>

      </row>

      <row><entry>options-nhc</entry>
           <entry>--OPTIONS--</entry>
           <entry>-P -t</entry>
           <entry>For command-line options not covered under
           <emphasis>extensions</emphasis>, add them here, separated
           by whitespace.</entry>
      </row>

      <row><entry>options-hugs</entry>
           <entry>--OPTIONS--</entry>
           <entry>-98 +g</entry>
           <entry>For command-line options not covered under
           <emphasis>extensions</emphasis>, add them here, separated
           by whitespace.</entry>
      </row>

   </tbody></tgroup></table></para>

<para>Further details on some fields:
  <itemizedlist>

   <listitem><para><emphasis>--PATH--</emphasis> Paths are written in
   the Unix style, with directories separated by slashes, optionally
   ending in a filename.  There are two kinds of paths supported:
   "Simple" and "Complex".  "Simple" paths are alpha-numeric values
   separated by slashes (foo/bar/bang).  More "Complex" paths such as
   those with spaces or non-alphanumeric characters must be put in
   quotes ("foo, /bar \//bang").  You should assume that the paths are
   case sensitive, though in practice this varies depending on the end
   user's file system.  </para></listitem>

   <listitem><para><emphasis>--MODULE LIST--</emphasis> A module list
   is a standard Haskell module name, without any file suffixes (.lhs
   or .hs).  Each module should be separated by a
   comma.</para></listitem>

   <listitem><para><emphasis>--FREE TEXT--</emphasis> You may put
   anything in these fields.  For multi-line fields, start the
   subsequent lines with whitespace.</para></listitem>

   <listitem><para><emphasis>--OPTIONS--</emphasis>The exact syntax of
   the options field is dependent on the compiler you're using.  Refer
   to your compiler's man page for details.  Multiple options should
   be separated by whitespace.</para></listitem> </itemizedlist>

</para>

<para>On hidden modules: Hidden modules form part of the
implementation of the package, but not its interface: a client of the
package cannot import an internal module.  The system still must
derive their existence, or they must be listed explicity for two
reasons: (a) to allow the global program invariant to be checked (see
<xref linkend="packages-and-haskell">) and (b) to enable a build
system or programming environment to find the source files.  </para>
</sect2>

<sect2 id="sbi-setup"><title><literal>Distribution.Simple</literal></title>

<para>This section gives the command line interface supported by
<literal>Distribution.Simple.defaultMain</literal>.  It supports all the
commands described in <xref linkend=setup-spec>, (except for "test" -
FIX) and in addition the following: <table frame=all><title>Extra
commands supported by the simple build infrastructure setup
script</title>

     <tgroup cols=2 align=left colsep=1 rowsep=1>     <tbody>

     <row><Entry><command>./Setup.lhs sdist </command></entry>
         <Entry><para> Create a source tarball</para></entry></row>
     <row><Entry><command>... </command></entry>
         <Entry><para>...</para></entry></row>

     </tbody></tgroup>
     </table>
    </para>

<para>Distribution.Simple.defaultMain provides interactive command-line
help.  For each command, a help string is available by typing
"./Setup.lhs COMMAND --help".</para>

</sect2>

<sect2><title>The Makefile route</title>

<para>The Haskell libraries that support the simple build infrastructure can, of course, also
be re-used to make setup scripts that work quite differently.  At one extreme is a setup
script that immediately shells out into <literal>make</literal>, which does all the work.</para>

<para>To support this, &hps; provides a trivial setup library <literal>Distribution.Make</literal>, which
simply parses the command line arguments and shells out into <literal>make</literal>.  Marcus uses the following
<filename>Setup.lhs</filename>
<programlisting>
  #! /usr/bin/env runhugs

  > module Main where
  > import Distribution.Make (defaultMain)
  > main = defaultMain
</programlisting>
All the package description information is assumed to be known to the makefile system, and so does not
appear in the setup script.
Thus, 
<programlisting>
  ./Setup.lhs configure --ghc
</programlisting>
invokes
<programlisting>
  ./configure --with-compiler=ghc
</programlisting>
Similarly
<literal>./Setup.lhs build</literal>
invokes
<literal>make all</literal> And so on.</para>

<para>Marcus simply arranges that when his makefiles build a distribution, they include this simple setup script in
the root of the distribution, where the Bob the Builder expects to find it.</para>

</sect2>

</sect1>



<!-- Appendix: Layered Tools --------------------------------- -->
<appendix><title>Layered Tools</title>

<para>One great advantage to having a standard configure/build/install
interface for all Haskell packages is that end users don't need to
learn a new method for each package they install.</para>

<para>Likewise, with such an interface, we can build layered tools in
a typical Unix fashion.  For instance, we might want a tool that
downloads and installs Haskell packages.  It can be implemented as a
simple shell script, <application>haskell-install</application> (where
"$@" represents the command-line argument):

<programlisting>#!/bin/sh

echo "wget http://packages.haskell.org/$@"
echo "tar -zxvf $@.tgz"
echo "cd $@"
echo "./Setup.lhs configure"
echo "./Setup.lhs build"
echo "./Setup.lhs install"</programlisting></para>

<para>Now the end-user (Isabella) only needs to say "haskell-install
myPackage", rather than performing all of the Setup steps by
hand.</para>

</appendix>


<!-- Appendix: Related Systems --------------------------------- -->
<appendix><title>Related Systems</title>

<para>I will try to outline interesting points in a variety of systems
that we can learn from.  These systems may be intended for building or
installing packages, or repositories for packages.  I am not deeply
familiar with all of the tools here, and would be interested in
hearing more relevant points from someone with more knowledge.
Another weakness of mine is that I don't know much about Microsoft
Windows, so some good examples for Windows systems would be
helpful.</para>

<section id="lip-appendix-debian"><Title>Debian</title>

<para>
The <ulink url="http://www.debian.org">Debian GNU/Linux system</ulink>
is a good example of a <emphasis>binary</emphasis> distribution
(meaning that packages are distributed in binary, as opposed to source
code form), and its packaging system (<application>dpkg</application>)
is somewhat similar to the more famous <application>RPM</application>.
Debian has several other tools to help the user to install packages,
most notably, <command>apt</command>.  The Debian toolset is
interesting for several reasons:

<itemizedList>

  <listItem><para>It handles dependencies extremely well.  A single
  command can download and install a package, as well as downloading
  and installing all of its dependencies.</para></listItem>

  <listItem><para>It handles updates extremely well.  One command
  (<command>apt-get update</command>) checks for new versions of
  packages and updates a local database.  Another command
  (<command>apt-get dist-upgrade</command>) downloads and installs all
  new versions of installed packages and any new
  dependencies.</para></listItem>


  <listItem><para>There are standard commands for downloading and
  building packages from source.  If I'm interested in hacking on a
  package, I can run <command>apt-get source packagename</command>
  which will download and unpack the source code for the package.  The
  source can then be built with the standard command
  <command>debuild</command>.</para></listItem>


  <listItem><para>The Debian Project maintains a central repository
  for packages, and the packaging tools offer support for using
  unofficial repositories as well.  The central repositories include a
  set of servers, the <emphasis>autobuilders</emphasis>, which compile
  uploaded source packages for a variety of hardware architectures
  (see below) and make them available as binary packages.  As a
  packager, I merely upload the source code to my package, and the
  autobuilders do the rest.</para></listItem>

  <listitem><para>Currently the hardware architectures supported by
  Debian are Intel x86, Motorola 68k, Sun SPARC, Alpha, PowerPC, ARM,
  MIPS, HP PA-RISC, IA-64, S/390.  Debian also runs on non-Linux
  systems, including GNU/Hurd, GNU/NetBSD, and GNU/FreeBSD.  The
  package management tools also run on MacOS X under the name of the
  <application>Fink</application> project.</para></listItem>

</itemizedList>
</para>

</section>

<section id="lip-appendix-distutils"><title>Python Distutils</title>

<para>Python's <ulink
url="http://www.python.org/sigs/distutils-sig/">&distutils;
system</ulink> is in many ways similar to what we propose here.  It is
a system for building and installing Python modules, written purely in
Python.  The user interface is a Python script,
(<filename>setup.py</filename> by convention) and a setup
configuration file (<filename>setup.cfg</filename> by convention). To
quote from <ulink
url="http://www.python.org/doc/current/dist/dist.html">Distributing
Python Modules</ulink>, "The setup configuration file is a useful
middle-ground between the setup script--which, ideally, would be
opaque to installers -- and the command-line to the setup script,
which is outside of your control and entirely up to the
installer. "</para>

<para>Its noteworthy that Python has a big advantage over many
programming languages when implementing a system like &distutils;: It
is designed to be well suited to so-called scripting tasks, which are
common to the installation task, and Python has done these tasks in a
portable way for a long time.  I believe that Haskell should evolve
portable ways to perform common scripting tasks.</para>

</section>

<section id="lip-appendix-cpan-boost"><title>&cpan; and Boost</title>

<para> Quoting from &cpan;'s <ulink url="http://www.cpan.org"> web
site </ulink> "&cpan; is the Comprehensive Perl Archive Network, a
large collection of Perl software and documentation."  That really
says it all.  It is a central location where Perl developers can
contribute the software they write.</para>

<para>&cpan; has a means of standardizing installation,
<filename>Makefile.pl</filename> (which is a Perl script which creates
a Makefile with targets like "install", "test", "config", "clean", etc.). Makefile.pl typically uses the <ulink
url="http://www.perldoc.com/perl5.6/lib/ExtUtils/MakeMaker.html">MakeMover
module</ulink>. It also has a means of registering a namespace for the
module that a developer is contributing.</para>

<para>From the Boost <ulink url="http://www.boost.org">web
site</ulink> "[Boost] provides free peer-reviewed portable C++ source
libraries. The emphasis is on libraries which work well with the C++
Standard Library. One goal is to establish "existing practice" and
provide reference implementations so that the Boost libraries are
suitable for eventual standardization. Some of the libraries have
already been proposed for inclusion in the C++ Standards Committee's
upcoming C++ Standard Library Technical Report."</para>

<para>From what I can tell, unlike &cpan;, Boost is a bit more focused
on standards and review.  That is, it is perhaps more Cathedral than
Bazaar <footnote><para>See Eric Raymond's essay <ulink
url="http://catb.org/~esr/writings/cathedral-bazaar/cathedral-bazaar/">The
Cathedral and the Bazaar</ulink>.</para></footnote>. Boost does not
currently have a standard means of installation.</para>
</section>

<section id="lip-appendix-freebsd"><title>FreeBSD's Ports System</title>

<para>The FreeBSD <ulink url="http://www.freebsd.org/ports/">Ports
Collection</ulink> is a collection of software with a standard means
of compilation and installation.  FreeBSD is a source distribution
(whereas Debian is a Binary Distribution).  Packages come in
source-code form with a Makefile suitable for installing the program
on a FreeBSD system.  The ports collection is very large (around 9000
packages).</para>

<para>Some things may be simpler with a source distribution than with
a binary distribution.  For instance, since the code is expected to be
already on the machine and buildable, when a new compiler is installed
one merely needs to rebuild the dependant libraries.  In contrast,
with a binary distribution like Debian one must wait for a new binary
package to be made available.  However, as I understand it, FreeBSD
has no means of recompiling dependant packages automatically when a
new compiler is installed.</para>

</section>

<!-- FIX: I'm not sure why I thought this was so interesting.  I don't -->
<!-- reference it anywhere and it really doesn't add anything that the perl -->
<!-- and python systems don't have. -->

<section id="lip-appendix-xemacs"><title>The &xemacs; Packaging
System</title>

<para>
As most folks know, &xemacs; is not only a text editor, but also a
Lisp environment.  Its functionality can be extended with lisp
programs, and many such programs are available from &xemacs;' <ulink
url="http://www.xemacs.org/Documentation/21.5/html/lispref_4.html">Packaging
System</ulink>.  Simply put, the packaging system offers a menu-driven
interface within &xemacs; where the user can browse available
packages, select packages she is interested in, and ask &xemacs; to
download and install them.  This system is interesting because it is
cross-platform (Unix, Linux, Windows, etc.) and is designed to work
only with elisp.
</para>



 </section>

<section id="lip-appendix-make-based"><title>Make-Based Systems</title>

<para>The "fptools" build system has been used for many years in the
cross-platform &ghc; compiler.  It is a make-based system which is
capable of a wide variety of installation tasks, compilation tasks,
and system configuration tasks.  Currently, it is not entirely generic
across &impls;, and does not yet deal with some of the package
registration issues mentioned above.</para>

<para>At Yale, another system is being developed.  It is also a
make-based system and works reasonably well on various platforms
(Unix, Linux, Windows) and &impls;.  It also does not yet deal with
all of the package registration issues mentioned above.</para>

<para>Both tools can benefit from a standard packaging system.</para>

<para>Because <application>make</application> has been used for many
years, it is expected that these systems will be able to do more than
the initial release of the &distMod;.  The Setup script will be
designed with this in mind, and should be able to wrap these tools in
order to provide a common interface for users and for layered
tools.</para>

</section>

<section id="lip-appendix-hmake"><title>&hmake;</title>

<para>From the &hmake; <ulink
url="http://www.cs.york.ac.uk/fp/hmake/">home page</ulink>,
<quote>&hmake; is an intelligent compilation management tool for
Haskell programs. It automatically extracts dependencies between
source modules, and issues the appropriate compiler commands to
rebuild only those that have changed, given just the name of the
program or module that you want to build. Yes, you need never write a
Makefile again!</quote> &hmake; also does a good job of handling the
variety of compilers that might be installed on a user's system.  It
maintains a list of compilers and can switch between them according to
a flag.  It also has a default compiler.</para>

<para>&hmake; is particularly interesting to us because it is written
in Haskell and handles the task of compiling Haskell tools quite well.
One shortcoming is that it is not extensible on a per-project basis:
it is difficult to add support for new preprocessors without editing
the &hmake; code itself.  It does, however, perform a lot of the tasks
that &DistBuild; will ultimately have to perform, and we hope to reuse
some of the code.</para>

<para>Another interesting feature of &hmake; is the
<application>Haskell Interactive</application> tool (hi).  hi
<quote>is, an interpreter-like environment that you can wrap over any
common Haskell compiler to achieve an interactive development
style.</quote> This is interesting because it would be nice to have a
generic <filename>/usr/bin/haskell</filename> which would use the
default compiler to interpret Haskell scripts.</para>

</section>

</appendix>
 
</article>