ref: 330b77e1df403fdfcbc6b49534571a76b1b525b5
dir: /build.myr/
use std
use "config.use"
use "deps.use"
use "opts.use"
use "parse.use"
use "types.use"
use "util.use"
use "subdir.use"
pkg bld =
const buildall : (p : parser# -> bool)
const test : (p : parser# -> bool)
const build : (p : parser#, target : byte[:] -> bool)
const buildbin : (bin : byte[:], inputs : byte[:][:], ldscript : byte[:], rt : byte[:] -> void)
const buildlib : (lib : byte[:], inputs : byte[:][:] -> void)
;;
const buildall = {p
for t in p.targs
match t
| `Bin [.name=bin, .inputs=leaves, .ldscript=lds, .runtime=rt]:
buildbin(bin, leaves, lds, rt)
| `Lib [.name=lib, .inputs=leaves]:
buildlib(lib, leaves)
| `Sub subs:
subdirs(p, subs, `std.None)
| `Man m:
/* nothing needed */
;;
;;
-> true
}
const test = {p
std.fatal(1, "testing not yet supported\n")
-> false
}
const build = {p, targ
var built
built = false
for t in p.targs
match t
| `Bin [.name=bin, .inputs=leaves, .ldscript=lds, .runtime=rt]:
if std.sleq(bin, targ)
buildbin(bin, leaves, lds, rt)
built = true
;;
| `Lib [.name=lib, .inputs=leaves]:
if std.sleq(lib, targ)
buildlib(lib, leaves)
built = true
;;
| `Sub subs:
subdirs(p, subs, `std.Some targ)
| `Man m:
/* nothing needed */
;;
;;
if !built
std.fatal(1, "%s: no such target\n", targ)
;;
-> built
}
const buildbin = {bin, inputs, ldscript, rt
var dg
var built
if !myrdeps(&dg, bin, inputs, false)
std.fatal(1, "Could not load dependencies for %s\n", bin)
;;
match std.htget(dg.deps, bin)
| `std.Some deps:
built = false
for d in deps
if builddep(&dg, d, bin)
built = true
;;
;;
if built
linkbin(&dg, bin, inputs, ldscript, rt)
;;
| `std.None:
std.fatal(1, "No such binary %s\n", bin)
;;
}
const buildlib = {lib, inputs
var dg
var built
if !myrdeps(&dg, lib, inputs, true)
std.fatal(1, "Could not load dependencies for %s\n", lib)
;;
match std.htget(dg.deps, lib)
| `std.Some deps:
built = false
for d in deps
if builddep(&dg, d, lib)
built = true
;;
;;
if built
archivelib(&dg, lib, inputs)
;;
| `std.None:
std.fatal(1, "No such library %s\n", lib)
;;
}
const builddep = {dg, dep, out
var freshdep
freshdep = true
match std.htget(dg.deps, dep)
| `std.Some deps:
for d in deps
builddep(dg, d, dep)
if !isfresh(d, out)
freshdep = false
;;
;;
| `std.None:
;;
if freshdep && isfresh(dep, out)
-> false
;;
if std.hassuffix(dep, ".myr")
run(["6m", dep][:], "")
;;
-> true
}
const linkbin = {dg, bin, srcfiles, ldscript, rt
var cmd
var obj
cmd = [][:]
/* ld -o bin */
cmd = std.slpush(cmd, std.sldup("ld"))
cmd = std.slpush(cmd, std.sldup("-o"))
cmd = std.slpush(cmd, std.sldup(bin))
/* [-T script] */
if ldscript.len > 0
cmd = std.slpush(cmd, std.sldup("-T"))
cmd = std.slpush(cmd, std.sldup(ldscript))
;;
if rt.len != 0
cmd = std.slpush(cmd, std.sldup(rt))
else
cmd = std.slpush(cmd, std.sldup(opt_runtime))
;;
/* input.o list.o... */
for f in srcfiles
if std.hassuffix(f, ".myr")
obj = swapsuffix(f, ".myr", ".o")
elif std.hassuffix(f, ".s")
obj = swapsuffix(f, ".s", ".o")
else
std.fatal(1, "unknown file type for %s\n", f)
;;
cmd = std.slpush(cmd, obj)
;;
/* -l lib... */
cmd = addlibs(cmd, dg.libs)
/* -L incpath... */
for inc in opt_incpaths
cmd = std.slpush(cmd, std.fmt("-L%s", inc))
;;
cmd = std.slpush(cmd, std.fmt("-L%s%s", opt_instroot, "/lib/myr"))
/* special for OSX: it warns if we don't add this */
if std.sleq(opt_sys, "osx")
cmd = std.slpush(cmd, std.sldup("-macosx_version_min"))
cmd = std.slpush(cmd, std.sldup("10.6"))
;;
run(cmd, "")
strlistfree(cmd)
}
const archivelib = {dg, lib, files
var cmd
var obj
cmd = [][:]
cmd = std.slpush(cmd, std.sldup("ar"))
cmd = std.slpush(cmd, std.sldup("-rcs"))
cmd = std.slpush(cmd, std.fmt("lib%s.a", lib))
for f in files
if std.hassuffix(f, ".myr")
obj = swapsuffix(f, ".myr", ".o")
elif std.hassuffix(f, ".s")
obj = swapsuffix(f, ".s", ".o")
else
std.fatal(1, "unknown file type for %s\n", f)
;;
cmd = std.slpush(cmd, obj)
;;
run(cmd, "")
strlistfree(cmd)
}
const addlibs = {cmd, libgraph
var looped : std.htab(byte[:], bool)#
var marked : std.htab(byte[:], bool)#
var libs
var head
libs = std.htkeys(libgraph)
looped = std.mkht(std.strhash, std.streq)
marked = std.mkht(std.strhash, std.streq)
head = cmd.len
for lib in libs
cmd = visit(cmd, head, libgraph, lib, looped, marked)
;;
-> cmd
}
const visit = {cmd, head, g, lib, looped, marked -> byte[:][:]
if std.hthas(looped, lib)
std.fatal(1, "cycle in library graph involving \"%s\"\n", lib)
elif std.hthas(marked, lib)
-> cmd
;;
std.htput(looped, lib, true)
for dep in std.htgetv(g, lib, [][:])
cmd = visit(cmd, head, g, dep, looped, marked)
;;
std.htdel(looped, lib)
std.htput(marked, lib, true)
-> std.slput(cmd, head, std.fmt("-l%s", lib))
}
const isfresh = {src, dst
var srcsb, dstsb
if std.stat(src, &srcsb) != 0
std.fatal(1, "could not stat %s\n", src)
;;
if std.stat(dst, &dstsb) != 0
-> false
;;
if srcsb.mtime.sec != dstsb.mtime.sec
-> srcsb.mtime.sec < dstsb.mtime.sec
else
-> srcsb.mtime.nsec < dstsb.mtime.nsec
;;
}