canoe 0.3.0 → 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.
- checksums.yaml +4 -4
- data/bin/canoe +1 -1
- data/lib/canoe.rb +22 -18
- data/lib/cmd.rb +73 -88
- data/lib/coloring.rb +23 -0
- data/lib/compiler.rb +44 -46
- data/lib/config_reader.rb +1 -1
- data/lib/default_files.rb +19 -26
- data/lib/dependence.rb +116 -97
- data/lib/source_files.rb +7 -7
- data/lib/util.rb +81 -0
- data/lib/workspace/add.rb +29 -0
- data/lib/workspace/build.rb +150 -0
- data/lib/workspace/clean.rb +36 -0
- data/lib/workspace/dep.rb +14 -0
- data/lib/workspace/generate.rb +10 -0
- data/lib/workspace/help.rb +84 -0
- data/lib/workspace/make.rb +280 -0
- data/lib/workspace/new.rb +31 -0
- data/lib/workspace/run.rb +12 -0
- data/lib/workspace/test.rb +136 -0
- data/lib/workspace/update.rb +7 -0
- data/lib/workspace/version.rb +15 -0
- data/lib/workspace/workspace.rb +63 -0
- metadata +18 -5
- data/lib/err.rb +0 -19
- data/lib/workspace.rb +0 -328
|
@@ -0,0 +1,136 @@
|
|
|
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
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# extract one test file's dependency
|
|
20
|
+
def extract_one_file(file, deps)
|
|
21
|
+
ret = deps[file]
|
|
22
|
+
|
|
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
|
|
28
|
+
end
|
|
29
|
+
ret.map { |f| f.gsub(".#{@header_suffix}", ".#{@source_suffix}") }
|
|
30
|
+
end
|
|
31
|
+
|
|
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
|
|
37
|
+
|
|
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
|
|
135
|
+
end
|
|
136
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module Canoe
|
|
2
|
+
class WorkSpace
|
|
3
|
+
def self.version
|
|
4
|
+
puts <<~VER
|
|
5
|
+
canoe v0.3.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
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +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 '../util'
|
|
7
|
+
require_relative '../dependence'
|
|
8
|
+
require_relative '../coloring'
|
|
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
|
+
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
|
|
20
|
+
|
|
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'
|
|
35
|
+
|
|
36
|
+
@target_short = './target'
|
|
37
|
+
@src_short = './src'
|
|
38
|
+
@components_short = "#{@src_short}/components"
|
|
39
|
+
@obj_short = './obj'
|
|
40
|
+
@tests_short = './tests'
|
|
41
|
+
|
|
42
|
+
@src_prefix = './src/'
|
|
43
|
+
@components_prefix = './src/components/'
|
|
44
|
+
@obj_prefix = './obj/'
|
|
45
|
+
|
|
46
|
+
@source_suffix = src_suffix
|
|
47
|
+
@header_suffix = hdr_suffix
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
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.
|
|
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:
|
|
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.
|
|
@@ -28,13 +28,26 @@ files:
|
|
|
28
28
|
- bin/canoe
|
|
29
29
|
- lib/canoe.rb
|
|
30
30
|
- lib/cmd.rb
|
|
31
|
+
- lib/coloring.rb
|
|
31
32
|
- lib/compiler.rb
|
|
32
33
|
- lib/config_reader.rb
|
|
33
34
|
- lib/default_files.rb
|
|
34
35
|
- lib/dependence.rb
|
|
35
|
-
- lib/err.rb
|
|
36
36
|
- lib/source_files.rb
|
|
37
|
-
- lib/
|
|
37
|
+
- lib/util.rb
|
|
38
|
+
- lib/workspace/add.rb
|
|
39
|
+
- lib/workspace/build.rb
|
|
40
|
+
- lib/workspace/clean.rb
|
|
41
|
+
- lib/workspace/dep.rb
|
|
42
|
+
- lib/workspace/generate.rb
|
|
43
|
+
- lib/workspace/help.rb
|
|
44
|
+
- lib/workspace/make.rb
|
|
45
|
+
- lib/workspace/new.rb
|
|
46
|
+
- lib/workspace/run.rb
|
|
47
|
+
- lib/workspace/test.rb
|
|
48
|
+
- lib/workspace/update.rb
|
|
49
|
+
- lib/workspace/version.rb
|
|
50
|
+
- lib/workspace/workspace.rb
|
|
38
51
|
homepage: https://github.com/Dicridon/canoe
|
|
39
52
|
licenses:
|
|
40
53
|
- MIT
|
|
@@ -54,7 +67,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
54
67
|
- !ruby/object:Gem::Version
|
|
55
68
|
version: '0'
|
|
56
69
|
requirements: []
|
|
57
|
-
rubygems_version: 3.
|
|
70
|
+
rubygems_version: 3.2.3
|
|
58
71
|
signing_key:
|
|
59
72
|
specification_version: 4
|
|
60
73
|
summary: a C/C++ project management and building tool
|
data/lib/err.rb
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
module Err
|
|
2
|
-
def warn_on_err(err)
|
|
3
|
-
puts <<~ERR
|
|
4
|
-
Warning:
|
|
5
|
-
#{err}
|
|
6
|
-
try 'canoe help' for more information
|
|
7
|
-
ERR
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
def abort_on_err(err)
|
|
11
|
-
abort <<~ERR
|
|
12
|
-
Fatal:
|
|
13
|
-
#{err}
|
|
14
|
-
try 'canoe help' for more information
|
|
15
|
-
ERR
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
module_function :warn_on_err, :abort_on_err
|
|
19
|
-
end
|
data/lib/workspace.rb
DELETED
|
@@ -1,328 +0,0 @@
|
|
|
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
|
-
|
|
9
|
-
class WorkSpace
|
|
10
|
-
include Err
|
|
11
|
-
attr_reader :name, :cwd
|
|
12
|
-
def self.help
|
|
13
|
-
info = <<~INFO
|
|
14
|
-
canoe is a C/C++ project manager, inspired by Rust cargo.
|
|
15
|
-
usage:
|
|
16
|
-
canoe new tada: create a project named 'tada' in current directory
|
|
17
|
-
|
|
18
|
-
canoe build: compile current project (execute this command in project directory)
|
|
19
|
-
|
|
20
|
-
canoe generate: generate dependency relationships and store it in '.canoe.deps' file. Alias: update
|
|
21
|
-
|
|
22
|
-
canoe update: udpate dependency relationships and store it in '.canoe.deps' file.
|
|
23
|
-
|
|
24
|
-
canoe run: compile and execute current project (execute this command in project directory)
|
|
25
|
-
|
|
26
|
-
canoe clean: remove all generated object files and binary files
|
|
27
|
-
|
|
28
|
-
canoe help: show this help message
|
|
29
|
-
|
|
30
|
-
canoe add tada: add a folder named tada under workspace/components,
|
|
31
|
-
|
|
32
|
-
canoe dep: show current dependency relationships of current project
|
|
33
|
-
|
|
34
|
-
canoe verion: version information
|
|
35
|
-
|
|
36
|
-
new project_name [mode] [suffixes]:
|
|
37
|
-
create a new project with project_name.
|
|
38
|
-
In this project, four directories obj, src, target and third-party will be generated in project directory.
|
|
39
|
-
in src, directory 'components' will be generated if [mode] is '--lib', an extra main.cpp will be generated if [mode] is '--bin'
|
|
40
|
-
|
|
41
|
-
[mode]: --lib for a library and --bin for executable binaries
|
|
42
|
-
[suffixes]: should be in 'source_suffix:header_suffix" format, notice the ':' between two suffixes
|
|
43
|
-
add component_name:
|
|
44
|
-
add a folder named tada under workspace/components.
|
|
45
|
-
two files tada.hpp and tada.cpp would be craeted and intialized. File suffix may differ according users' specifications.
|
|
46
|
-
if component_name is a path separated by '/', then canoe would create folders and corresponding files recursively.
|
|
47
|
-
|
|
48
|
-
generate:
|
|
49
|
-
generate dependence relationship for each file, this may accelarate
|
|
50
|
-
`canoe buid` command. It's recommanded to execute this command everytime
|
|
51
|
-
headers are added or removed from any file.
|
|
52
|
-
|
|
53
|
-
update:
|
|
54
|
-
this command is needed because '.canoe.deps' is actually a cache of dependency relationships so that
|
|
55
|
-
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.
|
|
58
|
-
|
|
59
|
-
build [options]:
|
|
60
|
-
build current project, arguments in [options] will be passed to C++ compiler
|
|
61
|
-
|
|
62
|
-
run [options]:
|
|
63
|
-
build current project with no specific compilation flags, and run this project, passing [options] as command line arguments to the binary
|
|
64
|
-
|
|
65
|
-
clean:
|
|
66
|
-
remove all generated object files and binary files
|
|
67
|
-
|
|
68
|
-
help:
|
|
69
|
-
show this help message
|
|
70
|
-
|
|
71
|
-
verion:
|
|
72
|
-
display version information
|
|
73
|
-
|
|
74
|
-
dep:
|
|
75
|
-
display file dependencies in a better readable way
|
|
76
|
-
|
|
77
|
-
@author: written by XIONG Ziwei, ICT, CAS
|
|
78
|
-
@contact: noahxiong@outlook.com
|
|
79
|
-
INFO
|
|
80
|
-
puts info
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
def initialize(name, mode, src_suffix='cpp', hdr_suffix='hpp')
|
|
85
|
-
@name = name
|
|
86
|
-
@compiler = Compiler.new 'clang++', ['-Isrc/components']
|
|
87
|
-
@cwd = Dir.new(Dir.pwd)
|
|
88
|
-
@workspace = "#{Dir.pwd}/#{@name}"
|
|
89
|
-
@src = "#{@workspace}/src"
|
|
90
|
-
@components = "#{@src}/components"
|
|
91
|
-
@obj = "#{@workspace}/obj"
|
|
92
|
-
@third = "#{@workspace}/third-party"
|
|
93
|
-
@target = "#{@workspace}/target"
|
|
94
|
-
@tests = "#{@workspace}/tests"
|
|
95
|
-
@mode = mode
|
|
96
|
-
@deps = '.canoe.deps'
|
|
97
|
-
|
|
98
|
-
@src_prefix = './src/'
|
|
99
|
-
@components_prefix = './src/components/'
|
|
100
|
-
@obj_prefix = './obj/'
|
|
101
|
-
|
|
102
|
-
@source_suffix = src_suffix
|
|
103
|
-
@header_suffix = hdr_suffix
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
def new
|
|
107
|
-
Dir.mkdir(@name)
|
|
108
|
-
Dir.mkdir(@src)
|
|
109
|
-
Dir.mkdir(@components)
|
|
110
|
-
Dir.mkdir("#{@workspace}/obj")
|
|
111
|
-
if @mode == :bin
|
|
112
|
-
DefaultFiles.create_main(@src, @source_suffix)
|
|
113
|
-
else
|
|
114
|
-
DefaultFiles.create_lib_header(@src, @name, @header_suffix)
|
|
115
|
-
end
|
|
116
|
-
File.new("#{@workspace}/.canoe", "w")
|
|
117
|
-
DefaultFiles.create_config @workspace, @source_suffix, @header_suffix
|
|
118
|
-
# DefaultFiles.create_emacs_dir_local @workspace
|
|
119
|
-
|
|
120
|
-
Dir.mkdir(@third)
|
|
121
|
-
Dir.mkdir(@target)
|
|
122
|
-
Dir.chdir(@workspace) do
|
|
123
|
-
system "git init"
|
|
124
|
-
end
|
|
125
|
-
puts "workspace #{@workspace} is created"
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
# args are commandline parameters passed to `canoe build`
|
|
129
|
-
def build(args)
|
|
130
|
-
deps = File.exist?(@deps) ?
|
|
131
|
-
DepAnalyzer.read_from(@deps) :
|
|
132
|
-
DepAnalyzer.new('./src').build_to_file(['./src', './src/components'], @deps)
|
|
133
|
-
target = "./target/#{@name}"
|
|
134
|
-
build_time = File.exist?(target) ? File.mtime(target) : Time.new(0)
|
|
135
|
-
files = DepAnalyzer.compiling_filter(deps, build_time, @source_suffix, @header_suffix)
|
|
136
|
-
|
|
137
|
-
if files.empty?
|
|
138
|
-
puts "nothing to do, all up to date"
|
|
139
|
-
return
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
self.send "build_#{@mode.to_s}", files, args
|
|
143
|
-
end
|
|
144
|
-
|
|
145
|
-
def generate
|
|
146
|
-
DepAnalyzer.new('./src', @source_suffix, @header_suffix)
|
|
147
|
-
.build_to_file ['./src', './src/components'], @deps
|
|
148
|
-
end
|
|
149
|
-
|
|
150
|
-
def update
|
|
151
|
-
generate
|
|
152
|
-
end
|
|
153
|
-
|
|
154
|
-
def clean
|
|
155
|
-
self.send "clean_#{@mode.to_s}"
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
def run(args)
|
|
159
|
-
return if @mode == :lib
|
|
160
|
-
build []
|
|
161
|
-
args = args.join " "
|
|
162
|
-
puts "./target/#{@name} #{args}"
|
|
163
|
-
exec "./target/#{@name} #{args}"
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
def add(args)
|
|
167
|
-
args.each do |i|
|
|
168
|
-
dir = @components
|
|
169
|
-
filenames = i.split("/")
|
|
170
|
-
prefix = []
|
|
171
|
-
filenames.each do |filename|
|
|
172
|
-
dir += "/#{filename}"
|
|
173
|
-
prefix << filename
|
|
174
|
-
unless Dir.exist? dir
|
|
175
|
-
FileUtils.mkdir dir
|
|
176
|
-
Dir.chdir(dir) do
|
|
177
|
-
puts "created " + Dir.pwd
|
|
178
|
-
create_working_files prefix.join('__'), filename
|
|
179
|
-
end
|
|
180
|
-
end
|
|
181
|
-
end
|
|
182
|
-
end
|
|
183
|
-
end
|
|
184
|
-
|
|
185
|
-
def dep
|
|
186
|
-
deps = DepAnalyzer.read_from(@deps) if File.exist?(@deps)
|
|
187
|
-
deps.each do |k, v|
|
|
188
|
-
unless v.empty?
|
|
189
|
-
puts "#{k} depends on: "
|
|
190
|
-
v.each {|f| puts " #{f}"}
|
|
191
|
-
puts ""
|
|
192
|
-
end
|
|
193
|
-
end
|
|
194
|
-
end
|
|
195
|
-
|
|
196
|
-
def test(args)
|
|
197
|
-
args.each do |arg|
|
|
198
|
-
case arg
|
|
199
|
-
when "all"
|
|
200
|
-
test_all
|
|
201
|
-
else
|
|
202
|
-
test_single arg
|
|
203
|
-
end
|
|
204
|
-
end
|
|
205
|
-
end
|
|
206
|
-
|
|
207
|
-
private
|
|
208
|
-
def create_working_files(prefix, filename)
|
|
209
|
-
DefaultFiles.create_cpp filename, @source_suffix, @header_suffix
|
|
210
|
-
DefaultFiles.create_hpp @name, prefix, filename, @header_suffix
|
|
211
|
-
end
|
|
212
|
-
|
|
213
|
-
def build_compiler_from_config(args)
|
|
214
|
-
Dir.chdir(@workspace) do
|
|
215
|
-
flags = ConfigReader.extract_flags "config.json"
|
|
216
|
-
compiler_name = flags['compiler'] ? flags['compiler'] : "clang++"
|
|
217
|
-
abort_on_err "compiler #{compiler_name} not found" unless File.exists?("/usr/bin/#{compiler_name}")
|
|
218
|
-
compiler_flags = ['-Isrc/components'] + args
|
|
219
|
-
|
|
220
|
-
if opts = flags['flags']
|
|
221
|
-
opts.each do |k, v|
|
|
222
|
-
case v
|
|
223
|
-
when String
|
|
224
|
-
compiler_flags << v
|
|
225
|
-
when Array
|
|
226
|
-
v.each do |o|
|
|
227
|
-
compiler_flags << o
|
|
228
|
-
end
|
|
229
|
-
else
|
|
230
|
-
abort_on_err "unknown options in config.json, #{v}"
|
|
231
|
-
end
|
|
232
|
-
end
|
|
233
|
-
end
|
|
234
|
-
|
|
235
|
-
@compiler = Compiler.new compiler_name, compiler_flags
|
|
236
|
-
end
|
|
237
|
-
end
|
|
238
|
-
|
|
239
|
-
def compile(f, o)
|
|
240
|
-
@compiler.compile f, o
|
|
241
|
-
end
|
|
242
|
-
|
|
243
|
-
def link_exectutable(odir, objs)
|
|
244
|
-
puts "[100%] linking"
|
|
245
|
-
@compiler.link_executable "#{odir}/#{@name}", objs
|
|
246
|
-
end
|
|
247
|
-
|
|
248
|
-
def link_shared(odir, objs)
|
|
249
|
-
puts "[100%] linking"
|
|
250
|
-
@compiler.link_shared "#{odir}/lib#{@name}", objs
|
|
251
|
-
end
|
|
252
|
-
|
|
253
|
-
def build_bin(files, args)
|
|
254
|
-
return if files.empty?
|
|
255
|
-
build_compiler_from_config args
|
|
256
|
-
if build_common(files, args)
|
|
257
|
-
link_exectutable('./target', Dir.glob("obj/*.o"))
|
|
258
|
-
puts "canoe: building succeeded"
|
|
259
|
-
else
|
|
260
|
-
puts "canoe: building failed"
|
|
261
|
-
end
|
|
262
|
-
end
|
|
263
|
-
|
|
264
|
-
def build_lib(files, args)
|
|
265
|
-
return if files.empty?
|
|
266
|
-
build_compiler_from_config args
|
|
267
|
-
@compiler.append_compiling_flag '-fPIC'
|
|
268
|
-
if (build_common files, args)
|
|
269
|
-
link_shared('./target', Dir.glob("obj/*.o"))
|
|
270
|
-
puts "canoe: building succeeded"
|
|
271
|
-
else
|
|
272
|
-
puts "canoe: building failed"
|
|
273
|
-
end
|
|
274
|
-
end
|
|
275
|
-
|
|
276
|
-
def build_common(files, args)
|
|
277
|
-
all = SourceFiles.get_all('./src') {|f| f.end_with? @source_suffix}
|
|
278
|
-
total = all.size.to_f
|
|
279
|
-
compiled = total - files.size
|
|
280
|
-
comps = files.select {|f| f.start_with? @components_prefix}
|
|
281
|
-
srcs = files - comps
|
|
282
|
-
flag = true;
|
|
283
|
-
srcs.each do |f|
|
|
284
|
-
progress = (compiled / total).round(2) * 100
|
|
285
|
-
printf "[#{progress.to_i}%%] compiling #{f}: "
|
|
286
|
-
fname = f.split("/")[-1]
|
|
287
|
-
o = @obj_prefix + fname.delete_suffix(File.extname(fname)) + '.o'
|
|
288
|
-
flag = false unless compile f, o
|
|
289
|
-
compiled += 1
|
|
290
|
-
end
|
|
291
|
-
|
|
292
|
-
comps.each do |f|
|
|
293
|
-
progress = (compiled / total).round(2) * 100
|
|
294
|
-
printf "[#{progress.to_i}%%] compiling #{f}: "
|
|
295
|
-
o = @obj_prefix + f.delete_suffix(File.extname(f))[@components_prefix.length..]
|
|
296
|
-
.gsub('/', '_') + '.o'
|
|
297
|
-
flag = false unless compile f, o
|
|
298
|
-
compiled += 1
|
|
299
|
-
end
|
|
300
|
-
flag
|
|
301
|
-
end
|
|
302
|
-
|
|
303
|
-
def clean_obj
|
|
304
|
-
puts "rm -f ./obj/*.o"
|
|
305
|
-
system "rm -f ./obj/*.o"
|
|
306
|
-
end
|
|
307
|
-
|
|
308
|
-
def clean_target
|
|
309
|
-
puts "rm -f ./target/*"
|
|
310
|
-
system "rm -f ./target/*"
|
|
311
|
-
end
|
|
312
|
-
|
|
313
|
-
def clean_bin
|
|
314
|
-
clean_obj
|
|
315
|
-
clean_target
|
|
316
|
-
end
|
|
317
|
-
|
|
318
|
-
def clean_lib
|
|
319
|
-
clean_obj
|
|
320
|
-
clean_target
|
|
321
|
-
end
|
|
322
|
-
|
|
323
|
-
public
|
|
324
|
-
def inspect
|
|
325
|
-
puts "name is #{@name}"
|
|
326
|
-
puts "name is #{@workspace}"
|
|
327
|
-
end
|
|
328
|
-
end
|