openSUSE:Packaging Bazel

Jump to: navigation, search


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:

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 and libprofiler.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