How do I pass two build parameters to bundle config? - ruby

I'm trying to configure bundler such that building the mysql2 gem will pass the necessary parameters to extconf. Problem is, I can't figure out how to pass more than one parameter.
In my Gemfile, I just have:
gem mysql2, '= 0.3.11'
(There is some problem with the latest version which prevents compiling it at all, so I'm using 0.3.11 based on a recommendation I found on another post somewhere around here.)
I tried this:
bundle config build.mysql2 --with-mysql-include=C:\DevEnv\Tools\Ruby\mysql-connector-c-noinstall-6.0.2-winx64\include --with-mysql-lib=C:\DevEnv\Tools\Ruby\mysql-connector-c-noinstall-6.0.2-winx64\lib
I also tried quoting the parameters into a single parameter:
bundle config build.mysql2 "--with-mysql-include=C:\DevEnv\Tools\Ruby\mysql-connector-c-noinstall-6.0.2-winx64\include --with-mysql-lib=C:\DevEnv\Tools\Ruby\mysql-connector-c-noinstall-6.0.2-winx64\lib"
I can tell it isn't working because gem is showing me the command-line which is actually being used, and then the build fails because it can't provide the lib):
C:/DevEnv/Tools/Ruby/Ruby200-x64/bin/ruby.exe extconf.rb --with-mysql-include=C:\DevEnv\Tools\Ruby\mysql-connector-c-noinstall-6.0.2-winx64\include
If I provide just the --with-mysql-lib parameter or swap the order of the parameters, the build passes on looking for the lib but fails on a missing include instead.
If I pass the same flags to gem directly, that works fine. But that won't be terribly great when it comes time to deploy.
How are other people doing this?
PS a binary DLL would have been nice, but I guess they stopped doing that.

For the next poor sap that has to deal with this, the answer is a lot of quoting:
bundle config build.mysql2 "--with-mysql-include=\"C:\DevEnv\Tools\Ruby\mysql-connector-c-noinstall-6.0.2-winx64\include\" --with-mysql-lib=\"C:\DevEnv\Tools\Ruby\mysql-connector-c-noinstall-6.0.2-winx64\lib\""

bundle config --local --with-mysql-include 'C:\INC_PATH\include'
bundle config --local --with-mysql-lib 'C:\LIB_PATH\lib'
The above will store configuration directives in current directory in .bundle/config file. After you have these two directives run, try normal build install. Hope it helps.
More info.

Related

How to add conditional Gemspec dependencies

I have made a Gem that optionally logs with Sentry or Airbrake, depending on the ENV variables. I have these in my Gemspec but I only need one or the other:
spec.add_runtime_dependency "sentry-raven"
spec.add_runtime_dependency "airbrake"
Is there a way to only include the one that the end user needs, based on ENV variables?
You may be best off leaving off both dependencies and adding to your README that a user needs to add the dependency to their own Gemfile. I've seen some gems check to see what is defined, raising an error if they don't find anything, as well as allowing the user to configure in their application which tool to use.
No, this is not possible for the simple reason that the Gemspec is executed on your computer, not the user's computer. It is executed to build the Gem, not install it.
RubyGems does not have a sophisticated dependency system like e.g. dpkg/APT has: a Gem either depends on another Gem or it doesn't.

Creating Ruby gems with same name executables?

I want to have a Ruby Gem that will have the same executable as another Gem.
When called with command args it will either do something, or pass the command on to the other Gem.
The first problem I have is that it isn't able to run two same named executables. I get this error:
Bundler is using a binstub that was created for a different gem. This is deprecated, in future versions you may need to bundle binstub yourgem to work around a system/bundle conflict.
How can I have Gems with the same named executables and ensure that the target one executes?
You cannot rely on Bundler or Rubygems to manage this for you. All it does it copy an executable that you specified in your gem spec to its bin/ directory.
The first problem you'll have is that the executable that runs may be dependent on the order in which the gems were installed which you can't guarantee.
Another problem that you'll have is that you cannot execute code on gem installation so you will be unable to run code that would try to automate this set up for people who install your gem.
I believe your gem should provide a non-conflicting executable. You can then supply post install instructions in your gem spec that are displayed to a user installing the gem, in the README, in a blog post, etc. you can tell the user that they need to set up an alias that points to your executable. In all shells that I'm aware of aliases will be executed before filesystem executables.
For the times when people want to bypass your alias and execute the original executable you can tell people to escape the command, e.g. \original-gem. That bypasses alias and function lookup in most shells and will allow users to have your super awesome version as the default (thru the alias) and a way to easily access the original.

Guard running outside of Bundler warning

When I run the guard command it gives the following warning:
Guard here! It looks like your project has a Gemfile, yet you are
running guard outside of Bundler. If this is your intent, feel free
to ignore this message. Otherwise, consider using bundle exec guard
to ensure your dependencies are loaded correctly.
Is this hinting to me that Rails is not configured to work with Bundler correctly, or is it normal? It's not the expected behavior in the tutorial I'm following.
You should run bundle exec guard instead. Or, alternatively, run bundle install --binstubs, then you may run guard with bin/guard (it creates a script at this location). This is the recommended way of running all commands coming from gems installed with bundle install.
(If I understand it correctly) It ensures that you run the specific version of the gem specified in the bundle as well as that this gem will not be able to run gems which are installed on you computer but not included in the Gemfile (which could fool you into believing that you project is fine until you try to run it on a different computer, or a production server, where the other gem would be missing). It also does a lot of of stuff which, frankly, I have no idea about.
More info in the docs.

Getting started with gems and jeweler

With Jeweler I created a gem folder structure with ease.
However, I still have some questions:
Why are params like --gemcutter and --rubyforge still available for Jeweler. Aren't these replaced by RubyGems? Do I have to specify anything to create a gem for RubyGems?
In the Rakefile I have information about the gem, and when I run "rake install" it created a gemspec. Why is the same information in two places?
What is a manifest? Just read about it, haven't seen such file.
How do I make my gem callable from the shell once I have installed it, like rails. Cause right now it's just accessible through a Ruby script using require.
Should I use "jeweler release" or "gem push" to push my gem to RubyGems.org?
I have to specify "handle" when signing up in RubyGems. What is that?
Thanks.
jeweler was created before RubyGems became what it is, so it still reflects the split. I'm not sure when jeweler was last updated, either. (I think it also still recognizes building gems on Github, which is now disabled.)
I'm not sure I follow what you're saying. The specification in the Rakefile details what the spec that gets written should look like. The spec that gets written details what should be installed and how, I believe.
A manifest is a list of all the files that your gem should ship with. Not everyone uses one. See the hoe documentation for some pro-manifest discussion.
Many Ruby gems are only libraries. If you want yours to also have a program like jeweler or rake or rails that you can call, you have to write the callable program, put it in bin in your gem's layout and specify (in your gemspec) that it should be packaged and installed. See the Gem::Specification reference under files and executable.
Not sure. Consult both jeweler's docs and the docs for RubyGems.
You can give an email address or use a name (a 'handle', like I use Telemachus here), which is all they mean by 'handle'.
For the record, if you are just learning how to write gems, you do not need to upload your first attempts using RubyGems or anything like it. You can simply install the gem on your machine only.

How to develop a gem in staging environment?

I am trying to hack through a forked gem (buildr). As such I cloned it from github and began to butcher the code. The official gem is installed on my system (under /usr/lib/ruby.../gems/buildr...). There is an executable which I need to use in my dev process - buildr.
Now I want the buildr executable and the library to point to my forked repo and not the default gem installation. This would be for this gem only. As such, the changes I make against the forked repo is usable directly for testing and so forth.
I would guess I need to load my library prior to the system gem loading. Can somebody recommend the best way to do so?
I did something similar for work when the Spreadsheet gem broke backward compatibility. I put the previous versions code in it's own module and just renamed the gem my-spreadsheet and installed that (I really wanted some of the features of the new gem but I also didn't want to rewrite all my previous code at that point).
If it's just a binary you want to override you could always do some PATH magic, setting the directory of your binary first and thus make sure you always override. But personally I'd prefer making my own copy with a new name and installing that.
you could bump the version in the gemspec for your fork. Then when you install your version of the gem, it will use your (newer) version by default.
change buildr.gemspec
#...
spec.version = '1.3.4.dev'
#...
Then
$ gem build buildr.gemspec
$ sudo gem install buildr-1.3.4.dev.gem
and it should work.

Resources