diff options
| author | Misty De Meo | 2013-10-06 01:51:31 -0700 |
|---|---|---|
| committer | Misty De Meo | 2013-10-06 19:26:06 -0700 |
| commit | 74ab0234223332585f9d249c8d55a33de60a9b4c (patch) | |
| tree | 871fb635b1edf016b0f3e2d4c618feda5ab9b788 /Library | |
| parent | 9c53a1b8b760614fc076afe0d94ff68ac30cd385 (diff) | |
| download | brew-74ab0234223332585f9d249c8d55a33de60a9b4c.tar.bz2 | |
Only track C++ stdlibs for C++ code
After a formula is built, scan all mach-o files for dynamic links
to see if any of them point to a C++ stdlib (libc++ or libstdc++).
If one of them is linked, record that information in the formula's tab.
This replaces the old behaviour where all files were assumed to be C++
code, and stdlibs were always tracked regardless of whether they were
actually linked against.
This also modifies the way that tabs are written - now tabs are written
with the stdlib field null, and values are only written if an stdlib
is detected.
Diffstat (limited to 'Library')
| -rwxr-xr-x | Library/Homebrew/build.rb | 2 | ||||
| -rw-r--r-- | Library/Homebrew/extend/pathname.rb | 11 | ||||
| -rw-r--r-- | Library/Homebrew/formula_installer.rb | 14 | ||||
| -rw-r--r-- | Library/Homebrew/keg_fix_install_names.rb | 15 | ||||
| -rw-r--r-- | Library/Homebrew/tab.rb | 5 |
5 files changed, 43 insertions, 4 deletions
diff --git a/Library/Homebrew/build.rb b/Library/Homebrew/build.rb index de9d503f3..6cb903efd 100755 --- a/Library/Homebrew/build.rb +++ b/Library/Homebrew/build.rb @@ -171,7 +171,7 @@ class Build begin f.install - Tab.create(f, :libstdcxx, ENV.compiler, + Tab.create(f, ENV.compiler, Options.coerce(ARGV.options_only)).write rescue Exception => e if ARGV.debug? diff --git a/Library/Homebrew/extend/pathname.rb b/Library/Homebrew/extend/pathname.rb index 8ca86d39a..d54e7d72f 100644 --- a/Library/Homebrew/extend/pathname.rb +++ b/Library/Homebrew/extend/pathname.rb @@ -390,6 +390,17 @@ class Pathname end end + # Returns an array containing all dynamically-linked libraries, based on the + # output of otool. This returns the install names, so these are not guaranteed + # to be absolute paths. + # Returns an empty array both for software that links against no libraries, + # and for non-mach objects. + def dynamically_linked_libraries + `otool -L "#{expand_path}"`.chomp.split("\n")[1..-1].map do |line| + line[/\t(.+) \([^(]+\)/, 1] + end + end + # We redefine these private methods in order to add the /o modifier to # the Regexp literals, which forces string interpolation to happen only # once instead of each time the method is called. This is fixed in 1.9+. diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb index f2f739c53..8bc09475c 100644 --- a/Library/Homebrew/formula_installer.rb +++ b/Library/Homebrew/formula_installer.rb @@ -349,6 +349,8 @@ class FormulaInstaller fix_install_names + record_cxx_stdlib + ohai "Summary" if ARGV.verbose? or show_summary_heading unless ENV['HOMEBREW_NO_EMOJI'] print "\xf0\x9f\x8d\xba " if MacOS.version >= :lion @@ -490,6 +492,18 @@ class FormulaInstaller @show_summary_heading = true end + def record_cxx_stdlib + stdlibs = Keg.new(f.prefix).detect_cxx_stdlibs + return if stdlibs.empty? + + tab = Tab.for_formula(f) + tab.tabfile.unlink + # It's technically possible for the same lib to link to multiple C++ stdlibs, + # but very bad news. Right now we don't track this woeful scenario. + tab.stdlib = stdlibs.first + tab.write + end + def clean ohai "Cleaning" if ARGV.verbose? if f.class.skip_clean_all? diff --git a/Library/Homebrew/keg_fix_install_names.rb b/Library/Homebrew/keg_fix_install_names.rb index fdb348608..3b37ccf26 100644 --- a/Library/Homebrew/keg_fix_install_names.rb +++ b/Library/Homebrew/keg_fix_install_names.rb @@ -42,6 +42,21 @@ class Keg end end + # Detects the C++ dynamic libraries in place, scanning the dynamic links + # of the files within the keg. + # Note that this doesn't attempt to distinguish between libstdc++ versions, + # for instance between Apple libstdc++ and GNU libstdc++ + def detect_cxx_stdlibs + results = Set.new + mach_o_files.each do |file| + dylibs = file.dynamically_linked_libraries + results << :libcxx unless dylibs.grep(/libc\+\+.+\.dylib/).empty? + results << :libstdcxx unless dylibs.grep(/libstdc\+\+.+\.dylib/).empty? + end + + results.to_a + end + private OTOOL_RX = /\t(.*) \(compatibility version (\d+\.)*\d+, current version (\d+\.)*\d+\)/ diff --git a/Library/Homebrew/tab.rb b/Library/Homebrew/tab.rb index 9b19e9510..4b8eb3581 100644 --- a/Library/Homebrew/tab.rb +++ b/Library/Homebrew/tab.rb @@ -10,7 +10,7 @@ require 'utils/json' class Tab < OpenStruct FILENAME = 'INSTALL_RECEIPT.json' - def self.create f, stdlib, compiler, args + def self.create f, compiler, args f.build.args = args sha = HOMEBREW_REPOSITORY.cd do @@ -25,8 +25,7 @@ class Tab < OpenStruct :tapped_from => f.tap, :time => Time.now.to_i, # to_s would be better but Ruby has no from_s function :P :HEAD => sha, - :compiler => compiler, - :stdlib => stdlib + :compiler => compiler end def self.from_file path |
