shithub: mc

ref: 9b864a2bc7fbdae40704708a6893e6f29ad48397
dir: /mbld/main.myr/

View raw version
use std
use regex
use thread

use "build"
use "config"
use "deps"
use "install"
use "opts"
use "parse"
use "test"
use "types"
use "util"
use "syssel"

const main = {args : byte[:][:]
	var b : bld.build#
	var runsrc, objdir, path, tmp, cmd
	var targname, tags, pid
	var ok, r

	cmd = std.optparse(args, &[
		.argdesc = "[inputs...]",
		.opts = [
			[.opt='j', .arg="jobs", .desc="build with at most 'jobs' jobs"],
			[.opt='t', .arg="tag", .desc="build with specified systag"],
			[.opt='T', .arg="tag", .desc="build with only the specified systag"],
			[.opt='S', .desc="generate assembly when building"],
			[.opt='I', .arg="inc", .desc="add 'inc' to your include path"],
			[.opt='R', .arg="runsrc", .desc="source to compile and run"],
			[.opt='B', .arg="base", .desc="install into 'base'"],
			[.opt='b', .arg="bin", .desc="compile binary 'bin' from inputs"],
			[.opt='r', .arg="rt", .desc="link against runtime 'rt'"],
			[.opt='o', .arg="dir", .desc="output directory"],
			[.opt='v', .desc="increase build verbosity"],
		][:]
	])

	tags = [][:]
	runsrc = ""
	targname = ""
	ok = true

	bld.initopts()
	for opt : cmd.opts
		match opt
		| ('S', ""):	bld.opt_genasm = true
		| ('I', arg):	std.slpush(&bld.opt_incpaths, arg)
		| ('B', arg):	bld.opt_instbase = arg
		| ('t', tag):	std.slpush(&tags, tag)
		| ('T', tag):	std.slpush(&bld.opt_alltags, tag)
		| ('j', arg):	bld.opt_maxproc = std.getv(std.intparse(arg), 1)
		| ('R', arg):	runsrc = arg
		| ('o', arg):	objdir = arg
		| ('b', arg):	targname = arg
		| ('r', arg):	bld.opt_runtime = arg
		| ('v', _):	bld.opt_verbosity++
		| _:		std.die("unreachable\n")
		;;
	;;
	path = std.pathcat(bld.opt_instbase, config.Libpath)
	std.slpush(&bld.opt_incpaths, path)

	for (e, v) : config.Env
		std.setenv(e, v)
	;;

	b = mkbuild(tags)
	if targname.len != 0
		bld.opt_objdir = objdir
		ok = buildimm(b, targname, cmd.args)
	elif runsrc.len != 0
		bld.opt_objdir = objdir
		bld.opt_verbosity = -1
		tmp = std.mktemppath("runmyr")
		ok = buildimm(b, tmp, [runsrc][:])
		if ok
			pid = runcmd(tmp, cmd.args)
			match std.wait(pid)
			| `std.Wsuccess:	ok = true
			| _:			ok = false
			;;
		;;
		std.remove(tmp)
	else
		if objdir.len > 0
			bld.opt_objdir = objdir
		;;
		findproj(b)
		bld.load(b)
		bld.deps(b)
		bld.testdeps(b)
		bld.resolve(b)
		/* default: buildall */
		if cmd.args.len == 0
			ok = bld.buildtarg(b, "all")
		else
			match cmd.args[0]
			| "clean":	r = bld.clean(b)
			| "install":	r = bld.install(b)
			| "uninstall":	r = bld.uninstall(b)
			| "test":	r = bld.test(b, cmd.args[1:])
			| "bench":	r = bld.bench(b, cmd.args[1:])
			| "list":	r = show(b, cmd.args[1:])
			| _:
				ok = true
				for target : cmd.args
					r = ok && bld.buildtarg(b, target)
				;;
			;;
		;;
	;;
	if !ok
		std.exit(1)
	;;
}

const buildimm = {b, targ, inputs
	var mt : bld.myrtarg

	mt = [
		.name=targ,
		.inputs=inputs,
		.runtime=bld.opt_runtime,
		.incpath=bld.opt_incpaths,
		.libdeps=[][:]
	]
	std.slpush(&b.all, "__out__")
	std.htput(b.targs, "__out__", `bld.Bin &mt)
	bld.deps(b)
	bld.resolve(b)
	-> bld.buildtarg(b, "all")
}

const runcmd = {bin, args
	var sl

	sl = std.sldup([bin][:])
	-> bld.run(std.sljoin(&sl, args), "")
}

const mkbuild = {tags
	var b

	b = std.zalloc()
	b.libs = std.mkht()
	b.proc = std.mkht()
	b.targs = std.mkht()
	b.tags = std.mkht()
	b.deps = std.mk([
		.targs = std.mkht(),
		.gen = std.mkht(),
		.leaves = [][:],
		.nodes = [][:],
	])
	b.tctime = tctime()
	bld.addsysattrs(b, tags)
	-> b
}

const tctime = {
	var path : byte[1024]
	var tm

	tm = 0
	for bin : [bld.opt_muse, bld.opt_mc][:]
		match which(path[:], bin)
		| `std.None:
		| `std.Some p:
			match std.fmtime(p)
			| `std.Ok t:	tm = std.max(tm, t)
			| `std.Err e:	tm = std.now()
			;;
		;;
	;;
	-> tm
}

const which = {buf, name
	var path, f

	path = std.getenvv("PATH", "/bin")
	for p : std.bysplit(path, ":")
		f = std.bfmt(buf, "{}/{}", p, name)
		if std.fexists(f)
			-> `std.Some f
		;;
	;;
	-> `std.None
}


const findproj = {b
	var dir

	dir = std.getcwd()
	while dir.len > 0 && !std.eq(dir, "/")
		if std.chdir(dir) && std.fexists("bld.proj")
			b.basedir = dir
			b.rootdir = dir
			break
		;;
		dir = std.dirname(dir)
	;;
	if dir.len > 0 && std.eq(b.basedir, "/")
		std.fatal("could not find bld.proj\n")
	;;
}

const show = {b, targs
	var k
	
	k = std.htkeys(b.targs)
	std.put("{j=\n}\n", k)
	std.slfree(k)
	-> true
}