ref: fdafa085a245d4f48f84c6875a6b7cb89b8b5c6c
dir: /mbld/main.myr/
use std
use regex
use "build"
use "clean"
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 cleanfirst
	var dumponly
	var bintarg
	var targname
	var runsrc
	var tmp
	var cmd 
	var tags
	var ok, r
	cmd = std.optparse(args, &[
		.argdesc = "[inputs...]",
		.opts = [
			[.opt='c', .desc="clean before building"],
			[.opt='T', .desc="list all available targets"],
			[.opt='t', .arg="tag", .desc="build with specified systag"],
			[.opt='S', .desc="generate assembly when building"],
			[.opt='d', .desc="dump debugging information for mbld"],
			[.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 named 'bin' from inputs"],
			[.opt='G', .arg="bin", .desc="compile and run binary 'bin' from inputs"],
			[.opt='l', .arg="lib", .desc="compile lib named 'lib' from inputs"],
			[.opt='r', .arg="rt", .desc="link against runtime 'rt' instead of default"],
			[.opt='C', .arg="mc", .desc="compile with 'mc' instead of the default compiler"],
			[.opt='M', .arg="mu", .desc="merge uses with 'mu' instead of the default muse"],
		][:]
	])
	tags = [][:]
	runsrc = ""
	targname = ""
	dumponly = false
	cleanfirst = false
	ok = true
	bld.initopts()
	for opt in cmd.opts
		match opt
		| ('T', ""):	dumponly = true
		| ('S', ""):	bld.opt_genasm = true
		| ('c', ""):	cleanfirst = true
		| ('I', arg):	std.slpush(&bld.opt_incpaths, arg)
		| ('B', arg):	bld.opt_instbase = arg
		| ('t', tag):	std.slpush(&tags, tag)
		| ('R', arg):	runsrc = arg
		| ('b', arg):
			targname = arg
			bintarg = true
		| ('l', arg):
			targname = arg
			bintarg = false
		| ('r', arg):
			if std.sleq(arg, "none")
				bld.opt_runtime = ""
			else
				bld.opt_runtime = arg
			;;
		/*
		internal undocumented args; used by compiler suite for
		building with an uninstalled compiler.
		*/
		| ('d', arg): bld.opt_debug = true
		| ('C', arg): bld.opt_mc = arg
		| ('M', arg): bld.opt_muse = arg
		| _:	std.die("unreachable\n")
		;;
	;;
	b = mkbuild(tags)
	if targname.len != 0
		buildimm(b, targname, cmd.args, bintarg, cleanfirst)
	elif runsrc.len != 0
		tmp = std.mktemppath("runmyr")
		ok = buildimm(b, tmp, [runsrc][:], true, cleanfirst)
		if ok
			ok = runcmd(tmp, cmd.args)
		;;
		std.remove(tmp)
	elif dumponly
		findproj(b, "bld.proj")
		bld.load(b)
		for t in b.all
			std.put("{}\n", t)
		;;
	else
		findproj(b, "bld.proj")
		bld.load(b)
		/*bld.configure()*/
		/* default: buildall */
		if cleanfirst
			bld.cleanall(b)
		;;
		if cmd.args.len == 0
			bld.buildall(b)
		else
			for c in cmd.args
				match c
				| "all":	r = bld.buildall(b)
				| "gen":	r = bld.genall(b)
				| "clean":	r = bld.cleanall(b)
				| "install":	r = bld.install(b)
				| "uninstall":	r = bld.uninstall(b)
				| "test":	r = bld.test(b)
				| target:	r = bld.buildtarg(b, target)
				;;
				ok = ok && r
			;;
		;;
	;;
	if !ok
		std.exit(1)
	;;
}
const buildimm = {b, targ, inputs, bintarg, cleanfirst -> bool
	var mt : bld.myrtarg
	mt = [
		.name=targ,
		.inputs=inputs,
		.runtime=bld.opt_runtime,
		.incpath=bld.opt_incpaths,
		.libdeps=[][:]
	]
	if cleanfirst
		bld.cleanmyr(b, &mt)
	;;
	if bintarg
		-> bld.buildbin(b, &mt, true)
	else
		-> bld.buildlib(b, &mt)
	;;
}
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.targs = std.mkht(std.strhash, std.streq)
	b.gensrc = std.mkht(std.strhash, std.streq)
	b.built = std.mkht(std.strhash, std.streq)
	b.sysattrs = std.mkht(std.strhash, std.streq)
	bld.addsysattrs(b, tags)
	-> b
}
const findproj = {b, bldfile
	if !findbase(b, bldfile) || !std.chdir(b.basedir)
		std.fatal("could not find {}\n", bldfile)
	;;
	bld.setdir(b, "")
}
const findbase = {b, file
	var p, bld, dir
	dir = std.getcwd()
	while !std.sleq(dir, "/")
		bld = std.pathcat(dir, file)
		if std.fexists(bld)
			std.put("project base {}:\n", dir)
			b.basedir = dir
			b.bldfile = bld
			-> true
		;;
		p = std.pathcat(dir, "..")
		std.slfree(dir)
		dir = p
	;;
	-> false
}