File Coverage

blib/lib/Dpkg/Arch.pm
Criterion Covered Total %
statement 219 229 95.6
branch 87 98 88.7
condition 46 73 63.0
subroutine 45 46 97.8
pod 15 24 62.5
total 412 470 87.6


line stmt bran cond sub pod time code
1             # Copyright © 2006-2015 Guillem Jover
2             #
3             # This program is free software; you can redistribute it and/or modify
4             # it under the terms of the GNU General Public License as published by
5             # the Free Software Foundation; either version 2 of the License, or
6             # (at your option) any later version.
7             #
8             # This program is distributed in the hope that it will be useful,
9             # but WITHOUT ANY WARRANTY; without even the implied warranty of
10             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11             # GNU General Public License for more details.
12             #
13             # You should have received a copy of the GNU General Public License
14             # along with this program. If not, see .
15              
16             package Dpkg::Arch;
17              
18             =encoding utf8
19              
20             =head1 NAME
21              
22             Dpkg::Arch - handle architectures
23              
24             =head1 DESCRIPTION
25              
26             The Dpkg::Arch module provides functions to handle Debian architectures,
27             wildcards, and mapping from and to GNU triplets.
28              
29             No symbols are exported by default. The :all tag can be used to import all
30             symbols. The :getters, :parsers, :mappers and :operators tags can be used
31             to import specific symbol subsets.
32              
33             =cut
34              
35 527     527   78240 use strict;
  527         548  
  527         15803  
36 527     527   2635 use warnings;
  527         1054  
  527         14258  
37 527     527   2641 use feature qw(state);
  527         1049  
  527         111166  
38              
39             our $VERSION = '1.03';
40             our @EXPORT_OK = qw(
41             get_raw_build_arch
42             get_raw_host_arch
43             get_build_arch
44             get_host_arch
45             get_host_gnu_type
46             get_valid_arches
47             debarch_eq
48             debarch_is
49             debarch_is_wildcard
50             debarch_is_illegal
51             debarch_is_concerned
52             debarch_to_abiattrs
53             debarch_to_cpubits
54             debarch_to_gnutriplet
55             debarch_to_debtuple
56             debarch_to_multiarch
57             debarch_list_parse
58             debtuple_to_debarch
59             debtuple_to_gnutriplet
60             gnutriplet_to_debarch
61             gnutriplet_to_debtuple
62             gnutriplet_to_multiarch
63             );
64             our %EXPORT_TAGS = (
65             all => [ @EXPORT_OK ],
66             getters => [ qw(
67             get_raw_build_arch
68             get_raw_host_arch
69             get_build_arch
70             get_host_arch
71             get_host_gnu_type
72             get_valid_arches
73             ) ],
74             parsers => [ qw(
75             debarch_list_parse
76             ) ],
77             mappers => [ qw(
78             debarch_to_abiattrs
79             debarch_to_gnutriplet
80             debarch_to_debtuple
81             debarch_to_multiarch
82             debtuple_to_debarch
83             debtuple_to_gnutriplet
84             gnutriplet_to_debarch
85             gnutriplet_to_debtuple
86             gnutriplet_to_multiarch
87             ) ],
88             operators => [ qw(
89             debarch_eq
90             debarch_is
91             debarch_is_wildcard
92             debarch_is_illegal
93             debarch_is_concerned
94             ) ],
95             );
96              
97              
98 527     527   3693 use Exporter qw(import);
  527         1054  
  527         22717  
99 527     527   3170 use List::Util qw(any);
  527         1589  
  527         54722  
100              
101 527     527   4516 use Dpkg ();
  527         548  
  527         9015  
102 527     527   3340 use Dpkg::Gettext;
  527         1573  
  527         33162  
103 527     527   4556 use Dpkg::ErrorHandling;
  527         1054  
  527         42156  
104 527     527   225652 use Dpkg::Build::Env;
  527         1585  
  527         52692  
105              
106             my (@cpu, @os);
107             my (%cputable, %ostable);
108             my (%cputable_re, %ostable_re);
109             my (%cpubits, %cpuendian);
110             my %abibits;
111              
112             my %debtuple_to_debarch;
113             my %debarch_to_debtuple;
114              
115             =head1 FUNCTIONS
116              
117             =over 4
118              
119             =item $arch = get_raw_build_arch()
120              
121             Get the raw build Debian architecture, without taking into account variables
122             from the environment.
123              
124             =cut
125              
126             sub get_raw_build_arch()
127             {
128 0     0 1 0 state $build_arch;
129              
130 0 0       0 return $build_arch if defined $build_arch;
131              
132             # Note: We *always* require an installed dpkg when inferring the
133             # build architecture. The bootstrapping case is handled by
134             # dpkg-architecture itself, by avoiding computing the DEB_BUILD_
135             # variables when they are not requested.
136              
137             ## no critic (TestingAndDebugging::ProhibitNoWarnings)
138 527     527   3692 no warnings qw(exec);
  527         1054  
  527         107314  
139 0         0 $build_arch = qx(dpkg --print-architecture);
140 0 0       0 syserr('dpkg --print-architecture failed') if $? >> 8;
141              
142 0         0 chomp $build_arch;
143 0         0 return $build_arch;
144             }
145              
146             =item $arch = get_build_arch()
147              
148             Get the build Debian architecture, using DEB_BUILD_ARCH from the environment
149             if available.
150              
151             =cut
152              
153             sub get_build_arch()
154             {
155 17   33 17 1 50 return Dpkg::Build::Env::get('DEB_BUILD_ARCH') || get_raw_build_arch();
156             }
157              
158             {
159             my %cc_host_gnu_type;
160              
161             sub get_host_gnu_type()
162             {
163 7   100 7 0 56 my $CC = $ENV{CC} || 'gcc';
164              
165 7 50       24 return $cc_host_gnu_type{$CC} if defined $cc_host_gnu_type{$CC};
166              
167             ## no critic (TestingAndDebugging::ProhibitNoWarnings)
168 527     527   4212 no warnings qw(exec);
  527         1053  
  527         1761877  
169 7         25123 $cc_host_gnu_type{$CC} = qx($CC -dumpmachine);
170 7 100       413 if ($? >> 8) {
171 1         10 $cc_host_gnu_type{$CC} = '';
172             } else {
173 6         101 chomp $cc_host_gnu_type{$CC};
174             }
175              
176 7         296 return $cc_host_gnu_type{$CC};
177             }
178              
179             sub set_host_gnu_type
180             {
181 5     5 0 135 my ($host_gnu_type) = @_;
182 5   50     80 my $CC = $ENV{CC} || 'gcc';
183              
184 5         33 $cc_host_gnu_type{$CC} = $host_gnu_type;
185             }
186             }
187              
188             =item $arch = get_raw_host_arch()
189              
190             Get the raw host Debian architecture, without taking into account variables
191             from the environment.
192              
193             =cut
194              
195             sub get_raw_host_arch()
196             {
197 51     51 1 94 state $host_arch;
198              
199 51 100       345 return $host_arch if defined $host_arch;
200              
201 5         18 my $host_gnu_type = get_host_gnu_type();
202              
203 5 50       151 if ($host_gnu_type eq '') {
204 0         0 warning(g_('cannot determine CC system type, falling back to ' .
205             'default (native compilation)'));
206             } else {
207 5         149 my (@host_archtuple) = gnutriplet_to_debtuple($host_gnu_type);
208 5         37 $host_arch = debtuple_to_debarch(@host_archtuple);
209              
210 5 50       41 if (defined $host_arch) {
211 5         77 $host_gnu_type = debtuple_to_gnutriplet(@host_archtuple);
212             } else {
213 0         0 warning(g_('unknown CC system type %s, falling back to ' .
214             'default (native compilation)'), $host_gnu_type);
215 0         0 $host_gnu_type = '';
216             }
217 5         23 set_host_gnu_type($host_gnu_type);
218             }
219              
220 5 50       18 if (!defined($host_arch)) {
221             # Switch to native compilation.
222 0         0 $host_arch = get_raw_build_arch();
223             }
224              
225 5         115 return $host_arch;
226             }
227              
228             =item $arch = get_host_arch()
229              
230             Get the host Debian architecture, using DEB_HOST_ARCH from the environment
231             if available.
232              
233             =cut
234              
235             sub get_host_arch()
236             {
237 55   66 55 1 257 return Dpkg::Build::Env::get('DEB_HOST_ARCH') || get_raw_host_arch();
238             }
239              
240             =item @arch_list = get_valid_arches()
241              
242             Get an array with all currently known Debian architectures.
243              
244             =cut
245              
246             sub get_valid_arches()
247             {
248 2     2 1 16 _load_cputable();
249 2         8 _load_ostable();
250              
251 2         5 my @arches;
252              
253 2         4 foreach my $os (@os) {
254 54         70 foreach my $cpu (@cpu) {
255 1890         3319 my $arch = debtuple_to_debarch(split(/-/, $os, 3), $cpu);
256 1890 100       3552 push @arches, $arch if defined($arch);
257             }
258             }
259              
260 2         193 return @arches;
261             }
262              
263             my %table_loaded;
264             sub _load_table
265             {
266 157117     157117   261747 my ($table, $loader) = @_;
267              
268 157117 100       337659 return if $table_loaded{$table};
269              
270 23         96 local $_;
271 23         226 local $/ = "\n";
272              
273 23 50       1648 open my $table_fh, '<', "$Dpkg::DATADIR/$table"
274             or syserr(g_('cannot open %s'), $table);
275 23         813 while (<$table_fh>) {
276 1056         1871 $loader->($_);
277             }
278 23         253 close $table_fh;
279              
280 23         251 $table_loaded{$table} = 1;
281             }
282              
283             sub _load_cputable
284             {
285             _load_table('cputable', sub {
286 371 100   371   1818 if (m/^(?!\#)(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)/) {
287 245         1022 $cputable{$1} = $2;
288 245         595 $cputable_re{$1} = $3;
289 245         642 $cpubits{$1} = $4;
290 245         563 $cpuendian{$1} = $5;
291 245         1083 push @cpu, $1;
292             }
293 57896     57896   213344 });
294             }
295              
296             sub _load_ostable
297             {
298             _load_table('ostable', sub {
299 258 100   258   992 if (m/^(?!\#)(\S+)\s+(\S+)\s+(\S+)/) {
300 162         651 $ostable{$1} = $2;
301 162         454 $ostable_re{$1} = $3;
302 162         752 push @os, $1;
303             }
304 16     16   141 });
305             }
306              
307             sub _load_abitable()
308             {
309             _load_table('abitable', sub {
310 42 100   42   125 if (m/^(?!\#)(\S+)\s+(\S+)/) {
311 9         67 $abibits{$1} = $2;
312             }
313 41325     41325   106811 });
314             }
315              
316             sub _load_tupletable()
317             {
318 57880     57880   114052 _load_cputable();
319              
320             _load_table('tupletable', sub {
321 385 100   385   1363 if (m/^(?!\#)(\S+)\s+(\S+)/) {
322 231         534 my $debtuple = $1;
323 231         449 my $debarch = $2;
324              
325 231 100       552 if ($debtuple =~ //) {
326 105         184 foreach my $_cpu (@cpu) {
327 3675         8499 (my $dt = $debtuple) =~ s//$_cpu/;
328 3675         7806 (my $da = $debarch) =~ s//$_cpu/;
329              
330             next if exists $debarch_to_debtuple{$da}
331 3675 100 66     10977 or exists $debtuple_to_debarch{$dt};
332              
333 3647         8638 $debarch_to_debtuple{$da} = $dt;
334 3647         30747 $debtuple_to_debarch{$dt} = $da;
335             }
336             } else {
337 126         345 $debarch_to_debtuple{$2} = $1;
338 126         592 $debtuple_to_debarch{$1} = $2;
339             }
340             }
341 57880         244304 });
342             }
343              
344             sub debtuple_to_gnutriplet(@)
345             {
346 7     7 0 37 my ($abi, $libc, $os, $cpu) = @_;
347              
348 7         29 _load_cputable();
349 7         59 _load_ostable();
350              
351             return unless
352             defined $abi && defined $libc && defined $os && defined $cpu &&
353 7 50 33     193 exists $cputable{$cpu} && exists $ostable{"$abi-$libc-$os"};
      33        
      33        
      33        
      33        
354 7         58 return join('-', $cputable{$cpu}, $ostable{"$abi-$libc-$os"});
355             }
356              
357             sub gnutriplet_to_debtuple($)
358             {
359 8     8 0 44 my $gnu = shift;
360 8 100       95 return unless defined($gnu);
361 7         90 my ($gnu_cpu, $gnu_os) = split(/-/, $gnu, 2);
362 7 50 33     171 return unless defined($gnu_cpu) && defined($gnu_os);
363              
364 7         93 _load_cputable();
365 7         55 _load_ostable();
366              
367 7         37 my ($os, $cpu);
368              
369 7         51 foreach my $_cpu (@cpu) {
370 59 100       1150 if ($gnu_cpu =~ /^$cputable_re{$_cpu}$/) {
371 6         34 $cpu = $_cpu;
372 6         30 last;
373             }
374             }
375              
376 7         25 foreach my $_os (@os) {
377 99 100       1622 if ($gnu_os =~ /^(.*-)?$ostable_re{$_os}$/) {
378 6         61 $os = $_os;
379 6         39 last;
380             }
381             }
382              
383 7 100 66     140 return if !defined($cpu) || !defined($os);
384 6         54 return (split(/-/, $os, 3), $cpu);
385             }
386              
387             =item $multiarch = gnutriplet_to_multiarch($gnutriplet)
388              
389             Map a GNU triplet into a Debian multiarch triplet.
390              
391             =cut
392              
393             sub gnutriplet_to_multiarch($)
394             {
395 2     2 1 4 my $gnu = shift;
396 2         6 my ($cpu, $cdr) = split(/-/, $gnu, 2);
397              
398 2 100       9 if ($cpu =~ /^i[4567]86$/) {
399 1         7 return "i386-$cdr";
400             } else {
401 1         4 return $gnu;
402             }
403             }
404              
405             =item $multiarch = debarch_to_multiarch($arch)
406              
407             Map a Debian architecture into a Debian multiarch triplet.
408              
409             =cut
410              
411             sub debarch_to_multiarch($)
412             {
413 2     2 1 473 my $arch = shift;
414              
415 2         8 return gnutriplet_to_multiarch(debarch_to_gnutriplet($arch));
416             }
417              
418             sub debtuple_to_debarch(@)
419             {
420 1901     1901 0 2790 my ($abi, $libc, $os, $cpu) = @_;
421              
422 1901         2676 _load_tupletable();
423              
424 1901 100 33     10188 if (!defined $abi || !defined $libc || !defined $os || !defined $cpu) {
    100          
425 3         13 return;
426             } elsif (exists $debtuple_to_debarch{"$abi-$libc-$os-$cpu"}) {
427 1085         2249 return $debtuple_to_debarch{"$abi-$libc-$os-$cpu"};
428             } else {
429 813         1096 return;
430             }
431             }
432              
433             sub debarch_to_debtuple($)
434             {
435 55981     55981 0 111015 my $arch = shift;
436              
437 55981 100       95714 return if not defined $arch;
438              
439 55979         112986 _load_tupletable();
440              
441 55979 100       196164 if ($arch =~ /^linux-([^-]*)/) {
442             # XXX: Might disappear in the future, not sure yet.
443 6         18 $arch = $1;
444             }
445              
446 55979         102423 my $tuple = $debarch_to_debtuple{$arch};
447              
448 55979 100       97853 if (defined($tuple)) {
449 55962         140956 my @tuple = split /-/, $tuple, 4;
450 55962 100       224701 return @tuple if wantarray;
451             return {
452 3         23 abi => $tuple[0],
453             libc => $tuple[1],
454             os => $tuple[2],
455             cpu => $tuple[3],
456             };
457             } else {
458 17         860 return;
459             }
460             }
461              
462             =item $gnutriplet = debarch_to_gnutriplet($arch)
463              
464             Map a Debian architecture into a GNU triplet.
465              
466             =cut
467              
468             sub debarch_to_gnutriplet($)
469             {
470 2     2 1 3 my $arch = shift;
471              
472 2         5 return debtuple_to_gnutriplet(debarch_to_debtuple($arch));
473             }
474              
475             =item $arch = gnutriplet_to_debarch($gnutriplet)
476              
477             Map a GNU triplet into a Debian architecture.
478              
479             =cut
480              
481             sub gnutriplet_to_debarch($)
482             {
483 3     3 1 5 my $gnu = shift;
484              
485 3         8 return debtuple_to_debarch(gnutriplet_to_debtuple($gnu));
486             }
487              
488             sub debwildcard_to_debtuple($)
489             {
490 16549     16549 0 18349 my $arch = shift;
491 16549         28220 my @tuple = split /-/, $arch, 4;
492              
493 16549 100   26450   54468 if (any { $_ eq 'any' } @tuple) {
  26450         37751  
494 16249 100       25298 if (scalar @tuple == 4) {
    100          
    100          
495 10098         27457 return @tuple;
496             } elsif (scalar @tuple == 3) {
497 4477         12559 return ('any', @tuple);
498             } elsif (scalar @tuple == 2) {
499 1673         4321 return ('any', 'any', @tuple);
500             } else {
501 1         5 return ('any', 'any', 'any', 'any');
502             }
503             } else {
504 300         490 return debarch_to_debtuple($arch);
505             }
506             }
507              
508             sub debarch_to_abiattrs($)
509             {
510 41326     41326 0 63673 my $arch = shift;
511 41326         63474 my ($abi, $libc, $os, $cpu) = debarch_to_debtuple($arch);
512              
513 41326 100       80693 if (defined($cpu)) {
514 41325         84381 _load_abitable();
515              
516 41325   66     228150 return ($abibits{$abi} // $cpubits{$cpu}, $cpuendian{$cpu});
517             } else {
518 1         5 return;
519             }
520             }
521              
522             sub debarch_to_cpubits($)
523             {
524 3     3 0 8 my $arch = shift;
525 3         7 my (undef, undef, undef, $cpu) = debarch_to_debtuple($arch);
526              
527 3 100       7 if (defined $cpu) {
528 2         11 return $cpubits{$cpu};
529             } else {
530 1         4 return;
531             }
532             }
533              
534             =item $bool = debarch_eq($arch_a, $arch_b)
535              
536             Evaluate the equality of a Debian architecture, by comparing with another
537             Debian architecture. No wildcard matching is performed.
538              
539             =cut
540              
541             sub debarch_eq($$)
542             {
543 10     10 1 20 my ($a, $b) = @_;
544              
545 10 100       38 return 1 if ($a eq $b);
546              
547 7         14 my @a = debarch_to_debtuple($a);
548 7         13 my @b = debarch_to_debtuple($b);
549              
550 7 100 100     35 return 0 if scalar @a != 4 or scalar @b != 4;
551              
552 3   66     32 return $a[0] eq $b[0] && $a[1] eq $b[1] && $a[2] eq $b[2] && $a[3] eq $b[3];
553             }
554              
555             =item $bool = debarch_is($arch, $arch_wildcard)
556              
557             Evaluate the identity of a Debian architecture, by matching with an
558             architecture wildcard.
559              
560             =cut
561              
562             sub debarch_is($$)
563             {
564 14391     14391 1 2624334 my ($real, $alias) = @_;
565              
566 14391 100 100     49934 return 1 if ($alias eq $real or $alias eq 'any');
567              
568 13779         21023 my @real = debarch_to_debtuple($real);
569 13779         23533 my @alias = debwildcard_to_debtuple($alias);
570              
571 13779 100 100     45667 return 0 if scalar @real != 4 or scalar @alias != 4;
572              
573 13776 100 66     93568 if (($alias[0] eq $real[0] || $alias[0] eq 'any') &&
      66        
      33        
      100        
      66        
      100        
      100        
574             ($alias[1] eq $real[1] || $alias[1] eq 'any') &&
575             ($alias[2] eq $real[2] || $alias[2] eq 'any') &&
576             ($alias[3] eq $real[3] || $alias[3] eq 'any')) {
577 13477         50467 return 1;
578             }
579              
580 299         949 return 0;
581             }
582              
583             =item $bool = debarch_is_wildcard($arch)
584              
585             Evaluate whether a Debian architecture is an architecture wildcard.
586              
587             =cut
588              
589             sub debarch_is_wildcard($)
590             {
591 2771     2771 1 649207 my $arch = shift;
592              
593 2771 100       6198 return 0 if $arch eq 'all';
594              
595 2770         4696 my @tuple = debwildcard_to_debtuple($arch);
596              
597 2770 100       7631 return 0 if scalar @tuple != 4;
598 2769 100   3815   6299 return 1 if any { $_ eq 'any' } @tuple;
  3815         12217  
599 1         6 return 0;
600             }
601              
602             =item $bool = debarch_is_illegal($arch, %options)
603              
604             Validate an architecture name.
605              
606             If the "positive" option is set to a true value, only positive architectures
607             will be accepted, otherwise negated architectures are allowed.
608              
609             =cut
610              
611             sub debarch_is_illegal
612             {
613 33     33 1 61 my ($arch, %opts) = @_;
614 33         81 my $arch_re = qr/[a-zA-Z0-9][a-zA-Z0-9-]*/;
615              
616 33 100       77 if ($opts{positive}) {
617 6         58 return $arch !~ m/^$arch_re$/;
618             } else {
619 27         307 return $arch !~ m/^!?$arch_re$/;
620             }
621             }
622              
623             =item $bool = debarch_is_concerned($arch, @arches)
624              
625             Evaluate whether a Debian architecture applies to the list of architecture
626             restrictions, as usually found in dependencies inside square brackets.
627              
628             =cut
629              
630             sub debarch_is_concerned
631             {
632 175     175 1 512 my ($host_arch, @arches) = @_;
633              
634 175         277 my $seen_arch = 0;
635 175         331 foreach my $arch (@arches) {
636 369         732 $arch = lc $arch;
637              
638 369 100       1193 if ($arch =~ /^!/) {
    100          
639 221         377 my $not_arch = $arch;
640 221         634 $not_arch =~ s/^!//;
641              
642 221 100       462 if (debarch_is($host_arch, $not_arch)) {
643 44         69 $seen_arch = 0;
644 44         99 last;
645             } else {
646             # !arch includes by default all other arches
647             # unless they also appear in a !otherarch
648 177         409 $seen_arch = 1;
649             }
650             } elsif (debarch_is($host_arch, $arch)) {
651 28         48 $seen_arch = 1;
652 28         59 last;
653             }
654             }
655 175         1042 return $seen_arch;
656             }
657              
658             =item @array = debarch_list_parse($arch_list, %options)
659              
660             Parse an architecture list.
661              
662             If the "positive" option is set to a true value, only positive architectures
663             will be accepted, otherwise negated architectures are allowed.
664              
665             =cut
666              
667             sub debarch_list_parse
668             {
669 14     14 1 1316 my ($arch_list, %opts) = @_;
670 14         40 my @arch_list = split ' ', $arch_list;
671              
672 14         33 foreach my $arch (@arch_list) {
673 24 100       61 if (debarch_is_illegal($arch, %opts)) {
674 2         9 error(g_("'%s' is not a legal architecture in list '%s'"),
675             $arch, $arch_list);
676             }
677             }
678              
679 12         49 return @arch_list;
680             }
681              
682             1;
683              
684             __END__