Native gems, multiple gems per repo, and namespacing (was Fwd: Jeweler)

17 views
Skip to first unread message

Josh Nichols

unread,
Oct 25, 2009, 3:33:39 PM10/25/09
to jewel...@googlegroups.com, vassilisr...@gmail.com
Forwarded for discussion.


---------- Forwarded message ----------
From: Vassilis Rizopoulos <vassilisr...@gmail.com>
Date: Sun, Oct 25, 2009 at 4:42 AM
Subject: Jeweler
To: jo...@technicalpickles.com


Hey Josh,
my name is Vassilis and I'm currently trying to get
webdriver/selenium2.0 in a gem.
I've been looking at putting jeweler to work so I have a list of
issues/questions that might be interesting for you.

Now, our little project pulls the ruby drivers from a repo structure
that has all the webdriver relevant stuff (so we have C, Java, python,
ruby etc) so to build a gem we don't have the files in the usual lib/
bin/ test/ structure.
I actually have the same problem with hoe and I was wondering if you
have any ideas on that. How can I convince jeweler to take for example
common/src/rb/lib/**/*.rb and put it in lib/ on the gem?

It seems to me jeweler is setup to handle pure Ruby projects as it
comes out of the box, so my use case goes way out of the default
conventions - seems to happen to me all the time.

Another wish would be to be able to manage multiple gems in the same
project. Webdriver for example should have one gem pro platform
(windows, macosx, linux) and not pack everything into one gem.

The main hurdle here is basically the rake tasks created. If we could
parametrize that...

And talking about rake tasks, I'll come to the one thing I consider a
bug: The names of the tasks. Naming the task build is limiting the
library to pure Ruby projects. Please consider at least namespacing
the tasks: gem:build or jeweler:build would be fine.
Cheers,
V.-
--
http://www.ampelofilosofies.gr

Josh Nichols

unread,
Oct 25, 2009, 3:36:17 PM10/25/09
to jewel...@googlegroups.com
Hey Vassillis,

I'm going to reply in line...

> Now, our little project pulls the ruby drivers from a repo structure that
> has all the webdriver relevant stuff (so we have C, Java, python, ruby etc)
> so to build a gem we don't have the files in the usual lib/ bin/ test/
> structure.
> I actually have the same problem with hoe and I was wondering if you have
> any ideas on that. How can I convince jeweler to take for example
> common/src/rb/lib/**/*.rb and put it in lib/ on the gem?

Let me understand this correctly... you want common/src/rb/lib to show
up in the gem as lib?

The only way I can think of is to have a Rakefile in src/rb with
Jeweler setup, and build the gemspec/gem there. I think that should
work well.

> It seems to me jeweler is setup to handle pure Ruby projects as it comes out
> of the box, so my use case goes way out of the default conventions - seems
> to happen to me all the time.

This is very true. I've not done anything except pure ruby projects,
so my knowledge is kinda lacking for anything beyond that is lacking.
I don't think jeweler entirely precludes the use of native stuff
though. It is working on a gemspec, and the gemspec is where you setup
the extension stuff.

The only thing that is really lacking is out of the box jeweler tasks
for doing this.

> Another wish would be to be able to manage multiple gems in the same
> project. Webdriver for example should have one gem pro platform (windows,
> macosx, linux) and not pack everything into one gem.

I think this should be possible. Jeweler can be configured to have a
different 'base directory'. I'm not sure if the rake tasks expose this
though.

>
> The main hurdle here is basically the rake tasks created. If we could
> parametrize that...
>
> And talking about rake tasks, I'll come to the one thing I consider a bug:
> The names of the tasks. Naming the task build is limiting the library to
> pure Ruby projects. Please consider at least namespacing the tasks:
> gem:build or jeweler:build would be fine.

This makes sense. I could imagine a 'no conflict mode' which prefixes
everything with jeweler. Similarly, could have a custom namespace, as
if, one for each gem...

Let me know how that sounds. If you pointed me at the repo, I could
take a closer look at it.

- Josh

Nick Quaranto

unread,
Oct 25, 2009, 3:56:04 PM10/25/09
to jewel...@googlegroups.com
Maybe a different packaging solution would be better? Like crate: http://www.copiousfreetime.org/articles/2008/11/30/package-an-application-with-crate.html

-Nick

vassilis

unread,
Oct 26, 2009, 1:50:01 PM10/26/09
to jeweler.rb

On Oct 25, 8:56 pm, Nick Quaranto <n...@quaran.to> wrote:
> Maybe a different packaging solution would be better? Like crate:http://www.copiousfreetime.org/articles/2008/11/30/package-an-applica...

crate is interesting, but not appropriate in this case :)
webdriver (or Selenium - will be one and the same very soon) is not
an application, it's a library to automate web tests, so it needs to
be packaged as a gem.
This is actually a case I run into quite often as I work with projects
where Ruby is not the only language. I see a need for a tool that will
allow us to manage a project that has external dependencies, code in
other languages and/or multiple gems.

I was thinking something in the lines of passing a configuration file
or doing something like the following

gem("first_gem") do |g|
g.spec=gemspec do |gspec|
gspec.name = "the-perfect-gem"
gspec.summary = "Summarize your gem"
gspec.description = "Describe your gem"
gspec.email = "jo...@technicalpickles.com"
gspec.homepage = "http://github.com/technicalpickles/the-perfect-
gem"
gspec.description = "TODO"
gspec.authors = ["Josh Nichols"]
end
g.lib=FileList["/somewhere/in/the/repo/**/*"]#and g.bin and g.test
g.base=FileList["ruby_files/**/*"]#these would land in the gems/1.8/
gems/first-gem-x.x.x/
end

that would then create rake tasks jeweler:first_gem:build and
jeweler:first_gem:release

Josh Nichols

unread,
Oct 26, 2009, 2:27:12 PM10/26/09
to jewel...@googlegroups.com
Specifying the base directory for a gem is possibly internally (ie the
Jeweler class), so Jeweler::Tasks just needs to be exposed this. I'd
imagine going like this:

Jeweler::Tasks.new(:namespace => 'my_first_gem', :base_directory =>
'path/to/my_first_gem') do |gemspec|
# the usual stuff here, but it's all relative to path/to/my_first_gem
end

And this would define stuff like... my_first_gem:build,
my_first_gem:release, etc.

- Josh

vassilis

unread,
Oct 27, 2009, 1:29:01 PM10/27/09
to jeweler.rb
On Oct 26, 7:27 pm, Josh Nichols <j...@technicalpickles.com> wrote:
> Specifying the base directory for a gem is possibly internally (ie the
> Jeweler class), so Jeweler::Tasks just needs to be exposed this. I'd
> imagine going like this:
>
> Jeweler::Tasks.new(:namespace => 'my_first_gem', :base_directory =>
> 'path/to/my_first_gem') do |gemspec|
>    # the usual stuff here, but it's all relative to path/to/my_first_gem
> end
>
> And this would define stuff like... my_first_gem:build,
> my_first_gem:release, etc.

That would be a very nice first step.
But it still doesn't cover the non-standard-ruby-structure case where
files are strewn all over the place and they need to end up in lib/.
Anyone got any ideas on how to do that in a clever way (the non clever
way being to copy everything in a temp directory and then call jeweler
there)
Cheers,
V.-

vassilis

unread,
Oct 27, 2009, 1:29:16 PM10/27/09
to jeweler.rb
On Oct 26, 7:27 pm, Josh Nichols <j...@technicalpickles.com> wrote:
> Specifying the base directory for a gem is possibly internally (ie the
> Jeweler class), so Jeweler::Tasks just needs to be exposed this. I'd
> imagine going like this:
>
> Jeweler::Tasks.new(:namespace => 'my_first_gem', :base_directory =>
> 'path/to/my_first_gem') do |gemspec|
>    # the usual stuff here, but it's all relative to path/to/my_first_gem
> end
>
> And this would define stuff like... my_first_gem:build,
> my_first_gem:release, etc.

Josh Nichols

unread,
Oct 27, 2009, 2:45:24 PM10/27/09
to jewel...@googlegroups.com
I think putting stuff in the gem as 'lib' is probably a good idea,
since that's a standard that most projects use, so making a temp
directory that is laid out that way gems normal are wouldn't be so
horrible.

Also, take a look at the gemspec reference:
http://docs.rubygems.org/read/chapter/20

Specifically, look at require_paths:
http://docs.rubygems.org/read/chapter/20#require_paths

That might go a ways towards helping your setup.

- Josh

Vassilis Rizopoulos

unread,
Oct 27, 2009, 4:11:11 PM10/27/09
to jewel...@googlegroups.com
On 27/10/09 19:45 , Josh Nichols wrote:
>
> I think putting stuff in the gem as 'lib' is probably a good idea,
> since that's a standard that most projects use, so making a temp
> directory that is laid out that way gems normal are wouldn't be so
> horrible.
>
> Also, take a look at the gemspec reference:
> http://docs.rubygems.org/read/chapter/20
>
> Specifically, look at require_paths:
> http://docs.rubygems.org/read/chapter/20#require_paths
>
> That might go a ways towards helping your setup.
>
require_paths just adds paths to the LOADPATH of the gem.
I want the gem to have everything under lib/, not have a structure that
mirrors the one in the repository.
So I want to be able to say take all files from directory blabla/rb/ and
put them in the lib/ directory for the gem.

Josh Nichols

unread,
Oct 27, 2009, 5:20:39 PM10/27/09
to jewel...@googlegroups.com
Ok, I'm kinda confused now, because I thought you had previously said
the exact opposite.

I'm pretty sure you're just going to have to copy the files from your
project structure into a temporary gem directory (ie with lib). You
could probably make your own rake tasks to do this, and then make the
jeweler tasks depend on them.

- Josh

Vassilis Rizopoulos

unread,
Oct 27, 2009, 6:18:43 PM10/27/09
to jewel...@googlegroups.com
On 27/10/09 18:29 , vassilis wrote:
> On Oct 26, 7:27 pm, Josh Nichols<j...@technicalpickles.com> wrote:
>
>> Specifying the base directory for a gem is possibly internally (ie the
>> Jeweler class), so Jeweler::Tasks just needs to be exposed this. I'd
>> imagine going like this:
>>
>> Jeweler::Tasks.new(:namespace => 'my_first_gem', :base_directory =>
>> 'path/to/my_first_gem') do |gemspec|
>> # the usual stuff here, but it's all relative to path/to/my_first_gem
>> end
>>
>> And this would define stuff like... my_first_gem:build,
>> my_first_gem:release, etc.
>>
>
I forked the github repo and added code that puts all tasks under the
jeweler namespace.
As a test I added a pure_ruby_project flag in the constructor that
creates :build, :release and :install tasks.
So to force jeweler not to create these tasks one would have to do

Jeweler:Tasks.new(nil,false){...}

Not very nice I must admit, but it serves as a workaround for what I
currently want to do.
Any pointers on how to test this properly?

here's my repo: git://github.com/damphyr/jeweler.git

Vassilis Rizopoulos

unread,
Oct 27, 2009, 7:14:13 PM10/27/09
to jewel...@googlegroups.com
On 27/10/09 22:20 , Josh Nichols wrote:
> Ok, I'm kinda confused now, because I thought you had previously said
> the exact opposite.
>
> I'm pretty sure you're just going to have to copy the files from your
> project structure into a temporary gem directory (ie with lib). You
> could probably make your own rake tasks to do this, and then make the
> jeweler tasks depend on them.
>
>
That's still a problem I think, cause that is what I am doing now:

Create the gem structure I want under tmp/, so tmp/ looks like

tmp/
lib/
webdriver/
...
webdriver.rb

Now if I say gemspec.files=FileList["tmp/lib/**/*"]

the gem ends up with a tmp/ directory.
The only way to work around this is if I say
gemspec.files=FileList["lib/**/*"] and Dir.chdir("tmp/") in the task
that sets up the gem structure - not very nice.

Cheers,
V.-

Josh Nichols

unread,
Oct 31, 2009, 12:36:56 AM10/31/09
to jewel...@googlegroups.com
On Tue, Oct 27, 2009 at 7:14 PM, Vassilis Rizopoulos
<vassilisr...@gmail.com> wrote:
>>
> That's still a problem I think, cause that is what I am doing now:
>
> Create the gem structure I want under tmp/, so tmp/ looks like
>
> tmp/
>    lib/
>        webdriver/
>            ...
>        webdriver.rb
>
> Now if I say gemspec.files=FileList["tmp/lib/**/*"]
>
> the gem ends up with a tmp/ directory.
> The only way to work around this is if I say
> gemspec.files=FileList["lib/**/*"] and Dir.chdir("tmp/") in the task that
> sets up the gem structure - not very nice.
>

Yes, it'd still be a problem, but that's why I'm saying Jeweler (the
class) allows you to specify a base directory to work in. It just
needs to be exposed to Jeweler::Tasks.

When you use base_dir, Jeweler does a chdir internally, so that the
file paths are correct. This was mainly done initially for testing,
but now it's useful for your situation.

So, I'd imagine doing this:

Jeweler::Tasks.new :base_dir => 'tmp' do |gemspec|
# snip
gemspec.files = FileList["lib/**/*"]
end

Additionally, I think you'd need a task to prepare your tmp directory,
and you'd need to make the jeweler tasks that deal with the gemspec
depend on it. I'd imagine something like...

task :prepare_tmp do
# copy stuff
end

namespace :gemspec do
task :debug => :prepare_tmp
task :build => :prepare_tmp
end

I don't think any others would need it, but that's just what I can
think of off the top of my head.

Hope that helps a bit.

- Josh

Reply all
Reply to author
Forward
0 new messages