05ec4a39de70462ab9ff66adf33e0ba73e87e518
[platform/upstream/libzypp.git] / zypp / Arch.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/Arch.cc
10  *
11 */
12 #include <iostream>
13 #include <list>
14 #include <inttypes.h>
15
16 #include "zypp/base/Logger.h"
17 #include "zypp/base/Exception.h"
18 #include "zypp/base/NonCopyable.h"
19 #include "zypp/base/Tr1hash.h"
20 #include "zypp/Arch.h"
21 #include "zypp/Bit.h"
22
23 using std::endl;
24
25 ///////////////////////////////////////////////////////////////////
26 namespace zypp
27 { /////////////////////////////////////////////////////////////////
28
29   ///////////////////////////////////////////////////////////////////
30   //
31   //    CLASS NAME : Arch::CompatEntry
32   //
33   /** Holds an architecture ID and it's compatible relation.
34    * An architecture is compatibleWith, if it's _idBit is set in
35    * _compatBits. noarch has ID 0, non builtin archs ID 1 and
36    * have to be treated specialy.
37   */
38   struct Arch::CompatEntry
39   {
40     /** Bitfield for architecture IDs and compatBits relation.
41      * \note Need one bit for each builtin Arch.
42      * \todo Migrate to some infinite BitField
43     */
44     typedef bit::BitField<uint64_t> CompatBits;
45
46     CompatEntry( const std::string & archStr_r,
47                  CompatBits::IntT idBit_r = 1 )
48     : _idStr( archStr_r )
49     , _archStr( archStr_r )
50     , _idBit( idBit_r )
51     , _compatBits( idBit_r )
52     {}
53
54     CompatEntry( IdString archStr_r,
55                  CompatBits::IntT idBit_r = 1 )
56     : _idStr( archStr_r )
57     , _archStr( archStr_r.asString() )
58     , _idBit( idBit_r )
59     , _compatBits( idBit_r )
60     {}
61
62     void addCompatBit( const CompatBits & idBit_r ) const
63     {
64       if ( idBit_r && ! (_compatBits & idBit_r) )
65         {
66           _compatBits |= idBit_r;
67         }
68     }
69
70     /** Return whether \c this is compatible with \a targetEntry_r.*/
71     bool compatibleWith( const CompatEntry & targetEntry_r ) const
72     {
73       switch ( _idBit.value() )
74         {
75         case 0:
76           // this is noarch and always comatible
77           return true;
78           break;
79         case 1:
80           // this is a non builtin: self compatible only
81           return _archStr == targetEntry_r._archStr;
82           break;
83         }
84       // This is a builtin: compatible if mentioned in targetEntry_r
85       return bool( targetEntry_r._compatBits & _idBit );
86     }
87
88     /** compare by score, then archStr. */
89     int compare( const CompatEntry & rhs ) const
90     {
91       if ( _idBit.value() != rhs. _idBit.value() )
92         return( _idBit.value() < rhs. _idBit.value() ? -1 : 1 );
93       return _archStr.compare( rhs._archStr ); // Id 1: non builtin
94     }
95
96     bool isBuiltIn() const
97     { return( _idBit != CompatBits(1) ); }
98
99     IdString::IdType id() const
100     { return _idStr.id(); }
101
102     IdString            _idStr;
103     std::string         _archStr; // frequently used by the UI so we keep a reference
104     CompatBits          _idBit;
105     mutable CompatBits  _compatBits;
106   };
107   ///////////////////////////////////////////////////////////////////
108
109   /** \relates Arch::CompatEntry Stream output */
110   inline std::ostream & operator<<( std::ostream & str, const Arch::CompatEntry & obj )
111   {
112     Arch::CompatEntry::CompatBits bit( obj._idBit );
113     unsigned bitnum = 0;
114     while ( bit )
115     {
116       ++bitnum;
117       bit >>= 1;
118     }
119     return str << str::form( "%-15s ", obj._archStr.c_str() ) << str::numstring(bitnum,2) << ' '
120                << obj._compatBits << ' ' << obj._compatBits.value();
121   }
122
123   /** \relates Arch::CompatEntry */
124   inline bool operator==( const Arch::CompatEntry & lhs, const Arch::CompatEntry & rhs )
125   { return lhs._idStr == rhs._idStr; }
126   /** \relates Arch::CompatEntry */
127   inline bool operator!=( const Arch::CompatEntry & lhs, const Arch::CompatEntry & rhs )
128   { return ! ( lhs == rhs ); }
129
130   /////////////////////////////////////////////////////////////////
131 } // namespace zypp
132 ///////////////////////////////////////////////////////////////////
133
134 ZYPP_DEFINE_ID_HASHABLE( zypp::Arch::CompatEntry );
135
136 ///////////////////////////////////////////////////////////////////
137 namespace zypp
138 { /////////////////////////////////////////////////////////////////
139
140   // Builtin architecture STRING VALUES to be
141   // used in defCompatibleWith below!
142   //
143   // const IdString  _foo( "foo" );
144   // const Arch Arch_foo( _foo() );
145   //
146   // NOTE: Builtin CLASS Arch CONSTANTS are defined below.
147   //       You have to change them accordingly in Arch.h.
148   //
149   // NOTE: Thake care CompatBits::IntT is able to provide one
150   //       bit for each architecture.
151   //
152   #define DEF_BUILTIN(A) \
153   namespace { static inline const IdString & _##A () { static IdString __str(#A); return __str; } } \
154   const Arch Arch_##A( _##A() )
155
156   DEF_BUILTIN( noarch );
157
158   DEF_BUILTIN( i386 );
159   DEF_BUILTIN( i486 );
160   DEF_BUILTIN( i586 );
161   DEF_BUILTIN( i686 );
162   DEF_BUILTIN( athlon );
163   DEF_BUILTIN( x86_64 );
164
165   DEF_BUILTIN( pentium3 );
166   DEF_BUILTIN( pentium4 );
167
168   DEF_BUILTIN( s390 );
169   DEF_BUILTIN( s390x );
170
171   DEF_BUILTIN( ppc );
172   DEF_BUILTIN( ppc64 );
173   DEF_BUILTIN( ppc64p7 );
174
175   DEF_BUILTIN( ppc64le );
176
177   DEF_BUILTIN( ia64 );
178
179   DEF_BUILTIN( alphaev67 );
180   DEF_BUILTIN( alphaev6 );
181   DEF_BUILTIN( alphapca56 );
182   DEF_BUILTIN( alphaev56 );
183   DEF_BUILTIN( alphaev5 );
184   DEF_BUILTIN( alpha );
185
186   DEF_BUILTIN( sparc64v );
187   DEF_BUILTIN( sparcv9v );
188   DEF_BUILTIN( sparc64 );
189   DEF_BUILTIN( sparcv9 );
190   DEF_BUILTIN( sparcv8 );
191   DEF_BUILTIN( sparc );
192
193   DEF_BUILTIN( aarch64 );
194   DEF_BUILTIN( armv7tnhl );
195   DEF_BUILTIN( armv7thl );
196   DEF_BUILTIN( armv7nhl );
197   DEF_BUILTIN( armv7hl );
198   DEF_BUILTIN( armv7l );
199   DEF_BUILTIN( armv6hl );
200   DEF_BUILTIN( armv6l );
201   DEF_BUILTIN( armv5tejl );
202   DEF_BUILTIN( armv5tel );
203   DEF_BUILTIN( armv5l );
204   DEF_BUILTIN( armv4tl );
205   DEF_BUILTIN( armv4l );
206   DEF_BUILTIN( armv3l );
207
208   DEF_BUILTIN( sh3 );
209
210   DEF_BUILTIN( sh4 );
211   DEF_BUILTIN( sh4a );
212
213   DEF_BUILTIN( m68k );
214
215   DEF_BUILTIN( mips );
216   DEF_BUILTIN( mipsel );
217   DEF_BUILTIN( mips64 );
218   DEF_BUILTIN( mips64el );
219 #undef DEF_BUILTIN
220
221   ///////////////////////////////////////////////////////////////////
222   namespace
223   { /////////////////////////////////////////////////////////////////
224
225     ///////////////////////////////////////////////////////////////////
226     //
227     //  CLASS NAME : CompatSet
228     //
229     /** Maintain architecture compatibility (Singleton by the way it is used).
230      *
231      * Povides \ref Arch::CompatEntry for \ref Arch. Defines the
232      * compatibleWith relation.
233      * \li \c noarch has _idBit 0
234      * \li \c nonbuiltin archs have _idBit 1
235     */
236     struct ArchCompatSet : private base::NonCopyable
237     {
238       typedef Arch::CompatEntry       CompatEntry;
239       typedef CompatEntry::CompatBits CompatBits;
240
241       typedef std::tr1::unordered_set<CompatEntry> Set;
242       typedef Set::iterator           iterator;
243       typedef Set::const_iterator     const_iterator;
244
245       /** Singleton access. */
246       static ArchCompatSet & instance()
247       {
248         static ArchCompatSet _instance;
249         return _instance;
250       }
251
252       /** Return the entry related to \a archStr_r.
253        * Creates an entry for nonbuiltin archs.
254       */
255       const Arch::CompatEntry & assertDef( const std::string & archStr_r )
256       { return *_compatSet.insert( Arch::CompatEntry( archStr_r ) ).first; }
257       /** \overload */
258       const Arch::CompatEntry & assertDef( IdString archStr_r )
259       { return *_compatSet.insert( Arch::CompatEntry( archStr_r ) ).first; }
260
261       const_iterator begin() const
262       { return _compatSet.begin(); }
263
264       const_iterator end() const
265       { return _compatSet.end(); }
266
267       struct DumpOnCompare
268       {
269         int operator()( const CompatEntry & lhs,  const CompatEntry & rhs ) const
270         { return lhs._idBit.value() < rhs._idBit.value(); }
271       };
272
273       std::ostream & dumpOn( std::ostream & str ) const
274       {
275         str << "ArchCompatSet:";
276         std::list<CompatEntry> ov( _compatSet.begin(), _compatSet.end() );
277         ov.sort( DumpOnCompare() );
278         for_( it, ov.begin(), ov.end() )
279           {
280             str << endl << ' ' << *it;
281           }
282         return str;
283       }
284
285     private:
286       /** Singleton ctor. */
287       ArchCompatSet()
288       {
289         // _noarch must have _idBit 0.
290         // Other builtins have 1-bit set
291         // and are initialized done on the fly.
292         _compatSet.insert( Arch::CompatEntry( _noarch(), 0 ) );
293         ///////////////////////////////////////////////////////////////////
294         // Define the CompatibleWith relation:
295         //
296         // NOTE: Order of definition is significant! (Arch::compare)
297         //       - define compatible (less) architectures first!
298         //
299         defCompatibleWith( _i386(),             _noarch() );
300         defCompatibleWith( _i486(),             _noarch(),_i386() );
301         defCompatibleWith( _i586(),             _noarch(),_i386(),_i486() );
302         defCompatibleWith( _i686(),             _noarch(),_i386(),_i486(),_i586() );
303         defCompatibleWith( _athlon(),           _noarch(),_i386(),_i486(),_i586(),_i686() );
304         defCompatibleWith( _x86_64(),           _noarch(),_i386(),_i486(),_i586(),_i686(),_athlon() );
305
306         defCompatibleWith( _pentium3(),         _noarch(),_i386(),_i486(),_i586(),_i686() );
307         defCompatibleWith( _pentium4(),         _noarch(),_i386(),_i486(),_i586(),_i686(),_pentium3() );
308
309         defCompatibleWith( _ia64(),             _noarch(),_i386(),_i486(),_i586(),_i686() );
310         //
311         defCompatibleWith( _s390(),             _noarch() );
312         defCompatibleWith( _s390x(),            _noarch(),_s390() );
313         //
314         defCompatibleWith( _ppc(),              _noarch() );
315         defCompatibleWith( _ppc64(),            _noarch(),_ppc() );
316         defCompatibleWith( _ppc64p7(),          _noarch(),_ppc(),_ppc64() );
317         //
318         defCompatibleWith( _ppc64le(),          _noarch() );
319         //
320         defCompatibleWith( _alpha(),            _noarch() );
321         defCompatibleWith( _alphaev5(),         _noarch(),_alpha() );
322         defCompatibleWith( _alphaev56(),        _noarch(),_alpha(),_alphaev5() );
323         defCompatibleWith( _alphapca56(),       _noarch(),_alpha(),_alphaev5(),_alphaev56() );
324         defCompatibleWith( _alphaev6(),         _noarch(),_alpha(),_alphaev5(),_alphaev56(),_alphapca56() );
325         defCompatibleWith( _alphaev67(),        _noarch(),_alpha(),_alphaev5(),_alphaev56(),_alphapca56(),_alphaev6() );
326         //
327         defCompatibleWith( _sparc(),            _noarch() );
328         defCompatibleWith( _sparcv8(),          _noarch(),_sparc() );
329         defCompatibleWith( _sparcv9(),          _noarch(),_sparc(),_sparcv8() );
330         defCompatibleWith( _sparcv9v(),         _noarch(),_sparc(),_sparcv8(),_sparcv9() );
331         //
332         defCompatibleWith( _sparc64(),          _noarch(),_sparc(),_sparcv8(),_sparcv9() );
333         defCompatibleWith( _sparc64v(),         _noarch(),_sparc(),_sparcv8(),_sparcv9(),_sparcv9v(),_sparc64() );
334         //
335         defCompatibleWith( _armv3l(),           _noarch() );
336         defCompatibleWith( _armv4l(),           _noarch(),_armv3l() );
337         defCompatibleWith( _armv4tl(),          _noarch(),_armv3l(),_armv4l() );
338         defCompatibleWith( _armv5l(),           _noarch(),_armv3l(),_armv4l(),_armv4tl() );
339         defCompatibleWith( _armv5tel(),         _noarch(),_armv3l(),_armv4l(),_armv4tl(),_armv5l() );
340         defCompatibleWith( _armv5tejl(),        _noarch(),_armv3l(),_armv4l(),_armv4tl(),_armv5l(),_armv5tel() );
341         defCompatibleWith( _armv6l(),           _noarch(),_armv3l(),_armv4l(),_armv4tl(),_armv5l(),_armv5tel(),_armv5tejl() );
342         defCompatibleWith( _armv6hl(),          _noarch() );
343         defCompatibleWith( _armv7l(),           _noarch(),_armv3l(),_armv4l(),_armv4tl(),_armv5l(),_armv5tel(),_armv5tejl(),_armv6l() );
344         defCompatibleWith( _armv7hl(),          _noarch(),_armv6hl() );
345         defCompatibleWith( _armv7nhl(),         _noarch(),_armv7hl() );
346         defCompatibleWith( _armv7thl(),         _noarch(),_armv7hl() );
347         defCompatibleWith( _armv7tnhl(),        _noarch(),_armv7hl(),_armv7nhl(),_armv7thl() );
348         defCompatibleWith( _aarch64(),          _noarch() );
349         //
350         defCompatibleWith( _sh3(),              _noarch() );
351         //
352         defCompatibleWith( _sh4(),              _noarch() );
353         defCompatibleWith( _sh4a(),             _noarch(),_sh4() );
354
355         defCompatibleWith( _m68k(),             _noarch() );
356
357         defCompatibleWith( _mips(),             _noarch() );
358         defCompatibleWith( _mipsel(),           _noarch() );
359         defCompatibleWith( _mips64(),           _noarch() );
360         defCompatibleWith( _mips64el(),         _noarch() );
361         //
362         ///////////////////////////////////////////////////////////////////
363         // dumpOn( USR ) << endl;
364       }
365
366     private:
367       /** Return the next avialable _idBit.
368        * Ctor injects _noarch into the _compatSet, 1 is for
369        * nonbuiltin archs, so we can use <tt>size</tt> for
370        * buitin archs.
371       */
372       CompatBits::IntT nextIdBit() const
373       {
374         if ( CompatBits::size == _compatSet.size() )
375         {
376           // Provide more bits in CompatBits::IntT
377           INT << "Need more than " << CompatBits::size << " bits to encode architectures." << endl;
378           ZYPP_THROW( Exception("Need more bits to encode architectures.") );
379         }
380         CompatBits::IntT nextBit = CompatBits::IntT(1) << (_compatSet.size());
381         return nextBit;
382       }
383
384       /** Assert each builtin Arch gets an unique _idBit when
385        *  inserted into the _compatSet.
386       */
387       const CompatEntry & assertCompatSetEntry( IdString archStr_r )
388       { return *_compatSet.insert( Arch::CompatEntry( archStr_r, nextIdBit() ) ).first; }
389
390       /** Initialize builtin Archs and set _compatBits.
391       */
392       void defCompatibleWith( IdString targetArch_r,
393                               IdString arch0_r,
394                               IdString arch1_r = IdString(),
395                               IdString arch2_r = IdString(),
396                               IdString arch3_r = IdString(),
397                               IdString arch4_r = IdString(),
398                               IdString arch5_r = IdString(),
399                               IdString arch6_r = IdString(),
400                               IdString arch7_r = IdString(),
401                               IdString arch8_r = IdString(),
402                               IdString arch9_r = IdString() )
403       {
404         const CompatEntry & target( assertCompatSetEntry( targetArch_r ) );
405         target.addCompatBit( assertCompatSetEntry( arch0_r )._idBit );
406 #define _SETARG(N) if ( arch##N##_r.empty() ) return; target.addCompatBit( assertCompatSetEntry( arch##N##_r )._idBit )
407         _SETARG(1); _SETARG(2); _SETARG(3); _SETARG(4);
408         _SETARG(5); _SETARG(6); _SETARG(7); _SETARG(8); _SETARG(9);
409 #undef _SETARG
410       }
411
412     private:
413       Set _compatSet;
414     };
415
416     /////////////////////////////////////////////////////////////////
417   } // namespace
418   ///////////////////////////////////////////////////////////////////
419
420   ///////////////////////////////////////////////////////////////////
421   //
422   //    CLASS NAME : Arch
423   //
424   ///////////////////////////////////////////////////////////////////
425
426   const Arch Arch_empty ( IdString::Empty );
427   // remaining Arch_* constants are defined by DEF_BUILTIN above.
428
429   ///////////////////////////////////////////////////////////////////
430   //
431   //    METHOD NAME : Arch::Arch
432   //    METHOD TYPE : Ctor
433   //
434   Arch::Arch()
435   : _entry( &ArchCompatSet::instance().assertDef( _noarch() ) )
436   {}
437
438   Arch::Arch( IdString::IdType id_r )
439   : _entry( &ArchCompatSet::instance().assertDef( IdString(id_r) ) )
440   {}
441
442   Arch::Arch( const IdString & idstr_r )
443   : _entry( &ArchCompatSet::instance().assertDef( idstr_r ) )
444   {}
445
446   Arch::Arch( const std::string & str_r )
447   : _entry( &ArchCompatSet::instance().assertDef( str_r ) )
448   {}
449
450   Arch::Arch( const char * cstr_r )
451   : _entry( &ArchCompatSet::instance().assertDef( cstr_r ) )
452   {}
453
454   Arch::Arch( const CompatEntry & rhs )
455   : _entry( &rhs )
456   {}
457
458   ///////////////////////////////////////////////////////////////////
459   //
460   //    METHOD NAME : Arch::idStr
461   //    METHOD TYPE : IdString
462   //
463   IdString Arch::idStr() const
464   { return _entry->_idStr; }
465
466   ///////////////////////////////////////////////////////////////////
467   //
468   //    METHOD NAME : Arch::asString
469   //    METHOD TYPE : const std::string &
470   //
471   const std::string & Arch::asString() const
472   { return _entry->_archStr; }
473
474   ///////////////////////////////////////////////////////////////////
475   //
476   //    METHOD NAME : Arch::isBuiltIn
477   //    METHOD TYPE : bool
478   //
479   bool Arch::isBuiltIn() const
480   { return _entry->isBuiltIn(); }
481
482   ///////////////////////////////////////////////////////////////////
483   //
484   //    METHOD NAME : Arch::compatibleWith
485   //    METHOD TYPE : bool
486   //
487   bool Arch::compatibleWith( const Arch & targetArch_r ) const
488   { return _entry->compatibleWith( *targetArch_r._entry ); }
489
490   ///////////////////////////////////////////////////////////////////
491   //
492   //    METHOD NAME : Arch::baseArch
493   //    METHOD TYPE : Arch
494   //
495   Arch Arch::baseArch( ) const
496   {
497     // check the multilib archs:
498     if (Arch_x86_64.compatibleWith(*this))
499     {
500       return Arch_x86_64;
501     }
502     if (Arch_sparc64v.compatibleWith(*this))
503     {
504       return Arch_sparc64v;
505     }
506     if (Arch_sparc64.compatibleWith(*this))
507     {
508       return Arch_sparc64;
509     }
510     if (Arch_ppc64.compatibleWith(*this))
511     {
512       return Arch_ppc64;
513     }
514     if (Arch_s390x.compatibleWith(*this))
515     {
516       return Arch_s390x;
517     }
518     // Here: no multilib; return arch before noarch
519     CompatSet cset( compatSet( *this ) );
520     if ( cset.size() > 2 )      // systemArchitecture, ..., basearch, noarch
521     {
522       return *(++cset.rbegin());
523     }
524     return *this;
525   }
526
527   ///////////////////////////////////////////////////////////////////
528   //
529   //    METHOD NAME : Arch::compare
530   //    METHOD TYPE : bool
531   //
532   int Arch::compare( const Arch & rhs ) const
533   { return _entry->compare( *rhs._entry ); }
534
535   ///////////////////////////////////////////////////////////////////
536   //
537   //    METHOD NAME : Arch::compatSet
538   //    METHOD TYPE : Arch::CompatSet
539   //
540   Arch::CompatSet Arch::compatSet( const Arch & targetArch_r )
541   {
542     Arch::CompatSet ret;
543
544     for ( ArchCompatSet::const_iterator it = ArchCompatSet::instance().begin();
545           it != ArchCompatSet::instance().end(); ++it )
546       {
547         if ( it->compatibleWith( *targetArch_r._entry ) )
548           {
549             ret.insert( Arch(*it) );
550           }
551       }
552
553     return ret;
554   }
555
556   /////////////////////////////////////////////////////////////////
557 } // namespace zypp
558 ///////////////////////////////////////////////////////////////////