summaryrefslogtreecommitdiff
path: root/tools/gccabicheck/abicheck.c
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2015-09-26 18:23:19 +0200
committerRobin Gareus <robin@gareus.org>2015-09-26 19:03:22 +0200
commitba6e274efa8ec04ffa26cb74a4a9879294720bdf (patch)
treed4d897753739f4faff4c5680d91bebe323711b95 /tools/gccabicheck/abicheck.c
parent9a47744fc0849ac42f0a2b206347ce3079dfef28 (diff)
new tool to test gcc4/5 ABI
Diffstat (limited to 'tools/gccabicheck/abicheck.c')
-rw-r--r--tools/gccabicheck/abicheck.c166
1 files changed, 166 insertions, 0 deletions
diff --git a/tools/gccabicheck/abicheck.c b/tools/gccabicheck/abicheck.c
new file mode 100644
index 0000000000..fcff80e611
--- /dev/null
+++ b/tools/gccabicheck/abicheck.c
@@ -0,0 +1,166 @@
+// gcc -Wall -o gcc-glibmm-abi-check abicheck.c -ldl
+// help2man -N -n 'glib gcc4/5 C++11 ABI compatibility test' -o gcc-glibmm-abi-check.1 ./gcc-glibmm-abi-check
+#include <stdio.h>
+#include <dlfcn.h>
+#include <getopt.h>
+
+#ifndef VERSION
+#define VERSION "0.1"
+#endif
+
+static void print_usage (void) {
+ printf ("gcc-glibmm-abi-check - gcc4/5 C++11 ABI compatibility test\n\n");
+
+ printf ("Usage: gcc-glibmm-abi-check [ OPTIONS ]\n\n");
+ printf (
+ "This tool checks for C++ specific symbols in libglimm which are different in\n"
+ "the gcc4 and gcc5/c++11 ABI in order to determine system-wide use of gcc5.\n"
+ // TODO document error codes,...
+ );
+
+ printf ("\nOptions:\n"
+ " -f, --fail fail if system cannot be determined.\n"
+ " -h, --help Display this help and exit.\n"
+ " -4, --gcc4 Test succeeds if gcc4 ABI is found.\n"
+ " -5, --gcc5 Test succeeds if gcc5 ABI is found.\n"
+ " -g <soname>, --glibmm <soname>\n"
+ " Specify alternative file for libglibmm-2.4.so\n"
+ " -v, --verbose Print information.\n"
+ " -V, --version Print version information and exit.\n"
+ );
+}
+
+static void print_version (void) {
+ printf ("gcc-glibmm-abi-check version %s\n\n", VERSION);
+ printf (
+ "Copyright (C) GPL 2015 Robin Gareus <robin@gareus.org>\n"
+ "This is free software; see the source for copying conditions. There is NO\n"
+ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
+}
+
+
+int main (int argc, char **argv) {
+ int expect = 0;
+ int error_fail = 0;
+ int verbose = 0;
+
+ char *glibmm = "libglibmm-2.4.so";
+
+ const struct option long_options[] = {
+ { "help", no_argument, 0, 'h' },
+ { "gcc4", no_argument, 0, '4' },
+ { "gcc5", no_argument, 0, '5' },
+ { "glibmm", required_argument, 0, 'g' },
+ { "version", no_argument, 0, 'V' },
+ };
+
+ const char *optstring = "fh45g:vV";
+
+ int c;
+ while ((c = getopt_long (argc, argv, optstring, long_options, NULL)) != -1) {
+ switch (c) {
+ case 'f':
+ error_fail = 1;
+ break;
+ case 'h':
+ print_usage ();
+ return 0;
+ break;
+ case '4':
+ expect |= 1;
+ break;
+ case '5':
+ expect |= 2;
+ break;
+ case 'g':
+ glibmm = optarg;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case 'V':
+ print_version ();
+ return 0;
+ break;
+ default:
+ fprintf (stderr, "invalid argument.\n");
+ print_usage ();
+ return -1;
+ break;
+ }
+ }
+
+ int gcc5 = 0;
+ int gcc4 = 0;
+
+ dlerror (); // reset error
+
+ void *h = dlopen (glibmm, RTLD_LAZY);
+ if (!h) {
+ if (verbose) {
+ fprintf (stderr, "Cannot open '%s': %s.\n", glibmm, dlerror ());
+ }
+ return error_fail ? 3 : 0;
+ }
+
+ // Glib::ustring::ustring(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
+ if (dlsym (h, "_ZN4Glib7ustringC1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE")) {
+ gcc5 |= 1;
+ }
+
+ // Glib::ustring::ustring(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
+ if (dlsym (h, "_ZN4Glib7ustringC1ERKSs")) {
+ gcc4 |= 1;
+ }
+
+
+ // Glib::Module::Module(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Glib::ModuleFlags)
+ if (dlsym (h, "_ZN4Glib6ModuleC1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_11ModuleFlagsE")) {
+ gcc5 |= 2;
+ }
+
+ // Glib::Module::Module(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Glib::ModuleFlags)
+ if (dlsym (h, "_ZN4Glib6ModuleC1ERKSsNS_11ModuleFlagsE")) {
+ gcc4 |= 2;
+ }
+
+
+ // Glib::ustring::operator=(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
+ if (dlsym (h, "_ZN4Glib7ustringaSERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE")) {
+ gcc5 |= 4;
+ }
+
+ // Glib::ustring::operator=(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
+ if (dlsym (h, "_ZN4Glib7ustringaSERKSs")) {
+ gcc4 |= 4;
+ }
+
+ dlclose (h);
+
+ if (7 != (gcc4 ^ gcc5)) {
+ if (verbose) {
+ fprintf (stderr, "Inconsistent result: gcc4=%x gcc5=%x\n", gcc4, gcc5);
+ }
+ }
+ else if (gcc4 == 7) {
+ if (verbose) {
+ printf ("System uses gcc4 c++ ABI\n");
+ }
+ if (expect != 0) {
+ return (expect & 1) ? 0 : 1;
+ }
+ }
+ else if (gcc5 == 7) {
+ if (verbose) {
+ printf ("System uses gcc5 c++11 ABI\n");
+ }
+ if (expect != 0) {
+ return (expect & 2) ? 0 : 1;
+ }
+ }
+ else if (verbose) {
+ fprintf (stderr, "Incomplete result: gcc4=%x gcc5=%x\n", gcc4, gcc5);
+ }
+
+ return error_fail ? 2 : 0;
+}