Support dependencies requiring a specific architecture:
authorMichael Andres <ma@suse.de>
Wed, 23 Apr 2008 19:26:00 +0000 (19:26 +0000)
committerMichael Andres <ma@suse.de>
Wed, 23 Apr 2008 19:26:00 +0000 (19:26 +0000)
"name[.arch] [op edition]".

12 files changed:
VERSION.cmake
devel/devel.ma/NewPool.cc
package/libzypp.changes
tests/zypp/Arch_test.cc
tests/zypp/Capabilities_test.cc
zypp/Arch.cc
zypp/Arch.h
zypp/Capability.cc
zypp/Capability.h
zypp/IdStringType.h
zypp/sat/Solvable.cc
zypp/sat/detail/PoolImpl.cc

index 9bff196..5cc01fd 100644 (file)
@@ -45,6 +45,6 @@
 #
 
 SET(LIBZYPP_MAJOR "4")
-SET(LIBZYPP_MINOR "14")
+SET(LIBZYPP_MINOR "15")
 SET(LIBZYPP_COMPATMINOR "14")
 SET(LIBZYPP_PATCH "0")
index 53e0643..616f7da 100644 (file)
@@ -512,8 +512,17 @@ namespace zypp
   }
 }
 
-void ditest( const PoolItem & pi_r )
+void ditest( Capability cap_r )
 {
+  DBG << "    (" << cap_r.id() << ") " << endl;
+  DBG << "    " << cap_r << endl;
+  DBG << "    " << dump(cap_r) << endl;
+}
+
+void ditest( const std::string & str_r )
+{
+  MIL <<  str_r << endl;
+  ditest( Capability(str_r) );
 }
 
 /******************************************************************
@@ -591,13 +600,12 @@ try {
     }
   }
 
-  if ( 1 )
+  if ( 0 )
   {
     Measure x( "INIT TARGET" );
     {
       getZYpp()->initializeTarget( sysRoot );
       getZYpp()->target()->load();
-      SEC << getZYpp()->target()->release() << endl;
     }
   }
 
@@ -614,6 +622,20 @@ try {
   ///////////////////////////////////////////////////////////////////
   ///////////////////////////////////////////////////////////////////
 
+  ditest("foo");
+  ditest("foo.baa");
+  ditest("foo.i386");
+  ditest("foo.baa < 13");
+  ditest("foo.foo.baa < 13");
+  ditest("foo.foo.i386 < 13");
+  ditest("");
+
+  ///////////////////////////////////////////////////////////////////
+  INT << "===[END]============================================" << endl << endl;
+  zypp::base::LogControl::instance().logNothing();
+  return 0;
+
+
   if ( 0 ) {
     Measure x( "PROXY" );
     pool.proxy();
index 9db9ae1..909dc8d 100644 (file)
@@ -1,4 +1,13 @@
 -------------------------------------------------------------------
+Wed Apr 23 21:12:56 CEST 2008 - ma@suse.de
+
+- Support dependencies requiring a specific architecture: 
+  "name[.arch] [op edition]". See class Capability for details 
+  about how to construct dependencies. (bnc #305445)  
+- version 4.15.0
+- revision 9805
+
+-------------------------------------------------------------------
 Tue Apr 22 17:39:28 CEST 2008 - dmacvicar@suse.de
 
 - patch attributes and deprecate old ones
index de0beb6..2a7eaab 100644 (file)
@@ -31,15 +31,45 @@ using namespace zypp;
 */
 BOOST_AUTO_TEST_CASE(arch_test)
 {
-  Arch _arch32( "i386" );
-
-  BOOST_CHECK_EQUAL( _arch32, Arch_i386 );
-  BOOST_CHECK_EQUAL( _arch32.asString(), string("i386"));
-  BOOST_REQUIRE( _arch32.compatibleWith (Arch_x86_64));
-  BOOST_CHECK_THROW( Arch(NULL), exception);
-  BOOST_CHECK_EQUAL( Arch(), Arch_noarch );
-  BOOST_REQUIRE( Arch("") != Arch_noarch );
-  BOOST_REQUIRE( Arch("").empty() );
+  //////////////////////////////////////////////////////////////////////
+  //
+  //////////////////////////////////////////////////////////////////////
+  BOOST_REQUIRE( Arch()   == Arch_noarch );
+  BOOST_REQUIRE( Arch("") == Arch_empty );
   BOOST_REQUIRE( ! Arch_noarch.empty() );
-  BOOST_REQUIRE( ! ( _arch32.compare(Arch_x86_64) >= 0) );
+  BOOST_REQUIRE( Arch_empty.empty() );
+  BOOST_REQUIRE( Arch_noarch.isBuiltIn() );
+  BOOST_REQUIRE( ! Arch_empty.isBuiltIn() );
+  BOOST_REQUIRE( Arch_empty != Arch_noarch );
+  //////////////////////////////////////////////////////////////////////
+  //
+  //////////////////////////////////////////////////////////////////////
+  BOOST_CHECK_EQUAL( Arch("i386"), Arch_i386 );
+  BOOST_CHECK_EQUAL( Arch("i386").idStr(), "i386" );
+  BOOST_CHECK_EQUAL( Arch("i386").asString(), "i386" );
+  BOOST_REQUIRE( Arch_i386.isBuiltIn() );
+
+  BOOST_CHECK_EQUAL( Arch("FOO").idStr(), "FOO" );
+  BOOST_CHECK_EQUAL( Arch("FOO").asString(), "FOO" );
+  BOOST_REQUIRE( ! Arch("FOO").isBuiltIn() );
+  //////////////////////////////////////////////////////////////////////
+  //
+  //////////////////////////////////////////////////////////////////////
+  BOOST_REQUIRE( Arch_noarch.compatibleWith( Arch_noarch ) );
+  BOOST_REQUIRE( Arch_noarch.compatibleWith( Arch_i386 ) );
+  BOOST_REQUIRE( Arch_noarch.compatibleWith( Arch_x86_64 ) );
+
+  BOOST_REQUIRE( ! Arch_i386.compatibleWith( Arch_noarch ) );
+  BOOST_REQUIRE( Arch_i386.compatibleWith( Arch_i386 ) );
+  BOOST_REQUIRE( Arch_i386.compatibleWith( Arch_x86_64 ) );
+
+  BOOST_REQUIRE( ! Arch_x86_64.compatibleWith( Arch_noarch ) );
+  BOOST_REQUIRE( ! Arch_x86_64.compatibleWith( Arch_i386 ) );
+  BOOST_REQUIRE( Arch_x86_64.compatibleWith( Arch_x86_64 ) );
+  //////////////////////////////////////////////////////////////////////
+  //
+  //////////////////////////////////////////////////////////////////////
+  BOOST_REQUIRE( Arch_i386.compare( Arch_noarch ) >  0 );
+  BOOST_REQUIRE( Arch_i386.compare( Arch_i386 )   == 0 );
+  BOOST_REQUIRE( Arch_i386.compare( Arch_x86_64 ) <  0 );
 }
index 6c0323b..7bce883 100644 (file)
@@ -9,6 +9,7 @@
 #include <boost/test/floating_point_comparison.hpp>
 #include <boost/test/auto_unit_test.hpp>
 
+#include "zypp/Arch.h"
 #include "zypp/Capability.h"
 #include "zypp/Capabilities.h"
 
@@ -21,48 +22,14 @@ using namespace zypp;
 
 BOOST_AUTO_TEST_CASE(capabilities_test)
 {
-//     Resolvable::Kind kind = ResTraits<zypp::Package>::kind;
-//     CapFactory factory;
-//
-//     Edition edition ("1.0", "42");
-//     Capability cap = factory.parse ( kind, "foo", "=", "1.0-42");
-//     BOOST_CHECK_EQUAL( cap.asString(), "foo == 1.0-42" );
-//     BOOST_CHECK_EQUAL( cap.index(), "foo");
-//     BOOST_CHECK_EQUAL( cap.op(), Rel::EQ);
-//     BOOST_CHECK_EQUAL( cap.edition(), edition);
-//
-//     Capability cap2 = factory.parse ( kind, "foo", Rel::EQ, edition);
-//     BOOST_CHECK_EQUAL( cap2.index(), cap.index());
-//     BOOST_CHECK_EQUAL( cap2.op(), cap.op());
-//     BOOST_CHECK_EQUAL( cap2.edition(), cap.edition());
-//
-//     Capability cap3 = factory.parse ( kind, "foo = 1.0-42");
-//     BOOST_CHECK_EQUAL( cap3.index(), cap.index());
-//     BOOST_CHECK_EQUAL( cap3.op(), cap.op());
-//     BOOST_CHECK_EQUAL( cap3.edition(), cap.edition());
-//
-//     Capability cap6 = factory.parse ( kind, "kdelibs* > 1.5");
-//     BOOST_CHECK_EQUAL( cap6.index(), "kdelibs*");
-//     BOOST_CHECK_EQUAL( cap6.op(), Rel::GT);
-//     BOOST_CHECK_EQUAL( cap6.edition(), Edition("1.5"));
-//
-//
-//     string bash = "/bin/bash";
-//     Capability cap4 = factory.parse ( kind, bash);
-//     BOOST_CHECK_EQUAL(cap4.index(), bash);
-//     BOOST_CHECK_EQUAL(cap4.op(), Rel::NONE);
-//     BOOST_CHECK_EQUAL(cap4.edition(), Edition::noedition);
-//
-//     string hal = "hal(smp)";
-//     Capability cap5 = factory.parse ( kind, hal);
-//     BOOST_CHECK_EQUAL(cap5.index(), "hal()");
-//     BOOST_CHECK_EQUAL(cap5.op(), Rel::NONE);
-//     BOOST_CHECK_EQUAL(cap5.edition(), Edition::noedition);
+  //////////////////////////////////////////////////////////////////////
+  // Id 0 and 1 are nor equal, but share the same representation ""/NOCAP
+  //////////////////////////////////////////////////////////////////////
 
-  Capability c0( 0 ); // id 0
-  Capability c1( 1 ); // id 1
-  Capability cD;      // default constructed empty
-  Capability cE( "" );// empty
+  Capability c0( 0 );  // id 0
+  Capability c1( 1 );  // id 1
+  Capability cD;       // default constructed empty
+  Capability cE( "" ); // empty
 
   BOOST_CHECK_EQUAL( c0.id(), 0 );
   BOOST_CHECK_EQUAL( c1.id(), 1 );
@@ -81,6 +48,9 @@ BOOST_AUTO_TEST_CASE(capabilities_test)
   BOOST_CHECK_EQUAL( ( c0 == c1 ), false );
   BOOST_CHECK_EQUAL( Capability::matches( c0, c1 ), CapMatch::yes );
 
+  //////////////////////////////////////////////////////////////////////
+  // skipping internal marker in Capabilities
+  //////////////////////////////////////////////////////////////////////
 
   Capability r( "req" );
   Capability p( "prereq" );
@@ -93,7 +63,7 @@ BOOST_AUTO_TEST_CASE(capabilities_test)
 
   // Capabilities with and without prereq (skip marker in ++)
   Capabilities c( caps );
-  cout << c << endl;
+  //cout << c << endl;
   BOOST_CHECK_EQUAL( c.size(), 2 );
   Capabilities::const_iterator it( c.begin() );
   BOOST_CHECK_EQUAL( *it, r );
@@ -104,11 +74,39 @@ BOOST_AUTO_TEST_CASE(capabilities_test)
 
   // Capabilities with prereq only (skip marker in ctor)
   c = Capabilities( caps+1 );
-  cout << c << endl;
+  //cout << c << endl;
   BOOST_CHECK_EQUAL( c.size(), 1 );
   it = c.begin();
   BOOST_CHECK_EQUAL( *it, p );
   BOOST_CHECK_EQUAL( it.tagged(), true );
 
+
+  //////////////////////////////////////////////////////////////////////
+  //
+  //////////////////////////////////////////////////////////////////////
+  Capability n( "na.me" );
+  Capability na( "na.me.i386" );
+  Capability noe( "na.me == 1" );
+  Capability naoe( "na.me.i386 == 1" );
+
+  BOOST_CHECK_EQUAL( n.detail().kind(), CapDetail::NAMED );
+  BOOST_CHECK_EQUAL( na.detail().kind(), CapDetail::NAMED );
+  BOOST_CHECK_EQUAL( noe.detail().kind(), CapDetail::VERSIONED );
+  BOOST_CHECK_EQUAL( naoe.detail().kind(), CapDetail::VERSIONED );
+
+  BOOST_CHECK_EQUAL( n.detail().hasArch(), false );
+  BOOST_CHECK_EQUAL( na.detail().hasArch(), true );
+  BOOST_CHECK_EQUAL( noe.detail().hasArch(), false );
+  BOOST_CHECK_EQUAL( naoe.detail().hasArch(), true );
+
+  BOOST_REQUIRE    ( n.detail().arch().empty() );
+  BOOST_CHECK_EQUAL( na.detail().arch(), Arch_i386.idStr() );
+  BOOST_REQUIRE    ( noe.detail().arch().empty() );
+  BOOST_CHECK_EQUAL( naoe.detail().arch(), Arch_i386.idStr() );
+
+  BOOST_CHECK_EQUAL( Capability( "",     "na.me", "",   "" ), n );
+  BOOST_CHECK_EQUAL( Capability( "i386", "na.me", "",   "" ), na );
+  BOOST_CHECK_EQUAL( Capability( "",     "na.me", "==", "1" ), noe );
+  BOOST_CHECK_EQUAL( Capability( "i386", "na.me", "==", "1" ), naoe );
 }
 
index 5b5600e..c4850b4 100644 (file)
@@ -14,6 +14,7 @@
 
 #include "zypp/base/Logger.h"
 #include "zypp/base/NonCopyable.h"
+#include "zypp/base/Tr1hash.h"
 #include "zypp/Arch.h"
 #include "zypp/Bit.h"
 
@@ -29,7 +30,7 @@ namespace zypp
   //
   /** Holds an architecture ID and it's compatible relation.
    * An architecture is compatibleWith, if it's _idBit is set in
-   * _compatBits. noarch has ID 0, non builtin archs id 1 and
+   * _compatBits. noarch has ID 0, non builtin archs ID 1 and
    * have to be treated specialy.
   */
   struct Arch::CompatEntry
@@ -37,11 +38,21 @@ namespace zypp
     /** Bitfield for architecture IDs and compatBits relation.
      * \note Need one bit for each builtin Arch.
     */
-    typedef bit::BitField<uint16_t> CompatBits;
+    typedef bit::BitField<uint32_t> CompatBits;
 
     CompatEntry( const std::string & archStr_r,
-                 CompatBits::IntT idBit_r = CompatBits::IntT(1) )
-    : _archStr( archStr_r )
+                 CompatBits::IntT idBit_r = 1 )
+    : _idStr( archStr_r )
+    , _archStr( archStr_r )
+    , _idBit( idBit_r )
+    , _compatBits( idBit_r )
+    , _compatScore( idBit_r ? 1 : 0 ) // number of compatible archs
+    {}
+
+    CompatEntry( IdString archStr_r,
+                 CompatBits::IntT idBit_r = 1 )
+    : _idStr( archStr_r )
+    , _archStr( archStr_r.asString() )
     , _idBit( idBit_r )
     , _compatBits( idBit_r )
     , _compatScore( idBit_r ? 1 : 0 ) // number of compatible archs
@@ -82,7 +93,14 @@ namespace zypp
       return _archStr.compare( rhs._archStr );
     }
 
-    std::string         _archStr;
+    bool isBuiltIn() const
+    { return( _idBit != CompatBits(1) ); }
+
+    IdString::IdType id() const
+    { return _idStr.id(); }
+
+    IdString            _idStr;
+    std::string         _archStr; // frequently used by the UI so we keep a reference
     CompatBits          _idBit;
     mutable CompatBits  _compatBits;
     mutable unsigned    _compatScore;
@@ -92,23 +110,33 @@ namespace zypp
   /** \relates Arch::CompatEntry Stream output */
   inline std::ostream & operator<<( std::ostream & str, const Arch::CompatEntry & obj )
   {
-    return str << obj._archStr << '\t' << obj._idBit << ' '
+    return str << str::form( "%-15s ", obj._archStr.c_str() ) << obj._idBit << ' '
                << obj._compatBits << ' ' << obj._compatScore;
   }
 
-  /** \relates Arch::CompatEntry ComaptSet ordering.
-   * \note This is purely based on _archStr, as required by class CompatSet.
-  */
-  inline bool operator<( const Arch::CompatEntry & lhs, const Arch::CompatEntry & rhs )
-  { return lhs._archStr < rhs._archStr; }
+  /** \relates Arch::CompatEntry */
+  inline bool operator==( const Arch::CompatEntry & lhs, const Arch::CompatEntry & rhs )
+  { return lhs._idStr == rhs._idStr; }
+  /** \relates Arch::CompatEntry */
+  inline bool operator!=( const Arch::CompatEntry & lhs, const Arch::CompatEntry & rhs )
+  { return ! ( lhs == rhs ); }
+
+  /////////////////////////////////////////////////////////////////
+} // namespace zypp
+///////////////////////////////////////////////////////////////////
+
+ZYPP_DEFINE_ID_HASHABLE( zypp::Arch::CompatEntry );
+
+///////////////////////////////////////////////////////////////////
+namespace zypp
+{ /////////////////////////////////////////////////////////////////
 
   ///////////////////////////////////////////////////////////////////
   namespace
   { /////////////////////////////////////////////////////////////////
 
     // builtin architecture STRING VALUES
-#define DEF_BUILTIN(A) const std::string  _##A( #A )
-
+#define DEF_BUILTIN(A) const IdString  _##A( #A )
     DEF_BUILTIN( noarch );
 
     DEF_BUILTIN( i386 );
@@ -118,7 +146,8 @@ namespace zypp
     DEF_BUILTIN( athlon );
     DEF_BUILTIN( x86_64 );
 
-    DEF_BUILTIN( ia64 );
+    DEF_BUILTIN( pentium3 );
+    DEF_BUILTIN( pentium4 );
 
     DEF_BUILTIN( s390 );
     DEF_BUILTIN( s390x );
@@ -126,6 +155,19 @@ namespace zypp
     DEF_BUILTIN( ppc );
     DEF_BUILTIN( ppc64 );
 
+    DEF_BUILTIN( ia64 );
+
+    DEF_BUILTIN( alphaev67 );
+    DEF_BUILTIN( alphaev6 );
+    DEF_BUILTIN( alphapca56 );
+    DEF_BUILTIN( alphaev56 );
+    DEF_BUILTIN( alphaev5 );
+    DEF_BUILTIN( alpha );
+
+    DEF_BUILTIN( sparc64 );
+    DEF_BUILTIN( sparcv9 );
+    DEF_BUILTIN( sparcv8 );
+    DEF_BUILTIN( sparc );
 #undef DEF_BUILTIN
 
     ///////////////////////////////////////////////////////////////////
@@ -144,7 +186,7 @@ namespace zypp
       typedef Arch::CompatEntry       CompatEntry;
       typedef CompatEntry::CompatBits CompatBits;
 
-      typedef std::set<CompatEntry>   Set;
+      typedef std::tr1::unordered_set<CompatEntry> Set;
       typedef Set::iterator           iterator;
       typedef Set::const_iterator     const_iterator;
 
@@ -159,10 +201,10 @@ namespace zypp
        * Creates an entry for nonbuiltin archs.
       */
       const Arch::CompatEntry & assertDef( const std::string & archStr_r )
-      {
-        return *_compatSet.insert( Arch::CompatEntry( archStr_r )
-                                 ).first;
-      }
+      { return *_compatSet.insert( Arch::CompatEntry( archStr_r ) ).first; }
+      /** \overload */
+      const Arch::CompatEntry & assertDef( IdString archStr_r )
+      { return *_compatSet.insert( Arch::CompatEntry( archStr_r ) ).first; }
 
       const_iterator begin() const
       { return _compatSet.begin(); }
@@ -191,51 +233,36 @@ namespace zypp
         ///////////////////////////////////////////////////////////////////
         // Define the CompatibleWith relation:
         //
-        defCompatibleWith( _noarch,    _i386 );
-
-        defCompatibleWith( _noarch,    _i486 );
-        defCompatibleWith( _i386,      _i486 );
-
-        defCompatibleWith( _noarch,    _i586 );
-        defCompatibleWith( _i386,      _i586 );
-        defCompatibleWith( _i486,      _i586 );
-
-        defCompatibleWith( _noarch,    _i686 );
-        defCompatibleWith( _i386,      _i686 );
-        defCompatibleWith( _i486,      _i686 );
-        defCompatibleWith( _i586,      _i686 );
-
-        defCompatibleWith( _noarch,    _athlon );
-        defCompatibleWith( _i386,      _athlon );
-        defCompatibleWith( _i486,      _athlon );
-        defCompatibleWith( _i586,      _athlon );
-        defCompatibleWith( _i686,      _athlon );
-
-        defCompatibleWith( _noarch,    _x86_64 );
-        defCompatibleWith( _i386,      _x86_64 );
-        defCompatibleWith( _i486,      _x86_64 );
-        defCompatibleWith( _i586,      _x86_64 );
-        defCompatibleWith( _i686,      _x86_64 );
-        defCompatibleWith( _athlon,    _x86_64 );
-
-        /////
-        defCompatibleWith( _noarch,    _ia64 );
-        defCompatibleWith( _i386,      _ia64 );
-        defCompatibleWith( _i486,      _ia64 );
-        defCompatibleWith( _i586,      _ia64 );
-        defCompatibleWith( _i686,      _ia64 );
-
-        /////
-        defCompatibleWith( _noarch,    _s390 );
-
-        defCompatibleWith( _noarch,    _s390x );
-        defCompatibleWith( _s390,      _s390x );
-
-        /////
-        defCompatibleWith( _noarch,    _ppc );
-
-        defCompatibleWith( _noarch,    _ppc64 );
-        defCompatibleWith( _ppc,       _ppc64 );
+        defCompatibleWith( _i386,      _noarch );
+        defCompatibleWith( _i486,      _noarch,_i386 );
+        defCompatibleWith( _i586,      _noarch,_i386,_i486 );
+        defCompatibleWith( _i686,      _noarch,_i386,_i486,_i586 );
+        defCompatibleWith( _athlon,    _noarch,_i386,_i486,_i586,_i686 );
+        defCompatibleWith( _x86_64,    _noarch,_i386,_i486,_i586,_i686,_athlon );
+
+        defCompatibleWith( _pentium3,  _noarch,_i386,_i486,_i586,_i686 );
+        defCompatibleWith( _pentium4,  _noarch,_i386,_i486,_i586,_i686,_pentium3 );
+
+        defCompatibleWith( _ia64,      _noarch,_i386,_i486,_i586,_i686 );
+        //
+        defCompatibleWith( _s390,      _noarch );
+        defCompatibleWith( _s390x,     _noarch,_s390 );
+        //
+        defCompatibleWith( _ppc,       _noarch );
+        defCompatibleWith( _ppc64,     _noarch,_ppc );
+        //
+        defCompatibleWith( _alpha,     _noarch );
+        defCompatibleWith( _alphaev5,  _noarch,_alpha );
+        defCompatibleWith( _alphaev56, _noarch,_alpha,_alphaev5 );
+        defCompatibleWith( _alphapca56,        _noarch,_alpha,_alphaev5,_alphaev56 );
+        defCompatibleWith( _alphaev6,  _noarch,_alpha,_alphaev5,_alphaev56,_alphapca56 );
+        defCompatibleWith( _alphaev67, _noarch,_alpha,_alphaev5,_alphaev56,_alphapca56,_alphaev6 );
+        //
+        defCompatibleWith( _sparc,     _noarch );
+        defCompatibleWith( _sparcv8,   _noarch,_sparc );
+        //
+        defCompatibleWith( _sparcv9,   _noarch,_sparc );
+        defCompatibleWith( _sparc64,   _noarch,_sparc,_sparcv9 );
         //
         ///////////////////////////////////////////////////////////////////
         //dumpOn( USR ) << endl;
@@ -249,7 +276,7 @@ namespace zypp
       */
       CompatBits::IntT nextIdBit() const
       {
-        CompatBits::IntT nextBit = 1 << (_compatSet.size());
+        CompatBits::IntT nextBit = CompatBits::IntT(1) << (_compatSet.size());
         assert( nextBit ); // need more bits in CompatBits::IntT
         return nextBit;
       }
@@ -257,19 +284,29 @@ namespace zypp
       /** Assert each builtin Arch gets an unique _idBit when
        *  inserted into the _compatSet.
       */
-      const CompatEntry & assertCompatSetEntry( const std::string & archStr_r )
-      {
-        return *_compatSet.insert( Arch::CompatEntry( archStr_r, nextIdBit() )
-                                 ).first;
-      }
+      const CompatEntry & assertCompatSetEntry( IdString archStr_r )
+      { return *_compatSet.insert( Arch::CompatEntry( archStr_r, nextIdBit() ) ).first; }
 
       /** Initialize builtin Archs and set _compatBits.
       */
-      void defCompatibleWith( const std::string & arch_r, const std::string & targetArch_r )
+      void defCompatibleWith( IdString targetArch_r,
+                              IdString arch0_r,
+                              IdString arch1_r = IdString(),
+                              IdString arch2_r = IdString(),
+                              IdString arch3_r = IdString(),
+                              IdString arch4_r = IdString(),
+                              IdString arch5_r = IdString(),
+                              IdString arch6_r = IdString(),
+                              IdString arch7_r = IdString(),
+                              IdString arch8_r = IdString(),
+                              IdString arch9_r = IdString() )
       {
-        const CompatEntry & arch  ( assertCompatSetEntry( arch_r ) );
         const CompatEntry & target( assertCompatSetEntry( targetArch_r ) );
-        target.addCompatBit( arch._idBit );
+        target.addCompatBit( assertCompatSetEntry( arch0_r )._idBit );
+#define _SETARG(N) if ( arch##N##_r.empty() ) return; target.addCompatBit( assertCompatSetEntry( arch##N##_r )._idBit )
+        _SETARG(1); _SETARG(2); _SETARG(3); _SETARG(4);
+        _SETARG(5); _SETARG(6); _SETARG(7); _SETARG(8); _SETARG(9);
+#undef _SETARG
       }
 
     private:
@@ -286,8 +323,13 @@ namespace zypp
   //
   ///////////////////////////////////////////////////////////////////
 
+  const Arch Arch_empty ( IdString::Empty );
+
   const Arch Arch_noarch( _noarch );
 
+  const Arch Arch_pentium4( _pentium4 );
+  const Arch Arch_pentium3( _pentium3 );
+
   const Arch Arch_x86_64( _x86_64 );
   const Arch Arch_athlon( _athlon );
   const Arch Arch_i686  ( _i686 );
@@ -303,6 +345,18 @@ namespace zypp
 
   const Arch Arch_ia64  ( _ia64 );
 
+  const Arch Arch_alphaev67 ( _alphaev67 );
+  const Arch Arch_alphaev6  ( _alphaev6 );
+  const Arch Arch_alphapca56( _alphapca56 );
+  const Arch Arch_alphaev56 ( _alphaev56 );
+  const Arch Arch_alphaev5  ( _alphaev5 );
+  const Arch Arch_alpha     ( _alpha );
+
+  const Arch Arch_sparc64( _sparc64 );
+  const Arch Arch_sparcv9( _sparcv9 );
+  const Arch Arch_sparcv8( _sparcv8 );
+  const Arch Arch_sparc  ( _sparc );
+
   ///////////////////////////////////////////////////////////////////
   //
   //   METHOD NAME : Arch::Arch
@@ -310,25 +364,35 @@ namespace zypp
   //
   Arch::Arch()
   : _entry( &ArchCompatSet::instance().assertDef( _noarch ) )
-  { assert( _entry ); }
+  {}
 
-  ///////////////////////////////////////////////////////////////////
-  //
-  //   METHOD NAME : Arch::Arch
-  //   METHOD TYPE : Ctor
-  //
-  Arch::Arch( const std::string & rhs )
-  : _entry( &ArchCompatSet::instance().assertDef( rhs ) )
-  { assert( _entry ); }
+  Arch::Arch( IdString::IdType id_r )
+  : _entry( &ArchCompatSet::instance().assertDef( IdString(id_r) ) )
+  {}
+
+  Arch::Arch( const IdString & idstr_r )
+  : _entry( &ArchCompatSet::instance().assertDef( idstr_r ) )
+  {}
+
+  Arch::Arch( const std::string & str_r )
+  : _entry( &ArchCompatSet::instance().assertDef( str_r ) )
+  {}
+
+  Arch::Arch( const char * cstr_r )
+  : _entry( &ArchCompatSet::instance().assertDef( cstr_r ) )
+  {}
+
+  Arch::Arch( const CompatEntry & rhs )
+  : _entry( &rhs )
+  {}
 
   ///////////////////////////////////////////////////////////////////
   //
-  //   METHOD NAME : Arch::Arch
-  //   METHOD TYPE : Ctor
+  //   METHOD NAME : Arch::idStr
+  //   METHOD TYPE : IdString
   //
-  Arch::Arch( const CompatEntry & rhs )
-  : _entry( &rhs )
-  { assert( _entry ); }
+  IdString Arch::idStr() const
+  { return _entry->_idStr; }
 
   ///////////////////////////////////////////////////////////////////
   //
@@ -340,6 +404,14 @@ namespace zypp
 
   ///////////////////////////////////////////////////////////////////
   //
+  //   METHOD NAME : Arch::isBuiltIn
+  //   METHOD TYPE : bool
+  //
+  bool Arch::isBuiltIn() const
+  { return _entry->isBuiltIn(); }
+
+  ///////////////////////////////////////////////////////////////////
+  //
   //   METHOD NAME : Arch::compatibleWith
   //   METHOD TYPE : bool
   //
index 17bd467..607f1ed 100644 (file)
@@ -36,29 +36,51 @@ namespace zypp
   class Arch
   {
   public:
-    /** Default ctor 'noarch' */
+    /** Default ctor \ref Arc_noarch. */
     Arch();
-    /** Ctor from string. */
-    explicit
-    Arch( const std::string & rhs );
+
+    /** Ctor taking Arch as string. */
+    explicit Arch( IdString::IdType id_r );
+    explicit Arch( const IdString & idstr_r );
+    explicit Arch( const std::string & str_r );
+    explicit Arch( const char * cstr_r );
 
   public:
+    /** \name IdStringType like interface.
+     * We can't use the complete \ref IdStringType mixin until
+     * _doCompare can be redefined on any level, not just as char*.
+    */
+    //@{
     /** String representation of Arch. */
-    IdString idStr() const
-    { return IdString( asString() ); }
-    /** \overload */
+    IdString idStr() const;
+     /** \overload */
     const std::string & asString() const;
     /** \overload */
     const char * c_str() const
     { return asString().c_str(); }
 
+    /** Test for an empty Arch (this is \ref Arch_epmty, not \ref Arch_noarch ). */
+    bool empty() const
+    { return asString().empty(); }
+
+    /** Size of the string representation. */
+    unsigned size() const
+    { return asString().size(); }
+
+    /** Expert backdoor. */
     IdString::IdType id() const
     { return idStr().id(); }
+    //@}
 
-    /** Test for an empty Arch (this is "", not Arch_noarch). */
-    bool empty() const
-    { return asString().empty(); }
+  public:
+    /** Whether this is a buitin (or known) architecture.
+     * Used e.g. in \ref Capability to determine whether
+     * some trailing \c ".string" is part ot the name or
+     * restriction to an architecture.
+    */
+    bool isBuiltIn() const;
 
+  public:
     /** Compatibility relation.
      * \return \c True iff \c this is compatible with \a targetArch_r.
      * \code
@@ -121,10 +143,23 @@ namespace zypp
    * like \c Arch::i386.
   */
   //@{
+  /** \relates Arch
+   * This is an empty \ref Arch represented by an empty string.
+   * Sometimes used to indicate an any or an unknown Arch. Don't
+   * confuse this with \ref Arch_noarch, which is in fact an
+   * architecture.
+  */
+  extern const Arch Arch_empty;
+
   /** \relates Arch */
   extern const Arch Arch_noarch;
 
   /** \relates Arch */
+  extern const Arch Arch_pentium4;
+  /** \relates Arch */
+  extern const Arch Arch_pentium3;
+
+  /** \relates Arch */
   extern const Arch Arch_x86_64;
   /** \relates Arch */
   extern const Arch Arch_athlon;
@@ -149,6 +184,28 @@ namespace zypp
 
   /** \relates Arch */
   extern const Arch Arch_ia64;
+
+  /** \relates Arch */
+  extern const Arch Arch_alphaev67;
+  /** \relates Arch */
+  extern const Arch Arch_alphaev6;
+  /** \relates Arch */
+  extern const Arch Arch_alphapca56;
+  /** \relates Arch */
+  extern const Arch Arch_alphaev56;
+  /** \relates Arch */
+  extern const Arch Arch_alphaev5;
+  /** \relates Arch */
+  extern const Arch Arch_alpha;
+
+  /** \relates Arch */
+  extern const Arch Arch_sparc64;
+  /** \relates Arch */
+  extern const Arch Arch_sparcv9;
+  /** \relates Arch */
+  extern const Arch Arch_sparcv8;
+  /** \relates Arch */
+  extern const Arch Arch_sparc;
   //@}
 
   ///////////////////////////////////////////////////////////////////
index 5662bab..098b1ec 100644 (file)
@@ -33,18 +33,16 @@ namespace zypp
   ///////////////////////////////////////////////////////////////////
   namespace
   { /////////////////////////////////////////////////////////////////
+    /** Build \ref Capability from data. No parsing required.
+    */
     sat::detail::IdType relFromStr( ::_Pool * pool_r,
                                     const Arch & arch_r,
-                                    const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & kind_r )
-    {
-      sat::detail::IdType nid( sat::detail::noId );
-      return nid;
-    }
-
-    sat::detail::IdType relFromStr( ::_Pool * pool_r,
-                                    const std::string & name_r, Rel op_r, const Edition & ed_r,
+                                    const std::string & name_r,
+                                    Rel op_r,
+                                    const Edition & ed_r,
                                     const ResKind & kind_r )
     {
+      // First build the name, non-packages prefixed by kind
       sat::detail::IdType nid( sat::detail::noId );
       if ( ! kind_r || kind_r == ResKind::package )
       {
@@ -52,12 +50,19 @@ namespace zypp
       }
       else
       {
-        // non-packages prefixed by kind
         nid = IdString( str::form( "%s:%s",
                         kind_r.c_str(),
-                                     name_r.c_str() ) ).id();
+                        name_r.c_str() ) ).id();
+      }
+
+
+      // Extend name by architecture, if provided
+      if ( ! arch_r.empty() )
+      {
+        nid = ::rel2id( pool_r, nid, arch_r.id(), REL_ARCH, /*create*/true );
       }
 
+      // Extend 'op edition', if provided
       if ( op_r != Rel::ANY && ed_r != Edition::noedition )
       {
         nid = ::rel2id( pool_r, nid, ed_r.id(), op_r.bits(), /*create*/true );
@@ -66,9 +71,34 @@ namespace zypp
       return nid;
     }
 
+    /** Build \ref Capability from data, just parsing name for '[.arch]'.
+    */
+    sat::detail::IdType relFromStr( ::_Pool * pool_r,
+                                    const std::string & name_r, Rel op_r, const Edition & ed_r,
+                                    const ResKind & kind_r )
+    {
+      Arch arch( Arch_empty );
+      std::string name( name_r );
+
+      std::string::size_type asep( name_r.rfind( "." ) );
+      if ( asep != std::string::npos )
+      {
+        Arch ext( name_r.substr( asep+1 ) );
+        if ( ext.isBuiltIn() )
+        {
+          arch = ext;
+          name.erase( asep );
+        }
+      }
+
+      return relFromStr( pool_r, arch, name, op_r, ed_r, kind_r );
+    }
+
+    /** Full parse from string, unless Capability::PARSED.
+    */
     sat::detail::IdType relFromStr( ::_Pool * pool_r,
-                                      const std::string & str_r, const ResKind & kind_r,
-                                      Capability::CtorFlag flag_r )
+                                    const std::string & str_r, const ResKind & kind_r,
+                                    Capability::CtorFlag flag_r )
     {
       // strval_r has at least two words which could make 'op edition'?
       // improve regex!
@@ -100,7 +130,7 @@ namespace zypp
       //else
       // not a versioned relation
 
-      return relFromStr( pool_r, name, op, ed, kind_r );
+      return relFromStr( pool_r, name, op, ed, kind_r ); // parses for name[.arch]
     }
 
     /////////////////////////////////////////////////////////////////
@@ -127,27 +157,42 @@ namespace zypp
   : _id( relFromStr( myPool().getPool(), str_r, prefix_r, flag_r ) )
   {}
 
+  ///////////////////////////////////////////////////////////////////
+  // Ctor from <name[.arch] op edition>.
+  ///////////////////////////////////////////////////////////////////
 
   Capability::Capability( const std::string & name_r, const std::string & op_r, const std::string & ed_r, const ResKind & prefix_r )
   : _id( relFromStr( myPool().getPool(), name_r, Rel(op_r), Edition(ed_r), prefix_r ) )
   {}
-
   Capability::Capability( const std::string & name_r, Rel op_r, const std::string & ed_r, const ResKind & prefix_r )
   : _id( relFromStr( myPool().getPool(), name_r, op_r, Edition(ed_r), prefix_r ) )
   {}
-
   Capability::Capability( const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & prefix_r )
   : _id( relFromStr( myPool().getPool(), name_r, op_r, ed_r, prefix_r ) )
   {}
 
-#if 0
-  Capability::Capability( const std::string & arch_r, const std::string & name_r, const std::string & op_r, const std::string & ed_r, const ResKind & prefix_r = ResKind() );
-  Capability::Capability( const std::string & arch_r, const std::string & name_r, Rel op_r, const std::string & ed_r, const ResKind & prefix_r = ResKind() );
-  Capability::Capability( const std::string & arch_r, const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & prefix_r = ResKind() );
-  Capability::Capability( const Arch & arch_r, const std::string & name_r, const std::string & op_r, const std::string & ed_r, const ResKind & prefix_r = ResKind() );
-  Capability::Capability( const Arch & arch_r, const std::string & name_r, Rel op_r, const std::string & ed_r, const ResKind & prefix_r = ResKind() );
-  Capability::Capability( const Arch & arch_r, const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & prefix_r = ResKind() );
-#endif
+  ///////////////////////////////////////////////////////////////////
+  // Ctor from <arch name op edition>.
+  ///////////////////////////////////////////////////////////////////
+
+  Capability::Capability( const std::string & arch_r, const std::string & name_r, const std::string & op_r, const std::string & ed_r, const ResKind & prefix_r )
+  : _id( relFromStr( myPool().getPool(), Arch(arch_r), name_r, Rel(op_r), Edition(ed_r), prefix_r ) )
+  {}
+  Capability::Capability( const std::string & arch_r, const std::string & name_r, Rel op_r, const std::string & ed_r, const ResKind & prefix_r )
+  : _id( relFromStr( myPool().getPool(), Arch(arch_r), name_r, op_r, Edition(ed_r), prefix_r ) )
+  {}
+  Capability::Capability( const std::string & arch_r, const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & prefix_r )
+  : _id( relFromStr( myPool().getPool(), Arch(arch_r), name_r, op_r, ed_r, prefix_r ) )
+  {}
+  Capability::Capability( const Arch & arch_r, const std::string & name_r, const std::string & op_r, const std::string & ed_r, const ResKind & prefix_r )
+  : _id( relFromStr( myPool().getPool(), arch_r, name_r, Rel(op_r), Edition(ed_r), prefix_r ) )
+  {}
+  Capability::Capability( const Arch & arch_r, const std::string & name_r, Rel op_r, const std::string & ed_r, const ResKind & prefix_r )
+  : _id( relFromStr( myPool().getPool(), arch_r, name_r, op_r, Edition(ed_r), prefix_r ) )
+  {}
+  Capability::Capability( const Arch & arch_r, const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & prefix_r )
+  : _id( relFromStr( myPool().getPool(), arch_r, name_r, op_r, ed_r, prefix_r ) )
+  {}
 
   const char * Capability::c_str() const
   { return( _id ? ::dep2str( myPool().getPool(), _id ) : "" ); }
@@ -191,6 +236,11 @@ namespace zypp
     if ( l.name() != r.name() )
       return CapMatch::no;
 
+    // if both are arch restricted they must match
+    if ( l.arch() != r.arch()
+         && ! ( l.arch().empty() || r.arch().empty() ) )
+      return CapMatch::no;
+
     // isNamed matches ANY edition:
     if ( l.isNamed() || r.isNamed() )
       return CapMatch::yes;
@@ -233,13 +283,14 @@ namespace zypp
 
   void CapDetail::_init()
   {
-    // : _kind( NOCAP ), _lhs( id_r ), _rhs( 0 ), _flag( 0 )
+    // : _kind( NOCAP ), _lhs( id_r ), _rhs( 0 ), _flag( 0 ), _archIfSimple( 0 )
 
     if ( _lhs == sat::detail::emptyId || _lhs == sat::detail::noId )
       return; // NOCAP
 
     if ( ! ISRELDEP(_lhs) )
     {
+      // this is name without arch!
       _kind = NAMED;
       return;
     }
@@ -249,7 +300,31 @@ namespace zypp
     _rhs  = rd->evr;
     _flag = rd->flags;
 
-    _kind = Rel::isRel( _flag ) ? VERSIONED : EXPRESSION;
+    if ( Rel::isRel( _flag ) )
+    {
+      _kind = VERSIONED;
+      // Check for name.arch...
+      if ( ! ISRELDEP(_lhs) )
+        return; // this is name without arch!
+      rd = GETRELDEP( myPool().getPool(), _lhs );
+      if ( rd->flags != CAP_ARCH )
+        return; // this is not name.arch
+      // This is name.arch:
+      _lhs = rd->name;
+      _archIfSimple = rd->evr;
+    }
+    else if ( rd->flags == CAP_ARCH )
+    {
+      _kind = NAMED;
+      // This is name.arch:
+      _lhs = rd->name;
+      _archIfSimple = rd->evr;
+    }
+    else
+    {
+      _kind = EXPRESSION;
+      return;
+    }
   }
 
   /******************************************************************
@@ -265,10 +340,16 @@ namespace zypp
         return str << "<NoCap>";
         break;
       case CapDetail::NAMED:
-        return str << obj.name();
+        str << obj.name();
+        if ( obj.hasArch() )
+          str << '.' << obj.arch();
+        return str;
         break;
       case CapDetail::VERSIONED:
-        return str << obj.name() << " " << obj.op() << " " << obj.ed();
+        str << obj.name();
+        if ( obj.hasArch() )
+          str << '.' << obj.arch();
+        return str << " " << obj.op() << " " << obj.ed();
         break;
       case CapDetail::EXPRESSION:
         switch ( obj.capRel() )
index a4f0b70..6a6bf31 100644 (file)
@@ -32,6 +32,7 @@ namespace zypp
 
   class Capability;
   class CapDetail;
+  class Arch;
 
   typedef std::tr1::unordered_set<Capability> CapabilitySet;
 
@@ -97,7 +98,6 @@ namespace zypp
       Capability( const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & prefix_r = ResKind() );
       //@}
 
-#if 0
       /** \name Ctors taking a broken down Capability: <tt>( arch, name, op, edition )</tt>
       */
       //@{
@@ -114,7 +114,6 @@ namespace zypp
       /** \overload */
       Capability( const Arch & arch_r, const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & prefix_r = ResKind() );
       //@}
-#endif
 
     public:
       /** No or Null \ref Capability ( Id \c 0 ). */
@@ -154,8 +153,6 @@ namespace zypp
        *
        * If a capability expression is involved, \ref matches returns
        * \ref CapMatch::irrelevant.
-       *
-       * \todo check whether we must promote string to Capability in order to match.
        */
       //@{
       static CapMatch matches( const Capability & lhs,  const Capability & rhs )     { return _doMatch( lhs.id(), rhs.id() ); }
@@ -240,6 +237,17 @@ namespace zypp
   //   CLASS NAME : CapDetail
   //
   /** Helper providing more detailed information about a \ref Capability.
+   *
+   * Capabilities are classified to be either \c SIMPLE:
+   * \code
+   *   name[.arch] [op edition]
+   *   with op := <|<=|=|>=|>|!=
+   * \endcode
+   * or formed by some \c EXPRESSION:
+   * \code
+   *   left_cap op right_cap
+   *   with op := AND|OR|WITH|NAMESPACE
+   * \endcode
    */
   class CapDetail: protected sat::detail::PoolMember
   {
@@ -253,7 +261,7 @@ namespace zypp
       };
 
       /** Enum values corresponding with libsatsolver defines.
-       * MPL check in PoolImpl.cc
+       * \note MPL check in PoolImpl.cc
       */
       enum CapRel
       {
@@ -261,18 +269,19 @@ namespace zypp
         CAP_AND       = 16,
         CAP_OR        = 17,
         CAP_WITH      = 18,
-        CAP_NAMESPACE = 19
+        CAP_NAMESPACE = 19,
+        CAP_ARCH      = 20
       };
 
     public:
       CapDetail()
-      : _kind( NOCAP ), _lhs( 0 ), _rhs( 0 ), _flag( 0 )
+      : _kind( NOCAP ), _lhs( 0 ), _rhs( 0 ), _flag( 0 ), _archIfSimple( 0 )
       {}
       explicit CapDetail( const Capability & cap_r )
-      : _kind( NOCAP ), _lhs( cap_r.id() ), _rhs( 0 ), _flag( 0 )
+      : _kind( NOCAP ), _lhs( cap_r.id() ), _rhs( 0 ), _flag( 0 ), _archIfSimple( 0 )
       { _init(); }
       explicit CapDetail( sat::detail::IdType id_r )
-      : _kind( NOCAP ), _lhs( id_r ), _rhs( 0 ), _flag( 0 )
+      : _kind( NOCAP ), _lhs( id_r ), _rhs( 0 ), _flag( 0 ), _archIfSimple( 0 )
       { _init(); }
 
     public:
@@ -283,8 +292,10 @@ namespace zypp
       bool isSimple()     const { return _kind & (NAMED|VERSIONED); }
       bool isExpression() const { return _kind == EXPRESSION; }
 
-      /** \name Is simple: <tt>name [op edition]</tt> */
+      /** \name Is simple: <tt>name[.arch] [op edition]</tt> */
       //@{
+      bool     hasArch()  const { return _archIfSimple; }
+      IdString arch()     const { return _archIfSimple ? IdString( _archIfSimple ) : IdString(); }
       IdString name()     const { return isSimple()    ? IdString( _lhs ) : IdString(); }
       Rel      op()       const { return isVersioned() ? Rel( _flag )     : Rel::ANY; }
       Edition  ed()       const { return isVersioned() ? Edition( _rhs )  : Edition(); }
@@ -304,6 +315,7 @@ namespace zypp
       sat::detail::IdType _lhs;
       sat::detail::IdType _rhs;
       unsigned            _flag;
+      sat::detail::IdType _archIfSimple;
   };
   ///////////////////////////////////////////////////////////////////
 
index 15fc69d..86d4666 100644 (file)
@@ -79,6 +79,7 @@ namespace zypp
    *    DBG << "na == a ? " << (na == "a") << endl;   // na == a ? 1
    *    DBG << "na == A ? " << (na == "A") << endl;   // na == A ? 1
    * \endcode
+   * \todo allow redefinition of order vis _doCompare not only for char* but on any level
    * \ingroup g_CRTP
    */
   template <class Derived>
index 75c2df9..9c6c4fe 100644 (file)
@@ -423,16 +423,16 @@ namespace zypp
             case CapDetail::CAP_AND:
             case CapDetail::CAP_OR:
                 // expand
-            {
-              int res = invokeOnEachSupportedLocale( detail.lhs(), fnc_r );
-              if ( res < 0 )
-                return res; // negative on abort.
-              int res2 = invokeOnEachSupportedLocale( detail.rhs(), fnc_r );
-              if ( res2 < 0 )
-                return -res + res2; // negative on abort.
-              return res + res2;
-            }
-            break;
+              {
+                int res = invokeOnEachSupportedLocale( detail.lhs(), fnc_r );
+                if ( res < 0 )
+                  return res; // negative on abort.
+                int res2 = invokeOnEachSupportedLocale( detail.rhs(), fnc_r );
+                if ( res2 < 0 )
+                  return -res + res2; // negative on abort.
+                return res + res2;
+              }
+              break;
 
             case CapDetail::CAP_NAMESPACE:
               if ( detail.lhs().id() == NAMESPACE_LANGUAGE )
@@ -443,6 +443,7 @@ namespace zypp
 
             case CapDetail::REL_NONE:
             case CapDetail::CAP_WITH:
+            case CapDetail::CAP_ARCH:
               break; // unwanted
           }
         }
index 0817c13..941382b 100644 (file)
@@ -60,6 +60,7 @@ namespace zypp
       BOOST_MPL_ASSERT_RELATION( CapDetail::CAP_OR,        ==, REL_OR );
       BOOST_MPL_ASSERT_RELATION( CapDetail::CAP_WITH,      ==, REL_WITH );
       BOOST_MPL_ASSERT_RELATION( CapDetail::CAP_NAMESPACE, ==, REL_NAMESPACE );
+      BOOST_MPL_ASSERT_RELATION( CapDetail::CAP_ARCH,      ==, REL_ARCH );
 
      /////////////////////////////////////////////////////////////////