summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2023-12-21 14:41:31 +0800
committerGitHub <[email protected]>2023-12-21 14:41:31 +0800
commitb9bcacc934f10e034e7429a53921814c16d994ec (patch)
tree88f65d5e7491a08f21010042b670cfc08344022d
parent1597b1aab9db774d123f37a4ae38d145cef3f1bb (diff)
parent16271a7919d9ee12203f1ba5774d73f720b79451 (diff)
Merge pull request #4515 from xmake-io/rpm
Support to pack srpm package
-rw-r--r--tests/plugins/pack/xmake.lua6
-rw-r--r--xmake/includes/xpack/xmake.lua12
-rw-r--r--xmake/plugins/pack/batchcmds.lua68
-rw-r--r--xmake/plugins/pack/srpm/main.lua265
-rw-r--r--xmake/plugins/pack/xmake.lua2
-rw-r--r--xmake/plugins/pack/xpack.lua9
-rw-r--r--xmake/scripts/xpack/srpm/srpm.spec39
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}
+