DEADSOFTWARE

cpmake: add target-specific options (compiler/processor/os/linker)
[cpc.git] / src / generic / Dsw / Mod / MakeMain.cp
1 MODULE DswMakeMain;
3 IMPORT Kernel, Files, Log, Strings, DswOpts, DswProcs, DswDocuments, DevCPM, DevCPT, DevCPR, DevCPS;
5 CONST
6 maxImps = 127;
7 maxJobs = maxImps;
9 (* symbol values *)
10 null = 0; times = 1; slash = 2; div = 3; mod = 4;
11 and = 5; plus = 6; minus = 7; or = 8; eql = 9;
12 neq = 10; lss = 11; leq = 12; gtr = 13; geq = 14;
13 in = 15; is = 16; arrow = 17; dollar = 18; period = 19;
14 comma = 20; colon = 21; upto = 22; rparen = 23; rbrak = 24;
15 rbrace = 25; of = 26; then = 27; do = 28; to = 29;
16 by = 30; not = 33;
17 lparen = 40; lbrak = 41; lbrace = 42; becomes = 44;
18 number = 45; nil = 46; string = 47; ident = 48; semicolon = 49;
19 bar = 50; end = 51; else = 52; elsif = 53; until = 54;
20 if = 55; case = 56; while = 57; repeat = 58; for = 59;
21 loop = 60; with = 61; exit = 62; return = 63; array = 64;
22 record = 65; pointer = 66; begin = 67; const = 68; type = 69;
23 var = 70; out = 71; procedure = 72; close = 73; import = 74;
24 module = 75; eof = 76;
26 (* module state flags *)
27 imported = 0; trace = 1; hasObj = 2; hasSym = 3; hasErrors = 4; library = 5;
29 (* procesor types *)
30 anymach = 0; cmach = 1; mach386 = 10; mach68k = 20;
32 (* operation system types *)
33 anyos = 0; linux = 1; freebsd = 2; openbsd = 3; win32 = 4;
35 (* compiler types *)
36 anycp = 0; cpnative = 1; cpfront = 2;
38 (* internal linker types *)
39 anyint = 0; dev2 = 1;
41 debugImport = FALSE;
42 debugOrder = FALSE;
43 debugJobs = FALSE;
45 TYPE
46 String = POINTER TO ARRAY OF CHAR;
48 Selector = POINTER TO RECORD
49 name: DevCPT.Name;
50 value: BOOLEAN;
51 next: Selector
52 END;
54 Module = POINTER TO RECORD
55 name: DevCPT.Name;
56 path: Files.Name;
57 selectors: Selector; (* with head, list of selectors for this module *)
58 depth: INTEGER; (* 0: leaf, MAX: root *)
59 mno: INTEGER;
60 imp: ARRAY maxImps OF Module;
61 flags: SET;
62 worker: DswProcs.Process;
63 END;
65 VAR
66 err: INTEGER;
67 mno, rno: INTEGER; (* num modules *)
68 modList, lnkList, cmpList: ARRAY maxImps OF Module;
69 def: Selector; (* with head, global list of selectors *)
70 processor, compiler, os, linker: INTEGER;
71 auto: BOOLEAN;
72 jobs: INTEGER;
73 exe: String;
75 (* --------- options --------- *)
77 PROCEDURE IdentLen (IN s: ARRAY OF CHAR): INTEGER;
78 VAR i: INTEGER;
79 BEGIN
80 i := 0;
81 IF Strings.IsIdentStart(s[0]) THEN
82 REPEAT INC(i) UNTIL ~Strings.IsIdent(s[i])
83 END;
84 RETURN i
85 END IdentLen;
87 PROCEDURE Define (n: ARRAY OF CHAR);
88 VAR i: INTEGER; v: BOOLEAN; s: Selector;
89 BEGIN
90 i := IdentLen(n);
91 IF i # 0 THEN
92 IF ~((n[i] = 0X) OR (((n[i] = "+") OR (n[i] = "-")) & (n[i + 1] = 0X))) THEN
93 Log.String("option -D expect + or - after identifier"); Log.Ln; INC(err)
94 END;
95 v := n[i] # "-"; n[i] := 0X; s := def;
96 WHILE (s.next # NIL) & (s.next.name$ # n$) DO s := s.next END;
97 IF s.next = NIL THEN
98 NEW(s.next);
99 Strings.StringToUtf8(n, s.next.name, i);
100 ASSERT(i = 0)
101 END;
102 s.next.value := v
103 ELSE
104 Log.String("option -D expect identifier"); Log.Ln; INC(err)
105 END
106 END Define;
108 PROCEDURE Undefine (IN n: ARRAY OF CHAR);
109 VAR i: INTEGER; s: Selector;
110 BEGIN
111 i := IdentLen(n);
112 IF (i # 0) & (n[i] = 0X) THEN
113 s := def;
114 WHILE (s.next # NIL) & (s.next.name$ # n$) DO s := s.next END;
115 IF s.next # NIL THEN s.next := s.next.next END
116 ELSE
117 Log.String("option -U expect identifier"); Log.Ln; INC(err)
118 END
119 END Undefine;
121 PROCEDURE CopySelectorList (base: Selector): Selector;
122 VAR s, t, x: Selector;
123 BEGIN
124 ASSERT(base # NIL, 20);
125 s := base; NEW(t); x := t;
126 WHILE s # NIL DO
127 x^ := s^;
128 IF s.next # NIL THEN NEW(x.next); x := x.next END;
129 s := s.next
130 END;
131 RETURN t
132 END CopySelectorList;
134 PROCEDURE AddModule (IN n: ARRAY OF CHAR; selectors: Selector);
135 VAR i, res: INTEGER; m: Module;
136 BEGIN
137 i := IdentLen(n);
138 IF (i # 0) & (n[i] = 0X) THEN
139 i := 0;
140 WHILE (i < mno) & (modList[i].name$ # n$) DO INC(i) END;
141 IF i >= mno THEN
142 NEW(m);
143 Strings.StringToUtf8(n, m.name, res);
144 ASSERT(res = 0);
145 m.selectors := CopySelectorList(selectors);
146 modList[i] := m;
147 INC(mno)
148 END
149 ELSE
150 Log.String("module name must be identifier"); Log.Ln; INC(err)
151 END
152 END AddModule;
154 PROCEDURE StrToInt (IN s: ARRAY OF CHAR; def: INTEGER): INTEGER;
155 VAR x, res: INTEGER;
156 BEGIN
157 Strings.StringToInt(s, x, res);
158 IF res # 0 THEN
159 Log.String("expected integer"); Log.Ln; INC(err);
160 x := def
161 END;
162 RETURN x
163 END StrToInt;
165 PROCEDURE Help;
166 BEGIN
167 Log.String("Usage: cpmake [options] module..."); Log.Ln;
168 Log.String("Options:"); Log.Ln;
169 Log.String(" -Tm cpu Generate code for specified processor"); Log.Ln;
170 Log.String(" none Unknown processor (cpfront only)"); Log.Ln;
171 Log.String(" 486 Intel 486"); Log.Ln;
172 Log.String(" -Ts os Generate code for specified operation system"); Log.Ln;
173 Log.String(" none Unknown operation system"); Log.Ln;
174 Log.String(" linux Linux"); Log.Ln;
175 Log.String(" -Tg compiler Specify Component Pascal compiler"); Log.Ln;
176 Log.String(" native BlackBox based native code compiler"); Log.Ln;
177 Log.String(" cpfront BlackBox based C code translator"); Log.Ln;
178 Log.String(" -Ti linker Specify internal linker (native only)"); Log.Ln;
179 Log.String(" dev2 Dev2 based ELF/PE linker"); Log.Ln;
180 (*
181 Log.String(" -Fp path Add path with project"); Log.Ln;
182 Log.String(" -Fx path Add postfix for project directories"); Log.Ln;
183 Log.String(" -Xp path Use executable file for Component Pascal compiler"); Log.Ln;
184 Log.String(" -Xi path Use executable file for internal linker (native only)"); Log.Ln;
185 Log.String(" -Cp params Pass parameters to Component Pasacal compiler directly"); Log.Ln;
186 Log.String(" -Ci params Pass parameters to internal linker directly"); Log.Ln;
187 Log.String(" -a Enable automatic dependency resolution"); Log.Ln;
188 *)
189 Log.String(" -o name Generate executable file"); Log.Ln;
190 Log.String(" -j num Specifies the number of jobs to run simultaneously"); Log.Ln;
191 Log.String(' -D ident["+"|"-"] Add preprocessor selector'); Log.Ln;
192 Log.String(' -U ident Remove preprocessor selector'); Log.Ln;
193 Log.String(" -h Print help"); Log.Ln;
194 Log.String(" -v Print version"); Log.Ln;
195 Kernel.Quit(1)
196 END Help;
198 PROCEDURE ParseTargetOpts;
199 VAR s: DswOpts.String;
200 BEGIN
201 CASE DswOpts.GetOpt("m:s:g:i:") OF
202 | "m":
203 s := DswOpts.str;
204 Strings.ToLower(s, s);
205 IF s$ = "none" THEN processor := anymach
206 ELSIF s$ = "486" THEN processor := mach386
207 ELSIF s$ = "68k" THEN processor := mach68k
208 ELSE Log.String("unknwon processor "); Log.String(s); Log.Ln; INC(err)
209 END
210 | "s":
211 s := DswOpts.str;
212 Strings.ToLower(s, s);
213 IF s$ = "none" THEN os := anyos
214 ELSIF s$ = "linux" THEN os := linux
215 ELSE Log.String("unknwon os "); Log.String(s); Log.Ln; INC(err)
216 END
217 | "g":
218 s := DswOpts.str;
219 Strings.ToLower(s, s);
220 IF s$ = "native" THEN compiler := cpnative
221 ELSIF s$ = "cpfront" THEN compiler := cpfront
222 ELSE Log.String("unknwon compiler "); Log.String(s); Log.Ln; INC(err)
223 END
224 | "i":
225 s := DswOpts.str;
226 Strings.ToLower(s, s);
227 IF s$ = "dev2" THEN linker := dev2
228 ELSE Log.String("unknwon linker "); Log.String(s); Log.Ln; INC(err)
229 END
230 | ":": Log.String("missing argument for option -T"); Log.String(DswOpts.str); Log.Ln; INC(err)
231 | "?": Log.String("unknown option -T"); Log.String(DswOpts.str); Log.Ln; INC(err)
232 | 0X: Log.String("unknown option -T"); Log.Ln; INC(err)
233 END
234 END ParseTargetOpts;
236 PROCEDURE ParseArgs;
237 BEGIN
238 exe := NIL; auto := FALSE; jobs := 1; def.next := NIL; mno := 0; rno := 0;
239 processor := anymach; os := anyos; compiler := anycp;
240 LOOP
241 CASE DswOpts.GetOpt("ao:j:D:U:Th") OF
242 | "a": auto := TRUE
243 | "o": exe := DswOpts.str
244 | "j": jobs := MIN(MAX(StrToInt(DswOpts.str, 1), 1), maxJobs)
245 | "h": Help
246 | "D": Define(DswOpts.str)
247 | "U": Undefine(DswOpts.str)
248 | "T": ParseTargetOpts
249 | ":": Log.String("missing argument for option -"); Log.String(DswOpts.str); Log.Ln; INC(err)
250 | "?": Log.String("unknown option -"); Log.String(DswOpts.str); Log.Ln; INC(err)
251 | "$": AddModule(DswOpts.str, def)
252 | 0X: EXIT
253 END
254 END
255 END ParseArgs;
257 PROCEDURE CheckParams;
258 BEGIN
259 IF compiler = anycp THEN
260 Log.String("compiler not selected"); Log.Ln; INC(err)
261 ELSIF compiler = cpnative THEN
262 IF processor = anymach THEN
263 Log.String("processor not selected"); Log.Ln; INC(err)
264 ELSIF processor # mach386 THEN
265 Log.String("processor not supported by native compiler"); Log.Ln; INC(err)
266 END
267 END;
268 IF (compiler = cpfront) & (linker # anyint) THEN
269 Log.String("internal linker not required for cpfront"); Log.Ln; INC(err)
270 END;
271 IF (compiler = cpfront) & (exe # NIL) THEN
272 Log.String("cpfront can't out executable file"); Log.Ln; INC(err)
273 END;
274 IF (exe # NIL) & (compiler = cpnative) & (linker = anyint) THEN
275 Log.String("linker not selected"); Log.Ln; INC(err)
276 END;
277 IF (linker = dev2) & (os = anyos) THEN
278 Log.String("os not selected"); Log.Ln; INC(err)
279 END;
280 IF (exe # NIL) & (exe^ = "") THEN
281 Log.String("output file name can't be empty"); Log.Ln; INC(err)
282 END
283 END CheckParams;
285 (* --------- loader --------- *)
287 PROCEDURE Import (m: Module; IN name: DevCPT.Name);
288 VAR i, j: INTEGER; imp: Module;
289 BEGIN
290 ASSERT(m # NIL, 20);
291 ASSERT(name # "", 21);
292 IF debugImport THEN Log.String(" import "); Log.String(name$) END;
293 IF name = "SYSTEM" THEN INCL(DevCPM.options, DevCPM.sysImp)
294 ELSIF name = "COM" THEN INCL(DevCPM.options, DevCPM.com)
295 ELSIF name = "JAVA" THEN INCL(DevCPM.options, DevCPM.java)
296 ELSE
297 IF debugImport THEN Log.Char(" ") END;
298 i := 0; (* find module in local list *)
299 WHILE (i < m.mno) & (m.imp[i].name$ # name$) DO INC(i) END;
300 IF i >= m.mno THEN
301 j := 0; (* find module in global list *)
302 WHILE (j < mno) & (modList[j].name$ # name$) DO INC(j) END;
303 IF j >= mno THEN
304 NEW(imp); imp.name := name$; imp.selectors := CopySelectorList(m.selectors);
305 modList[mno] := imp; INC(mno)
306 ELSE
307 imp := modList[j]
308 END;
309 m.imp[m.mno] := imp; INC(m.mno)
310 ELSE DevCPM.err(1)
311 END
312 END;
313 IF debugImport THEN Log.Ln END;
314 END Import;
316 PROCEDURE ParseModule (m: Module);
317 VAR sym: BYTE; SelfName, impName, aliasName: DevCPT.Name;
319 PROCEDURE err (n: SHORTINT);
320 BEGIN DevCPM.err(n)
321 END err;
323 PROCEDURE CheckSym(s: SHORTINT);
324 BEGIN
325 IF sym = s THEN DevCPS.Get(sym) ELSE DevCPM.err(s) END
326 END CheckSym;
328 BEGIN
329 IF debugImport THEN Log.String("module " + m.name); Log.Ln END;
330 DevCPS.Init; DevCPS.Get(sym);
331 IF sym = module THEN DevCPS.Get(sym) ELSE err(16) END;
332 IF sym = ident THEN
333 SelfName := DevCPS.name$; DevCPS.Get(sym);
334 IF sym = lbrak THEN
335 INCL(DevCPM.options, DevCPM.interface); DevCPS.Get(sym);
336 IF sym = eql THEN DevCPS.Get(sym)
337 ELSE INCL(DevCPM.options, DevCPM.noCode)
338 END;
339 IF sym = string THEN INCL(m.flags, library); DevCPS.Get(sym)
340 ELSE err(string)
341 END;
342 CheckSym(rbrak)
343 END;
344 CheckSym(semicolon);
345 IF sym = import THEN DevCPS.Get(sym);
346 LOOP
347 IF sym = ident THEN
348 aliasName := DevCPS.name$; impName := aliasName$; DevCPS.Get(sym);
349 IF sym = becomes THEN DevCPS.Get(sym);
350 IF sym = ident THEN impName := DevCPS.name$; DevCPS.Get(sym) ELSE err(ident) END
351 END;
352 Import(m, impName)
353 ELSE err(ident)
354 END;
355 IF sym = comma THEN DevCPS.Get(sym)
356 ELSIF sym = ident THEN err(comma)
357 ELSE EXIT
358 END
359 END;
360 CheckSym(semicolon)
361 END
362 ELSE err(ident)
363 END;
364 DevCPS.str := NIL
365 END ParseModule;
367 PROCEDURE CheckModule (m: Module; source: String; OUT ok: BOOLEAN);
368 VAR s: Selector;
369 BEGIN
370 DevCPM.Init(source);
371 (*
372 DevCPM.symList := m.insym;
373 DevCPM.codePath := m.outcode;
374 DevCPM.symPath := m.outsym;
375 *)
376 DevCPM.name := m.name$;
377 (*
378 IF m.found THEN INCL(DevCPM.options, DevCPM.comAware) END;
379 IF errorTrap IN m.opts THEN INCL(DevCPM.options, DevCPM.trap) END;
380 IF oberon IN m.opts THEN INCL(DevCPM.options, DevCPM.oberon) END;
381 *)
382 DevCPR.Init;
383 s := m.selectors.next;
384 WHILE s # NIL DO
385 DevCPR.Set(s.name, s.value);
386 s := s.next
387 END;
388 ParseModule(m);
389 DevCPR.Check;
390 ok := DevCPM.noerr;
391 DevCPR.Close;
392 DevCPM.InsertMarks;
393 DevCPM.Close;
394 Kernel.FastCollect
395 END CheckModule;
397 PROCEDURE GetSource (IN modName: ARRAY OF CHAR; OUT path: Files.Name; OUT s: String);
398 CONST modDir = "Mod"; sysDir = "System";
399 VAR dir, name: Files.Name; loc: Files.Locator;
400 text: DswDocuments.Model; r: DswDocuments.Reader; i, res: INTEGER;
402 PROCEDURE MakePath (dir, name: Files.Name; type: Files.Type; OUT path: Files.Name);
403 BEGIN
404 ASSERT(name # "", 21);
405 IF dir = "" THEN path := modDir + "/" + name
406 ELSE path := dir + "/" + modDir + "/" + name
407 END;
408 Kernel.MakeFileName(path, type)
409 END MakePath;
411 BEGIN
412 s := NIL; path := "";
413 Kernel.SplitName(modName, dir, name);
414 loc := Files.dir.This(dir).This(modDir);
415 (* --> Kernel.MakeFileName(name, Kernel.docType); <-- *)
416 MakePath(dir, name, "cp", path);
417 DswDocuments.Open(loc, name + ".cp", text, res);
418 IF text = NIL THEN
419 MakePath(dir, name, "odc", path);
420 DswDocuments.Open(loc, name + ".odc", text, res);
421 IF (text = NIL) & (dir = "") THEN
422 MakePath(sysDir, name, "cp", path);
423 loc := Files.dir.This(sysDir).This(modDir);
424 DswDocuments.Open(loc, name + ".cp", text, res);
425 IF text = NIL THEN
426 MakePath(sysDir, name, "odc", path);
427 DswDocuments.Open(loc, name + ".odc", text, res);
428 IF text = NIL THEN
429 path := ""
430 END
431 END
432 END
433 END;
434 IF text # NIL THEN
435 NEW(s, text.Length() + 1);
436 IF s # NIL THEN
437 r := text.NewReader(NIL);
438 FOR i := 0 TO text.Length() - 1 DO
439 r.Read; s[i] := r.char
440 END
441 END
442 END
443 END GetSource;
445 PROCEDURE Trace (m, parent: Module; VAR lno: INTEGER);
446 VAR i: INTEGER;
447 BEGIN
448 IF ~(trace IN m.flags) THEN
449 INCL(m.flags, trace);
450 FOR i := 0 TO m.mno - 1 DO
451 Trace(m.imp[i], m, lno);
452 m.depth := MAX(m.depth, m.imp[i].depth + 1)
453 END;
454 IF ~(imported IN m.flags) THEN
455 INCL(m.flags, imported);
456 lnkList[lno] := m;
457 INC(lno)
458 END;
459 EXCL(m.flags, trace)
460 ELSE
461 Log.String("recursive import of " + m.name + " in " + parent.name); Log.Ln; INC(err)
462 END
463 END Trace;
465 PROCEDURE Sort;
466 VAR i, j: INTEGER; m: Module;
467 BEGIN
468 ASSERT((mno = 0) OR (lnkList[0] # NIL), 20);
469 cmpList := lnkList;
470 i := 1;
471 WHILE i < mno DO
472 m := cmpList[i];
473 j := i - 1;
474 WHILE (j >= 0) & (cmpList[j].depth > m.depth) DO
475 cmpList[j + 1] := cmpList[j];
476 DEC(j)
477 END;
478 cmpList[j + 1] := m;
479 INC(i)
480 END
481 END Sort;
483 PROCEDURE CheckDeps;
484 VAR i, j, num: INTEGER; m: Module; s: String; ok: BOOLEAN;
485 BEGIN
486 i := 0; rno := mno;
487 WHILE (err = 0) & (i < mno) DO
488 m := modList[i];
489 GetSource(m.name$, m.path, s);
490 IF s # NIL THEN
491 CheckModule(m, s, ok);
492 IF ~ok THEN INC(err) END
493 ELSE
494 Log.String("unable to open module " + m.name); Log.Ln; INC(err)
495 END;
496 INC(i)
497 END;
498 num := 0;
499 FOR i := 0 TO rno - 1 DO
500 Trace(modList[i], modList[i], num)
501 END;
502 ASSERT((err # 0) OR (num = mno), 100);
503 Sort;
504 IF debugOrder THEN
505 Log.String("Parallel depth:"); Log.Ln;
506 FOR i := 0 TO mno - 1 DO
507 Log.String(" " + cmpList[i].name); Log.Int(cmpList[i].depth); Log.Ln;
508 END
509 END
510 END CheckDeps;
512 PROCEDURE IsCompiled (m: Module): BOOLEAN;
513 CONST target = {hasSym, hasObj};
514 VAR i: INTEGER; ready: BOOLEAN;
515 BEGIN
516 ASSERT(m # NIL, 20);
517 i := 0;
518 ready := ~(hasErrors IN m.flags) & (m.flags * target = target);
519 WHILE ready & (i < m.mno) DO
520 ready := IsCompiled(m.imp[i]);
521 INC(i)
522 END;
523 RETURN ready
524 END IsCompiled;
526 PROCEDURE Ready (m: Module): BOOLEAN;
527 CONST target = {hasSym, hasObj};
528 VAR i: INTEGER; ready: BOOLEAN;
529 BEGIN
530 i := 0;
531 ready := ~(hasErrors IN m.flags) & (m.flags * target # target) & (m.worker = NIL);
532 WHILE ready & (i < m.mno) DO
533 ready := IsCompiled(m.imp[i]);
534 INC(i)
535 END;
536 RETURN ready
537 END Ready;
539 PROCEDURE ExecuteCompiler (m: Module): DswProcs.Process;
540 VAR w: DswProcs.Process; ok: BOOLEAN;
541 BEGIN
542 ASSERT(m # NIL, 20);
543 ASSERT(m.path # "", 21);
544 ASSERT(m.worker = NIL, 22);
545 w := DswProcs.dir.New();
546 CASE compiler OF
547 | cpnative: w.Program("cpc486")
548 | cpfront: w.Program("cpfront")
549 END;
550 w.PutParam("-legacy");
551 w.PutParam(m.path);
552 w.Execute(ok);
553 IF ok THEN
554 Log.String("Compile " + m.name + " (" + m.path + ")"); Log.Ln;
555 ELSE
556 w := NIL
557 END;
558 RETURN w
559 END ExecuteCompiler;
561 PROCEDURE Compile;
562 VAR i, j, num: INTEGER; ok: BOOLEAN; m: Module; w: DswProcs.Process;
563 BEGIN
564 IF mno = 0 THEN RETURN END;
565 num := 0; j := 0;
566 WHILE (err = 0) & (num < mno) OR (j > 0) DO
567 i := 0;
568 WHILE (err = 0) & (i < mno) & (j < jobs) DO
569 m := cmpList[i];
570 IF Ready(m) THEN
571 w := ExecuteCompiler(m);
572 IF debugJobs THEN Log.String("Start job " + m.name) END;
573 IF w # NIL THEN
574 IF debugJobs THEN Log.String(" ok") END;
575 m.worker := w;
576 INC(j)
577 ELSE
578 IF debugJobs THEN Log.String(" fail") END;
579 INCL(m.flags, hasErrors);
580 INC(err)
581 END;
582 IF debugJobs THEN Log.Ln END
583 END;
584 INC(i)
585 END;
586 WHILE (err = 0) & (j >= jobs) OR (j > 0) DO
587 i := 0;
588 WHILE (j > 0) & (i < mno) DO
589 m := cmpList[i];
590 w := m.worker;
591 IF (w # NIL) & w.IsTerminated() THEN
592 IF debugJobs THEN Log.String("Stop job " + m.name); Log.Int(w.Result()); Log.Ln END;
593 IF w.Result() = 0 THEN
594 INCL(m.flags, hasObj);
595 INCL(m.flags, hasSym);
596 INC(num)
597 ELSE
598 INCL(m.flags, hasErrors);
599 INC(err)
600 END;
601 m.worker := NIL;
602 DEC(j)
603 END;
604 INC(i)
605 END
606 END
607 END
608 END Compile;
610 PROCEDURE LinkDev2;
611 VAR p: DswProcs.Process; i, res: INTEGER; ok: BOOLEAN;
612 BEGIN
613 ASSERT((exe # NIL) & (exe^ # ""), 20);
614 ASSERT(processor = mach386, 21);
615 ASSERT(compiler = cpnative, 22);
616 ASSERT(os IN {linux, freebsd, openbsd, win32}, 23);
617 p := DswProcs.dir.New();
618 p.Program("cpl486");
619 IF os # anyos THEN
620 p.PutParam("-os");
621 CASE os OF
622 | linux: p.PutParam("linux")
623 | freebsd: p.PutParam("freebsd")
624 | openbsd: p.PutParam("openbsd")
625 | win32: p.PutParam("win32")
626 END
627 END;
628 p.PutParam("-kernel");
629 p.PutParam("Kernel");
630 p.PutParam("-main");
631 p.PutParam("Kernel");
632 p.PutParam("-legacycodedir");
633 p.PutParam(".");
634 p.PutParam("-o");
635 p.PutParam(exe);
636 i := 0;
637 WHILE i < mno DO
638 IF ~(library IN lnkList[i].flags) THEN
639 p.PutParam(lnkList[i].name$)
640 END;
641 INC(i)
642 END;
643 p.Execute(ok);
644 IF ok THEN
645 Log.String("Link "); Log.String(exe); Log.Ln;
646 res := p.Result();
647 IF res # 0 THEN
648 Log.String("linker terminated with error"); Log.Int(res); Log.Ln;
649 INC(err)
650 END
651 ELSE
652 Log.String("unable to execute linker"); Log.Int(i); Log.Ln;
653 INC(err)
654 END
655 END LinkDev2;
657 PROCEDURE Link;
658 BEGIN
659 IF exe # NIL THEN
660 CASE linker OF
661 | anyint: (* do not link *)
662 | dev2: LinkDev2
663 END
664 END
665 END Link;
667 PROCEDURE Main;
668 VAR m: Module; s: Selector; p: DswProcs.Process; ok: BOOLEAN; i, res: INTEGER;
669 BEGIN
670 IF Kernel.trapCount = 0 THEN
671 ParseArgs;
672 IF err = 0 THEN
673 CheckParams;
674 IF err = 0 THEN
675 CheckDeps;
676 IF err = 0 THEN
677 Compile;
678 IF err = 0 THEN
679 Link
680 END
681 END
682 END
683 END
684 ELSE INC(err)
685 END;
686 IF err = 0 THEN Kernel.Quit(0)
687 ELSE Kernel.Quit(1)
688 END;
689 END Main;
691 BEGIN
692 NEW(def);
693 Kernel.Start(Main)
694 END DswMakeMain.
696 ==============================
698 SYNTAX
699 cpmake {options module}
701 OPTIONS
702 -a Enable automatic dependency resolution
703 -o name Generate executable file
704 -j num Specifies the number of jobs to run simultaneously
705 -D ident["+"|"-"] Add preprocessor selector
706 -U ident Remove proprocessor selector