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

Exception when requiring after 'mkmf' library #47

Open
botandrose opened this issue Mar 8, 2016 · 9 comments
Open

Exception when requiring after 'mkmf' library #47

botandrose opened this issue Mar 8, 2016 · 9 comments

Comments

@botandrose
Copy link

Steps to reproduce:

$ irb
2.3.0 :001 > require 'scrypt'
 => true 
2.3.0 :002 > require 'mkmf'
 => true 
2.3.0 :003 > exit
$ irb
2.3.0 :001 > require 'mkmf'
 => true 
2.3.0 :002 > require 'scrypt'
ArgumentError: wrong number of arguments (given 1, expected 2+)
    from /home/micah/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/mkmf.rb:1237:in `find_type'
    from /home/micah/.rvm/gems/ruby-2.3.0/gems/ffi-1.9.10/lib/ffi/struct.rb:332:in `find_type'
    from /home/micah/.rvm/gems/ruby-2.3.0/gems/ffi-1.9.10/lib/ffi/struct.rb:326:in `find_field_type'
    from /home/micah/.rvm/gems/ruby-2.3.0/gems/ffi-1.9.10/lib/ffi/struct.rb:368:in `array_layout'
    from /home/micah/.rvm/gems/ruby-2.3.0/gems/ffi-1.9.10/lib/ffi/struct.rb:278:in `layout'
    from /home/micah/.rvm/gems/ruby-2.3.0/gems/scrypt-2.1.1/lib/scrypt.rb:140:in `<class:Calibration>'
    from /home/micah/.rvm/gems/ruby-2.3.0/gems/scrypt-2.1.1/lib/scrypt.rb:139:in `<class:Engine>'
    from /home/micah/.rvm/gems/ruby-2.3.0/gems/scrypt-2.1.1/lib/scrypt.rb:24:in `<module:SCrypt>'
    from /home/micah/.rvm/gems/ruby-2.3.0/gems/scrypt-2.1.1/lib/scrypt.rb:10:in `<top (required)>'
    from /home/micah/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:127:in `require'
    from /home/micah/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:127:in `rescue in require'
    from /home/micah/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:40:in `require'
    from (irb):2
    from /home/micah/.rvm/rubies/ruby-2.3.0/bin/irb:11:in `<main>'

Also reproducible on ruby-2.2.0. Haven't tried others.

botandrose pushed a commit to botandrose/ruby-elm-compiler that referenced this issue Mar 8, 2016
requiring mkmf can interfere with other gems, such as scrypt. see pbhogan/scrypt#47
@febeling
Copy link

mkmf is polluting the toplevel namespace here with it's defintion of find_type.

And ffi is tripping over it here.

@botandrose
Copy link
Author

Hmm, so it seems to me the "right" thing to here is to fix mkmf to not pollute the global namespace. Since mkmf is in core, and this would have backwards-compatibility ramifications, this might take a while, and existing Rubies will still have this problem, so a workaround might be a better short-term solution. I'll see if I can hack something together... maybe something that allows one to use the functionality in mkmf without polluting the top-level namespace.

@botandrose
Copy link
Author

Thanks for doing the detective work on this, btw, @febeling !

@botandrose
Copy link
Author

@febeling
Copy link

Yes, the right fix would be to isolate mkmf cleanly into a module. But FFI is also a bit casual about grabbing any find_type it sees and calling it.

For the first fix, a major version bump would be exactly the right tool. Too bad this is a core module, and not a gem. But there must be an equivalent to a major version bump in core? What is generally done to break an API in such cases in ruby?

I don't know if it's a bad idea, but maybe define the whole module just without the include when loaded as require 'mkmf/isolated' and start to write nagging deprecation warnings when used with require 'mkmf' going forward?

@botandrose
Copy link
Author

Yes, that was exactly my thought... extracting MakeMakeFile to its own file, and mkmf would just load that file and include the module. I think it would probably be nice to also use module_function or extend self within MakeMakeFile, so that one could use its functions in a nice qualified manner, e.g. MakeMakeFile.find_type(...).

Looking into more short-term workarounds, I found the https://github.com/rosylilly/uninclude gem, which, in theory, would let one immediately uninclude MakeMakeFile after requiring mkmf, but I can't get it to work on the top-level namespace. :/

@botandrose
Copy link
Author

Top-level namespace stuff is weird. This works:

require 'uninclude'
require 'mkmf'
Object.send :uninclude, MakeMakefile

After which you can call methods directly on MakeMakefile. FWIW.

@febeling
Copy link

febeling commented Jun 3, 2016

Yes, it looks like a welcome workaround for anyone who's blocked by this problem. It also neatly fits the description you gave a few days back - good job :)

Not sure if you agree, maybe this issue could even be closed now?

One can argue that the main issue is poor practice in mkmf, also ffi is a bit too cavalier about type definition discovery. And scrypt is only showing symptoms of this, as possibly many libs would that rely on both.

@stakach
Copy link
Collaborator

stakach commented Jun 3, 2016

I think we should leave the issue open until the workaround is no longer needed with the latest gems versions

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

No branches or pull requests

3 participants