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