diff options
| author | ruki <[email protected]> | 2023-12-21 14:41:31 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-12-21 14:41:31 +0800 |
| commit | b9bcacc934f10e034e7429a53921814c16d994ec (patch) | |
| tree | 88f65d5e7491a08f21010042b670cfc08344022d | |
| parent | 1597b1aab9db774d123f37a4ae38d145cef3f1bb (diff) | |
| parent | 16271a7919d9ee12203f1ba5774d73f720b79451 (diff) | |
Merge pull request #4515 from xmake-io/rpm
Support to pack srpm package
| -rw-r--r-- | tests/plugins/pack/xmake.lua | 6 | ||||
| -rw-r--r-- | xmake/includes/xpack/xmake.lua | 12 | ||||
| -rw-r--r-- | xmake/plugins/pack/batchcmds.lua | 68 | ||||
| -rw-r--r-- | xmake/plugins/pack/srpm/main.lua | 265 | ||||
| -rw-r--r-- | xmake/plugins/pack/xmake.lua | 2 | ||||
| -rw-r--r-- | xmake/plugins/pack/xpack.lua | 9 | ||||
| -rw-r--r-- | xmake/scripts/xpack/srpm/srpm.spec | 39 |
7 files changed, 394 insertions, 7 deletions
diff --git a/tests/plugins/pack/xmake.lua b/tests/plugins/pack/xmake.lua index 33d50b3d2..fc45c7fad 100644 --- a/tests/plugins/pack/xmake.lua +++ b/tests/plugins/pack/xmake.lua @@ -19,15 +19,17 @@ target("foo") add_packages("zlib") xpack("test") - set_formats("nsis", "zip", "targz", "srczip", "srctargz", "runself") + set_formats("nsis", "srpm", "zip", "targz", "srczip", "srctargz", "runself") set_title("hello") set_author("ruki") set_description("A test installer.") set_homepage("https://xmake.io") + set_license("Apache-2.0") set_licensefile("LICENSE.md") add_targets("test", "foo") add_installfiles("src/(assets/*.png)", {prefixdir = "images"}) add_sourcefiles("(src/**)") + add_sourcefiles("xmake.lua") set_iconfile("src/assets/xmake.ico") add_components("LongPath") @@ -40,7 +42,7 @@ xpack("test") end) after_installcmd(function (package, batchcmds) - if package:from_source() then + if package:format() == "runself" then batchcmds:runv("echo", {"hello"}) else batchcmds:mkdir(package:installdir("resources")) diff --git a/xmake/includes/xpack/xmake.lua b/xmake/includes/xpack/xmake.lua index c6ed04201..5b8580172 100644 --- a/xmake/includes/xpack/xmake.lua +++ b/xmake/includes/xpack/xmake.lua @@ -46,7 +46,7 @@ local apis = { "xpack.set_copyright", -- set company name "xpack.set_company", - -- set package formats, e.g. nsis, deb, rpm, targz, zip, srctargz, srczip, runself, ... + -- set package formats, e.g. nsis, deb, srpm, targz, zip, srctargz, srczip, runself, ... -- we can also add custom formats "xpack.set_formats", -- set the base name of the output file @@ -65,6 +65,8 @@ local apis = { "xpack.set_includedir", -- set prefix directory, e.g. prefixdir/bin, prefixdir/lib .. "xpack.set_prefixdir", + -- add build requires for source inputkind + "xpack.add_buildrequires", -- set nsis display icon "xpack.set_nsis_displayicon", -- set package component title @@ -79,6 +81,8 @@ local apis = { "xpack.set_specfile", -- set icon file path, e.g foo.ico "xpack.set_iconfile", + -- set package license + "xpack.set_license", -- set package license file, we will also get them from target "xpack.set_licensefile", -- add source files @@ -99,6 +103,12 @@ local apis = { "xpack.on_package", -- add custom package script after packing package "xpack.after_package", + -- add custom build commands script before building, it's only for source inputkind + "xpack.before_buildcmd", + -- add custom build commands script, it's only for source inputkind + "xpack.on_buildcmd", + -- add custom build commands script after building, it's only for source inputkind + "xpack.after_buildcmd", -- add custom commands script before installing "xpack.before_installcmd", -- add custom commands script before uninstalling diff --git a/xmake/plugins/pack/batchcmds.lua b/xmake/plugins/pack/batchcmds.lua index af55cc707..2403b5bca 100644 --- a/xmake/plugins/pack/batchcmds.lua +++ b/xmake/plugins/pack/batchcmds.lua @@ -183,6 +183,12 @@ function _on_target_installcmd_headeronly(target, batchcmds_, opt) _install_headers(target, batchcmds_, includedir) end +-- on build target command +function _on_target_buildcmd(target, batchcmds_, opt) + local package = opt.package + batchcmds_:vrunv("xmake", {"build", target:name()}) +end + -- on install target command function _on_target_installcmd(target, batchcmds_, opt) local package = opt.package @@ -295,6 +301,39 @@ function _on_target_uninstallcmd(target, batchcmds_, opt) end end +-- get build commands from targets +function _get_target_buildcmds(target, batchcmds_, opt) + + -- call script to get build commands + local scripts = { + target:script("buildcmd_before"), -- TODO unused + function (target) + for _, r in ipairs(target:orderules()) do + local before_buildcmd = r:script("buildcmd_before") + if before_buildcmd then + before_buildcmd(target, batchcmds_, opt) + end + end + end, + target:script("buildcmd", _on_target_buildcmd), -- TODO unused + function (target) + for _, r in ipairs(target:orderules()) do + local after_buildcmd = r:script("buildcmd_after") + if after_buildcmd then + after_buildcmd(target, batchcmds_, opt) + end + end + end, + target:script("buildcmd_after") -- TODO unused + } + for i = 1, 5 do + local script = scripts[i] + if script ~= nil then + script(target, batchcmds_, opt) + end + end +end + -- get install commands from targets function _get_target_installcmds(target, batchcmds_, opt) @@ -361,6 +400,16 @@ function _get_target_uninstallcmds(target, batchcmds_, opt) end end +-- on build command +function _on_buildcmd(package, batchcmds_) + if not package:from_source() then + return + end + for _, target in ipairs(package:targets()) do + _get_target_buildcmds(target, batchcmds_, {package = package}) + end +end + -- on install command function _on_installcmd(package, batchcmds_) if not package:from_binary() then @@ -389,6 +438,25 @@ function _on_uninstallcmd(package, batchcmds_) end end +-- get build commands +function get_buildcmds(package) + local batchcmds_ = batchcmds.new() + + -- call script to get build commands + local scripts = { + package:script("buildcmd_before"), + package:script("buildcmd", _on_buildcmd), + package:script("buildcmd_after") + } + for i = 1, 3 do + local script = scripts[i] + if script ~= nil then + script(package, batchcmds_) + end + end + return batchcmds_ +end + -- get install commands function get_installcmds(package) local batchcmds_ = batchcmds.new() diff --git a/xmake/plugins/pack/srpm/main.lua b/xmake/plugins/pack/srpm/main.lua new file mode 100644 index 000000000..2c9a0cb1b --- /dev/null +++ b/xmake/plugins/pack/srpm/main.lua @@ -0,0 +1,265 @@ +--!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, TBOOX Open Source Group. +-- +-- @author ruki +-- @file main.lua +-- + +-- imports +import("core.base.option") +import("core.base.semver") +import("core.base.hashset") +import("lib.detect.find_tool") +import("utils.archive") +import("private.action.require.impl.packagenv") +import("private.action.require.impl.install_packages") +import(".batchcmds") + +-- get the rpmbuild +function _get_rpmbuild() + + -- enter the environments of rpmbuild + local oldenvs = packagenv.enter("rpm") + + -- find rpmbuild + local packages = {} + local rpmbuild = find_tool("rpmbuild") + if not rpmbuild then + table.join2(packages, install_packages("rpm")) + 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 rpmbuild then + rpmbuild = find_tool("rpmbuild", {force = true}) + end + assert(rpmbuild, "rpmbuild not found!") + return rpmbuild, oldenvs +end + +-- get archive file +function _get_archivefile(package) + return path.absolute(path.join(package:buildir(), package:basename() .. ".tar.gz")) +end + +-- translate the file path +function _translate_filepath(package, filepath) + return filepath:replace(package:install_rootdir(), "%{buildroot}/%{_exec_prefix}", {plain = true}) +end + +-- get install command +function _get_customcmd(package, installcmds, 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 = _translate_filepath(package, 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 + table.insert(installcmds, string.format("install -Dpm0644 \"%s\" \"%s\"", srcfile, dstfile)) + end + elseif kind == "rm" then + local filepath = _translate_filepath(package, cmd.filepath) + table.insert(installcmds, string.format("rm -f \"%s\"", filepath)) + elseif kind == "rmdir" then + local dir = _translate_filepath(package, cmd.dir) + table.insert(installcmds, string.format("rm -rf \"%s\"", dir)) + elseif kind == "mv" then + local srcpath = _translate_filepath(package, cmd.srcpath) + local dstpath = _translate_filepath(package, cmd.dstpath) + table.insert(installcmds, string.format("mv \"%s\" \"%s\"", srcfile, dstfile)) + elseif kind == "cd" then + local dir = _translate_filepath(package, cmd.dir) + table.insert(installcmds, string.format("cd \"%s\"", dir)) + elseif kind == "mkdir" then + local dir = _translate_filepath(package, cmd.dir) + table.insert(installcmds, string.format("mkdir -p \"%s\"", dir)) + elseif cmd.program then + table.insert(installcmds, string.format("%s", os.args(table.join(cmd.program, cmd.argv)))) + end +end + +-- get build commands +function _get_buildcmds(package, buildcmds, cmds) + for _, cmd in ipairs(cmds) do + _get_customcmd(package, buildcmds, cmd) + end +end + +-- get install commands +function _get_installcmds(package, installcmds, cmds) + for _, cmd in ipairs(cmds) do + _get_customcmd(package, installcmds, cmd) + end +end + +-- get specvars +function _get_specvars(package) + local specvars = table.clone(package:specvars()) + specvars.PACKAGE_ARCHIVEFILE = path.filename(_get_archivefile(package)) + local datestr = os.iorunv("date", {"+%a %b %d %Y"}, {envs = {LC_TIME = "en_US"}}) + if datestr then + datestr = datestr:trim() + end + specvars.PACKAGE_PREFIXDIR = package:prefixdir() or "" + specvars.PACKAGE_DATE = datestr or "" + specvars.PACKAGE_INSTALLCMDS = function () + local prefixdir = package:get("prefixdir") + package:set("prefixdir", nil) + local installcmds = {} + _get_installcmds(package, installcmds, batchcmds.get_installcmds(package):cmds()) + for _, component in table.orderpairs(package:components()) do + if component:get("default") ~= false then + _get_installcmds(package, installcmds, batchcmds.get_installcmds(component):cmds()) + end + end + package:set("prefixdir", prefixdir) + return table.concat(installcmds, "\n") + end + specvars.PACKAGE_BUILDCMDS = function () + local buildcmds = {} + _get_buildcmds(package, buildcmds, batchcmds.get_buildcmds(package):cmds()) + return table.concat(buildcmds, "\n") + end + specvars.PACKAGE_BUILDREQUIRES = function () + local requires = {} + local buildrequires = package:get("buildrequires") + if buildrequires then + for _, buildrequire in ipairs(buildrequires) do + table.insert(requires, "BuildRequires: " .. buildrequire) + end + else + local programs = hashset.new() + for _, cmd in ipairs(batchcmds.get_buildcmds(package):cmds()) do + local program = cmd.program + if program then + programs:insert(program) + end + end + local map = { + xmake = "xmake", + cmake = "cmake", + make = "make" + } + for _, program in programs:keys() do + local requirename = map[program] + if requirename then + table.insert(requires, "BuildRequires: " .. requirename) + end + end + if #requires > 0 then + table.insert(requires, "BuildRequires: gcc") + table.insert(requires, "BuildRequires: gcc-c++") + end + end + return table.concat(requires, "\n") + end + return specvars +end + +-- pack srpm package +function _pack_srpm(rpmbuild, package) + + -- ensure prefixdir + local prefixdir = package:get("prefixdir") + if not prefixdir then + prefixdir = package:name() .. "-" .. package:version() + package:set("prefixdir", prefixdir) + end + + -- install the initial specfile + local specfile = package:specfile() + if not os.isfile(specfile) then + local specfile_template = path.join(os.programdir(), "scripts", "xpack", "srpm", "srpm.spec") + os.cp(specfile_template, specfile) + end + + -- replace variables in specfile + local specvars = _get_specvars(package) + local pattern = package:extraconf("specfile", "pattern") or "%${([^\n]-)}" + io.gsub(specfile, "(" .. pattern .. ")", function(_, name) + name = name:trim() + 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 + return value + 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 + + -- archive install files + local rootdir = package:source_rootdir() + local oldir = os.cd(rootdir) + local archivefiles = os.files("**") + os.cd(oldir) + local archivefile = _get_archivefile(package) + os.tryrm(archivefile) + archive.archive(archivefile, archivefiles, {curdir = rootdir, compress = "best"}) + + -- do pack + os.vrunv(rpmbuild, {"-bs", specfile, + "--define", "_topdir " .. package:buildir(), + "--define", "_sourcedir " .. package:buildir(), + "--define", "_srcrpmdir " .. package:outputdir()}) +end + +function main(package) + + if not is_host("linux") then + return + end + + cprint("packing %s", package:outputfile()) + + -- get rpmbuild + local rpmbuild, oldenvs = _get_rpmbuild() + + -- pack srpm package + _pack_srpm(rpmbuild.program, package) + + -- done + os.setenvs(oldenvs) +end diff --git a/xmake/plugins/pack/xmake.lua b/xmake/plugins/pack/xmake.lua index 96b0d2070..6ed3b6d3f 100644 --- a/xmake/plugins/pack/xmake.lua +++ b/xmake/plugins/pack/xmake.lua @@ -32,7 +32,7 @@ task("pack") "e.g.", " - xmake pack -f nsis,deb,rpm", "values:", - values = {"nsis", "deb", "rpm", "runself", "targz", "zip", "srctargz", "srczip"}}, + values = {"nsis", "deb", "srpm", "runself", "targz", "zip", "srctargz", "srczip"}}, {}, {nil, "packages", "vs", nil, "The package names."} } diff --git a/xmake/plugins/pack/xpack.lua b/xmake/plugins/pack/xpack.lua index 64e9d77dc..5cf5f24f4 100644 --- a/xmake/plugins/pack/xpack.lua +++ b/xmake/plugins/pack/xpack.lua @@ -237,7 +237,7 @@ function xpack:inputkind() srctargz = "source", runself = "source", deb = "source", - rpm = "source" + srpm = "source" } inputkind = inputkinds[self:format()] or "binary" end @@ -302,6 +302,7 @@ function xpack:specvars() PACKAGE_COPYRIGHT = self:get("copyright") or "", PACKAGE_COMPANY = self:get("company") or "", PACKAGE_ICONFILE = self:get("iconfile") or "", + PACKAGE_LICENSE = self:license() or "", PACKAGE_LICENSEFILE = self:get("licensefile") or "" } @@ -359,7 +360,9 @@ end -- get the specfile path function xpack:specfile() local extensions = { - nsis = ".nsi" + nsis = ".nsi", + srpm = ".spec", + runself = ".lsm" } local extension = extensions[self:format()] or ".spec" return self:get("specfile") or path.join(self:buildir(), self:basename() .. extension) @@ -377,7 +380,7 @@ function xpack:extension() srctargz = ".tar.gz", runself = ".gz.run", deb = ".deb", - rpm = ".rpm" + srpm = ".src.rpm" } extension = extensions[self:format()] or "" end diff --git a/xmake/scripts/xpack/srpm/srpm.spec b/xmake/scripts/xpack/srpm/srpm.spec new file mode 100644 index 000000000..a0b403dd1 --- /dev/null +++ b/xmake/scripts/xpack/srpm/srpm.spec @@ -0,0 +1,39 @@ +# this is a SRPM spec file, +# it is autogenerated by the xmake build system. +# do not edit by hand. + +%global debug_package %{nil} + +Name: ${PACKAGE_NAME} +Version: ${PACKAGE_VERSION} +Release: 1%{?dist} +Summary: ${PACKAGE_TITLE} + +License: ${PACKAGE_LICENSE} +URL: ${PACKAGE_HOMEPAGE} +Source0: ${PACKAGE_ARCHIVEFILE} + +${PACKAGE_BUILDREQUIRES} + +%description +${PACKAGE_DESCRIPTION} + +%prep +%autosetup -n ${PACKAGE_PREFIXDIR} -p1 + +%build +${PACKAGE_BUILDCMDS} + +%install +${PACKAGE_INSTALLCMDS} +cd %{buildroot} +find . -type f | sed 's!^\./!/!' > %{_builddir}/_installedfiles.txt + +%check + +%files -f %{_builddir}/_installedfiles.txt + +%changelog +* ${PACKAGE_DATE} ${PACKAGE_MAINTAINER} - ${PACKAGE_VERSION}-1 +- Update to ${PACKAGE_VERSION} + |
