# EPEL5-specific macros
%epel 5
# This file is named such that it appears alphabetically after other macro
# files in /etc/rpm. This allows us to overwrite RHEL-provided macros if
# necessary. (It turns out that it is necessary; see _font_pkg below.)
# First some miscellaneous macros
%make_build %{__make} %{?_smp_mflags}
%make_install %{__make} install DESTDIR=%{?buildroot}
%bash_completion_dir /usr/share/bash-completion/
# Now the big magic macros
# How this works:
# RPM for whatever reason allows the redifinition of the section specifiers:
# %description, %prep, %build, %install, and even %files. This gives us a
# convenient place to hang new tags (just before %description is emitted) and
# to add things to the beginning of a section.
# Also, note that lua state is global unless declared local. So non-local
# variables, as well as functions, defined in one macro are available to
# others.
#
# ================
# Some utility functions
#
# This turns debug output on or off.
# Wanted to make this a toggle, but rpm will re-parse the sec when it sees
# BuildArch:, so this just toggles again.
%epel_macros_trace() %{lua:
local args = rpm.expand("%*")
if args == "0" or args == "off" or args == "no" then
trace = 0
else
trace = 1
end
}%nil
# Initializes global lua state and then undefines itself.
# Should be called before or as part of any macros below this one.
%epel_macros_init() %{lua:
function db(str, nest)
if type(trace) ~= "number" or trace == 0 then
return
end
if type(nest) == "number" and nest > 0 then
io.stderr:write(string.rep("| ", nest))
end
io.stderr:write(str .. "\\n")
end
\
db("Epel macros loading.")
\
-- Return true if a particular macro is set to a "true" value, or false if not
function istrue(macro)
db("istrue <= " .. macro)
local val = rpm.expand(macro)
db(val)
if val == "0" or val == "off" or val == "no" or val == macro then
return False
end
if val == "1" or val == "on" or val == "yes" then
return True
end
error("Error: macro " .. macro .. " has non-true/false value.")
end
\
-- Return true if a particular macro is set to a "true" value, or false if not
function isfalse(macro)
db("isfalse <= " .. macro)
local val = rpm.expand('%' .. macro)
if val == "" or val == "0" or val == "off" or val == "no" then
return True
end
if val == "1" or val == "on" or val == "yes" then
return False
end
error("Error: macro " .. macro .. " has non-true/false value.")
end
\
-- Return the value of a particular macro
function getval(macro, default)
db("getval <= " .. macro)
macro = '%' .. macro
local val = rpm.expand(macro)
if val == macro then
return default
end
return val
end
\
-- Quiet debugging output
function db_silent()
savedtrace = trace
trace = 0
end
\
-- Restore debugging output, but does nothing if it wasn't enabled to begin
-- with.
function db_endsilent()
trace = savedtrace
end
\
-- Iterate through a bunch of numbered macros, accumulating any found
-- values in a table
function get_numbered_macros(macrobase, max)
db("get_numbered_macros <= " .. macrobase .. ", " .. max)
\
local val
local out = {}
\
db_silent() -- Doing a load of getvals, so make them quiet
for i=0,maxcheck do
val = getval(macrobase .. i)
if val ~= nil then
table.insert(out, val)
end
end
db_endsilent()
\
return out
end
\
rpm.define("epel_macros_init %{nil}")
}%nil
# ================
# This injects a BuildRoot: tag, a Group: tag and a %clean section by hooking
# %description. RPM requires that tags like BuildRoot:, Group: or License: be
# located before %description in the spec, so this is the perfect place to add
# them or change their values. Of course, we don't provide either if the spec
# does.
# This also defines %license to the string "%doc" for use later in the %files
# section. This can't just be a simple macro because RPM will overwrite it
# when it sees a License: tag. Hanging it here is quite convenient, but if
# %license is actually used in the spec then this will cause an issue. Hanging
# it off of %files fixes this but has its own problems involving the use of
# %define instead of %global and some expansions magically turning into endless
# recursion.
# It would be nice if the macro could define itself out of existence
# by defining %description to itself. Doesn't work, though, so instead the
# function just keeps state.
# What happens if the spec already has a %clean section? Sadly just defining
# it to exit doesn't work, because this makes it abort the previous scriptlet
# before the commands appended from __spec_*_post get run.
# So instead we redefine %clean to a deeply magical "cat << 'true '" and then
# prepend a call to true at the beginning of %__spec_install_post. The normal
# place for %clean is just after install. at some place before %files and
# after but not _immediately after %description, this means that what's in the
# spec's existing %clean section will just be appended to the previous section
# just after a call to exit. So the old clean section will still be there but
# will have no effect.
# If the clean section appears elsewhere, no harm is done because
# __spec_prep_post and __spec_build_post are just exit 0. The magic heredoc
# runs off the end of the scriptlet, which causes no error. If %clean appears
# immediately after %description, the magic cat is just appended there. Which
# isn't great, but doesn't harm anything.
# Alternately, we could just completely ignore %clean. RPM doesn't care if it
# isn't there, so removing it probably costs more than it could possibly save.
# It is an interesting exercise, though.
%description %epel_macros_init%{lua:
db("In %description.")
\
-- %group is reset changes after each Group: tag.
-- Unfortuantely it isn't reset when a package tag is seen.
local group = rpm.expand("%{?group}")
if type(group) == "nil" or string.len(group) == 0 or group == "Unspecified" then
-- What we use for Group: isn't important; it just has to be there
db("No Group tag found; adding one.")
print("Group: Unspecified\\n")
else
db("Group specified: " .. group)
end
-- If we don't do this, the %group keeps the value from the last specified
-- Group: tag, even though we just provided one. And if we do this, then
-- RPM will re-assign it. Which is confusing, but whatever.
rpm.expand("%undefine group")
\
-- Don't do anything else twice
if did_description == 1 then
db("Already did %description processing")
print("%description")
return
end
local buildroot = rpm.expand("%{?buildroot}")
if type(buildroot) == "nil" or string.len(buildroot) == 0 then
-- Use the recommended form for BuildRoot
db("No BuildRoot tag found; adding one.")
buildroot = rpm.expand("%(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)")
print("BuildRoot: " .. buildroot .. "\\n\\n")
else
db("Buildroot already specified: " .. buildroot)
end
\
-- Add a %clean section
db("Adding %clean.")
print("%clean\\n")
-- Note that we can't use %buildroot here, because rpm hasn't parsed the
-- BuildRoot tag yet.
print("rm -rf " .. buildroot .. "\\n\\n")
\
-- Make sure any other %clean doesn't get executed.
-- db("Redefining %clean.")
rpm.define("clean cat << \'true \'")
\
-- Redefine __spec_install_post
db("Redefining %__spec_install_post.")
local oldvar = rpm.expand("%{__spec_install_post}")
oldvar = string.gsub(oldvar, "%s+\\n", " \\\\\\n")
rpm.define("__spec_install_post echo foo\\\\\\ntrue\\\\" .. oldvar)
\
-- Make %license work in the %files list.
rpm.define("license %doc")
\
-- Actually output the %description tag
print("%description")
\
-- The next call to this macro should skip all the work
did_description = 1
}%nil
# ================
# Add the usual buildroot cleaning to the very beginning of %install
%install %{lua:
db("In %install.")
print("%install\\n")
print(rpm.expand("rm -rf %{buildroot}\\n"))
}%nil
# Add a directory for RPM macros that can be used consistently across Fedora and EPEL
%rpmmacrodir %{_sysconfdir}/rpm
# RPM before 4.6.0 does not provide the patches and sources tables to lua code.
# This means that the autosetup macro, if copied over to EL5, won't find any
# patches to apply. However, it is possible to fill those tables manually by
# iterating over a large number of possible 'SOURCE' tags and seeing if they
# exist.
%el5_sources_limit 100000
%el5_patches_limit 100000
%el5_setup_sources %epel_macros_init%{lua:
maxcheck = getval("el5_sources_limit")
\
sources = get_numbered_macros("SOURCE", maxcheck)
\
for i,v in ipairs(sources) do
db("Found source: " .. v)
end
}%nil
%el5_setup_patches() %{lua:
maxcheck = getval("el5_patches_limit")
\
patches = get_numbered_macros("PATCH", maxcheck)
\
for i,v in ipairs(patches) do
db("Found patch: " .. v)
end
}%nil
# vim: set filetype=spec: