simple-make 0.0.1 → 0.0.2

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.
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'rake'
4
+ gem 'rspec'
5
+ gem 'simple-make', :path => "."
data/Gemfile.lock ADDED
@@ -0,0 +1,26 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ simple-make (0.0.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ diff-lcs (1.1.3)
10
+ rake (10.1.0)
11
+ rspec (2.8.0)
12
+ rspec-core (~> 2.8.0)
13
+ rspec-expectations (~> 2.8.0)
14
+ rspec-mocks (~> 2.8.0)
15
+ rspec-core (2.8.0)
16
+ rspec-expectations (2.8.0)
17
+ diff-lcs (~> 1.1.2)
18
+ rspec-mocks (2.8.0)
19
+
20
+ PLATFORMS
21
+ ruby
22
+
23
+ DEPENDENCIES
24
+ rake
25
+ rspec
26
+ simple-make!
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'rake'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec) do |t|
5
+ t.rspec_opts = "--tag ~not_on_ci"
6
+ end
7
+
8
+ task :default => :spec
data/bin/sm CHANGED
@@ -1,10 +1,11 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'simple-make'
4
+ require 'simple-make/cli'
4
5
 
5
6
  raise "Cannot find the build file <build.sm>" if !File.exist?("build.sm")
6
7
 
7
8
  configuration = File.open("build.sm").read
8
- project = Project.new
9
+ project = Cli.new.create_project ARGV
9
10
  project.instance_eval(configuration)
10
11
  project.generate_make_file
@@ -0,0 +1,19 @@
1
+ require "simple-make/project"
2
+ require "simple-make/std_logger"
3
+ require "optparse"
4
+
5
+ class Cli
6
+ def create_project args
7
+ options = {workspace: File.absolute_path(".")}
8
+ parser = OptionParser.new do |opts|
9
+ opts.on("--relative-path") do
10
+ options[:path_mode] = :relative
11
+ end
12
+ opts.on("-v") do
13
+ $std_logger.level = Logger::DEBUG
14
+ end
15
+ end
16
+ parser.parse(args)
17
+ Project.new options
18
+ end
19
+ end
@@ -1,10 +1,14 @@
1
+ require "simple-make/path_helper"
2
+
1
3
  class Dependency
4
+ include PathHelper
2
5
  attr_reader :include, :scope
3
- def initialize map
6
+
7
+ def initialize map, path_mode = :absolute
4
8
  raise wrong_format_msg(map) if !(map.is_a? Hash) or map[:include].nil? or map[:lib].nil?
5
9
 
6
- @include = File.absolute_path(map[:include])
7
- @lib = File.absolute_path(map[:lib])
10
+ @include = get_path(path_mode, map[:include])
11
+ @lib = get_path(path_mode, map[:lib])
8
12
  @scope = map[:scope] || :compile
9
13
  end
10
14
 
@@ -0,0 +1,38 @@
1
+ class DependencyProject
2
+ attr_reader :scope
3
+
4
+ def initialize project, options
5
+ @project = project
6
+ @relative_path = options[:relative_path]
7
+ @scope = options[:scope] || :compile
8
+ end
9
+
10
+ def package_command
11
+ make_command("package")
12
+ end
13
+
14
+ def test_command
15
+ make_command("test")
16
+ end
17
+
18
+ def package_file
19
+ "#{@relative_path}/#{@project.package_file}"
20
+ end
21
+
22
+ def export_search_path_flag
23
+ @project.prod_time_search_path_flag
24
+ end
25
+
26
+ def output_path
27
+ "#{@relative_path}/#{@project.output_path}/*"
28
+ end
29
+
30
+ def generate_make_file
31
+ @project.generate_make_file
32
+ end
33
+
34
+ private
35
+ def make_command(string)
36
+ "make -C #{@relative_path} #{string}"
37
+ end
38
+ end
@@ -1,11 +1,12 @@
1
1
  class DirTraverser
2
- def self.all_files_in_absolute_path base, found=[]
2
+ def self.all_files_in_path base, found=[]
3
+ return [] if !File.exist? base
3
4
  Dir.foreach(base) do |each|
4
5
  next if(each == "." || each == "..")
5
6
 
6
7
  full_name = base + "/" +each
7
8
  if File.directory? full_name
8
- all_files_in_absolute_path(full_name, found)
9
+ all_files_in_path(full_name, found)
9
10
  else
10
11
  found << full_name
11
12
  end
@@ -13,14 +14,15 @@ class DirTraverser
13
14
  found
14
15
  end
15
16
 
16
- def self.all_folders_in_absolute_path base, found=[]
17
+ def self.all_folders_in_path base, found=[]
18
+ return [] if !File.exist? base
17
19
  Dir.foreach(base) do |each|
18
20
  next if(each == "." || each == "..")
19
21
 
20
22
  full_name = base + "/" +each
21
23
  if File.directory? full_name
22
24
  found << full_name
23
- all_folders_in_absolute_path(full_name, found)
25
+ all_folders_in_path(full_name, found)
24
26
  end
25
27
  end
26
28
  found
@@ -0,0 +1,31 @@
1
+ require "simple-make/std_logger"
2
+ require "simple-make/template"
3
+ require "erb"
4
+
5
+ class NormalMakefileMaker
6
+ def initialize project, context, template = "makefile"
7
+ @project = project
8
+ @makefile_template = template
9
+ @context = context
10
+ end
11
+
12
+ def generate_make_file
13
+ $std_logger.debug "generating makefile for project #{@project.name} and its deps"
14
+ generate_makefile_for_dep_project
15
+ generate_make_file_for_current_project
16
+ end
17
+
18
+ def generate_makefile_for_dep_project
19
+ $std_logger.debug "generating makefile for dep projects"
20
+ $std_logger.debug "projects: #{@project.dep_projects}"
21
+ @project.dep_projects.each(&:generate_make_file)
22
+ end
23
+
24
+ def generate_make_file_for_current_project
25
+ $std_logger.debug "generating makefile for project #{@project.name}"
26
+ makefile = ERB.new(Template.template_content(@makefile_template))
27
+ File.open("#{@project.workspace}/#{@project.makefile_name}", "w") do |f|
28
+ f.write makefile.result(@context)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,11 @@
1
+ require "simple-make/package_type/package"
2
+
3
+ class ArchivePackage < Package
4
+ def initialize project
5
+ super(project, "archive")
6
+ end
7
+
8
+ def package_file
9
+ "#{@project.output_path}/lib#{@project.name}.a"
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ require "simple-make/package_type/package"
2
+
3
+ class ExecutablePackage < Package
4
+ def initialize project
5
+ super(project, "executable")
6
+ end
7
+
8
+ def package_file
9
+ "#{@project.output_path}/#{@project.name}"
10
+ end
11
+ end
@@ -0,0 +1,25 @@
1
+ require "simple-make/template"
2
+
3
+ class Package
4
+ def initialize project, template_name
5
+ @project = project
6
+ @template_name = template_name
7
+ end
8
+
9
+ def package_file
10
+ raise "not implemented, use subtype!"
11
+ end
12
+
13
+ def pack_deps_command
14
+ package = ERB.new(Template.template_content("#{@template_name}_package"))
15
+ package.result(binding)
16
+ end
17
+
18
+ def pack_dep_project_commands
19
+ @project.dep_projects.map(&:package_command).join("\n\t")
20
+ end
21
+
22
+ def dep_projects_output_names
23
+ @project.dep_projects.map(&:package_file).join(" ")
24
+ end
25
+ end
@@ -0,0 +1,9 @@
1
+ require "simple-make/package_type/archive_package"
2
+ require "simple-make/package_type/executable_package"
3
+
4
+ class PackageFactory
5
+ def self.create_by_type type, project
6
+ return ArchivePackage.new(project) if type == :archive
7
+ return ExecutablePackage.new(project) if type == :executable
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ module PathHelper
2
+ def get_path(path_mode, var)
3
+ path_mode == :absolute ? File.absolute_path(var) : var
4
+ end
5
+ end
@@ -1,67 +1,91 @@
1
1
  require "simple-make/dependency"
2
2
  require "simple-make/search_path"
3
3
  require "simple-make/dir_traverser"
4
- require "erb"
4
+ require "simple-make/path_helper"
5
+ require "simple-make/project_factory"
6
+ require "simple-make/std_logger"
7
+ require "simple-make/template"
8
+ require "simple-make/normal_makefile_maker"
9
+ require "simple-make/root_makefile_maker"
10
+ require "simple-make/package_type/package_factory"
5
11
 
6
12
  class Project
7
- attr_writer :name
13
+ include PathHelper
14
+ attr_accessor :name, :src_suffix, :app_path, :test_path, :prod_path, :output_path, :compile_command_with_flag, :link, :source_folder_name
15
+ attr_reader :dep_projects, :workspace, :makefile_name
8
16
 
9
- def initialize(name=nil)
10
- @name = name || default_name
17
+ def initialize(options = {})
18
+ @workspace = options[:workspace] || File.absolute_path(".")
19
+ @name = @workspace.split("/").last
11
20
  @app_path = "app"
12
21
  @test_path = "test"
13
22
  @prod_path = "prod"
14
23
  @output_path = "build"
15
24
  @source_folder_name = "src"
16
25
  @deps = []
26
+ @dep_projects = []
17
27
  @includes = []
18
- @cc = "g++ -O0 -g3 -Wall"
19
- @link = "g++"
28
+ @compile_command_with_flag = "g++ -O0 -g3 -Wall"
29
+ @link_command_with_flag = "g++"
30
+ @src_suffix = "cc"
31
+ @path_mode = options[:path_mode] || :absolute
32
+ self.package_type = :executable
33
+ @makefile_name = options[:makefile] || "Makefile"
34
+ @makefile_maker = NormalMakefileMaker.new(self, binding)
20
35
  end
21
36
 
22
- def default_name
23
- File.absolute_path(".").split("/").last
37
+ def root_project
38
+ @makefile_maker = RootMakefileMaker.new(self, binding)
24
39
  end
25
40
 
26
- def depend_on(*deps)
27
- raise "depend_on only accept array of dependencies, use [] to wrap your dependency if there is only one" if !(deps.is_a? Array)
28
- @deps += deps.map{|depHash| Dependency.new(depHash)}
41
+ def package_type= type
42
+ @package = PackageFactory.create_by_type(type, self)
29
43
  end
30
44
 
31
- def srcs
32
- all_sources_in(@app_path)
45
+ def depend_on(*deps)
46
+ within_workspace do
47
+ @deps += deps.map{|depHash| Dependency.new(depHash, @path_mode)}
48
+ end
33
49
  end
34
50
 
35
- def test_srcs
36
- all_sources_in(@test_path)
51
+ def depend_on_project(*projects)
52
+ within_workspace do
53
+ @dep_projects += projects.map{|params| ProjectFactory.create_from_relative_path(params)}
54
+ end
37
55
  end
38
56
 
39
- def prod_srcs
40
- all_sources_in(@prod_path)
57
+ def header_search_path *paths
58
+ within_workspace do
59
+ @includes += paths.map{|path| SearchPath.new(path, @path_mode)}
60
+ end
41
61
  end
42
62
 
43
63
  def sub_folders_in_target_folder
44
- (all_output_dirs_related_to(@app_path) + all_output_dirs_related_to(@prod_path) + all_output_dirs_related_to(@test_path)).join(" \\\n")
64
+ folders = []
65
+ {"app" => @app_path, "prod" => @prod_path, "test" => @test_path}.each_pair do |k,v|
66
+ folders += all_output_dirs_related_to(k, v)
67
+ end
68
+ folders.map{|raw| "#{@output_path}/#{raw}"}.join(" \\\n")
45
69
  end
46
70
 
47
- def header_search_path *paths
48
- raise "search path only accept array of paths, use [] to wrap your search paths if there is only one" if !(paths.is_a? Array)
49
- @includes += paths.map{|path| SearchPath.new(path)}
71
+ def generate_make_file
72
+ @makefile_maker.generate_make_file
50
73
  end
51
74
 
52
- def compile_command_with_flag cc
53
- @cc = cc
75
+ def package_file
76
+ @package.package_file
54
77
  end
55
78
 
56
- def link_command_with_flag link
57
- @link = link
79
+ def pack_dep_project_commands
80
+ @package.pack_dep_project_commands
58
81
  end
59
82
 
60
- def generate_make_file(filename = "Makefile")
61
- makefile = ERB.new(File.open(File.expand_path(File.dirname(__FILE__) + "/../../template/makefile.erb")).read)
62
- File.open(filename, "w") do |f|
63
- f.write makefile.result(binding)
64
- end
83
+ def package_part
84
+ @package.pack_deps_command
85
+ end
86
+
87
+ def run_test_on_deps
88
+ @dep_projects.map(&:test_command).join("\n\t")
65
89
  end
66
90
 
67
91
  [:compile, :test, :prod].each do |scope|
@@ -69,6 +93,11 @@ class Project
69
93
  return search_path_flag(:compile) if scope == :compile
70
94
  search_path_flag(:compile, scope)
71
95
  end
96
+
97
+ define_method("#{scope}_time_srcs") do
98
+ scope = :app if scope == :compile
99
+ all_sources_in(send("#{scope}_path"))
100
+ end
72
101
  end
73
102
 
74
103
  [:test, :prod].each do |scope|
@@ -80,15 +109,31 @@ class Project
80
109
  lib_name_flag(:compile, scope)
81
110
  end
82
111
  end
112
+
113
+ def dep_projects_output_path
114
+ @dep_projects.map(&:output_path).join(" ")
115
+ end
116
+
83
117
  private
84
- def all_output_dirs_related_to(base)
85
- (DirTraverser.all_folders_in_absolute_path("#{base}/#{@source_folder_name}") << "#{base}/#{@source_folder_name}").map do |origin|
86
- "build/#{origin.sub("/#{@source_folder_name}", "")}"
118
+ def all_output_dirs_related_to(scope, base)
119
+ within_workspace do
120
+ File.exist?(base) ?
121
+ (DirTraverser.all_folders_in_path("#{base}/#{@source_folder_name}")).map do |origin|
122
+ scope + origin.sub("#{base}/#{@source_folder_name}", "")
123
+ end << scope : []
87
124
  end
88
125
  end
89
126
 
90
127
  def all_sources_in(base)
91
- DirTraverser.all_files_in_absolute_path("#{base}/#{@source_folder_name}").join(" \\\n")
128
+ within_workspace {DirTraverser.all_files_in_path("#{base}/#{@source_folder_name}").join(" \\\n")}
129
+ end
130
+
131
+ def within_workspace
132
+ ret = ""
133
+ Dir.chdir(@workspace) do
134
+ ret = yield
135
+ end
136
+ ret
92
137
  end
93
138
 
94
139
  def lib_name_flag(*scopes)
@@ -108,11 +153,13 @@ private
108
153
  end
109
154
 
110
155
  def search_path_flag(*scopes)
111
- includes = ["-I#{File.absolute_path(@app_path)}/include"]
156
+ includes = [within_workspace{"-I#{get_path(@path_mode, @app_path)}/include"}]
157
+
112
158
  scopes.each do |scope|
113
159
  ex_includes = @includes.select { |include| include.scope == scope}.map(&:path)
114
160
  ex_includes += @deps.select { |dep| dep.scope == scope}.map(&:include)
115
161
  includes += ex_includes.map { |include| "-I#{include}" }
162
+ includes += @dep_projects.select{|dep_project| dep_project.scope == scope}.map(&:export_search_path_flag)
116
163
  end
117
164
  includes.join(" ")
118
165
  end