1require "rubygems/deprecate"
2
3##
4# Available list of platforms for targeting Gem installations.
5
6class Gem::Platform
7
8  @local = nil
9
10  attr_accessor :cpu
11
12  attr_accessor :os
13
14  attr_accessor :version
15
16  def self.local
17    arch = Gem::ConfigMap[:arch]
18    arch = "#{arch}_60" if arch =~ /mswin32$/
19    @local ||= new(arch)
20  end
21
22  def self.match(platform)
23    Gem.platforms.any? do |local_platform|
24      platform.nil? or
25        local_platform == platform or
26        (local_platform != Gem::Platform::RUBY and local_platform =~ platform)
27    end
28  end
29
30  def self.new(arch) # :nodoc:
31    case arch
32    when Gem::Platform::CURRENT then
33      Gem::Platform.local
34    when Gem::Platform::RUBY, nil, '' then
35      Gem::Platform::RUBY
36    else
37      super
38    end
39  end
40
41  def initialize(arch)
42    case arch
43    when Array then
44      @cpu, @os, @version = arch
45    when String then
46      arch = arch.split '-'
47
48      if arch.length > 2 and arch.last !~ /\d/ then # reassemble x86-linux-gnu
49        extra = arch.pop
50        arch.last << "-#{extra}"
51      end
52
53      cpu = arch.shift
54
55      @cpu = case cpu
56             when /i\d86/ then 'x86'
57             else cpu
58             end
59
60      if arch.length == 2 and arch.last =~ /^\d+(\.\d+)?$/ then # for command-line
61        @os, @version = arch
62        return
63      end
64
65      os, = arch
66      @cpu, os = nil, cpu if os.nil? # legacy jruby
67
68      @os, @version = case os
69                      when /aix(\d+)?/ then             [ 'aix',       $1  ]
70                      when /cygwin/ then                [ 'cygwin',    nil ]
71                      when /darwin(\d+)?/ then          [ 'darwin',    $1  ]
72                      when /^macruby$/ then             [ 'macruby',   nil ]
73                      when /freebsd(\d+)?/ then         [ 'freebsd',   $1  ]
74                      when /hpux(\d+)?/ then            [ 'hpux',      $1  ]
75                      when /^java$/, /^jruby$/ then     [ 'java',      nil ]
76                      when /^java([\d.]*)/ then         [ 'java',      $1  ]
77                      when /^dalvik(\d+)?$/ then        [ 'dalvik',    $1  ]
78                      when /^dotnet$/ then              [ 'dotnet',    nil ]
79                      when /^dotnet([\d.]*)/ then       [ 'dotnet',    $1  ]
80                      when /linux/ then                 [ 'linux',     $1  ]
81                      when /mingw32/ then               [ 'mingw32',   nil ]
82                      when /(mswin\d+)(\_(\d+))?/ then
83                        os, version = $1, $3
84                        @cpu = 'x86' if @cpu.nil? and os =~ /32$/
85                        [os, version]
86                      when /netbsdelf/ then             [ 'netbsdelf', nil ]
87                      when /openbsd(\d+\.\d+)?/ then    [ 'openbsd',   $1  ]
88                      when /solaris(\d+\.\d+)?/ then    [ 'solaris',   $1  ]
89                      # test
90                      when /^(\w+_platform)(\d+)?/ then [ $1,          $2  ]
91                      else                              [ 'unknown',   nil ]
92                      end
93    when Gem::Platform then
94      @cpu = arch.cpu
95      @os = arch.os
96      @version = arch.version
97    else
98      raise ArgumentError, "invalid argument #{arch.inspect}"
99    end
100  end
101
102  def inspect
103    "#<%s:0x%x @cpu=%p, @os=%p, @version=%p>" % [self.class, object_id, *to_a]
104  end
105
106  def to_a
107    [@cpu, @os, @version]
108  end
109
110  def to_s
111    to_a.compact.join '-'
112  end
113
114  ##
115  # Is +other+ equal to this platform?  Two platforms are equal if they have
116  # the same CPU, OS and version.
117
118  def ==(other)
119    self.class === other and to_a == other.to_a
120  end
121
122  alias :eql? :==
123
124  def hash # :nodoc:
125    to_a.hash
126  end
127
128  ##
129  # Does +other+ match this platform?  Two platforms match if they have the
130  # same CPU, or either has a CPU of 'universal', they have the same OS, and
131  # they have the same version, or either has no version.
132
133  def ===(other)
134    return nil unless Gem::Platform === other
135
136    # cpu
137    (@cpu == 'universal' or other.cpu == 'universal' or @cpu == other.cpu) and
138
139    # os
140    @os == other.os and
141
142    # version
143    (@version.nil? or other.version.nil? or @version == other.version)
144  end
145
146  ##
147  # Does +other+ match this platform?  If +other+ is a String it will be
148  # converted to a Gem::Platform first.  See #=== for matching rules.
149
150  def =~(other)
151    case other
152    when Gem::Platform then # nop
153    when String then
154      # This data is from http://gems.rubyforge.org/gems/yaml on 19 Aug 2007
155      other = case other
156              when /^i686-darwin(\d)/     then ['x86',       'darwin',  $1    ]
157              when /^i\d86-linux/         then ['x86',       'linux',   nil   ]
158              when 'java', 'jruby'        then [nil,         'java',    nil   ]
159              when /^dalvik(\d+)?$/       then [nil,         'dalvik',  $1    ]
160              when /dotnet(\-(\d+\.\d+))?/ then ['universal','dotnet',  $2    ]
161              when /mswin32(\_(\d+))?/    then ['x86',       'mswin32', $2    ]
162              when 'powerpc-darwin'       then ['powerpc',   'darwin',  nil   ]
163              when /powerpc-darwin(\d)/   then ['powerpc',   'darwin',  $1    ]
164              when /sparc-solaris2.8/     then ['sparc',     'solaris', '2.8' ]
165              when /universal-darwin(\d)/ then ['universal', 'darwin',  $1    ]
166              else                             other
167              end
168
169      other = Gem::Platform.new other
170    else
171      return nil
172    end
173
174    self === other
175  end
176
177  ##
178  # A pure-ruby gem that may use Gem::Specification#extensions to build
179  # binary files.
180
181  RUBY = 'ruby'
182
183  ##
184  # A platform-specific gem that is built for the packaging ruby's platform.
185  # This will be replaced with Gem::Platform::local.
186
187  CURRENT = 'current'
188end
189
190