ref: f15de4539efb079f7c27ceb1daf4858a347ac832
dir: /build.myr/
use std
use "config.use"
use "deps.use"
use "opts.use"
use "parse.use"
use "util.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[:] -> void)
const buildlib : (lib : byte[:], inputs : byte[:][:] -> void)
;;
const buildall = {p
for t in p.targs
match t
| `Bin [.name=bin, .inputs=leaves, .ldscript=ldscript]:
buildbin(bin, leaves, ldscript)
| `Lib [.name=lib, .inputs=leaves]:
buildlib(lib, leaves)
| `Sub subs:
for s in subs
dosub(s)
;;
| `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=ldscript]:
if std.sleq(bin, targ)
buildbin(bin, leaves, ldscript)
built = true
;;
| `Lib [.name=lib, .inputs=leaves]:
if std.sleq(lib, targ)
buildlib(lib, leaves)
built = true
;;
| `Sub subs:
for s in subs
if std.sleq(s, targ)
dosub(s)
built = true
;;
;;
| `Man m:
/* nothing needed */
;;
;;
if !built
std.fatal(1, "%s: no such target\n", targ)
;;
-> built
}
const buildbin = {bin, inputs, ldscript
var dg
std.put("LD SCRIPT: %s\n", ldscript)
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:
for d in deps
builddep(&dg, d, bin)
;;
linkbin(&dg, bin, inputs, ldscript)
| `std.None:
std.fatal(1, "No such binary %s\n", bin)
;;
}
const buildlib = {lib, inputs
var dg
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:
for d in deps
builddep(&dg, d, lib)
;;
archivelib(&dg, lib, inputs)
| `std.None:
std.fatal(1, "No such library %s\n", lib)
;;
}
const dosub = {sub
std.put("subdir %s\n", sub)
}
const builddep = {dg, dep, out
match std.htget(dg.deps, dep)
| `std.Some deps:
for d in deps
builddep(dg, d, dep)
;;
| `std.None:
;;
if isfresh(dep, out)
->
;;
if std.hassuffix(dep, ".myr")
run(["6m", dep][:])
;;
}
const linkbin = {dg, bin, srcfiles, ldscript
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] */
std.put("ldscript = %s\n")
if ldscript.len > 0
cmd = std.slpush(cmd, std.sldup("-T"))
cmd = std.slpush(cmd, std.sldup(ldscript))
;;
cmd = std.slpush(cmd, std.fmt("%s/%s", opt_instroot, "/lib/myr/_myrrt.o"))
/* 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_sysname, "Darwin")
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
;;
}