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

RGeo::Geos.supported? false with GEOS 3.12 on Amazon Linux 2023 #365

Closed
januszm opened this issue Oct 26, 2023 · 21 comments · Fixed by #368
Closed

RGeo::Geos.supported? false with GEOS 3.12 on Amazon Linux 2023 #365

januszm opened this issue Oct 26, 2023 · 21 comments · Fixed by #368

Comments

@januszm
Copy link
Contributor

januszm commented Oct 26, 2023

Amazon Linux 2023, I can't get RGeo to work with GEOS and Ruby 3.2 after succesful compilation and installation of all necessary files:

# geos-config --prefix
/usr
# geos-config --libs
-L/usr/lib64 -lgeos
# geos-config --includes
/usr/include
# geos-config --ldflags
-L/usr/lib64


# ls -la /usr/lib64/libgeos*
lrwxrwxrwx. 1 root root  /usr/lib64/libgeos_c.so -> libgeos_c.so.1
lrwxrwxrwx. 1 root root  /usr/lib64/libgeos_c.so.1 -> libgeos_c.so.1.18.0
-rwxr-xr-x. 1 root root    /usr/lib64/libgeos_c.so.1.18.0
lrwxrwxrwx. 1 root root  /usr/lib64/libgeos.so -> libgeos.so.3.12.0
-rwxr-xr-x. 1 root root   /usr/lib64/libgeos.so.3.12.0

# ls -la /usr/include/geos*
-rw-r--r--.  1 root root   /usr/include/geos_c.h
-rw-r--r--.  1 root root   /usr/include/geos.h

/usr/include/geos:
total 272
drwxr-xr-x.  6 root root  algorithm
-rw-r--r--.  1 root root   constants.h
drwxr-xr-x.  2 root root  coverage
drwxr-xr-x.  2 root root   edgegraph
-rw-r--r--.  1 root root    export.h
...
-rw-r--r--.  1 root root   version.h
gem uninstall rgeo
gem install rgeo

irb(main):002> require "rgeo"
=> true
irb(main):003> RGeo::Geos.supported?
=> false

any ideas why RGeo/Ruby still cannot see GEOS files although their in their most basic location, in /usr (not even /usr/local), all owned by root with read access.

more info from gem install --verbose rgeo on Amazon Linux 2023 with geos compiled, and Ruby 3.2

Building native extensions. This could take a while...
current directory: /usr/local/share/ruby3.2-gems/gems/rgeo-3.0.0/ext/geos_c_impl
["/usr/bin/ruby3.2", "-I/usr/share/ruby3.2-rubygems", "extconf.rb"]
checking for geos-config... yes
Using GEOS compile configuration from /usr/local/bin/geos-config
checking for geos_c.h... yes
checking for GEOSSetSRID_r() in geos_c.h... yes
checking for GEOSPreparedContains_r() in geos_c.h... yes
checking for GEOSPreparedDisjoint_r() in geos_c.h... yes
checking for GEOSUnaryUnion_r() in geos_c.h... yes
checking for GEOSCoordSeq_isCCW_r() in geos_c.h... yes
checking for rb_memhash() in ruby.h... yes
checking for rb_gc_mark_movable() in ruby.h... yes
creating Makefile
current directory: /usr/local/share/ruby3.2-gems/gems/rgeo-3.0.0/ext/geos_c_impl
["make", "DESTDIR=", "sitearchdir=./.gem.20231026-74813-mbjmdr", "sitelibdir=./.gem.20231026-74813-mbjmdr", "clean"]

current directory: /usr/local/share/ruby3.2-gems/gems/rgeo-3.0.0/ext/geos_c_impl
["make", "DESTDIR=", "sitearchdir=./.gem.20231026-74813-mbjmdr", "sitelibdir=./.gem.20231026-74813-mbjmdr"]
compiling analysis.c
compiling coordinates.c
compiling errors.c
compiling factory.c
compiling geometry.c
compiling geometry_collection.c
compiling globals.c
compiling line_string.c
compiling main.c
compiling point.c
compiling polygon.c
compiling ruby_more.c
linking shared-object rgeo/geos/geos_c_impl.so
current directory: /usr/local/share/ruby3.2-gems/gems/rgeo-3.0.0/ext/geos_c_impl
["make", "DESTDIR=", "sitearchdir=./.gem.20231026-74813-mbjmdr", "sitelibdir=./.gem.20231026-74813-mbjmdr", "install"]
/usr/bin/install -c -m 0755 geos_c_impl.so ./.gem.20231026-74813-mbjmdr/rgeo/geos
current directory: /usr/local/share/ruby3.2-gems/gems/rgeo-3.0.0/ext/geos_c_impl
["make", "DESTDIR=", "sitearchdir=./.gem.20231026-74813-mbjmdr", "sitelibdir=./.gem.20231026-74813-mbjmdr", "clean"]

current directory: /usr/local/share/ruby3.2-gems/gems/rgeo-3.0.0/ext/geos_c_impl
/usr/bin/ruby3.2 -I/usr/share/ruby3.2-rubygems extconf.rb
current directory: /usr/local/share/ruby3.2-gems/gems/rgeo-3.0.0/ext/geos_c_impl
make DESTDIR\= sitearchdir\=./.gem.20231026-74813-mbjmdr sitelibdir\=./.gem.20231026-74813-mbjmdr clean
current directory: /usr/local/share/ruby3.2-gems/gems/rgeo-3.0.0/ext/geos_c_impl
make DESTDIR\= sitearchdir\=./.gem.20231026-74813-mbjmdr sitelibdir\=./.gem.20231026-74813-mbjmdr
current directory: /usr/local/share/ruby3.2-gems/gems/rgeo-3.0.0/ext/geos_c_impl
make DESTDIR\= sitearchdir\=./.gem.20231026-74813-mbjmdr sitelibdir\=./.gem.20231026-74813-mbjmdr install
current directory: /usr/local/share/ruby3.2-gems/gems/rgeo-3.0.0/ext/geos_c_impl
make DESTDIR\= sitearchdir\=./.gem.20231026-74813-mbjmdr sitelibdir\=./.gem.20231026-74813-mbjmdr clean
Successfully installed rgeo-3.0.0

# irb
irb(main):001> require "rgeo"
=> true
irb(main):002> RGeo::Geos.supported?
=> false
irb(main):003> require 'rgeo/geos/geos_c_impl'
=> true
irb(main):004> RGeo::Geos.capi_supported?
=> false
@januszm
Copy link
Contributor Author

januszm commented Oct 26, 2023

Downgraded to GEOS 3.7 installed directly from EPEL 8 RPM and now I get this error:

irb(main):001> require 'rgeo'
=> true
irb(main):002> require 'rgeo/geos/geos_c_impl'
<internal:/usr/share/ruby3.2-rubygems/rubygems/core_ext/kernel_require.rb>:85:in `require': /gem/ruby/extensions/x86_64-linux/3.2.0/rgeo-3.0.0/rgeo/geos/geos_c_impl.so: undefined symbol: GEOSMakeValid - /gem/ruby/extensions/x86_64-linux/3.2.0/rgeo-3.0.0/rgeo/geos/geos_c_impl.so (LoadError)

Does it seem more like issue with Ruby 3.2 or too new GEOS (3.12) ?

I mean, GEOS 3.12 works perfectly fine with rgeo 3.0 on my Macbook at least.

@keithdoggett
Copy link
Member

Have you tried running ldconfig in the environment after installing 3.12? Given that the output of the installation shows its able to find every function my guess would be this is some kind of runtime linking issue.

@januszm
Copy link
Contributor Author

januszm commented Oct 28, 2023

I tried, ldconfig doesn't help.

What's more, when I look in GEM_HOME, I can see these files in ext:

# ls vendor/bundle/ruby/3.2.0/gems/rgeo-3.0.0/ext/geos_c_impl/
analysis.c  coordinates.c  errors.c  extconf.rb  factory.h   geometry_collection.c  geometry.h  globals.h      line_string.h  Makefile  point.h    polygon.h  ruby_more.c
analysis.h  coordinates.h  errors.h  factory.c   geometry.c  geometry_collection.h  globals.c   line_string.c  main.c         point.c   polygon.c  preface.h  ruby_more.h

@keithdoggett
Copy link
Member

Hi @januszm, given your comment (#360 (comment)) in another issue it seems like you were able to get this compiled or are you still having issues?

@januszm
Copy link
Contributor Author

januszm commented Nov 9, 2023

@keithdoggett unfortunately it's still an issue, I decided to continue with RGeo::Geos.supported? => false until it's resolved as for me it was more important to move to the new AWS platform.

I'm going to give it one more try on a fresh Amazon Linux 2023 server outside the usual Elastic Beanstalk Ruby 3.2 platform and see if it works there.

@keithdoggett
Copy link
Member

Ok let me know how that goes. Next week I might have some time to test it as well. I also had a ton of issues migrating to Amazon Linux 2023 and ended up containerizing as much as I could since it seemed like every dependency was broken.

@januszm
Copy link
Contributor Author

januszm commented Nov 10, 2023

It works on a regular EC2 server running Amazon Linux 2023 with Ruby 3.2.2

> require "rgeo"
=> true
> RGeo::Geos.supported?
=> true

In this case we can close this issue because this is something related only to one specific Amazon product, Elastic Beanstalk where Ruby setup looks to be slightly different.

FYI my approach to AL2023 is, I compile missing dependencies, such as FreeTDS or GEOS from source and package as tar.gz archives stored on S3. When I need them for Ruby gems I simply call:

aws s3 cp s3://MY_BUCKET/geos-al2023/geos.tar.bz2 geos.tar.bz2
tar xfo geos.tar.bz2 -C /usr/

before bundle install. This seems to work fine with all dependencies except for GEOS 😢

@januszm januszm closed this as completed Nov 10, 2023
@januszm
Copy link
Contributor Author

januszm commented Dec 14, 2023

@keithdoggett something is not right here still, see, if I just test RGeo Geos support from Rails console it says false

bin/rails console
> RGeo::Geos.supported?
=> false

bundle exec irb
> require "rgeo"
=> true
> RGeo::Geos.supported?
=> false

but If I test it from IRB, with a slightly different order of initializating RGeo modules:

> require "rgeo/feature"
=> true
> require 'rgeo/impl_helper'
=> true
require "rgeo/geos/geos_c_impl"
=> true
> require "rgeo/geos"
=> true
> RGeo::Geos.supported?
=> true

Apparently rgeo/geos/geos_c_impl must be required before rgeo/geos and it doesn't work if you simply require "rgeo" !

I guess that there's a moment during app initialization where this errors:

    begin
      require_relative "geos/geos_c_impl"
    rescue LoadError
      # continue
    end

but since we're not logging anything here it's hard to say what's wrong.

@januszm januszm reopened this Dec 14, 2023
@BuonOmo
Copy link
Member

BuonOmo commented Jan 6, 2024

Hi @januszm sorry that there is still an issue...

May you try and log the silent error to see if this is indeed the issue ? Or is it that you don't have access to any logs on the machine you are executing on ?

@januszm
Copy link
Contributor Author

januszm commented Jan 7, 2024

@BuonOmo I've just made the following change to raise error in rgeo-3.0.1/lib/rgeo/geos.rb

    begin
      require_relative "geos/geos_c_impl"
    rescue LoadError
      # continue
    end

with

    begin
      require_relative "geos/geos_c_impl"
    rescue LoadError => e
      raise e
    end

and I'm getting this:

$ bin/rails c
rgeo-3.0.1/lib/rgeo/geos.rb:27:in `require_relative':
  cannot load such file -- rgeo-3.0.1/lib/rgeo/geos/geos_c_impl (LoadError)
	from rgeo-3.0.1/lib/rgeo/geos.rb:27:in `<module:Geos>'

it looks like geos_c_impl.bundle is missing there in lib/rgeo/geos/

@BuonOmo
Copy link
Member

BuonOmo commented Jan 7, 2024

@januszm super interesting, this might mean that

  • the path where geos_c_impl is installed is not correct (ls should give it away)
  • the geos.rb file is somehow evaluated from somewhere else (easy to verify by logging the backtrace)
  • you may have multiple rgeo installations, one being correct

If you could have access to the tree of your gems and look where the bundle file is installed, we might have a better lead ?

@januszm
Copy link
Contributor Author

januszm commented Jan 7, 2024

@BuonOmo any chance this works with the following file (Amazon Linux 2023, the .bundle file was on my local Mac OS X)

/usr/lib64/gems/ruby3.2/rgeo-3.0.1/rgeo/geos/geos_c_impl.so

If this is how it's supposed to work on Linux, then I'm wondering why the application cannot see this file in /usr/lib64

@januszm
Copy link
Contributor Author

januszm commented Jan 7, 2024

just for the sake of completeness, rgeo ruby files are installed in /usr/share/ruby3.2-gems/gems/rgeo-3.0.1/

just the .so file is in

/usr/lib64/gems/ruby3.2/rgeo-3.0.1
/usr/lib64/gems/ruby3.2/rgeo-3.0.1/mkmf.log
/usr/lib64/gems/ruby3.2/rgeo-3.0.1/rgeo
/usr/lib64/gems/ruby3.2/rgeo-3.0.1/rgeo/geos
/usr/lib64/gems/ruby3.2/rgeo-3.0.1/rgeo/geos/geos_c_impl.so
/usr/lib64/gems/ruby3.2/rgeo-3.0.1/gem_make.out
/usr/lib64/gems/ruby3.2/rgeo-3.0.1/gem.build_complete

along with other extensions for other gems

@BuonOmo
Copy link
Member

BuonOmo commented Jan 8, 2024

Yes, .so is the Linux .bundle!
I think we have the error here : you have two different rgeo installations (in share and lib64). The geos.rb file running is likely to be the one that is not in lib64 (would be great to verify). Since we require a relative file, ruby doesn't find the so which in the other installation.

Does it make sense ?

If this theory proves to be true, the next step is understanding why the two installations exists. It may be external to the gem, or it may be due to our rubygem related configurations.

Sorry for the formatting, sent from my phone

@januszm
Copy link
Contributor Author

januszm commented Jan 8, 2024

I think we have the error here : you have two different rgeo installations (in share and lib64).

It actually looks like one installation, but C-extensions are saved in lib64 while the Ruby files alone are in share. Same applies to other gems that are installed on this system, and for some reason other gems work fine in this setup (e.g. tiny_tds or datadog agent)

@BuonOmo
Copy link
Member

BuonOmo commented Jan 8, 2024

Maybe they do not require_relative? It bothers me a bit that specifically for this installation we'd have to change for require but it may be necessary. I don't want to dig into the links between amazon's linux and rubygem either!

Could you verify that changing the require method for require "rgeo/geos/geos_c_impl" works ?

@keithdoggett WDYT?

@januszm
Copy link
Contributor Author

januszm commented Jan 8, 2024

Holy ***, changing require_relative to require in geos.rb fixes it 🎉

    begin
      require "geos/geos_c_impl"
    rescue LoadError
      # continue
    end
> RGeo::Geos.supported?
=> true

🤯
so, if you want to make it work on the modern Amazon Linux, this is the way I guess

@BuonOmo
Copy link
Member

BuonOmo commented Jan 9, 2024

@januszm yep that's just that IDK if this is the way to go since it basically says : let's look for any rgeo installation and find the first one in path. Maybe that is ok but I'd rather at least discuss it! (hence the ping in my previous message..)

@januszm
Copy link
Contributor Author

januszm commented Jan 11, 2024

@BuonOmo WDYT about using require only as a fallback, if require_relative doesn't work? In a production-like system such as AL I'd expect to find only one version of the binary or lib anyway (automated deployments)

@keithdoggett
Copy link
Member

@BuonOmo @januszm sorry about the delay been very busy, but agree with @januszm it would probably be best to check locally first then could do a system-wide search if that fails. I'm not sure how require works currently, but does it already attempt to do this?

@BuonOmo
Copy link
Member

BuonOmo commented Jan 13, 2024

I just verified in load.c and the only place where they look for relative path is in require_relative!

Let's go with you solution then @januszm! Would you want to implement the PR?

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

Successfully merging a pull request may close this issue.

3 participants