bazel-contrib / toolchains_llvm

LLVM toolchain for bazel
Apache License 2.0
291 stars 209 forks source link

Impossible to use `llvm-ar` on macOS (maybe?) #360

Closed ParkMyCar closed 1 month ago

ParkMyCar commented 1 month ago

Hey folks! I'm trying to build openssl 3.3.1 using Bazel with configure_make from rules_foreign_cc and llvm_toolchain. The default archiver on darwin/macOS is libtool but I wanted to use llvm-ar to try avoiding an undefined symbol issue like the one referenced here. It seems like toolchains_llvm unconditionally sets the -static flag in archive_flags on darwin, which is not a supported flag for llvm-ar, making llvm-ar unusable?

I set the llvm-ar to be the archiver via the AR environment variable, e.g.

configure_make(
    name = "openssl",
    // ...
    build_data = select({
        "@platforms//os:macos": ["@llvm_toolchain_llvm//:ar"],
        "//conditions:default": {},
    }),
    env = select({
        "@platforms//os:macos": {"AR": "$(execpath @llvm_toolchain_llvm//:ar)"},
        "//conditions:default": {},
    }),

    // ...
)

The problem is llvm_toolchain seems to always include the -static flag in archive_flags but -static is not an argument llvm-ar recognizes. This leads to an error like:

/private/var/tmp/_bazel_parker.timmerman/497be8b2783f71dbb03155dd9130f54f/sandbox/darwin-sandbox/2694/execroot/_main/external/llvm_toolchain_llvm/bin/llvm-ar: error: only one operation may be specified
OVERVIEW: LLVM Archiver

USAGE: llvm-ar [options] [-]<operation>[modifiers] [relpos] [count] <archive> [files]
       llvm-ar -M [<mri-script]

OPTIONS:
  --format              - archive format to create
    =default            -   default
    =gnu                -   gnu
    =darwin             -   darwin
    =bsd                -   bsd
    =bigarchive         -   big archive (AIX OS)
  --plugin=<string>     - ignored for compatibility
  -h --help             - display this help and exit
  --output              - the directory to extract archive members to
  --rsp-quoting         - quoting style for response files
    =posix              -   posix
    =windows            -   windows
  --thin                - create a thin archive
  --version             - print the version and exit
  -X{32|64|32_64|any}   - object mode (only for AIX OS)
  @<file>               - read options from <file>

OPERATIONS:
  d - delete [files] from the archive
  m - move [files] in the archive
  p - print contents of [files] found in the archive
  q - quick append [files] to the archive
  r - replace or insert [files] into the archive
  s - act as ranlib
  t - display list of files in archive
  x - extract [files] from the archive

MODIFIERS:
  [a] - put [files] after [relpos]
  [b] - put [files] before [relpos] (same as [i])
  [c] - do not warn if archive had to be created
  [D] - use zero for timestamps and uids/gids (default)
  [h] - display this help and exit
  [i] - put [files] before [relpos] (same as [b])
  [l] - ignored for compatibility
  [L] - add archive's contents
  [N] - use instance [count] of name
  [o] - preserve original dates
  [O] - display member offsets
  [P] - use full names when matching (implied for thin archives)
  [s] - create an archive index (cf. ranlib)
  [S] - do not build a symbol table
  [T] - deprecated, use --thin instead
  [u] - update only [files] newer than archive contents
  [U] - use actual timestamps and uids/gids
  [v] - be verbose about actions taken
  [V] - display the version and exit
/private/var/tmp/_bazel_parker.timmerman/497be8b2783f71dbb03155dd9130f54f/sandbox/darwin-sandbox/2694/execroot/_main/external/llvm_toolchain_llvm/bin/llvm-ar: error: only one operation may be specified
OVERVIEW: LLVM Archiver

Indeed if we enable verbose errors we can see the invocation of llvm-ar includes the -static flag:

/private/var/tmp/_bazel_parker.timmerman/497be8b2783f71dbb03155dd9130f54f/sandbox/darwin-sandbox/2694/execroot/_main/external/llvm_toolchain_llvm/bin/llvm-ar -static apps/libapps.a apps/lib/libapps-lib-app_libctx.o apps/lib/libapps-lib-app_params.o apps/lib/libapps-lib-app_provider.o apps/lib/libapps-lib-app_rand.o apps/lib/libapps-lib-app_x509.o apps/lib/libapps-lib-apps.o apps/lib/libapps-lib-apps_opt_printf.o apps/lib/libapps-lib-apps_ui.o apps/lib/libapps-lib-columns.o apps/lib/libapps-lib-engine.o apps/lib/libapps-lib-engine_loader.o apps/lib/libapps-lib-fmt.o apps/lib/libapps-lib-http_server.o apps/lib/libapps-lib-log.o apps/lib/libapps-lib-names.o apps/lib/libapps-lib-opt.o apps/lib/libapps-lib-s_cb.o apps/lib/libapps-lib-s_socket.o apps/lib/libapps-lib-tlssrp_depr.o

FWIW the build rule works fine on Linux distributions, it only fails on macOS

ParkMyCar commented 1 month ago

Nevermind I'm just a Bazel noob! I was able to override the ARFLAGS via configure_options, e.g.

configure_make(

   // ...

   configure_options = CONFIGURE_OPTIONS + select({
        "@platforms//os:macos": ["ARFLAGS=r"],
        "//conditions:default": [],
    }),

    // ...
)

Note: Initially I tried overriding the ARFLAGS via the env field but that didn't work, it was setting them via configure_options that did the trick.