shithub: mc

ref: ff88594df5c5df6fb8f227ab8e5df3529ba6e72f
dir: /mbld/libs.myr/

View raw version
use std
use bio

use "config"
use "opts"
use "types"

pkg bld =
	const addlibs	: (b : build#, \
		sl : byte[:][:]#, \
		libs : byte[:][:], \
		incs : byte[:][:] -> bool)

	const builtlib	: (b : build#, \
		lt : myrtarg#, \
		dep : byte[:][:], \
		dyndep : byte[:][:] -> void)

	const scrapelib : (b : build#, \
		targ : byte[:], \
		libs : byte[:], \
		incs : byte[:][:] -> void)
;;

/* Keep in sync with parse/parse.h */
const Abiversion = 23

const builtlib = {b, mt, dep, dyndep
	var ldep, l, u

	l = std.fmt("lib{}.a", mt.name)
	u = std.fmt("lib{}.use", mt.name)
	ldep = std.mk([
		.name=mt.name,
		.dir=std.pathcat(opt_objdir, mt.dir),
		.dep=dep,
		.dyndep=dyndep,
		.genuse=std.pathjoin([opt_objdir, mt.dir, u][:]),
		.genar=std.pathjoin([opt_objdir, mt.dir, l][:]),
	])
	std.slfree(l)
	std.slfree(u)
	for d : dep
		scrapelib(b, mt.name, d, mt.incpath)
	;;
	std.htput(b.libs, mt.name, ldep)
}

const scrapelib = {b, targ, lib, incs
	var path, dep, dyndep, ldep
	var f, dir

	if std.hthas(b.libs, lib)
		-> void
	;;

	(f, path, dir) = openlib(lib, targ, incs)
	match bio.getc(f)
	| `std.Ok 'U':	/* ok */
	| `std.Ok _:	std.fput(1, "{}/{}: not a usefile\n", dir, lib)
	| `std.Err e:	std.fatal("{}/{}: error reading: {}\n", dir, lib, e)
	;;
	match bio.getbe32(f)
	| `std.Ok Abiversion:	/* nothing: version matches. */
	| `std.Ok v:	std.fput(1, "{}/{}: mismatched abi {}\n", dir, lib, v)
	| `std.Err e:	std.fatal("{}/{}: error reading: {}\n", dir, lib, e)
	;;
	std.slfree(rdstr(f))

	dep = [][:]
	dyndep = [][:]
	while true
		match bio.getc(f)
		| `std.Ok 'L':	std.slpush(&dep, rdstr(f))
		| `std.Ok 'X':	std.slpush(&dyndep, rdstr(f))
		| `std.Err e:	std.fatal("{}: error reading {}\n", lib, e)
		| _:		break
		;;
	;;
	bio.close(f)
	ldep = std.mk([
		.name=lib,
		.dir=dir,
		.dep=dep,
		.dyndep=dyndep,
		.genuse="",
		.genar="",
		.mtime=std.tryv(std.fmtime(path), 0)
	])
	std.slfree(path)
	std.htput(b.libs, lib, ldep)

	for d : dep
		scrapelib(b, targ, d, incs)
	;;
}

const openlib = {lib, targ, incs
	var path, libname

	path = ""
	libname = ""
	for p : incs
		libname = std.fmt("lib{}.use", lib)
		path = std.pathjoin([p, libname][:])
		std.slfree(libname)
		if std.fisreg(path)
			match  bio.open(path, bio.Rd)
			| `std.Ok file:	-> (file, path, p)
			| `std.Err m:	/* next */
			;;
			std.fatal("{}: {} does not exist in {j=, }\n", targ, lib, incs)
		;;
		std.slfree(path)
	;;
	std.fatal("{}: {} does not exist in {j= }\n", targ, lib, incs)
}

const addlibs = {b, sl, libs, incs
	var added, diradded, looped
	var dynlink
	var lo

	added  = std.mkht()
	looped  = std.mkht()
	diradded  = std.mkht()

	lo = sl#.len
	dynlink = false
	for l : libs
		dynlink = addlib(b, sl, l, added, diradded, looped, dynlink)
	;;
	for var i = 0; i < sl#[lo:].len/2; i++
		std.swap(&sl#[lo+i], &sl#[sl#.len - i - 1])
	;;

	std.htfree(diradded)
	std.htfree(looped)
	std.htfree(added)

	-> dynlink
}

const addlib = {b, sl, lib, added, diradded, looped, dl
	var ar

	if std.hthas(looped, lib)
		std.fatal("{}: loop in deps\n", lib)
	;;
	std.htput(looped, lib, void)
	match std.htget(b.libs, lib)
	| `std.None:
		std.slpush(sl, std.fmt("-l{}", lib))
		dl = true
	| `std.Some ld:
		for l : ld.dep
			dl = addlib(b, sl, l, added, diradded, looped, dl)
		;;
		for l : ld.dyndep
			dl = addlib(b, sl, l, added, diradded, looped, dl)
		;;
		if !std.hthas(added, lib)
			if config.Directlib
				ar = std.fmt("lib{}.a", lib)
				std.slpush(sl, std.pathcat(ld.dir, ar))
				std.slfree(ar)
			else
				std.slpush(sl, std.fmt("-l{}", lib))
			;;
			std.htput(added, lib, void)
		;;
		if !config.Directlib && !std.hthas(diradded, ld.dir)
			std.htput(diradded, ld.dir, void)
			std.slpush(sl, std.fmt("-L{}", ld.dir))
		;;
	;;
	std.htdel(looped, lib)
	-> dl
}


const rdstr = {f -> byte[:]
	var len
	var sl

	match bio.getbe32(f)
	| `std.Ok l:
		len = l
		sl = std.slalloc(len)
	| `std.Err e:	std.fatal("error while reading string: {}", e)
	;;
	bio.read(f, sl)
	-> sl
}