paper_house 0.6.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -1
  3. data/Rakefile +3 -10
  4. data/examples/executable/Rakefile +5 -0
  5. data/examples/executable/Rakefile.llvm +5 -0
  6. data/examples/executable/hello.c +7 -0
  7. data/examples/executable_subdirs/Rakefile +11 -0
  8. data/examples/executable_subdirs/includes/hello.h +1 -0
  9. data/examples/executable_subdirs/sources/hello.c +6 -0
  10. data/examples/executable_subdirs/sources/main.c +8 -0
  11. data/examples/fail/Rakefile +5 -0
  12. data/examples/fail/hello +0 -0
  13. data/examples/fail/hello.c +1 -0
  14. data/examples/ruby_extension/Rakefile +5 -0
  15. data/examples/ruby_extension/Rakefile.llvm +5 -0
  16. data/examples/ruby_extension/hello.c +6 -0
  17. data/examples/shared_library/Rakefile +23 -0
  18. data/examples/shared_library/Rakefile.llvm +25 -0
  19. data/examples/shared_library/hello.c +6 -0
  20. data/examples/shared_library/hello.h +1 -0
  21. data/examples/shared_library/main.c +7 -0
  22. data/examples/shared_library_subdirs/Rakefile +28 -0
  23. data/examples/shared_library_subdirs/includes/hello.h +1 -0
  24. data/examples/shared_library_subdirs/sources/hello.c +6 -0
  25. data/examples/shared_library_subdirs/sources/main.c +8 -0
  26. data/examples/static_library/Rakefile +14 -0
  27. data/examples/static_library/Rakefile.llvm +14 -0
  28. data/examples/static_library/hello.c +6 -0
  29. data/examples/static_library/hello.h +1 -0
  30. data/examples/static_library/main.c +7 -0
  31. data/examples/static_library_subdirs/Rakefile +19 -0
  32. data/examples/static_library_subdirs/includes/hello.h +1 -0
  33. data/examples/static_library_subdirs/sources/hello.c +6 -0
  34. data/examples/static_library_subdirs/sources/main.c +8 -0
  35. data/features/step_definitions/paper_house_steps.rb +1 -1
  36. data/features/support/hooks.rb +2 -2
  37. data/lib/paper_house/auto_depends.rb +3 -8
  38. data/lib/paper_house/build_failed.rb +3 -1
  39. data/lib/paper_house/build_task.rb +7 -4
  40. data/lib/paper_house/dependency.rb +9 -7
  41. data/lib/paper_house/executable_task.rb +13 -1
  42. data/lib/paper_house/library_task.rb +7 -6
  43. data/lib/paper_house/linker_options.rb +1 -1
  44. data/lib/paper_house/platform.rb +7 -8
  45. data/lib/paper_house/ruby_extension_task.rb +0 -4
  46. data/lib/paper_house/shared_library_task.rb +11 -0
  47. data/lib/paper_house/version.rb +1 -1
  48. data/paper_house.gemspec +2 -1
  49. data/spec/paper_house/executable_task_spec.rb +35 -42
  50. data/spec/paper_house/ruby_extension_task_spec.rb +38 -76
  51. data/spec/paper_house/shared_library_task_spec.rb +71 -105
  52. data/spec/paper_house/static_library_task_spec.rb +63 -54
  53. data/spec/paper_house/version_spec.rb +2 -4
  54. data/spec/spec_helper.rb +2 -1
  55. metadata +54 -24
  56. data/lib/paper_house/safe_popen.rb +0 -26
@@ -12,9 +12,11 @@ module PaperHouse
12
12
  class BuildTask < Rake::TaskLib
13
13
  # Helper class for defining CLEAN and CLOBBER.
14
14
  class CleanTask
15
- def initialize(targets, file_list)
15
+ # Add +targets+ to +target_type+ (+:CLEAN+ or +:CLOBBER+).
16
+ # @example CleanTask.new %w(file1 file2), :CLEAN
17
+ def initialize(targets, target_type)
16
18
  @targets = targets
17
- @file_list = Object.const_get(file_list.to_s.upcase)
19
+ @file_list = Object.const_get(target_type)
18
20
  define_task
19
21
  end
20
22
 
@@ -50,6 +52,7 @@ module PaperHouse
50
52
  ENV['CC'] || @cc || 'gcc'
51
53
  end
52
54
 
55
+ # @private
53
56
  def initialize(name, &block)
54
57
  @name = name.to_s
55
58
  block.call self if block
@@ -109,8 +112,8 @@ module PaperHouse
109
112
  end
110
113
 
111
114
  def define_clean_tasks
112
- CleanTask.new objects, :clean
113
- CleanTask.new clobber_targets, :clobber
115
+ CleanTask.new objects, :CLEAN
116
+ CleanTask.new clobber_targets, :CLOBBER
114
117
  end
115
118
 
116
119
  def clobber_targets
@@ -4,30 +4,32 @@ require 'pstore'
4
4
  require 'rake'
5
5
 
6
6
  module PaperHouse
7
- #
8
7
  # Keeps compilation dependencies
9
- #
10
8
  class Dependency
11
9
  attr_reader :path
12
10
 
11
+ # Creates an object that tracks depencency information about a
12
+ # rake task specified with the +name+ argument.
13
+ #
14
+ # @example
15
+ # Dependency.new('hello')
13
16
  def initialize(name)
14
17
  @name = name
15
18
  @path = File.join(Rake.original_dir, ".#{name}.depends")
16
19
  @cache = {}
17
20
  end
18
21
 
19
- #
20
22
  # Reads the dependency information of +object_file+.
21
- #
23
+ # @return [Array<String>]
22
24
  def read(object_file)
23
25
  db.transaction(true) do |store|
24
26
  store[object_file]
25
27
  end || []
26
28
  end
27
29
 
28
- #
29
- # Saves the dependency information (+object_file+ => +dependent_files+).
30
- #
30
+ # Saves the dependency information
31
+ # (+object_file+ => +dependent_files+).
32
+ # @return [void]
31
33
  def write(object_file, dependent_files)
32
34
  db.transaction(false) do |store|
33
35
  store[object_file] = dependent_files
@@ -12,6 +12,18 @@ module PaperHouse
12
12
  class ExecutableTask < BuildTask
13
13
  include LinkerOptions
14
14
 
15
+ # Defines a rake task called +name+ that builds an executable.
16
+ # Several task attributes can be set in the +block+.
17
+ #
18
+ # @yield [task]
19
+ # @example
20
+ # PaperHouse::ExecutableTask.new :hello do |task|
21
+ # task.executable_name = 'hello'
22
+ # task.target_directory = 'objects'
23
+ # task.sources = 'sources/*.c'
24
+ # task.includes = 'includes'
25
+ # task.cflags = %w(-Wall -Wextra)
26
+ # end
15
27
  def initialize(name, &block)
16
28
  super name, &block
17
29
  Rake::Task[name].prerequisites.each do |each|
@@ -24,7 +36,7 @@ module PaperHouse
24
36
  attr_writer :executable_name
25
37
 
26
38
  def executable_name
27
- @executable_name ||= @name
39
+ (@executable_name ||= @name).to_s
28
40
  end
29
41
  alias_method :target_file_name, :executable_name
30
42
 
@@ -5,17 +5,18 @@ require 'paper_house/build_task'
5
5
  module PaperHouse
6
6
  # Common base class for static, shared, and ruby library tasks.
7
7
  class LibraryTask < BuildTask
8
- # Find a LibraryTask by name
9
- def self.find_named(name)
8
+ # Find a LibraryTask by +name+.
9
+ # @return [LibraryTask]
10
+ def self.find_by_name(name)
10
11
  ObjectSpace.each_object(self) do |each|
11
12
  obj_name = each.name
12
- if Rake::Task.task_defined?(obj_name) && obj_name == name.to_s
13
- return each
14
- end
13
+ next if !Rake::Task.task_defined?(obj_name) || obj_name != name.to_s
14
+ return each
15
15
  end
16
16
  nil
17
17
  end
18
18
 
19
+ # @private
19
20
  def initialize(name, &block)
20
21
  @library_dependencies = []
21
22
  super name, &block
@@ -23,7 +24,7 @@ module PaperHouse
23
24
 
24
25
  # Name of library.
25
26
  def library_name
26
- @library_name ||= @name
27
+ (@library_name ||= @name).to_s
27
28
  end
28
29
 
29
30
  # Name of library.
@@ -38,7 +38,7 @@ module PaperHouse
38
38
  end
39
39
 
40
40
  def maybe_enhance(name, klass)
41
- task = klass.find_named(name)
41
+ task = klass.find_by_name(name)
42
42
  enhance task if task
43
43
  end
44
44
 
@@ -3,9 +3,7 @@
3
3
  require 'rbconfig'
4
4
 
5
5
  module PaperHouse
6
- #
7
6
  # Platform-dependent stuff.
8
- #
9
7
  module Platform
10
8
  include RbConfig
11
9
 
@@ -13,13 +11,13 @@ module PaperHouse
13
11
  MAC = (/darwin|mac os/ =~ CONFIG['host_os'])
14
12
 
15
13
  # File extension of C extensions.
16
- SHARED_EXT = MAC ? '.bundle' : '.so'
14
+ SHARED_EXT = (MAC ? '.bundle' : '.so').freeze
17
15
 
18
16
  # CC options for compiling shared libraries.
19
- LDSHARED = MAC ? '-dynamic -bundle' : '-shared'
17
+ LDSHARED = (MAC ? '-dynamic -bundle' : '-shared').freeze
20
18
 
21
19
  # CC option for setting soname.
22
- SONAME_OPTION = MAC ? '-install_name' : '-soname'
20
+ SONAME_OPTION = (MAC ? '-install_name' : '-soname').freeze
23
21
 
24
22
  # Include directories for compiling C extensions.
25
23
  RUBY_INCLUDES =
@@ -27,13 +25,14 @@ module PaperHouse
27
25
  File.join(CONFIG['rubyhdrdir'], CONFIG['arch']),
28
26
  File.join(CONFIG['rubyhdrdir'], 'ruby/backward'),
29
27
  CONFIG['rubyhdrdir']
30
- ]
28
+ ].freeze
31
29
 
32
30
  # Library directories for compiling C extensions.
33
- RUBY_LIBDIR = CONFIG['libdir']
31
+ RUBY_LIBDIR = CONFIG['libdir'].freeze
34
32
 
33
+ # Platform name.
35
34
  def self.name
36
- MAC ? 'mac' : 'linux'
35
+ (MAC ? 'mac' : 'linux').freeze
37
36
  end
38
37
  end
39
38
  end
@@ -4,13 +4,9 @@ require 'paper_house/library_task'
4
4
  require 'paper_house/linker_options'
5
5
  require 'paper_house/platform'
6
6
 
7
- #
8
7
  # Rake for C projects.
9
- #
10
8
  module PaperHouse
11
- #
12
9
  # Compiles *.c files into a Ruby extension library.
13
- #
14
10
  class RubyExtensionTask < LibraryTask
15
11
  include LinkerOptions
16
12
  include Platform
@@ -13,6 +13,17 @@ module PaperHouse
13
13
  # Library version string.
14
14
  attr_accessor :version
15
15
 
16
+ # Defines a rake task called +name+ that builds a shared library.
17
+ # Note that version number must be set as the +version+ argument
18
+ # or in the +block+ to build the library.
19
+ #
20
+ # @yield [task]
21
+ # @example
22
+ # PaperHouse::SharedLibraryTask.new :libhello do |task|
23
+ # task.version = '0.1.0'
24
+ # task.sources = 'hello.c'
25
+ # task.library_dependencies = 'm'
26
+ # end
16
27
  def initialize(name, version = nil, &block)
17
28
  @version = version
18
29
  super name, &block
@@ -3,5 +3,5 @@
3
3
  # Base module.
4
4
  module PaperHouse
5
5
  # gem version.
6
- VERSION = '0.6.0'
6
+ VERSION = '0.6.1'.freeze
7
7
  end
data/paper_house.gemspec CHANGED
@@ -19,6 +19,7 @@ Gem::Specification.new do |gem|
19
19
  gem.files = %w(CONTRIBUTING.md LICENSE Rakefile paper_house.gemspec)
20
20
  gem.files += Dir.glob('lib/**/*.rb')
21
21
  gem.files += Dir.glob('bin/**/*')
22
+ gem.files += Dir.glob('examples/**/*')
22
23
  gem.files += Dir.glob('spec/**/*')
23
24
  gem.files += Dir.glob('features/**/*')
24
25
 
@@ -30,5 +31,5 @@ Gem::Specification.new do |gem|
30
31
 
31
32
  gem.required_ruby_version = '>= 1.9.3'
32
33
  gem.add_dependency 'POpen4', '~> 0.1.4'
33
- gem.add_dependency 'rake', '~> 10.2.1'
34
+ gem.add_dependency 'rake'
34
35
  end
@@ -3,65 +3,58 @@
3
3
  require 'paper_house/executable_task'
4
4
 
5
5
  describe Rake::Task do
6
- before { Rake::Task.clear }
6
+ context 'when ExecutableTask (name = :test) is defined' do
7
+ Given { Rake::Task.clear }
8
+ Given { PaperHouse::ExecutableTask.new :test }
7
9
 
8
- describe '.[]' do
9
- subject { Rake::Task[task] }
10
+ describe '.[]' do
11
+ context 'with :test' do
12
+ Given(:name) { :test }
10
13
 
11
- context 'with :test' do
12
- let(:task) { :test }
13
-
14
- context 'when ExecutableTask named :test is defined' do
15
- before { PaperHouse::ExecutableTask.new :test }
14
+ When(:task) { Rake::Task[name] }
15
+ Then { task.is_a? Rake::Task }
16
16
 
17
17
  describe '#invoke' do
18
- it do
19
- expect do
20
- subject.invoke
21
- end.to raise_error('Cannot find sources (*.c).')
18
+ When(:result) { task.invoke }
19
+ Then do
20
+ result ==
21
+ Failure(RuntimeError, 'Cannot find sources (*.c).')
22
22
  end
23
23
  end
24
24
  end
25
-
26
- context 'when ExecutableTask named :test is not defined' do
27
- it { expect { subject }.to raise_error }
28
- end
29
25
  end
30
26
  end
31
27
  end
32
28
 
33
29
  describe PaperHouse::ExecutableTask, '.new' do
34
- context 'with name :test' do
35
- subject { PaperHouse::ExecutableTask.new :test }
36
-
37
- its(:cc) { should eq 'gcc' }
38
- its(:cflags) { should be_empty }
39
- its(:executable_name) { should eq 'test' }
40
- its(:includes) { should be_empty }
41
- its(:ldflags) { should be_empty }
42
- its(:library_dependencies) { should be_empty }
43
- its(:name) { should eq 'test' }
44
- its(:sources) { should eq '*.c' }
45
- its(:target_directory) { should eq '.' }
30
+ context 'with :test' do
31
+ When(:task) { PaperHouse::ExecutableTask.new(:test) }
32
+ Then { task.name == 'test' }
33
+ Then { task.executable_name == 'test' }
34
+ Then { task.sources == '*.c' }
35
+ Then { task.target_directory == '.' }
36
+ Then { task.cc == 'gcc' }
37
+ Then { task.cflags.empty? }
38
+ Then { task.includes.empty? }
39
+ Then { task.ldflags.empty? }
40
+ Then { task.library_dependencies.empty? }
46
41
  end
47
42
 
48
- context 'with :test and block' do
49
- subject do
50
- PaperHouse::ExecutableTask.new(:test) do | task |
51
- task.executable_name = executable_name
43
+ context "with :test and a block setting :executable_name = 'executable'" do
44
+ When(:task) do
45
+ PaperHouse::ExecutableTask.new(:test) do |task|
46
+ task.executable_name = 'executable'
52
47
  end
53
48
  end
49
+ Then { task.executable_name == 'executable' }
50
+ end
54
51
 
55
- context %(with #executable_name = 'new_name') do
56
- let(:executable_name) { 'new_name' }
57
-
58
- its(:executable_name) { should eq 'new_name' }
59
- end
60
-
61
- context 'with #executable_name = :new_name' do
62
- let(:executable_name) { :new_name }
63
-
64
- its(:executable_name) { should eq :new_name }
52
+ context 'with :test and a block setting :executable_name = :executable' do
53
+ When(:task) do
54
+ PaperHouse::ExecutableTask.new(:test) do |task|
55
+ task.executable_name = :executable
56
+ end
65
57
  end
58
+ Then { task.executable_name == 'executable' }
66
59
  end
67
60
  end
@@ -3,100 +3,62 @@
3
3
  require 'paper_house/ruby_extension_task'
4
4
 
5
5
  describe Rake::Task do
6
- before { Rake::Task.clear }
6
+ context 'when RubyExtensionTask (name = :test) is defined' do
7
+ Given { Rake::Task.clear }
8
+ Given { PaperHouse::RubyExtensionTask.new :test }
7
9
 
8
- describe '.[]' do
9
- subject { Rake::Task[task] }
10
+ describe '.[]' do
11
+ context 'with :test' do
12
+ Given(:name) { :test }
10
13
 
11
- context 'with :test' do
12
- let(:task) { :test }
13
-
14
- context 'when RubyExtensionTask named :test is defined' do
15
- before { PaperHouse::RubyExtensionTask.new :test }
14
+ When(:task) { Rake::Task[name] }
15
+ Then { task.is_a? Rake::Task }
16
16
 
17
17
  describe '#invoke' do
18
- it do
19
- expect do
20
- subject.invoke
21
- end.to raise_error('Cannot find sources (*.c).')
18
+ When(:result) { task.invoke }
19
+ Then do
20
+ result ==
21
+ Failure(RuntimeError, 'Cannot find sources (*.c).')
22
22
  end
23
23
  end
24
24
  end
25
-
26
- context 'when RubyExtensionTask named :test is not defined' do
27
- it { expect { subject }.to raise_error }
28
- end
29
25
  end
30
26
  end
31
27
  end
32
28
 
33
- describe PaperHouse::RubyExtensionTask do
34
- before { Rake::Task.clear }
35
-
36
- describe '.find_named' do
37
- subject { PaperHouse::RubyExtensionTask.find_named name }
38
-
39
- context 'with :test' do
40
- let(:name) { :test }
41
-
42
- context 'when RubyExtensionTask named :test is defined' do
43
- before { PaperHouse::RubyExtensionTask.new :test }
44
-
45
- it { expect(subject).to be_a PaperHouse::RubyExtensionTask }
46
- end
47
-
48
- context 'when RubyExtensionTask named :test is not defined' do
49
- it { expect(subject).to be_nil }
50
- end
29
+ describe PaperHouse::RubyExtensionTask, '.new' do
30
+ context 'with :test' do
31
+ When(:task) { PaperHouse::RubyExtensionTask.new(:test) }
32
+ Then { task.name == 'test' }
33
+ Then { task.library_name == 'test' }
34
+ Then { task.sources == '*.c' }
35
+ Then { task.target_directory == '.' }
36
+ Then { task.cc == 'gcc' }
37
+ if PaperHouse::Platform.name == 'mac'
38
+ Then { task.library_dependencies == ['ruby'] }
39
+ else
40
+ Then { task.library_dependencies.empty? }
51
41
  end
42
+ Then { task.cflags.empty? }
43
+ Then { task.includes.empty? }
44
+ Then { task.ldflags.empty? }
45
+ end
52
46
 
53
- context %(with 'test') do
54
- let(:name) { 'test' }
55
-
56
- context %(when RubyExtensionTask named 'test' is defined) do
57
- before { PaperHouse::RubyExtensionTask.new :test }
58
-
59
- it { expect(subject).to be_a PaperHouse::RubyExtensionTask }
47
+ context "with :test and a block setting :library_name = 'libtest'" do
48
+ When(:task) do
49
+ PaperHouse::RubyExtensionTask.new(:test) do |task|
50
+ task.library_name = 'libtest'
60
51
  end
61
52
  end
62
-
63
- context 'with :no_such_task' do
64
- let(:name) { :no_such_task }
65
-
66
- it { expect(subject).to be_nil }
67
- end
53
+ Then { task.library_name == 'libtest' }
68
54
  end
69
55
 
70
- describe '.new' do
71
- context 'with :test' do
72
- subject { PaperHouse::RubyExtensionTask.new :test }
73
-
74
- its(:cc) { should eq 'gcc' }
75
- its(:cflags) { should be_empty }
76
- its(:includes) { should be_empty }
77
- its(:name) { should eq 'test' }
78
- its(:sources) { should eq '*.c' }
79
- its(:target_directory) { should eq '.' }
80
- end
81
-
82
- context 'with :test and block' do
83
- subject do
84
- PaperHouse::RubyExtensionTask.new(:test) do | task |
85
- task.library_name = library_name
86
- end
87
- end
88
-
89
- context %(with #library_name = 'new_name') do
90
- let(:library_name) { 'new_name' }
91
-
92
- its(:library_name) { should eq 'new_name' }
93
- end
94
-
95
- context 'with #library_name = :new_name' do
96
- let(:library_name) { :new_name }
97
-
98
- its(:library_name) { should eq :new_name }
56
+ context 'with :test and a block setting :library_name = :libtest' do
57
+ When(:task) do
58
+ PaperHouse::RubyExtensionTask.new(:test) do |task|
59
+ task.library_name = :libtest
99
60
  end
100
61
  end
62
+ Then { task.library_name == 'libtest' }
101
63
  end
102
64
  end