ueno / ruby-gpgme

a ruby interface to GnuPG Made Easy (GPGME).
GNU Lesser General Public License v2.1
232 stars 99 forks source link

v2.0.22 ignores `pkg-config` failures and creates a shared library that cannot load symbols #167

Closed stanhu closed 1 year ago

stanhu commented 1 year ago

https://github.com/ueno/ruby-gpgme/pull/166 changed from pkg-config to gpgme-config, but if --use-system-libraries is used and PKG_CONFIG_PATH is set properly, you get this error:

[root@ece815d6fed2 tmp]# pkg-config --libs gpgme
Package gpgme was not found in the pkg-config search path.
Perhaps you should add the directory containing `gpgme.pc'
to the PKG_CONFIG_PATH environment variable
Package 'gpgme', required by 'virtual:world', not found

The following line quietly ignores this error and includes an empty string: https://github.com/ueno/ruby-gpgme/blob/b53405ee0581661e97a3bd3fefe5f2a244b53ec0/ext/gpgme/extconf.rb#L46

This effectively causes the linker flags to omit -lgpgme, which causes symbol resolution errors:

Error:
    rake aborted!
LoadError: /opt/gitlab/embedded/lib/ruby/gems/2.7.0/gems/gpgme-2.0.22/lib/gpgme_n.so: undefined symbol: gpgme_data_release - /opt/gitlab/embedded/lib/ruby/gems/2.7.0/gems/gpgme-2.0.22/lib/gpgme_n.so
[root@ece815d6fed2 tmp]# ldd /usr/local/lib/ruby/gems/3.0.0/gems/gpgme-2.0.22/lib/gpgme_n.so
    linux-vdso.so.1 (0x00007ffd95b2c000)
    libm.so.6 => /lib64/libm.so.6 (0x00007f4e15c88000)
    libc.so.6 => /lib64/libc.so.6 (0x00007f4e158c3000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f4e1621b000)

Originally detected in https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/7345.

Nokogiri avoids this failure mode by checking the existence of the .pc file in https://github.com/sparklemotion/nokogiri/blob/685a940678a8b15501f997a70693cc5e2d7008c7/ext/nokogiri/extconf.rb#L244-L259:

   require "pkg-config"

    checking_for("#{pc} using pkg-config gem version #{PKGConfig::VERSION}", LOCAL_PACKAGE_RESPONSE) do
      if PKGConfig.have_package(pc)
        cflags  = PKGConfig.cflags(pc)
        ldflags = PKGConfig.libs_only_L(pc)
        libs    = PKGConfig.libs_only_l(pc)

I think we need to do something like that and fallback to gpgme-config otherwise.