Build the split-select tool without C++11 support
It was complicated to get the tool building on Windows, Linux,
and OSX with C++11 support.
OSX uses Clang to build C++11 binaries, which requires the libc++
standard library. Since most of the dependencies of this program
are built against libstdc++, this was difficult to resolve.
Now we build without C++11 support.
Change-Id: I4e537c113734508a8f480a1c402ed237de4f0e60
diff --git a/tools/aapt/AaptUtil.h b/tools/aapt/AaptUtil.h
index 47a704a..89e1ee8 100644
--- a/tools/aapt/AaptUtil.h
+++ b/tools/aapt/AaptUtil.h
@@ -14,9 +14,11 @@
* limitations under the License.
*/
-#ifndef __AAPT_UTIL_H
-#define __AAPT_UTIL_H
+#ifndef H_AAPT_UTIL
+#define H_AAPT_UTIL
+#include <utils/KeyedVector.h>
+#include <utils/SortedVector.h>
#include <utils/String8.h>
#include <utils/Vector.h>
@@ -25,6 +27,38 @@
android::Vector<android::String8> split(const android::String8& str, const char sep);
android::Vector<android::String8> splitAndLowerCase(const android::String8& str, const char sep);
+template <typename KEY, typename VALUE>
+void appendValue(android::KeyedVector<KEY, android::Vector<VALUE> >& keyedVector,
+ const KEY& key, const VALUE& value);
+
+template <typename KEY, typename VALUE>
+void appendValue(android::KeyedVector<KEY, android::SortedVector<VALUE> >& keyedVector,
+ const KEY& key, const VALUE& value);
+
+//
+// Implementations
+//
+
+template <typename KEY, typename VALUE>
+void appendValue(android::KeyedVector<KEY, android::Vector<VALUE> >& keyedVector,
+ const KEY& key, const VALUE& value) {
+ ssize_t idx = keyedVector.indexOfKey(key);
+ if (idx < 0) {
+ idx = keyedVector.add(key, android::Vector<VALUE>());
+ }
+ keyedVector.editValueAt(idx).add(value);
+}
+
+template <typename KEY, typename VALUE>
+void appendValue(android::KeyedVector<KEY, android::SortedVector<VALUE> >& keyedVector,
+ const KEY& key, const VALUE& value) {
+ ssize_t idx = keyedVector.indexOfKey(key);
+ if (idx < 0) {
+ idx = keyedVector.add(key, android::SortedVector<VALUE>());
+ }
+ keyedVector.editValueAt(idx).add(value);
+}
+
} // namespace AaptUtil
-#endif // __AAPT_UTIL_H
+#endif // H_AAPT_UTIL
diff --git a/tools/split-select/Abi.cpp b/tools/split-select/Abi.cpp
index 20654b6..180dd8f 100644
--- a/tools/split-select/Abi.cpp
+++ b/tools/split-select/Abi.cpp
@@ -16,42 +16,58 @@
#include "Abi.h"
+using namespace android;
+
namespace split {
namespace abi {
-static const std::vector<Variant> sNoneVariants = {};
-static const std::vector<Variant> sArmVariants =
- {Variant::armeabi, Variant::armeabi_v7a, Variant::arm64_v8a};
-static const std::vector<Variant> sIntelVariants = {Variant::x86, Variant::x86_64};
-static const std::vector<Variant> sMipsVariants = {Variant::mips, Variant::mips64};
+static Vector<Variant> buildVariants(Variant v1, Variant v2) {
+ Vector<Variant> v;
+ v.add(v1);
+ v.add(v2);
+ return v;
+}
+
+static Vector<Variant> buildVariants(Variant v1, Variant v2, Variant v3) {
+ Vector<Variant> v;
+ v.add(v1);
+ v.add(v2);
+ v.add(v3);
+ return v;
+}
+
+static const Vector<Variant> sNoneVariants;
+static const Vector<Variant> sArmVariants = buildVariants(Variant_armeabi, Variant_armeabi_v7a, Variant_arm64_v8a);
+static const Vector<Variant> sIntelVariants = buildVariants(Variant_x86, Variant_x86_64);
+static const Vector<Variant> sMipsVariants = buildVariants(Variant_mips, Variant_mips64);
Family getFamily(Variant variant) {
switch (variant) {
- case Variant::none:
- return Family::none;
- case Variant::armeabi:
- case Variant::armeabi_v7a:
- case Variant::arm64_v8a:
- return Family::arm;
- case Variant::x86:
- case Variant::x86_64:
- return Family::intel;
- case Variant::mips:
- case Variant::mips64:
- return Family::mips;
+ case Variant_none:
+ return Family_none;
+ case Variant_armeabi:
+ case Variant_armeabi_v7a:
+ case Variant_arm64_v8a:
+ return Family_arm;
+ case Variant_x86:
+ case Variant_x86_64:
+ return Family_intel;
+ case Variant_mips:
+ case Variant_mips64:
+ return Family_mips;
}
- return Family::none;
+ return Family_none;
}
-const std::vector<Variant>& getVariants(Family family) {
+const Vector<Variant>& getVariants(Family family) {
switch (family) {
- case Family::none:
+ case Family_none:
return sNoneVariants;
- case Family::arm:
+ case Family_arm:
return sArmVariants;
- case Family::intel:
+ case Family_intel:
return sIntelVariants;
- case Family::mips:
+ case Family_mips:
return sMipsVariants;
}
return sNoneVariants;
@@ -59,21 +75,21 @@
const char* toString(Variant variant) {
switch (variant) {
- case Variant::none:
+ case Variant_none:
return "";
- case Variant::armeabi:
+ case Variant_armeabi:
return "armeabi";
- case Variant::armeabi_v7a:
+ case Variant_armeabi_v7a:
return "armeabi-v7a";
- case Variant::arm64_v8a:
+ case Variant_arm64_v8a:
return "arm64-v8a";
- case Variant::x86:
+ case Variant_x86:
return "x86";
- case Variant::x86_64:
+ case Variant_x86_64:
return "x86_64";
- case Variant::mips:
+ case Variant_mips:
return "mips";
- case Variant::mips64:
+ case Variant_mips64:
return "mips64";
}
return "";
diff --git a/tools/split-select/Abi.h b/tools/split-select/Abi.h
index 3e00eba..85b4d62 100644
--- a/tools/split-select/Abi.h
+++ b/tools/split-select/Abi.h
@@ -17,31 +17,31 @@
#ifndef H_ANDROID_SPLIT_ABI
#define H_ANDROID_SPLIT_ABI
-#include <vector>
+#include <utils/Vector.h>
namespace split {
namespace abi {
-enum class Variant {
- none = 0,
- armeabi,
- armeabi_v7a,
- arm64_v8a,
- x86,
- x86_64,
- mips,
- mips64,
+enum Variant {
+ Variant_none = 0,
+ Variant_armeabi,
+ Variant_armeabi_v7a,
+ Variant_arm64_v8a,
+ Variant_x86,
+ Variant_x86_64,
+ Variant_mips,
+ Variant_mips64,
};
-enum class Family {
- none,
- arm,
- intel,
- mips,
+enum Family {
+ Family_none,
+ Family_arm,
+ Family_intel,
+ Family_mips,
};
Family getFamily(Variant variant);
-const std::vector<Variant>& getVariants(Family family);
+const android::Vector<Variant>& getVariants(Family family);
const char* toString(Variant variant);
} // namespace abi
diff --git a/tools/split-select/Android.mk b/tools/split-select/Android.mk
index d0b7287..dc48ea8 100644
--- a/tools/split-select/Android.mk
+++ b/tools/split-select/Android.mk
@@ -17,10 +17,6 @@
# This tool is prebuilt if we're doing an app-only build.
ifeq ($(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)),)
-# TODO(adamlesinski): Enable OS X builds when I figure out how
-# to build with clang and libc++
-ifneq ($(HOST_OS),darwin)
-
# ==========================================================
# Setup some common variables for the different build
# targets here.
@@ -55,7 +51,7 @@
libexpat \
libziparchive-host
-cFlags := -std=c++11 -Wall -Werror
+cFlags := -Wall -Werror
ifeq ($(HOST_OS),linux)
hostLdLibs += -lrt -ldl -lpthread
@@ -115,5 +111,4 @@
include $(BUILD_HOST_EXECUTABLE)
-endif # Not OS X
endif # No TARGET_BUILD_APPS or TARGET_BUILD_PDK
diff --git a/tools/split-select/Grouper.cpp b/tools/split-select/Grouper.cpp
index 15edf89..22685cd 100644
--- a/tools/split-select/Grouper.cpp
+++ b/tools/split-select/Grouper.cpp
@@ -16,25 +16,17 @@
#include "Grouper.h"
+#include "aapt/AaptUtil.h"
#include "SplitDescription.h"
#include <utils/KeyedVector.h>
#include <utils/Vector.h>
using namespace android;
+using AaptUtil::appendValue;
namespace split {
-template <typename Key, typename Value>
-static void addToVector(KeyedVector<Key, SortedVector<Value> >& group,
- const Key& key, const Value& value) {
- ssize_t idx = group.indexOfKey(key);
- if (idx < 0) {
- idx = group.add(key, SortedVector<Value>());
- }
- group.editValueAt(idx).add(value);
-}
-
Vector<SortedVector<SplitDescription> >
groupByMutualExclusivity(const Vector<SplitDescription>& splits) {
Vector<SortedVector<SplitDescription> > groups;
@@ -43,20 +35,22 @@
KeyedVector<SplitDescription, SortedVector<SplitDescription> > densityGroups;
KeyedVector<SplitDescription, SortedVector<SplitDescription> > abiGroups;
KeyedVector<SplitDescription, SortedVector<SplitDescription> > localeGroups;
- for (const SplitDescription& split : splits) {
+ const size_t splitCount = splits.size();
+ for (size_t i = 0; i < splitCount; i++) {
+ const SplitDescription& split = splits[i];
if (split.config.density != 0) {
SplitDescription key(split);
key.config.density = 0;
key.config.sdkVersion = 0; // Ignore density so we can support anydpi.
- addToVector(densityGroups, key, split);
- } else if (split.abi != abi::Variant::none) {
+ appendValue(densityGroups, key, split);
+ } else if (split.abi != abi::Variant_none) {
SplitDescription key(split);
- key.abi = abi::Variant::none;
- addToVector(abiGroups, key, split);
+ key.abi = abi::Variant_none;
+ appendValue(abiGroups, key, split);
} else if (split.config.locale != 0) {
SplitDescription key(split);
key.config.clearLocale();
- addToVector(localeGroups, key, split);
+ appendValue(localeGroups, key, split);
} else {
groups.add();
groups.editTop().add(split);
diff --git a/tools/split-select/Grouper_test.cpp b/tools/split-select/Grouper_test.cpp
index 4d146cd..a5f9c5a 100644
--- a/tools/split-select/Grouper_test.cpp
+++ b/tools/split-select/Grouper_test.cpp
@@ -19,7 +19,6 @@
#include "SplitDescription.h"
#include <gtest/gtest.h>
-#include <initializer_list>
#include <utils/String8.h>
#include <utils/Vector.h>
@@ -55,7 +54,11 @@
}
void addSplit(Vector<SplitDescription>& splits, const char* str);
- void expectHasGroupWithSplits(std::initializer_list<const char*> l);
+ void expectHasGroupWithSplits(const char* a);
+ void expectHasGroupWithSplits(const char* a, const char* b);
+ void expectHasGroupWithSplits(const char* a, const char* b, const char* c);
+ void expectHasGroupWithSplits(const char* a, const char* b, const char* c, const char* d);
+ void expectHasGroupWithSplits(const Vector<const char*>& expectedStrs);
Vector<SortedVector<SplitDescription> > mGroups;
};
@@ -65,39 +68,70 @@
}
TEST_F(GrouperTest, shouldGroupDensities) {
- expectHasGroupWithSplits({"en-rUS-sw300dp-hdpi", "en-rUS-sw300dp-xhdpi"});
- expectHasGroupWithSplits({"en-rUS-sw600dp-hdpi", "en-rUS-sw600dp-xhdpi"});
- expectHasGroupWithSplits({"fr-rFR-sw600dp-hdpi", "fr-rFR-sw600dp-xhdpi"});
- expectHasGroupWithSplits({"hdpi", "xhdpi", "xxhdpi", "anydpi"});
+ expectHasGroupWithSplits("en-rUS-sw300dp-hdpi", "en-rUS-sw300dp-xhdpi");
+ expectHasGroupWithSplits("en-rUS-sw600dp-hdpi", "en-rUS-sw600dp-xhdpi");
+ expectHasGroupWithSplits("fr-rFR-sw600dp-hdpi", "fr-rFR-sw600dp-xhdpi");
+ expectHasGroupWithSplits("hdpi", "xhdpi", "xxhdpi", "anydpi");
}
TEST_F(GrouperTest, shouldGroupAbi) {
- expectHasGroupWithSplits({":armeabi", ":x86"});
+ expectHasGroupWithSplits(":armeabi", ":x86");
}
TEST_F(GrouperTest, shouldGroupLocale) {
- expectHasGroupWithSplits({"pl-rPL", "de-rDE"});
+ expectHasGroupWithSplits("pl-rPL", "de-rDE");
}
TEST_F(GrouperTest, shouldGroupEachSplitIntoItsOwnGroup) {
- expectHasGroupWithSplits({"large"});
- expectHasGroupWithSplits({"xlarge"});
- expectHasGroupWithSplits({"v7"});
- expectHasGroupWithSplits({"v8"});
- expectHasGroupWithSplits({"sw600dp"});
- expectHasGroupWithSplits({"sw300dp"});
+ expectHasGroupWithSplits("large");
+ expectHasGroupWithSplits("xlarge");
+ expectHasGroupWithSplits("v7");
+ expectHasGroupWithSplits("v8");
+ expectHasGroupWithSplits("sw600dp");
+ expectHasGroupWithSplits("sw300dp");
}
//
// Helper methods
//
-void GrouperTest::expectHasGroupWithSplits(std::initializer_list<const char*> l) {
+void GrouperTest::expectHasGroupWithSplits(const char* a) {
+ Vector<const char*> expected;
+ expected.add(a);
+ expectHasGroupWithSplits(expected);
+}
+
+void GrouperTest::expectHasGroupWithSplits(const char* a, const char* b) {
+ Vector<const char*> expected;
+ expected.add(a);
+ expected.add(b);
+ expectHasGroupWithSplits(expected);
+}
+
+void GrouperTest::expectHasGroupWithSplits(const char* a, const char* b, const char* c) {
+ Vector<const char*> expected;
+ expected.add(a);
+ expected.add(b);
+ expected.add(c);
+ expectHasGroupWithSplits(expected);
+}
+
+void GrouperTest::expectHasGroupWithSplits(const char* a, const char* b, const char* c, const char* d) {
+ Vector<const char*> expected;
+ expected.add(a);
+ expected.add(b);
+ expected.add(c);
+ expected.add(d);
+ expectHasGroupWithSplits(expected);
+}
+
+void GrouperTest::expectHasGroupWithSplits(const Vector<const char*>& expectedStrs) {
Vector<SplitDescription> splits;
- for (const char* str : l) {
+ const size_t expectedStrCount = expectedStrs.size();
+ for (size_t i = 0; i < expectedStrCount; i++) {
splits.add();
- if (!SplitDescription::parse(String8(str), &splits.editTop())) {
- ADD_FAILURE() << "Failed to parse SplitDescription " << str;
+ if (!SplitDescription::parse(String8(expectedStrs[i]), &splits.editTop())) {
+ ADD_FAILURE() << "Failed to parse SplitDescription " << expectedStrs[i];
return;
}
}
diff --git a/tools/split-select/Main.cpp b/tools/split-select/Main.cpp
index d6251c3..434494e 100644
--- a/tools/split-select/Main.cpp
+++ b/tools/split-select/Main.cpp
@@ -63,7 +63,7 @@
class SplitSelector {
public:
- SplitSelector() = default;
+ SplitSelector();
SplitSelector(const Vector<SplitDescription>& splits);
Vector<SplitDescription> getBestSplits(const SplitDescription& target) const;
@@ -75,6 +75,9 @@
Vector<SortedVector<SplitDescription> > mGroups;
};
+SplitSelector::SplitSelector() {
+}
+
SplitSelector::SplitSelector(const Vector<SplitDescription>& splits)
: mGroups(groupByMutualExclusivity(splits)) {
}
diff --git a/tools/split-select/RuleGenerator.cpp b/tools/split-select/RuleGenerator.cpp
index 669ae78..b8f3bcb 100644
--- a/tools/split-select/RuleGenerator.cpp
+++ b/tools/split-select/RuleGenerator.cpp
@@ -65,12 +65,12 @@
sp<Rule> RuleGenerator::generateAbi(const Vector<abi::Variant>& splitAbis, size_t index) {
const abi::Variant thisAbi = splitAbis[index];
- const std::vector<abi::Variant>& familyVariants = abi::getVariants(abi::getFamily(thisAbi));
+ const Vector<abi::Variant>& familyVariants = abi::getVariants(abi::getFamily(thisAbi));
- std::vector<abi::Variant>::const_iterator start =
+ Vector<abi::Variant>::const_iterator start =
std::find(familyVariants.begin(), familyVariants.end(), thisAbi);
- std::vector<abi::Variant>::const_iterator end = familyVariants.end();
+ Vector<abi::Variant>::const_iterator end = familyVariants.end();
if (index + 1 < splitAbis.size()) {
end = std::find(start, familyVariants.end(), splitAbis[index + 1]);
}
@@ -127,7 +127,7 @@
rootRule->subrules.add(generateDensity(allDensities, densityIndex));
}
- if (group[index].abi != abi::Variant::none) {
+ if (group[index].abi != abi::Variant_none) {
size_t abiIndex = 0;
Vector<abi::Variant> allVariants;
allVariants.add(group[index].abi);
diff --git a/tools/split-select/RuleGenerator_test.cpp b/tools/split-select/RuleGenerator_test.cpp
index 60baabe..ee387be 100644
--- a/tools/split-select/RuleGenerator_test.cpp
+++ b/tools/split-select/RuleGenerator_test.cpp
@@ -25,19 +25,19 @@
namespace split {
static void expectDensityRule(const Vector<int>& densities, int density, int greaterThan, int lessThan);
-static void expectAbiRule(const Vector<abi::Variant>& abis, abi::Variant variant,
- std::initializer_list<const char*> matches);
+static void expectAbiRule(const Vector<abi::Variant>& abis, abi::Variant variant, const char* a);
+static void expectAbiRule(const Vector<abi::Variant>& abis, abi::Variant variant, const char* a, const char* b);
TEST(RuleGeneratorTest, testAbiRules) {
Vector<abi::Variant> abis;
- abis.add(abi::Variant::armeabi);
- abis.add(abi::Variant::armeabi_v7a);
- abis.add(abi::Variant::x86);
+ abis.add(abi::Variant_armeabi);
+ abis.add(abi::Variant_armeabi_v7a);
+ abis.add(abi::Variant_x86);
std::sort(abis.begin(), abis.end());
- expectAbiRule(abis, abi::Variant::armeabi, {"armeabi"});
- expectAbiRule(abis, abi::Variant::armeabi_v7a, {"armeabi-v7a", "arm64-v8a"});
- expectAbiRule(abis, abi::Variant::x86, {"x86", "x86_64"});
+ expectAbiRule(abis, abi::Variant_armeabi, "armeabi");
+ expectAbiRule(abis, abi::Variant_armeabi_v7a, "armeabi-v7a", "arm64-v8a");
+ expectAbiRule(abis, abi::Variant_x86, "x86", "x86_64");
}
TEST(RuleGeneratorTest, testDensityRules) {
@@ -126,8 +126,7 @@
}
}
-static void expectAbiRule(const Vector<abi::Variant>& abis, abi::Variant variant,
- std::initializer_list<const char*> matches) {
+static void expectAbiRule(const Vector<abi::Variant>& abis, abi::Variant variant, const Vector<const char*>& matches) {
const abi::Variant* iter = std::find(abis.begin(), abis.end(), variant);
if (abis.end() == iter) {
ADD_FAILURE() << abi::toString(variant) << " was not in the abi list.";
@@ -143,7 +142,9 @@
EXPECT_EQ(matches.size(), rule->stringArgs.size())
<< " for " << abi::toString(variant) << " rule";
- for (const char* match : matches) {
+ const size_t matchCount = matches.size();
+ for (size_t i = 0; i < matchCount; i++) {
+ const char* match = matches[i];
if (rule->stringArgs.end() ==
std::find(rule->stringArgs.begin(), rule->stringArgs.end(), String8(match))) {
ADD_FAILURE() << "Rule for abi " << abi::toString(variant)
@@ -152,4 +153,17 @@
}
}
+static void expectAbiRule(const Vector<abi::Variant>& abis, abi::Variant variant, const char* a) {
+ Vector<const char*> matches;
+ matches.add(a);
+ expectAbiRule(abis, variant, matches);
+}
+
+static void expectAbiRule(const Vector<abi::Variant>& abis, abi::Variant variant, const char* a, const char* b) {
+ Vector<const char*> matches;
+ matches.add(a);
+ matches.add(b);
+ expectAbiRule(abis, variant, matches);
+}
+
} // namespace split
diff --git a/tools/split-select/SplitDescription.cpp b/tools/split-select/SplitDescription.cpp
index 8037ef0..99bc23d 100644
--- a/tools/split-select/SplitDescription.cpp
+++ b/tools/split-select/SplitDescription.cpp
@@ -27,7 +27,7 @@
namespace split {
SplitDescription::SplitDescription()
-: abi(abi::Variant::none) {
+: abi(abi::Variant_none) {
}
int SplitDescription::compare(const SplitDescription& rhs) const {
@@ -38,11 +38,11 @@
}
bool SplitDescription::isBetterThan(const SplitDescription& o, const SplitDescription& target) const {
- if (abi != abi::Variant::none || o.abi != abi::Variant::none) {
+ if (abi != abi::Variant_none || o.abi != abi::Variant_none) {
abi::Family family = abi::getFamily(abi);
abi::Family oFamily = abi::getFamily(o.abi);
if (family != oFamily) {
- return family != abi::Family::none;
+ return family != abi::Family_none;
}
if (int(target.abi) - int(abi) < int(target.abi) - int(o.abi)) {
@@ -53,7 +53,7 @@
}
bool SplitDescription::match(const SplitDescription& o) const {
- if (abi != abi::Variant::none) {
+ if (abi != abi::Variant_none) {
abi::Family family = abi::getFamily(abi);
abi::Family oFamily = abi::getFamily(o.abi);
if (family != oFamily) {
@@ -69,7 +69,7 @@
String8 SplitDescription::toString() const {
String8 extension;
- if (abi != abi::Variant::none) {
+ if (abi != abi::Variant_none) {
if (extension.isEmpty()) {
extension.append(":");
} else {
@@ -85,40 +85,40 @@
ssize_t parseAbi(const Vector<String8>& parts, const ssize_t index,
SplitDescription* outSplit) {
const ssize_t N = parts.size();
- abi::Variant abi = abi::Variant::none;
+ abi::Variant abi = abi::Variant_none;
ssize_t endIndex = index;
if (parts[endIndex] == "arm64") {
endIndex++;
if (endIndex < N) {
if (parts[endIndex] == "v8a") {
endIndex++;
- abi = abi::Variant::arm64_v8a;
+ abi = abi::Variant_arm64_v8a;
}
}
} else if (parts[endIndex] == "armeabi") {
endIndex++;
- abi = abi::Variant::armeabi;
+ abi = abi::Variant_armeabi;
if (endIndex < N) {
if (parts[endIndex] == "v7a") {
endIndex++;
- abi = abi::Variant::armeabi_v7a;
+ abi = abi::Variant_armeabi_v7a;
}
}
} else if (parts[endIndex] == "x86") {
endIndex++;
- abi = abi::Variant::x86;
+ abi = abi::Variant_x86;
} else if (parts[endIndex] == "x86_64") {
endIndex++;
- abi = abi::Variant::x86_64;
+ abi = abi::Variant_x86_64;
} else if (parts[endIndex] == "mips") {
endIndex++;
- abi = abi::Variant::mips;
+ abi = abi::Variant_mips;
} else if (parts[endIndex] == "mips64") {
endIndex++;
- abi = abi::Variant::mips64;
+ abi = abi::Variant_mips64;
}
- if (abi == abi::Variant::none && endIndex != index) {
+ if (abi == abi::Variant_none && endIndex != index) {
return -1;
}
diff --git a/tools/split-select/SplitDescription.h b/tools/split-select/SplitDescription.h
index 5fcafc8..b13c9ee 100644
--- a/tools/split-select/SplitDescription.h
+++ b/tools/split-select/SplitDescription.h
@@ -27,7 +27,6 @@
struct SplitDescription {
SplitDescription();
- SplitDescription(const SplitDescription&) = default;
ConfigDescription config;
abi::Variant abi;