canoe 0.3.1 → 0.3.2.3

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
+ compiler = @source_suffix == 'c' ? 'clang' : 'clang++'
19
+ DefaultFiles.create_config @workspace, compiler, @source_suffix, @header_suffix
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,144 @@
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
30
46
 
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
47
+ def test_single(name)
48
+ rebuild = false;
49
+ bin = "#{@target_short}/test_#{name}"
50
+ rebuild ||= !File.exist?(bin)
51
+
52
+ file = "#{@tests_short}/test_#{name}.#{@source_suffix}"
53
+
54
+ deps = fetch_all_deps
55
+ extract_one_file(file, deps).push(file).each do |f|
56
+ rebuild ||= File.mtime(bin) < File.mtime(f)
57
+ end
58
+
59
+ build_compiler_from_config && build_one_test(file, deps) if rebuild
60
+
61
+ issue_command bin
62
+ end
63
+
64
+ def fetch_all_test_files
65
+ Dir.glob("#{@tests_short}/*.#{@source_suffix}").filter do |f|
66
+ File.basename(f).start_with? 'test_'
67
+ end
68
+ end
69
+
70
+ def fetch_all_deps
71
+ target_deps.merge(tests_deps)
72
+ end
73
+
74
+ def test_build_time
75
+ fetch_all_test_files.map do |f|
76
+ obj = "#{@target_short}/#{File.basename(f, '.*')}"
77
+ File.exist?(obj) ? File.mtime(obj) : Time.new(0)
78
+ end.min
79
+ end
80
+
81
+ # @deps is the dependency hash for tests
82
+ # cyclic dependency is not handled
83
+ # compiler should first be built
84
+ def compile_one_test(test_file, deps)
85
+ extract_one_file(test_file, deps).each do |f|
86
+ o = file_to_obj(f)
87
+ next if File.exist?(o) && File.mtime(o) > File.mtime(f)
88
+
89
+ compile(f, o)
90
+ end
91
+ compile(test_file, file_to_obj(test_file))
92
+ end
93
+
94
+ def link_one_test(test_file, deps)
95
+ target = "#{@target_short}/#{File.basename(test_file, '.*')}"
96
+ @compiler.link_executable target, extract_one_file_obj(test_file, deps) + [file_to_obj(test_file)]
97
+ end
98
+
99
+ def build_one_test(test_file, deps)
100
+ compile_one_test(test_file, deps)
101
+ link_one_test(test_file, deps)
102
+ end
103
+
104
+ def compile_all_tests(deps)
105
+ files = DepAnalyzer.compiling_filter(deps, test_build_time, @source_suffix, @header_suffix).select do |f|
106
+ File.basename(f).start_with?('test_')
107
+ end
108
+
109
+ stepper = Stepper.new fetch_all_test_files.size, files.size
110
+
111
+ files.each do |f|
112
+ printf "#{stepper.progress_as_str.green} compiling #{f} "
113
+ compile_one_test(f, deps)
114
+ stepper.step
115
+ end
116
+ end
117
+
118
+ def link_all_tests(deps)
119
+ all_files = fetch_all_test_files
120
+
121
+ stepper = Stepper.new all_files.size, all_files.size
122
+ fetch_all_test_files.each do |f|
123
+ printf "#{stepper.progress_as_str.green} linking #{File.basename(f, '.*').yellow}: "
124
+ link_one_test(f, deps)
125
+ stepper.step
126
+ end
127
+ end
128
+
129
+ def build_test
130
+ puts "#{'[COMPILING TESTS]'.magenta}..."
131
+ return unless test_build_time
132
+
133
+ total_deps = fetch_all_deps
134
+ compile_all_tests(total_deps)
135
+ puts "#{'[100%]'.green} compiling done, starts linking..."
136
+ puts "#{'[LINKING TESTS]'.magenta}..."
137
+ # compilation and link are separated because they may be separated
138
+ # by unexpected interrupt like C-c, C-d, etc.
139
+ # thus unditionally link all tests
140
+ link_all_tests(total_deps)
141
+ puts "#{'[100%]'.green} linking done"
142
+ end
40
143
  end
41
144
  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
@@ -0,0 +1,15 @@
1
+ module Canoe
2
+ class WorkSpace
3
+ def self.version
4
+ puts <<~VER
5
+ canoe v0.3.2.3
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
13
+ end
14
+ end
15
+ end
@@ -1,52 +1,65 @@
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
+ # 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
13
22
 
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"
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'
27
37
 
28
- @src_prefix = "./src/"
29
- @components_prefix = "./src/components/"
30
- @obj_prefix = "./obj/"
38
+ @target_short = './target'
39
+ @src_short = './src'
40
+ @components_short = "#{@src_short}/components"
41
+ @obj_short = './obj'
42
+ @tests_short = './tests'
31
43
 
32
- @source_suffix = src_suffix
33
- @header_suffix = hdr_suffix
34
- end
44
+ @src_prefix = './src/'
45
+ @components_prefix = './src/components/'
46
+ @obj_prefix = './obj/'
35
47
 
36
- def inspect
37
- puts "name is #{@name}"
38
- puts "name is #{@workspace}"
48
+ @source_suffix = src_suffix
49
+ @header_suffix = hdr_suffix
50
+ end
39
51
  end
40
52
  end
41
53
 
42
- require_relative "help"
43
- require_relative "new"
44
- require_relative "add"
45
- require_relative "build"
46
- require_relative "generate"
47
- require_relative "run"
48
- require_relative "dep"
49
- require_relative "clean"
50
- require_relative "update"
51
- require_relative "test"
52
- require_relative "make"
54
+ require_relative 'help'
55
+ require_relative 'version'
56
+ require_relative 'new'
57
+ require_relative 'add'
58
+ require_relative 'build'
59
+ require_relative 'generate'
60
+ require_relative 'run'
61
+ require_relative 'dep'
62
+ require_relative 'clean'
63
+ require_relative 'update'
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.1
4
+ version: 0.3.2.3
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-15 00:00:00.000000000 Z
11
+ date: 2021-05-18 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
@@ -46,6 +46,7 @@ files:
46
46
  - lib/workspace/run.rb
47
47
  - lib/workspace/test.rb
48
48
  - lib/workspace/update.rb
49
+ - lib/workspace/version.rb
49
50
  - lib/workspace/workspace.rb
50
51
  homepage: https://github.com/Dicridon/canoe
51
52
  licenses:
@@ -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,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