-
Notifications
You must be signed in to change notification settings - Fork 92
Add relative RUNPATH entries in haskell_cabal_* targets #1267
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
5164550
Pass -rpath flags to Cabal
aherrmann 8f4ed57
Add a regression test
aherrmann 380880d
Line break _prepare_cabal_inputs parameters.
aherrmann 61792e3
Factor out relative RUNPATH prefix
aherrmann 0a1b977
Simplify test-case comment
aherrmann File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,122 @@ | ||
| load( | ||
| "//tests:inline_tests.bzl", | ||
| "py_inline_test", | ||
| ) | ||
| load("dynamic_libraries.bzl", "dynamic_libraries") | ||
|
|
||
| dynamic_libraries( | ||
| name = "libz", | ||
| srcs = ["@zlib.dev//:zlib"], | ||
| filter = "libz", | ||
| solib_names = "libz_soname", | ||
| tags = ["requires_zlib"], | ||
| ) | ||
|
|
||
| dynamic_libraries( | ||
| name = "libHSzlib", | ||
| srcs = ["@stackage-zlib//:zlib"], | ||
| filter = "libHSz", | ||
| tags = ["requires_zlib"], | ||
| ) | ||
|
|
||
| # Tests that haskell_cabal_library will generate a relative RUNPATH entry for | ||
| # the dependency on the nixpkgs provided libz. Relative meaning an entry that | ||
| # starts with $ORIGIN (Linux) or @loader_path (MacOS). The alternative is an | ||
| # absolute path, which would be wrong for the nixpkgs provided libz, as we want | ||
| # the RUNPATH entry to point to Bazel's _solib_<cpu> directory and its absolute | ||
| # path depends on the output root or execroot. | ||
| # | ||
| # It uses :libz_soname generated above to determine the expected RUNPATH entry | ||
| # for the libz dependency. The :libz_soname file will contain the file names of | ||
| # the libz library files underneath the `_solib_<cpu>` directory. | ||
| # | ||
| # It uses :libHSzlib to access the dynamic library output of | ||
| # haskell_cabal_library and read the RUNPATH entries. | ||
| # | ||
| # Note, ideally we would test that haskell_cabal_library _only_ generates a | ||
| # relative RUNPATH entry and no absolute entries that leak the execroot into | ||
| # the cache. Unfortunately, haskell_cabal_library generates such an entry at | ||
| # the moment. See https://github.com/tweag/rules_haskell/issues/1130. | ||
| py_inline_test( | ||
| name = "stackage_zlib_runpath", | ||
| args = [ | ||
| "$(rootpath :libz_soname)", | ||
| "$(rootpath :libHSzlib)", | ||
| ], | ||
| data = [ | ||
| ":libHSzlib", | ||
| ":libz_soname", | ||
| ], | ||
| script = """\ | ||
| from bazel_tools.tools.python.runfiles import runfiles as bazel_runfiles | ||
| import itertools | ||
| import os | ||
| import platform | ||
| import subprocess | ||
| import sys | ||
| r = bazel_runfiles.Create() | ||
|
|
||
| # Determine libz solib directory | ||
| libz_soname = r.Rlocation(os.path.join( | ||
| os.environ["TEST_WORKSPACE"], | ||
| sys.argv[1], | ||
| )) | ||
| with open(libz_soname) as fh: | ||
| sofile = fh.read().splitlines()[1] | ||
| sodir = os.path.dirname(sofile) | ||
|
|
||
| # Determine libHSzlib RUNPATH | ||
| libHSzlib = r.Rlocation(os.path.join( | ||
| os.environ["TEST_WORKSPACE"], | ||
| sys.argv[2], | ||
| )) | ||
| runpaths = [] | ||
| if platform.system() == "Darwin": | ||
| dynamic_section = iter(subprocess.check_output(["otool", "-l", libHSzlib]).decode().splitlines()) | ||
| # otool produces lines of the form | ||
| # | ||
| # Load command ... | ||
| # cmd LC_RPATH | ||
| # cmdsize ... | ||
| # path ... | ||
| # | ||
| for line in dynamic_section: | ||
| # Find LC_RPATH entry | ||
| if line.find("cmd LC_RPATH") != -1: | ||
| break | ||
| # Skip until path field | ||
| for line in dynamic_section: | ||
| if line.strip().startswith("path"): | ||
| break | ||
| runpaths.append(line.split()[1]) | ||
| else: | ||
| dynamic_section = subprocess.check_output(["objdump", "--private-headers", libHSzlib]).decode().splitlines() | ||
| # objdump produces lines of the form | ||
| # | ||
| # Dynamic Section: | ||
| # ... | ||
| # RUNPATH ... | ||
| # ... | ||
| for line in dynamic_section: | ||
| if not line.strip().startswith("RUNPATH"): | ||
| continue | ||
| runpaths.extend(line.split()[1].split(":")) | ||
|
|
||
| # Check that the binary contains a relative RUNPATH for sodir. | ||
| found = False | ||
| for runpath in runpaths: | ||
| if runpath.find(sodir) == -1: | ||
| continue | ||
| if runpath.startswith("$ORIGIN") or runpath.startswith("@loader_path"): | ||
| found = True | ||
| # XXX: Enable once #1130 is fixed. | ||
| #if os.path.isabs(runpath): | ||
| # print("Absolute RUNPATH entry discovered for %s: %s" % (sodir, runpath)) | ||
| # sys.exit(1) | ||
|
|
||
| if not found: | ||
| print("Did not find a relative RUNPATH entry for %s among %s." % (sodir, runpaths)) | ||
| sys.exit(1) | ||
| """, | ||
| tags = ["requires_zlib"], | ||
| ) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| def _dynamic_libraries_impl(ctx): | ||
| outputs = [] | ||
| solib_names = [] | ||
| for target in ctx.attr.srcs: | ||
| cc_info = target[CcInfo] | ||
| for library_to_link in cc_info.linking_context.libraries_to_link.to_list(): | ||
| library = library_to_link.resolved_symlink_dynamic_library | ||
| if not library or library.basename.find(ctx.attr.filter) == -1: | ||
| continue | ||
| outputs.append(library) | ||
| if library_to_link.dynamic_library: | ||
| solib_names.append(library_to_link.dynamic_library.short_path) | ||
| if ctx.attr.solib_names: | ||
| ctx.actions.write( | ||
| ctx.outputs.solib_names, | ||
| "\n".join(solib_names), | ||
| ) | ||
| return [DefaultInfo( | ||
| files = depset(outputs), | ||
| runfiles = ctx.runfiles(files = outputs), | ||
| )] | ||
|
|
||
| dynamic_libraries = rule( | ||
|
Profpatsch marked this conversation as resolved.
|
||
| _dynamic_libraries_impl, | ||
| attrs = { | ||
| "filter": attr.string( | ||
| doc = "Skip libraries that do not contain this string in their name.", | ||
| ), | ||
| "srcs": attr.label_list( | ||
| doc = "Extract dynamic libraries from these targets", | ||
| providers = [CcInfo], | ||
| ), | ||
| "solib_names": attr.output( | ||
| doc = "Write the `_solib_<cpu>` paths of the dynamic libraries to this file.", | ||
| ), | ||
| }, | ||
| doc = "Extract the dynamic libraries from cc_library targets.", | ||
| ) | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are
solib_namesexported as targets?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's an output attribute that means that it becomes accessible as a label.