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.so
andlibprofiler.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