Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MacOS: fails to build extension #592

Open
mouse07410 opened this issue Jan 3, 2023 · 11 comments
Open

MacOS: fails to build extension #592

mouse07410 opened this issue Jan 3, 2023 · 11 comments

Comments

@mouse07410
Copy link

MacOS Monterey 12.6.2 (Interl-based iMac), OpenSSL-1.1.1s (also have OpenSSL-3.0.7, but it fails to build extension exactly the same way), Macports-installed Ruby-3.2 (same results with Ruby-3.1).

The problem seems to be with openssl-3.1.0/ext/openssl/openssl_missing.h file, which improperly re-defines certain functions:

$ sudo gem install openssl -- --with-openssl-dir=/opt/local/libexec/openssl11
Fetching openssl-3.1.0.gem
Building native extensions with: '--with-openssl-dir=/opt/local/libexec/openssl11'
This could take a while...
ERROR:  Error installing openssl:
	ERROR: Failed to build gem native extension.

    current directory: /opt/local/lib/ruby3.2/gems/3.2.0/gems/openssl-3.1.0/ext/openssl
/opt/local/bin/ruby3.2 -I /opt/local/lib/ruby3.2/3.2.0 extconf.rb --with-openssl-dir\=/opt/local/libexec/openssl11
checking for rb_io_maybe_wait(0, Qnil, Qnil, Qnil) in ruby/io.h... yes
checking for t_open() in -lnsl... no
checking for socket() in -lsocket... no
checking for openssl/ssl.h... yes
checking for CRYPTO_malloc() in -lcrypto... yes
checking for SSL_new() in -lssl... yes
checking for LIBRESSL_VERSION_NUMBER in openssl/opensslv.h... no
checking for OpenSSL version >= 1.0.2... yes
checking for RAND_egd() in openssl/rand.h... no
checking for ENGINE_load_dynamic() in openssl/engine.h... yes
checking for ENGINE_load_4758cca() in openssl/engine.h... no
checking for ENGINE_load_aep() in openssl/engine.h... no
checking for ENGINE_load_atalla() in openssl/engine.h... no
checking for ENGINE_load_chil() in openssl/engine.h... no
checking for ENGINE_load_cswift() in openssl/engine.h... no
checking for ENGINE_load_nuron() in openssl/engine.h... no
checking for ENGINE_load_sureware() in openssl/engine.h... no
checking for ENGINE_load_ubsec() in openssl/engine.h... no
checking for ENGINE_load_padlock() in openssl/engine.h... no
checking for ENGINE_load_capi() in openssl/engine.h... no
checking for ENGINE_load_gmp() in openssl/engine.h... no
checking for ENGINE_load_gost() in openssl/engine.h... no
checking for ENGINE_load_cryptodev() in openssl/engine.h... yes
checking for SSL.ctx in openssl/ssl.h... no
checking for EVP_MD_CTX_new() in openssl/evp.h... yes
checking for EVP_MD_CTX_free(NULL) in openssl/evp.h... yes
checking for EVP_MD_CTX_pkey_ctx(NULL) in openssl/evp.h... no
checking for X509_STORE_get_ex_data(NULL, 0) in openssl/x509.h... yes
checking for X509_STORE_set_ex_data(NULL, 0, NULL) in openssl/x509.h... yes
checking for X509_STORE_get_ex_new_index(0, NULL, NULL, NULL, NULL) in openssl/x509.h... yes
checking for X509_CRL_get0_signature(NULL, NULL, NULL) in openssl/x509.h... yes
checking for X509_REQ_get0_signature(NULL, NULL, NULL) in openssl/x509.h... yes
checking for X509_REVOKED_get0_serialNumber(NULL) in openssl/x509.h... yes
checking for X509_REVOKED_get0_revocationDate(NULL) in openssl/x509.h... yes
checking for X509_get0_tbs_sigalg(NULL) in openssl/x509.h... yes
checking for X509_STORE_CTX_get0_untrusted(NULL) in openssl/x509.h... yes
checking for X509_STORE_CTX_get0_cert(NULL) in openssl/x509.h... yes
checking for X509_STORE_CTX_get0_chain(NULL) in openssl/x509.h... yes
checking for OCSP_SINGLERESP_get0_id(NULL) in openssl/ocsp.h... yes
checking for SSL_CTX_get_ciphers(NULL) in openssl/ssl.h... yes
checking for X509_up_ref(NULL) in openssl/x509.h... yes
checking for X509_CRL_up_ref(NULL) in openssl/x509.h... yes
checking for X509_STORE_up_ref(NULL) in openssl/x509.h... yes
checking for SSL_SESSION_up_ref(NULL) in openssl/ssl.h... yes
checking for EVP_PKEY_up_ref(NULL) in openssl/evp.h... yes
checking for SSL_CTX_set_min_proto_version(NULL, 0) in openssl/ssl.h... yes
checking for SSL_CTX_get_security_level(NULL) in openssl/ssl.h... yes
checking for X509_get0_notBefore(NULL) in openssl/x509.h... yes
checking for SSL_SESSION_get_protocol_version(NULL) in openssl/ssl.h... yes
checking for TS_STATUS_INFO_get0_status(NULL) in openssl/ts.h... yes
checking for TS_STATUS_INFO_get0_text(NULL) in openssl/ts.h... yes
checking for TS_STATUS_INFO_get0_failure_info(NULL) in openssl/ts.h... yes
checking for TS_VERIFY_CTS_set_certs(NULL, NULL) in openssl/ts.h... no
checking for TS_VERIFY_CTX_set_store(NULL, NULL) in openssl/ts.h... yes
checking for TS_VERIFY_CTX_add_flags(NULL, 0) in openssl/ts.h... yes
checking for TS_RESP_CTX_set_time_cb(NULL, NULL, NULL) in openssl/ts.h... yes
checking for EVP_PBE_scrypt("", 0, (unsigned char *)"", 0, 0, 0, 0, 0, NULL, 0) in openssl/evp.h... yes
checking for SSL_CTX_set_post_handshake_auth(NULL, 0) in openssl/ssl.h... yes
checking for EVP_PKEY_check(NULL) in openssl/evp.h... yes
checking for EVP_PKEY_new_raw_private_key(0, NULL, (unsigned char *)"", 0) in openssl/evp.h... yes
checking for SSL_CTX_set_ciphersuites(NULL, "") in openssl/ssl.h... yes
checking for SSL_set0_tmp_dh_pkey(NULL, NULL) in openssl/ssl.h... no
checking for ERR_get_error_all(NULL, NULL, NULL, NULL, NULL) in openssl/err.h... no
checking for TS_VERIFY_CTX_set_certs(NULL, NULL) in openssl/ts.h... no
checking for SSL_CTX_load_verify_file(NULL, "") in openssl/ssl.h... no
checking for BN_check_prime(NULL, NULL, NULL) in openssl/bn.h... no
checking for EVP_MD_CTX_get0_md(NULL) in openssl/evp.h... no
checking for EVP_MD_CTX_get_pkey_ctx(NULL) in openssl/evp.h... no
checking for EVP_PKEY_eq(NULL, NULL) in openssl/evp.h... no
checking for EVP_PKEY_dup(NULL) in openssl/evp.h... no
creating extconf.h
creating Makefile

current directory: /opt/local/lib/ruby3.2/gems/3.2.0/gems/openssl-3.1.0/ext/openssl
make DESTDIR\= sitearchdir\=./.gem.20230103-46694-yflkd8 sitelibdir\=./.gem.20230103-46694-yflkd8 clean

current directory: /opt/local/lib/ruby3.2/gems/3.2.0/gems/openssl-3.1.0/ext/openssl
make DESTDIR\= sitearchdir\=./.gem.20230103-46694-yflkd8 sitelibdir\=./.gem.20230103-46694-yflkd8
compiling openssl_missing.c
compiling ossl.c
compiling ossl_asn1.c
compiling ossl_bio.c
compiling ossl_bn.c
compiling ossl_cipher.c
compiling ossl_config.c
compiling ossl_digest.c
compiling ossl_engine.c
compiling ossl_hmac.c
ossl_hmac.c:249:35: error: incomplete definition of type 'struct evp_md_ctx_st'
    pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_get_pkey_ctx(ctx));
                                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
./openssl_missing.h:230:41: note: expanded from macro 'EVP_MD_CTX_get_pkey_ctx'
#  define EVP_MD_CTX_get_pkey_ctx(x) (x)->pctx
                                     ~~~^
/opt/local/libexec/openssl11/include/openssl/ossl_typ.h:92:16: note: forward declaration of 'struct evp_md_ctx_st'
typedef struct evp_md_ctx_st EVP_MD_CTX;
               ^
1 error generated.
make: *** [ossl_hmac.o] Error 1

make failed, exit code 2

Gem files will remain installed in /opt/local/lib/ruby3.2/gems/3.2.0/gems/openssl-3.1.0 for inspection.
Results logged to /opt/local/lib/ruby3.2/gems/3.2.0/extensions/x86_64-darwin-21/3.2.0/openssl-3.1.0/gem_make.out

Attempts to edit the offending file locally and recompile succeed - but the gem cannot be installed:

$ sudo gem spec ../../cache/openssl-3.1.0.gem --ruby > /tmp/openssl.gemspec
[/opt/local/lib/ruby3.2/gems/3.2.0/specifications/openssl-3.1.0.gemspec] isn't a Gem::Specification (NilClass instead).
$ sudo cp !!:$ ../../cache/openssl-3.1.0.gem 
sudo cp /tmp/openssl.gemspec ../../cache/openssl-3.1.0.gem 
$ sync
$ gem list openssl
[/opt/local/lib/ruby3.2/gems/3.2.0/specifications/openssl-3.1.0.gemspec] isn't a Gem::Specification (NilClass instead).

*** LOCAL GEMS ***

[/opt/local/lib/ruby3.2/gems/3.2.0/specifications/openssl-3.1.0.gemspec] isn't a Gem::Specification (NilClass instead).
openssl (default: 3.1.0)
$ 

openssl-3.0.1 gem installs fine.

@rhenium
Copy link
Member

rhenium commented Jan 3, 2023

checking for EVP_MD_CTX_pkey_ctx(NULL) in openssl/evp.h... no

This is strange. EVP_MD_CTX_pkey_ctx() is supposed to exist in OpenSSL 1.1.0 or later. The compile error is because the shim macro for OpenSSL 1.0.2 is wrongly enabled.

Could you attach the generated mkmf.log? I think it should be located in this directory:

Results logged to /opt/local/lib/ruby3.2/gems/3.2.0/extensions/x86_64-darwin-21/3.2.0/openssl-3.1.0/gem_make.out

@mouse07410
Copy link
Author

mouse07410 commented Jan 3, 2023

The compile error is because the shim macro for OpenSSL 1.0.2 is wrongly enabled.

Yes. And it happens with another macro as well (TS_VERIFY_CTS_<something>).

Here are the files. Oh, and it's with Xcode-14.2.

gem_mkmf.log.txt
gem_make.out.txt

@mouse07410
Copy link
Author

@rhenium this is a consistent failure. Help would be appreciated.

@rhenium
Copy link
Member

rhenium commented Jan 21, 2023

# mkmf.log, line 812
have_func: checking for EVP_MD_CTX_pkey_ctx(NULL) in openssl/evp.h... -------------------- no

DYLD_FALLBACK_LIBRARY_PATH=.:/opt/local/lib "/usr/bin/clang -o conftest [...] \
\
-I/opt/local/include/ruby-3.2.0/x86_64-darwin21 \
-I/opt/local/include/ruby-3.2.0/ruby/backward \
-I/opt/local/include/ruby-3.2.0 \
-I. \
-I/opt/local/libexec/openssl11//include \
-I/opt/local/libexec/openssl3/include \
[...] \
-L. \
-L/opt/local/lib \
-L/opt/local/libexec/openssl11//lib \
-L/opt/local/lib \
-L. \
-L/opt/local/libexec/openssl3/lib \
-L/opt/local/lib \
\
[...]"
Undefined symbols for architecture x86_64:
  "_EVP_MD_CTX_pkey_ctx", referenced from:
      _t in conftest-5f8259.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Do you have libcrypto*.dylib in /opt/local/lib? #545 looks similar.

According to this log output, conftest.c correctly found the 1.1.1 headers in /opt/local/libexec/openssl11//include, but then was linked against a wrong OpenSSL library in /opt/local/lib (presumably a 3.0.x, in which EVP_MD_CTX_pkey_ctx() is a macro as opposed to a function in 1.1.x).

This may be https://bugs.ruby-lang.org/issues/9760: --with-openssl-dir doesn't work correctly if (1) Ruby is compiled with --enable-shared and (2) an OpenSSL is installed with the same prefix as Ruby. In this case, I don't know a workaround except for installing Ruby outside MacPorts.

also have OpenSSL-3.0.7, but it fails to build extension exactly the same way

However I'm not sure why it would fail with OpenSSL 3.0.7, too (without specifying --with-openssl-dir?).

@mouse07410
Copy link
Author

Do you have libcrypto*.dylib in /opt/local/lib?

$ ll /opt/local/lib/libcrypto*.dylib
lrwxr-xr-x  1 root  admin  49 Dec 11 02:38 /opt/local/lib/libcrypto.3.dylib@ -> /opt/local/libexec/openssl3/lib/libcrypto.3.dylib
lrwxr-xr-x  1 root  admin  17 Dec 11 02:38 /opt/local/lib/libcrypto.dylib@ -> libcrypto.3.dylib
$ 

This may be https://bugs.ruby-lang.org/issues/9760: --with-openssl-dir doesn't work correctly if (1) Ruby is compiled with --enable-shared and (2) an OpenSSL is installed with the same prefix as Ruby. In this case, I don't know a workaround except for installing Ruby outside MacPorts.

Re. (1): I don't know.

$ port installed ruby32
The following ports are currently installed:
  ruby32 @3.2.0_0+gmp+relative+yjit (active)

I do not know about (1).
(2) definitely applies, as both OpenSSL and Ruby have been installed by/with Macports, into /opt/local/.

However I'm not sure why it would fail with OpenSSL 3.0.7, too (without specifying --with-openssl-dir?).

Good question. Another good question would be - why, given that OpenSSL 3.0.7 is installed symlinked to /opt/local (aka, /opt/local/include/openssl/ and /opt/local/lib/libcrypto.dylib), it would still manage to find and (partially) use OpenSSL-1.1.1 in /opt/local/libexec/openssl11...

@mouse07410
Copy link
Author

It looks like sudo gem update openssl -- --with-openssl-dir=/opt/local/libexec/openssl3 did the job of updating the openssl extension to 3.1.0.

How can I test to make sure the correct/latest gem and extension are installed and set to default?

@ziaulrehman40
Copy link

Any updates here?

@gregogalante
Copy link

Same problem here

@jskinne3
Copy link

jskinne3 commented Mar 16, 2024

I noticed a quirk that may shed light on the problem. My copy of Ruby believes itself to be using OpenSSL version 1.1, but the compilation of the gem is trying version 3 of OpenSSL. Might this version mismatch explain the incorrect version shim macro that @rhenium pointed out?

Below is my error when compiling the gem per the instructions on the CONTRIBUTING page. Notice that the output contains references to openssl@3in the errors about redefining the TS_VERIFY_CTS and EVP_MD_CTX macros:

$ bundle exec rake compile
/Users/johnsskinner/.rvm/rubies/ruby-3.0.4/bin/ruby -v
ruby 3.0.4p208 (2022-04-12 revision 3fa771dded) [x86_64-darwin20]
Compiler: gcc -fdeclspec
cd tmp/x86_64-darwin20/openssl/3.0.4
/usr/bin/make
compiling ../../../../ext/openssl/ossl_hmac.c
In file included from ../../../../ext/openssl/ossl_hmac.c:10:
In file included from ../../../../ext/openssl/ossl.h:175:
../../../../ext/openssl/openssl_missing.h:195:11: warning: 'TS_VERIFY_CTS_set_certs' macro redefined [-Wmacro-redefined]
#  define TS_VERIFY_CTS_set_certs(ctx, crts) ((ctx)->certs=(crts))
          ^
/usr/local/Cellar/openssl@3/3.2.1/include/openssl/ts.h:426:11: note: previous definition is here
#  define TS_VERIFY_CTS_set_certs(ctx, cert) TS_VERIFY_CTX_set_certs(ctx,cert)
          ^
../../../../ext/openssl/ossl_hmac.c:249:35: error: incomplete definition of type 'struct evp_md_ctx_st'
    pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_get_pkey_ctx(ctx));
                                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../../../ext/openssl/openssl_missing.h:230:41: note: expanded from macro 'EVP_MD_CTX_get_pkey_ctx'
#  define EVP_MD_CTX_get_pkey_ctx(x) (x)->pctx
                                     ~~~^
/usr/local/Cellar/openssl@3/3.2.1/include/openssl/types.h:107:16: note: forward declaration of 'struct evp_md_ctx_st'
typedef struct evp_md_ctx_st EVP_MD_CTX;
               ^
1 warning and 1 error generated.
make: *** [ossl_hmac.o] Error 1
rake aborted!
Command failed with status (2): [/usr/bin/make]
/Users/johnsskinner/Projects/openssl/vendor/ruby/3.0.0/gems/rake-compiler-1.2.7/lib/rake/extensiontask.rb:195:in `block (2 levels) in define_compile_tasks'
/Users/johnsskinner/Projects/openssl/vendor/ruby/3.0.0/gems/rake-compiler-1.2.7/lib/rake/extensiontask.rb:194:in `block in define_compile_tasks'
/Users/johnsskinner/Projects/openssl/vendor/ruby/3.0.0/gems/rake-13.1.0/exe/rake:27:in `<top (required)>'
/Users/johnsskinner/.rvm/gems/ruby-3.0.4/bin/ruby_executable_hooks:22:in `eval'
/Users/johnsskinner/.rvm/gems/ruby-3.0.4/bin/ruby_executable_hooks:22:in `<main>'
Tasks: TOP => compile => compile:x86_64-darwin20 => compile:openssl:x86_64-darwin20 => copy:openssl:x86_64-darwin20:3.0.4 => tmp/x86_64-darwin20/openssl/3.0.4/openssl.bundle
(See full trace by running task with --trace)

This output agrees with the version that the openssl command itself thinks it is using:

$ openssl version
OpenSSL 3.2.1 30 Jan 2024 (Library: OpenSSL 3.2.1 30 Jan 2024)

But, this differs from the version my installation of Ruby thinks it is using. Ruby believes it is on version 1.1 of OpenSSL:

$ ruby -ropenssl -e 'puts OpenSSL::OPENSSL_VERSION'
OpenSSL 1.1.1q  5 Jul 2022
$ ruby -ropenssl -e 'puts OpenSSL::OPENSSL_LIBRARY_VERSION'
OpenSSL 1.1.1w  11 Sep 2023

Indeed, I thought that Ruby did not support OpenSSL 3 until Ruby version 3.1 or later. I am using Ruby 3.0.4 in this example. So, it seems very wrong to me that my compilation of the openssl gem should create output related to version 3 of OpenSSL which my version of Ruby does not support.

Is this configuration somehow jammed between versions of OpenSSL? Perhaps the code is querying the OpenSSL version in two different ways, returning two different results, which is then executing two incompatible parts of the code?

In this issue, @BrianHawley believes configuration and compilation are picking two different versions when both the openssl@1.1 and openssl@3 formulas are installed.

Setup: I am on an Intel Macbook, Sonoma 14.4, using Homebrew and Ruby 3.0.4p208 installed with RVM.

@madleech
Copy link

I was able to manually install using:

gem install openssl -- --with-openssl-dir=$(brew --prefix openssl@3)

Then I could bundle install as normal.

@lmammino
Copy link

With rvm:

rvm install "ruby-3.3.0" -- --with-openssl-dir=/opt/homebrew/opt/openssl@3

Seems to have made the trick for me...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

7 participants