Allow both types of constrained drag (again).
[ardour.git] / tools / gccabicheck / abicheck.c
1 /* Copyright (C) 2015 Robin Gareus <robin@gareus.org>
2  *
3  * This program is free software. It comes without any warranty, to
4  * the extent permitted by applicable law. You can redistribute it
5  * and/or modify it under the terms of the Do What The Fuck You Want
6  * To Public License, Version 2, as published by Sam Hocevar. See
7  * http://www.wtfpl.net/ for more details.
8  */
9
10 // gcc -Wall -o gcc-glibmm-abi-check abicheck.c -ldl
11 // help2man -N -n 'glib gcc4/5 C++11 ABI compatibility test' -o gcc-glibmm-abi-check.1 ./gcc-glibmm-abi-check
12
13 #include <stdio.h>
14 #include <dlfcn.h>
15 #include <getopt.h>
16
17 #ifndef VERSION
18 #define VERSION "0.1"
19 #endif
20
21 static void print_usage (void) {
22         printf ("gcc-glibmm-abi-check - gcc4/5 C++11 ABI compatibility test\n\n");
23
24         printf ("Usage: gcc-glibmm-abi-check [ OPTIONS ]\n\n");
25         printf (
26                         "This tool checks for C++ specific symbols in libglimm which are different in\n"
27                         "the gcc4 and gcc5/c++11 ABI in order to determine system-wide use of gcc5.\n"
28                         // TODO document error codes,...
29                         );
30
31         printf ("\nOptions:\n"
32                         " -f, --fail                fail if system cannot be determined.\n"
33                         " -h, --help                Display this help and exit.\n"
34                         " -4, --gcc4                Test succeeds if gcc4 ABI is found.\n"
35                         " -5, --gcc5                Test succeeds if gcc5 ABI is found.\n"
36                         " -g <soname>, --glibmm <soname>\n"
37                         "                           Specify alternative file for libglibmm-2.4.so\n"
38                         " -v, --verbose             Print information.\n"
39                         " -V, --version             Print version information and exit.\n"
40                         );
41 }
42
43 static void print_version (void) {
44         printf ("gcc-glibmm-abi-check version %s\n\n", VERSION);
45         printf (
46                         "Copyright (C) 2015 Robin Gareus <robin@gareus.org>\n"
47                         "This is free software; see the source for copying conditions.  There is NO\n"
48                         "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
49 }
50
51
52 int main (int argc, char **argv) {
53         int expect = 0;
54         int error_fail = 0;
55         int verbose = 0;
56
57         char const * glibmm = "libglibmm-2.4.so.1";
58
59         const struct option long_options[] = {
60                 { "fail",       no_argument,       0, 'f' },
61                 { "help",       no_argument,       0, 'h' },
62                 { "gcc4",       no_argument,       0, '4' },
63                 { "gcc5",       no_argument,       0, '5' },
64                 { "glibmm",     required_argument, 0, 'g' },
65                 { "verbose",    no_argument,       0, 'v' },
66                 { "version",    no_argument,       0, 'V' },
67         };
68
69         const char *optstring = "fh45g:vV";
70
71         int c;
72         while ((c = getopt_long (argc, argv, optstring, long_options, NULL)) != -1) {
73                 switch (c) {
74                         case 'f':
75                                 error_fail = 1;
76                                 break;
77                         case 'h':
78                                 print_usage ();
79                                 return 0;
80                                 break;
81                         case '4':
82                                 expect |= 1;
83                                 break;
84                         case '5':
85                                 expect |= 2;
86                                 break;
87                         case 'g':
88                                 glibmm = optarg;
89                                 break;
90                         case 'v':
91                                 verbose = 1;
92                                 break;
93                         case 'V':
94                                 print_version ();
95                                 return 0;
96                                 break;
97                         default:
98                                 fprintf (stderr, "invalid argument.\n");
99                                 print_usage ();
100                                 return -1;
101                                 break;
102                 }
103         }
104
105         int gcc5 = 0;
106         int gcc4 = 0;
107
108         dlerror (); // reset error
109
110         void *h = dlopen (glibmm, RTLD_LAZY);
111         if (!h) {
112                 if (verbose) {
113                         fprintf (stderr, "Cannot open '%s': %s.\n", glibmm, dlerror ());
114                 }
115                 return error_fail ? 3 : 0;
116         }
117
118         // Glib::ustring::ustring(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
119         if (dlsym (h, "_ZN4Glib7ustringC1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE")) {
120                 gcc5 |= 1;
121         }
122
123         // Glib::ustring::ustring(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
124         if (dlsym (h, "_ZN4Glib7ustringC1ERKSs")) {
125                 gcc4 |= 1;
126         }
127
128
129         // Glib::Module::Module(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Glib::ModuleFlags)
130         if (dlsym (h, "_ZN4Glib6ModuleC1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_11ModuleFlagsE")) {
131                 gcc5 |= 2;
132         }
133
134         // Glib::Module::Module(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Glib::ModuleFlags)
135         if (dlsym (h, "_ZN4Glib6ModuleC1ERKSsNS_11ModuleFlagsE")) {
136                 gcc4 |= 2;
137         }
138
139
140         // Glib::ustring::operator=(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
141         if (dlsym (h, "_ZN4Glib7ustringaSERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE")) {
142                 gcc5 |= 4;
143         }
144
145         // Glib::ustring::operator=(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
146         if (dlsym (h, "_ZN4Glib7ustringaSERKSs")) {
147                 gcc4 |= 4;
148         }
149
150         dlclose (h);
151
152         if (7 != (gcc4 ^ gcc5)) {
153                 if (verbose) {
154                         fprintf (stderr, "Inconsistent result: gcc4=%x gcc5=%x\n", gcc4, gcc5);
155                 }
156         }
157         else if (gcc4 == 7) {
158                 if (verbose) {
159                         printf ("System uses gcc4 c++ ABI\n");
160                 }
161                 if (expect != 0) {
162                         return (expect & 1) ? 0 : 1;
163                 }
164         }
165         else if (gcc5 == 7) {
166                 if (verbose) {
167                         printf ("System uses gcc5 c++11 ABI\n");
168                 }
169                 if (expect != 0) {
170                         return (expect & 2) ? 0 : 1;
171                 }
172         }
173         else if (verbose) {
174                 fprintf (stderr, "Incomplete result: gcc4=%x gcc5=%x\n", gcc4, gcc5);
175         }
176
177         return error_fail ? 2 : 0;
178 }