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   76176 use strict;
  527         1063  
  527         15801  
36 527     527   2633 use warnings;
  527         1052  
  527         13737  
37 527     527   2133 use feature qw(state);
  527         5708  
  527         108527  
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   3696 use Exporter qw(import);
  527         5190  
  527         23698  
99 527     527   13019 use List::Util qw(any);
  527         1074  
  527         55798  
100              
101 527     527   4522 use Dpkg ();
  527         1062  
  527         7978  
102 527     527   3869 use Dpkg::Gettext;
  527         539  
  527         34689  
103 527     527   4945 use Dpkg::ErrorHandling;
  527         553  
  527         37454  
104 527     527   260118 use Dpkg::Build::Env;
  527         1574  
  527         44934  
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   3690 no warnings qw(exec);
  527         1055  
  527         104841  
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 53 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 49 my $CC = $ENV{CC} || 'gcc';
164              
165 7 50       26 return $cc_host_gnu_type{$CC} if defined $cc_host_gnu_type{$CC};
166              
167             ## no critic (TestingAndDebugging::ProhibitNoWarnings)
168 527     527   3692 no warnings qw(exec);
  527         1063  
  527         1766734  
169 7         29437 $cc_host_gnu_type{$CC} = qx($CC -dumpmachine);
170 7 100       417 if ($? >> 8) {
171 1         15 $cc_host_gnu_type{$CC} = '';
172             } else {
173 6         92 chomp $cc_host_gnu_type{$CC};
174             }
175              
176 7         270 return $cc_host_gnu_type{$CC};
177             }
178              
179             sub set_host_gnu_type
180             {
181 5     5 0 164 my ($host_gnu_type) = @_;
182 5   50     61 my $CC = $ENV{CC} || 'gcc';
183              
184 5         32 $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       395 return $host_arch if defined $host_arch;
200              
201 5         19 my $host_gnu_type = get_host_gnu_type();
202              
203 5 50       80 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         133 my (@host_archtuple) = gnutriplet_to_debtuple($host_gnu_type);
208 5         31 $host_arch = debtuple_to_debarch(@host_archtuple);
209              
210 5 50       30 if (defined $host_arch) {
211 5         96 $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       21 if (!defined($host_arch)) {
221             # Switch to native compilation.
222 0         0 $host_arch = get_raw_build_arch();
223             }
224              
225 5         118 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 254 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 5 _load_cputable();
249 2         7 _load_ostable();
250              
251 2         4 my @arches;
252              
253 2         5 foreach my $os (@os) {
254 54         80 foreach my $cpu (@cpu) {
255 1890         3520 my $arch = debtuple_to_debarch(split(/-/, $os, 3), $cpu);
256 1890 100       3925 push @arches, $arch if defined($arch);
257             }
258             }
259              
260 2         132 return @arches;
261             }
262              
263             my %table_loaded;
264             sub _load_table
265             {
266 157111     157111   245133 my ($table, $loader) = @_;
267              
268 157111 100       300848 return if $table_loaded{$table};
269              
270 23         117 local $_;
271 23         207 local $/ = "\n";
272              
273 23 50       1573 open my $table_fh, '<', "$Dpkg::DATADIR/$table"
274             or syserr(g_('cannot open %s'), $table);
275 23         716 while (<$table_fh>) {
276 1056         1648 $loader->($_);
277             }
278 23         254 close $table_fh;
279              
280 23         224 $table_loaded{$table} = 1;
281             }
282              
283             sub _load_cputable
284             {
285             _load_table('cputable', sub {
286 371 100   371   1305 if (m/^(?!\#)(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)/) {
287 245         911 $cputable{$1} = $2;
288 245         523 $cputable_re{$1} = $3;
289 245         531 $cpubits{$1} = $4;
290 245         507 $cpuendian{$1} = $5;
291 245         927 push @cpu, $1;
292             }
293 57894     57894   199502 });
294             }
295              
296             sub _load_ostable
297             {
298             _load_table('ostable', sub {
299 258 100   258   805 if (m/^(?!\#)(\S+)\s+(\S+)\s+(\S+)/) {
300 162         551 $ostable{$1} = $2;
301 162         365 $ostable_re{$1} = $3;
302 162         629 push @os, $1;
303             }
304 16     16   108 });
305             }
306              
307             sub _load_abitable()
308             {
309             _load_table('abitable', sub {
310 42 100   42   128 if (m/^(?!\#)(\S+)\s+(\S+)/) {
311 9         69 $abibits{$1} = $2;
312             }
313 41323     41323   99845 });
314             }
315              
316             sub _load_tupletable()
317             {
318 57878     57878   100406 _load_cputable();
319              
320             _load_table('tupletable', sub {
321 385 100   385   1194 if (m/^(?!\#)(\S+)\s+(\S+)/) {
322 231         502 my $debtuple = $1;
323 231         388 my $debarch = $2;
324              
325 231 100       512 if ($debtuple =~ //) {
326 105         180 foreach my $_cpu (@cpu) {
327 3675         8237 (my $dt = $debtuple) =~ s//$_cpu/;
328 3675         7442 (my $da = $debarch) =~ s//$_cpu/;
329              
330             next if exists $debarch_to_debtuple{$da}
331 3675 100 66     10519 or exists $debtuple_to_debarch{$dt};
332              
333 3647         8462 $debarch_to_debtuple{$da} = $dt;
334 3647         24743 $debtuple_to_debarch{$dt} = $da;
335             }
336             } else {
337 126         320 $debarch_to_debtuple{$2} = $1;
338 126         548 $debtuple_to_debarch{$1} = $2;
339             }
340             }
341 57878         224419 });
342             }
343              
344             sub debtuple_to_gnutriplet(@)
345             {
346 7     7 0 29 my ($abi, $libc, $os, $cpu) = @_;
347              
348 7         23 _load_cputable();
349 7         95 _load_ostable();
350              
351             return unless
352             defined $abi && defined $libc && defined $os && defined $cpu &&
353 7 50 33     177 exists $cputable{$cpu} && exists $ostable{"$abi-$libc-$os"};
      33        
      33        
      33        
      33        
354 7         50 return join('-', $cputable{$cpu}, $ostable{"$abi-$libc-$os"});
355             }
356              
357             sub gnutriplet_to_debtuple($)
358             {
359 8     8 0 45 my $gnu = shift;
360 8 100       105 return unless defined($gnu);
361 7         61 my ($gnu_cpu, $gnu_os) = split(/-/, $gnu, 2);
362 7 50 33     170 return unless defined($gnu_cpu) && defined($gnu_os);
363              
364 7         60 _load_cputable();
365 7         59 _load_ostable();
366              
367 7         33 my ($os, $cpu);
368              
369 7         52 foreach my $_cpu (@cpu) {
370 59 100       1013 if ($gnu_cpu =~ /^$cputable_re{$_cpu}$/) {
371 6         32 $cpu = $_cpu;
372 6         25 last;
373             }
374             }
375              
376 7         26 foreach my $_os (@os) {
377 99 100       1528 if ($gnu_os =~ /^(.*-)?$ostable_re{$_os}$/) {
378 6         18 $os = $_os;
379 6         15 last;
380             }
381             }
382              
383 7 100 66     118 return if !defined($cpu) || !defined($os);
384 6         48 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         5 my ($cpu, $cdr) = split(/-/, $gnu, 2);
397              
398 2 100       6 if ($cpu =~ /^i[4567]86$/) {
399 1         9 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 464 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 3024 my ($abi, $libc, $os, $cpu) = @_;
421              
422 1901         2998 _load_tupletable();
423              
424 1901 100 33     11256 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         2481 return $debtuple_to_debarch{"$abi-$libc-$os-$cpu"};
428             } else {
429 813         1233 return;
430             }
431             }
432              
433             sub debarch_to_debtuple($)
434             {
435 55979     55979 0 105356 my $arch = shift;
436              
437 55979 100       90782 return if not defined $arch;
438              
439 55977         101970 _load_tupletable();
440              
441 55977 100       185022 if ($arch =~ /^linux-([^-]*)/) {
442             # XXX: Might disappear in the future, not sure yet.
443 6         14 $arch = $1;
444             }
445              
446 55977         94372 my $tuple = $debarch_to_debtuple{$arch};
447              
448 55977 100       87216 if (defined($tuple)) {
449 55960         135762 my @tuple = split /-/, $tuple, 4;
450 55960 100       204983 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         868 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 2 my $arch = shift;
471              
472 2         3 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 6 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 19816 my $arch = shift;
491 16549         28978 my @tuple = split /-/, $arch, 4;
492              
493 16549 100   26450   53579 if (any { $_ eq 'any' } @tuple) {
  26450         37610  
494 16249 100       25534 if (scalar @tuple == 4) {
    100          
    100          
495 10098         27692 return @tuple;
496             } elsif (scalar @tuple == 3) {
497 4477         12477 return ('any', @tuple);
498             } elsif (scalar @tuple == 2) {
499 1673         4297 return ('any', 'any', @tuple);
500             } else {
501 1         9 return ('any', 'any', 'any', 'any');
502             }
503             } else {
504 300         506 return debarch_to_debtuple($arch);
505             }
506             }
507              
508             sub debarch_to_abiattrs($)
509             {
510 41324     41324 0 56104 my $arch = shift;
511 41324         62111 my ($abi, $libc, $os, $cpu) = debarch_to_debtuple($arch);
512              
513 41324 100       73263 if (defined($cpu)) {
514 41323         72357 _load_abitable();
515              
516 41323   66     210258 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 8 my $arch = shift;
525 3         8 my (undef, undef, undef, $cpu) = debarch_to_debtuple($arch);
526              
527 3 100       9 if (defined $cpu) {
528 2         10 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 21 my ($a, $b) = @_;
544              
545 10 100       26 return 1 if ($a eq $b);
546              
547 7         12 my @a = debarch_to_debtuple($a);
548 7         11 my @b = debarch_to_debtuple($b);
549              
550 7 100 100     36 return 0 if scalar @a != 4 or scalar @b != 4;
551              
552 3   66     28 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 2643966 my ($real, $alias) = @_;
565              
566 14391 100 100     50903 return 1 if ($alias eq $real or $alias eq 'any');
567              
568 13779         22877 my @real = debarch_to_debtuple($real);
569 13779         22739 my @alias = debwildcard_to_debtuple($alias);
570              
571 13779 100 100     46257 return 0 if scalar @real != 4 or scalar @alias != 4;
572              
573 13776 100 66     94451 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         47750 return 1;
578             }
579              
580 299         864 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 652466 my $arch = shift;
592              
593 2771 100       5796 return 0 if $arch eq 'all';
594              
595 2770         4300 my @tuple = debwildcard_to_debtuple($arch);
596              
597 2770 100       7112 return 0 if scalar @tuple != 4;
598 2769 100   3815   6274 return 1 if any { $_ eq 'any' } @tuple;
  3815         11776  
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 64 my ($arch, %opts) = @_;
614 33         109 my $arch_re = qr/[a-zA-Z0-9][a-zA-Z0-9-]*/;
615              
616 33 100       72 if ($opts{positive}) {
617 6         58 return $arch !~ m/^$arch_re$/;
618             } else {
619 27         347 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 484 my ($host_arch, @arches) = @_;
633              
634 175         250 my $seen_arch = 0;
635 175         366 foreach my $arch (@arches) {
636 369         618 $arch = lc $arch;
637              
638 369 100       1138 if ($arch =~ /^!/) {
    100          
639 221         350 my $not_arch = $arch;
640 221         601 $not_arch =~ s/^!//;
641              
642 221 100       502 if (debarch_is($host_arch, $not_arch)) {
643 44         65 $seen_arch = 0;
644 44         84 last;
645             } else {
646             # !arch includes by default all other arches
647             # unless they also appear in a !otherarch
648 177         377 $seen_arch = 1;
649             }
650             } elsif (debarch_is($host_arch, $arch)) {
651 28         63 $seen_arch = 1;
652 28         48 last;
653             }
654             }
655 175         1028 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 1462 my ($arch_list, %opts) = @_;
670 14         41 my @arch_list = split ' ', $arch_list;
671              
672 14         32 foreach my $arch (@arch_list) {
673 24 100       69 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__