libzypp  17.38.7
Arch.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
14 extern "C"
15 {
16 #include <features.h>
17 #include <sys/utsname.h>
18 #if __GLIBC_PREREQ (2,16)
19 #include <sys/auxv.h> // getauxval for PPC64P7 detection
20 #endif
21 #include <unistd.h>
22 }
23 
24 #include <iostream>
25 #include <list>
26 #include <fstream>
27 
29 #include <zypp-core/base/Logger.h>
32 #include <zypp-core/base/Hash.h>
33 #include <zypp-core/fs/PathInfo.h>
34 #include <zypp/Arch.h>
35 #include <zypp/Bit.h>
36 
37 using std::endl;
38 
40 namespace zypp
41 {
42 
43  namespace {
44  // From rpm's lib/rpmrc.c
45 # if defined(__linux__) && defined(__x86_64__)
46  inline void cpuid(uint32_t op, uint32_t op2, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
47  {
48  asm volatile (
49  "cpuid\n"
50  : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
51  : "a" (op), "c" (op2));
52  }
53 
54  /* From gcc's gcc/config/i386/cpuid.h */
55  /* Features (%eax == 1) */
56  /* %ecx */
57  #define bit_SSE3 (1 << 0)
58  #define bit_SSSE3 (1 << 9)
59  #define bit_FMA (1 << 12)
60  #define bit_CMPXCHG16B (1 << 13)
61  #define bit_SSE4_1 (1 << 19)
62  #define bit_SSE4_2 (1 << 20)
63  #define bit_MOVBE (1 << 22)
64  #define bit_POPCNT (1 << 23)
65  #define bit_OSXSAVE (1 << 27)
66  #define bit_AVX (1 << 28)
67  #define bit_F16C (1 << 29)
68 
69  /* Extended Features (%eax == 0x80000001) */
70  /* %ecx */
71  #define bit_LAHF_LM (1 << 0)
72  #define bit_LZCNT (1 << 5)
73 
74  /* Extended Features (%eax == 7) */
75  /* %ebx */
76  #define bit_BMI (1 << 3)
77  #define bit_AVX2 (1 << 5)
78  #define bit_BMI2 (1 << 8)
79  #define bit_AVX512F (1 << 16)
80  #define bit_AVX512DQ (1 << 17)
81  #define bit_AVX512CD (1 << 28)
82  #define bit_AVX512BW (1 << 30)
83  #define bit_AVX512VL (1u << 31)
84 
85  int get_x86_64_level(void)
86  {
87  int level = 1;
88 
89  unsigned int op_1_ecx = 0, op_80000001_ecx = 0, op_7_ebx = 0, unused = 0;
90  cpuid(1, 0, &unused, &unused, &op_1_ecx, &unused);
91  cpuid(0x80000001, 0, &unused, &unused, &op_80000001_ecx, &unused);
92  cpuid(7, 0, &unused, &op_7_ebx, &unused, &unused);
93 
94  const unsigned int op_1_ecx_lv2 = bit_SSE3 | bit_SSSE3 | bit_CMPXCHG16B | bit_SSE4_1 | bit_SSE4_2 | bit_POPCNT;
95  if ((op_1_ecx & op_1_ecx_lv2) == op_1_ecx_lv2 && (op_80000001_ecx & bit_LAHF_LM))
96  level = 2;
97 
98  const unsigned int op_1_ecx_lv3 = bit_FMA | bit_MOVBE | bit_OSXSAVE | bit_AVX | bit_F16C;
99  const unsigned int op_7_ebx_lv3 = bit_BMI | bit_AVX2 | bit_BMI2;
100  if (level == 2 && (op_1_ecx & op_1_ecx_lv3) == op_1_ecx_lv3 && (op_7_ebx & op_7_ebx_lv3) == op_7_ebx_lv3
101  && (op_80000001_ecx & bit_LZCNT))
102  level = 3;
103 
104  const unsigned int op_7_ebx_lv4 = bit_AVX512F | bit_AVX512DQ | bit_AVX512CD | bit_AVX512BW | bit_AVX512VL;
105  if (level == 3 && (op_7_ebx & op_7_ebx_lv4) == op_7_ebx_lv4)
106  level = 4;
107 
108  return level;
109  }
110 # endif
111 
112  Arch _autoDetectSystemArchitecture() {
113  struct ::utsname buf;
114  if ( ::uname( &buf ) < 0 )
115  {
116  ERR << "Can't determine system architecture" << endl;
117  return Arch_noarch;
118  }
119 
120  Arch architecture( buf.machine );
121  MIL << "Uname architecture is '" << buf.machine << "'" << endl;
122 
123  if ( architecture == Arch_x86_64 )
124  {
125  #if defined(__linux__) && defined(__x86_64__)
126  switch ( get_x86_64_level() )
127  {
128  case 2:
129  architecture = Arch_x86_64_v2;
130  WAR << "CPU has 'x86_64': architecture upgraded to '" << architecture << "'" << endl;
131  break;
132  case 3:
133  architecture = Arch_x86_64_v3;
134  WAR << "CPU has 'x86_64': architecture upgraded to '" << architecture << "'" << endl;
135  break;
136  case 4:
137  architecture = Arch_x86_64_v4;
138  WAR << "CPU has 'x86_64': architecture upgraded to '" << architecture << "'" << endl;
139  break;
140  }
141  # endif
142  }
143  else if ( architecture == Arch_i686 )
144  {
145  // some CPUs report i686 but dont implement cx8 and cmov
146  // check for both flags in /proc/cpuinfo and downgrade
147  // to i586 if either is missing (cf bug #18885)
148  std::ifstream cpuinfo( "/proc/cpuinfo" );
149  if ( cpuinfo )
150  {
151  for( iostr::EachLine in( cpuinfo ); in; in.next() )
152  {
153  if ( str::hasPrefix( *in, "flags" ) )
154  {
155  if ( in->find( "cx8" ) == std::string::npos
156  || in->find( "cmov" ) == std::string::npos )
157  {
158  architecture = Arch_i586;
159  WAR << "CPU lacks 'cx8' or 'cmov': architecture downgraded to '" << architecture << "'" << endl;
160  }
161  break;
162  }
163  }
164  }
165  else
166  {
167  ERR << "Cant open " << PathInfo("/proc/cpuinfo") << endl;
168  }
169  }
170  else if ( architecture == Arch_sparc || architecture == Arch_sparc64 )
171  {
172  // Check for sun4[vum] to get the real arch. (bug #566291)
173  std::ifstream cpuinfo( "/proc/cpuinfo" );
174  if ( cpuinfo )
175  {
176  for( iostr::EachLine in( cpuinfo ); in; in.next() )
177  {
178  if ( str::hasPrefix( *in, "type" ) )
179  {
180  if ( in->find( "sun4v" ) != std::string::npos )
181  {
182  architecture = ( architecture == Arch_sparc64 ? Arch_sparc64v : Arch_sparcv9v );
183  WAR << "CPU has 'sun4v': architecture upgraded to '" << architecture << "'" << endl;
184  }
185  else if ( in->find( "sun4u" ) != std::string::npos )
186  {
187  architecture = ( architecture == Arch_sparc64 ? Arch_sparc64 : Arch_sparcv9 );
188  WAR << "CPU has 'sun4u': architecture upgraded to '" << architecture << "'" << endl;
189  }
190  else if ( in->find( "sun4m" ) != std::string::npos )
191  {
192  architecture = Arch_sparcv8;
193  WAR << "CPU has 'sun4m': architecture upgraded to '" << architecture << "'" << endl;
194  }
195  break;
196  }
197  }
198  }
199  else
200  {
201  ERR << "Cant open " << PathInfo("/proc/cpuinfo") << endl;
202  }
203  }
204  else if ( architecture == Arch_armv8l || architecture == Arch_armv7l || architecture == Arch_armv6l )
205  {
206  std::ifstream platform( "/etc/rpm/platform" );
207  if (platform)
208  {
209  for( iostr::EachLine in( platform ); in; in.next() )
210  {
211  if ( str::hasPrefix( *in, "armv8hl-" ) )
212  {
213  architecture = Arch_armv8hl;
214  WAR << "/etc/rpm/platform contains armv8hl-: architecture upgraded to '" << architecture << "'" << endl;
215  break;
216  }
217  if ( str::hasPrefix( *in, "armv7hl-" ) )
218  {
219  architecture = Arch_armv7hl;
220  WAR << "/etc/rpm/platform contains armv7hl-: architecture upgraded to '" << architecture << "'" << endl;
221  break;
222  }
223  if ( str::hasPrefix( *in, "armv6hl-" ) )
224  {
225  architecture = Arch_armv6hl;
226  WAR << "/etc/rpm/platform contains armv6hl-: architecture upgraded to '" << architecture << "'" << endl;
227  break;
228  }
229  }
230  }
231  }
232  #if __GLIBC_PREREQ (2,16)
233  else if ( architecture == Arch_ppc64 )
234  {
235  const char * platform = (const char *)getauxval( AT_PLATFORM );
236  int powerlvl = 0;
237  if ( platform && sscanf( platform, "power%d", &powerlvl ) == 1 && powerlvl > 6 )
238  architecture = Arch_ppc64p7;
239  }
240  #endif
241  return architecture;
242  }
243 
244  }
245 
246 
247 
249  //
250  // CLASS NAME : Arch::CompatEntry
251  //
258  {
264 
265  CompatEntry( const std::string & archStr_r,
266  CompatBits::IntT idBit_r = 1 )
267  : _idStr( archStr_r )
268  , _archStr( archStr_r )
269  , _idBit( idBit_r )
270  , _compatBits( idBit_r )
271  {}
272 
273  CompatEntry( IdString archStr_r,
274  CompatBits::IntT idBit_r = 1 )
275  : _idStr( archStr_r )
276  , _archStr( archStr_r.asString() )
277  , _idBit( idBit_r )
278  , _compatBits( idBit_r )
279  {}
280 
281  void addCompatBit( const CompatBits & idBit_r ) const
282  {
283  if ( idBit_r && ! (_compatBits & idBit_r) )
284  {
285  _compatBits |= idBit_r;
286  }
287  }
288 
290  bool compatibleWith( const CompatEntry & targetEntry_r ) const
291  {
292  switch ( _idBit.value() )
293  {
294  case 0:
295  // this is noarch and always comatible
296  return true;
297  break;
298  case 1:
299  // this is a non builtin: self compatible only
300  return _archStr == targetEntry_r._archStr;
301  break;
302  }
303  // This is a builtin: compatible if mentioned in targetEntry_r
304  return bool( targetEntry_r._compatBits & _idBit );
305  }
306 
308  int compare( const CompatEntry & rhs ) const
309  {
310  if ( _idBit.value() != rhs. _idBit.value() )
311  return( _idBit.value() < rhs. _idBit.value() ? -1 : 1 );
312  return _archStr.compare( rhs._archStr ); // Id 1: non builtin
313  }
314 
315  bool isBuiltIn() const
316  { return( _idBit != CompatBits(1) ); }
317 
319  { return _idStr.id(); }
320 
322  std::string _archStr; // frequently used by the UI so we keep a reference
325  };
327 
329  inline std::ostream & operator<<( std::ostream & str, const Arch::CompatEntry & obj )
330  {
332  unsigned bitnum = 0;
333  while ( bit )
334  {
335  ++bitnum;
336  bit >>= 1;
337  }
338  return str << str::form( "%-15s ", obj._archStr.c_str() ) << str::numstring(bitnum,2) << ' '
339  << obj._compatBits << ' ' << obj._compatBits.value();
340  }
341 
343  inline bool operator==( const Arch::CompatEntry & lhs, const Arch::CompatEntry & rhs )
344  { return lhs._idStr == rhs._idStr; }
346  inline bool operator!=( const Arch::CompatEntry & lhs, const Arch::CompatEntry & rhs )
347  { return ! ( lhs == rhs ); }
348 
350 } // namespace zypp
352 
354 
356 namespace zypp
357 {
358 
359  // Builtin architecture STRING VALUES to be
360  // used in defCompatibleWith below!
361  //
362  // const IdString _foo( "foo" );
363  // const Arch Arch_foo( _foo() );
364  //
365  // NOTE: Builtin CLASS Arch CONSTANTS are defined below.
366  // You have to change them accordingly in Arch.h.
367  //
368  // NOTE: Thake care CompatBits::IntT is able to provide one
369  // bit for each architecture.
370  //
371  #define DEF_BUILTIN(A) \
372  namespace { static inline const IdString & a_##A () { static IdString _str(#A); return _str; } } \
373  const Arch Arch_##A( a_##A() )
374 
375  DEF_BUILTIN( noarch );
376 
377  DEF_BUILTIN( i386 );
378  DEF_BUILTIN( i486 );
379  DEF_BUILTIN( i586 );
380  DEF_BUILTIN( i686 );
381  DEF_BUILTIN( athlon );
382  DEF_BUILTIN( x86_64 );
383  DEF_BUILTIN( x86_64_v2 );
384  DEF_BUILTIN( x86_64_v3 );
385  DEF_BUILTIN( x86_64_v4 );
386 
387  DEF_BUILTIN( pentium3 );
388  DEF_BUILTIN( pentium4 );
389 
390  DEF_BUILTIN( s390 );
391  DEF_BUILTIN( s390x );
392 
393  DEF_BUILTIN( ppc );
394  DEF_BUILTIN( ppc64 );
395  DEF_BUILTIN( ppc64p7 );
396 
397  DEF_BUILTIN( ppc64le );
398 
399  DEF_BUILTIN( ia64 );
400 
401  DEF_BUILTIN( alphaev67 );
402  DEF_BUILTIN( alphaev6 );
403  DEF_BUILTIN( alphapca56 );
404  DEF_BUILTIN( alphaev56 );
405  DEF_BUILTIN( alphaev5 );
406  DEF_BUILTIN( alpha );
407 
408  DEF_BUILTIN( sparc64v );
409  DEF_BUILTIN( sparcv9v );
410  DEF_BUILTIN( sparc64 );
411  DEF_BUILTIN( sparcv9 );
412  DEF_BUILTIN( sparcv8 );
413  DEF_BUILTIN( sparc );
414 
415  DEF_BUILTIN( aarch64 );
416 
417  DEF_BUILTIN( armv7tnhl ); /* exists? */
418  DEF_BUILTIN( armv7thl ); /* exists? */
419 
420  DEF_BUILTIN( armv7hnl ); /* legacy: */DEF_BUILTIN( armv7nhl );
421  DEF_BUILTIN( armv8hl );
422  DEF_BUILTIN( armv7hl );
423  DEF_BUILTIN( armv6hl );
424 
425  DEF_BUILTIN( armv8l );
426  DEF_BUILTIN( armv7l );
427  DEF_BUILTIN( armv6l );
428  DEF_BUILTIN( armv5tejl );
429  DEF_BUILTIN( armv5tel );
430  DEF_BUILTIN( armv5tl );
431  DEF_BUILTIN( armv5l );
432  DEF_BUILTIN( armv4tl );
433  DEF_BUILTIN( armv4l );
434  DEF_BUILTIN( armv3l );
435 
436  DEF_BUILTIN( riscv64 );
437 
438  DEF_BUILTIN( sh3 );
439 
440  DEF_BUILTIN( sh4 );
441  DEF_BUILTIN( sh4a );
442 
443  DEF_BUILTIN( m68k );
444 
445  DEF_BUILTIN( mips );
446  DEF_BUILTIN( mipsel );
447  DEF_BUILTIN( mips64 );
448  DEF_BUILTIN( mips64el );
449 
450  DEF_BUILTIN( loong64 );
451 #undef DEF_BUILTIN
452 
454  namespace
455  {
456 
458  //
459  // CLASS NAME : CompatSet
460  //
468  struct ArchCompatSet : private base::NonCopyable
469  {
470  using CompatEntry = Arch::CompatEntry;
471  using CompatBits = CompatEntry::CompatBits;
472 
473  using Set = std::unordered_set<CompatEntry>;
474  using iterator = Set::iterator;
475  using const_iterator = Set::const_iterator;
476 
478  static ArchCompatSet & instance()
479  {
480  static ArchCompatSet _instance;
481  return _instance;
482  }
483 
487  const Arch::CompatEntry & assertDef( const std::string & archStr_r )
488  { return *_compatSet.insert( Arch::CompatEntry( archStr_r ) ).first; }
490  const Arch::CompatEntry & assertDef( IdString archStr_r )
491  { return *_compatSet.insert( Arch::CompatEntry( archStr_r ) ).first; }
492 
493  const_iterator begin() const
494  { return _compatSet.begin(); }
495 
496  const_iterator end() const
497  { return _compatSet.end(); }
498 
499  struct DumpOnCompare
500  {
501  int operator()( const CompatEntry & lhs, const CompatEntry & rhs ) const
502  { return lhs._idBit.value() < rhs._idBit.value(); }
503  };
504 
505  std::ostream & dumpOn( std::ostream & str ) const
506  {
507  str << "ArchCompatSet:";
508  std::list<CompatEntry> ov( _compatSet.begin(), _compatSet.end() );
509  ov.sort( DumpOnCompare() );
510  for_( it, ov.begin(), ov.end() )
511  {
512  str << endl << ' ' << *it;
513  }
514  return str;
515  }
516 
517  private:
519  ArchCompatSet()
520  {
521  // _noarch must have _idBit 0.
522  // Other builtins have 1-bit set
523  // and are initialized done on the fly.
524  _compatSet.insert( Arch::CompatEntry( a_noarch(), 0 ) );
526  // Define the CompatibleWith relation:
527  //
528  // NOTE: Order of definition is significant! (Arch::compare)
529  // - define compatible (less) architectures first!
530  //
531  defCompatibleWith( a_i386(), a_noarch() );
532  defCompatibleWith( a_i486(), a_noarch(),a_i386() );
533  defCompatibleWith( a_i586(), a_noarch(),a_i386(),a_i486() );
534  defCompatibleWith( a_i686(), a_noarch(),a_i386(),a_i486(),a_i586() );
535  defCompatibleWith( a_athlon(), a_noarch(),a_i386(),a_i486(),a_i586(),a_i686() );
536  defCompatibleWith( a_x86_64(), a_noarch(),a_i386(),a_i486(),a_i586(),a_i686(),a_athlon() );
537  defCompatibleWith( a_x86_64_v2(), a_noarch(),a_i386(),a_i486(),a_i586(),a_i686(),a_athlon(),a_x86_64() );
538  defCompatibleWith( a_x86_64_v3(), a_noarch(),a_i386(),a_i486(),a_i586(),a_i686(),a_athlon(),a_x86_64(),a_x86_64_v2() );
539  defCompatibleWith( a_x86_64_v4(), a_noarch(),a_i386(),a_i486(),a_i586(),a_i686(),a_athlon(),a_x86_64(),a_x86_64_v2(),a_x86_64_v3() );
540 
541  defCompatibleWith( a_pentium3(), a_noarch(),a_i386(),a_i486(),a_i586(),a_i686() );
542  defCompatibleWith( a_pentium4(), a_noarch(),a_i386(),a_i486(),a_i586(),a_i686(),a_pentium3() );
543 
544  defCompatibleWith( a_ia64(), a_noarch(),a_i386(),a_i486(),a_i586(),a_i686() );
545  //
546  defCompatibleWith( a_s390(), a_noarch() );
547  defCompatibleWith( a_s390x(), a_noarch(),a_s390() );
548  //
549  defCompatibleWith( a_ppc(), a_noarch() );
550  defCompatibleWith( a_ppc64(), a_noarch(),a_ppc() );
551  defCompatibleWith( a_ppc64p7(), a_noarch(),a_ppc(),a_ppc64() );
552  //
553  defCompatibleWith( a_ppc64le(), a_noarch() );
554  //
555  defCompatibleWith( a_alpha(), a_noarch() );
556  defCompatibleWith( a_alphaev5(), a_noarch(),a_alpha() );
557  defCompatibleWith( a_alphaev56(), a_noarch(),a_alpha(),a_alphaev5() );
558  defCompatibleWith( a_alphapca56(), a_noarch(),a_alpha(),a_alphaev5(),a_alphaev56() );
559  defCompatibleWith( a_alphaev6(), a_noarch(),a_alpha(),a_alphaev5(),a_alphaev56(),a_alphapca56() );
560  defCompatibleWith( a_alphaev67(), a_noarch(),a_alpha(),a_alphaev5(),a_alphaev56(),a_alphapca56(),a_alphaev6() );
561  //
562  defCompatibleWith( a_sparc(), a_noarch() );
563  defCompatibleWith( a_sparcv8(), a_noarch(),a_sparc() );
564  defCompatibleWith( a_sparcv9(), a_noarch(),a_sparc(),a_sparcv8() );
565  defCompatibleWith( a_sparcv9v(), a_noarch(),a_sparc(),a_sparcv8(),a_sparcv9() );
566  //
567  defCompatibleWith( a_sparc64(), a_noarch(),a_sparc(),a_sparcv8(),a_sparcv9() );
568  defCompatibleWith( a_sparc64v(), a_noarch(),a_sparc(),a_sparcv8(),a_sparcv9(),a_sparcv9v(),a_sparc64() );
569  //
570  defCompatibleWith( a_armv3l(), a_noarch() );
571  defCompatibleWith( a_armv4l(), a_noarch(),a_armv3l() );
572  defCompatibleWith( a_armv4tl(), a_noarch(),a_armv3l(),a_armv4l() );
573  defCompatibleWith( a_armv5l(), a_noarch(),a_armv3l(),a_armv4l(),a_armv4tl() );
574  defCompatibleWith( a_armv5tl(), a_noarch(),a_armv3l(),a_armv4l(),a_armv4tl(),a_armv5l() );
575  defCompatibleWith( a_armv5tel(), a_noarch(),a_armv3l(),a_armv4l(),a_armv4tl(),a_armv5l(),a_armv5tl() );
576  defCompatibleWith( a_armv5tejl(), a_noarch(),a_armv3l(),a_armv4l(),a_armv4tl(),a_armv5l(),a_armv5tl(),a_armv5tel() );
577  defCompatibleWith( a_armv6l(), a_noarch(),a_armv3l(),a_armv4l(),a_armv4tl(),a_armv5l(),a_armv5tl(),a_armv5tel(),a_armv5tejl() );
578  defCompatibleWith( a_armv7l(), a_noarch(),a_armv3l(),a_armv4l(),a_armv4tl(),a_armv5l(),a_armv5tl(),a_armv5tel(),a_armv5tejl(),a_armv6l() );
579  defCompatibleWith( a_armv8l(), a_noarch(),a_armv3l(),a_armv4l(),a_armv4tl(),a_armv5l(),a_armv5tl(),a_armv5tel(),a_armv5tejl(),a_armv6l(),a_armv7l() );
580 
581  defCompatibleWith( a_armv6hl(), a_noarch() );
582  defCompatibleWith( a_armv7hl(), a_noarch(),a_armv6hl() );
583  defCompatibleWith( a_armv8hl(), a_noarch(),a_armv7hl() );
584  defCompatibleWith( a_armv7hnl(), a_noarch(),a_armv7hl(),a_armv6hl() );
585  /*legacy: rpm uses v7hnl */
586  defCompatibleWith( a_armv7nhl(), a_noarch(),a_armv7hnl(),a_armv7hl(),a_armv6hl() );
587 
588  /*?*/defCompatibleWith( a_armv7thl(), a_noarch(),a_armv7hl() );
589  /*?*/defCompatibleWith( a_armv7tnhl(), a_noarch(),a_armv7hl(),a_armv7nhl(),a_armv7thl() );
590 
591  defCompatibleWith( a_aarch64(), a_noarch() );
592  //
593  defCompatibleWith( a_riscv64(), a_noarch() );
594  //
595  defCompatibleWith( a_sh3(), a_noarch() );
596  //
597  defCompatibleWith( a_sh4(), a_noarch() );
598  defCompatibleWith( a_sh4a(), a_noarch(),a_sh4() );
599 
600  defCompatibleWith( a_m68k(), a_noarch() );
601 
602  defCompatibleWith( a_mips(), a_noarch() );
603  defCompatibleWith( a_mipsel(), a_noarch() );
604  defCompatibleWith( a_mips64(), a_noarch() );
605  defCompatibleWith( a_mips64el(), a_noarch() );
606 
607  defCompatibleWith( a_loong64(), a_noarch() );
608  //
610  // dumpOn( USR ) << endl;
611  }
612 
613  private:
619  CompatBits::IntT nextIdBit() const
620  {
621  if ( CompatBits::size == _compatSet.size() )
622  {
623  // Provide more bits in CompatBits::IntT
624  INT << "Need more than " << CompatBits::size << " bits to encode architectures." << endl;
625  ZYPP_THROW( Exception("Need more bits to encode architectures.") );
626  }
627  CompatBits::IntT nextBit = CompatBits::IntT(1) << (_compatSet.size());
628  return nextBit;
629  }
630 
634  const CompatEntry & assertCompatSetEntry( IdString archStr_r )
635  { return *_compatSet.insert( Arch::CompatEntry( archStr_r, nextIdBit() ) ).first; }
636 
639  void defCompatibleWith( IdString targetArch_r,
640  IdString arch0_r,
641  IdString arch1_r = IdString(),
642  IdString arch2_r = IdString(),
643  IdString arch3_r = IdString(),
644  IdString arch4_r = IdString(),
645  IdString arch5_r = IdString(),
646  IdString arch6_r = IdString(),
647  IdString arch7_r = IdString(),
648  IdString arch8_r = IdString(),
649  IdString arch9_r = IdString() )
650  {
651  const CompatEntry & target( assertCompatSetEntry( targetArch_r ) );
652  target.addCompatBit( assertCompatSetEntry( arch0_r )._idBit );
653 #define SETARG(N) if ( arch##N##_r.empty() ) return; target.addCompatBit( assertCompatSetEntry( arch##N##_r )._idBit )
654  SETARG(1); SETARG(2); SETARG(3); SETARG(4);
655  SETARG(5); SETARG(6); SETARG(7); SETARG(8); SETARG(9);
656 #undef SETARG
657  }
658 
659  private:
661  };
662 
664  } // namespace
666 
668  //
669  // CLASS NAME : Arch
670  //
672 
673  const Arch Arch_empty ( IdString::Empty );
674  // remaining Arch_* constants are defined by DEF_BUILTIN above.
675 
677  //
678  // METHOD NAME : Arch::Arch
679  // METHOD TYPE : Ctor
680  //
682  : _entry( &ArchCompatSet::instance().assertDef( a_noarch() ) )
683  {}
684 
686  : _entry( &ArchCompatSet::instance().assertDef( IdString(id_r) ) )
687  {}
688 
689  Arch::Arch( const IdString & idstr_r )
690  : _entry( &ArchCompatSet::instance().assertDef( idstr_r ) )
691  {}
692 
693  Arch::Arch( const std::string & str_r )
694  : _entry( &ArchCompatSet::instance().assertDef( str_r ) )
695  {}
696 
697  Arch::Arch( const char * cstr_r )
698  : _entry( &ArchCompatSet::instance().assertDef( cstr_r ) )
699  {}
700 
702  {
703  static Arch _val( _autoDetectSystemArchitecture() );
704  return _val;
705  }
706 
707  Arch::Arch( const CompatEntry & rhs )
708  : _entry( &rhs )
709  {}
710 
712  //
713  // METHOD NAME : Arch::idStr
714  // METHOD TYPE : IdString
715  //
717  { return _entry->_idStr; }
718 
720  //
721  // METHOD NAME : Arch::asString
722  // METHOD TYPE : const std::string &
723  //
724  const std::string & Arch::asString() const
725  { return _entry->_archStr; }
726 
728  //
729  // METHOD NAME : Arch::isBuiltIn
730  // METHOD TYPE : bool
731  //
732  bool Arch::isBuiltIn() const
733  { return _entry->isBuiltIn(); }
734 
736  //
737  // METHOD NAME : Arch::compatibleWith
738  // METHOD TYPE : bool
739  //
740  bool Arch::compatibleWith( const Arch & targetArch_r ) const
741  { return _entry->compatibleWith( *targetArch_r._entry ); }
742 
744  //
745  // METHOD NAME : Arch::baseArch
746  // METHOD TYPE : Arch
747  //
749  {
750  // check the multilib archs:
751  if (Arch_x86_64.compatibleWith(*this))
752  {
753  return Arch_x86_64;
754  }
755  if (Arch_sparc64v.compatibleWith(*this))
756  {
757  return Arch_sparc64v;
758  }
759  if (Arch_sparc64.compatibleWith(*this))
760  {
761  return Arch_sparc64;
762  }
763  if (Arch_ppc64.compatibleWith(*this))
764  {
765  return Arch_ppc64;
766  }
767  if (Arch_s390x.compatibleWith(*this))
768  {
769  return Arch_s390x;
770  }
771  // Here: no multilib; return arch before noarch
772  CompatSet cset( compatSet( *this ) );
773  if ( cset.size() > 2 ) // systemArchitecture, ..., basearch, noarch
774  {
775  return *(++cset.rbegin());
776  }
777  return *this;
778  }
779 
781  //
782  // METHOD NAME : Arch::compare
783  // METHOD TYPE : bool
784  //
785  int Arch::compare( const Arch & rhs ) const
786  { return _entry->compare( *rhs._entry ); }
787 
789  //
790  // METHOD NAME : Arch::compatSet
791  // METHOD TYPE : Arch::CompatSet
792  //
793  Arch::CompatSet Arch::compatSet( const Arch & targetArch_r )
794  {
795  Arch::CompatSet ret;
796 
797  for ( ArchCompatSet::const_iterator it = ArchCompatSet::instance().begin();
798  it != ArchCompatSet::instance().end(); ++it )
799  {
800  if ( it->compatibleWith( *targetArch_r._entry ) )
801  {
802  ret.insert( Arch(*it) );
803  }
804  }
805 
806  return ret;
807  }
808 
810 } // namespace zypp
#define MIL
Definition: Logger.h:103
bool operator==(const Capability &lhs, const Capability &rhs)
relates: Capability
Definition: Capability.h:309
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:459
Architecture.
Definition: Arch.h:36
IdType id() const
Expert backdoor.
Definition: IdString.h:144
#define INT
Definition: Logger.h:107
TInt value() const
Return the value.
Definition: Bit.h:179
static Arch detectSystemArchitecture()
Determine system architecture evaluating uname and /proc/cpuinfo.
Definition: Arch.cc:701
const Arch Arch_empty(IdString::Empty)
String related utilities and Regular expression matching.
Access to the sat-pools string space.
Definition: IdString.h:51
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition: Easy.h:27
int compare(const Arch &rhs) const
Arch comparison.
Definition: Arch.cc:785
CompatEntry(const std::string &archStr_r, CompatBits::IntT idBit_r=1)
Definition: Arch.cc:265
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Definition: String.cc:39
#define SETARG(N)
IdString::IdType id() const
Definition: Arch.cc:318
bool compatibleWith(const Arch &targetArch_r) const
Compatibility relation.
Definition: Arch.cc:740
sat::detail::IdType IdType
Definition: IdString.h:57
#define ERR
Definition: Logger.h:105
bit::BitField< uint64_t > CompatBits
Bitfield for architecture IDs and compatBits relation.
Definition: Arch.cc:263
Set _compatSet
Definition: Arch.cc:660
const CompatEntry * _entry
Definition: Arch.h:153
static const IdString Empty
Empty string.
Definition: IdString.h:89
bool compatibleWith(const CompatEntry &targetEntry_r) const
Return whether this is compatible with targetEntry_r.
Definition: Arch.cc:290
#define WAR
Definition: Logger.h:104
bool operator!=(const Capability &lhs, const Capability &rhs)
relates: Capability
Definition: Capability.h:313
Arch baseArch() const
Definition: Arch.cc:748
DEF_BUILTIN(noarch)
std::set< Arch, CompareByGT< Arch > > CompatSet
Reversed arch order, best Arch first.
Definition: Arch.h:122
std::ostream & dumpOn(std::ostream &str, const Capability &obj)
relates: Capability Detailed stream output
Definition: Capability.cc:589
std::string numstring(char n, int w=0)
Definition: String.h:290
static CompatSet compatSet(const Arch &targetArch_r)
Return a set of all Arch&#39;s compatibleWith a targetArch_r.
Definition: Arch.cc:793
void addCompatBit(const CompatBits &idBit_r) const
Definition: Arch.cc:281
IdString idStr() const
String representation of Arch.
Definition: Arch.cc:716
Arch()
Default ctor Arc_noarch.
Definition: Arch.cc:681
ZYPP_DEFINE_ID_HASHABLE(zypp::Arch::CompatEntry)
CompatBits _compatBits
Definition: Arch.cc:324
std::string _archStr
Definition: Arch.cc:322
bool isBuiltIn() const
Whether this is a buitin (or known) architecture.
Definition: Arch.cc:732
const std::string & asString() const
Definition: Arch.cc:724
std::ostream & operator<<(std::ostream &str, const Capabilities &obj)
relates: Capabilities Stream output
Definition: Capabilities.cc:65
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:1
CompatEntry(IdString archStr_r, CompatBits::IntT idBit_r=1)
Definition: Arch.cc:273
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Return whether str_r has prefix prefix_r.
Definition: String.h:1098
zypp::IdString IdString
Definition: idstring.h:16
bool isBuiltIn() const
Definition: Arch.cc:315
int compare(const CompatEntry &rhs) const
compare by score, then archStr.
Definition: Arch.cc:308
boost::noncopyable NonCopyable
Ensure derived classes cannot be copied.
Definition: NonCopyable.h:26
CompatBits _idBit
Definition: Arch.cc:323
Holds an architecture ID and its compatible relation.
Definition: Arch.cc:257