mirror of
https://github.com/Homebrew/brew.git
synced 2026-08-12 22:29:27 +04:00
Merge pull request #23369 from Homebrew/change-dylib-id-dsl
Add explicit dylib ID helpers
This commit is contained in:
@@ -2325,6 +2325,29 @@ class Formula
|
||||
end
|
||||
end
|
||||
|
||||
# Changes the dynamic library ID of one Mach-O file and codesigns it on
|
||||
# Apple Silicon. The source and new ID are both explicit. Set
|
||||
# `resolve_source: true` to edit the target of a source symlink.
|
||||
#
|
||||
# ### Examples
|
||||
#
|
||||
# ```ruby
|
||||
# change_dylib_id lib/"libfoo.dylib", opt_lib/"libfoo.dylib"
|
||||
# change_dylib_id lib/"libfoo.dylib", "@rpath/libfoo.1.dylib", resolve_source: true
|
||||
# ```
|
||||
#
|
||||
# @api public
|
||||
sig {
|
||||
params(
|
||||
file: Pathname,
|
||||
id: T.any(String, Pathname),
|
||||
resolve_source: T::Boolean,
|
||||
).void
|
||||
}
|
||||
def change_dylib_id(file, id, resolve_source: false)
|
||||
Homebrew::InstallSteps.change_dylib_id(file, id, resolve_source:)
|
||||
end
|
||||
|
||||
# Replaces a universal binary with its native slice.
|
||||
#
|
||||
# If called with no parameters, does this with all compatible
|
||||
|
||||
@@ -23,6 +23,17 @@ module Homebrew
|
||||
SystemCommandArg = T.type_alias { T.any(String, Pathname) }
|
||||
TemplateTokenValue = T.type_alias { T.any(String, Pathname) }
|
||||
|
||||
sig { params(file: Pathname, id: T.any(String, Pathname), resolve_source: T::Boolean).void }
|
||||
def self.change_dylib_id(file, id, resolve_source: false)
|
||||
file = file.realpath if resolve_source
|
||||
|
||||
require "macho"
|
||||
file.ensure_writable do
|
||||
MachO::Tools.change_dylib_id file, id.to_s
|
||||
MachO.codesign! file if Hardware::CPU.arm?
|
||||
end
|
||||
end
|
||||
|
||||
class DSL
|
||||
((instance_methods + private_instance_methods) -
|
||||
(BasicObject.instance_methods + BasicObject.private_instance_methods) -
|
||||
@@ -540,6 +551,21 @@ module Homebrew
|
||||
"non_recursive" => !recursive)
|
||||
end
|
||||
|
||||
sig {
|
||||
params(
|
||||
source: ::T.any(::String, ::Pathname),
|
||||
id: ::T.any(::String, ::Pathname),
|
||||
base: ::T.nilable(::T.any(::String, ::Symbol)),
|
||||
resolve_source: ::T::Boolean,
|
||||
).void
|
||||
}
|
||||
def change_dylib_id(source, id, base: nil, resolve_source: false)
|
||||
add_step("change_dylib_id",
|
||||
"source" => path_spec(source, base:, default_base: @default_source_base),
|
||||
"id" => id.to_s,
|
||||
"resolve_source" => resolve_source)
|
||||
end
|
||||
|
||||
sig {
|
||||
params(
|
||||
command: ::T.any(::String, ::Pathname),
|
||||
@@ -872,6 +898,12 @@ module Homebrew
|
||||
run_serialised_command(step)
|
||||
when "terminate_process"
|
||||
run_terminate_process(step)
|
||||
when "change_dylib_id"
|
||||
Homebrew::InstallSteps.change_dylib_id(
|
||||
resolve_path(step_path(step, "source")),
|
||||
expand_template_tokens(step_string(step, "id")),
|
||||
resolve_source: step["resolve_source"] == true,
|
||||
)
|
||||
when "warn"
|
||||
opoo expand_template_tokens(step_string(step, "message"))
|
||||
when "configure_gcc_runtime"
|
||||
|
||||
@@ -33,6 +33,7 @@ module RuboCop
|
||||
"depends_on" => "formula.rb",
|
||||
"deprecated_option" => "formula.rb",
|
||||
"desc" => "formula.rb",
|
||||
"change_dylib_id" => "formula.rb",
|
||||
"env_script_all_files" => "extend/pathname.rb",
|
||||
"fails_with" => "formula.rb",
|
||||
"post_install_steps" => "formula.rb",
|
||||
|
||||
@@ -16,6 +16,7 @@ module RuboCop
|
||||
KEYCHAIN_STEP_METHODS = [:delete_keychain_certificate].freeze
|
||||
PERMISSION_STEP_METHODS = [:set_permissions, :set_ownership].freeze
|
||||
COMMAND_STEP_METHODS = [:run, :terminate_process].freeze
|
||||
MACHO_STEP_METHODS = [:change_dylib_id].freeze
|
||||
NOTICE_STEP_METHODS = [:warn].freeze
|
||||
FORMULA_ACTION_STEP_METHODS =
|
||||
[:configure_gcc_runtime, :install_gzipped_executable, :configure_glibc_runtime,
|
||||
@@ -24,12 +25,12 @@ module RuboCop
|
||||
ALLOWED_STEP_METHODS = T.let(
|
||||
[*FILE_PREPARATION_STEP_METHODS, *LINK_STEP_METHODS, *CONFIG_WRITE_STEP_METHODS, *SERVICE_DATA_STEP_METHODS,
|
||||
*REBUILD_ACTION_STEP_METHODS, :set_permissions, *COMMAND_STEP_METHODS, *NOTICE_STEP_METHODS,
|
||||
*FORMULA_ACTION_STEP_METHODS, *STEP_SCOPE_METHODS].freeze,
|
||||
*MACHO_STEP_METHODS, *FORMULA_ACTION_STEP_METHODS, *STEP_SCOPE_METHODS].freeze,
|
||||
T::Array[Symbol],
|
||||
)
|
||||
CASK_ALLOWED_STEP_METHODS = T.let(
|
||||
[*FILE_PREPARATION_STEP_METHODS, *CONFIG_WRITE_STEP_METHODS, *KEYCHAIN_STEP_METHODS,
|
||||
*PERMISSION_STEP_METHODS, *COMMAND_STEP_METHODS, *STEP_SCOPE_METHODS].freeze,
|
||||
*PERMISSION_STEP_METHODS, *COMMAND_STEP_METHODS, *MACHO_STEP_METHODS, *STEP_SCOPE_METHODS].freeze,
|
||||
T::Array[Symbol],
|
||||
)
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
require "install_steps"
|
||||
require "cask/quarantine"
|
||||
require "macho"
|
||||
|
||||
RSpec.describe Homebrew::InstallSteps do
|
||||
let(:root) { Pathname(TEST_TMPDIR)/"install-steps" }
|
||||
@@ -31,6 +32,22 @@ RSpec.describe Homebrew::InstallSteps do
|
||||
end
|
||||
end
|
||||
|
||||
specify "changes the resolved dylib ID and restores its mode" do
|
||||
dylib = root/"lib/libfoo.1.dylib"
|
||||
source = root/"lib/libfoo.dylib"
|
||||
dylib.dirname.mkpath
|
||||
dylib.write "Mach-O"
|
||||
dylib.chmod 0444
|
||||
FileUtils.ln_s dylib, source
|
||||
allow(Hardware::CPU).to receive(:arm?).and_return(true)
|
||||
expect(MachO::Tools).to receive(:change_dylib_id).with(dylib, "@rpath/libfoo.1.dylib")
|
||||
expect(MachO).to receive(:codesign!).with(dylib)
|
||||
|
||||
described_class.change_dylib_id source, "@rpath/libfoo.1.dylib", resolve_source: true
|
||||
|
||||
expect(dylib.stat.mode & 0777).to eq(0444)
|
||||
end
|
||||
|
||||
specify "runs mkdir, touch, move and symlink steps", :aggregate_failures do
|
||||
steps = Homebrew::InstallSteps::DSL.build(default_base: :var, default_source_base: :staged_path,
|
||||
default_target_base: :staged_path) do
|
||||
@@ -52,6 +69,20 @@ RSpec.describe Homebrew::InstallSteps do
|
||||
expect((root/"stage/linked-target").readlink).to eq(Pathname("move-target"))
|
||||
end
|
||||
|
||||
specify "changes an explicit Mach-O dylib ID" do
|
||||
steps = Homebrew::InstallSteps::DSL.build(default_source_base: :prefix) do
|
||||
on_macos do
|
||||
change_dylib_id "lib/libfoo.dylib", "{{HOMEBREW_PREFIX}}/opt/foo/lib/libfoo.1.dylib",
|
||||
resolve_source: true
|
||||
end
|
||||
end
|
||||
allow(Homebrew::SimulateSystem).to receive(:simulating_or_running_on_macos?).and_return(true)
|
||||
expect(described_class).to receive(:change_dylib_id)
|
||||
.with(root/"prefix/lib/libfoo.dylib", "#{HOMEBREW_PREFIX}/opt/foo/lib/libfoo.1.dylib", resolve_source: true)
|
||||
|
||||
Homebrew::InstallSteps::Runner.new(context:).run(steps)
|
||||
end
|
||||
|
||||
specify "links every source matched by a glob into a directory", :aggregate_failures do
|
||||
steps = Homebrew::InstallSteps::DSL.build(default_source_base: :prefix,
|
||||
default_target_base: :prefix) do
|
||||
|
||||
@@ -5,6 +5,41 @@ require "test/support/fixtures/testball"
|
||||
require "formula"
|
||||
|
||||
RSpec.describe Formula do
|
||||
describe "#change_dylib_id" do
|
||||
subject(:f) do
|
||||
formula "dylib-id-test" do
|
||||
url "foo-1.0"
|
||||
end
|
||||
end
|
||||
|
||||
let(:dylib) { f.lib/"libfoo.1.dylib" }
|
||||
|
||||
before do
|
||||
dylib.dirname.mkpath
|
||||
FileUtils.touch dylib
|
||||
end
|
||||
|
||||
after { f.prefix.rmtree }
|
||||
|
||||
it "uses the explicit source and dylib ID" do
|
||||
unversioned_dylib = f.lib/"libfoo.dylib"
|
||||
FileUtils.ln_s dylib, unversioned_dylib
|
||||
expect(Homebrew::InstallSteps).to receive(:change_dylib_id)
|
||||
.with(unversioned_dylib, f.opt_lib/"libfoo.dylib", resolve_source: false)
|
||||
|
||||
f.change_dylib_id unversioned_dylib, f.opt_lib/"libfoo.dylib"
|
||||
end
|
||||
|
||||
it "can resolve the source symlink and codesigns on ARM" do
|
||||
unversioned_dylib = f.lib/"libfoo.dylib"
|
||||
FileUtils.ln_s dylib, unversioned_dylib
|
||||
expect(Homebrew::InstallSteps).to receive(:change_dylib_id)
|
||||
.with(unversioned_dylib, "@rpath/libfoo.dylib", resolve_source: true)
|
||||
|
||||
f.change_dylib_id unversioned_dylib, "@rpath/libfoo.dylib", resolve_source: true
|
||||
end
|
||||
end
|
||||
|
||||
describe "#uses_from_macos" do
|
||||
before do
|
||||
allow(OS).to receive(:mac?).and_return(true)
|
||||
|
||||
@@ -30,7 +30,7 @@ RSpec.describe RuboCop::Cop::Cask::InstallSteps, :config do
|
||||
|
||||
preflight_steps do
|
||||
system "true"
|
||||
^^^^^^^^^^^^^ Steps blocks may only contain install step DSL calls: `mkdir`, `mkdir_p`, `touch`, `move`, `mv`, `move_children`, `move_contents`, `copy`, `remove`, `inreplace`, `symlink`, `ln_s`, `ln_sf`, `write`, `delete_keychain_certificate`, `set_permissions`, `set_ownership`, `run`, `terminate_process`, `if_path_exists`, `unless_path_exists`, `on_macos`, `on_linux`.
|
||||
^^^^^^^^^^^^^ Steps blocks may only contain install step DSL calls: `mkdir`, `mkdir_p`, `touch`, `move`, `mv`, `move_children`, `move_contents`, `copy`, `remove`, `inreplace`, `symlink`, `ln_s`, `ln_sf`, `write`, `delete_keychain_certificate`, `set_permissions`, `set_ownership`, `run`, `terminate_process`, `change_dylib_id`, `if_path_exists`, `unless_path_exists`, `on_macos`, `on_linux`.
|
||||
end
|
||||
end
|
||||
CASK
|
||||
@@ -44,7 +44,7 @@ RSpec.describe RuboCop::Cop::Cask::InstallSteps, :config do
|
||||
|
||||
preflight_steps do
|
||||
update_desktop_database
|
||||
^^^^^^^^^^^^^^^^^^^^^^^ Steps blocks may only contain install step DSL calls: `mkdir`, `mkdir_p`, `touch`, `move`, `mv`, `move_children`, `move_contents`, `copy`, `remove`, `inreplace`, `symlink`, `ln_s`, `ln_sf`, `write`, `delete_keychain_certificate`, `set_permissions`, `set_ownership`, `run`, `terminate_process`, `if_path_exists`, `unless_path_exists`, `on_macos`, `on_linux`.
|
||||
^^^^^^^^^^^^^^^^^^^^^^^ Steps blocks may only contain install step DSL calls: `mkdir`, `mkdir_p`, `touch`, `move`, `mv`, `move_children`, `move_contents`, `copy`, `remove`, `inreplace`, `symlink`, `ln_s`, `ln_sf`, `write`, `delete_keychain_certificate`, `set_permissions`, `set_ownership`, `run`, `terminate_process`, `change_dylib_id`, `if_path_exists`, `unless_path_exists`, `on_macos`, `on_linux`.
|
||||
end
|
||||
end
|
||||
CASK
|
||||
@@ -70,6 +70,7 @@ RSpec.describe RuboCop::Cop::Cask::InstallSteps, :config do
|
||||
set_ownership "Foo.app", user: "root", group: "wheel"
|
||||
run "foo", args: ["--repair"]
|
||||
terminate_process "foo", attempts: 3
|
||||
change_dylib_id "Foo.app/Contents/Frameworks/libfoo.dylib", "@rpath/libfoo.dylib"
|
||||
delete_keychain_certificate "Charles"
|
||||
delete_keychain_certificate "NodeMITMProxyCA", matching_certificate: "~/Library/Application Support/betwixt/ssl/certs/ca.pem"
|
||||
on_macos do
|
||||
@@ -95,7 +96,7 @@ RSpec.describe RuboCop::Cop::Cask::InstallSteps, :config do
|
||||
|
||||
preflight_steps do
|
||||
touch "#{appdir}/state"
|
||||
^^^^^^^^^ Steps blocks may only contain install step DSL calls: `mkdir`, `mkdir_p`, `touch`, `move`, `mv`, `move_children`, `move_contents`, `copy`, `remove`, `inreplace`, `symlink`, `ln_s`, `ln_sf`, `write`, `delete_keychain_certificate`, `set_permissions`, `set_ownership`, `run`, `terminate_process`, `if_path_exists`, `unless_path_exists`, `on_macos`, `on_linux`.
|
||||
^^^^^^^^^ Steps blocks may only contain install step DSL calls: `mkdir`, `mkdir_p`, `touch`, `move`, `mv`, `move_children`, `move_contents`, `copy`, `remove`, `inreplace`, `symlink`, `ln_s`, `ln_sf`, `write`, `delete_keychain_certificate`, `set_permissions`, `set_ownership`, `run`, `terminate_process`, `change_dylib_id`, `if_path_exists`, `unless_path_exists`, `on_macos`, `on_linux`.
|
||||
end
|
||||
end
|
||||
CASK
|
||||
@@ -110,7 +111,7 @@ RSpec.describe RuboCop::Cop::Cask::InstallSteps, :config do
|
||||
preflight_steps do
|
||||
on_macos do
|
||||
system "true"
|
||||
^^^^^^^^^^^^^ Steps blocks may only contain install step DSL calls: `mkdir`, `mkdir_p`, `touch`, `move`, `mv`, `move_children`, `move_contents`, `copy`, `remove`, `inreplace`, `symlink`, `ln_s`, `ln_sf`, `write`, `delete_keychain_certificate`, `set_permissions`, `set_ownership`, `run`, `terminate_process`, `if_path_exists`, `unless_path_exists`, `on_macos`, `on_linux`.
|
||||
^^^^^^^^^^^^^ Steps blocks may only contain install step DSL calls: `mkdir`, `mkdir_p`, `touch`, `move`, `mv`, `move_children`, `move_contents`, `copy`, `remove`, `inreplace`, `symlink`, `ln_s`, `ln_sf`, `write`, `delete_keychain_certificate`, `set_permissions`, `set_ownership`, `run`, `terminate_process`, `change_dylib_id`, `if_path_exists`, `unless_path_exists`, `on_macos`, `on_linux`.
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -41,7 +41,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::InstallSteps do
|
||||
|
||||
post_install_steps do
|
||||
system "true"
|
||||
^^^^^^^^^^^^^ FormulaAudit/InstallSteps: Steps blocks may only contain install step DSL calls: `mkdir`, `mkdir_p`, `touch`, `move`, `mv`, `move_children`, `move_contents`, `copy`, `remove`, `inreplace`, `symlink`, `ln_s`, `ln_sf`, `link_dir`, `link_children`, `write`, `init_data_dir`, `compile_gsettings_schemas`, `gio_querymodules`, `gdk_pixbuf_query_loaders`, `gtk_update_icon_cache`, `update_mime_database`, `update_desktop_database`, `set_permissions`, `run`, `terminate_process`, `warn`, `configure_gcc_runtime`, `install_gzipped_executable`, `configure_glibc_runtime`, `configure_clang_system`, `if_path_exists`, `unless_path_exists`, `on_macos`, `on_linux`.
|
||||
^^^^^^^^^^^^^ FormulaAudit/InstallSteps: Steps blocks may only contain install step DSL calls: `mkdir`, `mkdir_p`, `touch`, `move`, `mv`, `move_children`, `move_contents`, `copy`, `remove`, `inreplace`, `symlink`, `ln_s`, `ln_sf`, `link_dir`, `link_children`, `write`, `init_data_dir`, `compile_gsettings_schemas`, `gio_querymodules`, `gdk_pixbuf_query_loaders`, `gtk_update_icon_cache`, `update_mime_database`, `update_desktop_database`, `set_permissions`, `run`, `terminate_process`, `warn`, `change_dylib_id`, `configure_gcc_runtime`, `install_gzipped_executable`, `configure_glibc_runtime`, `configure_clang_system`, `if_path_exists`, `unless_path_exists`, `on_macos`, `on_linux`.
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
@@ -66,6 +66,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::InstallSteps do
|
||||
set_permissions "foo", "0755"
|
||||
run "foo", args: ["--repair"]
|
||||
terminate_process "foo", attempts: 3
|
||||
change_dylib_id "lib/libfoo.dylib", "{{opt_prefix}}/lib/libfoo.1.dylib", resolve_source: true
|
||||
warn "foo exists"
|
||||
configure_gcc_runtime
|
||||
install_gzipped_executable "compressed.gz", "bin/executable"
|
||||
@@ -106,7 +107,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::InstallSteps do
|
||||
post_install_steps do
|
||||
on_macos do
|
||||
system "true"
|
||||
^^^^^^^^^^^^^ FormulaAudit/InstallSteps: Steps blocks may only contain install step DSL calls: `mkdir`, `mkdir_p`, `touch`, `move`, `mv`, `move_children`, `move_contents`, `copy`, `remove`, `inreplace`, `symlink`, `ln_s`, `ln_sf`, `link_dir`, `link_children`, `write`, `init_data_dir`, `compile_gsettings_schemas`, `gio_querymodules`, `gdk_pixbuf_query_loaders`, `gtk_update_icon_cache`, `update_mime_database`, `update_desktop_database`, `set_permissions`, `run`, `terminate_process`, `warn`, `configure_gcc_runtime`, `install_gzipped_executable`, `configure_glibc_runtime`, `configure_clang_system`, `if_path_exists`, `unless_path_exists`, `on_macos`, `on_linux`.
|
||||
^^^^^^^^^^^^^ FormulaAudit/InstallSteps: Steps blocks may only contain install step DSL calls: `mkdir`, `mkdir_p`, `touch`, `move`, `mv`, `move_children`, `move_contents`, `copy`, `remove`, `inreplace`, `symlink`, `ln_s`, `ln_sf`, `link_dir`, `link_children`, `write`, `init_data_dir`, `compile_gsettings_schemas`, `gio_querymodules`, `gdk_pixbuf_query_loaders`, `gtk_update_icon_cache`, `update_mime_database`, `update_desktop_database`, `set_permissions`, `run`, `terminate_process`, `warn`, `change_dylib_id`, `configure_gcc_runtime`, `install_gzipped_executable`, `configure_glibc_runtime`, `configure_clang_system`, `if_path_exists`, `unless_path_exists`, `on_macos`, `on_linux`.
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -120,7 +121,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::InstallSteps do
|
||||
|
||||
post_install_steps do
|
||||
write "foo.conf", "prefix = #{prefix}"
|
||||
^^^^^^^^^ FormulaAudit/InstallSteps: Steps blocks may only contain install step DSL calls: `mkdir`, `mkdir_p`, `touch`, `move`, `mv`, `move_children`, `move_contents`, `copy`, `remove`, `inreplace`, `symlink`, `ln_s`, `ln_sf`, `link_dir`, `link_children`, `write`, `init_data_dir`, `compile_gsettings_schemas`, `gio_querymodules`, `gdk_pixbuf_query_loaders`, `gtk_update_icon_cache`, `update_mime_database`, `update_desktop_database`, `set_permissions`, `run`, `terminate_process`, `warn`, `configure_gcc_runtime`, `install_gzipped_executable`, `configure_glibc_runtime`, `configure_clang_system`, `if_path_exists`, `unless_path_exists`, `on_macos`, `on_linux`.
|
||||
^^^^^^^^^ FormulaAudit/InstallSteps: Steps blocks may only contain install step DSL calls: `mkdir`, `mkdir_p`, `touch`, `move`, `mv`, `move_children`, `move_contents`, `copy`, `remove`, `inreplace`, `symlink`, `ln_s`, `ln_sf`, `link_dir`, `link_children`, `write`, `init_data_dir`, `compile_gsettings_schemas`, `gio_querymodules`, `gdk_pixbuf_query_loaders`, `gtk_update_icon_cache`, `update_mime_database`, `update_desktop_database`, `set_permissions`, `run`, `terminate_process`, `warn`, `change_dylib_id`, `configure_gcc_runtime`, `install_gzipped_executable`, `configure_glibc_runtime`, `configure_clang_system`, `if_path_exists`, `unless_path_exists`, `on_macos`, `on_linux`.
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
|
||||
@@ -665,6 +665,7 @@ Relative paths default to `staged_path` for `base:`, `source_base:` and `target_
|
||||
* `set_ownership`: recursively change existing path ownership with `sudo chown`; example: `set_ownership "Shared/payload", user: "root", group: "wheel"`. Missing paths are ignored. When `user:` is omitted, the current user is used. When `group:` is omitted, `staff` is used.
|
||||
* `run`: run one executable with literal arguments; example: `run "Example.app/Contents/MacOS/helper", args: ["--repair"], base: :appdir`.
|
||||
* `terminate_process`: terminate a process by name; example: `terminate_process "Example", attempts: 3, must_succeed: false`. `attempts:` sets the total number of attempts and defaults to one. The step also supports `match: :full`, `notices:` shown before the first attempt and a `failure_message:` warning.
|
||||
* `change_dylib_id`: change one Mach-O dynamic library ID; pass the complete source and new ID, use `resolve_source: true` for a source symlink and wrap the step in `on_macos`.
|
||||
|
||||
Use `if_path_exists` and `unless_path_exists` blocks to guard one or more steps by a path, and `on_macos` and `on_linux` blocks for platform-specific steps. Each guard is evaluated once for its whole block. `copy`, `move` and symlink steps accept `source_glob: true`; path collections used by `remove`, `set_permissions` and `set_ownership` expand globs automatically. Symlink removal can additionally match the serialised source during uninstall, while `remove` can restrict removal with `symlink_target_contains:` or `content_contains:`.
|
||||
|
||||
|
||||
@@ -250,6 +250,22 @@ $ otool -L /opt/homebrew/bin/ldapvi
|
||||
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1213.0.0)
|
||||
```
|
||||
|
||||
### Changing a dynamic library ID
|
||||
|
||||
Use [`change_dylib_id`](/rubydoc/Formula.html#change_dylib_id-instance_method)
|
||||
inside `install` or `post_install` when one Mach-O dynamic library needs a
|
||||
non-standard ID. Both the source and its complete new ID are explicit. Set
|
||||
`resolve_source: true` when the source is a symlink and its target should be
|
||||
edited. For example:
|
||||
|
||||
```ruby
|
||||
change_dylib_id lib/"libfoo.dylib", opt_lib/"libfoo.dylib"
|
||||
change_dylib_id lib/"libfoo.dylib", "@rpath/libfoo.1.dylib", resolve_source: true
|
||||
```
|
||||
|
||||
The helper preserves the file's permissions and codesigns the modified library
|
||||
on Apple Silicon.
|
||||
|
||||
### Specifying macOS components as dependencies
|
||||
|
||||
If a formula dependency is required on all platforms but can be handled by a component that ships with macOS, specify it with [`uses_from_macos`](/rubydoc/Formula.html#uses_from_macos-class_method). On Linux it acts like [`depends_on`](/rubydoc/Formula.html#depends_on-class_method), while on macOS it's ignored unless the host system is older than the optional `since:` parameter.
|
||||
@@ -1090,6 +1106,7 @@ represented by structured steps.
|
||||
* `ln_s`: alias for `symlink`; example: `ln_s "cert.pem", "foo/cert.pem", source_base: :relative`.
|
||||
* `ln_sf`: create or replace a symlink; example: `ln_sf "cert.pem", "foo/cert.pem", source_base: :relative`.
|
||||
* `set_permissions`: change existing path permissions; example: `set_permissions "foo", "0755"`.
|
||||
* `change_dylib_id`: change one Mach-O dynamic library ID; pass the complete source and new ID, use `resolve_source: true` for a source symlink and wrap the step in `on_macos`.
|
||||
|
||||
Use `if_path_exists` and `unless_path_exists` blocks to guard one or more steps by a path, and `on_macos` and `on_linux` blocks for platform-specific steps. Each guard is evaluated once for its whole block. `copy`, `move` and symlink steps accept `source_glob: true`; path collections used by `remove` and `set_permissions` expand globs automatically. Removals may additionally be restricted with `symlink_target_contains:` or `content_contains:`.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user