bazelbuild / rules_pkg

Bazel rules for creating packages of many types (zip, tar, deb, rpm, ...)
Apache License 2.0
212 stars 166 forks source link

No practical way to create a package for a cc_binary with runfiles #871

Open armandomontanez opened 1 month ago

armandomontanez commented 1 month ago

Maybe I'm missing something here, but it seems there's no practical way to just cleanly package a cc_binary that requires shared libraries or other runfiles.

This is the most obvious solution:

pkg_zip(
    name = "release_package",
    srcs = ["//:mytool"],
    include_runfiles = True,
)

But then you end up with the following structure:

mytool.exe
mytool.runfiles/mytool.exe
mytool.runfiles/libfoo.dll

The fundamental problem here is that the mytool.exe at the root of the package is broken, since it's just the raw artifact of the cc_binary rule with none of the required runfiles. What I want is a zip file that just contains the contents of the generated runfiles directory. I used Windows extensions here for illustrative purposes (since it's the clearest about file types), but this is a problem on ALL operating systems.

Here's what I've tried:

Strip the runfiles prefix

pkg_files(
    name = "my_tool_runfiles",
    strip_prefix = strip_prefix.from_pkg() + "mytool.runfiles",
    include_runfiles = True,
    srcs = ["//:mytool"],
)

pkg_zip(
    name = "release_package",
    srcs = [":my_tool_runfiles"],
)

This fails because the tool I'm trying to drop can't have its prefix stripped:

Error in fail: Could not strip prefix 'mytool.runfiles' from file <generated file mytool> (@@//:mytool)

Create a shim filegroup

# Just present just_the_runfiles as runfiles.
filegroup(
    name = "just_the_runfiles",
    data = ["//:mytool"],
)

pkg_files(
    name = "my_tool_runfiles",
    strip_prefix = strip_prefix.from_pkg() + "mytool.runfiles",
    include_runfiles = True,
    srcs = [":just_the_runfiles"],
)

pkg_zip(
    name = "release_package",
    srcs = [":my_tool_runfiles"],
)

This doesn't work either; it produces an empty zip file.

Try to explicitly exclude just the binary

filegroup(
    name = "just_the_binary",
    srcs = ["//:mytool"],
)

pkg_files(
    name = "my_tool_runfiles",
    strip_prefix = strip_prefix.from_pkg() + "mytool.runfiles",
    include_runfiles = True,
    excludes = [":just_the_binary"],
    srcs = ["//:mytool"],
)

pkg_zip(
    name = "release_package",
    srcs = [":my_tool_runfiles"],
)

This doesn't work either; it produces an empty zip file.

Try to create an intermediate pkg_files

pkg_files(
    name = "my_tool_runfiles",
    include_runfiles = True,
    srcs = ["//:mytool"],
)

pkg_files(
    name = "tool_bin_wrapper",
    prefix = "bin",
    srcs = [":my_tool_runfiles"],
)

pkg_zip(
    name = "release_package",
    srcs = [":tool_bin_wrapper"],
)

Fails with:

Error in fail: After renames, multiple sources (at least bazel-out/darwin_x86_64-fastbuild/bin/external/libfoo/libfoo.dylib, bazel-out/darwin_x86_64-fastbuild/bin/_solib_darwin_x86_64/_Uexternal_Slibfoo_Usources/libfoo.dylib) map to the same destination.  Consider adjusting strip_prefix and/or renames

I've spent a lot of time messing around with prefixes to try and get that error to go away. No matter what I do, I can't get pkg_files to work if it references another thing that specifies include_runfiles. This means that any hope for renaming/stripping prefixes/excluding files using an intermediate is gone.

filter_directory

This is just fundamentally incompatible:

in src attribute of filter_directory rule //bazel:strip_redundant_binary: '//bazel:bins' must produce a single file
riking commented 5 days ago

Yeah this looks like an outright bug with the newly added include_runfiles feature