ritsu 0.1.0

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 (73) hide show
  1. data/README.md +96 -0
  2. data/Thorfile +95 -0
  3. data/VERSION +1 -0
  4. data/bin/ritsu +32 -0
  5. data/lib/ritsu/block.rb +259 -0
  6. data/lib/ritsu/ext/test_case.rb +20 -0
  7. data/lib/ritsu/external_library.rb +47 -0
  8. data/lib/ritsu/project.rb +89 -0
  9. data/lib/ritsu/project_generator.rb +34 -0
  10. data/lib/ritsu/project_generators/default_generator.rb +73 -0
  11. data/lib/ritsu/project_generators/default_generator_files/Thorfile.erb +9 -0
  12. data/lib/ritsu/project_generators/default_generator_files/meta/project.rb.erb +9 -0
  13. data/lib/ritsu/project_generators.rb +1 -0
  14. data/lib/ritsu/src_file.rb +76 -0
  15. data/lib/ritsu/src_files/cpp_file.rb +33 -0
  16. data/lib/ritsu/src_files/cpp_file_mixin.rb +13 -0
  17. data/lib/ritsu/src_files/executable_cmake_lists.rb +40 -0
  18. data/lib/ritsu/src_files/header_file.rb +46 -0
  19. data/lib/ritsu/src_files/header_file_mixin.rb +20 -0
  20. data/lib/ritsu/src_files/project_cmake_lists.rb +110 -0
  21. data/lib/ritsu/src_files/project_config_header_file.rb +15 -0
  22. data/lib/ritsu/src_files/project_config_header_template_file.rb +46 -0
  23. data/lib/ritsu/src_files/shared_library_cmake_lists.rb +40 -0
  24. data/lib/ritsu/src_files/static_library_cmake_lists.rb +40 -0
  25. data/lib/ritsu/src_files/target_cmake_lists.rb +159 -0
  26. data/lib/ritsu/src_files/templated_src_file.rb +44 -0
  27. data/lib/ritsu/src_files.rb +14 -0
  28. data/lib/ritsu/target.rb +134 -0
  29. data/lib/ritsu/targets/executable.rb +45 -0
  30. data/lib/ritsu/targets/library.rb +29 -0
  31. data/lib/ritsu/targets/shared_library.rb +39 -0
  32. data/lib/ritsu/targets/static_library.rb +33 -0
  33. data/lib/ritsu/targets.rb +4 -0
  34. data/lib/ritsu/template.rb +69 -0
  35. data/lib/ritsu/template_policies.rb +133 -0
  36. data/lib/ritsu/test_helpers.rb +124 -0
  37. data/lib/ritsu/thors/default_thor.rb +57 -0
  38. data/lib/ritsu/thors.rb +1 -0
  39. data/lib/ritsu/utility/accessors.rb +30 -0
  40. data/lib/ritsu/utility/check_upon_add_set.rb +35 -0
  41. data/lib/ritsu/utility/file_robot.rb +129 -0
  42. data/lib/ritsu/utility/files.rb +13 -0
  43. data/lib/ritsu/utility/instance_dependencies.rb +113 -0
  44. data/lib/ritsu/utility/instance_set.rb +29 -0
  45. data/lib/ritsu/utility/platform.rb +21 -0
  46. data/lib/ritsu/utility/simple_io.rb +65 -0
  47. data/lib/ritsu/utility/single_instance.rb +34 -0
  48. data/lib/ritsu/utility/strings.rb +41 -0
  49. data/lib/ritsu/utility.rb +8 -0
  50. data/lib/ritsu.rb +17 -0
  51. data/test/ritsu/block_test.rb +197 -0
  52. data/test/ritsu/external_library_test.rb +42 -0
  53. data/test/ritsu/project_generators/default_generator_test.rb +34 -0
  54. data/test/ritsu/project_test.rb +128 -0
  55. data/test/ritsu/src_file_test.rb +70 -0
  56. data/test/ritsu/src_files/cpp_file_test.rb +43 -0
  57. data/test/ritsu/src_files/executable_cmake_lists_test.rb +52 -0
  58. data/test/ritsu/src_files/header_file_test.rb +58 -0
  59. data/test/ritsu/src_files/project_cmake_lists_test.rb +152 -0
  60. data/test/ritsu/src_files/shared_library_cmake_lists_test.rb +52 -0
  61. data/test/ritsu/src_files/static_library_cmake_lists_test.rb +52 -0
  62. data/test/ritsu/src_files/target_cmake_lists_test.rb +16 -0
  63. data/test/ritsu/target_test.rb +106 -0
  64. data/test/ritsu/targets/executable_test.rb +11 -0
  65. data/test/ritsu/targets/shared_library_test.rb +11 -0
  66. data/test/ritsu/targets/static_library_test.rb +11 -0
  67. data/test/ritsu/template_policies_test.rb +0 -0
  68. data/test/ritsu/utility/accessors_test.rb +15 -0
  69. data/test/ritsu/utility/check_upon_add_set_test.rb +32 -0
  70. data/test/ritsu/utility/file_robot_test.rb +176 -0
  71. data/test/ritsu/utility/strings_test.rb +29 -0
  72. data/test/test_helpers.rb +4 -0
  73. metadata +209 -0
@@ -0,0 +1,159 @@
1
+ require File.dirname(__FILE__) + '/../src_file'
2
+ require File.dirname(__FILE__) + '/../utility/instance_set'
3
+ require File.dirname(__FILE__) + '/../template'
4
+ require File.dirname(__FILE__) + '/../template_policies'
5
+ require File.dirname(__FILE__) + '/../src_files/templated_src_file'
6
+
7
+ module Ritsu
8
+ module SrcFiles
9
+ class TargetCmakeLists < Ritsu::SrcFiles::TemplatedSrcFile
10
+ class LibrariesTemplate < Ritsu::Template
11
+ attr_accessor :target
12
+
13
+ def initialize(target)
14
+ super("TargetCmakeLists -- #{target.name} -- Libraries")
15
+ @target = target
16
+ end
17
+
18
+ def update_block(block, options = {})
19
+ external_libraries = target.dependency_libraries.to_a
20
+ external_libraries.sort! {|x,y| x.name <=> y.name}
21
+
22
+ dependency_targets = target.dependency_targets.to_a
23
+ dependency_targets.sort! {|x,y| x.name <=> y.name}
24
+
25
+ block.contents.clear
26
+ external_libraries.each do |external_library|
27
+ block.contents << external_library.cmake_depend_script
28
+ end
29
+ dependency_targets.each do |dependency_target|
30
+ if dependency_target.cmake_depend_script.strip.length > 0
31
+ block.contents << dependency_target.cmake_depend_script
32
+ end
33
+ end
34
+
35
+ if target.library?
36
+ if target.cmake_depend_script.strip.length > 0
37
+ block.contents << target.cmake_depend_script
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ class CustomCommandsTemplate < Ritsu::Template
44
+ attr_accessor :target
45
+
46
+ def initialize(target)
47
+ super("TargetCmakeLists -- #{target.name} -- Custom Commands")
48
+ @target = target
49
+ end
50
+
51
+ def update_block(block, options = {})
52
+ block.contents.clear
53
+ target.custom_commands.each do |custom_command|
54
+ block.contents << custom_command.to_s
55
+ end
56
+ end
57
+ end
58
+
59
+ class SourceFilesTemplate < Ritsu::Template
60
+ attr_accessor :target
61
+
62
+ def initialize(target)
63
+ super("TargetCmakeLists -- #{target.name} -- Source Files")
64
+ @target = target
65
+ end
66
+
67
+ def src_files_var_name
68
+ target.name.upcase + "_SRC_FILES"
69
+ end
70
+
71
+ def update_block(block, options = {})
72
+ block.contents.clear
73
+ block.contents << "SET(#{src_files_var_name}"
74
+
75
+ src_files = target.src_files.to_a
76
+ src_files.sort! {|x,y| x.src_path <=> y.src_path}
77
+ src_files.each do |src_file|
78
+ block.contents << " ${CMAKE_SOURCE_DIR}/#{src_file.src_path}" if src_file.include_in_cmake?
79
+ end
80
+
81
+ block.contents << ")"
82
+ end
83
+ end
84
+
85
+ class DependenciesTemplate < Ritsu::Template
86
+ attr_reader :target
87
+
88
+ def initialize(target)
89
+ super("TargetCmakeLists -- #{target.name} -- Dependencies")
90
+ @target = target
91
+ end
92
+
93
+ def update_block(block, options = {})
94
+ block.contents.clear
95
+
96
+ external_libraries = target.dependency_libraries.to_a
97
+ external_libraries.sort! {|x,y| x.name <=> y.name}
98
+ dependency_targets = target.dependency_targets.to_a
99
+ dependency_targets.sort! {|x,y| x.name <=> y.name}
100
+
101
+ if external_libraries.length == 0 && dependency_targets.length == 0
102
+ return
103
+ end
104
+
105
+ block.contents << "TARGET_LINK_LIBRARIES(#{target.name}"
106
+
107
+ external_libraries.each do |external_library|
108
+ block.contents << " " + external_library.cmake_name
109
+ end
110
+
111
+ dependency_targets.each do |dependency_target|
112
+ block.contents << " " + dependency_target.name
113
+ end
114
+
115
+ block.contents << ")"
116
+ end
117
+ end
118
+
119
+ class Template < Ritsu::Template
120
+ include Ritsu::TemplatePolicies::FlexibleBlockMatchingAndCreateMissingBlockButLeaveUserTextBe
121
+ attr_reader :target
122
+ attr_reader :libraries_template
123
+ attr_reader :custom_commands_template
124
+ attr_reader :source_files_template
125
+ attr_reader :dependencies_template
126
+
127
+ def initialize(target, id = nil)
128
+ super(id)
129
+ @target = target
130
+
131
+ @libraries_template = LibrariesTemplate.new(@target)
132
+ contents << @libraries_template
133
+ contents << ""
134
+
135
+ @custom_commands_template = CustomCommandsTemplate.new(@target)
136
+ contents << @custom_commands_template
137
+ contents << ""
138
+
139
+ @source_files_template = SourceFilesTemplate.new(@target)
140
+ contents << @source_files_template
141
+ contents << ""
142
+
143
+ @dependencies_template = DependenciesTemplate.new(@target)
144
+ contents << @dependencies_template
145
+ end
146
+ end
147
+
148
+ def initialize(target)
149
+ super("#{target.name}/CMakeLists.txt", target,
150
+ :block_start_prefix=>'##<<',
151
+ :block_end_prefix=>'##>>')
152
+ end
153
+
154
+ def include_in_cmake?
155
+ false
156
+ end
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,44 @@
1
+ require File.dirname(__FILE__) + '/../src_file'
2
+ require File.dirname(__FILE__) + '/../utility/file_robot'
3
+ require File.dirname(__FILE__) + '/../block'
4
+ require File.dirname(__FILE__) + '/../utility/files'
5
+
6
+ module Ritsu::SrcFiles
7
+ class TemplatedSrcFile < Ritsu::SrcFile
8
+ attr_accessor :template
9
+ attr_accessor :block_start_prefix
10
+ attr_accessor :block_end_prefix
11
+
12
+ def initialize(src_path, owner, options={})
13
+ super(src_path, owner)
14
+
15
+ options = {
16
+ :block_start_prefix => "//<<",
17
+ :block_end_prefix => "//>>"
18
+ }.merge(options)
19
+ @block_start_prefix = options[:block_start_prefix]
20
+ @block_end_prefix = options[:block_end_prefix]
21
+ end
22
+
23
+ def create
24
+ block = template.create_block(
25
+ :block_start_prefix => block_start_prefix,
26
+ :block_end_prefix => block_end_prefix)
27
+ template.update_block(block)
28
+ Ritsu::Utility::FileRobot.create_file(abs_path, block.to_s(:no_delimiter=>true) + "\n")
29
+ end
30
+
31
+ def update_content
32
+ file_content = Ritsu::Utility::Files.read(abs_path)
33
+ block = Ritsu::Block.parse(file_content,
34
+ :block_start_prefix => block_start_prefix,
35
+ :block_end_prefix => block_end_prefix)
36
+ template.update_block(block)
37
+
38
+ new_content = block.to_s(:no_delimiter=>true) + "\n"
39
+ if new_content != file_content
40
+ Ritsu::Utility::FileRobot.create_file(abs_path, new_content)
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,14 @@
1
+ require File.dirname(__FILE__) + '/src_files/project_cmake_lists'
2
+
3
+ require File.dirname(__FILE__) + '/src_files/templated_src_file'
4
+
5
+ require File.dirname(__FILE__) + '/src_files/cpp_file_mixin'
6
+ require File.dirname(__FILE__) + '/src_files/cpp_file'
7
+ require File.dirname(__FILE__) + '/src_files/header_file_mixin'
8
+ require File.dirname(__FILE__) + '/src_files/header_file'
9
+ require File.dirname(__FILE__) + '/src_files/target_cmake_lists'
10
+ require File.dirname(__FILE__) + '/src_files/executable_cmake_lists'
11
+ require File.dirname(__FILE__) + '/src_files/shared_library_cmake_lists'
12
+ require File.dirname(__FILE__) + '/src_files/static_library_cmake_lists'
13
+ require File.dirname(__FILE__) + '/src_files/project_config_header_file'
14
+ require File.dirname(__FILE__) + '/src_files/project_config_header_template_file'
@@ -0,0 +1,134 @@
1
+ require 'rubygems'
2
+ require 'active_support'
3
+ require 'set'
4
+ require 'pathname'
5
+ require File.dirname(__FILE__) + '/utility/instance_set'
6
+ require File.dirname(__FILE__) + '/utility/strings'
7
+ require File.dirname(__FILE__) + '/project'
8
+ require File.dirname(__FILE__) + '/utility/check_upon_add_set'
9
+ require File.dirname(__FILE__) + '/external_library'
10
+ require File.dirname(__FILE__) + '/utility/instance_dependencies'
11
+
12
+ module Ritsu
13
+ class Target
14
+ include Ritsu::Utility::InstanceSet
15
+ include Ritsu::Utility::InstanceDependencies
16
+ include Ritsu::Utility::Strings
17
+
18
+ dependencies_between :targets
19
+
20
+ attr_reader :name
21
+ attr_reader :dependency_libraries
22
+ attr_reader :project
23
+ attr_reader :src_files
24
+ attr_reader :custom_commands
25
+ attr_accessor :topological_order
26
+
27
+ def initialize(name, options={})
28
+ options = {:project => Ritsu::Project.instance}.merge(options)
29
+
30
+ if !is_c_name?(name)
31
+ raise ArgumentError.new(
32
+ "target name must be a valid C name")
33
+ end
34
+
35
+ @name = name
36
+ @dependency_libraries = Set.new
37
+ @project = options[:project]
38
+ @src_files = Set.new
39
+ @custom_commands = []
40
+ @topological_order = 0
41
+
42
+ Target.instances << self
43
+ @project.targets << self
44
+ end
45
+
46
+ def self.validate_instance(instance)
47
+ if instances.select { |x| x.name == instance.name }.length > 1
48
+ raise "target with name '#{instance.name}' already exists"
49
+ end
50
+ end
51
+
52
+ def src_dir
53
+ self.name
54
+ end
55
+
56
+ def abs_dir
57
+ File.expand_path(project.project_dir + "src/#{src_dir}")
58
+ end
59
+
60
+ def compute_src_path(path, options={})
61
+ options = {:relative_to => :target}.merge(options)
62
+
63
+ case options[:relative_to]
64
+ when :target
65
+ self.src_dir + "/" + path
66
+ when :src
67
+ path
68
+ when :absolute
69
+ src_dir = Pathname.new(project.src_dir)
70
+ input_path = Pathname.new(path)
71
+ input_path.relative_path_from(src_dir).to_s
72
+ else
73
+ raise ArgumentError.new("option :relative_to must be one of :target, :src, and :absolute")
74
+ end
75
+ end
76
+
77
+ def include_file(filename, options={})
78
+ file_content = Ritsu::Utility::Files.read(filename)
79
+ instance_eval(file_content)
80
+ end
81
+
82
+ def update
83
+ src_files.each do |src_file|
84
+ src_file.update
85
+ end
86
+ end
87
+
88
+ def self.find_by_name(name)
89
+ instances.each do |instance|
90
+ if instance.name == name
91
+ return instance
92
+ end
93
+ end
94
+ return nil
95
+ end
96
+
97
+ def add_external_library(name)
98
+ external_library = Ritsu::ExternalLibrary.find_by_name(name.to_s)
99
+ if !external_library.nil?
100
+ dependency_libraries << external_library
101
+ else
102
+ raise ArgumentError.new("no external library with name '#{name}'")
103
+ end
104
+ end
105
+
106
+ def add_dependency_target(target_or_target_name)
107
+ if target_or_target_name.kind_of?(String)
108
+ dependency = Target.find_by_name(target_or_target_name)
109
+ if dependency.nil?
110
+ raise ArgumentError.new("no target with name '#{name}'")
111
+ end
112
+ else
113
+ dependency = target_or_target_name
114
+ end
115
+ dependency_targets << dependency
116
+ end
117
+
118
+ def dependency_targets_sorted_by_topological_order
119
+ Target.compute_topological_orders
120
+ result = dependency_targets.to_a
121
+ result.sort! {|x,y| x.topological_order - y.topological_order}
122
+ result
123
+ end
124
+ end
125
+
126
+ class Project
127
+ def targets_sorted_by_topological_order
128
+ Target.compute_topological_orders
129
+ result = targets.to_a
130
+ result.sort! {|x,y| x.topological_order - y.topological_order}
131
+ result
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,45 @@
1
+ require 'rubygems'
2
+ require 'active_support'
3
+ require File.dirname(__FILE__) + '/../target'
4
+ require File.dirname(__FILE__) + '/../utility/instance_set'
5
+ require File.dirname(__FILE__) + '/../src_files/executable_cmake_lists'
6
+
7
+ module Ritsu::Targets
8
+ class Executable < Ritsu::Target
9
+ attr_reader :cmake_lists
10
+
11
+ def initialize(name, options={})
12
+ super(name, options)
13
+ @cmake_lists = Ritsu::SrcFiles::ExecutableCmakeLists.new(self)
14
+ end
15
+
16
+ def can_be_depended_on?
17
+ false
18
+ end
19
+
20
+ def executable?
21
+ true
22
+ end
23
+
24
+ def shared_library?
25
+ false
26
+ end
27
+
28
+ def static_library?
29
+ false
30
+ end
31
+
32
+ def library?
33
+ false
34
+ end
35
+ end
36
+ end
37
+
38
+ module Ritsu
39
+ class Project
40
+ def add_executable(name)
41
+ executable = Ritsu::Targets::Executable.new(name, :project=>self)
42
+ yield executable if block_given?
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,29 @@
1
+ require File.dirname(__FILE__) + "/../target"
2
+ require File.dirname(__FILE__) + "/../utility/accessors"
3
+
4
+ module Ritsu::Targets
5
+ class Library < Ritsu::Target
6
+ include Ritsu::Utility::Accessors
7
+
8
+ attr_accessor :cmake_depend_script
9
+ attr_method :cmake_depend_script
10
+
11
+ def initialize(name, options={})
12
+ options = {:cmake_depend_script => ""}.merge(options)
13
+ super(name, options)
14
+ @cmake_depend_script = options[:cmake_depend_script]
15
+ end
16
+
17
+ def can_be_depended_on?
18
+ true
19
+ end
20
+
21
+ def executable?
22
+ false
23
+ end
24
+
25
+ def library?
26
+ true
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,39 @@
1
+ require 'rubygems'
2
+ require 'active_support'
3
+ require File.dirname(__FILE__) + '/library'
4
+ require File.dirname(__FILE__) + '/../utility/instance_set'
5
+ require File.dirname(__FILE__) + '/../src_files/shared_library_cmake_lists'
6
+
7
+ module Ritsu::Targets
8
+ class SharedLibrary < Ritsu::Targets::Library
9
+ attr_reader :cmake_lists
10
+
11
+ def initialize(name, options={})
12
+ super(name, options)
13
+ initialize_cmake_lists
14
+ end
15
+
16
+ protected
17
+ def initialize_cmake_lists
18
+ @cmake_lists = Ritsu::SrcFiles::SharedLibraryCmakeLists.new(self)
19
+ end
20
+
21
+ public
22
+ def shared_library?
23
+ true
24
+ end
25
+
26
+ def static_library?
27
+ false
28
+ end
29
+ end
30
+ end
31
+
32
+ module Ritsu
33
+ class Project
34
+ def add_shared_library(name)
35
+ shared_library = Ritsu::Targets::SharedLibrary.new(name, :project=>self)
36
+ yield shared_library if block_given?
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,33 @@
1
+ require 'rubygems'
2
+ require 'active_support'
3
+ require File.dirname(__FILE__) + '/library'
4
+ require File.dirname(__FILE__) + '/../utility/instance_set'
5
+ require File.dirname(__FILE__) + '/../src_files/static_library_cmake_lists'
6
+
7
+ module Ritsu::Targets
8
+ class StaticLibrary < Ritsu::Targets::Library
9
+ attr_reader :cmake_lists
10
+
11
+ def initialize(name, options={})
12
+ super(name, options)
13
+ @cmake_lists = Ritsu::SrcFiles::StaticLibraryCmakeLists.new(self)
14
+ end
15
+
16
+ def shared_library?
17
+ false
18
+ end
19
+
20
+ def static_library?
21
+ true
22
+ end
23
+ end
24
+ end
25
+
26
+ module Ritsu
27
+ class Project
28
+ def add_static_library(name)
29
+ static_library = Ritsu::Targets::StaticLibrary.new(name, :project=>self)
30
+ yield static_library if block_given?
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,4 @@
1
+ require File.dirname(__FILE__) + '/targets/executable'
2
+ require File.dirname(__FILE__) + '/targets/library'
3
+ require File.dirname(__FILE__) + '/targets/static_library'
4
+ require File.dirname(__FILE__) + '/targets/shared_library'
@@ -0,0 +1,69 @@
1
+ require File.dirname(__FILE__) + '/block'
2
+
3
+ module Ritsu
4
+ class Template
5
+ include BlockMixin
6
+
7
+ def initialize(id = nil, options = {})
8
+ initialize_block_mixin(id, options)
9
+ end
10
+
11
+ ##
12
+ # @return (Template) the first child template with the given ID.
13
+ # nil if there is no such child template.
14
+ def child_template_with_id(id)
15
+ contents.each do |content|
16
+ if content.kind_of?(Template) and content.id == id
17
+ return content
18
+ end
19
+ end
20
+ return nil
21
+ end
22
+
23
+ ##
24
+ # @return (Template) the position of the child template with the given ID in the contents array.
25
+ # nil if there is no such child template.
26
+ def child_template_with_id_position(id)
27
+ contents.length.times do |i|
28
+ if contents[i].kind_of?(Template) and contents[i].id == id
29
+ return i
30
+ end
31
+ end
32
+ return nil
33
+ end
34
+
35
+ def child_templates
36
+ contents.select {|x| x.kind_of?(Template)}
37
+ end
38
+
39
+ def create_block(options={})
40
+ options = {}.merge(options)
41
+ options[:local_indentation] = local_indentation
42
+ block = Block.new(id, options)
43
+ contents.each do |content|
44
+ if !content.kind_of?(Template)
45
+ block.contents << content
46
+ else
47
+ block.contents << content.create_block(options)
48
+ end
49
+ end
50
+ block
51
+ end
52
+
53
+ def update_block(block, options={})
54
+ raise NotImplmentedError.new
55
+ end
56
+
57
+ def add_template(template)
58
+ add_block_structure(template)
59
+ end
60
+
61
+ def add_content(content)
62
+ if content.kind_of?(Template)
63
+ add_template(content)
64
+ else
65
+ add_line_or_other_content(content)
66
+ end
67
+ end
68
+ end
69
+ end