canoe 0.2.1 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 78d6318d9757575b6e8f3f118e161ca06bb08655f26e7531e33c31d63f26aa18
4
- data.tar.gz: 5cb8230a80e4bb2f03b8afb3dbebea90fccfd4b97bafa652502b2161e70ce374
3
+ metadata.gz: 7c1916c0ee5ce05d67222c84f93ac7e41de04895ffb523b1a5435276c6f8e11f
4
+ data.tar.gz: f3b69717aed857c30f8154fb1f63126b8f84c42081890ef1be75c6d2a7250735
5
5
  SHA512:
6
- metadata.gz: 9501ebdd1d4ef09e6bfaede0c712044d665650b2a9d07dcfe490fe35afc378dae1d66429dc5919e217b48f4d3df9156611a4c496c64ebe3916870fc2da48453a
7
- data.tar.gz: 848272aacd562ef7bc05ae50bd948a4221721b9432be46acb669e8ee6bb4f5a27e7e7ed57d5e6b64d83fce52be6a882955324f0c782b9e9252611ed29ba50cf8
6
+ metadata.gz: adae82066e778ae3756d970b75fb87784087e25996051c9cd5dd5ad75f265c09418eeb5c4387db9b0c9c125d1b1739461f1f0a0dfc72cde9f1914a65023eb030
7
+ data.tar.gz: 7d31ba373cf0a9a7f41178a153ee8fd7f9eb442a2698ec464c5ea9ca247b9816765f2bc17db1d0902209c6e6e4ff4bc238a4d7e9fa59cf74ba29a841bf519c3b
@@ -4,7 +4,16 @@ require_relative "source_files"
4
4
 
5
5
  class Canoe
6
6
  def initialize
7
- options = ["new", "build", "run", "clean", "help", "add", "generate", "deps", "version"]
7
+ options = ['new',
8
+ 'add',
9
+ 'build',
10
+ 'generate',
11
+ 'run',
12
+ 'dep',
13
+ 'clean',
14
+ 'version',
15
+ 'help',
16
+ 'update']
8
17
  @cmd = CmdParser.new options
9
18
  end
10
19
 
data/lib/cmd.rb CHANGED
@@ -2,6 +2,9 @@ require_relative "workspace"
2
2
  require_relative "err"
3
3
  require_relative "config_reader"
4
4
 
5
+ ##
6
+ # class CmdParser
7
+ # Parsing command arguments passed to canoe
5
8
  class CmdParser
6
9
  include Err
7
10
  def initialize(options)
@@ -85,9 +88,13 @@ class CmdParser
85
88
  get_current_workspace.clean
86
89
  end
87
90
 
91
+ def parse_test(args)
92
+ get_current_workspace.test args
93
+ end
94
+
88
95
  def parse_version(args)
89
96
  puts <<~VER
90
- canoe v0.2.1
97
+ canoe v0.3.0
91
98
  For features in this version, please visit https://github.com/Dicridon/canoe
92
99
  Currently, canoe can do below:
93
100
  - project creation
@@ -0,0 +1,23 @@
1
+ ##
2
+ # gem Colorize is a great tool, but I don't want add dependencies to Canoe
3
+ class String
4
+ def self.define_coloring_methods
5
+ colors = {
6
+ 30 => :black,
7
+ 31 => :red,
8
+ 32 => :green,
9
+ 33 => :yellow,
10
+ 34 => :blue,
11
+ 35 => :magenta,
12
+ 36 => :cyan,
13
+ 37 => :white
14
+ }
15
+ colors.each do |k, v|
16
+ define_method v do
17
+ "\033[#{k}m#{self}\033[0m"
18
+ end
19
+ end
20
+ end
21
+
22
+ define_coloring_methods
23
+ end
@@ -1,29 +1,49 @@
1
+ ##
2
+ # class Compiler
3
+ # Storing compiler name in String and flags as an array
1
4
  class Compiler
2
5
  attr_reader :name, :flags
6
+ ##
7
+ # @name: String
8
+ # @flgs: Array of String
3
9
  def initialize(name, flgs)
4
10
  @name = name
5
- @flags = flgs
11
+ @linking_flags = flgs.filter {|f| f.start_with? "-l"}
12
+ @compiling_flags = flgs - @linking_flags
6
13
  end
7
14
 
8
- def flags_as_str
9
- flags.join " "
15
+ def compiling_flags_as_str
16
+ @compiling_flags.join " "
10
17
  end
11
18
 
12
- def append_flag(flag)
13
- @flags << flag
19
+ def linking_flags_as_str
20
+ @linking_flags.join " "
21
+ end
22
+
23
+
24
+ def append_compiling_flag(flag)
25
+ @compiling_flags << flag
26
+ end
27
+
28
+ def append_linking_flag(flag)
29
+ @linking_flags << flag
14
30
  end
15
31
 
16
32
  def compile(src, out)
17
- puts "#{name} -o #{out} #{flags_as_str} -c #{src}"
18
- system "#{name} -o #{out} #{flags_as_str} -c #{src}"
33
+ puts "#{name} -o #{out} #{compiling_flags_as_str} -c #{src}"
34
+ system "#{name} -o #{out} #{compiling_flags_as_str} -c #{src}"
19
35
  end
20
36
 
21
- def link(out, objs)
22
- libs = flags.select {|f| f.start_with?('-l')}
23
- puts "#{name} -o #{out} #{objs.join(" ")} #{libs.join(" ")}"
24
- system "#{name} -o #{out} #{objs.join(" ")} #{libs.join(" ")}"
37
+ def link_executable(out, objs)
38
+ puts "#{name} -o #{out} #{objs.join(" ")} #{linking_flags_as_str}"
39
+ system "#{name} -o #{out} #{objs.join(" ")} #{linking_flags_as_str}"
25
40
  end
26
41
 
42
+ def link_shared(out, objs)
43
+ puts "#{name} -shared -o #{out}.so #{objs.join(" ")} #{linking_flags_as_str}"
44
+ system "#{name} -shared -o #{out}.so #{objs.join(" ")} #{linking_flags_as_str}"
45
+ end
46
+
27
47
  def inspect
28
48
  puts "compiler name: #{name.inspect}"
29
49
  puts "compiler flags: #{flags.inspect}"
@@ -1,5 +1,8 @@
1
1
  require 'json'
2
2
 
3
+ ##
4
+ # class ConfigReader
5
+ # Just read a json file
3
6
  class ConfigReader
4
7
  def self.extract_flags(file)
5
8
  abort_on_err("config file #{file} does not exsit") unless File.exists? file
@@ -1,70 +1,88 @@
1
+ ##
2
+ # class DefaultFiles
3
+ # A singleton class to generate header and souce files.
4
+ # TODO: consider using class source_file.rb in Pareater
1
5
  class DefaultFiles
2
- def self.open_file_and_write(filename, content)
3
- File.open(filename, "w") {|f|
4
- f.write(content)
5
- }
6
- end
6
+ class << self
7
+ def open_file_and_write(filename, content)
8
+ File.open(filename, "w") do |f|
9
+ f.write(content)
10
+ end
11
+ end
7
12
 
8
- def self.create_config(path, src_sfx='cpp', hdr_sfx='hpp')
9
- open_file_and_write(
10
- "#{path}/config.json",
11
- <<~CONFIG
12
- {
13
- "compiler": "clang++",
14
- "header-suffix": "#{hdr_sfx}",
15
- "source-suffix": "#{src_sfx}",
16
- "flags": {
17
- "opt": "-O2",
18
- "debug": "-g",
19
- "std": "-std=c++17"
20
- }
21
- }
22
- CONFIG
23
- )
24
- end
13
+ def create_config(path, src_sfx='cpp', hdr_sfx='hpp')
14
+ open_file_and_write(
15
+ "#{path}/config.json",
16
+ <<~CONFIG
17
+ {
18
+ "compiler": "clang++",
19
+ "header-suffix": "#{hdr_sfx}",
20
+ "source-suffix": "#{src_sfx}",
21
+ "flags": {
22
+ "opt": "-O2",
23
+ "debug": "-g",
24
+ "std": "-std=c++17"
25
+ }
26
+ }
27
+ CONFIG
28
+ )
29
+ end
25
30
 
26
- def self.create_main(path, suffix='cpp')
27
- open_file_and_write(
28
- "#{path}/main.#{suffix}",
29
- <<~DOC
30
- #include <iostream>
31
- int main(int argc, char *argv[]) {
32
- std::cout << "hello world!" << std::endl;
33
- }
34
- DOC
35
- )
36
- end
31
+ def create_main(path, suffix='cpp')
32
+ open_file_and_write(
33
+ "#{path}/main.#{suffix}",
34
+ <<~DOC
35
+ #include <iostream>
36
+ int main(int argc, char *argv[]) {
37
+ std::cout << "hello world!" << std::endl;
38
+ }
39
+ DOC
40
+ )
41
+ end
37
42
 
38
- def self.create_emacs_dir_local(path)
39
- open_file_and_write(
40
- "#{path}/.dir-locals.el",
41
- <<~DOC
42
- ((nil . ((company-clang-arguments . ("-I./src/components/"
43
- "-I./components/"))))
44
- (nil . ((company-c-headers-path-user . ("./src/components/"
45
- "./components/")))))
46
- DOC
47
- )
48
- end
43
+ def create_lib_header(path, lib_name, suffix='hpp')
44
+ open_file_and_write(
45
+ "#{path}/#{lib_name}.#{suffix}",
46
+ <<~DOC
47
+ #ifndef __#{lib_name.upcase}__
48
+ #define __#{lib_name.upcase}__
49
+
50
+ #endif
51
+ DOC
52
+ )
53
+ end
49
54
 
50
- def self.create_cpp(filename, src_sfx='cpp', hdr_sfx='hpp')
51
- open_file_and_write(
52
- "#{filename}.#{src_sfx}",
53
- <<~DOC
54
- #include "#{filename}.#{hdr_sfx}"
55
- DOC
56
- )
57
- end
55
+ # def create_emacs_dir_local(path)
56
+ # open_file_and_write(
57
+ # "#{path}/.dir-locals.el",
58
+ # <<~DOC
59
+ # ((nil . ((company-clang-arguments . ("-I./src/components/"
60
+ # "-I./components/"))))
61
+ # (nil . ((company-c-headers-path-user . ("./src/components/"
62
+ # "./components/")))))
63
+ # DOC
64
+ # )
65
+ # end
58
66
 
59
- def self.create_hpp(workspace, prefix, filename, hdr_sfx='hpp')
60
- open_file_and_write(
61
- "#{filename}.#{hdr_sfx}",
62
- <<~DOC
63
- #ifndef __#{workspace.upcase}__#{prefix.upcase}__#{filename.upcase}__
64
- #define __#{workspace.upcase}__#{prefix.upcase}__#{filename.upcase}__
67
+ def create_cpp(filename, src_sfx='cpp', hdr_sfx='hpp')
68
+ open_file_and_write(
69
+ "#{filename}.#{src_sfx}",
70
+ <<~DOC
71
+ #include "#{filename}.#{hdr_sfx}"
72
+ DOC
73
+ )
74
+ end
65
75
 
66
- #endif
67
- DOC
68
- )
76
+ def create_hpp(workspace, prefix, filename, hdr_sfx='hpp')
77
+ open_file_and_write(
78
+ "#{filename}.#{hdr_sfx}",
79
+ <<~DOC
80
+ #ifndef __#{workspace.upcase}__#{prefix.upcase}__#{filename.upcase}__
81
+ #define __#{workspace.upcase}__#{prefix.upcase}__#{filename.upcase}__
82
+
83
+ #endif
84
+ DOC
85
+ )
86
+ end
69
87
  end
70
88
  end
@@ -1,6 +1,19 @@
1
1
  require_relative 'source_files'
2
2
  require_relative 'err'
3
3
 
4
+ ##
5
+ # class DepAnalyzer
6
+ # This class is the key component of canoe, which offers file dependency analysis functionality.
7
+ # A DepAnalyzer takes a directory as input, sources files and corresponding header files in this
8
+ # directory should have same name, i.e. test.cpp and test.hpp.
9
+ # DepAnalyzer would read every source file and recursively process user header files included in this source file to
10
+ # find out all user header files this source file depends on.
11
+ # Based on dependencies built in previous stage, DepAnalyzer determines which files should be recompiled and return
12
+ # these files to caller.
13
+ #
14
+ # Dependencies could be written to a file to avoid wasting time parsing all files, Depanalyzer would read from
15
+ # this file to construct dependencies. But if sources files included new headers or included headers are revmoed,
16
+ # Depanalyzer should rebuild the whole dependencies.
4
17
  class DepAnalyzer
5
18
  include Err
6
19
  def self.read_from(filename)
@@ -16,11 +29,19 @@ class DepAnalyzer
16
29
  end
17
30
 
18
31
  def self.compiling_filter(deps, build_time, src_sfx='cpp', hdr_sfx='hpp')
19
- files = []
32
+ files = []
33
+ @processed = {}
34
+ @recompiles = {}
35
+ deps.keys.each do |k|
36
+ @processed[k] = false
37
+ @recompiles[k] = false
38
+ end
20
39
  deps.each do |k, v|
21
40
  next if k.end_with? ".#{hdr_sfx}"
22
41
  if should_recompile?(k, build_time)
23
42
  files << k
43
+ @processed[k] = true
44
+ @recompiles[k] = true
24
45
  next
25
46
  end
26
47
  v.each do |f|
@@ -40,7 +61,12 @@ class DepAnalyzer
40
61
  return true
41
62
  else
42
63
  deps[file].each do |f|
43
- return true if mark(f, build_time, deps)
64
+ return @recompiles[f] if @processed[f]
65
+ @processed[f] = true
66
+ if mark(f, build_time, deps)
67
+ @recompiles[f] = true
68
+ return true
69
+ end
44
70
  end
45
71
  end
46
72
  false
@@ -49,7 +75,11 @@ class DepAnalyzer
49
75
  def self.should_recompile?(file, build_time)
50
76
  judge = build_time
51
77
  if build_time == Time.new(0)
52
- objfile = "./obj/#{File.basename(file, ".*")}.o"
78
+ objfile = if file.start_with?("./src/components")
79
+ './obj/' + file.delete_suffix(File.extname(file))['./src/components/'.length..].gsub('/', '_') + '.o'
80
+ else
81
+ "./obj/#{File.basename(file, ".*")}.o"
82
+ end
53
83
  return true unless File.exists? objfile
54
84
  judge = File.mtime(objfile)
55
85
  end
data/lib/err.rb CHANGED
@@ -1,7 +1,8 @@
1
+ require_relative 'coloring'
1
2
  module Err
2
3
  def warn_on_err(err)
3
4
  puts <<~ERR
4
- Warning:
5
+ #{"Waring: ".yellow}
5
6
  #{err}
6
7
  try 'canoe help' for more information
7
8
  ERR
@@ -9,11 +10,11 @@ module Err
9
10
 
10
11
  def abort_on_err(err)
11
12
  abort <<~ERR
12
- Fatal:
13
+ #{"Fatal: ".red}
13
14
  #{err}
14
15
  try 'canoe help' for more information
15
16
  ERR
16
17
  end
17
18
 
18
19
  module_function :warn_on_err, :abort_on_err
19
- end
20
+ end
@@ -1,3 +1,6 @@
1
+ ##
2
+ # class SourceFiles
3
+ # A simple class to assist collect all files or some files in a directory.
1
4
  class SourceFiles
2
5
  class << self
3
6
  def get_all(dir, &block)
@@ -1,11 +1,11 @@
1
1
  require 'fileutils'
2
- require 'open3'
3
2
  require_relative 'source_files'
4
3
  require_relative 'compiler'
5
4
  require_relative 'config_reader'
6
5
  require_relative 'default_files'
7
6
  require_relative 'err'
8
7
  require_relative 'dependence'
8
+ require_relative 'coloring'
9
9
 
10
10
  class WorkSpace
11
11
  include Err
@@ -18,7 +18,9 @@ class WorkSpace
18
18
 
19
19
  canoe build: compile current project (execute this command in project directory)
20
20
 
21
- canoe generate: generate dependency relationship and store it in '.canoe.deps'
21
+ canoe generate: generate dependency relationships and store it in '.canoe.deps' file. Alias: update
22
+
23
+ canoe update: udpate dependency relationships and store it in '.canoe.deps' file.
22
24
 
23
25
  canoe run: compile and execute current project (execute this command in project directory)
24
26
 
@@ -27,7 +29,8 @@ class WorkSpace
27
29
  canoe help: show this help message
28
30
 
29
31
  canoe add tada: add a folder named tada under workspace/components,
30
- two files tada.hpp and tada.cpp would be craeted and intialized
32
+
33
+ canoe dep: show current dependency relationships of current project
31
34
 
32
35
  canoe verion: version information
33
36
 
@@ -38,11 +41,20 @@ class WorkSpace
38
41
 
39
42
  [mode]: --lib for a library and --bin for executable binaries
40
43
  [suffixes]: should be in 'source_suffix:header_suffix" format, notice the ':' between two suffixes
44
+ add component_name:
45
+ add a folder named tada under workspace/components.
46
+ two files tada.hpp and tada.cpp would be craeted and intialized. File suffix may differ according users' specifications.
47
+ if component_name is a path separated by '/', then canoe would create folders and corresponding files recursively.
41
48
 
42
49
  generate:
43
50
  generate dependence relationship for each file, this may accelarate
44
51
  `canoe buid` command. It's recommanded to execute this command everytime
45
52
  headers are added or removed from any file.
53
+
54
+ update:
55
+ this command is needed because '.canoe.deps' is actually a cache of dependency relationships so that canoe doesn't have to analyze all the files when building a project.
56
+ So when a file includes new headers or some headers are removed, users have to use 'canoe udpate'
57
+ to update dependency relationships.
46
58
 
47
59
  build [options]:
48
60
  build current project, arguments in [options] will be passed to C++ compiler
@@ -71,7 +83,7 @@ class WorkSpace
71
83
 
72
84
  def initialize(name, mode, src_suffix='cpp', hdr_suffix='hpp')
73
85
  @name = name
74
- @compiler = Compiler.new 'clang++', '-Isrc/components'
86
+ @compiler = Compiler.new 'clang++', ['-Isrc/components']
75
87
  @cwd = Dir.new(Dir.pwd)
76
88
  @workspace = "#{Dir.pwd}/#{@name}"
77
89
  @src = "#{@workspace}/src"
@@ -79,6 +91,7 @@ class WorkSpace
79
91
  @obj = "#{@workspace}/obj"
80
92
  @third = "#{@workspace}/third-party"
81
93
  @target = "#{@workspace}/target"
94
+ @tests = "#{@workspace}/tests"
82
95
  @mode = mode
83
96
  @deps = '.canoe.deps'
84
97
 
@@ -91,18 +104,29 @@ class WorkSpace
91
104
  end
92
105
 
93
106
  def new
94
- Dir.mkdir(@name)
107
+ begin
108
+ Dir.mkdir(@name)
109
+ rescue
110
+ abort_on_err "workspace #{@name} already exsits"
111
+ end
95
112
  Dir.mkdir(@src)
96
113
  Dir.mkdir(@components)
97
114
  Dir.mkdir("#{@workspace}/obj")
98
- DefaultFiles.create_main(@src, @source_suffix) if @mode == :bin
115
+ if @mode == :bin
116
+ DefaultFiles.create_main(@src, @source_suffix)
117
+ else
118
+ DefaultFiles.create_lib_header(@src, @name, @header_suffix)
119
+ end
99
120
  File.new("#{@workspace}/.canoe", "w")
100
121
  DefaultFiles.create_config @workspace, @source_suffix, @header_suffix
101
- DefaultFiles.create_emacs_dir_local @workspace
122
+ # DefaultFiles.create_emacs_dir_local @workspace
102
123
 
103
124
  Dir.mkdir(@third)
104
125
  Dir.mkdir(@target)
105
- puts "workspace #{@workspace} is created"
126
+ Dir.chdir(@workspace) do
127
+ system "git init"
128
+ end
129
+ puts "workspace #{@workspace.blue} is created"
106
130
  end
107
131
 
108
132
  # args are commandline parameters passed to `canoe build`
@@ -114,7 +138,7 @@ class WorkSpace
114
138
  build_time = File.exist?(target) ? File.mtime(target) : Time.new(0)
115
139
  files = DepAnalyzer.compiling_filter(deps, build_time, @source_suffix, @header_suffix)
116
140
 
117
- if files.empty?
141
+ if files.empty? && File.exist?(target)
118
142
  puts "nothing to do, all up to date"
119
143
  return
120
144
  end
@@ -136,6 +160,7 @@ class WorkSpace
136
160
  end
137
161
 
138
162
  def run(args)
163
+ return if @mode == :lib
139
164
  build []
140
165
  args = args.join " "
141
166
  puts "./target/#{@name} #{args}"
@@ -153,7 +178,7 @@ class WorkSpace
153
178
  unless Dir.exist? dir
154
179
  FileUtils.mkdir dir
155
180
  Dir.chdir(dir) do
156
- puts "created " + Dir.pwd
181
+ puts "created " + Dir.pwd.blue
157
182
  create_working_files prefix.join('__'), filename
158
183
  end
159
184
  end
@@ -165,12 +190,23 @@ class WorkSpace
165
190
  deps = DepAnalyzer.read_from(@deps) if File.exist?(@deps)
166
191
  deps.each do |k, v|
167
192
  unless v.empty?
168
- puts "#{k} depends on: "
169
- v.each {|f| puts " #{f}"}
193
+ puts "#{k.blue} depends on: "
194
+ v.each {|f| puts " #{f.blue}"}
170
195
  puts ""
171
196
  end
172
197
  end
173
198
  end
199
+
200
+ def test(args)
201
+ args.each do |arg|
202
+ case arg
203
+ when "all"
204
+ test_all
205
+ else
206
+ test_single arg
207
+ end
208
+ end
209
+ end
174
210
 
175
211
  private
176
212
  def create_working_files(prefix, filename)
@@ -208,40 +244,62 @@ class WorkSpace
208
244
  @compiler.compile f, o
209
245
  end
210
246
 
211
- def link(odir, objs)
212
- status = system "#{@compiler} -o #{odir}/#{@name} #{objs.join(" ")}"
213
- unless status
214
- puts "compilation failed"
215
- return
216
- end
217
-
218
- @compiler.link "#{odir}/#{@name}", objs
247
+ def link_exectutable(odir, objs)
248
+ puts "#{"[100%]".green} linking"
249
+ @compiler.link_executable "#{odir}/#{@name}", objs
250
+ end
251
+
252
+ def link_shared(odir, objs)
253
+ puts "#{"[100%]".green} linking"
254
+ @compiler.link_shared "#{odir}/lib#{@name}", objs
219
255
  end
220
256
 
221
257
  def build_bin(files, args)
258
+ # return if files.empty?
222
259
  build_compiler_from_config args
260
+ if build_common(files, args) && link_exectutable('./target', Dir.glob("obj/*.o"))
261
+ puts "BUILDING SUCCEEDED".green
262
+ else
263
+ puts "building FAILED".red
264
+ end
265
+ end
266
+
267
+ def build_lib(files, args)
268
+ # return if files.empty?
269
+ build_compiler_from_config args
270
+ @compiler.append_compiling_flag '-fPIC'
271
+ if (build_common files, args) && link_shared('./target', Dir.glob("obj/*.o"))
272
+ puts "BUILDING SUCCEEDED".green
273
+ else
274
+ puts "building FAILED".red
275
+ end
276
+ end
277
+
278
+ def build_common(files, args)
279
+ all = SourceFiles.get_all('./src') {|f| f.end_with? @source_suffix}
280
+ total = all.size.to_f
281
+ compiled = total - files.size
223
282
  comps = files.select {|f| f.start_with? @components_prefix}
224
283
  srcs = files - comps
225
-
284
+ flag = true;
226
285
  srcs.each do |f|
227
- puts "compiling #{f}"
286
+ progress = (compiled / total).round(2) * 100
287
+ printf "[#{progress.to_i}%%]".green + " compiling #{f}: "
228
288
  fname = f.split("/")[-1]
229
- o = @obj_prefix + fname.delete_suffix(File.extname(fname)) + '.o'
230
- compile f, o
289
+ o = @obj_prefix + File.basename(fname, ".*") + '.o'
290
+ flag = false unless compile f, o
291
+ compiled += 1
231
292
  end
232
293
 
233
294
  comps.each do |f|
234
- puts "compiling #{f}"
295
+ progress = (compiled / total).round(2) * 100
296
+ printf "[#{progress.to_i}%%]".green + " compiling #{f}: "
235
297
  o = @obj_prefix + f.delete_suffix(File.extname(f))[@components_prefix.length..]
236
298
  .gsub('/', '_') + '.o'
237
- compile f, o
299
+ flag = false unless compile f, o
300
+ compiled += 1
238
301
  end
239
-
240
- link('./target', Dir.glob("obj/*.o")) unless files.empty?
241
- end
242
-
243
- def build_lib
244
- puts "build a lib"
302
+ flag
245
303
  end
246
304
 
247
305
  def clean_obj
metadata CHANGED
@@ -1,19 +1,24 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: canoe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - XIONG Ziwei
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-23 00:00:00.000000000 Z
11
+ date: 2020-07-11 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: |
14
- Tired of writing Makefile, CMakeList and even SConstruct? Let Canoe help you wipe them out.
13
+ description: |+
14
+ Canoe offers project management and building facilities to C/C++ projects.
15
+
16
+ If you are tired of writing Makefile, CMakeList and even SConstruct, please let Canoe help you wipe them out.
17
+
15
18
  Similar to Cargo for Rust, Canoe offers commands such as new, build, run, etc. to help you generate a C/C++ project and build it automatically.
16
- No more Makefiles, Canoe would analyze dependencies and build like our old friend make if you follow a few conventions over file names
19
+
20
+ Different from tools like Scons and Blade, Canoe requires users to write NO building scripts, Canoe would analyze dependencies and build like our old friend 'make' if a few conventions over file names are followed.
21
+
17
22
  email: noahxiong@outlook.com
18
23
  executables:
19
24
  - canoe
@@ -23,6 +28,7 @@ files:
23
28
  - bin/canoe
24
29
  - lib/canoe.rb
25
30
  - lib/cmd.rb
31
+ - lib/coloring.rb
26
32
  - lib/compiler.rb
27
33
  - lib/config_reader.rb
28
34
  - lib/default_files.rb
@@ -42,7 +48,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
42
48
  requirements:
43
49
  - - ">="
44
50
  - !ruby/object:Gem::Version
45
- version: '0'
51
+ version: 2.7.1
46
52
  required_rubygems_version: !ruby/object:Gem::Requirement
47
53
  requirements:
48
54
  - - ">="
@@ -52,5 +58,5 @@ requirements: []
52
58
  rubygems_version: 3.1.2
53
59
  signing_key:
54
60
  specification_version: 4
55
- summary: a C/C++ project management and build tool
61
+ summary: a C/C++ project management and building tool
56
62
  test_files: []