ref: b612c54208eb92725f85f2521ba1a4be58fc7f44
parent: 66a103f6afd50eb45e9ba62f167688edeb10063a
author: Ori Bernstein <ori@eigenstate.org>
date: Sun Apr 12 20:42:30 EDT 2015
Mostly finish off the new single process world order. We no longer need to spawn subprocesses to do our building. We can handle library dependencies in the form of '../lib:foo', although we don't transitively link them in for binaries yet, or do loop detection.
--- a/build.myr
+++ b/build.myr
@@ -6,7 +6,6 @@
use "parse.use"
use "types.use"
use "util.use"
-use "subdir.use"
pkg bld =
const buildall : (b : build# -> bool)
@@ -17,16 +16,12 @@
;;
const buildall = {b
- var targs
-
- targs = std.htgetv(b.targs, "", [][:])
- for t in targs
- match t
+ for tn in b.all
+ match gettarg(b._targs, tn)
| `Bin bt: buildbin(b, bt, false)
| `Lib lt: buildlib(b, lt)
| `Test tt: /* build on 'mbld test' by default */
| `Gen gt: genfiles(b, gt)
- | `Sub subs: subdirs(b, subs, `std.None)
| `Man m: /* nothing needed */
;;
;;
@@ -34,11 +29,8 @@
}
const genall = {b
- var targs
-
- targs = std.htgetv(b.targs, "", [][:])
- for t in targs
- match t
+ for tn in b.all
+ match gettarg(b._targs, tn)
| `Gen gt: run(gt.cmd)
| _: /* skip */
;;
@@ -48,44 +40,15 @@
}
const build = {b, targ
- var found, targs
-
- found = false
- targs = std.htgetv(b.targs, "", [][:])
- for t in targs
- match t
- | `Bin bt:
- if std.sleq(bt.name, targ)
- buildbin(b, bt, false)
- ;;
- | `Lib lt:
- if std.sleq(lt.name, targ)
- buildlib(b, lt)
- found = true
- ;;
- | `Test tt:
- if std.sleq(tt.name, targ)
- buildbin(b, tt, false)
- found = true
- ;;
- | `Gen gt:
- for n in gt.out
- if std.sleq(n, targ)
- run(gt.cmd)
- ;;
- ;;
- | `Sub subs:
- found = true
- subdirs(b, subs, `std.Some targ)
- | `Man m:
- found = true
- /* nothing needed */
- ;;
+ match std.htget(b._targs, targ)
+ | `std.Some (`Bin bt): buildbin(b, bt, false)
+ | `std.Some (`Lib lt): buildlib(b, lt)
+ | `std.Some (`Test tt): buildbin(b, tt, false)
+ | `std.Some (`Gen gt): run(gt.cmd)
+ | `std.Some (`Man m): /* nothing needed */
+ | `std.None: std.fatal(1, "invalid target %s\n", targ)
;;
- if !found
- std.fatal(1, "%s: no such target\n", targ)
- ;;
- -> found
+ -> true
}
const buildbin = {b, targ, addsrc
@@ -94,13 +57,14 @@
if targ.built
->
;;
+ setdir(b, targ.dir)
if targ.libdeps.len > 0
- if !hasinc(targ.incpath, ".")
- targ.incpath = std.slpush(targ.incpath, ".")
+ for (inc, lib, subtarg) in targ.libdeps
+ if !hasinc(targ.incpath, inc)
+ targ.incpath = std.slpush(targ.incpath, inc)
+ ;;
+ build(b, subtarg)
;;
- for l in targ.libdeps
- build(b, l)
- ;;
;;
std.put("%s...\n", targ.name)
if !myrdeps(b, targ, false, false, addsrc, &dg)
@@ -135,6 +99,7 @@
if targ.built
->
;;
+ setdir(b, targ.dir)
lib = targ.name
std.put("lib%s.a...\n", lib)
archive = std.fmt("lib%s.a", lib)
@@ -266,7 +231,7 @@
/* -L path -l lib... */
cmd = addlibs(cmd, dg.libs, incs)
- for l in extralibs
+ for (d, l, t) in extralibs
cmd = std.slpush(cmd, std.fmt("-l%s", l))
;;
--- a/clean.myr
+++ b/clean.myr
@@ -6,6 +6,7 @@
use "parse.use"
use "subdir.use"
use "types.use"
+use "util.use"
pkg bld =
const cleanall : (b : build# -> bool)
@@ -13,11 +14,8 @@
;;
const cleanall = {b
- var targs
-
- targs = std.htgetv(b.targs, "", [][:])
- for t in targs
- match t
+ for tn in b.all
+ match gettarg(b._targs, tn)
| `Bin bt:
cleanup(b, bt, bt.inputs, true)
| `Lib lt:
@@ -30,8 +28,6 @@
std.put("\tclean %s\n", f)
;;
;;
- | `Sub subs:
- subdirs(b, subs, `std.None)
| `Man m:
;;
;;
@@ -39,11 +35,8 @@
}
const clean = {b, targ
- var targs
-
- targs = std.htgetv(b.targs, "", [][:])
- for t in targs
- match t
+ for tn in b.all
+ match gettarg(b._targs, tn)
| `Bin bt:
if std.sleq(bt.name, targ)
cleanup(b, bt, bt.inputs, true)
@@ -57,8 +50,11 @@
cleanup(b, tt, tt.inputs, true)
;;
| `Gen gt:
- | `Sub subs:
- subdirs(b, subs, `std.Some targ)
+ for f in gt.out
+ if !gt.durable && std.remove(f)
+ std.put("\tclean %s\n", f)
+ ;;
+ ;;
| `Man m:
;;
;;
@@ -65,7 +61,7 @@
-> true
}
-const cleanup = {p, targ, leaves, islib
+const cleanup = {b, targ, leaves, islib
var mchammer_files /* cant touch this */
var keys
var dg
@@ -74,7 +70,8 @@
we want to automatically add 'clean' sources since otherwise,
mbld won't be able to clean code after changing a build file.
*/
- if !myrdeps(p, targ, islib, true, true, &dg)
+ setdir(b, targ.dir)
+ if !myrdeps(b, targ, islib, true, true, &dg)
std.fatal(1, "Could not load dependencies for %s\n", targ.name)
;;
mchammer_files = std.mkht(std.strhash, std.streq)
--- a/install.myr
+++ b/install.myr
@@ -24,11 +24,10 @@
}
const movetargs = {b, delete
- var libarchive, targs
+ var libarchive
- targs = std.htgetv(b.targs, "", [][:])
- for t in targs
- match t
+ for tn in b.all
+ match gettarg(b._targs, tn)
| `Bin bt:
movefile(delete, bt.name, opt_instroot, opt_destdir, "bin", 0o755)
| `Lib lt:
@@ -38,8 +37,6 @@
std.slfree(libarchive)
| `Gen gt:
/* nothing to do (?) */
- | `Sub subs:
- subdirs(b, subs, `std.None)
| `Man mans:
/* FIXME: figure out man section by number */
for m in mans
--- a/main.myr
+++ b/main.myr
@@ -97,8 +97,10 @@
var b
b = std.zalloc()
- b.targs = std.mkht(std.strhash, std.streq)
+ b._targs = std.mkht(std.strhash, std.streq)
b.gensrc = std.mkht(std.strhash, std.streq)
+ b.basedir = std.getcwd()
+ std.put("base dir = %s\n", b.basedir)
-> b
}
--- a/parse.myr
+++ b/parse.myr
@@ -15,6 +15,7 @@
rest : byte[:]
fname : byte[:]
fdir : byte[:] /* directory relative to base */
+ basedir : byte[:]
line : int
/* extracted data for further parsing */
@@ -30,7 +31,7 @@
var p : parser#
var subpath, subbld, ok
- p = mkparser(path, dir)
+ p = mkparser(path, dir, b.basedir)
ok = bld.parse(b, p, "")
for s in p.subdirs
subpath = std.pathcat(p.fdir, s)
@@ -43,7 +44,7 @@
-> ok
}
-const mkparser = {path, dir
+const mkparser = {path, dir, basedir
var p
p = std.zalloc()
@@ -50,6 +51,7 @@
p.line = 1
p.fname = std.sldup(path)
p.fdir = std.sldup(dir)
+ p.basedir = std.sldup(basedir)
match std.slurp(path)
| `std.Ok d: p.data = d
| `std.Fail _: std.fatal(1, "could not open '%s'\n", path)
@@ -61,6 +63,7 @@
const freeparser = {p
std.slfree(p.fname)
std.slfree(p.fdir)
+ std.slfree(p.basedir)
std.slfree(p.subdirs)
std.slfree(p.data)
std.free(p)
@@ -108,29 +111,41 @@
/* bintarget: myrtarget */
const bintarget = {b, p
- addtarg(b, p.fdir, `Bin myrtarget(p, "bin"))
+ var t
+ t = myrtarget(p, "bin")
+ addtarg(p, b, t.name, `Bin t)
}
+/* libtarget: myrtarget */
+const libtarget = {b, p
+ var t
+ t = myrtarget(p, "lib")
+ addtarg(p, b, t.name, `Lib t)
+}
+
/* testtarget: myrtarget */
const testtarget = {b, p
- addtarg(b, p.fdir, `Test myrtarget(p, "test"))
+ var t
+ t = myrtarget(p, "test")
+ addtarg(p, b, t.name, `Test myrtarget(p, "test"))
}
-/* libtarget: myrtarget */
-const libtarget = {b, p
- addtarg(b, p.fdir, `Lib myrtarget(p, "lib"))
+/* mantarget: anontarget */
+const mantarget = {b, p
+ addtarg(p, b, "__man__", `Man anontarget(p, "man"))
}
/* subtarget : anontarget */
const subtarget = {b, p
- p.subdirs = std.sljoin(p.subdirs, anontarget(p, "sub"))
-}
+ var subs
-/* mantarget: anontarget */
-const mantarget = {b, p
- addtarg(b, p.fdir, `Man anontarget(p, "man"))
+ subs = anontarget(p, "sub")
+ for s in subs
+ p.subdirs = std.slpush(p.subdirs, std.pathcat(p.fdir, s))
+ ;;
}
+
/* gentarget: wordlist {attrs} = wordlist ;; */
const gentarget = {b, p
var outlist, cmdlist
@@ -178,6 +193,7 @@
;;
gt = std.mk([
+ .dir=std.sldup(p.fdir),
.out=outlist,
.durable=durable,
.cmd=cmdlist
@@ -184,8 +200,8 @@
])
for o in outlist
std.htput(b.gensrc, o, gt)
+ addtarg(p, b, o, `Gen gt)
;;
- addtarg(b, p.fdir, `Gen gt)
}
/*
@@ -251,6 +267,7 @@
;;
-> std.mk([
/* target */
+ .dir=std.sldup(p.fdir),
.name=name,
.inputs=inputs,
.libdeps=libdeps,
@@ -335,6 +352,7 @@
| "lib" word
*/
const inputlist = {p
+ var dir, lib, targ
var wl, libs
wl = [][:]
@@ -343,8 +361,12 @@
match word(p)
| `std.Some "lib":
match word(p)
- | `std.Some l: libs = std.slpush(libs, l)
- | `std.None: failparse(p, "expected lib name after 'lib'\n")
+ | `std.Some l:
+ (dir, lib, targ) = libpath(p, l)
+ std.put("dir: %s, lib: %s, targ: %s\n", dir, lib, targ)
+ libs = std.slpush(libs, (dir, lib, targ))
+ | `std.None:
+ failparse(p, "expected lib name after 'lib'\n")
;;
| `std.Some w: wl = std.slpush(wl, w)
| `std.None: break
@@ -476,10 +498,43 @@
-> c
}
-const addtarg = {b, d, t
- var tl
+const addtarg = {p, b, name, targ
+ var tn
- tl = std.htgetv(b.targs, d, [][:])
- tl = std.slpush(tl, t)
- std.htput(b.targs, d, tl)
+ tn = std.fmt("%s:%s", p.fdir, name)
+ if std.hthas(b._targs, tn)
+ failparse(p, "duplicate target %s\n", tn)
+ ;;
+ b.all = std.slpush(b.all, tn)
+ std.htput(b._targs, tn, targ)
+}
+
+const libpath = {p, libpath
+ var dir, lib_, targ
+
+ match(std.strrfind(libpath, ":"))
+ | `std.None:
+ dir = std.sldup(".")
+ lib_ = std.sldup(libpath)
+ targ = std.fmt("%s:%s", p.fdir, lib_)
+ | `std.Some idx:
+ if idx == libpath.len
+ std.fatal(1, "libdep %s missing library after ':'\n")
+ ;;
+ /* absolute path */
+ if std.hasprefix(libpath, "@/") || std.hasprefix(libpath, "@:")
+ dir = std.pathcat(p.basedir, libpath[2:idx])
+ lib_ = std.sldup(libpath[idx+1:])
+ targ = std.sldup(libpath[2:])
+ /* relative path */
+ else
+ dir = std.sldup(libpath[:idx])
+ lib_ = std.sldup(libpath[idx+1:])
+ targ = std.pathcat(p.fdir, libpath)
+ if std.hasprefix(targ, "../")
+ std.fatal(1, "library %s outside of project\n", libpath)
+ ;;
+ ;;
+ ;;
+ -> (dir, lib_, targ)
}
--- a/test.myr
+++ b/test.myr
@@ -16,15 +16,13 @@
;;
const test = {b
- var hasdir, ok, bin, targs
+ var ok/*, bin */
/* no implicit tests to run */
ok = true
- hasdir = std.fexists("test")
- targs = std.htgetv(b.targs, "", [][:])
- if hasdir
- for tt in targs
- match tt
+ if std.fexists("test")
+ for tn in b.all
+ match gettarg(b._targs, tn)
| `Bin bt:
if !dotest(b, bt, ok)
ok = false
@@ -37,6 +35,8 @@
;;
;;
;;
+ /*
+ FIXME: reenable test binaries
for `Test t in targs
for s in t.incpath
if std.sleq(".", s)
@@ -53,6 +53,7 @@
;;
std.slfree(bin)
;;
+ */
if ok
std.put("TESTS PASSED\n")
else
@@ -61,10 +62,11 @@
;;
}
-const dotest = {p, targ, ok
+const dotest = {b, targ, ok
var tt, bin ,path, tests
tests = [][:]
+ setdir(b, targ.dir)
for s in targ.inputs
path = std.pathcat("./test", s)
if std.fexists(path)
@@ -71,6 +73,7 @@
bin = srcswapsuffix(path, "")
tt = [
.name = bin,
+ .dir = targ.dir,
.inputs = [path, s][:],
.install = false,
.libdeps = targ.libdeps,
@@ -78,8 +81,8 @@
.built = false,
]
- cleantest(p, path)
- buildbin(p, &tt, true)
+ cleantest(b, path)
+ buildbin(b, &tt, true)
tests = std.slpush(tests, bin)
;;
std.slfree(path)
@@ -96,7 +99,7 @@
-> ok
}
-const cleantest = {p, src
+const cleantest = {b, src
var obj, bin, log, usef
obj = srcswapsuffix(src, config.Objsuffix)
--- a/types.myr
+++ b/types.myr
@@ -2,10 +2,14 @@
pkg bld =
type build = struct
- cmd : byte[:][:]
+ cmd : byte[:][:] /* command that we ran */
+ /* build state */
+ basedir : byte[:]
/* build params */
- targs : std.htab(byte[:], targ[:])# /* dir => target mapping */
- gensrc : std.htab(byte[:], gentarg#)#
+ all : byte[:][:]
+ _targs : std.htab(byte[:], targ)# /* dir => target mapping */
+ tdeps : std.htab(byte[:], byte[:][:]) /* targname => depname[:] mapping */
+ gensrc : std.htab(byte[:], gentarg#)# /* generated src => generating target mapping */
prefix : byte[:]
system : byte[:]
arch : byte[:]
@@ -24,9 +28,10 @@
;;
type myrtarg = struct
+ dir : byte[:]
name : byte[:]
inputs : byte[:][:]
- libdeps : byte[:][:]
+ libdeps : (byte[:], byte[:], byte[:])[:] /* dir, lib pairs */
built : bool
install : bool
runtime : byte[:]
@@ -35,9 +40,12 @@
;;
type gentarg = struct
+ dir : byte[:]
out : byte[:][:]
cmd : byte[:][:]
durable : bool
+ /* we can have multiple outputs, but we only want to run once for each */
+ done : bool
;;
type targ = union
@@ -45,7 +53,6 @@
`Lib myrtarg#
`Test myrtarg#
`Gen gentarg#
- `Sub byte[:][:]
`Man byte[:][:]
;;
;;
--- a/util.myr
+++ b/util.myr
@@ -1,6 +1,7 @@
use std
use "opts.use"
+use "types.use"
pkg bld =
const run : (cmd : byte[:][:] -> void)
@@ -9,6 +10,8 @@
const swapsuffix : (f : byte[:], suff : byte[:], newsuff : byte[:] -> byte[:])
const srcswapsuffix : (f : byte[:], newsuff : byte[:] -> byte[:])
const strlistfree : (sl : byte[:][:] -> void)
+ const gettarg : (tab : std.htab(byte[:], targ)#, n : byte[:] -> targ)
+ const setdir : (b : build#, dir : byte[:] -> void)
;;
const run = {cmd
@@ -91,5 +94,23 @@
std.slfree(s)
;;
std.slfree(sl)
+}
+
+const gettarg = {tab, n
+ match std.htget(tab, n)
+ | `std.None: std.fatal(1, "internal: nonexistent %s\n", n)
+ | `std.Some t: -> t
+ ;;
+}
+
+const setdir = {b, dir
+ var p
+
+ p = std.pathcat(b.basedir, dir)
+ std.put("changing into '%s'\n", p)
+ if !std.chdir(p)
+ std.fatal(1, "could not cd into %s\n")
+ ;;
+ std.slfree(p)
}