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   61680 use strict;
  527         1063  
  527         14766  
36 527     527   2638 use warnings;
  527         1053  
  527         13740  
37 527     527   8329 use feature qw(state);
  527         1054  
  527         117281  
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   3694 use Exporter qw(import);
  527         2088  
  527         22135  
99 527     527   3182 use List::Util qw(any);
  527         1074  
  527         58414  
100              
101 527     527   4506 use Dpkg ();
  527         1054  
  527         7993  
102 527     527   3351 use Dpkg::Gettext;
  527         1063  
  527         33648  
103 527     527   4449 use Dpkg::ErrorHandling;
  527         1055  
  527         38019  
104 527     527   221377 use Dpkg::Build::Env;
  527         1059  
  527         45021  
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   3693 no warnings qw(exec);
  527         1066  
  527         110046  
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 43 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 50 my $CC = $ENV{CC} || 'gcc';
164              
165 7 50       29 return $cc_host_gnu_type{$CC} if defined $cc_host_gnu_type{$CC};
166              
167             ## no critic (TestingAndDebugging::ProhibitNoWarnings)
168 527     527   4214 no warnings qw(exec);
  527         1058  
  527         1799256  
169 7         25700 $cc_host_gnu_type{$CC} = qx($CC -dumpmachine);
170 7 100       394 if ($? >> 8) {
171 1         5 $cc_host_gnu_type{$CC} = '';
172             } else {
173 6         89 chomp $cc_host_gnu_type{$CC};
174             }
175              
176 7         245 return $cc_host_gnu_type{$CC};
177             }
178              
179             sub set_host_gnu_type
180             {
181 5     5 0 132 my ($host_gnu_type) = @_;
182 5   50     56 my $CC = $ENV{CC} || 'gcc';
183              
184 5         29 $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 86 state $host_arch;
198              
199 51 100       308 return $host_arch if defined $host_arch;
200              
201 5         15 my $host_gnu_type = get_host_gnu_type();
202              
203 5 50       85 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         114 my (@host_archtuple) = gnutriplet_to_debtuple($host_gnu_type);
208 5         67 $host_arch = debtuple_to_debarch(@host_archtuple);
209              
210 5 50       50 if (defined $host_arch) {
211 5         108 $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         21 set_host_gnu_type($host_gnu_type);
218             }
219              
220 5 50       23 if (!defined($host_arch)) {
221             # Switch to native compilation.
222 0         0 $host_arch = get_raw_build_arch();
223             }
224              
225 5         108 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 248 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 7 _load_cputable();
249 2         10 _load_ostable();
250              
251 2         5 my @arches;
252              
253 2         5 foreach my $os (@os) {
254 54         76 foreach my $cpu (@cpu) {
255 1890         4025 my $arch = debtuple_to_debarch(split(/-/, $os, 3), $cpu);
256 1890 100       4425 push @arches, $arch if defined($arch);
257             }
258             }
259              
260 2         167 return @arches;
261             }
262              
263             my %table_loaded;
264             sub _load_table
265             {
266 157111     157111   258270 my ($table, $loader) = @_;
267              
268 157111 100       321386 return if $table_loaded{$table};
269              
270 23         87 local $_;
271 23         190 local $/ = "\n";
272              
273 23 50       1515 open my $table_fh, '<', "$Dpkg::DATADIR/$table"
274             or syserr(g_('cannot open %s'), $table);
275 23         755 while (<$table_fh>) {
276 1056         1631 $loader->($_);
277             }
278 23         243 close $table_fh;
279              
280 23         230 $table_loaded{$table} = 1;
281             }
282              
283             sub _load_cputable
284             {
285             _load_table('cputable', sub {
286 371 100   371   1292 if (m/^(?!\#)(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)/) {
287 245         946 $cputable{$1} = $2;
288 245         538 $cputable_re{$1} = $3;
289 245         516 $cpubits{$1} = $4;
290 245         531 $cpuendian{$1} = $5;
291 245         975 push @cpu, $1;
292             }
293 57894     57894   223814 });
294             }
295              
296             sub _load_ostable
297             {
298             _load_table('ostable', sub {
299 258 100   258   797 if (m/^(?!\#)(\S+)\s+(\S+)\s+(\S+)/) {
300 162         545 $ostable{$1} = $2;
301 162         340 $ostable_re{$1} = $3;
302 162         597 push @os, $1;
303             }
304 16     16   94 });
305             }
306              
307             sub _load_abitable()
308             {
309             _load_table('abitable', sub {
310 42 100   42   130 if (m/^(?!\#)(\S+)\s+(\S+)/) {
311 9         73 $abibits{$1} = $2;
312             }
313 41323     41323   109085 });
314             }
315              
316             sub _load_tupletable()
317             {
318 57878     57878   116040 _load_cputable();
319              
320             _load_table('tupletable', sub {
321 385 100   385   1160 if (m/^(?!\#)(\S+)\s+(\S+)/) {
322 231         484 my $debtuple = $1;
323 231         424 my $debarch = $2;
324              
325 231 100       475 if ($debtuple =~ //) {
326 105         204 foreach my $_cpu (@cpu) {
327 3675         8188 (my $dt = $debtuple) =~ s//$_cpu/;
328 3675         7411 (my $da = $debarch) =~ s//$_cpu/;
329              
330             next if exists $debarch_to_debtuple{$da}
331 3675 100 66     11237 or exists $debtuple_to_debarch{$dt};
332              
333 3647         13155 $debarch_to_debtuple{$da} = $dt;
334 3647         20458 $debtuple_to_debarch{$dt} = $da;
335             }
336             } else {
337 126         353 $debarch_to_debtuple{$2} = $1;
338 126         517 $debtuple_to_debarch{$1} = $2;
339             }
340             }
341 57878         248319 });
342             }
343              
344             sub debtuple_to_gnutriplet(@)
345             {
346 7     7 0 30 my ($abi, $libc, $os, $cpu) = @_;
347              
348 7         22 _load_cputable();
349 7         43 _load_ostable();
350              
351             return unless
352             defined $abi && defined $libc && defined $os && defined $cpu &&
353 7 50 33     216 exists $cputable{$cpu} && exists $ostable{"$abi-$libc-$os"};
      33        
      33        
      33        
      33        
354 7         49 return join('-', $cputable{$cpu}, $ostable{"$abi-$libc-$os"});
355             }
356              
357             sub gnutriplet_to_debtuple($)
358             {
359 8     8 0 40 my $gnu = shift;
360 8 100       121 return unless defined($gnu);
361 7         64 my ($gnu_cpu, $gnu_os) = split(/-/, $gnu, 2);
362 7 50 33     136 return unless defined($gnu_cpu) && defined($gnu_os);
363              
364 7         87 _load_cputable();
365 7         55 _load_ostable();
366              
367 7         34 my ($os, $cpu);
368              
369 7         46 foreach my $_cpu (@cpu) {
370 59 100       1030 if ($gnu_cpu =~ /^$cputable_re{$_cpu}$/) {
371 6         24 $cpu = $_cpu;
372 6         29 last;
373             }
374             }
375              
376 7         25 foreach my $_os (@os) {
377 99 100       1508 if ($gnu_os =~ /^(.*-)?$ostable_re{$_os}$/) {
378 6         23 $os = $_os;
379 6         31 last;
380             }
381             }
382              
383 7 100 66     124 return if !defined($cpu) || !defined($os);
384 6         47 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 3 my $gnu = shift;
396 2         7 my ($cpu, $cdr) = split(/-/, $gnu, 2);
397              
398 2 100       9 if ($cpu =~ /^i[4567]86$/) {
399 1         10 return "i386-$cdr";
400             } else {
401 1         15 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 622 my $arch = shift;
414              
415 2         7 return gnutriplet_to_multiarch(debarch_to_gnutriplet($arch));
416             }
417              
418             sub debtuple_to_debarch(@)
419             {
420 1901     1901 0 3330 my ($abi, $libc, $os, $cpu) = @_;
421              
422 1901         3311 _load_tupletable();
423              
424 1901 100 33     12858 if (!defined $abi || !defined $libc || !defined $os || !defined $cpu) {
    100          
425 3         14 return;
426             } elsif (exists $debtuple_to_debarch{"$abi-$libc-$os-$cpu"}) {
427 1085         2840 return $debtuple_to_debarch{"$abi-$libc-$os-$cpu"};
428             } else {
429 813         1414 return;
430             }
431             }
432              
433             sub debarch_to_debtuple($)
434             {
435 55979     55979 0 120505 my $arch = shift;
436              
437 55979 100       99303 return if not defined $arch;
438              
439 55977         108103 _load_tupletable();
440              
441 55977 100       193904 if ($arch =~ /^linux-([^-]*)/) {
442             # XXX: Might disappear in the future, not sure yet.
443 6         20 $arch = $1;
444             }
445              
446 55977         108761 my $tuple = $debarch_to_debtuple{$arch};
447              
448 55977 100       91825 if (defined($tuple)) {
449 55960         136866 my @tuple = split /-/, $tuple, 4;
450 55960 100       218463 return @tuple if wantarray;
451             return {
452 3         17 abi => $tuple[0],
453             libc => $tuple[1],
454             os => $tuple[2],
455             cpu => $tuple[3],
456             };
457             } else {
458 17         678 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         4 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 8 my $gnu = shift;
484              
485 3         9 return debtuple_to_debarch(gnutriplet_to_debtuple($gnu));
486             }
487              
488             sub debwildcard_to_debtuple($)
489             {
490 16549     16549 0 21697 my $arch = shift;
491 16549         35031 my @tuple = split /-/, $arch, 4;
492              
493 16549 100   26450   64747 if (any { $_ eq 'any' } @tuple) {
  26450         45772  
494 16249 100       31087 if (scalar @tuple == 4) {
    100          
    100          
495 10098         37093 return @tuple;
496             } elsif (scalar @tuple == 3) {
497 4477         15874 return ('any', @tuple);
498             } elsif (scalar @tuple == 2) {
499 1673         5493 return ('any', 'any', @tuple);
500             } else {
501 1         7 return ('any', 'any', 'any', 'any');
502             }
503             } else {
504 300         473 return debarch_to_debtuple($arch);
505             }
506             }
507              
508             sub debarch_to_abiattrs($)
509             {
510 41324     41324 0 54963 my $arch = shift;
511 41324         63174 my ($abi, $libc, $os, $cpu) = debarch_to_debtuple($arch);
512              
513 41324 100       73251 if (defined($cpu)) {
514 41323         77418 _load_abitable();
515              
516 41323   66     213995 return ($abibits{$abi} // $cpubits{$cpu}, $cpuendian{$cpu});
517             } else {
518 1         6 return;
519             }
520             }
521              
522             sub debarch_to_cpubits($)
523             {
524 3     3 0 7 my $arch = shift;
525 3         8 my (undef, undef, undef, $cpu) = debarch_to_debtuple($arch);
526              
527 3 100       10 if (defined $cpu) {
528 2         12 return $cpubits{$cpu};
529             } else {
530 1         5 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 22 my ($a, $b) = @_;
544              
545 10 100       37 return 1 if ($a eq $b);
546              
547 7         15 my @a = debarch_to_debtuple($a);
548 7         16 my @b = debarch_to_debtuple($b);
549              
550 7 100 100     54 return 0 if scalar @a != 4 or scalar @b != 4;
551              
552 3   66     39 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 3214623 my ($real, $alias) = @_;
565              
566 14391 100 100     61232 return 1 if ($alias eq $real or $alias eq 'any');
567              
568 13779         26307 my @real = debarch_to_debtuple($real);
569 13779         29267 my @alias = debwildcard_to_debtuple($alias);
570              
571 13779 100 100     56767 return 0 if scalar @real != 4 or scalar @alias != 4;
572              
573 13776 100 66     112078 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         60370 return 1;
578             }
579              
580 299         877 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 794298 my $arch = shift;
592              
593 2771 100       7397 return 0 if $arch eq 'all';
594              
595 2770         5405 my @tuple = debwildcard_to_debtuple($arch);
596              
597 2770 100       9665 return 0 if scalar @tuple != 4;
598 2769 100   3815   7867 return 1 if any { $_ eq 'any' } @tuple;
  3815         15250  
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 62 my ($arch, %opts) = @_;
614 33         103 my $arch_re = qr/[a-zA-Z0-9][a-zA-Z0-9-]*/;
615              
616 33 100       76 if ($opts{positive}) {
617 6         62 return $arch !~ m/^$arch_re$/;
618             } else {
619 27         308 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 489 my ($host_arch, @arches) = @_;
633              
634 175         357 my $seen_arch = 0;
635 175         333 foreach my $arch (@arches) {
636 369         605 $arch = lc $arch;
637              
638 369 100       1056 if ($arch =~ /^!/) {
    100          
639 221         329 my $not_arch = $arch;
640 221         575 $not_arch =~ s/^!//;
641              
642 221 100       472 if (debarch_is($host_arch, $not_arch)) {
643 44         66 $seen_arch = 0;
644 44         77 last;
645             } else {
646             # !arch includes by default all other arches
647             # unless they also appear in a !otherarch
648 177         356 $seen_arch = 1;
649             }
650             } elsif (debarch_is($host_arch, $arch)) {
651 28         56 $seen_arch = 1;
652 28         45 last;
653             }
654             }
655 175         1066 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 1521 my ($arch_list, %opts) = @_;
670 14         37 my @arch_list = split ' ', $arch_list;
671              
672 14         27 foreach my $arch (@arch_list) {
673 24 100       60 if (debarch_is_illegal($arch, %opts)) {
674 2         11 error(g_("'%s' is not a legal architecture in list '%s'"),
675             $arch, $arch_list);
676             }
677             }
678              
679 12         40 return @arch_list;
680             }
681              
682             1;
683              
684             __END__