p4ruby 2022.1.2359956-x64-mingw-ucrt

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/ext/P4/extconf.rb ADDED
@@ -0,0 +1,634 @@
1
+ # File: extconf.rb
2
+
3
+ $:.push File.expand_path("../../../lib", __FILE__)
4
+
5
+ require 'mkmf'
6
+ require 'net/ftp'
7
+ require 'P4/version'
8
+ require 'rbconfig'
9
+ require 'openssl'
10
+
11
+ # Set this to the main version directory we look up in ftp.perforce.com for the P4API
12
+ # This is ignored if you specify the version on the command line.
13
+ # Changed the hardcoded string so that the version is now derived from version.rb file
14
+ #P4API_VERSION_DIR = 'r19.1'
15
+ def p4api_version_dir
16
+ ver=P4::Version.split(".")
17
+ p4_major = ver[0].chars.last(2).join
18
+ p4_minor = ver[1]
19
+ dir = "r" + p4_major + "." + p4_minor
20
+ end
21
+
22
+
23
+ #==============================================================================
24
+ # Provide platform variables in P4-specific format
25
+
26
+ def p4osplat
27
+ @p4osplat ||= calculate_p4osplat
28
+ end
29
+
30
+ def calculate_p4osplat
31
+ plat = RbConfig::CONFIG['arch'].split(/-/)[0].upcase
32
+
33
+ # On Mac OSX, fix the build to 64 bit arch
34
+ if p4osname == 'DARWIN'
35
+ plat = 'X86_64'
36
+ end
37
+
38
+ # Translate Ruby's arch names into Perforce's. Mostly the same so
39
+ # only the exceptions are handled here.
40
+ case plat
41
+ when /^I.86$/
42
+ plat = 'X86'
43
+ when /^AMD64$/
44
+ plat = 'X86_64'
45
+ when 'POWERPC'
46
+ plat = 'PPC'
47
+ end
48
+
49
+ return plat
50
+ end
51
+
52
+ def p4osname
53
+ @p4osname ||= calculate_p4osname
54
+ end
55
+
56
+ def calculate_p4osname
57
+ osname = RbConfig::CONFIG['arch'].split(/-/)[1].upcase
58
+ osname = osname.gsub(/MSWIN32(_\d+)?/, "NT")
59
+ osname = osname.split('-').shift
60
+
61
+ case osname
62
+ when /FREEBSD/
63
+ osname = 'FREEBSD'
64
+ when /DARWIN/
65
+ osname = 'DARWIN'
66
+ when /AIX/
67
+ osname = 'AIX'
68
+ when /SOLARIS/
69
+ osname = 'SOLARIS'
70
+ end
71
+
72
+ return osname
73
+ end
74
+
75
+ def p4osver
76
+ @p4osver ||= calculate_p4osver
77
+ end
78
+
79
+ def calculate_p4osver
80
+ ver = ''
81
+
82
+ case p4osname
83
+ when 'NT'
84
+ # do nothing
85
+ when /MINGW/
86
+ # do nothing
87
+ when /FREEBSD([0-9]+)/
88
+ ver = $1
89
+ when /DARWIN/
90
+ ver = CONFIG['arch'].upcase.gsub(/.*DARWIN(\d+).*/, '\1')
91
+ when /AIX(5)\.(\d)/
92
+ ver = $1 + $2
93
+ when /SOLARIS2\.(\d+)/
94
+ ver = $1
95
+ else
96
+ # use uname -r to see if it works
97
+ begin
98
+ ver=`uname -r`.chomp
99
+ ver_re = /^(\d+)\.(\d+)/
100
+ md = ver_re.match(ver)
101
+ if (md)
102
+ maj = md[1].to_i
103
+ min = md[2].to_i
104
+ ver = maj.to_s + min.to_s
105
+ end
106
+ rescue
107
+ # Nothing - if it failed, it failed.
108
+ end
109
+ end
110
+
111
+ return ver
112
+ end
113
+
114
+ def gcc
115
+ @gcc ||= calculate_gcc
116
+ end
117
+
118
+ def calculate_gcc
119
+ gcc = RbConfig::CONFIG["GCC"]
120
+ return gcc
121
+ end
122
+
123
+ def uname_platform
124
+ @uname_platform ||= calculate_uname_platform
125
+ end
126
+
127
+ def calculate_uname_platform
128
+ plat = "UNKNOWN"
129
+ begin
130
+ plat = `uname -p`
131
+ plat = plat.chomp.upcase
132
+ rescue
133
+ # Nothing - if it failed, it failed.
134
+ end
135
+ plat
136
+ end
137
+
138
+ #==============================================================================
139
+ # Setup additional compiler and linker options.
140
+ #
141
+ # We generally need to launch these things before we configure most of the flags.
142
+ # (See the main script at the end.)
143
+
144
+ def set_platform_opts
145
+
146
+ # Expand any embedded variables (like '$(CC)')
147
+ CONFIG["CC"] = RbConfig::CONFIG["CC"]
148
+ CONFIG["LDSHARED"] = RbConfig::CONFIG["LDSHARED"]
149
+
150
+ # Make sure we have a CXX value (sometimes there isn't one)
151
+ CONFIG["CXX"] = CONFIG["CC"] unless CONFIG.has_key?("CXX")
152
+
153
+ # O/S specific oddities
154
+
155
+ case p4osname
156
+ when /DARWIN/
157
+ CONFIG['CC'] = 'xcrun c++'
158
+ CONFIG['CXX'] = 'xcrun c++'
159
+ CONFIG['LDSHARED'] = CONFIG['CXX'] + ' -bundle'
160
+ when /FREEBSD/, /LINUX/
161
+ # FreeBSD 6 and some Linuxes use 'cc' for linking by default. The
162
+ # gcc detection patterns above won't catch that, so for these
163
+ # platforms, we specifically convert cc to c++.
164
+ CONFIG['LDSHARED'].sub!(/^cc/, 'c++')
165
+ when /MINGW32/, /MINGW/
166
+ # When building with MinGW we need to statically link libgcc
167
+ # and make sure we're linking with gcc and not g++. On older
168
+ # Rubies, they use LDSHARED; newer ones (>=1.9) use LDSHAREDXX
169
+ CONFIG['LDSHARED'].sub!(/g\+\+/, 'gcc')
170
+ CONFIG['LDSHAREDXX'].sub!(/g\+\+/, 'gcc')
171
+ CONFIG['LDSHARED'] = CONFIG['LDSHARED'] + ' -static-libgcc'
172
+ CONFIG['LDSHAREDXX'] = CONFIG['LDSHARED'] + ' -static-libgcc'
173
+ end
174
+ end
175
+
176
+ def set_platform_cxxflags
177
+ if (p4osname == 'LINUX') && (gcc == 'yes')
178
+ $CXXFLAGS += " -std=c++11 "
179
+ end
180
+ end
181
+
182
+
183
+ def set_platform_cppflags
184
+ $CPPFLAGS += "-DOS_#{p4osname} "
185
+ $CPPFLAGS += "-DOS_#{p4osname}#{p4osver} "
186
+ $CPPFLAGS += "-DOS_#{p4osname}#{p4osver}#{p4osplat} "
187
+
188
+ if (p4osname == 'NT')
189
+ $CPPFLAGS += '/DCASE_INSENSITIVE '
190
+ end
191
+
192
+ if (p4osname == 'MINGW32')
193
+ $CPPFLAGS += '-DOS_NT -DCASE_INSENSITIVE '
194
+ end
195
+
196
+ if (p4osname == 'MINGW')
197
+ $CPPFLAGS += '-DOS_NT -DCASE_INSENSITIVE '
198
+ end
199
+
200
+ if (p4osname == 'SOLARIS')
201
+ $CPPFLAGS += '-Dsolaris '
202
+ end
203
+
204
+ if (p4osname == 'DARWIN')
205
+ $CPPFLAGS += '-DCASE_INSENSITIVE '
206
+ end
207
+ end
208
+
209
+ def set_platform_cflags
210
+ if (p4osname == 'DARWIN')
211
+ # Only build for 64 bit if we have more than one arch defined in CFLAGS
212
+ $CFLAGS.slice!("-arch i386")
213
+ $CFLAGS.slice!("-arch ppc");
214
+ end
215
+ end
216
+
217
+ # Initialize the base sets of platform libraries *before other initializers*
218
+ # to preserve linking order.
219
+ def set_platform_libs
220
+
221
+ case p4osname
222
+ when 'SOLARIS'
223
+ osver = `uname -r`
224
+ osver.gsub!(/5\./, '2')
225
+ if (osver == '25')
226
+ $LDFLAGS += '/usr/ucblib/libucb.a '
227
+ end
228
+ have_library('nsl')
229
+ have_library('socket')
230
+ when 'NT'
231
+ have_library('advapi32')
232
+ have_library('wsock32')
233
+ have_library('kernel32')
234
+ have_library('oldnames')
235
+ when 'CYGWIN'
236
+ # Clear out 'bogus' libs on cygwin
237
+ CONFIG['LIBS'] = ''
238
+ when 'DARWIN'
239
+ if p4osver.to_i >= 8
240
+ # Only build for 64 bit if we have more than one arch defined in CFLAGS
241
+ $LDFLAGS.slice!('-arch i386')
242
+ $LDFLAGS.slice!('-arch ppc')
243
+ $LDFLAGS += ' -framework CoreFoundation -framework Foundation'
244
+ end
245
+ when 'LINUX', 'MINGW32', 'MINGW'
246
+ $LDFLAGS += ' -Wl,--allow-multiple-definition'
247
+ have_library('supc++')
248
+ end
249
+ end
250
+
251
+ #==============================================================================
252
+ # Manage p4api version
253
+ #
254
+ # The p4ruby implementation has some branching to support different versions
255
+ # of the C++ API. So we need to generate a p4rubyconf.h file that will setup
256
+ # this #define based branching based on the C++ API being compiled against.
257
+
258
+ # This captures the version information of the P4API C++ library we're building
259
+ # against. This is mostly parsed into this structure and then spit out into
260
+ # a header file we compile into the Ruby API.
261
+ class P4ApiVersion
262
+
263
+ def P4ApiVersion.load(dir)
264
+ #
265
+ # 2007.2 and later APIs put the Version file in the 'sample'
266
+ # subdirectory. Look there if we can't find it in the API root
267
+ #
268
+ ver_file = dir + "/Version"
269
+ unless File.exists?(ver_file)
270
+ ver_file = dir + "/sample/Version"
271
+ return nil unless File.exists?(ver_file)
272
+ end
273
+
274
+ re = Regexp.new('^RELEASE = (\d+)\s+(\d+)\s+(\w*\S*)\s*;')
275
+ rp = Regexp.new('^PATCHLEVEL = (.*)\s*;')
276
+ rs = Regexp.new('^SUPPDATE = (.*)\s*;')
277
+
278
+ p4api_version = nil
279
+
280
+ File.open(ver_file, "r") do
281
+ |f|
282
+ f.each_line do
283
+ |line|
284
+ if md = re.match(line)
285
+ p4api_version = P4ApiVersion.new(md[1], md[2])
286
+ p4api_version.set_type(md[3])
287
+ elsif md = rp.match(line)
288
+ p4api_version.patchlevel = md[1]
289
+ elsif md = rs.match(line)
290
+ p4api_version.suppdate = md[1]
291
+ end
292
+ end
293
+ end
294
+ puts("Found #{p4api_version} Perforce API in #{dir}")
295
+ return p4api_version
296
+ end
297
+
298
+ def initialize(major, minor = nil)
299
+ if (major.kind_of?(String) && !minor)
300
+ if (major =~ /(\d+)\.(\d+)/)
301
+ major = $1
302
+ minor = $2
303
+ else
304
+ raise("Bad API version: #{major}")
305
+ end
306
+ end
307
+
308
+ @major = major.to_i
309
+ @minor = minor.to_i
310
+ @type = nil
311
+
312
+ @patchlevel = nil
313
+ @suppdate = nil
314
+ end
315
+
316
+ def set_type(type)
317
+ if (type.kind_of?(String))
318
+ @type = type
319
+ end
320
+ end
321
+
322
+ attr_accessor :patchlevel, :suppdate
323
+ attr_reader :major, :minor, :type
324
+
325
+ include Comparable
326
+
327
+ def to_s
328
+ if (@type and not @type.empty?)
329
+ "#{major}.#{minor}.#{@type.upcase}"
330
+ else
331
+ "#{major}.#{minor}"
332
+ end
333
+ end
334
+
335
+ def to_i
336
+ major << 8 | minor
337
+ end
338
+
339
+ def <=>(other)
340
+ hi = @major <=> other.major
341
+ lo = @minor <=> other.minor
342
+
343
+ return hi == 0 ? lo : hi
344
+ end
345
+ end
346
+
347
+ def macro_def(macro, value, string=true)
348
+ if (string)
349
+ %Q{#define #{macro}\t"#{value}"}
350
+ else
351
+ %Q{#define #{macro}\t#{value}}
352
+ end
353
+ end
354
+
355
+ def create_p4rubyconf_header(p4api_version, libs)
356
+ File.open("p4rubyconf.h", "w") do
357
+ |ch|
358
+ ch.puts(macro_def("P4APIVER_STRING", p4api_version.to_s))
359
+ ch.puts(macro_def("P4APIVER_ID", p4api_version.to_i, false))
360
+ ch.puts(macro_def("P4API_PATCHLEVEL", p4api_version.patchlevel, false))
361
+ ch.puts(macro_def("P4API_PATCHLEVEL_STRING", p4api_version.patchlevel.to_s))
362
+ ch.puts(macro_def("P4RUBY_VERSION", P4::VERSION))
363
+ ch.puts(macro_def("WITH_LIBS", libs, true))
364
+ end
365
+ end
366
+
367
+ #==============================================================================
368
+ # P4API (C++ API) Helpers
369
+ #
370
+ # We do not have system installers yet, so allow most people to just get a
371
+ # version downloaded if since they very likely do not care about it.
372
+
373
+ # If the user has *not* specified --with-p4api-dir, check the --enable-p4api-download
374
+ # flag, and download the p4api before proceeding, unless that's disabled.
375
+ #
376
+ # This may be a little confusing. If people specify --with-p4api-dir, we want
377
+ # use only use that setting. If that setting is wrong, we want to fail.
378
+ #
379
+ # If they don't set the --with-p4api-dir, we'll proceed as if --enable-p4api-download
380
+ # has been set. Otherwise, they can --disable-p4api-download to ensure we
381
+ # just don't bother doing anything.
382
+ def resolve_p4api_dir
383
+ p4api_dir = nil
384
+
385
+ # When running rake compile, use this instead of other options, I'm not sure how
386
+ # gem/bundler options are passed through via rake
387
+ if ENV.has_key?('p4api_dir')
388
+ p4api_dir = ENV['p4api_dir']
389
+ dir_config('p4api', "#{p4api_dir}/include", "#{p4api_dir}/lib")
390
+ end
391
+
392
+ if !p4api_dir && !with_config('p4api-dir') && enable_config('p4api-download', true)
393
+ download_api_via_ftp
394
+ unzip_file
395
+ p4api_dir = downloaded_p4api_dir
396
+ dir_config('p4api', "#{p4api_dir}/include", "#{p4api_dir}/lib")
397
+ elsif with_config('p4api_dir')
398
+ p4api_dir = with_config('p4api-dir')
399
+ dir_config('p4api', "#{p4api_dir}/include", "#{p4api_dir}/lib")
400
+ elsif !p4api_dir
401
+ raise '--with-p4api-dir option has not been specified, and --disable-p4api-download is in effect'
402
+ end
403
+
404
+ p4api_dir
405
+ end
406
+
407
+ def resolve_ssl_dirs
408
+ ssl_dir = nil
409
+ # When running rake compile, use this instead of other options, I'm not sure how
410
+ # gem/bundler options are passed through via rake
411
+ if ENV.has_key?('ssl_dir')
412
+ ssl_dir = ENV['ssl_dir']
413
+ dir_config('ssl', "#{ssl_dir}/include", "#{ssl_dir}/lib")
414
+ puts "SSL Path #{ssl_dir}"
415
+ end
416
+ if ENV.has_key?('ssl_include_dir') && ENV.has_key?('ssl_lib_dir')
417
+ ssl_include_dir = ENV['ssl_include_dir']
418
+ ssl_lib_dir = ENV['ssl_lib_dir']
419
+ dir_config('ssl', ssl_include_dir, ssl_lib_dir)
420
+ puts "SSL Includes #{ssl_include_dir} Lib #{ssl_lib_dir}"
421
+ end
422
+ ssl_dir
423
+ end
424
+
425
+ # Our 'cpu' label we use as part of the directory name on ftp.perforce.com
426
+ def p4_cpu(os)
427
+ cpu = RbConfig::CONFIG['target_cpu']
428
+ case os
429
+ when :darwin, :linux
430
+ if cpu =~ /i686/
431
+ 'x86'
432
+ elsif cpu =~ /universal/
433
+ 'x86_64'
434
+ else
435
+ cpu
436
+ end
437
+ else
438
+ case cpu
439
+ when /ia/i
440
+ 'ia64'
441
+ else
442
+ cpu
443
+ end
444
+ end
445
+ end
446
+
447
+ # The p4_platform is our label that basically ends up being part of the
448
+ # directory name where we can download files from.
449
+ def p4_platform_label
450
+ case RbConfig::CONFIG["target_os"].downcase
451
+ when /nt|mswin|mingw|cygwin|msys/
452
+ # Ruby on windows is only MinGW via Rubyinstaller.org, though this may
453
+ # not work on all rubies.
454
+ # There are too many permutations of Windows p4api, to automate.
455
+ raise 'Automatic fetching of p4api from perforce FTP is not supported on Windows'
456
+ when /darwin19|darwin[2-9][0-9]/
457
+ "macosx1015#{p4_cpu(:darwin)}"
458
+ when /darwin/
459
+ "darwin90#{p4_cpu(:darwin)}"
460
+ when /solaris/
461
+ "solaris10#{p4_cpu(:solaris)}"
462
+ when /linux/
463
+ "linux26#{p4_cpu(:linux)}"
464
+ end
465
+ end
466
+
467
+ def platform_dir_name
468
+ "bin.#{p4_platform_label}"
469
+ end
470
+
471
+ def ftp_download_dir(version)
472
+ "perforce/#{version}/#{platform_dir_name}"
473
+ end
474
+
475
+ def filename
476
+ openssl_number = OpenSSL::OPENSSL_VERSION.split(' ')[1].to_s
477
+ openssl_number = openssl_number.slice(0, (openssl_number.rindex('.')))
478
+
479
+ if RbConfig::CONFIG['target_os'].downcase =~ /nt|mswin|mingw/
480
+ filename = 'p4api.zip'
481
+ if !openssl_number.to_s.empty?
482
+ case openssl_number.to_s
483
+ when /1.1/
484
+ filename = 'p4api-openssl1.1.1.zip'
485
+ when /1.0/
486
+ filename = 'p4api-openssl1.0.2.zip'
487
+ end
488
+ end
489
+ elsif RbConfig::CONFIG['target_os'].downcase =~ /darwin19|darwin[2-9][0-9]/
490
+ filename = 'p4api-openssl1.1.1.tgz'
491
+ else
492
+ filename = 'p4api.tgz'
493
+ if !openssl_number.to_s.empty?
494
+ case openssl_number.to_s
495
+ when /1.1/
496
+ filename = 'p4api-glibc2.3-openssl1.1.1.tgz'
497
+ when /1.0/
498
+ filename = 'p4api-glibc2.3-openssl1.0.2.tgz'
499
+ end
500
+ end
501
+ end
502
+ return filename
503
+ end
504
+
505
+
506
+ def remote_files_matching(ftp, dir, regex)
507
+ ftp.ls(dir.to_s).map { |entry|
508
+ if match = entry.match(regex)
509
+ yield match
510
+ else
511
+ nil
512
+ end
513
+ }.reject { |entry|
514
+ entry.nil?
515
+ }
516
+ end
517
+
518
+ def find_latest_with_p4api(ftp, versions)
519
+ versions.reverse_each { |v|
520
+ begin
521
+ remote_files_matching(ftp, "r#{v}/#{platform_dir_name}/", /p4api/) do
522
+ return v
523
+ end
524
+ rescue
525
+ next
526
+ end
527
+ }
528
+ end
529
+
530
+ def find_latest_version_dir(ftp)
531
+ ftp.chdir('perforce')
532
+
533
+ # Capture all versions
534
+ versions = remote_files_matching(ftp, '.', /r(1\d\.\d)/) { |m| m.captures.first }.sort
535
+
536
+ version = find_latest_with_p4api(ftp, versions)
537
+
538
+ ftp.chdir('..')
539
+
540
+ "r#{version}"
541
+ end
542
+
543
+ # Downloads the C++ P4API via FTP to the local directory, then 'initializes' it
544
+ # by unpacking it.
545
+ def download_api_via_ftp
546
+ ftp = Net::FTP.new('ftp.perforce.com')
547
+ ftp.passive=true
548
+ ftp.login
549
+
550
+ # At one point, we allowed the gem build to just find the most recent p4api build.
551
+ # P4Ruby probably shouldn't do that by default.
552
+ #version_dir = find_latest_version_dir(ftp)
553
+
554
+ dir = ftp_download_dir(p4api_version_dir)
555
+ ftp.chdir(dir)
556
+
557
+ puts "downloading #{filename} from #{dir} on ftp.perforce.com"
558
+ ftp.getbinaryfile(filename)
559
+
560
+ ensure
561
+ ftp.close if ftp and !ftp.closed?
562
+ end
563
+
564
+ def unzip_file
565
+ if RbConfig::CONFIG['target_os'].downcase =~ /nt|mswin|mingw/
566
+ `unzip #{filename}`
567
+ else
568
+ `tar xzf #{filename}`
569
+ end
570
+ end
571
+
572
+ def downloaded_p4api_dir
573
+ File.expand_path(Dir.entries('.').select { |x| x =~ /^p4api/ and File.directory?(x) }.first)
574
+ end
575
+
576
+ #==============================================================================
577
+ # Main script
578
+
579
+ puts "p4osname #{p4osname}"
580
+ puts "p4osver #{p4osver}"
581
+
582
+ # Specify different toolsets based on the platform type.
583
+ set_platform_opts
584
+
585
+ # We setup these flags in the beginning, before any libraries are detected,
586
+ # based solely on platform detection.
587
+ set_platform_cppflags
588
+ set_platform_cflags
589
+ set_platform_cxxflags
590
+
591
+ puts "$CPPFLAGS #{$CPPFLAGS}"
592
+ puts "$CFLAGS #{$CFLAGS}"
593
+ puts "$CXXFLAGS #{$CXXFLAGS}"
594
+
595
+ # Setup additional system library definitions based on platform type before
596
+ # we setup other libraries, in order to preserve linking order
597
+ set_platform_libs
598
+
599
+ puts "$LDFLAGS #{$LDFLAGS}"
600
+
601
+ p4api_dir = resolve_p4api_dir
602
+ puts "P4API Path #{p4api_dir}"
603
+
604
+ resolve_ssl_dirs
605
+
606
+ # If we happen to need SSL on Windows, we also need gdi32
607
+ if RbConfig::CONFIG['target_os'].downcase =~ /mingw/
608
+ have_library('gdi32') or raise
609
+ have_library('ole32') or raise
610
+ have_library('crypt32') or raise
611
+ end
612
+
613
+ have_library('crypto') or raise
614
+ have_library('ssl') or raise
615
+ have_library('supp') or raise
616
+ have_library('p4script_sqlite') or raise
617
+ have_library('p4script_curl') or raise
618
+ have_library('p4script') or raise
619
+ have_library('p4script_c') or raise
620
+ have_library('rpc') or raise
621
+ have_library('client') or raise
622
+
623
+ puts "$libs #{$libs}"
624
+
625
+ # Parse the Version file into a ruby structure
626
+ version_info = P4ApiVersion.load(p4api_dir)
627
+ create_p4rubyconf_header(version_info, $libs)
628
+
629
+ # This will generate a standard extconf.h based on what we discover locally.
630
+ # These are typically just 'yes I have such and such a library', which I
631
+ # don't believe we need to rely on actually.
632
+ create_header
633
+
634
+ create_makefile('P4')
data/ext/P4/gc_hack.h ADDED
@@ -0,0 +1,10 @@
1
+ /*******************************************************************************
2
+ * Hack to get garbage collection working reliably and portably.
3
+ ******************************************************************************/
4
+
5
+ #ifndef _GC_HACK_INCLUDED
6
+ # define _GC_HACK_INCLUDED
7
+
8
+ # define rb_gc_mark(value) ((void (*)(VALUE))(rb_gc_mark))(value)
9
+
10
+ #endif