Skip to content

Commit

Permalink
Fix broken compilation with Ruby interpreter compiled with XCode 14
Browse files Browse the repository at this point in the history
XCode 14 warns if the `-undefined dynamic_lookup` linker option is
used. As a result, the `configure` script for the Ruby interpreter
disables these flags, causing building the native gem to fail with
undefined symbols:

```
compiling encoder.c
encoder.c:307:14: warning: unused function 'rb_cBignum_ffi_yajl' [-Wunused-function]
static VALUE rb_cBignum_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) {
             ^
1 warning generated.
linking shared-object ffi_yajl/ext/encoder.bundle
Undefined symbols for architecture arm64:
  "_yajl_gen_alloc", referenced from:
      _mEncoder_do_yajl_encode in encoder.o
  "_yajl_gen_array_close", referenced from:
      _gen_array_close in encoder.o
  "_yajl_gen_array_open", referenced from:
      _gen_array_open in encoder.o
  "_yajl_gen_bool", referenced from:
      _gen_true in encoder.o
      _gen_false in encoder.o
  "_yajl_gen_config", referenced from:
      _mEncoder_do_yajl_encode in encoder.o
  "_yajl_gen_free", referenced from:
      _mEncoder_do_yajl_encode in encoder.o
  "_yajl_gen_get_buf", referenced from:
      _mEncoder_do_yajl_encode in encoder.o
  "_yajl_gen_map_close", referenced from:
      _gen_map_close in encoder.o
  "_yajl_gen_map_open", referenced from:
      _gen_map_open in encoder.o
  "_yajl_gen_null", referenced from:
      _gen_null in encoder.o
  "_yajl_gen_number", referenced from:
      _gen_number in encoder.o
  "_yajl_gen_string", referenced from:
      _gen_cstring in encoder.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [encoder.bundle] Error 1
```

To fix this, we can explicitly list the symbols that will be
dynamically looked up and use that in the `-U` linker option to
specify that it is okay for that symbol to have no definition.

Relates to ruby/ruby#6193

Signed-off-by: Stan Hu <stanhu@gmail.com>
  • Loading branch information
stanhu committed Dec 13, 2022
1 parent 16abaa0 commit 966eee2
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 0 deletions.
18 changes: 18 additions & 0 deletions ext/ffi_yajl/ext/dlopen/yajl.sym
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
_yajl_gen_alloc
_yajl_gen_array_close
_yajl_gen_array_open
_yajl_gen_bool
_yajl_gen_config
_yajl_gen_free
_yajl_gen_get_buf
_yajl_gen_map_close
_yajl_gen_map_open
_yajl_gen_null
_yajl_gen_number
_yajl_gen_string
_yajl_alloc
_yajl_complete_parse
_yajl_config
_yajl_free
_yajl_get_error
_yajl_parse
21 changes: 21 additions & 0 deletions ext/ffi_yajl/ext/encoder/extconf.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,27 @@ def windows?
!!(RUBY_PLATFORM =~ /mswin|mingw|cygwin|windows/)
end

def macos?
!!(RUBY_PLATFORM =~ /darwin/)
end

def clang?
cc_version = `#{RbConfig.expand("$(CC) --version")}`
cc_version.match?(/clang/i)
end

# XCode 14 warns if `-Wl,-undefined dynamic_lookup` is specified, and as
# a result Ruby interpreters compiled under XCode 14 no longer specify
# this flag by default in DLDFLAGS. Let's specify the list of dynamic symbols
# here to avoid compilation failures.
if clang? && macos?
symfile = File.join(__dir__, '../dlopen/yajl.sym')
dynamic_symbols = File.readlines(symfile)
dynamic_symbols.each do |sym|
$DLDFLAGS << " -Wl,-U,#{sym.strip}"
end
end

if windows?
# include our libyajldll.a definitions on windows in the libyajl2 gem
$libs = "#{$libs} -lyajldll"
Expand Down
21 changes: 21 additions & 0 deletions ext/ffi_yajl/ext/parser/extconf.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,27 @@ def windows?
!!(RUBY_PLATFORM =~ /mswin|mingw|cygwin|windows/)
end

def macos?
!!(RUBY_PLATFORM =~ /darwin/)
end

def clang?
cc_version = `#{RbConfig.expand("$(CC) --version")}`
cc_version.match?(/clang/i)
end

# XCode 14 warns if `-Wl,-undefined dynamic_lookup` is specified, and as
# a result Ruby interpreters compiled under XCode 14 no longer specify
# this flag by default in DLDFLAGS. Let's specify the list of dynamic symbols
# here to avoid compilation failures.
if clang? && macos?
symfile = File.join(__dir__, '../dlopen/yajl.sym')
dynamic_symbols = File.readlines(symfile)
dynamic_symbols.each do |sym|
$DLDFLAGS << " -Wl,-U,#{sym.strip}"
end
end

if windows?
# include our libyajldll.a definitions on windows in the libyajl2 gem
$libs = "#{$libs} -lyajldll"
Expand Down

0 comments on commit 966eee2

Please sign in to comment.