| 
									
										
										
										
											2020-10-10 14:16:11 +02:00
										 |  |  | # typed: true | 
					
						
							| 
									
										
										
										
											2019-04-19 15:38:03 +09:00
										 |  |  | # frozen_string_literal: true | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-22 16:56:37 -07:00
										 |  |  | class Keg | 
					
						
							|  |  |  |   def relocate_dynamic_linkage(relocation) | 
					
						
							| 
									
										
										
										
											2018-08-20 11:24:19 -07:00
										 |  |  |     # Patching the dynamic linker of glibc breaks it. | 
					
						
							| 
									
										
										
										
											2019-10-10 15:16:30 +01:00
										 |  |  |     return if name == "glibc" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-22 16:56:37 -07:00
										 |  |  |     # Patching patchelf using itself fails with "Text file busy" or SIGBUS. | 
					
						
							| 
									
										
										
										
											2019-10-10 15:16:30 +01:00
										 |  |  |     return if name == "patchelf" | 
					
						
							| 
									
										
										
										
											2018-06-22 16:56:37 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     elf_files.each do |file| | 
					
						
							|  |  |  |       file.ensure_writable do | 
					
						
							|  |  |  |         change_rpath(file, relocation.old_prefix, relocation.new_prefix) | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def change_rpath(file, old_prefix, new_prefix) | 
					
						
							|  |  |  |     return if !file.elf? || !file.dynamic_elf? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-05 20:32:37 +05:30
										 |  |  |     updated = {} | 
					
						
							| 
									
										
										
										
											2020-07-10 06:31:31 +05:30
										 |  |  |     old_rpath = file.rpath | 
					
						
							|  |  |  |     new_rpath = if old_rpath | 
					
						
							|  |  |  |       rpath = old_rpath.split(":") | 
					
						
							|  |  |  |                        .map { |x| x.sub(old_prefix, new_prefix) } | 
					
						
							|  |  |  |                        .select { |x| x.start_with?(new_prefix, "$ORIGIN") } | 
					
						
							| 
									
										
										
										
											2018-06-22 16:56:37 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-10 06:31:31 +05:30
										 |  |  |       lib_path = "#{new_prefix}/lib" | 
					
						
							|  |  |  |       rpath << lib_path unless rpath.include? lib_path | 
					
						
							| 
									
										
										
										
											2020-06-23 03:18:29 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-05 20:32:37 +05:30
										 |  |  |       rpath.join(":") | 
					
						
							| 
									
										
										
										
											2018-07-16 23:17:16 +02:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2020-08-05 20:32:37 +05:30
										 |  |  |     updated[:rpath] = new_rpath if old_rpath != new_rpath | 
					
						
							| 
									
										
										
										
											2018-06-22 16:56:37 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-23 03:18:29 +05:30
										 |  |  |     old_interpreter = file.interpreter | 
					
						
							|  |  |  |     new_interpreter = if old_interpreter.nil? | 
					
						
							|  |  |  |       nil | 
					
						
							|  |  |  |     elsif File.readable? "#{new_prefix}/lib/ld.so" | 
					
						
							|  |  |  |       "#{new_prefix}/lib/ld.so" | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       old_interpreter.sub old_prefix, new_prefix | 
					
						
							| 
									
										
										
										
											2018-06-22 16:56:37 -07:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2020-08-05 20:32:37 +05:30
										 |  |  |     updated[:interpreter] = new_interpreter if old_interpreter != new_interpreter | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-05 20:32:37 +05:30
										 |  |  |     file.patch!(interpreter: updated[:interpreter], rpath: updated[:rpath]) | 
					
						
							| 
									
										
										
										
											2018-06-22 16:56:37 -07:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def detect_cxx_stdlibs(options = {}) | 
					
						
							|  |  |  |     skip_executables = options.fetch(:skip_executables, false) | 
					
						
							|  |  |  |     results = Set.new | 
					
						
							|  |  |  |     elf_files.each do |file| | 
					
						
							|  |  |  |       next unless file.dynamic_elf? | 
					
						
							|  |  |  |       next if file.binary_executable? && skip_executables | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-22 16:56:37 -07:00
										 |  |  |       dylibs = file.dynamically_linked_libraries | 
					
						
							|  |  |  |       results << :libcxx if dylibs.any? { |s| s.include? "libc++.so" } | 
					
						
							|  |  |  |       results << :libstdcxx if dylibs.any? { |s| s.include? "libstdc++.so" } | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |     results.to_a | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def elf_files | 
					
						
							|  |  |  |     hardlinks = Set.new | 
					
						
							|  |  |  |     elf_files = [] | 
					
						
							|  |  |  |     path.find do |pn| | 
					
						
							|  |  |  |       next if pn.symlink? || pn.directory? | 
					
						
							|  |  |  |       next if !pn.dylib? && !pn.binary_executable? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       # If we've already processed a file, ignore its hardlinks (which have the | 
					
						
							|  |  |  |       # same dev ID and inode). This prevents relocations from being performed | 
					
						
							|  |  |  |       # on a binary more than once. | 
					
						
							|  |  |  |       next unless hardlinks.add? [pn.stat.dev, pn.stat.ino] | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-22 16:56:37 -07:00
										 |  |  |       elf_files << pn | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |     elf_files | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def self.relocation_formulae | 
					
						
							|  |  |  |     ["patchelf"] | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2018-10-01 16:36:03 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   def self.bottle_dependencies | 
					
						
							|  |  |  |     @bottle_dependencies ||= begin | 
					
						
							|  |  |  |       formulae = relocation_formulae | 
					
						
							|  |  |  |       gcc = Formula["gcc"] | 
					
						
							| 
									
										
										
										
											2020-04-05 15:44:50 +01:00
										 |  |  |       if !Homebrew::EnvConfig.force_homebrew_on_linux? && | 
					
						
							| 
									
										
										
										
											2018-10-01 16:36:03 -07:00
										 |  |  |          DevelopmentTools.non_apple_gcc_version("gcc") < gcc.version.to_i | 
					
						
							|  |  |  |         formulae += gcc.recursive_dependencies.map(&:name) | 
					
						
							|  |  |  |         formulae << gcc.name | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |       formulae | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2018-06-22 16:56:37 -07:00
										 |  |  | end |