|
|
@@ -15,6 +15,8 @@ MODULE M2make;
|
|
|
IMPORT FileIO, M2makeOS;
|
|
|
|
|
|
CONST
|
|
|
+ AbiVersion = "v3-separate-abi-1";
|
|
|
+ AbiStampPath = "gen_ssa/.m2abi";
|
|
|
MaxMods = 256;
|
|
|
MaxDeps = 64;
|
|
|
MaxDirs = 16;
|
|
|
@@ -866,24 +868,67 @@ BEGIN
|
|
|
RETURN FALSE
|
|
|
END SepObjStale;
|
|
|
|
|
|
+PROCEDURE AbiStampOK (): BOOLEAN;
|
|
|
+(* Content check for the object ABI/flags stamp. This is deliberately
|
|
|
+ a small build-system marker, not a per-object binary format. *)
|
|
|
+VAR h: M2makeOS.RdFile; line: Line; want: Path; ok: BOOLEAN;
|
|
|
+BEGIN
|
|
|
+ h := M2makeOS.OpenRead(AbiStampPath);
|
|
|
+ IF h = NIL THEN RETURN FALSE END;
|
|
|
+ ok := M2makeOS.ReadLine(h, line, HIGH(line) + 1);
|
|
|
+ M2makeOS.CloseRead(h);
|
|
|
+ IF NOT ok THEN RETURN FALSE END;
|
|
|
+ Copy(AbiVersion, want);
|
|
|
+ IF Len(m2Flags) > 0 THEN
|
|
|
+ Cat(want, " ", tmpA);
|
|
|
+ Cat(tmpA, m2Flags, want)
|
|
|
+ END;
|
|
|
+ RETURN Cmp(line, want) = 0
|
|
|
+END AbiStampOK;
|
|
|
+
|
|
|
+PROCEDURE WriteAbiStamp;
|
|
|
+VAR cmd: Cmd;
|
|
|
+BEGIN
|
|
|
+ Zero(cmd);
|
|
|
+ AppendSeg(cmd, "mkdir -p gen_ssa && printf '%s\n' '");
|
|
|
+ AppendSeg(cmd, AbiVersion);
|
|
|
+ IF Len(m2Flags) > 0 THEN
|
|
|
+ AppendSeg(cmd, " ");
|
|
|
+ AppendSeg(cmd, m2Flags)
|
|
|
+ END;
|
|
|
+ AppendSeg(cmd, "' > ");
|
|
|
+ AppendSeg(cmd, AbiStampPath);
|
|
|
+ IF M2makeOS.ExecCmd(cmd) # 0 THEN
|
|
|
+ Out("M2make: could not write ABI stamp"); OutLn;
|
|
|
+ M2makeOS.ExitNow(1)
|
|
|
+ END
|
|
|
+END WriteAbiStamp;
|
|
|
+
|
|
|
PROCEDURE BuildM2Separate(out: ARRAY OF CHAR);
|
|
|
(* Compile stale modules to their own QBE objects, then link. The
|
|
|
program module is last in the topological order and is the only
|
|
|
object with main; every module object exports <mod>_init. *)
|
|
|
VAR cmd: Cmd; k, m: CARDINAL; rc: INTEGER;
|
|
|
obj, src, ssafile, sfile, flags: Path;
|
|
|
- outT: LONGINT; compiledAny, linkNeeded: BOOLEAN;
|
|
|
+ outT: LONGINT; compiledAny, linkNeeded, abiOK: BOOLEAN;
|
|
|
BEGIN
|
|
|
Zero(cmd);
|
|
|
+ abiOK := AbiStampOK();
|
|
|
compiledAny := FALSE;
|
|
|
k := 0;
|
|
|
WHILE k < nOrder DO
|
|
|
m := order[k];
|
|
|
GetSrc(m, src);
|
|
|
- IF Len(src) > 0 THEN
|
|
|
+ GetDef(m, tmpQ);
|
|
|
+ IF (Len(src) > 0) OR ((NOT modIsMain[m]) AND (Len(tmpQ) > 0)) THEN
|
|
|
+ IF Len(src) = 0 THEN
|
|
|
+ (* A definition-only module still contributes exported data and
|
|
|
+ class vtables to the link. *)
|
|
|
+ Copy(tmpQ, src)
|
|
|
+ END;
|
|
|
IF modIsMain[m] THEN Copy(progName, tmpN) ELSE GetName(m, tmpN) END;
|
|
|
Zero(obj); Cat("gen_ssa/", tmpN, tmpA); Cat(tmpA, ".o", obj);
|
|
|
- IF SepObjStale(m, obj) THEN
|
|
|
+ IF (NOT abiOK) OR SepObjStale(m, obj) THEN
|
|
|
CpyPath(ssafile, "gen_ssa/"); Cat(ssafile, tmpN, tmpA); Cat(tmpA, ".ssa", ssafile);
|
|
|
CpyPath(sfile, "gen_ssa/"); Cat(sfile, tmpN, tmpA); Cat(tmpA, ".s", sfile);
|
|
|
Zero(tmpCmd);
|
|
|
@@ -959,7 +1004,8 @@ BEGIN
|
|
|
WHILE k < nOrder DO
|
|
|
m := order[k];
|
|
|
GetSrc(m, src);
|
|
|
- IF Len(src) > 0 THEN
|
|
|
+ GetDef(m, tmpQ);
|
|
|
+ IF (Len(src) > 0) OR ((NOT modIsMain[m]) AND (Len(tmpQ) > 0)) THEN
|
|
|
IF modIsMain[m] THEN Copy(progName, tmpN) ELSE GetName(m, tmpN) END;
|
|
|
Zero(obj); Cat("gen_ssa/", tmpN, tmpA); Cat(tmpA, ".o", obj);
|
|
|
AppendTok(tmpCmd, obj)
|
|
|
@@ -980,7 +1026,8 @@ BEGIN
|
|
|
Out("M2make: separate build failed");
|
|
|
OutLn;
|
|
|
M2makeOS.ExitNow(1)
|
|
|
- END
|
|
|
+ END;
|
|
|
+ WriteAbiStamp
|
|
|
END BuildM2Separate;
|
|
|
|
|
|
PROCEDURE CpyPath(VAR dst: Path; src: ARRAY OF CHAR);
|
|
|
@@ -1288,7 +1335,12 @@ BEGIN
|
|
|
IF NOT outGiven THEN Copy(progName, outName) END;
|
|
|
TopoSort;
|
|
|
IF verbose OR dryRun THEN PrintOrder END;
|
|
|
- rebuild := NeedBuild(outName, missing);
|
|
|
+ IF separate THEN
|
|
|
+ (* BuildM2Separate owns per-object freshness and the ABI stamp. *)
|
|
|
+ rebuild := TRUE
|
|
|
+ ELSE
|
|
|
+ rebuild := NeedBuild(outName, missing)
|
|
|
+ END;
|
|
|
IF NOT rebuild THEN
|
|
|
Out("M2make: ");
|
|
|
Out(outName);
|