shithub: mc

ref: dfc145534768f3b461d92c929931bb3b48237bdb
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, runsrc, objdir, path, cmd, srcs
	var targname, tags, pid, ok

	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="src", .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 = false
	targname = ""
	ok = true
	objdir = ""
	srcs = cmd.args

	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)
		| ('o', arg):	objdir = arg
		| ('r', arg):	bld.opt_runtime = arg
		| ('v', _):	bld.opt_verbosity++
		| ('b', arg):
			if targname.len != 0
				std.fatal("at most one -b and -R may be specified\n")
			;;
			targname = arg
		| ('R', src):
			if targname.len != 0
				std.fatal("at most one -b and -R may be specified\n")
			;;
			bld.opt_verbosity = -1
			runsrc = true
			targname = std.mktemppath("runmyr")
			srcs = [src][:]
		| _:	
			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
		if srcs.len == 0
			std.fatal("nothing to compile\n")
		;;

		bld.opt_objdir = objdir
		ok = buildimm(b, targname, srcs)
		if runsrc && ok
			pid = runcmd(targname, cmd.args)
			match std.wait(pid)
			| `std.Wsuccess:	ok = true
			| _:			ok = false
			;;
			std.remove(targname)
		;;
	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":	ok = bld.clean(b)
			| "install":	ok = bld.install(b)
			| "uninstall":	ok = bld.uninstall(b)
			| "test":	ok = bld.test(b, cmd.args[1:])
			| "bench":	ok = bld.bench(b, cmd.args[1:])
			| "list":	ok = show(b, cmd.args[1:])
			| _:
				for target : cmd.args
					ok = ok && bld.buildtarg(b, target)
				;;
			;;
		;;
	;;
	std.exit(ok ? 0 : 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
}