summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2015-04-13 00:42:30 -0700
committerOri Bernstein <ori@eigenstate.org>2015-04-13 00:42:30 -0700
commitb612c54208eb92725f85f2521ba1a4be58fc7f44 (patch)
tree0107169ac9c14074df3a68f7aadd92ac257786a7
parent66a103f6afd50eb45e9ba62f167688edeb10063a (diff)
downloadmbld-b612c54208eb92725f85f2521ba1a4be58fc7f44.tar.gz
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.
-rw-r--r--build.myr75
-rw-r--r--clean.myr29
-rw-r--r--install.myr9
-rw-r--r--main.myr4
-rw-r--r--parse.myr95
-rw-r--r--test.myr23
-rw-r--r--types.myr17
-rw-r--r--util.myr21
8 files changed, 160 insertions, 113 deletions
diff --git a/build.myr b/build.myr
index afc191b..2fa7725 100644
--- a/build.myr
+++ b/build.myr
@@ -6,7 +6,6 @@ use "opts.use"
use "parse.use"
use "types.use"
use "util.use"
-use "subdir.use"
pkg bld =
const buildall : (b : build# -> bool)
@@ -17,16 +16,12 @@ pkg bld =
;;
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 buildall = {b
}
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 genall = {b
}
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 */
- ;;
- ;;
- if !found
- std.fatal(1, "%s: no such target\n", targ)
+ 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)
;;
- -> found
+ -> true
}
const buildbin = {b, targ, addsrc
@@ -94,12 +57,13 @@ const buildbin = {b, targ, addsrc
if targ.built
->
;;
+ setdir(b, targ.dir)
if targ.libdeps.len > 0
- if !hasinc(targ.incpath, ".")
- targ.incpath = std.slpush(targ.incpath, ".")
- ;;
- for l in targ.libdeps
- build(b, l)
+ for (inc, lib, subtarg) in targ.libdeps
+ if !hasinc(targ.incpath, inc)
+ targ.incpath = std.slpush(targ.incpath, inc)
+ ;;
+ build(b, subtarg)
;;
;;
std.put("%s...\n", targ.name)
@@ -135,6 +99,7 @@ const buildlib = {b, targ
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 @@ const linkbin = {dg, bin, srcfiles, ldscript, rt, incs, extralibs
/* -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))
;;
diff --git a/clean.myr b/clean.myr
index c6e0025..5f37602 100644
--- a/clean.myr
+++ b/clean.myr
@@ -6,6 +6,7 @@ use "opts.use"
use "parse.use"
use "subdir.use"
use "types.use"
+use "util.use"
pkg bld =
const cleanall : (b : build# -> bool)
@@ -13,11 +14,8 @@ pkg bld =
;;
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 @@ const cleanall = {b
std.put("\tclean %s\n", f)
;;
;;
- | `Sub subs:
- subdirs(b, subs, `std.None)
| `Man m:
;;
;;
@@ -39,11 +35,8 @@ const cleanall = {b
}
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,15 +50,18 @@ const clean = {b, targ
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:
;;
;;
-> 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 @@ const cleanup = {p, targ, leaves, islib
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)
diff --git a/install.myr b/install.myr
index 9e919c7..e91011c 100644
--- a/install.myr
+++ b/install.myr
@@ -24,11 +24,10 @@ const uninstall = {b
}
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 @@ const movetargs = {b, delete
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
diff --git a/main.myr b/main.myr
index 03ffb78..cf2f9bb 100644
--- a/main.myr
+++ b/main.myr
@@ -97,8 +97,10 @@ const mkbuild = {
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
}
diff --git a/parse.myr b/parse.myr
index 3722785..3627533 100644
--- a/parse.myr
+++ b/parse.myr
@@ -15,6 +15,7 @@ type parser = struct
rest : byte[:]
fname : byte[:]
fdir : byte[:] /* directory relative to base */
+ basedir : byte[:]
line : int
/* extracted data for further parsing */
@@ -30,7 +31,7 @@ const loadall = {b, path, dir
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,13 +44,14 @@ const loadall = {b, path, dir
-> ok
}
-const mkparser = {path, dir
+const mkparser = {path, dir, basedir
var p
p = std.zalloc()
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 mkparser = {path, dir
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 @@ const target = {b, p
/* 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,14 +193,15 @@ const gentarget = {b, p
;;
gt = std.mk([
+ .dir=std.sldup(p.fdir),
.out=outlist,
.durable=durable,
.cmd=cmdlist
])
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 @@ const myrtarget = {p, targ
;;
-> std.mk([
/* target */
+ .dir=std.sldup(p.fdir),
.name=name,
.inputs=inputs,
.libdeps=libdeps,
@@ -335,6 +352,7 @@ input : word
| "lib" word
*/
const inputlist = {p
+ var dir, lib, targ
var wl, libs
wl = [][:]
@@ -343,8 +361,12 @@ const inputlist = {p
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 @@ const getc = {p
-> c
}
-const addtarg = {b, d, t
- var tl
+const addtarg = {p, b, name, targ
+ var tn
+
+ 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)
+}
- tl = std.htgetv(b.targs, d, [][:])
- tl = std.slpush(tl, t)
- std.htput(b.targs, d, tl)
+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)
}
diff --git a/test.myr b/test.myr
index 6f41885..e13f261 100644
--- a/test.myr
+++ b/test.myr
@@ -16,15 +16,13 @@ pkg bld =
;;
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 @@ const test = {b
;;
;;
;;
+ /*
+ FIXME: reenable test binaries
for `Test t in targs
for s in t.incpath
if std.sleq(".", s)
@@ -53,6 +53,7 @@ const test = {b
;;
std.slfree(bin)
;;
+ */
if ok
std.put("TESTS PASSED\n")
else
@@ -61,16 +62,18 @@ const test = {b
;;
}
-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)
bin = srcswapsuffix(path, "")
tt = [
.name = bin,
+ .dir = targ.dir,
.inputs = [path, s][:],
.install = false,
.libdeps = targ.libdeps,
@@ -78,8 +81,8 @@ const dotest = {p, targ, ok
.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 @@ const dotest = {p, targ, ok
-> ok
}
-const cleantest = {p, src
+const cleantest = {b, src
var obj, bin, log, usef
obj = srcswapsuffix(src, config.Objsuffix)
diff --git a/types.myr b/types.myr
index b64593e..d9aa019 100644
--- a/types.myr
+++ b/types.myr
@@ -2,10 +2,14 @@ use std
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 @@ pkg bld =
;;
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 @@ pkg bld =
;;
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 @@ pkg bld =
`Lib myrtarg#
`Test myrtarg#
`Gen gentarg#
- `Sub byte[:][:]
`Man byte[:][:]
;;
;;
diff --git a/util.myr b/util.myr
index c426576..463c2c9 100644
--- 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 @@ pkg bld =
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
@@ -93,3 +96,21 @@ const strlistfree = {sl
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)
+}
+