| 
									
										
										
										
											2014-07-02 21:57:52 -05:00
										 |  |  | require "compilers" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-27 00:11:45 -07:00
										 |  |  | class CxxStdlib | 
					
						
							| 
									
										
										
										
											2014-08-02 19:29:59 -05:00
										 |  |  |   include CompilerConstants | 
					
						
							| 
									
										
										
										
											2013-07-27 00:11:45 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-22 22:36:58 -05:00
										 |  |  |   class CompatibilityError < StandardError | 
					
						
							|  |  |  |     def initialize(formula, dep, stdlib) | 
					
						
							|  |  |  |       super <<-EOS.undent
 | 
					
						
							| 
									
										
										
										
											2015-05-27 21:33:11 +08:00
										 |  |  |         #{formula.full_name} dependency #{dep.name} was built with a different C++ standard | 
					
						
							| 
									
										
										
										
											2014-08-22 22:36:58 -05:00
										 |  |  |         library (#{stdlib.type_string} from #{stdlib.compiler}). This may cause problems at runtime. | 
					
						
							|  |  |  |         EOS | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-02 19:29:59 -05:00
										 |  |  |   def self.create(type, compiler) | 
					
						
							| 
									
										
										
										
											2013-10-06 16:59:39 -07:00
										 |  |  |     if type && ![:libstdcxx, :libcxx].include?(type) | 
					
						
							| 
									
										
										
										
											2013-07-27 00:11:45 -07:00
										 |  |  |       raise ArgumentError, "Invalid C++ stdlib type: #{type}" | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2014-08-02 19:29:59 -05:00
										 |  |  |     klass = GNU_GCC_REGEXP === compiler.to_s ? GnuStdlib : AppleStdlib | 
					
						
							|  |  |  |     klass.new(type, compiler) | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-22 22:18:03 -05:00
										 |  |  |   def self.check_compatibility(formula, deps, keg, compiler) | 
					
						
							|  |  |  |     return if formula.skip_cxxstdlib_check? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     stdlib = create(keg.detect_cxx_stdlibs.first, compiler) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     begin | 
					
						
							|  |  |  |       stdlib.check_dependencies(formula, deps) | 
					
						
							| 
									
										
										
										
											2014-08-22 22:36:58 -05:00
										 |  |  |     rescue CompatibilityError => e | 
					
						
							| 
									
										
										
										
											2014-08-22 22:18:03 -05:00
										 |  |  |       opoo e.message | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-02 19:29:59 -05:00
										 |  |  |   attr_reader :type, :compiler | 
					
						
							| 
									
										
										
										
											2013-07-27 00:11:45 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-02 19:29:59 -05:00
										 |  |  |   def initialize(type, compiler) | 
					
						
							| 
									
										
										
										
											2014-08-02 19:29:58 -05:00
										 |  |  |     @type = type | 
					
						
							| 
									
										
										
										
											2013-07-27 00:11:45 -07:00
										 |  |  |     @compiler = compiler.to_sym | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-02 19:29:59 -05:00
										 |  |  |   # If either package doesn't use C++, all is well | 
					
						
							|  |  |  |   # libstdc++ and libc++ aren't ever intercompatible | 
					
						
							|  |  |  |   # libstdc++ is compatible across Apple compilers, but | 
					
						
							|  |  |  |   # not between Apple and GNU compilers, or between GNU compiler versions | 
					
						
							| 
									
										
										
										
											2013-07-27 00:11:45 -07:00
										 |  |  |   def compatible_with?(other) | 
					
						
							| 
									
										
										
										
											2014-08-02 20:03:42 -05:00
										 |  |  |     return true if type.nil? || other.type.nil? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return false unless type == other.type | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-02 20:09:42 -05:00
										 |  |  |     apple_compiler? && other.apple_compiler? || | 
					
						
							|  |  |  |       !other.apple_compiler? && compiler.to_s[4..6] == other.compiler.to_s[4..6] | 
					
						
							| 
									
										
										
										
											2013-07-27 00:11:45 -07:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def check_dependencies(formula, deps) | 
					
						
							| 
									
										
										
										
											2014-08-22 22:18:03 -05:00
										 |  |  |     deps.each do |dep| | 
					
						
							|  |  |  |       # Software is unlikely to link against libraries from build-time deps, so | 
					
						
							|  |  |  |       # it doesn't matter if they link against different C++ stdlibs. | 
					
						
							|  |  |  |       next if dep.build? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       dep_stdlib = Tab.for_formula(dep.to_formula).cxxstdlib | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |       unless compatible_with? dep_stdlib | 
					
						
							| 
									
										
										
										
											2014-08-22 22:36:58 -05:00
										 |  |  |         raise CompatibilityError.new(formula, dep, dep_stdlib) | 
					
						
							| 
									
										
										
										
											2013-07-27 00:11:45 -07:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def type_string | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |     type.to_s.gsub(/cxx$/, "c++") | 
					
						
							| 
									
										
										
										
											2013-07-27 00:11:45 -07:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2014-08-02 19:29:59 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-03 15:28:26 -05:00
										 |  |  |   def inspect | 
					
						
							|  |  |  |     "#<#{self.class.name}: #{compiler} #{type}>" | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-02 19:29:59 -05:00
										 |  |  |   class AppleStdlib < CxxStdlib | 
					
						
							|  |  |  |     def apple_compiler? | 
					
						
							|  |  |  |       true | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   class GnuStdlib < CxxStdlib | 
					
						
							|  |  |  |     def apple_compiler? | 
					
						
							|  |  |  |       false | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2013-07-27 00:11:45 -07:00
										 |  |  | end |