bazelbuild / rules_foreign_cc

Build rules for interfacing with "foreign" (non-Bazel) build systems (CMake, configure-make, GNU Make, boost, ninja, Meson)
https://bazelbuild.github.io/rules_foreign_cc
Apache License 2.0
649 stars 232 forks source link

OpenSSL 3.0.12 not building using rules_foreign_cc 0.9.0 #1162

Closed Algomorph closed 5 months ago

Algomorph commented 5 months ago

I'm trying to use cpp-httplib in a mediapipe-based project. cpp-httplib requires OpenSSL 3.0 or newer. Mediapipe uses rules_foregn_cc-0.9.0 at the moment, and I would rather not spend cycles on upgrading that right now (and my intuition is that upgrading won't help).

One way to approach this problem is by building a static OpenSSL 3.0.12 (long term release) using rules_foregn_cc-0.9.0. For this, I have switched the openssl http_archive rule in openssl_repositories.bzl to the functional equivalent of the following:

maybe(
    http_archive,
    name = "openssl",
    build_file = Label("//openssl:BUILD.openssl.bazel"),
    sha256 = "f93c9e8edde5e9166119de31755fc87b4aa34863662f67ddfcba14d0b6b69b61",
    strip_prefix = "openssl-3.0.12",
    urls = [
        "https://www.openssl.org/source/openssl-3.0.12.tar.gz",
        "https://github.com/openssl/openssl/releases/download/openssl-3.0.12/openssl-3.0.12.tar.gz",
    ],
)

I have verified that when ("manually") building OpenSSL 3.0.12 on Linux using the same Configure options as specified in the BUILD.openssl.bazel file of rules_foreign_cc-0.9.0, I get a valid libssl.a and libcrypto.a generated in the root directory, just like for OpenSSL 1.1.1k as is used originally in rules_foreign_cc-0.9.0.

However, during the build, I get:

ERROR: /home/greg/.cache/bazel/_bazel_greg/217399706ea15206fcdc8f34c121835f/external/openssl/BUILD.bazel:82:15: output 'external/openssl/openssl/lib/libssl.a' was not created
ERROR: /home/greg/.cache/bazel/_bazel_greg/217399706ea15206fcdc8f34c121835f/external/openssl/BUILD.bazel:82:15: output 'external/openssl/openssl/lib/libcrypto.a' was not created
ERROR: /home/greg/.cache/bazel/_bazel_greg/217399706ea15206fcdc8f34c121835f/external/openssl/BUILD.bazel:82:15: Foreign Cc - Configure: Building openssl failed: not all outputs were created or valid

How can I alter the setup inside the openssl folder to fix this error and successfully be able to link the @openssl target?

Algomorph commented 5 months ago

I figured it out!

The key was that, for OpenSSL 3.0.12, the library sub-directory inside the install path is lib64, not lib as in 1.1.1* versions. Working code for BUILD.openssl.bazel (tuned for OpenSSL 3.X):

"""An openssl build file based on a snippet found in the github issue:
https://github.com/bazelbuild/rules_foreign_cc/issues/337

Note that the $(PERL) "make variable" (https://docs.bazel.build/versions/main/be/make-variables.html)
is populated by the perl toolchain provided by rules_perl.
"""

load("@rules_foreign_cc//foreign_cc:defs.bzl", "configure_make", "configure_make_variant")

# Read https://wiki.openssl.org/index.php/Compilation_and_Installation

filegroup(
    name = "all_srcs",
    srcs = glob(
        include = ["**"],
        exclude = ["*.bazel"],
    ),
)

CONFIGURE_OPTIONS = [
    "no-comp",
    "no-idea",
    "no-weak-ssl-ciphers",
    "no-shared",
]

LIB_NAME = "openssl"

MAKE_TARGETS = [
    "build_libs",
    "install_dev",
]

config_setting(
    name = "msvc_compiler",
    flag_values = {
        "@bazel_tools//tools/cpp:compiler": "msvc-cl",
    },
    visibility = ["//visibility:public"],
)

alias(
    name = "openssl",
    actual = select({
        ":msvc_compiler": "openssl_msvc",
        "//conditions:default": "openssl_default",
    }),
    visibility = ["//visibility:public"],
)

configure_make_variant(
    name = "openssl_msvc",
    build_data = [
        "@nasm//:nasm",
    ],
    configure_command = "Configure",
    configure_in_place = True,
    configure_options = CONFIGURE_OPTIONS + [
        "VC-WIN64A",
        # Unset Microsoft Assembler (MASM) flags set by built-in MSVC toolchain,
        # as NASM is unsed to build OpenSSL rather than MASM
        "ASFLAGS=\" \"",
    ],
    configure_prefix = "$$PERL",
    env = {
        # The Zi flag must be set otherwise OpenSSL fails to build due to missing .pdb files
        "CFLAGS": "-Zi",
        "PATH": "$$(dirname $(execpath @nasm//:nasm)):$$PATH",
        "PERL": "$$EXT_BUILD_ROOT$$/$(PERL)",
    },
    lib_name = LIB_NAME,
    lib_source = ":all_srcs",
    out_static_libs = [
        "libssl.lib",
        "libcrypto.lib",
    ],
    out_lib_dir = "lib64",
    targets = MAKE_TARGETS,
    toolchain = "@rules_foreign_cc//toolchains:preinstalled_nmake_toolchain",
    toolchains = ["@rules_perl//:current_toolchain"],
)

configure_make(
    name = "openssl_default",
    configure_command = "config",
    configure_in_place = True,
    configure_options = CONFIGURE_OPTIONS,
    env = select({
        "@platforms//os:macos": {
            "AR": "",
            "PERL": "$$EXT_BUILD_ROOT$$/$(PERL)",
        },
        "//conditions:default": {
            "PERL": "$$EXT_BUILD_ROOT$$/$(PERL)",
        },
    }),
    lib_name = LIB_NAME,
    lib_source = ":all_srcs",
    # Note that for Linux builds, libssl must come before libcrypto on the linker command-line.
    # As such, libssl must be listed before libcrypto
    out_static_libs = [
        "libssl.a",
        "libcrypto.a",
    ],
    out_lib_dir = "lib64",
    targets = MAKE_TARGETS,
    toolchains = ["@rules_perl//:current_toolchain"],
)

filegroup(
    name = "gen_dir",
    srcs = [":openssl"],
    output_group = "gen_dir",
    visibility = ["//visibility:public"],
)