simple-make 0.0.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b6aa846b3416f493a8e42e59338a63e74970ea3d
4
+ data.tar.gz: 6cb6ec03baa63adfcfecb0cddd7a1b537cb00767
5
+ SHA512:
6
+ metadata.gz: fb13206f2c96d93171666e77d25940b4adc1633bd745384378b89adca9cdee6dc4da445c7592036c1dcb1d36d274eb9bdfd078ac60c84268f0e3e001746d16f6
7
+ data.tar.gz: 4d58f6d963967b8d6604f74d2b30d0f6ac82b255faa136cb20d5bf8b86d435777b44f72cf16db762bb45a4ccdc6344480d1eb2e0fa2ee7b5e269cb7d37bd86f1
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ .idea
2
+ *.gem
3
+ Makefile
4
+ makefile
data/bin/sm ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'simple-make'
4
+
5
+ raise "Cannot find the build file <build.sm>" if !File.exist?("build.sm")
6
+
7
+ configuration = File.open("build.sm").read
8
+ project = Project.new
9
+ project.instance_eval(configuration)
10
+ project.generate_make_file
@@ -0,0 +1,33 @@
1
+ class Dependency
2
+ attr_reader :include, :scope
3
+ def initialize map
4
+ raise wrong_format_msg(map) if !(map.is_a? Hash) or map[:include].nil? or map[:lib].nil?
5
+
6
+ @include = File.absolute_path(map[:include])
7
+ @lib = File.absolute_path(map[:lib])
8
+ @scope = map[:scope] || :compile
9
+ end
10
+
11
+ def lib_name
12
+ if @lib_name.nil?
13
+ matches = @lib.match /.*\/lib([^\/]*)\.a/
14
+ raise "lib name format is wrong, it should be [libxxx.a]" if matches.nil?
15
+ @lib_name = matches[1]
16
+ raise "lib name format is wrong, it should be [libxxx.a], and the xxx should not be empty" if @lib_name.empty?
17
+ end
18
+ @lib_name
19
+ end
20
+
21
+ def lib_path
22
+ if @lib_path.nil?
23
+ matches = @lib.match /(.*\/)[^\/]*/
24
+ @lib_path = matches[1]
25
+ end
26
+ @lib_path
27
+ end
28
+
29
+ private
30
+ def wrong_format_msg(map)
31
+ "#{map.inspect} is not a map, please present dependencies in format {include: <include_path>, lib: <lib_file_name>}"
32
+ end
33
+ end
@@ -0,0 +1,28 @@
1
+ class DirTraverser
2
+ def self.all_files_in_absolute_path base, found=[]
3
+ Dir.foreach(base) do |each|
4
+ next if(each == "." || each == "..")
5
+
6
+ full_name = base + "/" +each
7
+ if File.directory? full_name
8
+ all_files_in_absolute_path(full_name, found)
9
+ else
10
+ found << full_name
11
+ end
12
+ end
13
+ found
14
+ end
15
+
16
+ def self.all_folders_in_absolute_path base, found=[]
17
+ Dir.foreach(base) do |each|
18
+ next if(each == "." || each == "..")
19
+
20
+ full_name = base + "/" +each
21
+ if File.directory? full_name
22
+ found << full_name
23
+ all_folders_in_absolute_path(full_name, found)
24
+ end
25
+ end
26
+ found
27
+ end
28
+ end
@@ -0,0 +1,119 @@
1
+ require "simple-make/dependency"
2
+ require "simple-make/search_path"
3
+ require "simple-make/dir_traverser"
4
+ require "erb"
5
+
6
+ class Project
7
+ attr_writer :name
8
+
9
+ def initialize(name=nil)
10
+ @name = name || default_name
11
+ @app_path = "app"
12
+ @test_path = "test"
13
+ @prod_path = "prod"
14
+ @output_path = "build"
15
+ @source_folder_name = "src"
16
+ @deps = []
17
+ @includes = []
18
+ @cc = "g++ -O0 -g3 -Wall"
19
+ @link = "g++"
20
+ end
21
+
22
+ def default_name
23
+ File.absolute_path(".").split("/").last
24
+ end
25
+
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)}
29
+ end
30
+
31
+ def srcs
32
+ all_sources_in(@app_path)
33
+ end
34
+
35
+ def test_srcs
36
+ all_sources_in(@test_path)
37
+ end
38
+
39
+ def prod_srcs
40
+ all_sources_in(@prod_path)
41
+ end
42
+
43
+ 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")
45
+ end
46
+
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)}
50
+ end
51
+
52
+ def compile_command_with_flag cc
53
+ @cc = cc
54
+ end
55
+
56
+ def link_command_with_flag link
57
+ @link = link
58
+ end
59
+
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
65
+ end
66
+
67
+ [:compile, :test, :prod].each do |scope|
68
+ define_method("#{scope}_time_search_path_flag") do
69
+ return search_path_flag(:compile) if scope == :compile
70
+ search_path_flag(:compile, scope)
71
+ end
72
+ end
73
+
74
+ [:test, :prod].each do |scope|
75
+ define_method("#{scope}_time_lib_path_flag") do
76
+ lib_path_flag(:compile, scope)
77
+ end
78
+
79
+ define_method("#{scope}_time_lib_flag") do
80
+ lib_name_flag(:compile, scope)
81
+ end
82
+ end
83
+ 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}", "")}"
87
+ end
88
+ end
89
+
90
+ def all_sources_in(base)
91
+ DirTraverser.all_files_in_absolute_path("#{base}/#{@source_folder_name}").join(" \\\n")
92
+ end
93
+
94
+ def lib_name_flag(*scopes)
95
+ libs_name = []
96
+ scopes.each do |scope|
97
+ @deps.select { |dep| dep.scope == scope}.each{|dep| libs_name << dep.lib_name}
98
+ end
99
+ libs_name.map{|p| "-l#{p}"}.join(" ")
100
+ end
101
+
102
+ def lib_path_flag(*scopes)
103
+ libs_path = []
104
+ scopes.each do |scope|
105
+ @deps.select { |dep| dep.scope == scope}.each{|dep| libs_path << dep.lib_path}
106
+ end
107
+ libs_path.map{|p| "-L#{p}"}.join(" ")
108
+ end
109
+
110
+ def search_path_flag(*scopes)
111
+ includes = ["-I#{File.absolute_path(@app_path)}/include"]
112
+ scopes.each do |scope|
113
+ ex_includes = @includes.select { |include| include.scope == scope}.map(&:path)
114
+ ex_includes += @deps.select { |dep| dep.scope == scope}.map(&:include)
115
+ includes += ex_includes.map { |include| "-I#{include}" }
116
+ end
117
+ includes.join(" ")
118
+ end
119
+ end
@@ -0,0 +1,14 @@
1
+ class SearchPath
2
+ attr_reader :path, :scope
3
+ def initialize map
4
+ raise wrong_format_msg(map) if !(map.is_a? Hash) or map[:path].nil?
5
+
6
+ @path = File.absolute_path(map[:path])
7
+ @scope = map[:scope] || :compile
8
+ end
9
+
10
+ private
11
+ def wrong_format_msg(map)
12
+ "#{map.inspect} is not a map, please present dependencies in format {path: <include_path>, type: <compile/test/prod(external is default value)>}"
13
+ end
14
+ end
@@ -0,0 +1 @@
1
+ require "simple-make/project"
@@ -0,0 +1,65 @@
1
+ #--------------------configurations-----------------
2
+ APP_PATH = <%= @app_path %>
3
+ TEST_PATH = <%= @test_path %>
4
+ PROD_PATH = <%= @prod_path %>
5
+ PROJECT_NAME = <%= @name %>
6
+ OUTPUT_PATH = <%= @output_path %>
7
+ SOURCE_FOLDER_NAME = <%= @source_folder_name %>
8
+
9
+ #--------------------flags-----------------
10
+ DEPS_FLAG = -MMD -MP -MF"$(@:%.o=%.d)"
11
+ CC = <%= @cc %>
12
+ LINK = <%= @link %>
13
+
14
+ #--------------------source files-----------------
15
+ SRCS = <%= srcs %>
16
+ TEST_SRCS = <%= test_srcs %>
17
+ PROD_SRCS = <%= prod_srcs %>
18
+
19
+ #--------------------folders-----------------
20
+
21
+ FOLDERS = <%= sub_folders_in_target_folder%>
22
+
23
+ #--------------------objs-----------------
24
+ OBJS += $(patsubst $(APP_PATH)/$(SOURCE_FOLDER_NAME)/%.cc, $(OUTPUT_PATH)/app/%.o, $(SRCS))
25
+ TEST_OBJS += $(patsubst $(TEST_PATH)/$(SOURCE_FOLDER_NAME)/%.cc, $(OUTPUT_PATH)/test/%.o, $(TEST_SRCS))
26
+ PROD_OBJS += $(patsubst $(PROD_PATH)/$(SOURCE_FOLDER_NAME)/%.cc, $(OUTPUT_PATH)/prod/%.o, $(PROD_SRCS))
27
+
28
+ #--------------------deps-----------------
29
+ DEPS += $(OBJS:.o=.d)
30
+ TEST_DEPS += $(TEST_OBJS:.o=.d)
31
+ PROD_DEPS += $(PROD_OBJS:.o=.d)
32
+ ALL_DEPS = $(DEPS) $(TEST_DEPS) $(PROD_DEPS)
33
+
34
+ #--------------------compile rules-----------------
35
+
36
+ $(TEST_OBJS): $(OUTPUT_PATH)/test/%.o: $(TEST_PATH)/$(SOURCE_FOLDER_NAME)/%.cc
37
+ $(CC) <%= test_time_search_path_flag %> $(DEPS_FLAG) -c -o "$@" "$<"
38
+ $(OBJS): $(OUTPUT_PATH)/app/%.o: $(APP_PATH)/$(SOURCE_FOLDER_NAME)/%.cc
39
+ $(CC) <%= compile_time_search_path_flag %> $(DEPS_FLAG) -c -o "$@" "$<"
40
+ $(PROD_OBJS): $(OUTPUT_PATH)/prod/%.o: $(PROD_PATH)/$(SOURCE_FOLDER_NAME)/%.cc
41
+ $(CC) <%= prod_time_search_path_flag %> $(DEPS_FLAG) -c -o "$@" "$<"
42
+
43
+ #--------------------ut-----------------
44
+ $(OUTPUT_PATH)/$(PROJECT_NAME)_ut: $(OBJS) $(TEST_OBJS)
45
+ $(LINK) -o $(OUTPUT_PATH)/$(PROJECT_NAME)_ut <%= test_time_lib_path_flag %> ${TEST_OBJS} $(OBJS) <%= test_time_lib_flag %>
46
+ test: init $(OUTPUT_PATH)/$(PROJECT_NAME)_ut
47
+ $(OUTPUT_PATH)/$(PROJECT_NAME)_ut
48
+
49
+ #--------------------package-----------------
50
+ $(OUTPUT_PATH)/$(PROJECT_NAME): $(OBJS) $(PROD_OBJS)
51
+ $(LINK) -o $(OUTPUT_PATH)/$(PROJECT_NAME) <%= prod_time_lib_path_flag %> ${PROD_OBJS} $(OBJS) <%= prod_time_lib_flag %>
52
+ run: init $(OUTPUT_PATH)/$(PROJECT_NAME)
53
+ $(OUTPUT_PATH)/$(PROJECT_NAME)
54
+ package: $(OUTPUT_PATH)/$(PROJECT_NAME)
55
+
56
+ #--------------------misc-----------------
57
+ $(FOLDERS): %:
58
+ mkdir -p "$@"
59
+ init:$(FOLDERS)
60
+ clean:
61
+ rm -rf $(OBJS) $(TEST_OBJS) $(PROD_OBJS) $(ALL_DEPS) $(OUTPUT_PATH)/$(PROJECT_NAME) $(OUTPUT_PATH)/$(PROJECT_NAME)_ut $(FOLDERS)
62
+
63
+ .PHONY: clean init
64
+
65
+ -include $(ALL_DEPS)
metadata ADDED
@@ -0,0 +1,52 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: simple-make
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Cui Liqiang
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-12-30 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A tool to help you create makefile base on a build.sm file.
14
+ email: cui.liqiang@gmail.com
15
+ executables:
16
+ - sm
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - .gitignore
21
+ - bin/sm
22
+ - lib/simple-make.rb
23
+ - lib/simple-make/dependency.rb
24
+ - lib/simple-make/dir_traverser.rb
25
+ - lib/simple-make/project.rb
26
+ - lib/simple-make/search_path.rb
27
+ - template/makefile.erb
28
+ homepage: ''
29
+ licenses:
30
+ - MIT
31
+ metadata: {}
32
+ post_install_message:
33
+ rdoc_options: []
34
+ require_paths:
35
+ - lib
36
+ required_ruby_version: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ required_rubygems_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ requirements: []
47
+ rubyforge_project:
48
+ rubygems_version: 2.0.3
49
+ signing_key:
50
+ specification_version: 4
51
+ summary: convention over configuration c/c++ file build tool
52
+ test_files: []