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

Installing hiredis-client on macos with M1 fails #58

Closed
dup2 opened this issue Nov 1, 2022 · 56 comments · Fixed by #59
Closed

Installing hiredis-client on macos with M1 fails #58

dup2 opened this issue Nov 1, 2022 · 56 comments · Fixed by #59

Comments

@dup2
Copy link

dup2 commented Nov 1, 2022

Trying to install this as part of a bundle fails

Ruby: ruby 2.7.5p203 (2021-11-24 revision f69aeb8314) [arm64-darwin21]
OS: macos 12.6.1 / Apple M1 Pro

...
Using hashery 2.1.2
Using hirb 0.7.3
Fetching hiredis-client 0.10.0
Installing hiredis-client 0.10.0 with native extensions
Gem::Ext::BuildError: ERROR: Failed to build gem native extension.
...

checking for rb_hash_new_capa() in ruby.h... no
cc -std=c99 -pedantic -c -O3 -fPIC  "-I/opt/homebrew/opt/openssl@1.1/include" -Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers -g -ggdb alloc.c
cc -std=c99 -pedantic -c -O3 -fPIC  "-I/opt/homebrew/opt/openssl@1.1/include" -Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers -g -ggdb net.c
cc -std=c99 -pedantic -c -O3 -fPIC  "-I/opt/homebrew/opt/openssl@1.1/include" -Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers -g -ggdb hiredis.c
cc -std=c99 -pedantic -c -O3 -fPIC  "-I/opt/homebrew/opt/openssl@1.1/include" -Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers -g -ggdb sds.c
cc -std=c99 -pedantic -c -O3 -fPIC  "-I/opt/homebrew/opt/openssl@1.1/include" -Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers -g -ggdb async.c
cc -std=c99 -pedantic -c -O3 -fPIC  "-I/opt/homebrew/opt/openssl@1.1/include" -Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers -g -ggdb read.c
cc -std=c99 -pedantic -c -O3 -fPIC  "-I/opt/homebrew/opt/openssl@1.1/include" -Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers -g -ggdb sockcompat.c
ar rcs libhiredis.a alloc.o net.o hiredis.o sds.o async.o read.o sockcompat.o
cc -std=c99 -pedantic -c -O3 -fPIC  "-I/opt/homebrew/opt/openssl@1.1/include" -Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers -g -ggdb ssl.c
ar rcs libhiredis_ssl.a ssl.o
creating Makefile
..
make "DESTDIR="
compiling hiredis_connection.c
linking shared-object redis_client/hiredis_connection.bundle
Undefined symbols for architecture arm64:
  "_ruby_abi_version", referenced from:
     -exported_symbol[s_list] command line option
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [hiredis_connection.bundle] Error 1

make failed, exit code 2

..

An error occurred while installing hiredis-client (0.10.0), and Bundler cannot continue.
Make sure that `gem install hiredis-client -v '0.10.0' --source 'https://rubygems.org/'` succeeds before bundling.
@casperisfine
Copy link
Collaborator

Hum, works fine on my machine:

$ ruby -v
ruby 2.7.5p203 (2021-11-24 revision f69aeb8314) [arm64-darwin21]

$ gem install hiredis-client -v 0.10.0
Fetching redis-client-0.10.0.gem
Fetching hiredis-client-0.10.0.gem
Successfully installed redis-client-0.10.0
Building native extensions. This could take a while...
Successfully installed hiredis-client-0.10.0
Parsing documentation for redis-client-0.10.0
Installing ri documentation for redis-client-0.10.0
Parsing documentation for hiredis-client-0.10.0
Installing ri documentation for hiredis-client-0.10.0
Done installing documentation for redis-client, hiredis-client after 1 seconds
2 gems installed

What does RbConfig::CONFIG['CC'] look like on your machine?

@dup2
Copy link
Author

dup2 commented Nov 1, 2022

Thanks for the feedback.

What does RbConfig::CONFIG['CC'] look like on your machine?

Just tried with 2.7.6:

$ ruby -v
ruby 2.7.6p219 (2022-04-12 revision c9c2245c0a) [arm64-darwin21]

$ ruby -e "puts RbConfig::CONFIG['CC']"
gcc

I get the same error when building as with ruby 2.7.5.

When I use the x86_64-darwin21 architecture, it works..

@casperisfine
Copy link
Collaborator

Hum, that's interesting, I'll try to reproduce.

What you pasted suggest your ruby was built with gcc, even though you are on macOS.

How did you build that ruby and did you brew install gcc or something? Asking to see if I can find a way to reproduce on my machine (I'm also on M1).

Also could you run cc --version and show me the output? Thank you!

@arianf
Copy link

arianf commented Nov 1, 2022

I'm seeing the same issue:

$ gem install hiredis-client -v 0.11.0 -- --with-openssl-dir=/opt/homebrew/opt/openssl@3
Building native extensions with: '--with-openssl-dir=/opt/homebrew/opt/openssl@3'
This could take a while...
ERROR:  Error installing hiredis-client:
  ERROR: Failed to build gem native extension.

    current directory: /Users/arian/.rvm/gems/ruby-3.1.2@my-app/gems/hiredis-client-0.11.0/ext/redis_client/hiredis
/Users/arian/.rvm/rubies/ruby-3.1.2/bin/ruby -I /Users/arian/.rvm/rubies/ruby-3.1.2/lib/ruby/3.1.0 -r ./siteconf20221101-81291-r5ixvl.rb extconf.rb --with-openssl-dir\=/opt/homebrew/opt/openssl@3
checking for rb_hash_new_capa() in ruby.h... no
cc -std=c99 -pedantic -c -O3 -fPIC  "-I/opt/homebrew/opt/openssl@3/include" -Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers -g -ggdb alloc.c
cc -std=c99 -pedantic -c -O3 -fPIC  "-I/opt/homebrew/opt/openssl@3/include" -Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers -g -ggdb net.c
cc -std=c99 -pedantic -c -O3 -fPIC  "-I/opt/homebrew/opt/openssl@3/include" -Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers -g -ggdb hiredis.c
cc -std=c99 -pedantic -c -O3 -fPIC  "-I/opt/homebrew/opt/openssl@3/include" -Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers -g -ggdb sds.c
cc -std=c99 -pedantic -c -O3 -fPIC  "-I/opt/homebrew/opt/openssl@3/include" -Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers -g -ggdb async.c
cc -std=c99 -pedantic -c -O3 -fPIC  "-I/opt/homebrew/opt/openssl@3/include" -Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers -g -ggdb read.c
cc -std=c99 -pedantic -c -O3 -fPIC  "-I/opt/homebrew/opt/openssl@3/include" -Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers -g -ggdb sockcompat.c
ar rcs libhiredis.a alloc.o net.o hiredis.o sds.o async.o read.o sockcompat.o
cc -std=c99 -pedantic -c -O3 -fPIC  "-I/opt/homebrew/opt/openssl@3/include" -Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers -g -ggdb ssl.c
ar rcs libhiredis_ssl.a ssl.o
creating Makefile

current directory: /Users/arian/.rvm/gems/ruby-3.1.2@my-app/gems/hiredis-client-0.11.0/ext/redis_client/hiredis
make DESTDIR\= clean

current directory: /Users/arian/.rvm/gems/ruby-3.1.2@my-app/gems/hiredis-client-0.11.0/ext/redis_client/hiredis
make DESTDIR\=
compiling hiredis_connection.c
linking shared-object redis_client/hiredis_connection.bundle
Undefined symbols for architecture arm64:
  "_ruby_abi_version", referenced from:
     -exported_symbol[s_list] command line option
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [hiredis_connection.bundle] Error 1

make failed, exit code 2

Gem files will remain installed in /Users/arian/.rvm/gems/ruby-3.1.2@my-app/gems/hiredis-client-0.11.0 for inspection.
Results logged to /Users/arian/.rvm/gems/ruby-3.1.2@my-app/extensions/arm64-darwin-22/3.1.0/hiredis-client-0.11.0/gem_make.out
$ ruby -e "puts RbConfig::CONFIG['CC']"
gcc

@byroot
Copy link
Member

byroot commented Nov 1, 2022

@arianf thanks for the report, can you run cc --version and post the output?

@arianf
Copy link

arianf commented Nov 1, 2022

$ cc --version                                                                             
Apple clang version 14.0.0 (clang-1400.0.29.201)
Target: arm64-apple-darwin22.2.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

@byroot
Copy link
Member

byroot commented Nov 1, 2022

Oh that's a weird one, even macOS 13 (Ventura) is supposed to ship with clang 13 and somehow you have clang 14.

I'll try to see if that's what cause the issue, not sure how I can upgrade though.

@arianf
Copy link

arianf commented Nov 1, 2022

See an similar issue here: grpc/grpc#30976

@byroot
Copy link
Member

byroot commented Nov 1, 2022

Yeah I know, @peterzhu2118 pointed the same GRPC error to me. I suppose we now know that clang-14 is the trigger. Now the question is how to fix it.

@stanhu
Copy link
Contributor

stanhu commented Nov 1, 2022

I'm not able to reproduce this issue on Xcode 14 either.

There is an upstream Ruby bug report about this, though: https://bugs.ruby-lang.org/issues/19005

@byroot
Copy link
Member

byroot commented Nov 1, 2022

Thank you very much @stanhu. If I understood that ticket correctly, ruby interpreters compiled with Xcode 14 have some missing flags in RbConfig::CONFIG['DLDFLAGS'], so we could probably work around this by adding them back?

@dup2 / @arianf I'd appreciate if you could share the value of p RbConfig::CONFIG['DLDFLAGS'] on your rubies, just do confirm dynamic_lookup is missing.

I'll try to repro and provide a fix tomorrow.

@stanhu
Copy link
Contributor

stanhu commented Nov 1, 2022

Oh, I forgot I had my compiler set with -Wl,-undefined,dynamic_lookup.

When I used Ruby 3.1.2 without those flags, it fails on XCode 14.

irb(main):001:0> RbConfig::CONFIG['DLDFLAGS']
=> "-L/Users/stanhu/.asdf/installs/ruby/3.1.2/lib  -Wl,-multiply_defined,suppress"

@arianf
Copy link

arianf commented Nov 1, 2022

Upgrading from Ruby 3.1.2 to Ruby 3.2.0-preview2 fixes it for me

gem install hiredis-client -v 0.11.0 -- --with-openssl-dir=/opt/homebrew/opt/openssl@3
Building native extensions with: '--with-openssl-dir=/opt/homebrew/opt/openssl@3'
This could take a while...
Successfully installed hiredis-client-0.11.0
Parsing documentation for hiredis-client-0.11.0
Installing ri documentation for hiredis-client-0.11.0
Done installing documentation for hiredis-client after 0 seconds
1 gem installed

@stanhu
Copy link
Contributor

stanhu commented Nov 1, 2022

Thank you very much @stanhu. If I understood that ticket correctly, ruby interpreters compiled with Xcode 14 have some missing flags in RbConfig::CONFIG['DLDFLAGS'], so we could probably work around this by adding them back?

Yes, that's a workaround, but I believe gems should be able to be compiled without those flags, though that's not a commonly-tested path.

Examples of other fixes:

  1. Drop Init_pg_query from exported symbol map pganalyze/pg_query#256 (this one seems quite similar here)
  2. Fix broken compilation with Ruby interpreter compiled with XCode 14 chef/ffi-yajl#114

@arianf
Copy link

arianf commented Nov 1, 2022

I'd appreciate if you could share the value of p RbConfig::CONFIG['DLDFLAGS'] on your rubies, just do confirm dynamic_lookup is missing.

Ruby 3.2.0-preview2 (hiredis-client installs successfully):

3.2.0-preview2 :001 > p RbConfig::CONFIG['DLDFLAGS']
"-Wl,-undefined,dynamic_lookup -Wl,-multiply_defined,suppress"

Ruby 3.1.2 (hiredis-client does not install):

3.1.2 :001 > p RbConfig::CONFIG['DLDFLAGS']
"-L/opt/homebrew/opt/libyaml/lib -L/opt/homebrew/opt/libksba/lib -L/opt/homebrew/opt/readline/lib -L/opt/homebrew/opt/zlib/lib -L/opt/homebrew/opt/openssl@1.1/lib -Wl,-multiply_defined,suppress"

Ruby 3.0.4 (hiredis-client does not install):

3.0.4 :001 > p RbConfig::CONFIG['DLDFLAGS']
"-L/opt/homebrew/opt/libyaml/lib -L/opt/homebrew/opt/libksba/lib -L/opt/homebrew/opt/readline/lib -L/opt/homebrew/opt/zlib/lib -L/opt/homebrew/opt/openssl@1.1/lib -Wl,-multiply_defined,suppress"

@stanhu
Copy link
Contributor

stanhu commented Nov 1, 2022

Dropping this line fixed the compilation issue for me:

diff --git a/hiredis-client/ext/redis_client/hiredis/export.clang b/hiredis-client/ext/redis_client/hiredis/export.clang
index 10065f7..883acc2 100644
--- a/hiredis-client/ext/redis_client/hiredis/export.clang
+++ b/hiredis-client/ext/redis_client/hiredis/export.clang
@@ -1,2 +1 @@
 _Init_hiredis_connection
-_ruby_abi_version

@byroot
Copy link
Member

byroot commented Nov 1, 2022

Dropping this line fixed the compilation issue for me:

Yeah, because it doesn't exist on 3.1 and older, but then that will break on 3.2.0 when this field will need to be exported. @peterzhu2118 can correct me if I'm wrong on that one.

@stanhu
Copy link
Contributor

stanhu commented Nov 1, 2022

I wonder if another option is to ignore the missing symbol via:

diff --git a/hiredis-client/ext/redis_client/hiredis/extconf.rb b/hiredis-client/ext/redis_client/hiredis/extconf.rb
index 39204c3..a7c13c1 100644
--- a/hiredis-client/ext/redis_client/hiredis/extconf.rb
+++ b/hiredis-client/ext/redis_client/hiredis/extconf.rb
@@ -45,6 +45,7 @@ if RUBY_ENGINE == "ruby" && !RUBY_PLATFORM.match?(/mswin/)
 
   $CFLAGS << " -I#{hiredis_dir}"
   $LDFLAGS << " -lssl -lcrypto"
+  $DLDFLAGS << " -Wl,-U,_ruby_abi_version"
   $libs << " #{hiredis_dir}/libhiredis.a #{hiredis_dir}/libhiredis_ssl.a "
   $CFLAGS << " -std=c99 "
   if ENV["EXT_PEDANTIC"]

@peterzhu2118
Copy link
Contributor

Yeah, this export is required for Ruby 3.2 compatibility.

I wonder if this is a regression in xcode 14.1 beta. I remember being able to repro this issue in gRPC but I'm now unable to. Looking at @arianf's output, it seems like you're on xcode 14.1 beta 3, whereas I'm on the release version of xcode 14.1 (released today, Nov 1 2022) with a newer build of clang:

$ cc --version
Apple clang version 14.0.0 (clang-1400.0.29.202)
Target: arm64-apple-darwin22.1.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

I will try to downgrade to xcode 14.1 beta 3 tomorrow and see if I can repro this issue again.

@stanhu
Copy link
Contributor

stanhu commented Nov 1, 2022

I wonder if this is a regression in xcode 14.1 beta.

As I mentioned in the Ruby bug report, XCode 14.0 now warns with the message when -Wl,undefined,dynamic_lookup is used:

% gcc -o test -Wl,-undefined,dynamic_lookup test.c
ld: warning: -undefined dynamic_lookup may not work with chained fixups

This warning was enough to make the Ruby configure script believe that those flags were no longer available on the system. -Wl,undefined,dynamic_lookup has long been the default everywhere, and most gems were not tested without those flags.

I believe the patches in https://github.com/ruby/ruby/pull/6441/files fix the configure script in Ruby to enable this linker option despite the warning message, which is why the latest 3.2.0 preview release works fine.

@dup2
Copy link
Author

dup2 commented Nov 1, 2022

Thanks for your quick reaction, lads - much appreciated!

@dup2 / @arianf I'd appreciate if you could share the value of p RbConfig::CONFIG['DLDFLAGS'] on your rubies, just do confirm dynamic_lookup is missing.

$ ruby --version
ruby 2.7.6p219 (2022-04-12 revision c9c2245c0a) [arm64-darwin21]

$ ruby -e "p RbConfig::CONFIG['DLDFLAGS']"
"-Wl,-multiply_defined,suppress -L/opt/homebrew/opt/libyaml/lib -L/opt/homebrew/opt/libksba/lib -L/opt/homebrew/opt/readline/lib -L/opt/homebrew/opt/zlib/lib -L/opt/homebrew/opt/openssl@1.1/lib"

$ cc --version
Apple clang version 14.0.0 (clang-1400.0.29.102)
Target: arm64-apple-darwin21.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

casperisfine pushed a commit that referenced this issue Nov 2, 2022
Fix: #58
Ref: https://bugs.ruby-lang.org/issues/19005

Rubies compiled with Xcode 14 are missing some flags in LDFLAGS
which cause the hiredis gem to fail to compile.

We work around this by adding the flags back if we detect this bug.
@casperisfine
Copy link
Collaborator

Ok, so I made a PR with what I think is a decent workaround: #59

I'd appreciate if someone who experience this bug could give that branch a try to confirm the workaround doesn't only work on my machine.

gem "hiredis-client", github: "redis-rb/redis-client"

Also I'm far from a linker and compiler expert, so if you believe that is a better way to handle this, I'm all ears.

@dup2
Copy link
Author

dup2 commented Nov 2, 2022

Ok, so I made a PR with what I think is a decent workaround: #59

Thanks!

Unfortunately, this does not work for me. Most likely because the check for RbConfig::CONFIG['CC'] does not match as it is set to gcc on my installation.

casperisfine pushed a commit that referenced this issue Nov 2, 2022
Fix: #58
Ref: https://bugs.ruby-lang.org/issues/19005

Rubies compiled with Xcode 14 are missing some flags in LDFLAGS
which cause the hiredis gem to fail to compile.

We work around this by adding the flags back if we detect this bug.
@casperisfine
Copy link
Collaborator

Thank you @dup2. I modified my PR a bit more to try to account for this. Could you try again?

@dup2
Copy link
Author

dup2 commented Nov 2, 2022

Thank you @dup2. I modified my PR a bit more to try to account for this. Could you try again?

Thanks @casperisfine - I get another error now:

/Users/ok/.rvm/rubies/ruby-2.7.6/lib/ruby/2.7.0/arm64-darwin21/rbconfig.rb:302:in `replace': can't modify frozen String: "$(CC) --version" (FrozenError)

Please note also that the reference in the Gemfile had to be like this to test the commit in the linked PR #59 :

gem "hiredis-client", github: "redis-rb/redis-client", ref: "5fdf0a53141e56d19cb3df2069dd827ae66d5961"

otherwise just the master branch would have been used..

@casperisfine
Copy link
Collaborator

Hum, interesting, IMO that's a bug in RbConfig, I'll fix it upstream. In the meantime we can dup that string.

I pushed another commit.

And yes indeed I forgot to add the branch: in the Gemfile extract, sorry :/

@eregon
Copy link
Contributor

eregon commented Dec 30, 2022

Is there a reason to use a symbol list (like #58 (comment)) in this gem? Dropping that list would be the most future-proof solution and easiest to maintain.
EDIT: the reason for the stripping is #17 / #16.

The symbol list will also make the gem not build on TruffleRuby for instance which uses a different symbol (which predates rb_abi_version).

@eregon
Copy link
Contributor

eregon commented Dec 30, 2022

FYI I've filed https://bugs.ruby-lang.org/issues/19289 on the Ruby side to see how we could improve things related to rb_abi_version.

@byroot
Copy link
Member

byroot commented Dec 30, 2022

Is there a reason to use a symbol list (like #58 (comment)) in this gem?

Yes, it's to allow both hiredis-client and hiredis to be loaded in the same process: #17 / #16.

I wish I didn't have to do this, but the two gems might need to co-exist for a while.

If you know of a better way to fix that root cause I'd be happy to switch, otherwise, I might remove that hack in a year or so when I can expect most people will have migrated out of the hiredis / redis 4.x gems.

@miry
Copy link

miry commented Jan 10, 2023

The same error exists for x86_64-darwin-22 with ruby 3.2.0

Undefined symbols for architecture x86_64:
  "_ruby_abi_version", referenced from:
     -exported_symbol[s_list] command line option
ld: symbol(s) not found for architecture x86_64

Update to version 0.12.0 fixed the problem.

@byroot
Copy link
Member

byroot commented Jan 10, 2023

Yes, the issue was never specific to M1.

@nobu
Copy link

nobu commented Jan 19, 2023

I think the simplest check would be to use the RUBY_PATCHLEVEL constant. It's -1 on development versions and >= 0 on released versions.

have_func("ruby_abi_version()") would suffice.

@byroot
Copy link
Member

byroot commented Jan 19, 2023

have_func("ruby_abi_version()") would suffice.

🤦 that makes so much sense...

@eregon
Copy link
Contributor

eregon commented Jan 19, 2023

Damn, somehow I also didn't think about that, but it's definitely cleaner than checking the version and patchlevel.
It assumes ruby_abi_version is a function and not a global variable, hopefully that doesn't need to change.

@casperisfine
Copy link
Collaborator

Maybe I'm doing something wrong, but it doesn't seem to work:

$ ruby -v
ruby 3.2.0dev (2022-12-12T07:21:31Z master be18b60c33) [arm64-darwin22]
$ bundle exec rake clean compile
mkdir -p tmp/arm64-darwin22/hiredis_connection/3.2.0
cd tmp/arm64-darwin22/hiredis_connection/3.2.0
/opt/rubies/3.2.0/bin/ruby -I. -r.rake-compiler-siteconf.rb ../../../../hiredis-client/ext/redis_client/hiredis/extconf.rb
checking for rb_hash_new_capa() in ruby.h... yes
checking for ruby_abi_version() in ruby.h... no

@eregon
Copy link
Contributor

eregon commented Jan 19, 2023

@casperisfine Could you try without the parens too, i.e., have_func("ruby_abi_version") ?
Or maybe have_func doesn't work for __attribute__((weak)) functions?

@eregon
Copy link
Contributor

eregon commented Jan 19, 2023

As usual the mkmf.log should contain more info about what it tried and what failed.

@casperisfine
Copy link
Collaborator

without parens:

have_func: checking for ruby_abi_version() in ruby.h... -------------------- no

DYLD_FALLBACK_LIBRARY_PATH=.:/opt/rubies/3.2.0/lib "clang -o conftest -I/opt/rubies/3.2.0/include/ruby-3.2.0/arm64-darwin22 -I/opt/rubies/3.2.0/include/ruby-3.2.0/ruby/backward -I/opt/rubies/3.2.0/include/ruby-3.2.0 -I../../../../hiredis-client/ext/redis_client/hiredis -I/opt/rubies/3.2.0/include  -I/opt/homebrew/opt/gmp/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT   -fdeclspec -O3 -fno-fast-math -ggdb3 -Wall -Wextra -Wextra-tokens -Wdeprecated-declarations -Wdivision-by-zero -Wdiv-by-zero -Wimplicit-function-declaration -Wimplicit-int -Wmisleading-indentation -Wpointer-arith -Wshorten-64-to-32 -Wwrite-strings -Wold-style-definition -Wmissing-noreturn -Wno-cast-function-type -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wunused-variable -Wundef  -fno-common -pipe conftest.c  -L. -L/opt/rubies/3.2.0/lib -L. -L/opt/rubies/3.2.0/lib  -fstack-protector-strong -L/opt/homebrew/opt/gmp/lib     -lruby.3.2  -lpthread  "
conftest.c:16:57: error: use of undeclared identifier 'ruby_abi_version'
int t(void) { void ((*volatile p)()); p = (void ((*)()))ruby_abi_version; return !p; }
                                                        ^
1 error generated.
checked program was:
/* begin */
 1: #include "ruby.h"
 2: 
 3: #include <ruby.h>
 4: 
 5: /*top*/
 6: extern int t(void);
 7: int main(int argc, char **argv)
 8: {
 9:   if (argc > 1000000) {
10:     int (* volatile tp)(void)=(int (*)(void))&t;
11:     printf("%d", (*tp)());
12:   }
13: 
14:   return !!argv[argc];
15: }
16: int t(void) { void ((*volatile p)()); p = (void ((*)()))ruby_abi_version; return !p; }
/* end */

with parens:

have_func: checking for ruby_abi_version() in ruby.h... -------------------- no

DYLD_FALLBACK_LIBRARY_PATH=.:/opt/rubies/3.2.0/lib "clang -o conftest -I/opt/rubies/3.2.0/include/ruby-3.2.0/arm64-darwin22 -I/opt/rubies/3.2.0/include/ruby-3.2.0/ruby/backward -I/opt/rubies/3.2.0/include/ruby-3.2.0 -I../../../../hiredis-client/ext/redis_client/hiredis -I/opt/rubies/3.2.0/include  -I/opt/homebrew/opt/gmp/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT   -fdeclspec -O3 -fno-fast-math -ggdb3 -Wall -Wextra -Wextra-tokens -Wdeprecated-declarations -Wdivision-by-zero -Wdiv-by-zero -Wimplicit-function-declaration -Wimplicit-int -Wmisleading-indentation -Wpointer-arith -Wshorten-64-to-32 -Wwrite-strings -Wold-style-definition -Wmissing-noreturn -Wno-cast-function-type -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wunused-variable -Wundef  -fno-common -pipe conftest.c  -L. -L/opt/rubies/3.2.0/lib -L. -L/opt/rubies/3.2.0/lib  -fstack-protector-strong -L/opt/homebrew/opt/gmp/lib     -lruby.3.2  -lpthread  "
conftest.c:17:15: error: implicit declaration of function 'ruby_abi_version' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
int t(void) { ruby_abi_version(); return 0; }
              ^
conftest.c:17:15: note: did you mean 'ruby_show_version'?
/opt/rubies/3.2.0/include/ruby-3.2.0/ruby/internal/interpreter.h:120:6: note: 'ruby_show_version' declared here
void ruby_show_version(void);
     ^
1 error generated.
checked program was:
/* begin */
 1: #include "ruby.h"
 2: 
 3: #include <ruby.h>
 4: 
 5: /*top*/
 6: extern int t(void);
 7: int main(int argc, char **argv)
 8: {
 9:   if (argc > 1000000) {
10:     int (* volatile tp)(void)=(int (*)(void))&t;
11:     printf("%d", (*tp)());
12:   }
13: 
14:   return !!argv[argc];
15: }
16: 
17: int t(void) { ruby_abi_version(); return 0; }
/* end */

--------------------

@casperisfine
Copy link
Collaborator

Hum, wait: /opt/rubies/3.2.0/include

it's looking into my final 3.2.0, not the currently active dev version:

$ which ruby
/opt/rubies/3.2.0-dev-12-13/bin/ruby

@nobu
Copy link

nobu commented Jan 20, 2023

$ which ruby
/opt/rubies/3.2.0-dev-12-13/bin/ruby

Did you configure it with --prefix=/opt/rubies/3.2.0-dev-12-13?

@nobu
Copy link

nobu commented Jan 20, 2023

Rather I recommend decorating Init_hiredis_connection with RUBY_FUNC_EXPORTED and adding -fvisibility=hidden.

@casperisfine
Copy link
Collaborator

@nobu your solution works great, but I tried it and I don't think it works in this case:

$ nm hiredis-client/lib/redis_client/hiredis_connection.bundle 
...
000000000000dab8 T _redisAsyncConnectWithOptions
000000000000e4f4 T _redisAsyncDisconnect
000000000000faf8 T _redisAsyncFormattedCommand
000000000000df08 T _redisAsyncFree
000000000000ed44 T _redisAsyncHandleRead
000000000000f0f8 T _redisAsyncHandleTimeout
000000000000f0a8 T _redisAsyncHandleWrite
000000000000ec40 T _redisAsyncRead
0000000000012460 t _redisAsyncRead.cold.1
...

I think the reason is that we first compile the hiredis library, and then link it:

  $libs << " #{hiredis_dir}/libhiredis.a #{hiredis_dir}/libhiredis_ssl.a "

If I try to compile libhiredis with -fvisibility=hidden too, then It fail to find openssl somehow:

$ bundle exec rake clean compile
mkdir -p tmp/arm64-darwin22/hiredis_connection/3.2.0
cd tmp/arm64-darwin22/hiredis_connection/3.2.0
/opt/rubies/3.2.0/bin/ruby -I. -r.rake-compiler-siteconf.rb ../../../../hiredis-client/ext/redis_client/hiredis/extconf.rb
checking for rb_hash_new_capa() in ruby.h... yes
cc -std=c99 -pedantic -c -O3 -fPIC  "-I/opt/rubies/3.2.0/openssl/include -fvisibility=hidden" -Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers -g -ggdb alloc.c
cc -std=c99 -pedantic -c -O3 -fPIC  "-I/opt/rubies/3.2.0/openssl/include -fvisibility=hidden" -Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers -g -ggdb net.c
cc -std=c99 -pedantic -c -O3 -fPIC  "-I/opt/rubies/3.2.0/openssl/include -fvisibility=hidden" -Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers -g -ggdb hiredis.c
cc -std=c99 -pedantic -c -O3 -fPIC  "-I/opt/rubies/3.2.0/openssl/include -fvisibility=hidden" -Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers -g -ggdb sds.c
cc -std=c99 -pedantic -c -O3 -fPIC  "-I/opt/rubies/3.2.0/openssl/include -fvisibility=hidden" -Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers -g -ggdb async.c
cc -std=c99 -pedantic -c -O3 -fPIC  "-I/opt/rubies/3.2.0/openssl/include -fvisibility=hidden" -Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers -g -ggdb read.c
cc -std=c99 -pedantic -c -O3 -fPIC  "-I/opt/rubies/3.2.0/openssl/include -fvisibility=hidden" -Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers -g -ggdb sockcompat.c
ar rcs libhiredis.a alloc.o net.o hiredis.o sds.o async.o read.o sockcompat.o
cc -std=c99 -pedantic -c -O3 -fPIC  "-I/opt/rubies/3.2.0/openssl/include -fvisibility=hidden" -Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers -g -ggdb ssl.c
ssl.c:45:10: fatal error: 'openssl/ssl.h' file not found
#include <openssl/ssl.h>
         ^~~~~~~~~~~~~~~
1 error generated.
make: *** [ssl.o] Error 1
*** ../../../../hiredis-client/ext/redis_client/hiredis/extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers.  Check the mkmf.log file for more details.  You may
need configuration options.

Not sure if there is a way to fix this, I'm really not good enough with linkers and such to really figure that out. I'd love to make it work that way though, it seems much cleaner and simpler.

@casperisfine
Copy link
Collaborator

Nevermind, I think i figured it out.

casperisfine pushed a commit that referenced this issue Jan 20, 2023
Rather than to use an exported symbols list, we compile with -fvisibility=hidden
and mark the init function with RUBY_FUNC_EXPORTED.

This was suggested by @nobu.

Ref: #58 (comment)
casperisfine pushed a commit that referenced this issue Jan 20, 2023
Rather than to use an exported symbols list, we compile with -fvisibility=hidden
and mark the init function with RUBY_FUNC_EXPORTED.

This was suggested by @nobu.

Ref: #58 (comment)
casperisfine pushed a commit that referenced this issue Jan 20, 2023
Rather than to use an exported symbols list, we compile with -fvisibility=hidden
and mark the init function with RUBY_FUNC_EXPORTED.

This was suggested by @nobu.

Ref: #58 (comment)
casperisfine pushed a commit that referenced this issue Jan 20, 2023
Rather than to use an exported symbols list, we compile with -fvisibility=hidden
and mark the init function with RUBY_FUNC_EXPORTED.

This was suggested by @nobu.

Ref: #58 (comment)
casperisfine pushed a commit that referenced this issue Jan 20, 2023
Rather than to use an exported symbols list, we compile with -fvisibility=hidden
and mark the init function with RUBY_FUNC_EXPORTED.

This was suggested by @nobu.

Ref: #58 (comment)
casperisfine pushed a commit that referenced this issue Jan 20, 2023
Rather than to use an exported symbols list, we compile with -fvisibility=hidden
and mark the init function with RUBY_FUNC_EXPORTED.

This was suggested by @nobu.

Ref: #58 (comment)
casperisfine pushed a commit that referenced this issue Jan 20, 2023
Rather than to use an exported symbols list, we compile with -fvisibility=hidden
and mark the init function with RUBY_FUNC_EXPORTED.

This was suggested by @nobu.

Ref: #58 (comment)
casperisfine pushed a commit that referenced this issue Jan 20, 2023
Rather than to use an exported symbols list, we compile with -fvisibility=hidden
and mark the init function with RUBY_FUNC_EXPORTED.

This was suggested by @nobu.

Ref: #58 (comment)
stanhu added a commit to stanhu/oj-introspect that referenced this issue Jan 24, 2023
When compiling Ruby 3.2.0 on an Apple M1, this error results:

```
compiling ../../../../ext/oj-introspect/introspect.c
linking shared-object oj/introspect/introspect_ext.bundle
Undefined symbols for architecture arm64:
  "_ruby_abi_version", referenced from:
     -exported_symbol[s_list] command line option
ld: symbol(s) not found for architecture arm64
```

`_ruby_abi_version` is only exported on development builds
(redis-rb/redis-client#58 (comment)).
stanhu added a commit to stanhu/oj-introspect that referenced this issue Jan 24, 2023
When compiling Ruby 3.2.0 on an Apple M1, this error results:

```
compiling ../../../../ext/oj-introspect/introspect.c
linking shared-object oj/introspect/introspect_ext.bundle
Undefined symbols for architecture arm64:
  "_ruby_abi_version", referenced from:
     -exported_symbol[s_list] command line option
ld: symbol(s) not found for architecture arm64
```

`_ruby_abi_version` is only exported on development builds
(redis-rb/redis-client#58 (comment)).
meinac pushed a commit to meinac/oj-introspect that referenced this issue Jan 25, 2023
* Fix _ruby_abi_version symbol not found with Ruby 3.2.0

When compiling Ruby 3.2.0 on an Apple M1, this error results:

```
compiling ../../../../ext/oj-introspect/introspect.c
linking shared-object oj/introspect/introspect_ext.bundle
Undefined symbols for architecture arm64:
  "_ruby_abi_version", referenced from:
     -exported_symbol[s_list] command line option
ld: symbol(s) not found for architecture arm64
```

`_ruby_abi_version` is only exported on development builds
(redis-rb/redis-client#58 (comment)).

* Restrict symbol handling to macOS

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