Arch.pm 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. package Dpkg::Arch;
  2. use strict;
  3. use warnings;
  4. use base qw(Exporter);
  5. our @EXPORT_OK = qw(get_raw_build_arch get_raw_host_arch
  6. get_build_arch get_host_arch get_gcc_host_gnu_type
  7. get_valid_arches debarch_eq debarch_is
  8. debarch_to_cpuattrs
  9. debarch_to_gnutriplet gnutriplet_to_debarch
  10. debtriplet_to_gnutriplet gnutriplet_to_debtriplet
  11. debtriplet_to_debarch debarch_to_debtriplet);
  12. use Dpkg;
  13. use Dpkg::Gettext;
  14. use Dpkg::ErrorHandling;
  15. my (@cpu, @os);
  16. my (%cputable, %ostable);
  17. my (%cputable_re, %ostable_re);
  18. my (%cpubits, %cpuendian);
  19. my %debtriplet_to_debarch;
  20. my %debarch_to_debtriplet;
  21. {
  22. my $build_arch;
  23. my $host_arch;
  24. my $gcc_host_gnu_type;
  25. sub get_raw_build_arch()
  26. {
  27. return $build_arch if defined $build_arch;
  28. my $build_arch = `dpkg --print-architecture`;
  29. # FIXME: Handle bootstrapping
  30. syserr("dpkg --print-architecture failed") if $? >> 8;
  31. chomp $build_arch;
  32. return $build_arch;
  33. }
  34. sub get_build_arch()
  35. {
  36. return $ENV{DEB_BUILD_ARCH} || get_raw_build_arch();
  37. }
  38. sub get_gcc_host_gnu_type()
  39. {
  40. return $gcc_host_gnu_type if defined $gcc_host_gnu_type;
  41. my $gcc_host_gnu_type = `\${CC:-gcc} -dumpmachine`;
  42. if ($? >> 8) {
  43. $gcc_host_gnu_type = '';
  44. } else {
  45. chomp $gcc_host_gnu_type;
  46. }
  47. return $gcc_host_gnu_type;
  48. }
  49. sub get_raw_host_arch()
  50. {
  51. return $host_arch if defined $host_arch;
  52. $gcc_host_gnu_type = get_gcc_host_gnu_type();
  53. if ($gcc_host_gnu_type eq '') {
  54. warning(_g("Couldn't determine gcc system type, falling back to " .
  55. "default (native compilation)"));
  56. } else {
  57. my (@host_archtriplet) = gnutriplet_to_debtriplet($gcc_host_gnu_type);
  58. $host_arch = debtriplet_to_debarch(@host_archtriplet);
  59. if (defined $host_arch) {
  60. $gcc_host_gnu_type = debtriplet_to_gnutriplet(@host_archtriplet);
  61. } else {
  62. warning(_g("Unknown gcc system type %s, falling back to " .
  63. "default (native compilation)"), $gcc_host_gnu_type);
  64. $gcc_host_gnu_type = '';
  65. }
  66. }
  67. if (!defined($host_arch)) {
  68. # Switch to native compilation.
  69. $host_arch = get_raw_build_arch();
  70. }
  71. return $host_arch;
  72. }
  73. sub get_host_arch()
  74. {
  75. return $ENV{DEB_HOST_ARCH} || get_raw_host_arch();
  76. }
  77. }
  78. sub get_valid_arches()
  79. {
  80. read_cputable() if (!@cpu);
  81. read_ostable() if (!@os);
  82. my @arches;
  83. foreach my $os (@os) {
  84. foreach my $cpu (@cpu) {
  85. my $arch = debtriplet_to_debarch(split(/-/, $os, 2), $cpu);
  86. push @arches, $arch if defined($arch);
  87. }
  88. }
  89. return @arches;
  90. }
  91. sub read_cputable
  92. {
  93. local $_;
  94. local $/ = "\n";
  95. open CPUTABLE, "$pkgdatadir/cputable"
  96. or syserr(_g("cannot open %s"), "cputable");
  97. while (<CPUTABLE>) {
  98. if (m/^(?!\#)(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)/) {
  99. $cputable{$1} = $2;
  100. $cputable_re{$1} = $3;
  101. $cpubits{$1} = $4;
  102. $cpuendian{$1} = $5;
  103. push @cpu, $1;
  104. }
  105. }
  106. close CPUTABLE;
  107. }
  108. sub read_ostable
  109. {
  110. local $_;
  111. local $/ = "\n";
  112. open OSTABLE, "$pkgdatadir/ostable"
  113. or syserr(_g("cannot open %s"), "ostable");
  114. while (<OSTABLE>) {
  115. if (m/^(?!\#)(\S+)\s+(\S+)\s+(\S+)/) {
  116. $ostable{$1} = $2;
  117. $ostable_re{$1} = $3;
  118. push @os, $1;
  119. }
  120. }
  121. close OSTABLE;
  122. }
  123. sub read_triplettable()
  124. {
  125. read_cputable() if (!@cpu);
  126. local $_;
  127. local $/ = "\n";
  128. open TRIPLETTABLE, "$pkgdatadir/triplettable"
  129. or syserr(_g("cannot open %s"), "triplettable");
  130. while (<TRIPLETTABLE>) {
  131. if (m/^(?!\#)(\S+)\s+(\S+)/) {
  132. my $debtriplet = $1;
  133. my $debarch = $2;
  134. if ($debtriplet =~ /<cpu>/) {
  135. foreach my $_cpu (@cpu) {
  136. (my $dt = $debtriplet) =~ s/<cpu>/$_cpu/;
  137. (my $da = $debarch) =~ s/<cpu>/$_cpu/;
  138. $debarch_to_debtriplet{$da} = $dt;
  139. $debtriplet_to_debarch{$dt} = $da;
  140. }
  141. } else {
  142. $debarch_to_debtriplet{$2} = $1;
  143. $debtriplet_to_debarch{$1} = $2;
  144. }
  145. }
  146. }
  147. close TRIPLETTABLE;
  148. }
  149. sub debtriplet_to_gnutriplet(@)
  150. {
  151. read_cputable() if (!@cpu);
  152. read_ostable() if (!@os);
  153. my ($abi, $os, $cpu) = @_;
  154. return undef unless defined($abi) && defined($os) && defined($cpu) &&
  155. exists($cputable{$cpu}) && exists($ostable{"$abi-$os"});
  156. return join("-", $cputable{$cpu}, $ostable{"$abi-$os"});
  157. }
  158. sub gnutriplet_to_debtriplet($)
  159. {
  160. my ($gnu) = @_;
  161. return undef unless defined($gnu);
  162. my ($gnu_cpu, $gnu_os) = split(/-/, $gnu, 2);
  163. return undef unless defined($gnu_cpu) && defined($gnu_os);
  164. read_cputable() if (!@cpu);
  165. read_ostable() if (!@os);
  166. my ($os, $cpu);
  167. foreach my $_cpu (@cpu) {
  168. if ($gnu_cpu =~ /^$cputable_re{$_cpu}$/) {
  169. $cpu = $_cpu;
  170. last;
  171. }
  172. }
  173. foreach my $_os (@os) {
  174. if ($gnu_os =~ /^(.*-)?$ostable_re{$_os}$/) {
  175. $os = $_os;
  176. last;
  177. }
  178. }
  179. return undef if !defined($cpu) || !defined($os);
  180. return (split(/-/, $os, 2), $cpu);
  181. }
  182. sub debtriplet_to_debarch(@)
  183. {
  184. read_triplettable() if (!%debtriplet_to_debarch);
  185. my ($abi, $os, $cpu) = @_;
  186. if (!defined($abi) || !defined($os) || !defined($cpu)) {
  187. return undef;
  188. } elsif (exists $debtriplet_to_debarch{"$abi-$os-$cpu"}) {
  189. return $debtriplet_to_debarch{"$abi-$os-$cpu"};
  190. } else {
  191. return undef;
  192. }
  193. }
  194. sub debarch_to_debtriplet($)
  195. {
  196. read_triplettable() if (!%debarch_to_debtriplet);
  197. local ($_) = @_;
  198. my $arch;
  199. if (/^linux-([^-]*)/) {
  200. # XXX: Might disappear in the future, not sure yet.
  201. $arch = $1;
  202. } else {
  203. $arch = $_;
  204. }
  205. my $triplet = $debarch_to_debtriplet{$arch};
  206. if (defined($triplet)) {
  207. return split('-', $triplet, 3);
  208. } else {
  209. return undef;
  210. }
  211. }
  212. sub debarch_to_gnutriplet($)
  213. {
  214. my ($arch) = @_;
  215. return debtriplet_to_gnutriplet(debarch_to_debtriplet($arch));
  216. }
  217. sub gnutriplet_to_debarch($)
  218. {
  219. my ($gnu) = @_;
  220. return debtriplet_to_debarch(gnutriplet_to_debtriplet($gnu));
  221. }
  222. sub debwildcard_to_debtriplet($)
  223. {
  224. local ($_) = @_;
  225. if (/any/) {
  226. if (/^([^-]*)-([^-]*)-(.*)/) {
  227. return ($1, $2, $3);
  228. } elsif (/^([^-]*)-([^-]*)$/) {
  229. return ('any', $1, $2);
  230. } else {
  231. return ($_, $_, $_);
  232. }
  233. } else {
  234. return debarch_to_debtriplet($_);
  235. }
  236. }
  237. sub debarch_to_cpuattrs($)
  238. {
  239. my ($arch) = @_;
  240. my ($abi, $os, $cpu) = debarch_to_debtriplet($arch);
  241. if (defined($cpu)) {
  242. return ($cpubits{$cpu}, $cpuendian{$cpu});
  243. } else {
  244. return undef;
  245. }
  246. }
  247. sub debarch_eq($$)
  248. {
  249. my ($a, $b) = @_;
  250. return 1 if ($a eq $b);
  251. my @a = debarch_to_debtriplet($a);
  252. my @b = debarch_to_debtriplet($b);
  253. return 0 if grep(!defined, (@a, @b));
  254. return ($a[0] eq $b[0] && $a[1] eq $b[1] && $a[2] eq $b[2]);
  255. }
  256. sub debarch_is($$)
  257. {
  258. my ($real, $alias) = @_;
  259. return 1 if ($alias eq $real or $alias eq 'any');
  260. my @real = debarch_to_debtriplet($real);
  261. my @alias = debwildcard_to_debtriplet($alias);
  262. return 0 if grep(!defined, (@real, @alias));
  263. if (($alias[0] eq $real[0] || $alias[0] eq 'any') &&
  264. ($alias[1] eq $real[1] || $alias[1] eq 'any') &&
  265. ($alias[2] eq $real[2] || $alias[2] eq 'any')) {
  266. return 1;
  267. }
  268. return 0;
  269. }
  270. 1;