Previously .lai files only had their locations replaced with
placeholders if /usr/bin/file recognized them as ASCII files, which is
only the case on macOS Sierra and above.
Virtualenvs remember the path to the stdlib in a file named
orig_prefix.txt. This file wasn't being relocated because Homebrew skips
files that look like they're intended for human consumption by matching
against the list of metafile extensions. This led to the bug described
in https://github.com/Homebrew/homebrew-core/issues/12869. This fixes
relocation by creating an exception for orig-prefix.txt.
ln_sf does the right thing when `dest` is a symlink pointing to a file:
the symlink gets overwritten with a link pointing to the new src. But
when dest points to a directory, we create a new symlink inside the
folder dest points to, which doesn't help us at all.
When we're assessing whether a bottle is relocatable, we shouldn't have
to descend into symlink paths we encounter. This is supposed to be the
default behavior but it doesn't appear to be (perhaps because we pass a
symlink to the keg on the command line?).
All of the switches that control this behavior differ between BSD and
GNU grep, so sniff the grep flavor first.
Replace relocate_text_files with three methods that clarify intent:
replace_locations_with_placeholders, replace_placeholders_with_locations
and replace_text_in_files, the first two calling the third.
`brew bottle` replaces instances of the Homebrew prefix, cellar, and
repository with placeholders in all text files. Cache these files in
INSTALL_RECEIPT.json so that we don't have to check every single text
file for placeholders on install.
Sometimes `file` output contains data from the file under examination,
which may include binary data that does not represent valid UTF-8
codepoints. String#split dies if it doesn't understand the encoding, so
tell Ruby to treat `file` output as a bytestring.
Now that the default from the installer, our CI and soon all users
is `/usr/local/Homebrew` it's a lot easier to check if there's
references to it (as we cannot look for `/usr/local` as it's a too
commonly hardcoded path).
There's an old bug in `file` which means it can't read certain files under a
non-C locale. This has been fixed upstream for some time, but Apple hasn't
picked that fix up & even on OS X El Capitan the `file` is ancient.
This is currently causing a lot of false positives in our bottle code around
relocating things like manpages translated into non-English languages, because
currently the test does:
```
pn = "/usr/local/Cellar/vim/7.4.2109/share/man/fr/man1/vim.1"
Utils.popen_read("/usr/bin/file", "--brief", pn).include?("text")
```
Which returns `false`. But it isn't returning `false` because the actual result
is false, but because `file` panics & fails, which for us equals a `false`. The
actual output when accessed is:
```
pn = "/usr/local/Cellar/vim/7.4.2109/share/man/fr/man1/vim.1"
Utils.popen_read("/usr/bin/file", "--brief", pn)
"ERROR: line 22: regexec error 17, (illegal byte sequence)\n"
```
Forcing this check to be done under a "C" locale eliminates this particular false
positive for strings we can't relocate & consequently things such as NLS may
prove to be more portable in some formulae than is currently the case.
Using `vim` again for the example:
```
pn = "/usr/local/Cellar/vim/7.4.2109/share/man/fr/man1/vim.1"
Utils.popen_read("/usr/bin/file", "--brief", pn).include?("text")
true
```
This reduces the flagged strings from `vim` from 4 issues to 2, the remaining
two with the `vim` executable itself which "remembers" the full path to perl,
python, ruby, etc during build & vomits that information out when requested
by the user. Both the manpages flagged before this change are no longer flagged
as unrelocatable.
This won't entirely resolve the NLS problem because some things hardcode in
a locale path, which will be stored in the executable, but at the very least it
should reduce the number of false positives & may enable relocation where that
locale path hasn't been burnt in.
- and branch for dylib_id_and_dylibs
- add branches for dylib id changing and change_install_name
- rename MachO module to HomebrewMachO to prevent namespace clashes
with MachO in ruby-macho. this will eventually be replaced entirely
with direct calls to ruby-macho methods
- break ruby-macho implementation out into separate RubyMachO module,
and include either RubyMachO or CctoolsMachO (the original
implementation) based on the HOMEBREW_RUBY_MACHO env var
- move ArchitectureListExtension and RubyMachO into separate files
- create {ruby_,cctools_,,}relocate.rb for isolation of different
methods of mach-o relocation (ruby-macho vs. cctools)
- fill in require_install_name_tool? for ruby_relocate.rb
- rename {ruby_,cctools_,,}relocate.rb to keg, isolate requires in
os/mac
ClosesHomebrew/homebrew#45001.
Signed-off-by: Mike McQuaid <mike@mikemcquaid.com>
When fixing references to regular dylibs, it is sufficient to search for
a file with the same base name, e.g., `libpoppler.56.dylib`. However, if
the broken reference is to a framework, we also have to take into
account preceding path components to find a suitable match. Framework
references (according to the `dyld` man page) come in two flavors:
- `XXX.framework/Versions/YYY/XXX` (with version)
- `XXX.framework/XXX` (without version)
The change here is to detect these patterns and to make sure that the
fixed library reference has the same suffix as the broken one.
Prior to this fix, a broken framework reference (if originating in a
sister framework) to `QtXml.framework/Versions/5/QtXml` would have been
rewritten to `<qt5-keg>/lib/QtXml.framework/QtXml`. In practice, this
mostly works, but is technically incorrect and thus creates problems
like in Homebrew/homebrew#42191. With this fix, the framework reference is correctly
rewritten to `<qt5-keg>/lib/QtXml.framework/Versions/5/QtXml`.
ClosesHomebrew/homebrew#45494.
Signed-off-by: Mike McQuaid <mike@mikemcquaid.com>
When fixing references to regular dylibs, it is sufficient to search for
a file with the same base name, e.g., `libpoppler.56.dylib`. However, if
the broken reference is to a framework, we also have to take into
account preceding path components to find a suitable match. Framework
references (according to the `dyld` man page) come in two flavors:
- `XXX.framework/Versions/YYY/XXX` (with version)
- `XXX.framework/XXX` (without version)
The change here is to detect these patterns and to make sure that the
fixed library reference has the same suffix as the broken one.
Prior to this fix, a broken framework reference (if originating in a
sister framework) to `QtXml.framework/Versions/5/QtXml` would have been
rewritten to `<qt5-keg>/lib/QtXml.framework/QtXml`. In practice, this
mostly works, but is technically incorrect and thus creates problems
like in Homebrew/homebrew#42191. With this fix, the framework reference is correctly
rewritten to `<qt5-keg>/lib/QtXml.framework/Versions/5/QtXml`.
ClosesHomebrew/homebrew#45494.
Signed-off-by: Mike McQuaid <mike@mikemcquaid.com>
dylib install_names are presently rewritten relative to HOMEBREW_PREFIX,
except for keg-only formulas, which are rewritten relative to
opt_prefix.
If we make a formula keg_only, all of its dependents need to be bumped,
since it will no longer exist in HOMEBREW_PREFIX and all of the links
will be written incorrectly.
If we always use opt_prefix, we avoid that dilemma, and make installed
packages more robust if a dependency is `brew unlink`ed.
ClosesHomebrew/homebrew#43518.
Signed-off-by: Dominyk Tiller <dominyktiller@gmail.com>