Bazel for packages with a "bootstrap->configure->make" build?
Asked Answered
G

1

7

I'm experimenting with using libhttpserver and, by extension, libmicrohttpd from inside a Bazel build. The build process for these libraries seems to go:

./bootstrap
mkdir build
cd build
../configure
make

which is a slight variation, that I haven't seen before, on the more classic configure && make workflow.

  • Has anyone managed to make such a library work under Bazel?
  • Does anyone have a public example I can crib from?

The closest thing I've found to supporting this is @rules_foreign_cc//tools/build_defs:configure.bzl#configure_make but that seems to have no concept of the bootstrap step. Even hacking it doesn't seem to work as the bootstrap script ends up failing with:

mkdir: cannot create directory 'tmpwrk23': Read-only file system
autopoint: *** cannot create directory tmpwrk23
autopoint: *** Stop.
autoreconf: autopoint failed with exit status: 1

I'm about ready to just reach for a genrule() but that seems very error prone...

Geraldo answered 3/2, 2020 at 23:15 Comment(4)
It looks like the bootstrap scripts are the same thing that is more conventionally named autogen.sh. These are not particularly unusual, but it is atypical of GNU software that running them should be a part of a normal build. There are in fact issues with that which are quite independent of Bazel. A distribution tarball of one of these packages should come with the configure script and other artifacts produced by bootstrap already present, and generally, these should not be rebuilt locally.Hinduism
But it has become fashionable these days to exclude the configure script, etc from revision control, on the basis that they are generated files (which they are). This is unfortunate, because the process of building the build system is much more sensitive to (Autotools) software versions than is the process of building the actual project. The Autotools themselves aren't even required for building a project from a proper distribution tarball of an Autotools project.Hinduism
Of course, none of that actually answers the question, but I hope it provides some insight. I'm uncertain how applicable it would be to Bazel, but if you can't download a real distribution tarball from somewhere then one possible solution would be to build one outside Bazel (./bootstrap; ./configure; make dist), then use the resulting distribution tarball, without ./bootstrap, for any number of subsequent actual builds.Hinduism
@JohnBollinger that is useful. And it suggests's one option if I want to to stick with pulling from versions control rather than a tarball: run just the bootstrap as a genrule, combine that result with the new_git_repository and then use configure_make on the result. Likely a bit brittle if the set of outputs from bootstrap change, but it's something to think about.Geraldo
I
6

I went down the same path as you and was able to get libhttpserver compiling with bazel using the rules_foreign_cc project after coming across the 6/23/20 update on this blog post. I added code below, but in general rules_foreign_cc has a make rule, which you can set override make_commands and call ./bootstrap.

WORKSPACE:

...
http_archive(
   name = "rules_foreign_cc",
   strip_prefix = "rules_foreign_cc-master",
   url = "https://github.com/bazelbuild/rules_foreign_cc/archive/master.zip",
)
load("@rules_foreign_cc//:workspace_definitions.bzl", "rules_foreign_cc_dependencies")
rules_foreign_cc_dependencies(register_default_tools = True)

all_content = """filegroup(name = "all", srcs = glob(["**"]), visibility = ["//visibility:public"])"""

http_archive(
  name = "rules_cc",
  urls = ["https://github.com/bazelbuild/rules_cc/archive/262ebec3c2296296526740db4aefce68c80de7fa.zip"],
  strip_prefix = "rules_cc-262ebec3c2296296526740db4aefce68c80de7fa",
)

http_archive(
    name = "libgnutls",
    build_file_content = all_content,
    strip_prefix = "gnutls-3.6.15",
    urls = ["https://www.gnupg.org/ftp/gcrypt/gnutls/v3.6/gnutls-3.6.15.tar.xz"],
)    

http_archive(
    name = "libhttpserver",
    build_file_content = all_content,
    strip_prefix = "libhttpserver-master",
    urls = ["https://github.com/etr/libhttpserver/archive/master.zip"],
)

http_archive(
    name = "libmicrohttpd",
    build_file_content = all_content,
    strip_prefix = "libmicrohttpd-0.9.71",
    urls = ["https://ftp.gnu.org/gnu/libmicrohttpd/libmicrohttpd-0.9.71.tar.gz"],
)

BUILD:

load("@rules_foreign_cc//tools/build_defs:configure.bzl", "configure_make")
load("@rules_foreign_cc//tools/build_defs:make.bzl", "make")
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")

package(default_visibility = ["//visibility:public"])

configure_make(
    name = "libgnutls",
    lib_source = "@libgnutls//:all",
    configure_options = ["--with-included-unistring"],
    out_include_dir = "include/gnutls",
    shared_libraries = ["libgnutls.so"],
)

configure_make(
    name = "libmicrohttpd",
    lib_source = "@libmicrohttpd//:all",
    deps = [":libgnutls"],
)

make(
    name = "libhttpserver",
    lib_source = "@libhttpserver//:all",
    make_commands = [
        "./bootstrap",
        "mkdir build_dir",
        "cd build_dir",
        "../configure --prefix=${INSTALLDIR}",
        "make",
        "make install",
    ],
    deps = [":libmicrohttpd", ":libgnutls"],
)

cc_binary(
    name = "hello-world",
    srcs = ["hello_world.cc"],
    deps = [
        ":libhttpserver"
    ],
)

hello_world.cc (example on libhttpserver github page, run "curl -XGET -v http://localhost:8080/hello" to test)

#include <iostream>
#include <httpserver.hpp>

using namespace std;
using namespace httpserver;

class hello_world_resource : public http_resource {
public:
    const std::shared_ptr<http_response> render(const http_request&) {
        return std::shared_ptr<http_response>(new string_response("Hello, World!"));
    }
};

int main(int argc, char** argv) {
    cout << "hello!" << std::endl;
    webserver web_server = create_webserver(8080);

    hello_world_resource resource;
    web_server.register_resource("/hello", &resource);
    web_server.start(true);

    return 0;
}
Ivanivana answered 21/9, 2020 at 23:11 Comment(2)
Nice! ... Is that published anywhere? E.g. GitHub?Geraldo
Added here: github.com/megamegabits/libhttpserver-bazel-example. Thanks for asking, it looks like the code above as-is fails to compile without the added dependency on absl you'll see in the github version. Not sure why right now, but will take a look later.Ivanivana

© 2022 - 2024 — McMap. All rights reserved.