canoe 0.3.1.1 → 0.3.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"
7
- 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
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
+ DefaultFiles.create_config @workspace, @source_suffix, @header_suffix
19
+ # DefaultFiles.create_emacs_dir_local @workspace
19
20
 
20
- Dir.mkdir(@third)
21
- Dir.mkdir(@target)
22
- Dir.mkdir(@tests)
23
- Dir.chdir(@workspace) do
24
- system "git init"
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"
25
29
  end
26
- puts "workspace #{@workspace.blue} is created"
27
30
  end
28
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
12
  end
@@ -1,41 +1,136 @@
1
- class WorkSpace
2
- public
1
+ module Canoe
2
+ class WorkSpace
3
+ def test(args)
4
+ if args.empty?
5
+ test_all
6
+ return
7
+ end
3
8
 
4
- def test(args)
5
- if args.empty?
6
- test_all
7
- return
9
+ args.each do |arg|
10
+ case arg
11
+ when 'all'
12
+ test_all
13
+ else
14
+ test_single arg
15
+ end
16
+ end
8
17
  end
18
+
19
+ # extract one test file's dependency
20
+ def extract_one_file(file, deps)
21
+ ret = deps[file]
9
22
 
10
- args.each do |arg|
11
- case arg
12
- when "all"
13
- test_all
14
- else
15
- 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
16
28
  end
29
+ ret.map { |f| f.gsub(".#{@header_suffix}", ".#{@source_suffix}") }
17
30
  end
18
- end
19
31
 
20
- private
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
21
37
 
22
- def test_all
23
- puts "tests all"
24
- end
38
+ private
25
39
 
26
- def test_single(name)
27
- puts "#{@tests}/bin/test_#{name}"
28
- # system "./#{@tests}/bin/test_#{name}"
29
- end
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
30
72
 
31
- ##
32
- # how to build:
33
- # each test file tests one or more components, indicated by included headers
34
- # find corresponding object file in ../obj and link them to test file
35
- # TODO
36
- def build_test
37
- build
38
- deps = DepAnalyzer.new("./tests").build_to_file(["./src", "./src/components", "./tests", "./tests/common"], "./tests/.canoe.deps")
39
- puts deps
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
40
135
  end
41
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
7
  end
@@ -1,13 +1,15 @@
1
- class WorkSpace
2
- def self.version
3
- puts <<~VER
4
- canoe v0.3.1.1
1
+ module Canoe
2
+ class WorkSpace
3
+ def self.version
4
+ puts <<~VER
5
+ canoe v0.3.2
5
6
  For features in this version, please visit https://github.com/Dicridon/canoe
6
7
  Currently, canoe can do below:
7
8
  - project creation
8
- - project auto build and run (works like Cargo for Rust)
9
+ - project auto build, run and test (works like Cargo for Rust)
9
10
  - project structure management
10
11
  by XIONG Ziwei
11
12
  VER
13
+ end
12
14
  end
13
15
  end
@@ -1,53 +1,63 @@
1
- require "fileutils"
2
- require_relative "../source_files"
3
- require_relative "../compiler"
4
- require_relative "../config_reader"
5
- require_relative "../default_files"
6
- require_relative "../err"
7
- require_relative "../dependence"
8
- require_relative "../coloring"
1
+ require 'fileutils'
2
+ require_relative '../source_files'
3
+ require_relative '../compiler'
4
+ require_relative '../config_reader'
5
+ require_relative '../default_files'
6
+ require_relative '../util'
7
+ require_relative '../dependence'
8
+ require_relative '../coloring'
9
9
 
10
- class WorkSpace
11
- include Err
12
- attr_reader :name, :cwd, :src_prefix, :components_prefix, :obj_prefix, :source_suffix, :header_suffix, :mode
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
+ class WorkSpace
15
+ include Err
16
+ include SystemCommand
17
+ attr_reader :name, :cwd, :src_prefix, :components_prefix, :obj_prefix,
18
+ :source_suffix, :header_suffix, :mode, :target_short,
19
+ :src_short, :components_short, :obj_short, :tests_short
13
20
 
14
- def initialize(name, mode, src_suffix = "cpp", hdr_suffix = "hpp")
15
- @name = name
16
- @compiler = Compiler.new "clang++", ["-Isrc/components"], []
17
- @cwd = Dir.new(Dir.pwd)
18
- @workspace = "#{Dir.pwd}/#{@name}"
19
- @src = "#{@workspace}/src"
20
- @components = "#{@src}/components"
21
- @obj = "#{@workspace}/obj"
22
- @third = "#{@workspace}/third-party"
23
- @target = "#{@workspace}/target"
24
- @tests = "#{@workspace}/tests"
25
- @mode = mode
26
- @deps = ".canoe.deps"
21
+ def initialize(name, mode, src_suffix = 'cpp', hdr_suffix = 'hpp', nu = false)
22
+ @name = name
23
+ @compiler = Compiler.new 'clang++', ['-Isrc/components'], []
24
+ @cwd = Dir.new(Dir.pwd)
25
+ @workspace = Dir.pwd.to_s + (nu ? "/#{@name}" : '')
26
+ @src = "#{@workspace}/src"
27
+ @components = "#{@src}/components"
28
+ @obj = "#{@workspace}/obj"
29
+ @third = "#{@workspace}/third-party"
30
+ @target = "#{@workspace}/target"
31
+ @tests = "#{@workspace}/tests"
32
+ @mode = mode
33
+ @deps = '.canoe.deps'
34
+ @test_deps = '.canoe.test.deps'
27
35
 
28
- @src_prefix = "./src/"
29
- @components_prefix = "./src/components/"
30
- @obj_prefix = "./obj/"
36
+ @target_short = './target'
37
+ @src_short = './src'
38
+ @components_short = "#{@src_short}/components"
39
+ @obj_short = './obj'
40
+ @tests_short = './tests'
31
41
 
32
- @source_suffix = src_suffix
33
- @header_suffix = hdr_suffix
34
- end
42
+ @src_prefix = './src/'
43
+ @components_prefix = './src/components/'
44
+ @obj_prefix = './obj/'
35
45
 
36
- def inspect
37
- puts "name is #{@name}"
38
- puts "name is #{@workspace}"
46
+ @source_suffix = src_suffix
47
+ @header_suffix = hdr_suffix
48
+ end
39
49
  end
40
50
  end
41
51
 
42
- require_relative "help"
43
- require_relative "version"
44
- require_relative "new"
45
- require_relative "add"
46
- require_relative "build"
47
- require_relative "generate"
48
- require_relative "run"
49
- require_relative "dep"
50
- require_relative "clean"
51
- require_relative "update"
52
- require_relative "test"
53
- require_relative "make"
52
+ require_relative 'help'
53
+ require_relative 'version'
54
+ require_relative 'new'
55
+ require_relative 'add'
56
+ require_relative 'build'
57
+ require_relative 'generate'
58
+ require_relative 'run'
59
+ require_relative 'dep'
60
+ require_relative 'clean'
61
+ require_relative 'update'
62
+ require_relative 'test'
63
+ 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.1.1
4
+ version: 0.3.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: 2021-02-25 00:00:00.000000000 Z
11
+ date: 2021-05-12 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,8 +33,8 @@ 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
data/lib/err.rb DELETED
@@ -1,21 +0,0 @@
1
- require_relative "coloring"
2
-
3
- module Err
4
- def warn_on_err(err)
5
- puts <<~ERR
6
- #{"Waring: ".yellow}
7
- #{err}
8
- try 'canoe help' for more information
9
- ERR
10
- end
11
-
12
- def abort_on_err(err)
13
- abort <<~ERR
14
- #{"Fatal: ".red}
15
- #{err}
16
- try 'canoe help' for more information
17
- ERR
18
- end
19
-
20
- module_function :warn_on_err, :abort_on_err
21
- end