blob: beb9ffff1c8ec5fb4d02c7908c23626691377394 [file] [log] [blame]
# Copyright 2017 The Bazel Authors. All rights reserved.
#
# 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.
"""Rules to create RPM archives."""
rpm_filetype = [".rpm"]
spec_filetype = [".spec"]
def _pkg_rpm_impl(ctx):
"""Implements to pkg_rpm rule."""
files = []
args = ["--name=" + ctx.label.name]
if ctx.attr.rpmbuild_path:
args += ["--rpmbuild=" + ctx.attr.rpmbuild_path]
# Version can be specified by a file or inlined.
if ctx.attr.version_file:
if ctx.attr.version:
fail("Both version and version_file attributes were specified")
args += ["--version=@" + ctx.file.version_file.path]
files += [ctx.file.version_file]
elif ctx.attr.version:
args += ["--version=" + ctx.attr.version]
# Release can be specified by a file or inlined.
if ctx.attr.release_file:
if ctx.attr.release:
fail("Both release and release_file attributes were specified")
args += ["--release=@" + ctx.file.release_file.path]
files += [ctx.file.release_file]
elif ctx.attr.release:
args += ["--release=" + ctx.attr.release]
if ctx.attr.architecture:
args += ["--arch=" + ctx.attr.architecture]
if not ctx.attr.spec_file:
fail("spec_file was not specified")
# Expand the spec file template.
spec_file = ctx.actions.declare_file("%s.spec" % ctx.label.name)
# Create the default substitutions based on the data files.
substitutions = {}
for data_file in ctx.files.data:
key = "{%s}" % data_file.basename
substitutions[key] = data_file.path
ctx.actions.expand_template(
template = ctx.file.spec_file,
output = spec_file,
substitutions = substitutions,
)
args += ["--spec_file=" + spec_file.path]
files += [spec_file]
args += ["--out_file=" + ctx.outputs.rpm.path]
# Add data files.
if ctx.file.changelog:
files += [ctx.file.changelog]
args += [ctx.file.changelog.path]
files += ctx.files.data
for f in ctx.files.data:
args += [f.path]
if ctx.attr.debug:
args += ["--debug"]
# Call the generator script.
# TODO(katre): Generate a source RPM.
ctx.actions.run(
executable = ctx.executable._make_rpm,
use_default_shell_env = True,
arguments = args,
inputs = files,
outputs = [ctx.outputs.rpm],
mnemonic = "MakeRpm",
)
# Link the RPM to the expected output name.
ctx.actions.run(
executable = "ln",
arguments = [
"-s",
ctx.outputs.rpm.basename,
ctx.outputs.out.path,
],
inputs = [ctx.outputs.rpm],
outputs = [ctx.outputs.out],
)
# Link the RPM to the RPM-recommended output name.
if "rpm_nvra" in dir(ctx.outputs):
ctx.actions.run(
executable = "ln",
arguments = [
"-s",
ctx.outputs.rpm.basename,
ctx.outputs.rpm_nvra.path,
],
inputs = [ctx.outputs.rpm],
outputs = [ctx.outputs.rpm_nvra],
)
def _pkg_rpm_outputs(version, release):
outputs = {
"out": "%{name}.rpm",
"rpm": "%{name}-%{architecture}.rpm",
}
# The "rpm_nvra" output follows the recommended package naming convention of
# Name-Version-Release.Arch.rpm
# See http://ftp.rpm.org/max-rpm/ch-rpm-file-format.html
if version and release:
outputs["rpm_nvra"] = "%{name}-%{version}-%{release}.%{architecture}.rpm"
return outputs
# Define the rule.
pkg_rpm = rule(
attrs = {
"spec_file": attr.label(
mandatory = True,
allow_single_file = spec_filetype,
),
"architecture": attr.string(default = "all"),
"version_file": attr.label(
allow_single_file = True,
),
"version": attr.string(),
"changelog": attr.label(
allow_single_file = True,
),
"data": attr.label_list(
mandatory = True,
allow_files = True,
),
"release_file": attr.label(allow_single_file = True),
"release": attr.string(),
"debug": attr.bool(default = False),
# Implicit dependencies.
"rpmbuild_path": attr.string(),
"_make_rpm": attr.label(
default = Label("//tools/build_defs/pkg:make_rpm"),
cfg = "host",
executable = True,
allow_files = True,
),
},
executable = False,
outputs = _pkg_rpm_outputs,
implementation = _pkg_rpm_impl,
)
"""Creates an RPM format package from the data files.
This runs rpmbuild (and requires it to be installed beforehand) to generate
an RPM package based on the spec_file and data attributes.
Two outputs are guaranteed to be produced: "%{name}.rpm", and
"%{name}-%{architecture}.rpm". If the "version" and "release" arguments are
non-empty, a third output will be produced, following the RPM-recommended
N-V-R.A format (Name-Version-Release.Architecture.rpm). Note that due to
the fact that rule implementations cannot access the contents of files,
the "version_file" and "release_file" arguments will not create an output
using N-V-R.A format.
Args:
spec_file: The RPM spec file to use. If the version or version_file
attributes are provided, the Version in the spec will be overwritten,
and likewise behaviour with release and release_file. Any Sources listed
in the spec file must be provided as data dependencies.
The base names of data dependencies can be replaced with the actual location
using "{basename}" syntax.
version: The version of the package to generate. This will overwrite any
Version provided in the spec file. Only specify one of version and
version_file.
version_file: A file containing the version of the package to generate. This
will overwrite any Version provided in the spec file. Only specify one of
version and version_file.
release: The release of the package to generate. This will overwrite any
release provided in the spec file. Only specify one of release and
release_file.
release_file: A file containing the release of the package to generate. This
will overwrite any release provided in the spec file. Only specify one of
release and release_file.
changelog: A changelog file to include. This will not be written to the spec
file, which should only list changes to the packaging, not the software itself.
data: List all files to be included in the package here.
"""