parsav  Artifact [60797f7bc4]

Artifact 60797f7bc40b8c849e841f707213aac9e127e9a4ac6cb5fd31c6525442f3c223:


local u = dofile('common.lua')
local default = function(var,def)
	local v = os.getenv(var)
	if v then return v else return def end
end
local function coalesce(x,...)
	if x ~= nil then return x else
		if select('#',...) == 0 then return nil end
		return coalesce(...)
	end
end
local posixes = {
	linux = true; osx = true;
	android = true; haiku = true;
}
local default_os = 'linux'
local conf = {
	pkg = {};
	dist      = default('parsav_dist', coalesce(
		os.getenv('NIX_PATH')  and 'nixos',
		os.getenv('NIX_STORE') and 'nixos',
	''));
	tgttrip   = default('parsav_arch_triple'); -- target triple, used in xcomp
	tgtcpu    = default('parsav_arch_cpu'); -- target cpu, used in xcomp
	tgthf     = u.tobool(default('parsav_arch_armhf',true)); 
	endian    = default('parsav_arch_endian', 'little');
	build     = {
		id = u.rndstr(6);
		release = u.ingest('release');
		when = os.date();
	};
	feat = {};
}
if u.ping '.fslckout' or u.ping '_FOSSIL_' then
	if u.ping '_FOSSIL_' then default_os = 'windows' end
	conf.build.branch = u.exec { 'fossil', 'branch', 'current' }
	conf.build.checkout = (u.exec { 'fossil', 'sql',
		[[select value from localdb.vvar where name = 'checkout-hash']]
	}):gsub("^'(.*)'$", '%1')
end
conf.os    = default('parsav_host_os', default_os);
conf.tgtos = default('parsav_target_os', default_os);
conf.posix = posixes[conf.os]
conf.exe   = u.tobool(default('parsav_link',not conf.tgttrip)); -- turn off for partial builds
conf.build.origin = coalesce(
	os.getenv('parsav_builder'),
	string.format('%s@%s', coalesce (
		os.getenv('USER'),
		u.exec{'whoami'}
	), u.exec{'hostname'}) -- whoami and hostname are present on both windows & unix
)
if conf.build.release then
	local v = conf.build.release
	conf.build.str = string.format('release %s', conf.build.release)
else
	conf.build.str = string.format('build %s-%s', conf.build.id, conf.build.origin)
	if conf.build.branch then
		conf.build.str = conf.build.str .. string.format(':%s(%s)',
			conf.build.branch, string.sub(conf.build.checkout,1,10))
	end
end

if conf.tgtos == 'linux' then
	conf.feat.randomizer = default('parsav_feat_randomizer', 'kern')
else
	conf.feat.randomizer = default('parsav_feat_randomizer', 'libc')
end

local choplib = function(l)
	if string.sub(l,1,3) == 'lib' then return string.sub(l,4) end
	return l
end
local fallback = dofile('pkgdata.lua')
local libfind do local mkf = function(p)
		return function(l) return string.format(p,l) end
	end
	local unx = function(p)
		return function(l)
			if string.sub(l,1,3) == 'lib'
				then return string.format('%s.%s',l,p)
				else return string.format('lib%s.%s',l,p)
			end
		end
	end

	libfind = {
		linux = { static = unx 'a', dynamic = unx 'so'; };
		osx   = { dynamic = mkf '%s.dylib'; };
		win   = { dynamic = mkf '%s.dll'; };
	}
end
local pkg = function(name)
	local fbo = fallback[name] and fallback[name].osvars and coalesce(
		fallback[name].osvars[conf.os .. '_' .. conf.dist],
		fallback[name].osvars[conf.os]
	)
	local fbv = fallback[name] and fallback[name].vars
	local fb = fallback[name]
	local pkgenv = function(e)
		return os.getenv(string.format('parsav_pkg_%s_%s',name,e))
	end
	local nul = function() end
	local pkc, pkv = nul, nul
	local locdep = false
	local cnfvar = function(v,e)
		local eval = function(e)
			if type(e) == 'function'
				then return e(conf)
				else return e
			end
		end
		return coalesce(
			pkgenv(v),
			pkv(e or v),
			(fbo and eval(fbo[v])),
			(fbv and eval(fbv[v])))
	end
	local name = cnfvar('override') or name
	local pcname = coalesce(cnfvar('pcname'), name)
	if conf.posix then
		pkc  = function(...) if locdep then return nil end
			return u.exec { 'pkg-config'; pcname; ...  } end
		local pkcv = function(...) return u.exec({ 'pkg-config'; pcname; ...  }, true) end
		if pkcv('--exists') == 0 then
			pkv = function(v)
				if locdep then return nil end
				return pkc('--variable', v)
			end
		else pkc = nul end
	else
		print '(warn) configuring on non-POSIX OS, all relevant paths must be specified manually in environment variables or build will fail!'
	end
	locdep = u.ping('./lib/' .. name)
	local incdir, libdir, prefix
	if locdep then
		prefix = './lib/' .. name
		libdir = prefix .. coalesce(cnfvar('libbuilddir'),cnfvar('builddir'),'')
		incdir = prefix .. coalesce(cnfvar('srcincdir'),cnfvar('builddir'),'/include')
	else
		prefix = coalesce(cnfvar('prefix'), '/usr')
		libdir = cnfvar('libdir')
		incdir = cnfvar('incdir','includedir')
	end
	libdir = libdir or prefix .. '/lib'
	incdir = incdir or prefix .. '/include'

	local libstr = pkc '--libs-only-l' -- (--static is not reliable)
	local libs = fb and fb.libs or {}
	local linkstatic = locdep
	if (not locdep) and libstr then
		libs = {}
		for m in string.gmatch(libstr, '-l(%g+)') do
			libs[#libs + 1] = m
		end
	else
		if #libs == 0 then libs = { name } end
	end

	conf.pkg[name] = {
		prefix = prefix;
		libdir = libdir;
		incdir = incdir;
		dylibs = {}, statlibs = {};
	}
	local me = conf.pkg[name]
	
	local lf = libfind[conf.os]
	if lf.dynamic then me.dylibs   = u.map(libs, lf.dynamic) end
	if lf.static  then me.statlibs = u.map(libs, lf.static)  end

	if linkstatic then
		local ldf = {}
		for _,v in pairs(me.statlibs) do
			local fl = libdir .. '/' .. v
			if u.ping(fl) then ldf[#ldf+1] = fl end
		end
		me.linkargs = ldf
	else
		local arg = choplib(name)
		local linkline = libstr
		if not linkline and #libs == 0 then
			linkline = string.format('-l%s', arg)
		elseif not linkline then linkline = '' end
		me.linkargs = {
			string.format('-L%s', me.libdir);
		}
		for m in string.gmatch(linkline, '(%g+)') do
			me.linkargs[#me.linkargs+1] = m
		end

		-- siiiiigh
		for _,l in pairs(libs) do
			local sw = string.format('-l%s', choplib(l)) 
			local found = false
			for _,a in pairs(me.linkargs) do
				if a == sw then found = true break end
			end
			if not found then
				me.linkargs[#me.linkargs+1] = sw
			end
		end
	end
end

pkg('mbedtls')
pkg('mongoose')
pkg('json-c')
pkg('libc')
pkg('libpq')

return conf