Getting Ruby to Compile in Modern Linux Distros

If we lived and worked in a laboratory environment, everything everywhere would run, compile and “just work” with the right versions of dependencies and requirements working “just fine” - and we would all have world peace, and no children would go hungry.
Back in the real world, though, it happens from time to time that the version of a dependency you need just isn’t working anymore. Usually, this means updating something or making a small adjustment. Every once in a while, though, dependencies get out of date, and updating things just isn’t an option. That’s where we find ourselves today.

Use Modern Linux

New versions of Linux have been released that dropped support for OpenSSL version 1.1 and instead only support newer versions of OpenSSL. This doesn’t mean that OpenSSL 1.1 can’t work, just that newer versions of some Linux distros are not going to release it in their package managers. That’s ok. Linux users have to move on at some point in time. OpenSSL 1.1 is 4 years old, and while the OpenSSL team has said it will EOL in 2023, current Linux LTS releases have to support what they release until around 2027.
Back in Ruby, OpenSSL 3 is not new. It was released in 2021. So there has been time to prepare for the transition to OpenSSL 3. This starts to be a problem if you can’t run ruby versions that are up to date. If you are running or can run Ruby 3.1 then you have no issues. But what about those projects running older versions of Rails that need older versions of ruby?
Like Ruby 2.7, Ruby 2.5, or even Ruby 1.9? Well, they won’t compile without a bit of “extra” work. Trying to compile them on a “new” Linux distro will give an error like this: (many lines omitted to make it workable)

compiling openssl_missing.c
compiling ossl_bn.c
ossl.c: In function ‘ossl_protect_x509 _ary2sk’:
ossl.c:47:13: warning: cast between incompatible function types from ‘struct stack_st_X509 * (*)(VALUE)’ {aka ‘struct stack_st_X509 * (\)(long unsigned int)’} to ‘VALUE (\)(VALUE)’ {aka ‘long unsigned int (\)(long unsigned int)’} [-Wcast-function-type]
47 | (VALUE (*)(VALUE))ossl##name##_ary2sk0,
| ^
ossl.c:63:1: note: in expansion of macro ‘OSSL_IMPL_ARY2SK’
63 | OSSL_IMPL_ARY2SK(x509, X509, cX509Cert, DupX509CertPtr)
| ^<<<<<<<<<<<<<<<
ossl_asn1.c: In function ‘decode_int’:
ossl_asn1.c:328:22: warning: cast between incompatible function types from ‘VALUE ( )(const ASN1_INTEGER *)’ {aka ‘long unsigned int ()(const struct asn1_string_st )’} to ‘VALUE ()(VALUE)’ {aka ‘long unsigned int ( )(long unsigned int)’} [-Wcast-function-type]
328 | ret = rb_protect((VALUE ()(VALUE))asn1integer_to_num,
| ^
ossl_asn1.c: In function ‘decode_enum’:
ossl_asn1.c:368:22: warning: cast between incompatible function types from ‘VALUE ( )(const ASN1_INTEGER *)’ {aka ‘long unsigned int ()(const struct asn1_string_st )’} to ‘VALUE ()(VALUE)’ {aka ‘long unsigned int ( )(long unsigned int)’} [-Wcast-function-type]
368 | ret = rb_protect((VALUE ()(VALUE))asn1integer_to_num,
| ^
ossl_asn1.c: In function ‘decode_time’:
ossl_asn1.c:430:22: warning: cast between incompatible function types from ‘VALUE ( )(const ASN1_TIME *)’ {aka ‘long unsigned int ()(const struct asn1_string_st )’} to ‘VALUE ()(VALUE)’ {aka ‘long unsigned int ( )(long unsigned int)’} [-Wcast-function-type]
430 | ret = rb_protect((VALUE ()(VALUE))asn1time_to_time,
| ^
ossl.c: In function ‘ossl_clear_error’:
ossl.c:311:9: error: ‘ERR_get_error_line_data’ is deprecated: Since OpenSSL 3.0 [-Werror=deprecated-declarations]
311 | while ((e = ERR_get_error_line_data(&file, &line, &data, &flags))) {
| ^<<<<
In file included from ossl.h:21,
from ossl.c:10:
/usr/include/openssl/err.h:413:15: note: declared here
413 | unsigned long ERR_get_error_line_data(const char **file, int *line,
| ^<<<<<<<<<<<<<<<<<<<<<<