canoe 0.3.0.2 → 0.3.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 +4 -4
- data/lib/canoe.rb +13 -12
- data/lib/cmd.rb +26 -20
- data/lib/coloring.rb +9 -9
- data/lib/compiler.rb +1 -2
- data/lib/config_reader.rb +1 -1
- data/lib/default_files.rb +17 -12
- data/lib/dependence.rb +23 -20
- data/lib/err.rb +4 -3
- data/lib/source_files.rb +4 -4
- data/lib/workspace/add.rb +5 -4
- data/lib/workspace/build.rb +24 -23
- data/lib/workspace/clean.rb +4 -3
- data/lib/workspace/dep.rb +2 -2
- data/lib/workspace/generate.rb +1 -2
- data/lib/workspace/help.rb +69 -64
- data/lib/workspace/make.rb +232 -0
- data/lib/workspace/new.rb +3 -3
- data/lib/workspace/run.rb +1 -1
- data/lib/workspace/test.rb +8 -6
- data/lib/workspace/update.rb +1 -1
- data/lib/workspace/workspace.rb +27 -28
- metadata +3 -3
- data/lib/workspace/version.rb +0 -13
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: af31768c0b36d635c13ff31e41dc772dd9834ccd2d52e791f399053ebb3b9782
|
|
4
|
+
data.tar.gz: 135f95f9631bcc43c4817833ee9a6075b1d336239b9131c8f5f26d3f0006cd3b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9c82734822d59c1cd1a119dcc55f954f3d6b971457f44df22c8e9f6eceaa638c503816a1f05dc54019ea8ded2c70f1431e26cab0c057db3cd4ee2775dc12583c
|
|
7
|
+
data.tar.gz: 9b23406264a260e2b715018f5ad275c6a8b9293d712fd4d7623b03709fa5d93ee03cbc916472d9b24e9e6e1d4e2dd83e6781903ca7987febc4ec28a3e92e0ce5
|
data/lib/canoe.rb
CHANGED
|
@@ -4,21 +4,22 @@ require_relative "source_files"
|
|
|
4
4
|
|
|
5
5
|
class Canoe
|
|
6
6
|
def initialize
|
|
7
|
-
options = [
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
7
|
+
options = ["new",
|
|
8
|
+
"add",
|
|
9
|
+
"build",
|
|
10
|
+
"generate",
|
|
11
|
+
"make",
|
|
12
|
+
"run",
|
|
13
|
+
"dep",
|
|
14
|
+
"clean",
|
|
15
|
+
"version",
|
|
16
|
+
"help",
|
|
17
|
+
"update",
|
|
18
|
+
"test"]
|
|
18
19
|
@cmd = CmdParser.new options
|
|
19
20
|
end
|
|
20
21
|
|
|
21
22
|
def parse(args)
|
|
22
|
-
|
|
23
|
+
@cmd.parse args
|
|
23
24
|
end
|
|
24
25
|
end
|
data/lib/cmd.rb
CHANGED
|
@@ -7,13 +7,14 @@ require_relative "config_reader"
|
|
|
7
7
|
# Parsing command arguments passed to canoe
|
|
8
8
|
class CmdParser
|
|
9
9
|
include Err
|
|
10
|
+
|
|
10
11
|
def initialize(options)
|
|
11
|
-
@options = options
|
|
12
|
+
@options = options
|
|
12
13
|
end
|
|
13
14
|
|
|
14
15
|
def parse(args)
|
|
15
|
-
if args.size < 1
|
|
16
|
-
abort_on_err "please give one command among #{@options.join(
|
|
16
|
+
if args.size < 1
|
|
17
|
+
abort_on_err "please give one command among #{@options.join(", ")}"
|
|
17
18
|
end
|
|
18
19
|
|
|
19
20
|
unless @options.include?(args[0])
|
|
@@ -24,6 +25,7 @@ class CmdParser
|
|
|
24
25
|
end
|
|
25
26
|
|
|
26
27
|
private
|
|
28
|
+
|
|
27
29
|
def get_current_workspace
|
|
28
30
|
abort_on_err "not in a canoe workspace" unless File.exists? ".canoe"
|
|
29
31
|
config = ConfigReader.extract_flags("config.json")
|
|
@@ -34,7 +36,7 @@ class CmdParser
|
|
|
34
36
|
name = Dir.pwd.split("/")[-1]
|
|
35
37
|
mode = File.exists?("src/main.#{src_sfx}") ? :bin : :lib
|
|
36
38
|
|
|
37
|
-
Dir.chdir(
|
|
39
|
+
Dir.chdir("..") do
|
|
38
40
|
return WorkSpace.new(name, mode, src_sfx, hdr_sfx)
|
|
39
41
|
end
|
|
40
42
|
end
|
|
@@ -44,10 +46,10 @@ class CmdParser
|
|
|
44
46
|
|
|
45
47
|
name, mode = nil, "bin"
|
|
46
48
|
suffixes = ["cpp", "hpp"]
|
|
47
|
-
|
|
49
|
+
|
|
48
50
|
args.each do |arg|
|
|
49
51
|
case arg
|
|
50
|
-
when
|
|
52
|
+
when "--bin", "--lib"
|
|
51
53
|
mode = arg[2..]
|
|
52
54
|
when /--suffix=(\w+)\:(\w+)/
|
|
53
55
|
suffixes[0], suffixes[1] = $1, $2
|
|
@@ -55,7 +57,7 @@ class CmdParser
|
|
|
55
57
|
name = arg unless name
|
|
56
58
|
end
|
|
57
59
|
end
|
|
58
|
-
|
|
60
|
+
|
|
59
61
|
abort_on_err("please give a name to this project") unless name
|
|
60
62
|
WorkSpace.new(name, mode.to_sym, suffixes[0], suffixes[1]).new
|
|
61
63
|
end
|
|
@@ -67,7 +69,7 @@ class CmdParser
|
|
|
67
69
|
|
|
68
70
|
get_current_workspace.add args
|
|
69
71
|
end
|
|
70
|
-
|
|
72
|
+
|
|
71
73
|
def parse_build(args)
|
|
72
74
|
get_current_workspace.build args
|
|
73
75
|
end
|
|
@@ -75,15 +77,15 @@ class CmdParser
|
|
|
75
77
|
def parse_generate(args)
|
|
76
78
|
get_current_workspace.generate
|
|
77
79
|
end
|
|
78
|
-
|
|
80
|
+
|
|
79
81
|
def parse_run(args)
|
|
80
82
|
get_current_workspace.run args
|
|
81
83
|
end
|
|
82
84
|
|
|
83
85
|
def parse_dep(args)
|
|
84
|
-
get_current_workspace.dep
|
|
86
|
+
get_current_workspace.dep
|
|
85
87
|
end
|
|
86
|
-
|
|
88
|
+
|
|
87
89
|
def parse_clean(args)
|
|
88
90
|
get_current_workspace.clean
|
|
89
91
|
end
|
|
@@ -94,16 +96,16 @@ class CmdParser
|
|
|
94
96
|
|
|
95
97
|
def parse_version(args)
|
|
96
98
|
puts <<~VER
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
99
|
+
canoe v0.3.1
|
|
100
|
+
For features in this version, please visit https://github.com/Dicridon/canoe
|
|
101
|
+
Currently, canoe can do below:
|
|
102
|
+
- project creation
|
|
103
|
+
- project auto build and run (works like Cargo for Rust)
|
|
104
|
+
- project structure management
|
|
105
|
+
by XIONG Ziwei
|
|
106
|
+
VER
|
|
105
107
|
end
|
|
106
|
-
|
|
108
|
+
|
|
107
109
|
def parse_help(args)
|
|
108
110
|
WorkSpace.help
|
|
109
111
|
end
|
|
@@ -111,4 +113,8 @@ class CmdParser
|
|
|
111
113
|
def parse_update(args)
|
|
112
114
|
get_current_workspace.update
|
|
113
115
|
end
|
|
116
|
+
|
|
117
|
+
def parse_make(args)
|
|
118
|
+
get_current_workspace.make
|
|
119
|
+
end
|
|
114
120
|
end
|
data/lib/coloring.rb
CHANGED
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
class String
|
|
4
4
|
def self.define_coloring_methods
|
|
5
5
|
colors = {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
14
|
}
|
|
15
15
|
colors.each do |k, v|
|
|
16
16
|
define_method v do
|
|
@@ -20,4 +20,4 @@ class String
|
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
define_coloring_methods
|
|
23
|
-
end
|
|
23
|
+
end
|
data/lib/compiler.rb
CHANGED
|
@@ -20,7 +20,6 @@ class Compiler
|
|
|
20
20
|
@linking_flags.join " "
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
|
|
24
23
|
def append_compiling_flag(flag)
|
|
25
24
|
@compiling_flags << flag
|
|
26
25
|
end
|
|
@@ -43,7 +42,7 @@ class Compiler
|
|
|
43
42
|
puts "#{name} -shared -o #{out}.so #{objs.join(" ")} #{linking_flags_as_str}"
|
|
44
43
|
system "#{name} -shared -o #{out}.so #{objs.join(" ")} #{linking_flags_as_str}"
|
|
45
44
|
end
|
|
46
|
-
|
|
45
|
+
|
|
47
46
|
def inspect
|
|
48
47
|
puts "compiler name: #{name.inspect}"
|
|
49
48
|
puts "compiler flags: #{flags.inspect}"
|
data/lib/config_reader.rb
CHANGED
data/lib/default_files.rb
CHANGED
|
@@ -10,9 +10,9 @@ class DefaultFiles
|
|
|
10
10
|
end
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
def create_config(path, src_sfx=
|
|
13
|
+
def create_config(path, src_sfx = "cpp", hdr_sfx = "hpp")
|
|
14
14
|
open_file_and_write(
|
|
15
|
-
"#{path}/config.json",
|
|
15
|
+
"#{path}/config.json",
|
|
16
16
|
<<~CONFIG
|
|
17
17
|
{
|
|
18
18
|
"compiler": "clang++",
|
|
@@ -30,10 +30,11 @@ class DefaultFiles
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
CONFIG
|
|
33
|
-
|
|
33
|
+
|
|
34
|
+
)
|
|
34
35
|
end
|
|
35
36
|
|
|
36
|
-
def create_main(path, suffix=
|
|
37
|
+
def create_main(path, suffix = "cpp")
|
|
37
38
|
open_file_and_write(
|
|
38
39
|
"#{path}/main.#{suffix}",
|
|
39
40
|
<<~DOC
|
|
@@ -42,10 +43,11 @@ class DefaultFiles
|
|
|
42
43
|
std::cout << "hello world!" << std::endl;
|
|
43
44
|
}
|
|
44
45
|
DOC
|
|
45
|
-
|
|
46
|
+
|
|
47
|
+
)
|
|
46
48
|
end
|
|
47
49
|
|
|
48
|
-
def create_lib_header(path, lib_name, suffix=
|
|
50
|
+
def create_lib_header(path, lib_name, suffix = "hpp")
|
|
49
51
|
open_file_and_write(
|
|
50
52
|
"#{path}/#{lib_name}.#{suffix}",
|
|
51
53
|
<<~DOC
|
|
@@ -54,7 +56,8 @@ class DefaultFiles
|
|
|
54
56
|
|
|
55
57
|
#endif
|
|
56
58
|
DOC
|
|
57
|
-
|
|
59
|
+
|
|
60
|
+
)
|
|
58
61
|
end
|
|
59
62
|
|
|
60
63
|
# def create_emacs_dir_local(path)
|
|
@@ -69,16 +72,17 @@ class DefaultFiles
|
|
|
69
72
|
# )
|
|
70
73
|
# end
|
|
71
74
|
|
|
72
|
-
def create_cpp(filename, src_sfx=
|
|
75
|
+
def create_cpp(filename, src_sfx = "cpp", hdr_sfx = "hpp")
|
|
73
76
|
open_file_and_write(
|
|
74
|
-
"#{filename}.#{src_sfx}",
|
|
77
|
+
"#{filename}.#{src_sfx}",
|
|
75
78
|
<<~DOC
|
|
76
79
|
#include "#{filename}.#{hdr_sfx}"
|
|
77
80
|
DOC
|
|
78
|
-
|
|
81
|
+
|
|
82
|
+
)
|
|
79
83
|
end
|
|
80
84
|
|
|
81
|
-
def create_hpp(workspace, prefix, filename, hdr_sfx=
|
|
85
|
+
def create_hpp(workspace, prefix, filename, hdr_sfx = "hpp")
|
|
82
86
|
open_file_and_write(
|
|
83
87
|
"#{filename}.#{hdr_sfx}",
|
|
84
88
|
<<~DOC
|
|
@@ -87,7 +91,8 @@ class DefaultFiles
|
|
|
87
91
|
|
|
88
92
|
#endif
|
|
89
93
|
DOC
|
|
90
|
-
|
|
94
|
+
|
|
95
|
+
)
|
|
91
96
|
end
|
|
92
97
|
end
|
|
93
98
|
end
|
data/lib/dependence.rb
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
require_relative
|
|
2
|
-
require_relative
|
|
1
|
+
require_relative "source_files"
|
|
2
|
+
require_relative "err"
|
|
3
3
|
|
|
4
4
|
##
|
|
5
5
|
# class DepAnalyzer
|
|
6
|
-
# This class is the key component of canoe, which offers file dependency analysis functionality.
|
|
6
|
+
# This class is the key component of canoe, which offers file dependency analysis functionality.
|
|
7
7
|
# A DepAnalyzer takes a directory as input, sources files and corresponding header files in this
|
|
8
|
-
# directory should have same name,
|
|
8
|
+
# directory should have same name, e.g. test.cpp and test.hpp.
|
|
9
9
|
# DepAnalyzer would read every source file and recursively process user header files included in this source file to
|
|
10
10
|
# find out all user header files this source file depends on.
|
|
11
11
|
# Based on dependencies built in previous stage, DepAnalyzer determines which files should be recompiled and return
|
|
@@ -20,15 +20,15 @@ class DepAnalyzer
|
|
|
20
20
|
File.open(filename, "r") do |f|
|
|
21
21
|
ret = Hash.new []
|
|
22
22
|
f.each_with_index do |line, i|
|
|
23
|
-
entry = line.split(
|
|
24
|
-
Err.abort_on_err("Bad .canoe.deps format, line #{i+1}") unless entry.length == 2
|
|
23
|
+
entry = line.split(": ")
|
|
24
|
+
Err.abort_on_err("Bad .canoe.deps format, line #{i + 1}") unless entry.length == 2
|
|
25
25
|
ret[entry[0]] = entry[1].split
|
|
26
|
-
end
|
|
26
|
+
end
|
|
27
27
|
ret
|
|
28
28
|
end
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
-
def self.compiling_filter(deps, build_time, src_sfx=
|
|
31
|
+
def self.compiling_filter(deps, build_time, src_sfx = "cpp", hdr_sfx = "hpp")
|
|
32
32
|
files = []
|
|
33
33
|
@processed = {}
|
|
34
34
|
@recompiles = {}
|
|
@@ -57,6 +57,7 @@ class DepAnalyzer
|
|
|
57
57
|
end
|
|
58
58
|
|
|
59
59
|
private
|
|
60
|
+
|
|
60
61
|
def self.mark(file, build_time, deps)
|
|
61
62
|
ret = false
|
|
62
63
|
return false unless File.exists? file
|
|
@@ -71,21 +72,21 @@ class DepAnalyzer
|
|
|
71
72
|
@processed[f] = true
|
|
72
73
|
if mark(f, build_time, deps)
|
|
73
74
|
@recompiles[f] = true
|
|
74
|
-
return true
|
|
75
|
+
return true
|
|
75
76
|
end
|
|
76
77
|
end
|
|
77
78
|
end
|
|
78
79
|
ret
|
|
79
80
|
end
|
|
80
81
|
|
|
81
|
-
def self.should_recompile?(file, build_time)
|
|
82
|
+
def self.should_recompile?(file, build_time)
|
|
82
83
|
judge = build_time
|
|
83
84
|
if build_time == Time.new(0)
|
|
84
85
|
objfile = if file.start_with?("./src/components")
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
86
|
+
"./obj/" + file.delete_suffix(File.extname(file))["./src/components/".length..].gsub("/", "_") + ".o"
|
|
87
|
+
else
|
|
88
|
+
"./obj/#{File.basename(file, ".*")}.o"
|
|
89
|
+
end
|
|
89
90
|
return true unless File.exists? objfile
|
|
90
91
|
judge = File.mtime(objfile)
|
|
91
92
|
end
|
|
@@ -93,7 +94,8 @@ class DepAnalyzer
|
|
|
93
94
|
end
|
|
94
95
|
|
|
95
96
|
public
|
|
96
|
-
|
|
97
|
+
|
|
98
|
+
def initialize(dir, src_sfx = "cpp", hdr_sfx = "hpp")
|
|
97
99
|
@dir = dir
|
|
98
100
|
@deps = Hash.new []
|
|
99
101
|
@source_suffix = src_sfx
|
|
@@ -115,25 +117,26 @@ class DepAnalyzer
|
|
|
115
117
|
|
|
116
118
|
def build_to_file(include_path, filename)
|
|
117
119
|
build_dependence include_path
|
|
118
|
-
|
|
120
|
+
|
|
119
121
|
File.open(filename, "w") do |f|
|
|
120
122
|
@deps.each do |k, v|
|
|
121
123
|
f.write "#{k}: #{v.join(" ")}\n"
|
|
122
124
|
end
|
|
123
125
|
end
|
|
124
|
-
|
|
126
|
+
|
|
125
127
|
@deps
|
|
126
128
|
end
|
|
127
129
|
|
|
128
130
|
private
|
|
129
|
-
|
|
131
|
+
|
|
132
|
+
def get_all_headers(include_path, file, suffix = "hpp")
|
|
130
133
|
File.open(file, "r") do |f|
|
|
131
134
|
ret = []
|
|
132
135
|
if file.end_with?(".#{@source_suffix}")
|
|
133
136
|
header = file.sub(".#{@source_suffix}", ".#{@header_suffix}")
|
|
134
137
|
ret += [header] if File.exists?(header)
|
|
135
138
|
end
|
|
136
|
-
|
|
139
|
+
|
|
137
140
|
f.each_line do |line|
|
|
138
141
|
if mat = line.match(/include "(.+\.#{suffix})"/)
|
|
139
142
|
include_path.each do |path|
|
|
@@ -142,7 +145,7 @@ class DepAnalyzer
|
|
|
142
145
|
end
|
|
143
146
|
end
|
|
144
147
|
end
|
|
145
|
-
|
|
148
|
+
|
|
146
149
|
ret.uniq
|
|
147
150
|
end
|
|
148
151
|
end
|
data/lib/err.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
require_relative
|
|
1
|
+
require_relative "coloring"
|
|
2
|
+
|
|
2
3
|
module Err
|
|
3
4
|
def warn_on_err(err)
|
|
4
5
|
puts <<~ERR
|
|
@@ -13,8 +14,8 @@ module Err
|
|
|
13
14
|
#{"Fatal: ".red}
|
|
14
15
|
#{err}
|
|
15
16
|
try 'canoe help' for more information
|
|
16
|
-
|
|
17
|
+
ERR
|
|
17
18
|
end
|
|
18
19
|
|
|
19
20
|
module_function :warn_on_err, :abort_on_err
|
|
20
|
-
end
|
|
21
|
+
end
|
data/lib/source_files.rb
CHANGED
|
@@ -5,7 +5,7 @@ class SourceFiles
|
|
|
5
5
|
class << self
|
|
6
6
|
def get_all(dir, &block)
|
|
7
7
|
@files = []
|
|
8
|
-
get_all_helper(dir, &block)
|
|
8
|
+
get_all_helper(dir, &block)
|
|
9
9
|
@files
|
|
10
10
|
end
|
|
11
11
|
|
|
@@ -19,13 +19,14 @@ class SourceFiles
|
|
|
19
19
|
else
|
|
20
20
|
@files << "#{file}"
|
|
21
21
|
end
|
|
22
|
-
end
|
|
22
|
+
end
|
|
23
23
|
end
|
|
24
|
-
|
|
24
|
+
|
|
25
25
|
@files
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
private
|
|
29
|
+
|
|
29
30
|
def get_all_helper(dir, &block)
|
|
30
31
|
Dir.each_child(dir) do |f|
|
|
31
32
|
file = "#{dir}/#{f}"
|
|
@@ -42,4 +43,3 @@ class SourceFiles
|
|
|
42
43
|
end
|
|
43
44
|
end
|
|
44
45
|
end
|
|
45
|
-
|
data/lib/workspace/add.rb
CHANGED
|
@@ -8,19 +8,20 @@ class WorkSpace
|
|
|
8
8
|
dir += "/#{filename}"
|
|
9
9
|
prefix << filename
|
|
10
10
|
unless Dir.exist? dir
|
|
11
|
-
FileUtils.mkdir dir
|
|
11
|
+
FileUtils.mkdir dir
|
|
12
12
|
Dir.chdir(dir) do
|
|
13
13
|
puts "created " + Dir.pwd.blue
|
|
14
|
-
create_working_files prefix.join(
|
|
14
|
+
create_working_files prefix.join("__"), filename
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
private
|
|
21
|
+
private
|
|
22
|
+
|
|
22
23
|
def create_working_files(prefix, filename)
|
|
23
24
|
DefaultFiles.create_cpp filename, @source_suffix, @header_suffix
|
|
24
25
|
DefaultFiles.create_hpp @name, prefix, filename, @header_suffix
|
|
25
26
|
end
|
|
26
|
-
end
|
|
27
|
+
end
|
data/lib/workspace/build.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
class WorkSpace
|
|
2
|
-
# args are commandline parameters passed to `canoe build`,
|
|
2
|
+
# args are commandline parameters passed to `canoe build`,
|
|
3
3
|
# could be 'all', 'test', 'target' or empty
|
|
4
4
|
def build(args)
|
|
5
5
|
case args[0]
|
|
@@ -12,8 +12,9 @@ class WorkSpace
|
|
|
12
12
|
end
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
private
|
|
16
|
-
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def build_flags(flags, config)
|
|
17
18
|
config.values.each do |v|
|
|
18
19
|
case v
|
|
19
20
|
when String
|
|
@@ -31,12 +32,12 @@ private
|
|
|
31
32
|
def build_compiler_from_config
|
|
32
33
|
Dir.chdir(@workspace) do
|
|
33
34
|
flags = ConfigReader.extract_flags "config.json"
|
|
34
|
-
compiler_name = flags[
|
|
35
|
+
compiler_name = flags["compiler"] ? flags["compiler"] : "clang++"
|
|
35
36
|
abort_on_err "compiler #{compiler_name} not found" unless File.exists?("/usr/bin/#{compiler_name}")
|
|
36
|
-
compiler_flags = [
|
|
37
|
+
compiler_flags = ["-Isrc/components"]
|
|
37
38
|
linker_flags = []
|
|
38
39
|
|
|
39
|
-
c_flags, l_flags = flags[
|
|
40
|
+
c_flags, l_flags = flags["flags"]["compile"], flags["flags"]["link"]
|
|
40
41
|
build_flags(compiler_flags, c_flags)
|
|
41
42
|
build_flags(linker_flags, l_flags)
|
|
42
43
|
|
|
@@ -61,9 +62,9 @@ private
|
|
|
61
62
|
def build_bin(files)
|
|
62
63
|
# return if files.empty?
|
|
63
64
|
build_compiler_from_config
|
|
64
|
-
if build_common(files) && link_exectutable(
|
|
65
|
-
|
|
66
|
-
else
|
|
65
|
+
if build_common(files) && link_exectutable("./target", Dir.glob("obj/*.o"))
|
|
66
|
+
puts "BUILDING SUCCEEDED".green
|
|
67
|
+
else
|
|
67
68
|
puts "building FAILED".red
|
|
68
69
|
end
|
|
69
70
|
end
|
|
@@ -71,28 +72,28 @@ private
|
|
|
71
72
|
def build_lib(files)
|
|
72
73
|
# return if files.empty?
|
|
73
74
|
build_compiler_from_config
|
|
74
|
-
@compiler.append_compiling_flag
|
|
75
|
-
if build_common(files) && link_shared(
|
|
75
|
+
@compiler.append_compiling_flag "-fPIC"
|
|
76
|
+
if build_common(files) && link_shared("./target", Dir.glob("obj/*.o"))
|
|
76
77
|
puts "BUILDING SUCCEEDED".green
|
|
77
|
-
else
|
|
78
|
+
else
|
|
78
79
|
puts "building FAILED".red
|
|
79
80
|
end
|
|
80
81
|
end
|
|
81
82
|
|
|
82
83
|
def build_common(files)
|
|
83
|
-
all = SourceFiles.get_all(
|
|
84
|
+
all = SourceFiles.get_all("./src") { |f| f.end_with? @source_suffix }
|
|
84
85
|
total = all.size.to_f
|
|
85
86
|
compiled = total - files.size
|
|
86
|
-
comps = files.select {|f| f.start_with? @components_prefix}
|
|
87
|
+
comps = files.select { |f| f.start_with? @components_prefix }
|
|
87
88
|
srcs = files - comps
|
|
88
|
-
flag = true
|
|
89
|
-
|
|
89
|
+
flag = true
|
|
90
|
+
|
|
90
91
|
srcs.each do |f|
|
|
91
92
|
progress = (compiled / total).round(2) * 100
|
|
92
93
|
printf "[#{progress.to_i}%%]".green + " compiling #{f}: "
|
|
93
94
|
fname = f.split("/")[-1]
|
|
94
|
-
o = @obj_prefix + File.basename(fname, ".*") +
|
|
95
|
-
flag = false unless compile f, o
|
|
95
|
+
o = @obj_prefix + File.basename(fname, ".*") + ".o"
|
|
96
|
+
flag = false unless compile f, o
|
|
96
97
|
compiled += 1
|
|
97
98
|
end
|
|
98
99
|
|
|
@@ -100,7 +101,7 @@ private
|
|
|
100
101
|
progress = (compiled / total).round(2) * 100
|
|
101
102
|
printf "[#{progress.to_i}%%]".green + " compiling #{f}: "
|
|
102
103
|
o = @obj_prefix + f.delete_suffix(File.extname(f))[@components_prefix.length..]
|
|
103
|
-
|
|
104
|
+
.gsub("/", "_") + ".o"
|
|
104
105
|
flag = false unless compile f, o
|
|
105
106
|
compiled += 1
|
|
106
107
|
end
|
|
@@ -113,9 +114,9 @@ private
|
|
|
113
114
|
end
|
|
114
115
|
|
|
115
116
|
def build_target
|
|
116
|
-
deps = File.exist?(@deps) ?
|
|
117
|
-
|
|
118
|
-
|
|
117
|
+
deps = File.exist?(@deps) ?
|
|
118
|
+
DepAnalyzer.read_from(@deps) :
|
|
119
|
+
DepAnalyzer.new("./src").build_to_file(["./src", "./src/components"], @deps)
|
|
119
120
|
target = "./target/#{@name}"
|
|
120
121
|
build_time = File.exist?(target) ? File.mtime(target) : Time.new(0)
|
|
121
122
|
files = DepAnalyzer.compiling_filter(deps, build_time, @source_suffix, @header_suffix)
|
|
@@ -127,4 +128,4 @@ private
|
|
|
127
128
|
|
|
128
129
|
self.send "build_#{@mode.to_s}", files
|
|
129
130
|
end
|
|
130
|
-
end
|
|
131
|
+
end
|
data/lib/workspace/clean.rb
CHANGED
data/lib/workspace/dep.rb
CHANGED
data/lib/workspace/generate.rb
CHANGED
data/lib/workspace/help.rb
CHANGED
|
@@ -1,71 +1,76 @@
|
|
|
1
1
|
class WorkSpace
|
|
2
2
|
def self.help
|
|
3
3
|
info = <<~INFO
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
4
|
+
canoe is a C/C++ project manager, inspired by Rust cargo.
|
|
5
|
+
usage:
|
|
6
|
+
canoe new tada: create a project named 'tada' in current directory
|
|
7
|
+
|
|
8
|
+
canoe build: compile current project (execute this command in project directory)
|
|
9
|
+
|
|
10
|
+
canoe generate: generate dependency relationships and store it in '.canoe.deps' file. Alias: update
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
canoe run: compile and execute current project (execute this command in project directory)
|
|
15
|
-
|
|
16
|
-
canoe clean: remove all generated object files and binary files
|
|
17
|
-
|
|
18
|
-
canoe help: show this help message
|
|
19
|
-
|
|
20
|
-
canoe add tada: add a folder named tada under workspace/components,
|
|
21
|
-
|
|
22
|
-
canoe dep: show current dependency relationships of current project
|
|
23
|
-
|
|
24
|
-
canoe verion: version information
|
|
25
|
-
|
|
26
|
-
new project_name [mode] [suffixes]:
|
|
27
|
-
create a new project with project_name.
|
|
28
|
-
In this project, four directories obj, src, target and third-party will be generated in project directory.
|
|
29
|
-
in src, directory 'components' will be generated if [mode] is '--lib', an extra main.cpp will be generated if [mode] is '--bin'
|
|
30
|
-
|
|
31
|
-
[mode]: --lib for a library and --bin for executable binaries
|
|
32
|
-
[suffixes]: should be in 'source_suffix:header_suffix" format, notice the ':' between two suffixes
|
|
33
|
-
add component_name:
|
|
34
|
-
add a folder named tada under workspace/components.
|
|
35
|
-
two files tada.hpp and tada.cpp would be craeted and intialized. File suffix may differ according users' specifications.
|
|
36
|
-
if component_name is a path separated by '/', then canoe would create folders and corresponding files recursively.
|
|
37
|
-
|
|
38
|
-
generate:
|
|
39
|
-
generate dependence relationship for each file, this may accelarate
|
|
40
|
-
`canoe buid` command. It's recommanded to execute this command everytime
|
|
41
|
-
headers are added or removed from any file.
|
|
42
|
-
|
|
43
|
-
update:
|
|
44
|
-
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.
|
|
45
|
-
So when a file includes new headers or some headers are removed, users have to use 'canoe udpate'
|
|
46
|
-
to update dependency relationships.
|
|
47
|
-
|
|
48
|
-
build [options]:
|
|
49
|
-
build current project, arguments in [options] will be passed to C++ compiler
|
|
12
|
+
canoe update: udpate dependency relationships and store it in '.canoe.deps' file.
|
|
50
13
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
14
|
+
canoe run: compile and execute current project (execute this command in project directory)
|
|
15
|
+
|
|
16
|
+
canoe clean: remove all generated object files and binary files
|
|
17
|
+
|
|
18
|
+
canoe help: show this help message
|
|
19
|
+
|
|
20
|
+
canoe add tada: add a folder named tada under workspace/components,
|
|
21
|
+
|
|
22
|
+
canoe dep: show current dependency relationships of current project
|
|
23
|
+
|
|
24
|
+
canoe verion: version information
|
|
25
|
+
|
|
26
|
+
canoe make: generate a makefile for this project
|
|
27
|
+
|
|
28
|
+
new project_name [mode] [suffixes]:
|
|
29
|
+
create a new project with project_name.
|
|
30
|
+
In this project, four directories obj, src, target and third-party will be generated in project directory.
|
|
31
|
+
in src, directory 'components' will be generated if [mode] is '--lib', an extra main.cpp will be generated if [mode] is '--bin'
|
|
32
|
+
|
|
33
|
+
[mode]: --lib for a library and --bin for executable binaries
|
|
34
|
+
[suffixes]: should be in 'source_suffix:header_suffix" format, notice the ':' between two suffixes
|
|
35
|
+
add component_name:
|
|
36
|
+
add a folder named tada under workspace/components.
|
|
37
|
+
two files tada.hpp and tada.cpp would be craeted and intialized. File suffix may differ according users' specifications.
|
|
38
|
+
if component_name is a path separated by '/', then canoe would create folders and corresponding files recursively.
|
|
39
|
+
|
|
40
|
+
generate:
|
|
41
|
+
generate dependence relationship for each file, this may accelarate
|
|
42
|
+
`canoe buid` command. It's recommanded to execute this command everytime
|
|
43
|
+
headers are added or removed from any file.
|
|
44
|
+
|
|
45
|
+
update:
|
|
46
|
+
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.
|
|
47
|
+
So when a file includes new headers or some headers are removed, users have to use 'canoe udpate'
|
|
48
|
+
to update dependency relationships.
|
|
49
|
+
|
|
50
|
+
build [options]:
|
|
51
|
+
build current project, arguments in [options] will be passed to C++ compiler
|
|
52
|
+
|
|
53
|
+
run [options]:
|
|
54
|
+
build current project with no specific compilation flags, and run this project, passing [options] as command line arguments to the binary
|
|
55
|
+
|
|
56
|
+
clean:
|
|
57
|
+
remove all generated object files and binary files
|
|
58
|
+
|
|
59
|
+
help:
|
|
60
|
+
show this help message
|
|
61
|
+
|
|
62
|
+
verion:
|
|
63
|
+
display version information
|
|
64
|
+
|
|
65
|
+
dep:
|
|
66
|
+
display file dependencies in a better readable way
|
|
67
|
+
|
|
68
|
+
make:
|
|
69
|
+
generate a Makefile for this project
|
|
70
|
+
|
|
71
|
+
@author: written by XIONG Ziwei, ICT, CAS
|
|
72
|
+
@contact: noahxiong@outlook.com
|
|
73
|
+
INFO
|
|
69
74
|
puts info
|
|
70
75
|
end
|
|
71
|
-
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
class Makefile
|
|
2
|
+
def initialize(workspace)
|
|
3
|
+
@workspace = workspace
|
|
4
|
+
@all_names = []
|
|
5
|
+
@common_variables = {}
|
|
6
|
+
@src_variables = {}
|
|
7
|
+
@hdr_variables = {}
|
|
8
|
+
@obj_variables = {}
|
|
9
|
+
@config = {}
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def configure(config)
|
|
13
|
+
@config = config
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def make!(deps)
|
|
17
|
+
File.open("Makefile", "w") do |f|
|
|
18
|
+
if cxx?(get_compiler)
|
|
19
|
+
make_cxx(f, deps)
|
|
20
|
+
else
|
|
21
|
+
make_c(f, deps)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def get_compiler
|
|
29
|
+
@config["compiler"]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def get_header_suffix
|
|
33
|
+
@workspace.header_suffix
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def get_source_suffix
|
|
37
|
+
@workspace.source_suffix
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def get_compiling_flags
|
|
41
|
+
flags = @config["flags"]["compile"].values.join " "
|
|
42
|
+
flags + " -I./src/components"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def get_ldflags
|
|
46
|
+
@config["flags"]["link"].values.select { |v| v.start_with?("-L") }.join " "
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def get_ldlibs
|
|
50
|
+
(@config["flags"]["link"].values - (get_ldflags.split)).join " "
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def cxx?(name)
|
|
54
|
+
return get_compiler.end_with? "++"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def make_cxx(makefile, deps)
|
|
58
|
+
make_common(makefile, "CXX", deps)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def make_c(makefile, deps)
|
|
62
|
+
make_common(makefile, "CC", deps)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def make_common(makefile, compiler_prefix, deps)
|
|
66
|
+
make_compiling_info(makefile, compiler_prefix)
|
|
67
|
+
define_variables(makefile, deps)
|
|
68
|
+
make_rules(makefile, deps)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def make_compiling_info(makefile, compiler_prefix)
|
|
72
|
+
makefile.puts("#{compiler_prefix}=#{get_compiler}")
|
|
73
|
+
makefile.puts("#{compiler_prefix}FLAGS=#{get_compiling_flags}")
|
|
74
|
+
makefile.puts("LDFLAGS=#{get_ldflags}")
|
|
75
|
+
makefile.puts("LDLIBS=#{get_ldlibs}")
|
|
76
|
+
makefile.puts ""
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def define_variables(makefile, deps)
|
|
80
|
+
define_dirs(makefile)
|
|
81
|
+
|
|
82
|
+
src_files = deps.keys.select { |f| f.end_with? get_source_suffix }
|
|
83
|
+
generate_all_names(src_files)
|
|
84
|
+
define_srcs(makefile, src_files)
|
|
85
|
+
makefile.puts ""
|
|
86
|
+
define_hdrs(makefile, src_files)
|
|
87
|
+
makefile.puts ""
|
|
88
|
+
define_objs(makefile, src_files)
|
|
89
|
+
makefile.puts ""
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def extract_name(name, prefix)
|
|
93
|
+
if name.start_with?(prefix)
|
|
94
|
+
name.delete_suffix(File.extname(name))[prefix.length..].gsub("/", "_")
|
|
95
|
+
else
|
|
96
|
+
File.basename(name.split("/")[-1], ".*")
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def generate_all_names(files)
|
|
101
|
+
files.each do |f|
|
|
102
|
+
name = extract_name(f, @workspace.components_prefix).upcase
|
|
103
|
+
@all_names << name
|
|
104
|
+
@src_variables[name] = f
|
|
105
|
+
@hdr_variables[name] = f.gsub(@workspace.source_suffix, @workspace.header_suffix)
|
|
106
|
+
@obj_variables[name] = @workspace.obj_prefix + extract_name(f, @workspace.components_prefix) + ".o"
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def define_dirs(makefile)
|
|
111
|
+
makefile.puts("TARGET_DIR=./target")
|
|
112
|
+
if @workspace.mode == :bin
|
|
113
|
+
makefile.puts("TARGET=$(TARGET_DIR)/#{@workspace.name}")
|
|
114
|
+
else
|
|
115
|
+
makefile.puts("TARGET=$(TARGET_DIR)/lib#{@workspace.name.downcase}.so")
|
|
116
|
+
end
|
|
117
|
+
# note the ending slash
|
|
118
|
+
makefile.puts("OBJ_DIR=#{@workspace.obj_prefix[..-2]}")
|
|
119
|
+
makefile.puts("SRC_DIR=#{@workspace.src_prefix[..-2]}")
|
|
120
|
+
makefile.puts("COMPONENTS_DIR=#{@workspace.components_prefix[..-2]}")
|
|
121
|
+
makefile.puts ""
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def define_srcs(makefile, files)
|
|
125
|
+
@src_variables.each do |k, v|
|
|
126
|
+
makefile.puts("SRC_#{k}=#{v}")
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def define_hdrs(makefile, files)
|
|
131
|
+
@hdr_variables.each do |k, v|
|
|
132
|
+
next if k == "MAIN"
|
|
133
|
+
makefile.puts("HDR_#{k}=#{v}")
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def define_objs(makefile, files)
|
|
138
|
+
@obj_variables.each do |k, v|
|
|
139
|
+
makefile.puts("OBJ_#{k}=#{v}")
|
|
140
|
+
end
|
|
141
|
+
objs = @obj_variables.keys.map { |k| "$(OBJ_#{k})" }.join " "
|
|
142
|
+
makefile.puts("OBJS=#{objs}")
|
|
143
|
+
makefile.puts ""
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def get_all_dep_name(file_name, deps)
|
|
147
|
+
dep = deps[file_name]
|
|
148
|
+
if dep.empty?
|
|
149
|
+
[]
|
|
150
|
+
else
|
|
151
|
+
tmp = dep.map { |n| extract_name(n, @workspace.components_prefix).upcase }
|
|
152
|
+
dep.each do |d|
|
|
153
|
+
tmp += get_all_dep_name(d, deps)
|
|
154
|
+
end
|
|
155
|
+
tmp
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def emit_dependencies(makefile, name, deps)
|
|
160
|
+
as_str = deps.map do |n|
|
|
161
|
+
if n == name
|
|
162
|
+
["$(SRC_#{n})"] + ["$(HDR_#{n})"] * (name == "MAIN" ? 0 : 1)
|
|
163
|
+
else
|
|
164
|
+
"$(#{n}_DEP)"
|
|
165
|
+
end
|
|
166
|
+
end.flatten.join " "
|
|
167
|
+
makefile.puts("#{name}_DEP=#{as_str}")
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def make_dependencies(makefile, deps)
|
|
171
|
+
dep_variables = Hash[@all_names.map { |n| [n, []] }]
|
|
172
|
+
reference = Hash[@all_names.map { |n| [n, []] }]
|
|
173
|
+
@all_names.each do |n|
|
|
174
|
+
dep_variables[n] = ([n] + get_all_dep_name(@src_variables[n], deps)).uniq
|
|
175
|
+
reference[n] = ([n] + get_all_dep_name(@src_variables[n], deps)).uniq
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
# deduplication
|
|
179
|
+
dep_variables.each do |k, v|
|
|
180
|
+
v.each do |n|
|
|
181
|
+
next if n == k
|
|
182
|
+
v = v - reference[n] + [n] if v.include? n
|
|
183
|
+
end
|
|
184
|
+
dep_variables[k] = v
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
dep_variables.each do |k, v|
|
|
188
|
+
emit_dependencies(makefile, k, v)
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def make_rules(makefile, deps)
|
|
193
|
+
make_dependencies(makefile, deps)
|
|
194
|
+
makefile.puts ""
|
|
195
|
+
makefile.puts("all: BIN\n")
|
|
196
|
+
makefile.puts ""
|
|
197
|
+
cmplr = cxx?(get_compiler) ? "CXX" : "CC"
|
|
198
|
+
@all_names.each do |n|
|
|
199
|
+
makefile.puts("$(OBJ_#{n}): $(#{n}_DEP)\n\t$(#{cmplr}) $(#{cmplr}FLAGS) -o $(OBJ_#{n}) -c $(SRC_#{n})")
|
|
200
|
+
makefile.puts ""
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
if @workspace.mode == :bin
|
|
204
|
+
makefile.puts("BIN: $(OBJS)\n\t$(#{cmplr}) $(#{cmplr}FLAGS) -o $(TARGET) $(wildcard ./obj/*.o) $(LDFLAGS) $(LDLIBS)")
|
|
205
|
+
else
|
|
206
|
+
makefile.puts("LIB: $(OBJS)\n\t$(#{cmplr}) $(#{cmplr}FLAGS) -shared -o $(TARGET) $(wildcard ./obj/*.o) -fPIC $(LDFLAGS) $(LDLIBS)")
|
|
207
|
+
end
|
|
208
|
+
makefile.puts ""
|
|
209
|
+
|
|
210
|
+
clean = <<~DOC
|
|
211
|
+
.PHONY: clean
|
|
212
|
+
clean:
|
|
213
|
+
\trm $(TARGET)
|
|
214
|
+
\trm ./obj/*.o
|
|
215
|
+
DOC
|
|
216
|
+
makefile.puts(clean)
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
class WorkSpace
|
|
221
|
+
def make
|
|
222
|
+
config = ConfigReader.extract_flags "config.json"
|
|
223
|
+
|
|
224
|
+
deps = File.exist?(@deps) ?
|
|
225
|
+
DepAnalyzer.read_from(@deps) :
|
|
226
|
+
DepAnalyzer.new("./src").build_to_fil
|
|
227
|
+
|
|
228
|
+
makefile = Makefile.new(self)
|
|
229
|
+
makefile.configure(config)
|
|
230
|
+
makefile.make!(deps)
|
|
231
|
+
end
|
|
232
|
+
end
|
data/lib/workspace/new.rb
CHANGED
|
@@ -9,14 +9,14 @@ class WorkSpace
|
|
|
9
9
|
Dir.mkdir(@components)
|
|
10
10
|
Dir.mkdir("#{@workspace}/obj")
|
|
11
11
|
if @mode == :bin
|
|
12
|
-
DefaultFiles.create_main(@src, @source_suffix)
|
|
12
|
+
DefaultFiles.create_main(@src, @source_suffix)
|
|
13
13
|
else
|
|
14
14
|
DefaultFiles.create_lib_header(@src, @name, @header_suffix)
|
|
15
15
|
end
|
|
16
16
|
File.new("#{@workspace}/.canoe", "w")
|
|
17
17
|
DefaultFiles.create_config @workspace, @source_suffix, @header_suffix
|
|
18
18
|
# DefaultFiles.create_emacs_dir_local @workspace
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
Dir.mkdir(@third)
|
|
21
21
|
Dir.mkdir(@target)
|
|
22
22
|
Dir.mkdir(@tests)
|
|
@@ -25,4 +25,4 @@ class WorkSpace
|
|
|
25
25
|
end
|
|
26
26
|
puts "workspace #{@workspace.blue} is created"
|
|
27
27
|
end
|
|
28
|
-
end
|
|
28
|
+
end
|
data/lib/workspace/run.rb
CHANGED
data/lib/workspace/test.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
class WorkSpace
|
|
2
|
-
public
|
|
2
|
+
public
|
|
3
|
+
|
|
3
4
|
def test(args)
|
|
4
5
|
if args.empty?
|
|
5
6
|
test_all
|
|
@@ -11,12 +12,13 @@ public
|
|
|
11
12
|
when "all"
|
|
12
13
|
test_all
|
|
13
14
|
else
|
|
14
|
-
test_single arg
|
|
15
|
+
test_single arg
|
|
15
16
|
end
|
|
16
17
|
end
|
|
17
18
|
end
|
|
18
19
|
|
|
19
|
-
private
|
|
20
|
+
private
|
|
21
|
+
|
|
20
22
|
def test_all
|
|
21
23
|
puts "tests all"
|
|
22
24
|
end
|
|
@@ -25,7 +27,7 @@ private
|
|
|
25
27
|
puts "#{@tests}/bin/test_#{name}"
|
|
26
28
|
# system "./#{@tests}/bin/test_#{name}"
|
|
27
29
|
end
|
|
28
|
-
|
|
30
|
+
|
|
29
31
|
##
|
|
30
32
|
# how to build:
|
|
31
33
|
# each test file tests one or more components, indicated by included headers
|
|
@@ -33,7 +35,7 @@ private
|
|
|
33
35
|
# TODO
|
|
34
36
|
def build_test
|
|
35
37
|
build
|
|
36
|
-
deps = DepAnalyzer.new(
|
|
38
|
+
deps = DepAnalyzer.new("./tests").build_to_file(["./src", "./src/components", "./tests", "./tests/common"], "./tests/.canoe.deps")
|
|
37
39
|
puts deps
|
|
38
40
|
end
|
|
39
|
-
end
|
|
41
|
+
end
|
data/lib/workspace/update.rb
CHANGED
data/lib/workspace/workspace.rb
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
|
-
require
|
|
2
|
-
require_relative
|
|
3
|
-
require_relative
|
|
4
|
-
require_relative
|
|
5
|
-
require_relative
|
|
6
|
-
require_relative
|
|
7
|
-
require_relative
|
|
8
|
-
require_relative
|
|
9
|
-
|
|
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"
|
|
10
9
|
|
|
11
10
|
class WorkSpace
|
|
12
11
|
include Err
|
|
13
|
-
attr_reader :name, :cwd
|
|
12
|
+
attr_reader :name, :cwd, :src_prefix, :components_prefix, :obj_prefix, :source_suffix, :header_suffix, :mode
|
|
14
13
|
|
|
15
|
-
def initialize(name, mode, src_suffix=
|
|
14
|
+
def initialize(name, mode, src_suffix = "cpp", hdr_suffix = "hpp")
|
|
16
15
|
@name = name
|
|
17
|
-
@compiler = Compiler.new
|
|
16
|
+
@compiler = Compiler.new "clang++", ["-Isrc/components"], []
|
|
18
17
|
@cwd = Dir.new(Dir.pwd)
|
|
19
18
|
@workspace = "#{Dir.pwd}/#{@name}"
|
|
20
19
|
@src = "#{@workspace}/src"
|
|
@@ -24,30 +23,30 @@ class WorkSpace
|
|
|
24
23
|
@target = "#{@workspace}/target"
|
|
25
24
|
@tests = "#{@workspace}/tests"
|
|
26
25
|
@mode = mode
|
|
27
|
-
@deps =
|
|
26
|
+
@deps = ".canoe.deps"
|
|
28
27
|
|
|
29
|
-
@src_prefix =
|
|
30
|
-
@components_prefix =
|
|
31
|
-
@obj_prefix =
|
|
28
|
+
@src_prefix = "./src/"
|
|
29
|
+
@components_prefix = "./src/components/"
|
|
30
|
+
@obj_prefix = "./obj/"
|
|
32
31
|
|
|
33
32
|
@source_suffix = src_suffix
|
|
34
33
|
@header_suffix = hdr_suffix
|
|
35
34
|
end
|
|
36
35
|
|
|
37
|
-
def inspect
|
|
36
|
+
def inspect
|
|
38
37
|
puts "name is #{@name}"
|
|
39
38
|
puts "name is #{@workspace}"
|
|
40
39
|
end
|
|
41
40
|
end
|
|
42
41
|
|
|
43
|
-
require_relative
|
|
44
|
-
require_relative
|
|
45
|
-
require_relative
|
|
46
|
-
require_relative
|
|
47
|
-
require_relative
|
|
48
|
-
require_relative
|
|
49
|
-
require_relative
|
|
50
|
-
require_relative
|
|
51
|
-
require_relative
|
|
52
|
-
require_relative
|
|
53
|
-
require_relative
|
|
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"
|
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.
|
|
4
|
+
version: 0.3.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:
|
|
11
|
+
date: 2021-02-15 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: |+
|
|
14
14
|
Canoe offers project management and building facilities to C/C++ projects.
|
|
@@ -41,11 +41,11 @@ files:
|
|
|
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
|
|
47
48
|
- lib/workspace/update.rb
|
|
48
|
-
- lib/workspace/version.rb
|
|
49
49
|
- lib/workspace/workspace.rb
|
|
50
50
|
homepage: https://github.com/Dicridon/canoe
|
|
51
51
|
licenses:
|
data/lib/workspace/version.rb
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
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
|
|
12
|
-
end
|
|
13
|
-
end
|