rules_pkg icon indicating copy to clipboard operation
rules_pkg copied to clipboard

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

Open armandomontanez opened this issue 1 year ago • 2 comments

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

armandomontanez avatar Jun 04 '24 03:06 armandomontanez

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

riking avatar Jul 03 '24 00:07 riking

This is part of a whole bunch of issues around what packaging with runfiles should do.

aiuto avatar Aug 15 '24 02:08 aiuto

I'm also interested in getting it done. Although it's not a huge problem for us(we're packing such binaries into oci containers, so we might point exactly into correct binary in runfiles) it's wasteful to have redundant binary and it doesn't look like there is a way to remove it from package.

sfc-gh-dbieliaiev avatar Sep 22 '25 13:09 sfc-gh-dbieliaiev