--!A cross-platform build utility based on Lua -- -- Licensed under the Apache License, Version 2.0 (the "License"); -- you may not use this file except in compliance with the License. -- You may obtain a copy of the License at -- -- http://www.apache.org/licenses/LICENSE-2.0 -- -- Unless required by applicable law or agreed to in writing, software -- distributed under the License is distributed on an "AS IS" BASIS, -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -- See the License for the specific language governing permissions and -- limitations under the License. -- -- Copyright (C) 2015-present, Xmake Open Source Community. -- -- @author ruki -- @file main.lua -- -- imports import("core.base.option") import("core.base.semver") import("lib.detect.find_tool") import("private.action.require.impl.packagenv") import("private.action.require.impl.install_packages") import(".batchcmds") -- get the makeself function _get_makeself() -- enter the environments of makeself local oldenvs = packagenv.enter("makeself") -- find makeself local packages = {} local makeself = find_tool("makeself.sh") if not makeself then table.join2(packages, install_packages("makeself")) end -- enter the environments of installed packages for _, instance in ipairs(packages) do instance:envs_enter() end -- we need to force detect and flush detect cache after loading all environments if not makeself then makeself = find_tool("makeself.sh", {force = true}) end assert(makeself, "makeself not found!") return makeself, oldenvs end -- get specvars function _get_specvars(package) local specvars = table.clone(package:specvars()) return specvars end -- write install command function _write_installcmd(package, scriptfile, cmd) local opt = cmd.opt or {} local kind = cmd.kind if kind == "cp" then local srcfiles = os.files(cmd.srcpath) for _, srcfile in ipairs(srcfiles) do -- the destination is directory? append the filename local dstfile = cmd.dstpath if #srcfiles > 1 or path.islastsep(dstfile) then if opt.rootdir then dstfile = path.join(dstfile, path.relative(srcfile, opt.rootdir)) else dstfile = path.join(dstfile, path.filename(srcfile)) end end scriptfile:print("cp -p \"%s\" \"%s\"", srcfile, dstfile) end elseif kind == "rm" then local filepath = cmd.filepath scriptfile:print("rm -f \"%s\"", filepath) elseif kind == "rmdir" then local dir = cmd.dir scriptfile:print("rm -rf \"%s\"", dir) elseif kind == "mv" then local srcpath = cmd.srcpath local dstpath = cmd.dstpath scriptfile:print("mv \"%s\" \"%s\"", srcfile, dstfile) elseif kind == "cd" then local dir = cmd.dir scriptfile:print("cd \"%s\"", dir) elseif kind == "mkdir" then local dir = cmd.dir scriptfile:print("mkdir -p \"%s\"", dir) elseif cmd.program then scriptfile:print("%s", os.args(table.join(cmd.program, cmd.argv))) end end -- write install commands function _write_installcmds(package, scriptfile, cmds) for _, cmd in ipairs(cmds) do _write_installcmd(package, scriptfile, cmd) end end -- pack runself package function _pack_runself(makeself, package) -- install the initial specfile local specfile = path.join(package:builddir(), package:basename() .. ".lsm") if not os.isfile(specfile) then local specfile_template = package:get("specfile") or path.join(os.programdir(), "scripts", "xpack", "runself", "makeself.lsm") os.cp(specfile_template, specfile, {writeable = true}) end -- replace variables in specfile local specvars = _get_specvars(package) local pattern = package:extraconf("specfile", "pattern") or "%${([^\n]-)}" local specvars_names = {} local specvars_values = {} io.gsub(specfile, "(" .. pattern .. ")", function(_, name) table.insert(specvars_names, name) end) for _, name in ipairs(specvars_names) do name = name:trim() if specvars_values[name] == nil then local value = specvars[name] if type(value) == "function" then value = value() end if value ~= nil then dprint(" > replace %s -> %s", name, value) end if type(value) == "table" then dprint("invalid variable value", value) end specvars_values[name] = value end end io.gsub(specfile, "(" .. pattern .. ")", function(_, name) name = name:trim() return specvars_values[name] end) -- archive source files local srcfiles, dstfiles = package:sourcefiles() for idx, srcfile in ipairs(srcfiles) do os.vcp(srcfile, dstfiles[idx]) end for _, component in table.orderpairs(package:components()) do if component:get("default") ~= false then local srcfiles, dstfiles = component:sourcefiles() for idx, srcfile in ipairs(srcfiles) do os.vcp(srcfile, dstfiles[idx]) end end end -- generate the setup.sh script local sourcedir = package:sourcedir() local setupfile = path.join(sourcedir, "__setup__.sh") os.cp(path.join(os.programdir(), "scripts", "xpack", "runself", "setup.sh"), setupfile) local scriptfile = io.open(setupfile, "a+") if scriptfile then _write_installcmds(package, scriptfile, batchcmds.get_installcmds(package):cmds()) for _, component in table.orderpairs(package:components()) do if component:get("default") ~= false then _write_installcmds(package, scriptfile, batchcmds.get_installcmds(component):cmds()) end end scriptfile:close() end -- make package os.vrunv(makeself, {"--gzip", "--sha256", "--lsm", specfile, sourcedir, package:outputfile(), package:basename(), "./__setup__.sh"}) end function main(package) if is_subhost("windows") then return end cprint("packing %s", package:outputfile()) -- get makeself local makeself, oldenvs = _get_makeself() -- pack runself package _pack_runself(makeself.program, package) -- done os.setenvs(oldenvs) end