Cutting MySQL into Musl Shape



July 14th, 2018 by Diana Coman

As I'm apparently the adventurous type or in fewer words an ice-breaker, I got to see all the ways in which MySQL fails to compile on a musltronic1 gentoo2. Note that there aren't that many versions of MySQL that portage knows about in the first place (exactly 5 versions: 5.5.60, 5.6.38, 5.6.39, 5.6.40, 5.7.22), mainly because of the nonsense proposition that "oh, we moved on to something new and shiny on which we got to stick another label and another name, be it mariadb". To quote specifically from mariadb itself when built3:

* Starting with version 10.1.8, MariaDB includes an improved systemd unit named mariadb.service
* You should prefer that unit over this package's mysqld.service.

Do you hear that? I won't even touch on the systemd nonsense but just read over and over again that part that says *you should prefer that unit* and nothing more. And tell me how can one write such a thing in the configuration files of a piece of software and then still have claim to ever be given the time of the day, not to mention to not being laughed out of town. And note that being laughed out of town is the best case there because frankly I find that offensive like hell rather than funny in the least.

Anyway, discarding with much pleasure the thing that "everyone" says I should prefer, here are the ways in which the various MySQL versions fail to emerge:

5.5.60: this version of MySQL pulls in openssl no matter what; even when libressl flag is added; even when -openssl is specifically added too; I just couldn't get it to leave openssl alone and so it's totally dead in the water. Not to mention that openssl then conflicts with libressl, so it's totally out of the question. RIP.

5.6.38: this was the preferred version so it was tried first, with a mask on anything greater than this aka >dev-db/mysql-5.6.38 written in /etc/portage/package.mask; it fails to compile because deep inside mysql code the stacktrace.c file relies on some thd_lib_detected variable and THD_LIB_LT constant to find out what implementation of threads it is running with. It was the first time I even saw those 2 things, a grep in MySQL code did NOT turn them anywhere else and then a quick dive into docs and everything else failed to find them anywhere *else* than in MySQL code. So I'm not even sure where are they meant to be set exactly, but given how the code compiles fine on a glibc system and fails miserably on the Musl system, I suspect it's some glibc-specific approach that got baked into this tiny corner of MySQL. Big mistake for the tiny corner, since the solution is to cut it away, of course. Anyway, the fail:

/var/tmp/portage/dev-db/mysql-5.6.38/work/mysql/mysys/stacktrace.c: In function 'my_print_stacktrace':
/var/tmp/portage/dev-db/mysql-5.6.38/work/mysql/mysys/stacktrace.c:360:27:
error: 'thd_lib_detected' undeclared (first use in this function)
sigreturn_frame_count = thd_lib_detected == THD_LIB_LT ? 2 : 1;
^
/var/tmp/portage/dev-db/mysql-5.6.38/work/mysql/mysys/stacktrace.c:360:27:
note: each undeclared identifier is reported only once for each function it appears in
/var/tmp/portage/dev-db/mysql-5.6.38/work/mysql/mysys/stacktrace.c:360:47:
error: 'THD_LIB_LT' undeclared (first use in this function)
sigreturn_frame_count = thd_lib_detected == THD_LIB_LT ? 2 : 1;

5.6.39: this is the version pulled by portage without any masking or keywords; it fails just like 5.6.38 with loud complaints about the unknown thd_lib constant & variable:

/var/tmp/portage/dev-db/mysql-5.6.39/work/mysql/mysys/stacktrace.c:360:27:
error: 'thd_lib_detected' undeclared (first use in this function)
sigreturn_frame_count = thd_lib_detected == THD_LIB_LT ? 2 : 1;
^
/var/tmp/portage/dev-db/mysql-5.6.39/work/mysql/mysys/stacktrace.c:360:27:
note: each undeclared identifier is reported only once for each function it appears in
/var/tmp/portage/dev-db/mysql-5.6.39/work/mysql/mysys/stacktrace.c:360:47:
error: 'THD_LIB_LT' undeclared (first use in this function)
sigreturn_frame_count = thd_lib_detected == THD_LIB_LT ? 2 : 1;

5.6.40: this fails quite the same as the 5.6.38 and 5.6.49 above:

/var/tmp/portage/dev-db/mysql-5.6.40/work/mysql/mysys/stacktrace.c: In function 'my_print_stacktrace':
/var/tmp/portage/dev-db/mysql-5.6.40/work/mysql/mysys/stacktrace.c:360:27:
error: 'thd_lib_detected' undeclared (first use in this function)
sigreturn_frame_count = thd_lib_detected == THD_LIB_LT ? 2 : 1;
^
/var/tmp/portage/dev-db/mysql-5.6.40/work/mysql/mysys/stacktrace.c:360:27:
note: each undeclared identifier is reported only once for each function it appears in
/var/tmp/portage/dev-db/mysql-5.6.40/work/mysql/mysys/stacktrace.c:360:47:
error: 'THD_LIB_LT' undeclared (first use in this function)
sigreturn_frame_count = thd_lib_detected == THD_LIB_LT ? 2 : 1;

5.7.22: this version requires the ~amd64 keywords on my proto-cuntoo so it's supposedly "at your own risk" grade. It fails at configuration stage with CMake barfing about a lack of mysys timer:

CMake Error at configure.cmake:573 (MESSAGE):
No mysys timer support detected!
Call Stack (most recent call first):
CMakeLists.txt:451 (INCLUDE)

And then I threw my hands up in despair at it all, took the plunge into MySQL code and Gentoo's very useful ebuild command4, cut away the misbehaving part and had the pleasant surprise that it was actually enough to make the whole thing work! After which I spent of course another few hours just checking the whole thing through because by now I am very, very suspicious when it's relatively easy to fix something.

The good news is that MySQL can be made to work on a musltronic system with just a small snip of the "safe printing" of a stacktrace - as I'm not terribly concerned at this time about MySQL's own stacktrace printing, I didn't really spend the time to *fix* the code although I'm sure it can be done with a bit of study of threads in Musl. For now though I am content to just delete that code and yes, have a MySQL that won't print its stacktrace. Specifically, here are the steps to get MySQL going on a proto-cuntoo system:

1. Get the source code by instructing ebuild to "fetch":

ebuild /usr/portage/dev-db/mysql/mysql-5.6.38.ebuild fetch

2. Unpack it:

ebuild /usr/portage/dev-db/mysql/mysql-5.6.38.ebuild unpack

3. Simply delete the contents of method my_print_stacktrace(uchar* stack_bottom, ulong thread_stack)  in /var/tmp/portage/dev-db/mysql-5.6.39/work/mysql/mysys/stacktrace.c and save the file. Leave the empty shell of the method there since it IS called (yes, I checked). Ideally one would fix the code I guess, but atm I really don't see this worth the time since the moment mysql fails that badly I seriously doubt I'll want to spend the time investigating its stack trace - it's more likely I'll throw it out the window entirely. At any rate, as this is not a "fix" by any measure, I'm not making it into a patch so you'll have to run through those steps rather than just emerge.

4. With the code thus modified, ask ebuild to go ahead and compile, install and then merge the result into the live file system, so three different commands to be run one at a time:

ebuild /usr/portage/dev-db/mysql/mysql-5.6.38.ebuild compile
ebuild /usr/portage/dev-db/mysql/mysql-5.6.38.ebuild install
ebuild /usr/portage/dev-db/mysql/mysql-5.6.38.ebuild qmerge

5. It's done; run your usual emerge --config=dev-db/mysql-5.6.38 and set the root password, create databases and users, as you need.

And there it is, I can happily report that MySQL 5.6.38 is now compiling and running quite happily on a fully musltronic system!


  1. Aka Musl-based rather than glibc-inflated. 

  2. Also known as proto-cuntoo since that's exactly what it is: an alpha version of trinque's cuntoo.  

  3. Yes, I built this one too and it builds fine. No, I won't use it though. 

  4. Man page for ebuild most recommended read! 

Comments feed: RSS 2.0

7 Responses to “Cutting MySQL into Musl Shape”

  1. pasenor says:

    You can just undefine the HAVE_STACKTRACE macro:

    sed 's/#define HAVE_STACKTRACE 1//g' -i /include/my_stacktrace.h

  2. Diana Coman says:

    Hi pasenor, are you familiar with the guts of mysql there?

    Tbh I just went straight for the troublesome code so perhaps I did use a bigger hammer than strictly necessary but then again, I'd rather take the whole thing out entirely so the macro too, sure.

  3. You know, this is actually pretty fucking great news.

  4. [...] else I could find on the topic) really focus almost exclusively2 on TCP connections - I suspect one "should prefer" TCP over UDP simply like that and we are even past the point of discussing therefore UDP in any [...]

  5. [...] it is "for some reasons not good", mmkay? It reminds me of the other display of great expertise in "reasons". Without wasting even more time on the MPI code of wonders5, the solution for SMG Comms is [...]

  6. [...] Where to begin but at the beginning? lobbes: welcome jfw here as well! lol. diana_coman this is Jacob Welsh (he's commented on a few things on Trilema and my own blog). I pointed him to your castle jfw: A vast republic of many castles! I think I'll start here because my current quest is blogotronics, which has me digging into a MySQL build and I see diana_coman was wrestling with it in http://ossasepia.com/2018/07/14/cutting-mysql-into-musl-shape/ [...]

  7. [...] when I took its first steps in July of 2020. My starting point was version 5.6.38, because it had been proven to work, after a fashion, in a prototype Cuntoo environment. This shared with Gales its most significant divergence from [...]

Leave a Reply to Mircea Popescu