canoe 0.3.0.2 → 0.3.2.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/lib/workspace/new.rb CHANGED
@@ -1,28 +1,31 @@
1
- class WorkSpace
2
- def new
3
- begin
4
- Dir.mkdir(@name)
5
- rescue
6
- abort_on_err "workspace #{@name} already exsits"
1
+ module Canoe
2
+ class WorkSpace
3
+ def new
4
+ begin
5
+ Dir.mkdir(@name)
6
+ rescue SystemCallError
7
+ abort_on_err "workspace #{@name} already exsits"
8
+ end
9
+ Dir.mkdir(@src)
10
+ Dir.mkdir(@components)
11
+ Dir.mkdir("#{@workspace}/obj")
12
+ if @mode == :bin
13
+ DefaultFiles.create_main(@src, @source_suffix)
14
+ else
15
+ DefaultFiles.create_lib_header(@src, @name, @header_suffix)
16
+ end
17
+ File.new("#{@workspace}/.canoe", 'w')
18
+ compiler = @source_suffix == 'c' ? 'clang' : 'clang++'
19
+ DefaultFiles.create_config @workspace, compiler, @source_suffix, @header_suffix
20
+
21
+ Dir.mkdir(@third)
22
+ Dir.mkdir(@target)
23
+ Dir.mkdir(@tests)
24
+ Dir.chdir(@workspace) do
25
+ system 'git init'
26
+ system 'canoe add tests'
27
+ end
28
+ puts "workspace #{@workspace.blue} is created"
7
29
  end
8
- Dir.mkdir(@src)
9
- Dir.mkdir(@components)
10
- Dir.mkdir("#{@workspace}/obj")
11
- if @mode == :bin
12
- DefaultFiles.create_main(@src, @source_suffix)
13
- else
14
- DefaultFiles.create_lib_header(@src, @name, @header_suffix)
15
- end
16
- File.new("#{@workspace}/.canoe", "w")
17
- DefaultFiles.create_config @workspace, @source_suffix, @header_suffix
18
- # DefaultFiles.create_emacs_dir_local @workspace
19
-
20
- Dir.mkdir(@third)
21
- Dir.mkdir(@target)
22
- Dir.mkdir(@tests)
23
- Dir.chdir(@workspace) do
24
- system "git init"
25
- end
26
- puts "workspace #{@workspace.blue} is created"
27
30
  end
28
- end
31
+ end
data/lib/workspace/run.rb CHANGED
@@ -1,9 +1,12 @@
1
- class WorkSpace
2
- def run(args)
3
- return if @mode == :lib
4
- build []
5
- args = args.join " "
6
- puts "./target/#{@name} #{args}"
7
- exec "./target/#{@name} #{args}"
1
+ module Canoe
2
+ class WorkSpace
3
+ def run(args)
4
+ return if @mode == :lib
5
+
6
+ return unless build
7
+
8
+ args = args.join ' '
9
+ issue_command "#{@target_short}/#{@name} #{args}"
10
+ end
8
11
  end
9
- end
12
+ end
@@ -1,39 +1,136 @@
1
- class WorkSpace
2
- public
3
- def test(args)
4
- if args.empty?
5
- test_all
6
- return
1
+ module Canoe
2
+ class WorkSpace
3
+ def test(args)
4
+ if args.empty?
5
+ test_all
6
+ return
7
+ end
8
+
9
+ args.each do |arg|
10
+ case arg
11
+ when 'all'
12
+ test_all
13
+ else
14
+ test_single arg
15
+ end
16
+ end
7
17
  end
18
+
19
+ # extract one test file's dependency
20
+ def extract_one_file(file, deps)
21
+ ret = deps[file]
8
22
 
9
- args.each do |arg|
10
- case arg
11
- when "all"
12
- test_all
13
- else
14
- test_single arg
23
+ deps[file].each do |f|
24
+ dep = extract_one_file(f, deps)
25
+ dep.each do |d|
26
+ ret << d unless ret.include?(d)
27
+ end
15
28
  end
29
+ ret.map { |f| f.gsub(".#{@header_suffix}", ".#{@source_suffix}") }
16
30
  end
17
- end
18
31
 
19
- private
20
- def test_all
21
- puts "tests all"
22
- end
32
+ def extract_one_file_obj(file, deps)
33
+ extract_one_file(file, deps).map do |f|
34
+ file_to_obj(f)
35
+ end
36
+ end
23
37
 
24
- def test_single(name)
25
- puts "#{@tests}/bin/test_#{name}"
26
- # system "./#{@tests}/bin/test_#{name}"
27
- end
28
-
29
- ##
30
- # how to build:
31
- # each test file tests one or more components, indicated by included headers
32
- # find corresponding object file in ../obj and link them to test file
33
- # TODO
34
- def build_test
35
- build
36
- deps = DepAnalyzer.new('./tests').build_to_file(['./src', './src/components', './tests', './tests/common'], './tests/.canoe.deps')
37
- puts deps
38
+ private
39
+
40
+ def test_all
41
+ build_test
42
+ fetch_all_test_files.each do |f|
43
+ test_single File.basename(f, '.*')['test_'.length..]
44
+ end
45
+ end
46
+
47
+ def test_single(name)
48
+ bin = "#{@target_short}/test_#{name}"
49
+ file = "#{@tests_short}/test_#{name}.#{@source_suffix}"
50
+ abort_on_err "Can not find source file #{file.red} for test #{name.red}" unless File.exist?(file)
51
+ build_one_test(file, fetch_all_deps) unless File.exist?(bin)
52
+
53
+ issue_command bin
54
+ end
55
+
56
+ def fetch_all_test_files
57
+ Dir.glob("#{@tests_short}/*.#{@source_suffix}").filter do |f|
58
+ File.basename(f).start_with? 'test_'
59
+ end
60
+ end
61
+
62
+ def fetch_all_deps
63
+ target_deps.merge(tests_deps)
64
+ end
65
+
66
+ def test_build_time
67
+ fetch_all_test_files.map do |f|
68
+ obj = "#{@target_short}/#{File.basename(f, '.*')}"
69
+ File.exist?(obj) ? File.mtime(obj) : Time.new(0)
70
+ end.min
71
+ end
72
+
73
+ # @deps is the dependency hash for tests
74
+ # cyclic dependency is not handled
75
+ # compiler should first be built
76
+ def compile_one_test(test_file, deps)
77
+ extract_one_file(test_file, deps).each do |f|
78
+ o = file_to_obj(f)
79
+ next if File.exist?(o) && File.mtime(o) > File.mtime(f)
80
+
81
+ compile(f, o)
82
+ end
83
+ compile(test_file, file_to_obj(test_file))
84
+ end
85
+
86
+ def link_one_test(test_file, deps)
87
+ target = "#{@target_short}/#{File.basename(test_file, '.*')}"
88
+ @compiler.link_executable target, extract_one_file_obj(test_file, deps) + [file_to_obj(test_file)]
89
+ end
90
+
91
+ def build_one_test(test_file, deps)
92
+ compile_one_test(test_file, deps)
93
+ link_one_test(test_file, deps)
94
+ end
95
+
96
+ def compile_all_tests(deps)
97
+ files = DepAnalyzer.compiling_filter(deps, test_build_time, @source_suffix, @header_suffix).select do |f|
98
+ File.basename(f).start_with?('test_')
99
+ end
100
+
101
+ stepper = Stepper.new fetch_all_test_files.size, files.size
102
+
103
+ files.each do |f|
104
+ printf "#{stepper.progress_as_str.green} compiling #{f} "
105
+ compile_one_test(f, deps)
106
+ stepper.step
107
+ end
108
+ end
109
+
110
+ def link_all_tests(deps)
111
+ all_files = fetch_all_test_files
112
+
113
+ stepper = Stepper.new all_files.size, all_files.size
114
+ fetch_all_test_files.each do |f|
115
+ printf "#{stepper.progress_as_str.green} linking #{File.basename(f, '.*').yellow}: "
116
+ link_one_test(f, deps)
117
+ stepper.step
118
+ end
119
+ end
120
+
121
+ def build_test
122
+ puts "#{'[COMPILING TESTS]'.magenta}..."
123
+ return unless test_build_time
124
+
125
+ total_deps = fetch_all_deps
126
+ compile_all_tests(total_deps)
127
+ puts "#{'[100%]'.green} compiling done, starts linking..."
128
+ puts "#{'[LINKING TESTS]'.magenta}..."
129
+ # compilation and link are separated because they may be separated
130
+ # by unexpected interrupt like C-c, C-d, etc.
131
+ # thus unditionally link all tests
132
+ link_all_tests(total_deps)
133
+ puts "#{'[100%]'.green} linking done"
134
+ end
38
135
  end
39
- end
136
+ end
@@ -1,5 +1,7 @@
1
- class WorkSpace
2
- def update
3
- generate
1
+ module Canoe
2
+ class WorkSpace
3
+ def update
4
+ generate
5
+ end
4
6
  end
5
- end
7
+ end
@@ -1,13 +1,15 @@
1
- class WorkSpace
2
- def version
3
- puts <<~VER
4
- canoe v0.3.0.2
5
- For features in this version, please visit https://github.com/Dicridon/canoe
6
- Currently, canoe can do below:
7
- - project creation
8
- - project auto build and run (works like Cargo for Rust)
9
- - project structure management
10
- by XIONG Ziwei
11
- VER
1
+ module Canoe
2
+ class WorkSpace
3
+ def self.version
4
+ puts <<~VER
5
+ canoe v0.3.2.2
6
+ For features in this version, please visit https://github.com/Dicridon/canoe
7
+ Currently, canoe can do below:
8
+ - project creation
9
+ - project auto build, run and test (works like Cargo for Rust)
10
+ - project structure management
11
+ by XIONG Ziwei
12
+ VER
12
13
  end
13
- end
14
+ end
15
+ end
@@ -3,44 +3,56 @@ require_relative '../source_files'
3
3
  require_relative '../compiler'
4
4
  require_relative '../config_reader'
5
5
  require_relative '../default_files'
6
- require_relative '../err'
6
+ require_relative '../util'
7
7
  require_relative '../dependence'
8
8
  require_relative '../coloring'
9
9
 
10
+ module Canoe
11
+ ##
12
+ # A workspace resents a C/C++ project
13
+ # This class is responsible for the main functionality of canoe, such as building and cleaning
14
+ # TODO
15
+ # add a command to generate compile_commands.json so users won't have to install bear
16
+ class WorkSpace
17
+ include Err
18
+ include SystemCommand
19
+ attr_reader :name, :cwd, :src_prefix, :components_prefix, :obj_prefix,
20
+ :source_suffix, :header_suffix, :mode, :target_short,
21
+ :src_short, :components_short, :obj_short, :tests_short
10
22
 
11
- class WorkSpace
12
- include Err
13
- attr_reader :name, :cwd
23
+ def initialize(name, mode, src_suffix = 'cpp', hdr_suffix = 'hpp', nu = false)
24
+ @name = name
25
+ @compiler = Compiler.new 'clang++', ['-Isrc/components'], []
26
+ @cwd = Dir.new(Dir.pwd)
27
+ @workspace = Dir.pwd.to_s + (nu ? "/#{@name}" : '')
28
+ @src = "#{@workspace}/src"
29
+ @components = "#{@src}/components"
30
+ @obj = "#{@workspace}/obj"
31
+ @third = "#{@workspace}/third-party"
32
+ @target = "#{@workspace}/target"
33
+ @tests = "#{@workspace}/tests"
34
+ @mode = mode
35
+ @deps = '.canoe.deps'
36
+ @test_deps = '.canoe.test.deps'
14
37
 
15
- def initialize(name, mode, src_suffix='cpp', hdr_suffix='hpp')
16
- @name = name
17
- @compiler = Compiler.new 'clang++', ['-Isrc/components'], []
18
- @cwd = Dir.new(Dir.pwd)
19
- @workspace = "#{Dir.pwd}/#{@name}"
20
- @src = "#{@workspace}/src"
21
- @components = "#{@src}/components"
22
- @obj = "#{@workspace}/obj"
23
- @third = "#{@workspace}/third-party"
24
- @target = "#{@workspace}/target"
25
- @tests = "#{@workspace}/tests"
26
- @mode = mode
27
- @deps = '.canoe.deps'
38
+ @target_short = './target'
39
+ @src_short = './src'
40
+ @components_short = "#{@src_short}/components"
41
+ @obj_short = './obj'
42
+ @tests_short = './tests'
28
43
 
29
- @src_prefix = './src/'
30
- @components_prefix = './src/components/'
31
- @obj_prefix = './obj/'
44
+ @src_prefix = './src/'
45
+ @components_prefix = './src/components/'
46
+ @obj_prefix = './obj/'
32
47
 
33
- @source_suffix = src_suffix
34
- @header_suffix = hdr_suffix
35
- end
36
-
37
- def inspect
38
- puts "name is #{@name}"
39
- puts "name is #{@workspace}"
48
+ @source_suffix = src_suffix
49
+ @header_suffix = hdr_suffix
50
+ end
40
51
  end
41
52
  end
42
53
 
43
54
  require_relative 'help'
55
+ require_relative 'version'
44
56
  require_relative 'new'
45
57
  require_relative 'add'
46
58
  require_relative 'build'
@@ -48,6 +60,6 @@ require_relative 'generate'
48
60
  require_relative 'run'
49
61
  require_relative 'dep'
50
62
  require_relative 'clean'
51
- require_relative 'version'
52
63
  require_relative 'update'
53
64
  require_relative 'test'
65
+ require_relative 'make'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: canoe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0.2
4
+ version: 0.3.2.2
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-09-06 00:00:00.000000000 Z
11
+ date: 2021-05-17 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |+
14
14
  Canoe offers project management and building facilities to C/C++ projects.
@@ -33,14 +33,15 @@ files:
33
33
  - lib/config_reader.rb
34
34
  - lib/default_files.rb
35
35
  - lib/dependence.rb
36
- - lib/err.rb
37
36
  - lib/source_files.rb
37
+ - lib/util.rb
38
38
  - lib/workspace/add.rb
39
39
  - lib/workspace/build.rb
40
40
  - lib/workspace/clean.rb
41
41
  - lib/workspace/dep.rb
42
42
  - lib/workspace/generate.rb
43
43
  - lib/workspace/help.rb
44
+ - lib/workspace/make.rb
44
45
  - lib/workspace/new.rb
45
46
  - lib/workspace/run.rb
46
47
  - lib/workspace/test.rb
@@ -66,7 +67,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
66
67
  - !ruby/object:Gem::Version
67
68
  version: '0'
68
69
  requirements: []
69
- rubygems_version: 3.1.2
70
+ rubygems_version: 3.2.3
70
71
  signing_key:
71
72
  specification_version: 4
72
73
  summary: a C/C++ project management and building tool
data/lib/err.rb DELETED
@@ -1,20 +0,0 @@
1
- require_relative 'coloring'
2
- module Err
3
- def warn_on_err(err)
4
- puts <<~ERR
5
- #{"Waring: ".yellow}
6
- #{err}
7
- try 'canoe help' for more information
8
- ERR
9
- end
10
-
11
- def abort_on_err(err)
12
- abort <<~ERR
13
- #{"Fatal: ".red}
14
- #{err}
15
- try 'canoe help' for more information
16
- ERR
17
- end
18
-
19
- module_function :warn_on_err, :abort_on_err
20
- end