simple-make 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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