2019-04-19 15:38:03 +09:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2014-05-03 10:01:30 -05:00
|
|
|
# This script is loaded by formula_installer as a separate instance.
|
2015-04-13 17:53:02 +08:00
|
|
|
# Thrown exceptions are propagated back to the parent process over a pipe
|
2011-03-15 22:02:14 -07:00
|
|
|
|
2014-08-26 22:06:43 -05:00
|
|
|
old_trap = trap("INT") { exit! 130 }
|
2012-08-22 15:50:27 -04:00
|
|
|
|
2014-08-26 22:06:43 -05:00
|
|
|
require "global"
|
2014-08-27 17:25:13 -05:00
|
|
|
require "build_options"
|
2014-08-26 22:06:43 -05:00
|
|
|
require "cxxstdlib"
|
|
|
|
require "keg"
|
|
|
|
require "extend/ENV"
|
2014-09-18 14:16:07 -05:00
|
|
|
require "debrew"
|
2014-08-26 22:06:43 -05:00
|
|
|
require "fcntl"
|
2015-04-08 14:15:38 +08:00
|
|
|
require "socket"
|
2020-02-11 23:47:15 +05:30
|
|
|
require "cmd/install"
|
2009-09-04 15:28:18 +01:00
|
|
|
|
2013-05-25 15:26:55 -05:00
|
|
|
class Build
|
2014-08-27 17:25:13 -05:00
|
|
|
attr_reader :formula, :deps, :reqs
|
2012-09-13 09:06:37 -04:00
|
|
|
|
2014-08-27 17:25:13 -05:00
|
|
|
def initialize(formula, options)
|
2014-08-27 17:25:13 -05:00
|
|
|
@formula = formula
|
2014-08-27 17:25:13 -05:00
|
|
|
@formula.build = BuildOptions.new(options, formula.options)
|
2014-03-03 23:47:00 -06:00
|
|
|
|
2020-03-15 19:05:09 +05:30
|
|
|
if Homebrew.args.ignore_deps?
|
2014-03-03 23:47:00 -06:00
|
|
|
@deps = []
|
|
|
|
@reqs = []
|
|
|
|
else
|
|
|
|
@deps = expand_deps
|
|
|
|
@reqs = expand_reqs
|
|
|
|
end
|
2013-05-25 15:26:55 -05:00
|
|
|
end
|
2012-08-28 13:46:29 -04:00
|
|
|
|
2013-05-25 15:26:55 -05:00
|
|
|
def post_superenv_hacks
|
|
|
|
# Only allow Homebrew-approved directories into the PATH, unless
|
|
|
|
# a formula opts-in to allowing the user's path.
|
2016-09-22 20:12:28 +02:00
|
|
|
return unless formula.env.userpaths? || reqs.any? { |rq| rq.env.userpaths? }
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2016-09-22 20:12:28 +02:00
|
|
|
ENV.userpaths!
|
2013-05-25 15:26:55 -05:00
|
|
|
end
|
2012-06-08 04:09:29 +02:00
|
|
|
|
2014-08-24 14:46:34 -05:00
|
|
|
def effective_build_options_for(dependent)
|
|
|
|
args = dependent.build.used_options
|
|
|
|
args |= Tab.for_formula(dependent).used_options
|
|
|
|
BuildOptions.new(args, dependent.options)
|
|
|
|
end
|
|
|
|
|
2013-06-03 15:08:47 -05:00
|
|
|
def expand_reqs
|
2014-08-27 17:25:13 -05:00
|
|
|
formula.recursive_requirements do |dependent, req|
|
2014-08-24 14:46:34 -05:00
|
|
|
build = effective_build_options_for(dependent)
|
2018-03-24 16:55:16 +00:00
|
|
|
if req.prune_from_option?(build)
|
2013-06-03 15:08:47 -05:00
|
|
|
Requirement.prune
|
2018-03-24 16:55:16 +00:00
|
|
|
elsif req.prune_if_build_and_not_dependent?(dependent, formula)
|
2013-06-03 15:08:47 -05:00
|
|
|
Requirement.prune
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-05-25 15:26:55 -05:00
|
|
|
def expand_deps
|
2014-08-27 17:25:13 -05:00
|
|
|
formula.recursive_dependencies do |dependent, dep|
|
2014-08-24 14:46:34 -05:00
|
|
|
build = effective_build_options_for(dependent)
|
2018-03-24 16:55:16 +00:00
|
|
|
if dep.prune_from_option?(build)
|
2013-07-22 21:36:11 -05:00
|
|
|
Dependency.prune
|
2018-03-24 16:55:16 +00:00
|
|
|
elsif dep.prune_if_build_and_not_dependent?(dependent, formula)
|
2013-07-22 21:36:11 -05:00
|
|
|
Dependency.prune
|
2018-03-21 05:30:51 -07:00
|
|
|
elsif dep.build?
|
|
|
|
Dependency.keep_but_prune_recursive_deps
|
2013-05-25 15:26:55 -05:00
|
|
|
end
|
2013-06-03 15:08:47 -05:00
|
|
|
end
|
2009-09-21 20:22:09 +01:00
|
|
|
end
|
|
|
|
|
2013-05-25 15:26:55 -05:00
|
|
|
def install
|
2015-11-20 14:18:18 +00:00
|
|
|
formula_deps = deps.map(&:to_formula)
|
|
|
|
keg_only_deps = formula_deps.select(&:keg_only?)
|
2018-05-16 11:34:12 -07:00
|
|
|
run_time_deps = deps.reject(&:build?).map(&:to_formula)
|
2013-05-25 15:26:55 -05:00
|
|
|
|
2015-11-20 14:18:18 +00:00
|
|
|
formula_deps.each do |dep|
|
2014-08-23 17:42:13 -05:00
|
|
|
fixopt(dep) unless dep.opt_prefix.directory?
|
2013-01-19 20:45:57 -06:00
|
|
|
end
|
superenv: build-environments that just work
1. A minimal build environment, we don't set CFLAGS, CPPFLAGS, LDFLAGS, etc. the rationale being, the less that is set, the less variables we are introducing that can break builds.
2. A set of scripts that replace cc, ld, etc. and inject the -I, -L, etc. flags we need into the args passed to the build-tools.
Because we now have complete control over compiler instantiations we do a variety of clean-up tasks, like removing bad flags, enforcing universal builds and ensuring makefiles don't try to change the order of library and include paths from ones that work to ones that don't.
The previous ENV-system is still available when --env=std is specified.
superenv applies to Xcode >= 4.3 only currently.
2012-08-11 12:30:51 -04:00
|
|
|
|
2014-07-28 23:05:44 -05:00
|
|
|
ENV.activate_extensions!
|
|
|
|
|
2013-05-25 15:26:55 -05:00
|
|
|
if superenv?
|
2015-06-17 22:03:50 -04:00
|
|
|
ENV.keg_only_deps = keg_only_deps
|
2015-11-20 14:18:18 +00:00
|
|
|
ENV.deps = formula_deps
|
2018-05-16 11:34:12 -07:00
|
|
|
ENV.run_time_deps = run_time_deps
|
2015-08-03 13:09:07 +01:00
|
|
|
ENV.x11 = reqs.any? { |rq| rq.is_a?(X11Requirement) }
|
2014-08-27 17:25:13 -05:00
|
|
|
ENV.setup_build_environment(formula)
|
2013-05-25 15:26:55 -05:00
|
|
|
post_superenv_hacks
|
2013-05-25 15:26:55 -05:00
|
|
|
reqs.each(&:modify_build_environment)
|
2013-06-03 15:08:47 -05:00
|
|
|
deps.each(&:modify_build_environment)
|
2013-05-25 15:26:55 -05:00
|
|
|
else
|
2014-08-27 17:25:13 -05:00
|
|
|
ENV.setup_build_environment(formula)
|
2013-05-25 15:26:55 -05:00
|
|
|
reqs.each(&:modify_build_environment)
|
2013-06-03 15:08:47 -05:00
|
|
|
deps.each(&:modify_build_environment)
|
2013-05-25 15:26:55 -05:00
|
|
|
|
|
|
|
keg_only_deps.each do |dep|
|
2014-06-09 14:55:01 -05:00
|
|
|
ENV.prepend_path "PATH", dep.opt_bin.to_s
|
|
|
|
ENV.prepend_path "PKG_CONFIG_PATH", "#{dep.opt_lib}/pkgconfig"
|
|
|
|
ENV.prepend_path "PKG_CONFIG_PATH", "#{dep.opt_share}/pkgconfig"
|
|
|
|
ENV.prepend_path "ACLOCAL_PATH", "#{dep.opt_share}/aclocal"
|
|
|
|
ENV.prepend_path "CMAKE_PREFIX_PATH", dep.opt_prefix.to_s
|
|
|
|
ENV.prepend "LDFLAGS", "-L#{dep.opt_lib}" if dep.opt_lib.directory?
|
|
|
|
ENV.prepend "CPPFLAGS", "-I#{dep.opt_include}" if dep.opt_include.directory?
|
2013-05-25 15:26:55 -05:00
|
|
|
end
|
2013-05-20 19:35:07 -05:00
|
|
|
end
|
2012-03-18 13:58:13 -05:00
|
|
|
|
2017-07-15 17:26:42 -07:00
|
|
|
new_env = {
|
|
|
|
"TMPDIR" => HOMEBREW_TEMP,
|
2018-11-02 17:18:07 +00:00
|
|
|
"TEMP" => HOMEBREW_TEMP,
|
|
|
|
"TMP" => HOMEBREW_TEMP,
|
2017-07-15 17:26:42 -07:00
|
|
|
}
|
2016-08-26 10:17:59 +08:00
|
|
|
|
2017-07-15 17:26:42 -07:00
|
|
|
with_env(new_env) do
|
|
|
|
formula.extend(Debrew::Formula) if ARGV.debug?
|
2014-09-18 14:16:07 -05:00
|
|
|
|
2020-05-12 12:37:54 +01:00
|
|
|
formula.update_head_version
|
|
|
|
|
|
|
|
formula.brew(fetch: false) do |_formula, staging|
|
2017-09-06 01:49:10 -07:00
|
|
|
# For head builds, HOMEBREW_FORMULA_PREFIX should include the commit,
|
|
|
|
# which is not known until after the formula has been staged.
|
|
|
|
ENV["HOMEBREW_FORMULA_PREFIX"] = formula.prefix
|
|
|
|
|
2020-03-15 17:02:31 +05:30
|
|
|
staging.retain! if Homebrew.args.keep_tmp?
|
2017-07-15 17:26:42 -07:00
|
|
|
formula.patch
|
2013-05-25 15:26:55 -05:00
|
|
|
|
2020-03-15 18:04:51 +05:30
|
|
|
if Homebrew.args.git?
|
2017-07-15 17:26:42 -07:00
|
|
|
system "git", "init"
|
|
|
|
system "git", "add", "-A"
|
|
|
|
end
|
2020-03-14 19:49:15 +05:30
|
|
|
if Homebrew.args.interactive?
|
2017-07-15 17:26:42 -07:00
|
|
|
ohai "Entering interactive mode"
|
2019-11-29 14:53:01 -05:00
|
|
|
puts "Type `exit` to return and finalize the installation."
|
2017-07-15 17:26:42 -07:00
|
|
|
puts "Install to this prefix: #{formula.prefix}"
|
|
|
|
|
2020-03-15 18:04:51 +05:30
|
|
|
if Homebrew.args.git?
|
2017-07-15 17:26:42 -07:00
|
|
|
puts "This directory is now a git repo. Make your changes and then use:"
|
|
|
|
puts " git diff | pbcopy"
|
|
|
|
puts "to copy the diff to the clipboard."
|
|
|
|
end
|
|
|
|
|
|
|
|
interactive_shell(formula)
|
|
|
|
else
|
|
|
|
formula.prefix.mkpath
|
|
|
|
|
|
|
|
(formula.logs/"00.options.out").write \
|
|
|
|
"#{formula.full_name} #{formula.build.used_options.sort.join(" ")}".strip
|
|
|
|
formula.install
|
|
|
|
|
|
|
|
stdlibs = detect_stdlibs(ENV.compiler)
|
|
|
|
tab = Tab.create(formula, ENV.compiler, stdlibs.first)
|
|
|
|
tab.write
|
|
|
|
|
|
|
|
# Find and link metafiles
|
|
|
|
formula.prefix.install_metafiles formula.buildpath
|
|
|
|
formula.prefix.install_metafiles formula.libexec if formula.libexec.exist?
|
2013-05-25 15:26:55 -05:00
|
|
|
end
|
|
|
|
end
|
2010-08-21 12:18:17 -07:00
|
|
|
end
|
2011-07-04 09:31:29 +01:00
|
|
|
end
|
2012-08-27 12:02:57 -04:00
|
|
|
|
2015-06-25 23:42:54 -04:00
|
|
|
def detect_stdlibs(compiler)
|
2014-08-27 17:25:13 -05:00
|
|
|
keg = Keg.new(formula.prefix)
|
2015-06-25 23:42:54 -04:00
|
|
|
CxxStdlib.check_compatibility(formula, deps, keg, compiler)
|
2014-08-09 17:47:10 -05:00
|
|
|
|
2014-08-22 22:18:03 -05:00
|
|
|
# The stdlib recorded in the install receipt is used during dependency
|
|
|
|
# compatibility checks, so we only care about the stdlib that libraries
|
|
|
|
# link against.
|
2016-09-17 15:32:44 +01:00
|
|
|
keg.detect_cxx_stdlibs(skip_executables: true)
|
2014-08-09 17:47:10 -05:00
|
|
|
end
|
|
|
|
|
2015-08-03 13:09:07 +01:00
|
|
|
def fixopt(f)
|
|
|
|
path = if f.linked_keg.directory? && f.linked_keg.symlink?
|
2014-07-28 21:22:33 -05:00
|
|
|
f.linked_keg.resolved_path
|
|
|
|
elsif f.prefix.directory?
|
|
|
|
f.prefix
|
2015-08-03 13:09:07 +01:00
|
|
|
elsif (kids = f.rack.children).size == 1 && kids.first.directory?
|
2014-07-28 21:22:33 -05:00
|
|
|
kids.first
|
|
|
|
else
|
|
|
|
raise
|
|
|
|
end
|
|
|
|
Keg.new(path).optlink
|
2018-09-02 20:14:54 +01:00
|
|
|
rescue
|
2015-05-27 20:35:18 +08:00
|
|
|
raise "#{f.opt_prefix} not present or broken\nPlease reinstall #{f.full_name}. Sorry :("
|
2012-08-27 12:02:57 -04:00
|
|
|
end
|
|
|
|
end
|
2014-08-26 22:06:43 -05:00
|
|
|
|
2014-08-27 17:25:13 -05:00
|
|
|
begin
|
2020-02-11 23:47:15 +05:30
|
|
|
Homebrew.install_args.parse
|
2015-04-08 14:15:38 +08:00
|
|
|
error_pipe = UNIXSocket.open(ENV["HOMEBREW_ERROR_PIPE"], &:recv_io)
|
2014-08-27 17:25:13 -05:00
|
|
|
error_pipe.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
|
2014-08-26 22:06:43 -05:00
|
|
|
|
2014-08-27 17:25:13 -05:00
|
|
|
trap("INT", old_trap)
|
2014-08-26 22:06:43 -05:00
|
|
|
|
2020-02-11 23:47:15 +05:30
|
|
|
formula = Homebrew.args.formulae.first
|
|
|
|
options = Options.create(Homebrew.args.flags_only)
|
2014-08-27 17:25:13 -05:00
|
|
|
build = Build.new(formula, options)
|
|
|
|
build.install
|
2017-10-07 00:31:28 +02:00
|
|
|
rescue Exception => e # rubocop:disable Lint/RescueException
|
2018-08-17 22:42:37 -04:00
|
|
|
error_hash = JSON.parse e.to_json
|
|
|
|
|
|
|
|
# Special case: need to recreate BuildErrors in full
|
|
|
|
# for proper analytics reporting and error messages.
|
2019-08-19 14:27:29 +10:00
|
|
|
# BuildErrors are specific to build processes and not other
|
2018-08-17 22:42:37 -04:00
|
|
|
# children, which is why we create the necessary state here
|
|
|
|
# and not in Utils.safe_fork.
|
|
|
|
if error_hash["json_class"] == "BuildError"
|
|
|
|
error_hash["cmd"] = e.cmd
|
|
|
|
error_hash["args"] = e.args
|
|
|
|
error_hash["env"] = e.env
|
2018-12-25 17:19:23 -05:00
|
|
|
elsif error_hash["json_class"] == "ErrorDuringExecution"
|
2018-12-23 11:24:48 -05:00
|
|
|
error_hash["cmd"] = e.cmd
|
|
|
|
error_hash["status"] = e.status.exitstatus
|
|
|
|
error_hash["output"] = e.output
|
2018-08-17 22:42:37 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
error_pipe.puts error_hash.to_json
|
2014-08-26 22:06:43 -05:00
|
|
|
error_pipe.close
|
|
|
|
exit! 1
|
|
|
|
end
|