openSUSE:Packaging Bazel
Build Service Tutorial 路 Tips & Tricks 路 Cross Distribution Howto 路 Packaging checks 路 Desktop menu categories 路 RPM Macros 路 Scriptlets 路 Init scripts 路 How to write good changes
Guidelines for packaging software using Bazel
This guideline applies to packaging software which uses Bazel build system.
Bazel multiversion packages
Bazel releases new version very quick and different projects support different versions of Bazel. That's why we have several packages like bazel0.29, bazel1.2, bazel2.0 and the main package bazel is an empty package which requires the default version of Bazel (which usually is either the newest one or the most commonly used one).
Bazel rules and extensions
Bazel stores different rules and extensions in separate git repos. For example:
- https://github.com/bazelbuild/rules_cc
- https://github.com/bazelbuild/rules_rust
- https://github.com/bazelbuild/rules_go
- https://github.com/bazelbuild/rules_python
- https://github.com/bazelbuild/platforms
In fact, most of the software built by Bazel use at least one of them.
Structure of the project
Every project using Bazel as the build system has to contain WORKSPACE file and at least one BUILD file in its source tree. WORKSPACE defines the name, settings and dependencies of the project. BUILD
Developers can also create modules with .bzl file extension, where they define functions, which then are called in the WORKSPACE file.
Repositories
Bazel refers to external dependencies of the project as repositories. Repositories are defined either in the WORKSPACE file or in functions inside .bzl files.
There are several ways of defining repositories:
http_archive
http_archive downloads the tarball and uses it as a dependency.
Example when dependency supports Bazel (has WORKSPACE and BUILD files in its source tree):
http_archive(
name = "com_google_protobuf",
sha256 = "416212e14481cff8fd4849b1c1c1200a7f34808a54377e22d7447efdf54ad758",
strip_prefix = "protobuf-09745575a923640154bcf307fba8aedff47f240a",
url = "https://github.com/google/protobuf/archive/09745575a923640154bcf307fba8aedff47f240a.tar.gz",
)
Example when dependency does not support Bazel (does not have WORKSPACE and BUILD files):
http_archive(
name = "openssl",
urls = ["https://github.com/openssl/openssl/archive/OpenSSL_1_1_1d.tar.gz"],
sha256 = "23011a5cc78e53d0dc98dfa608c51e72bcd350aa57df74c5d5574ba4ffb62e74",
build_file = "@//:openssl.BUILD",
strip_prefix = "openssl-OpenSSL_1_1_1d",
)
The content of openssl.BUILD should look like that.
local_repository
local_repository points directly to the locally available repository. Example of usage:
local_repository(
name = "my-grpc",
path = "/home/user/grpc",
)
It's not often used in publicly available projects.
new_local_repository
new_local_repository defines a workspace with the given name and allows to specify the BUILD file (or content of BUILD file) directly. Often used for dynamic linking.
Examples for dynamic linking:
new_local_repository( name = "openssl_shared", path = "/usr/lib", build_file = "openssl_host_shared.BUILD" )
new_local_repository(
name = "openssl_shared",
path = "/usr/lib",
build_file_content = """cc_library(
name = "ssl",
hdrs = glob(["thirdparty_build/include/openssl/**/*.h"]),
copts = ["-I/usr/include/openssl"],
linkopts = ["-lcrypto", "-lssl"],
visibility = ["//visibility:public"],
linkstatic = False,
)
"""
)
Overriding repositories
Bazel provides an option --override_repository. That parameter needs to provide the name of repository to override and the full path to the repository containing a Bazel project.
Providing dependency in form of source tree
If you have a source tree of some dependency already fetched and you don't want Bazel to download it, you can just point Bazel to that tree with --override_repository parameter.
openSUSE provides many *-source packages. Let's look i.e. at grpc-source. If your Bazel project requires grpc and normally it would download it with http_archive function, but instead you want to use sources available in openSUSE packaging, you can build it like:
bazel build \
--override_repository="com_github_grpc_grpc=/usr/src/grpc" \
//...
Dynamic linking in Bazel
Dynamic linking of a library can be done by writing a BUILD file like:
cc_library(
name = "gperftools",
hdrs = glob(["thirdparty_build/include/gperftools/**/*.h"]),
copts = ["-I/usr/include/gperftools"],
linkopts = ["-ltcmalloc", "-lprofiler"],
visibility = ["//visibility:public"],
linkstatic = False,
)
Which tells Bazel to:
- look for headers in
/usr/include/gperftools, recursively in all possible subdirectories - link
libtcmalloc.soandlibprofiler.so
There are two potential ways in including that library in a project.
The first way (preferred by us) is to create a project which contains the mentioned BUILD file and a small WORKSPACE file like:
workspace(name = "com_github_gperftools_gperftools")
bazel-workspaces
bazel-workspaces is a git repository which contains Bazel projects for dynamic linking of libraries packaged in (open)SUSE. Each sub directory represents a library.
There is also a package bazel-workspaces available in openSUSE Tumbleweed and CaaSP repositories. After installing it, all projects are available in /usr/share/bazel-workspaces. They can be used as an argument to --override_repository parameter, like i.e.:
bazel build \
--override_repository="com_github_gperftools_gperftools=/usr/share/bazel-workspaces/gperftools" \
//...
Or in rpmspec:
bazel build \
--override_repository="com_github_gperftools_gperftools=%{_datadir}/bazel-workspaces/gperftools" \
//...
Build Requirements
Runtime Requirements
Macros
There are no macros for Bazel yet, but we definitely plan to have them in future. If you want to help, reach out to User:Mrostecki.
Example of spec file
%define sover 0
%define libname lib%{name}_lib%{sover}
Name: bssl_wrapper
Version: 0.12.0
Release: 0
Summary: Library which translates BoringSSL calls to OpenSSL calls
License: Apache-2.0
Group: Development/Libraries/C and C++
Url: https://github.com/Maistra/%{name}
Source: %{name}-%{version}.tar.xz
BuildRequires: bazel
BuildRequires: bazel-rules-cc-source
BuildRequires: bazel-rules-java-source
BuildRequires: gcc-c++
BuildRequires: openssl-devel
ExclusiveArch: aarch64 x86_64 ppc64le
%description
bssl_wrapper is a library which translates BoringSSL calls to OpenSSL calls.
%package -n %{libname}
Summary: Library which translates BoringSSL calls to OpenSSL calls
Group: System/Libraries
%description -n %{libname}
bssl_wrapper is a library which translates BoringSSL calls to OpenSSL calls.
%package devel
Summary: Development files for bssl_wrapper
Group: Development/Libraries/C and C++
Requires: %{libname} = %{version}
%description devel
bssl_wrapper is a library which translates BoringSSL calls to OpenSSL calls.
This package contains development files for bssl_wrapper.
%prep
%setup -q
%build
# TODO(mrostecki): Create a macro in bazel package.
bazel build \
-c dbg \
--color=no \
%(for opt in %{optflags}; do echo -e "--copt=${opt} \c"; done) \
--curses=no \
--distdir=%{_sourcedir} \
--genrule_strategy=standalone \
--host_javabase=@local_jdk//:jdk \
--linkopt="-Wl,-soname,lib%{name}_lib.so.%{sover}" \
--override_repository="rules_cc=/usr/src/bazel-rules-cc" \
--override_repository="rules_java=/usr/src/bazel-rules-java" \
--spawn_strategy=standalone \
--strip=never \
--verbose_failures \
//...
bazel shutdown
%install
install -D -m755 bazel-bin/lib%{name}_lib.so %{buildroot}%{_libdir}/lib%{name}_lib.so.%{sover}
install -D -m644 %{name}/%{name}.h %{buildroot}%{_includedir}/%{name}/%{name}.h
ln -sf libbssl_wrapper_lib.so.%{sover} %{buildroot}%{_libdir}/libbssl_wrapper_lib.so
%post -n %{libname} -p /sbin/ldconfig
%postun -n %{libname} -p /sbin/ldconfig
%files -n %{libname}
%doc README.md
%{_libdir}/lib%{name}_lib.so.%{sover}
%files devel
%{_includedir}/%{name}
%{_includedir}/%{name}/%{name}.h
%{_libdir}/lib%{name}_lib.so
%changelog