cxxproject 0.5.48 → 0.5.59
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/Rakefile.rb +116 -116
- data/bin/cxx +10 -10
- data/lib/cxxproject.rb +23 -23
- data/lib/cxxproject/buildingblocks/binary_library.rb +39 -39
- data/lib/cxxproject/buildingblocks/building_block.rb +251 -239
- data/lib/cxxproject/buildingblocks/command_line.rb +79 -79
- data/lib/cxxproject/buildingblocks/custom_building_block.rb +39 -41
- data/lib/cxxproject/buildingblocks/executable.rb +257 -249
- data/lib/cxxproject/buildingblocks/has_dependencies_mixin.rb +83 -83
- data/lib/cxxproject/buildingblocks/has_includes_mixin.rb +20 -20
- data/lib/cxxproject/buildingblocks/has_libraries_mixin.rb +34 -34
- data/lib/cxxproject/buildingblocks/has_sources_mixin.rb +371 -364
- data/lib/cxxproject/buildingblocks/makefile.rb +153 -153
- data/lib/cxxproject/buildingblocks/module.rb +35 -35
- data/lib/cxxproject/buildingblocks/single_source.rb +33 -33
- data/lib/cxxproject/buildingblocks/source_library.rb +124 -124
- data/lib/cxxproject/errorparser/diab_compiler_error_parser.rb +40 -40
- data/lib/cxxproject/errorparser/diab_linker_error_parser.rb +41 -33
- data/lib/cxxproject/errorparser/error_parser.rb +50 -50
- data/lib/cxxproject/errorparser/gcc_compiler_error_parser.rb +35 -30
- data/lib/cxxproject/errorparser/gcc_linker_error_parser.rb +35 -29
- data/lib/cxxproject/errorparser/ti_compiler_error_parser.rb +30 -30
- data/lib/cxxproject/errorparser/ti_linker_error_parser.rb +30 -29
- data/lib/cxxproject/eval_context.rb +144 -136
- data/lib/cxxproject/ext/file.rb +71 -71
- data/lib/cxxproject/ext/filelist.rb +6 -6
- data/lib/cxxproject/ext/progressbar.rb +20 -20
- data/lib/cxxproject/ext/rake.rb +419 -397
- data/lib/cxxproject/ext/rake_dirty.rb +30 -30
- data/lib/cxxproject/ext/rake_listener.rb +59 -59
- data/lib/cxxproject/ext/stdout.rb +44 -44
- data/lib/cxxproject/ext/string.rb +9 -9
- data/lib/cxxproject/ide_interface.rb +187 -181
- data/lib/cxxproject/toolchain/clang.rb +39 -39
- data/lib/cxxproject/toolchain/colorizing_formatter.rb +99 -99
- data/lib/cxxproject/toolchain/diab.rb +3 -1
- data/lib/cxxproject/toolchain/gcc.rb +2 -1
- data/lib/cxxproject/toolchain/provider.rb +131 -128
- data/lib/cxxproject/toolchain/toolchain.rb +38 -38
- data/lib/cxxproject/toolchain/toolchain_benchmark.rb +23 -23
- data/lib/cxxproject/torake.rb +218 -216
- data/lib/cxxproject/utils/cleanup.rb +20 -20
- data/lib/cxxproject/utils/console.rb +6 -6
- data/lib/cxxproject/utils/exit_helper.rb +40 -40
- data/lib/cxxproject/utils/graphstream.rb +154 -154
- data/lib/cxxproject/utils/optional.rb +16 -16
- data/lib/cxxproject/utils/printer.rb +50 -50
- data/lib/cxxproject/utils/process.rb +52 -52
- data/lib/cxxproject/utils/progress.rb +66 -66
- data/lib/cxxproject/utils/progress_helper.rb +77 -77
- data/lib/cxxproject/utils/rbcurse.rb +284 -284
- data/lib/cxxproject/utils/rbcurse_executable_ext.rb +14 -14
- data/lib/cxxproject/utils/rbcurse_progress.rb +71 -71
- data/lib/cxxproject/utils/rbcurse_tasktable.rb +51 -51
- data/lib/cxxproject/utils/stats.rb +60 -60
- data/lib/cxxproject/utils/ubigraph.rb +228 -228
- data/lib/cxxproject/utils/utils.rb +60 -37
- data/lib/cxxproject/utils/valgrind.rb +11 -11
- data/lib/cxxproject/version.rb +7 -7
- data/lib/tools/Rakefile.rb.template +10 -10
- data/lib/tools/project.rb.template +6 -6
- data/lib/tools/project_wizard.rb +66 -66
- data/spec/building_block_spec.rb +56 -56
- data/spec/cxxproject_2_rake_spec.rb +186 -186
- data/spec/file_ext_spec.rb +30 -30
- data/spec/ide_interface_spec.rb +41 -41
- data/spec/object_dependency_spec.rb +83 -83
- data/spec/project_path_spec.rb +71 -71
- data/spec/rake_listener_ext_spec.rb +58 -58
- data/spec/spec_helper.rb +18 -18
- data/spec/string_spec.rb +11 -11
- data/spec/testdata/basic/exe12/project.rb +5 -5
- data/spec/testdata/basic/lib1/project.rb +5 -5
- data/spec/testdata/basic/lib2/project.rb +8 -8
- data/spec/testdata/multiple_levels/libs/lib1/project.rb +5 -5
- data/spec/testdata/multiple_levels/libs/lib2/project.rb +19 -19
- data/spec/testdata/multiple_levels/mainproject/basic/project.rb +8 -8
- data/spec/testdata/onlyOneHeader/Rakefile.rb +4 -4
- data/spec/testdata/onlyOneHeader/project.rb +4 -4
- data/spec/toolchain_spec.rb +29 -29
- metadata +58 -58
@@ -1,83 +1,83 @@
|
|
1
|
-
module Cxxproject
|
2
|
-
module HasDependencies
|
3
|
-
|
4
|
-
def dependencies
|
5
|
-
@dependencies ||= []
|
6
|
-
end
|
7
|
-
|
8
|
-
def helper_dependencies
|
9
|
-
@helper_dependencies ||= []
|
10
|
-
end
|
11
|
-
|
12
|
-
def set_dependencies(deps)
|
13
|
-
@dependencies = deps.map { |dep| dep.instance_of?(String) ? dep : dep.name }
|
14
|
-
self
|
15
|
-
end
|
16
|
-
|
17
|
-
def set_helper_dependencies(deps)
|
18
|
-
@helper_dependencies = deps.map { |dep| dep.instance_of?(String) ? dep : dep.name }
|
19
|
-
self
|
20
|
-
end
|
21
|
-
|
22
|
-
def direct_deps
|
23
|
-
return @direct_deps if @direct_deps
|
24
|
-
|
25
|
-
@all_dependencies_set = Set.new
|
26
|
-
@all_dependencies_set << self
|
27
|
-
@all_dependencies = [self]
|
28
|
-
|
29
|
-
depList = helper_dependencies.length > 0 ? helper_dependencies : dependencies
|
30
|
-
|
31
|
-
depList.each do |d|
|
32
|
-
bb = ALL_BUILDING_BLOCKS[d]
|
33
|
-
if not bb
|
34
|
-
raise "Error: while reading config file for #{self.name}: dependent building block \"#{d}\" was specified but not found!"
|
35
|
-
end
|
36
|
-
next if @all_dependencies_set.include?bb
|
37
|
-
|
38
|
-
@all_dependencies << bb
|
39
|
-
@all_dependencies_set << bb
|
40
|
-
|
41
|
-
# deps in modules may be splitted into its contents
|
42
|
-
if ModuleBuildingBlock === bb
|
43
|
-
bb.contents.each do |c|
|
44
|
-
next if @all_dependencies_set.include?c
|
45
|
-
@all_dependencies << c
|
46
|
-
@all_dependencies_set << c
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
end
|
51
|
-
|
52
|
-
@direct_deps = @all_dependencies.dup
|
53
|
-
@direct_deps
|
54
|
-
end
|
55
|
-
|
56
|
-
def all_dependencies()
|
57
|
-
return @all_dependencies if @all_deps_calculated
|
58
|
-
|
59
|
-
direct_deps.each do |d|
|
60
|
-
d.all_dependencies_recursive(@all_dependencies, @all_dependencies_set)
|
61
|
-
end
|
62
|
-
|
63
|
-
@all_deps_calculated = true
|
64
|
-
@all_dependencies
|
65
|
-
end
|
66
|
-
|
67
|
-
def all_dependencies_recursive(all_deps, all_deps_set)
|
68
|
-
deps = [] # needed to keep order
|
69
|
-
|
70
|
-
direct_deps.each do |d|
|
71
|
-
next if all_deps_set.include?d
|
72
|
-
all_deps << d
|
73
|
-
all_deps_set << d
|
74
|
-
deps << d
|
75
|
-
end
|
76
|
-
|
77
|
-
deps.each do |d|
|
78
|
-
d.all_dependencies_recursive(all_deps, all_deps_set)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
end
|
83
|
-
end
|
1
|
+
module Cxxproject
|
2
|
+
module HasDependencies
|
3
|
+
|
4
|
+
def dependencies
|
5
|
+
@dependencies ||= []
|
6
|
+
end
|
7
|
+
|
8
|
+
def helper_dependencies
|
9
|
+
@helper_dependencies ||= []
|
10
|
+
end
|
11
|
+
|
12
|
+
def set_dependencies(deps)
|
13
|
+
@dependencies = deps.map { |dep| dep.instance_of?(String) ? dep : dep.name }
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
def set_helper_dependencies(deps)
|
18
|
+
@helper_dependencies = deps.map { |dep| dep.instance_of?(String) ? dep : dep.name }
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def direct_deps
|
23
|
+
return @direct_deps if @direct_deps
|
24
|
+
|
25
|
+
@all_dependencies_set = Set.new
|
26
|
+
@all_dependencies_set << self
|
27
|
+
@all_dependencies = [self]
|
28
|
+
|
29
|
+
depList = helper_dependencies.length > 0 ? helper_dependencies : dependencies
|
30
|
+
|
31
|
+
depList.each do |d|
|
32
|
+
bb = ALL_BUILDING_BLOCKS[d]
|
33
|
+
if not bb
|
34
|
+
raise "Error: while reading config file for #{self.name}: dependent building block \"#{d}\" was specified but not found!"
|
35
|
+
end
|
36
|
+
next if @all_dependencies_set.include?bb
|
37
|
+
|
38
|
+
@all_dependencies << bb
|
39
|
+
@all_dependencies_set << bb
|
40
|
+
|
41
|
+
# deps in modules may be splitted into its contents
|
42
|
+
if ModuleBuildingBlock === bb
|
43
|
+
bb.contents.each do |c|
|
44
|
+
next if @all_dependencies_set.include?c
|
45
|
+
@all_dependencies << c
|
46
|
+
@all_dependencies_set << c
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
@direct_deps = @all_dependencies.dup
|
53
|
+
@direct_deps
|
54
|
+
end
|
55
|
+
|
56
|
+
def all_dependencies()
|
57
|
+
return @all_dependencies if @all_deps_calculated
|
58
|
+
|
59
|
+
direct_deps.each do |d|
|
60
|
+
d.all_dependencies_recursive(@all_dependencies, @all_dependencies_set)
|
61
|
+
end
|
62
|
+
|
63
|
+
@all_deps_calculated = true
|
64
|
+
@all_dependencies
|
65
|
+
end
|
66
|
+
|
67
|
+
def all_dependencies_recursive(all_deps, all_deps_set)
|
68
|
+
deps = [] # needed to keep order
|
69
|
+
|
70
|
+
direct_deps.each do |d|
|
71
|
+
next if all_deps_set.include?d
|
72
|
+
all_deps << d
|
73
|
+
all_deps_set << d
|
74
|
+
deps << d
|
75
|
+
end
|
76
|
+
|
77
|
+
deps.each do |d|
|
78
|
+
d.all_dependencies_recursive(all_deps, all_deps_set)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|
@@ -1,20 +1,20 @@
|
|
1
|
-
module Cxxproject
|
2
|
-
module HasIncludes
|
3
|
-
def includes
|
4
|
-
@includes ||= []
|
5
|
-
end
|
6
|
-
def set_includes(x)
|
7
|
-
@includes = x
|
8
|
-
self
|
9
|
-
end
|
10
|
-
|
11
|
-
def local_includes
|
12
|
-
@local_includes ||= []
|
13
|
-
end
|
14
|
-
def set_local_includes(x)
|
15
|
-
@local_includes = x
|
16
|
-
self
|
17
|
-
end
|
18
|
-
|
19
|
-
end
|
20
|
-
end
|
1
|
+
module Cxxproject
|
2
|
+
module HasIncludes
|
3
|
+
def includes
|
4
|
+
@includes ||= []
|
5
|
+
end
|
6
|
+
def set_includes(x)
|
7
|
+
@includes = x
|
8
|
+
self
|
9
|
+
end
|
10
|
+
|
11
|
+
def local_includes
|
12
|
+
@local_includes ||= []
|
13
|
+
end
|
14
|
+
def set_local_includes(x)
|
15
|
+
@local_includes = x
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -1,34 +1,34 @@
|
|
1
|
-
module Cxxproject
|
2
|
-
module HasLibraries
|
3
|
-
LIB = 1
|
4
|
-
USERLIB = 2
|
5
|
-
LIB_WITH_PATH = 3
|
6
|
-
SEARCH_PATH = 4
|
7
|
-
DEPENDENCY = 5
|
8
|
-
|
9
|
-
def lib_elements
|
10
|
-
@lib_elements ||= []
|
11
|
-
end
|
12
|
-
|
13
|
-
# value: can be string or building block
|
14
|
-
def add_lib_element(type, value, front = false)
|
15
|
-
elem = [type, value.instance_of?(String) ? value : value.name]
|
16
|
-
if front
|
17
|
-
lib_elements.unshift(elem)
|
18
|
-
else
|
19
|
-
lib_elements << elem
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
# 1. element: type
|
24
|
-
# 2. element: name, must not be a building block
|
25
|
-
def add_lib_elements(array_of_tuples, front = false)
|
26
|
-
if front
|
27
|
-
@lib_elements = array_of_tuples+lib_elements
|
28
|
-
else
|
29
|
-
lib_elements.concat(array_of_tuples)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
end
|
34
|
-
end
|
1
|
+
module Cxxproject
|
2
|
+
module HasLibraries
|
3
|
+
LIB = 1
|
4
|
+
USERLIB = 2
|
5
|
+
LIB_WITH_PATH = 3
|
6
|
+
SEARCH_PATH = 4
|
7
|
+
DEPENDENCY = 5
|
8
|
+
|
9
|
+
def lib_elements
|
10
|
+
@lib_elements ||= []
|
11
|
+
end
|
12
|
+
|
13
|
+
# value: can be string or building block
|
14
|
+
def add_lib_element(type, value, front = false)
|
15
|
+
elem = [type, value.instance_of?(String) ? value : value.name]
|
16
|
+
if front
|
17
|
+
lib_elements.unshift(elem)
|
18
|
+
else
|
19
|
+
lib_elements << elem
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# 1. element: type
|
24
|
+
# 2. element: name, must not be a building block
|
25
|
+
def add_lib_elements(array_of_tuples, front = false)
|
26
|
+
if front
|
27
|
+
@lib_elements = array_of_tuples+lib_elements
|
28
|
+
else
|
29
|
+
lib_elements.concat(array_of_tuples)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -1,364 +1,371 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
require 'cxxproject/utils/process'
|
3
|
-
require 'cxxproject/utils/utils'
|
4
|
-
require 'cxxproject/utils/printer'
|
5
|
-
|
6
|
-
module Cxxproject
|
7
|
-
module HasSources
|
8
|
-
|
9
|
-
attr_writer :file_dependencies
|
10
|
-
attr_reader :incArray
|
11
|
-
|
12
|
-
def file_dependencies
|
13
|
-
@file_dependencies ||= []
|
14
|
-
end
|
15
|
-
|
16
|
-
def sources
|
17
|
-
@sources ||= []
|
18
|
-
end
|
19
|
-
def set_sources(x)
|
20
|
-
@sources = x
|
21
|
-
self
|
22
|
-
end
|
23
|
-
|
24
|
-
def deps_in_depFiles
|
25
|
-
@deps_in_depFiles ||= Set.new
|
26
|
-
end
|
27
|
-
|
28
|
-
def source_patterns
|
29
|
-
@source_patterns ||= []
|
30
|
-
end
|
31
|
-
def set_source_patterns(x)
|
32
|
-
@source_patterns = x
|
33
|
-
self
|
34
|
-
end
|
35
|
-
|
36
|
-
def exclude_sources
|
37
|
-
@exclude_sources ||= []
|
38
|
-
end
|
39
|
-
def set_exclude_sources(x)
|
40
|
-
@exclude_sources = x
|
41
|
-
self
|
42
|
-
end
|
43
|
-
|
44
|
-
# used when a source file shall have different tcs than the project default
|
45
|
-
def tcs4source(source)
|
46
|
-
@tcs4source ||= {}
|
47
|
-
|
48
|
-
if @tcs4source.include?(source)
|
49
|
-
@tcs4source[source]
|
50
|
-
else
|
51
|
-
@tcs
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def set_tcs4source(x)
|
56
|
-
@tcs4source = x
|
57
|
-
self
|
58
|
-
end
|
59
|
-
|
60
|
-
def include_string(type)
|
61
|
-
@include_string[type] ||= ""
|
62
|
-
end
|
63
|
-
|
64
|
-
def define_string(type)
|
65
|
-
@define_string[type] ||= ""
|
66
|
-
end
|
67
|
-
|
68
|
-
def calc_compiler_strings()
|
69
|
-
@include_string = {}
|
70
|
-
@define_string = {}
|
71
|
-
|
72
|
-
@incArray = local_includes.dup
|
73
|
-
@incArray.concat(includes)
|
74
|
-
|
75
|
-
if Rake::application.deriveIncludes
|
76
|
-
all_dependencies.each_with_index do |d,i|
|
77
|
-
next if not HasIncludes === d
|
78
|
-
next if i == 0
|
79
|
-
prefix = File.rel_from_to_project(@project_dir,d.project_dir)
|
80
|
-
next if not prefix
|
81
|
-
@incArray.concat(d.includes.map {|inc| File.add_prefix(prefix,inc)})
|
82
|
-
end
|
83
|
-
@incArray.uniq!
|
84
|
-
end
|
85
|
-
|
86
|
-
[:CPP, :C, :ASM].each do |type|
|
87
|
-
@include_string[type] = get_include_string(@tcs, type)
|
88
|
-
@define_string[type] = get_define_string(@tcs, type)
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def get_include_string(tcs, type)
|
93
|
-
@incArray.map {|k| "#{tcs[:COMPILER][type][:INCLUDE_PATH_FLAG]}#{k}"}
|
94
|
-
end
|
95
|
-
|
96
|
-
def get_define_string(tcs, type)
|
97
|
-
tcs[:COMPILER][type][:DEFINES].map {|k| "#{tcs[:COMPILER][type][:DEFINE_FLAG]}#{k}"}
|
98
|
-
end
|
99
|
-
|
100
|
-
def get_object_file(sourceRel)
|
101
|
-
parts = [@output_dir]
|
102
|
-
if @output_dir_abs
|
103
|
-
parts = [@output_dir_relPath] if @output_dir_relPath
|
104
|
-
parts << 'objects'
|
105
|
-
parts << @name
|
106
|
-
end
|
107
|
-
|
108
|
-
parts << sourceRel.chomp(File.extname(sourceRel))
|
109
|
-
File.join(parts) + ".o"
|
110
|
-
end
|
111
|
-
|
112
|
-
def get_dep_file(object)
|
113
|
-
object + ".d"
|
114
|
-
end
|
115
|
-
|
116
|
-
def get_source_type(source)
|
117
|
-
ex = File.extname(source)
|
118
|
-
[:CPP, :C, :ASM].each do |t|
|
119
|
-
return t if tcs[:COMPILER][t][:SOURCE_FILE_ENDINGS].include?(ex)
|
120
|
-
end
|
121
|
-
nil
|
122
|
-
end
|
123
|
-
|
124
|
-
def get_sources_task_name
|
125
|
-
"Objects of #{name}"
|
126
|
-
end
|
127
|
-
|
128
|
-
def parse_includes(deps)
|
129
|
-
#deps look like "test.o: test.cpp test.h" -> remove .o and .cpp from list
|
130
|
-
return deps.gsub(/\\\n/,'').split()[2..-1]
|
131
|
-
end
|
132
|
-
|
133
|
-
def convert_depfile(depfile)
|
134
|
-
deps_string = read_file_or_empty_string(depfile)
|
135
|
-
deps = parse_includes(deps_string)
|
136
|
-
if deps.nil?
|
137
|
-
return # ok, because next run the source will be recompiled due to invalid depfile
|
138
|
-
end
|
139
|
-
expanded_deps = deps.map do |d|
|
140
|
-
tmp = d.gsub(/[\\]/,'/')
|
141
|
-
deps_in_depFiles << tmp
|
142
|
-
tmp
|
143
|
-
end
|
144
|
-
|
145
|
-
FileUtils.mkpath File.dirname(depfile)
|
146
|
-
File.open(depfile, 'wb') do |f|
|
147
|
-
f.write(expanded_deps.to_yaml)
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
def apply_depfile(depfile,outfileTask)
|
152
|
-
deps = nil
|
153
|
-
begin
|
154
|
-
deps = YAML.load_file(depfile)
|
155
|
-
deps.each do |d|
|
156
|
-
deps_in_depFiles << d
|
157
|
-
f = file d
|
158
|
-
f.ignore_missing_file
|
159
|
-
end
|
160
|
-
outfileTask.enhance(deps)
|
161
|
-
rescue
|
162
|
-
# may happen if depfile was not converted the last time
|
163
|
-
def outfileTask.needed?
|
164
|
-
true
|
165
|
-
end
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
|
-
def create_object_file_tasks()
|
170
|
-
|
171
|
-
sources_to_build = {}
|
172
|
-
|
173
|
-
exclude_files = Set.new
|
174
|
-
exclude_sources.each do |p|
|
175
|
-
if p.include?".."
|
176
|
-
Printer.printError "Error: Exclude source file pattern '#{p}' must not include '..'"
|
177
|
-
return nil
|
178
|
-
end
|
179
|
-
|
180
|
-
Dir.glob(p).each {|f| exclude_files << f}
|
181
|
-
end
|
182
|
-
files = Set.new # do not build the same file twice
|
183
|
-
|
184
|
-
sources.each do |f|
|
185
|
-
if f.include?".."
|
186
|
-
Printer.printError "Error: Source file '#{f}' must not include '..'"
|
187
|
-
return nil
|
188
|
-
end
|
189
|
-
|
190
|
-
next if exclude_files.include?(f)
|
191
|
-
next if files.include?(f)
|
192
|
-
files << f
|
193
|
-
sources_to_build[f] = tcs4source(f)
|
194
|
-
end
|
195
|
-
|
196
|
-
source_patterns.each do |p|
|
197
|
-
if p.include?".."
|
198
|
-
Printer.printError "Error: Source file pattern '#{p}' must not include '..'"
|
199
|
-
return nil
|
200
|
-
end
|
201
|
-
|
202
|
-
globRes = Dir.glob(p)
|
203
|
-
if (globRes.length == 0)
|
204
|
-
Printer.printWarning "Warning: Source file pattern '#{p}' did not match to any file"
|
205
|
-
end
|
206
|
-
globRes.each do |f|
|
207
|
-
next if exclude_files.include?(f)
|
208
|
-
next if files.include?(f)
|
209
|
-
files << f
|
210
|
-
t = tcs4source(f)
|
211
|
-
t = tcs4source(p) if t == nil
|
212
|
-
sources_to_build[f] = t
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
|
-
ordered = sources_to_build.keys.sort()
|
217
|
-
dirs = []
|
218
|
-
filemap = {}
|
219
|
-
ordered.reverse.each do |o|
|
220
|
-
d = File.dirname(o)
|
221
|
-
if filemap.include?(d)
|
222
|
-
filemap[d] << o
|
223
|
-
else
|
224
|
-
filemap[d] = [o]
|
225
|
-
dirs << d
|
226
|
-
end
|
227
|
-
end
|
228
|
-
|
229
|
-
obj_tasks = []
|
230
|
-
dirs.each do |d|
|
231
|
-
filemap[d].reverse.each do |f|
|
232
|
-
obj_task = create_object_file_task(f, sources_to_build[f])
|
233
|
-
obj_tasks << obj_task unless obj_task.nil?
|
234
|
-
end
|
235
|
-
end
|
236
|
-
obj_tasks
|
237
|
-
end
|
238
|
-
|
239
|
-
def create_object_file_task(sourceRel, the_tcs)
|
240
|
-
if File.is_absolute?(sourceRel)
|
241
|
-
sourceRel = File.rel_from_to_project(@project_dir, sourceRel, false)
|
242
|
-
end
|
243
|
-
|
244
|
-
type = get_source_type(sourceRel)
|
245
|
-
return nil if type.nil?
|
246
|
-
|
247
|
-
objectRel = get_object_file(sourceRel)
|
248
|
-
@objects << objectRel
|
249
|
-
object = File.expand_path(objectRel)
|
250
|
-
source = File.expand_path(sourceRel)
|
251
|
-
|
252
|
-
depStr = ""
|
253
|
-
dep_file = nil
|
254
|
-
if type != :ASM
|
255
|
-
dep_file = get_dep_file(objectRel)
|
256
|
-
dep_file = "\""+dep_file+"\"" if dep_file.include?" "
|
257
|
-
depStr = the_tcs[:COMPILER][type][:DEP_FLAGS]
|
258
|
-
end
|
259
|
-
|
260
|
-
res = typed_file_task Rake::Task::OBJECT, object => source do
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
cmd
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
end
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
1
|
+
require 'yaml'
|
2
|
+
require 'cxxproject/utils/process'
|
3
|
+
require 'cxxproject/utils/utils'
|
4
|
+
require 'cxxproject/utils/printer'
|
5
|
+
|
6
|
+
module Cxxproject
|
7
|
+
module HasSources
|
8
|
+
|
9
|
+
attr_writer :file_dependencies
|
10
|
+
attr_reader :incArray
|
11
|
+
|
12
|
+
def file_dependencies
|
13
|
+
@file_dependencies ||= []
|
14
|
+
end
|
15
|
+
|
16
|
+
def sources
|
17
|
+
@sources ||= []
|
18
|
+
end
|
19
|
+
def set_sources(x)
|
20
|
+
@sources = x
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
def deps_in_depFiles
|
25
|
+
@deps_in_depFiles ||= Set.new
|
26
|
+
end
|
27
|
+
|
28
|
+
def source_patterns
|
29
|
+
@source_patterns ||= []
|
30
|
+
end
|
31
|
+
def set_source_patterns(x)
|
32
|
+
@source_patterns = x
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
36
|
+
def exclude_sources
|
37
|
+
@exclude_sources ||= []
|
38
|
+
end
|
39
|
+
def set_exclude_sources(x)
|
40
|
+
@exclude_sources = x
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
# used when a source file shall have different tcs than the project default
|
45
|
+
def tcs4source(source)
|
46
|
+
@tcs4source ||= {}
|
47
|
+
|
48
|
+
if @tcs4source.include?(source)
|
49
|
+
@tcs4source[source]
|
50
|
+
else
|
51
|
+
@tcs
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def set_tcs4source(x)
|
56
|
+
@tcs4source = x
|
57
|
+
self
|
58
|
+
end
|
59
|
+
|
60
|
+
def include_string(type)
|
61
|
+
@include_string[type] ||= ""
|
62
|
+
end
|
63
|
+
|
64
|
+
def define_string(type)
|
65
|
+
@define_string[type] ||= ""
|
66
|
+
end
|
67
|
+
|
68
|
+
def calc_compiler_strings()
|
69
|
+
@include_string = {}
|
70
|
+
@define_string = {}
|
71
|
+
|
72
|
+
@incArray = local_includes.dup
|
73
|
+
@incArray.concat(includes)
|
74
|
+
|
75
|
+
if Rake::application.deriveIncludes
|
76
|
+
all_dependencies.each_with_index do |d,i|
|
77
|
+
next if not HasIncludes === d
|
78
|
+
next if i == 0
|
79
|
+
prefix = File.rel_from_to_project(@project_dir,d.project_dir)
|
80
|
+
next if not prefix
|
81
|
+
@incArray.concat(d.includes.map {|inc| File.add_prefix(prefix,inc)})
|
82
|
+
end
|
83
|
+
@incArray.uniq!
|
84
|
+
end
|
85
|
+
|
86
|
+
[:CPP, :C, :ASM].each do |type|
|
87
|
+
@include_string[type] = get_include_string(@tcs, type)
|
88
|
+
@define_string[type] = get_define_string(@tcs, type)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def get_include_string(tcs, type)
|
93
|
+
@incArray.map {|k| "#{tcs[:COMPILER][type][:INCLUDE_PATH_FLAG]}#{k}"}
|
94
|
+
end
|
95
|
+
|
96
|
+
def get_define_string(tcs, type)
|
97
|
+
tcs[:COMPILER][type][:DEFINES].map {|k| "#{tcs[:COMPILER][type][:DEFINE_FLAG]}#{k}"}
|
98
|
+
end
|
99
|
+
|
100
|
+
def get_object_file(sourceRel)
|
101
|
+
parts = [@output_dir]
|
102
|
+
if @output_dir_abs
|
103
|
+
parts = [@output_dir_relPath] if @output_dir_relPath
|
104
|
+
parts << 'objects'
|
105
|
+
parts << @name
|
106
|
+
end
|
107
|
+
|
108
|
+
parts << sourceRel.chomp(File.extname(sourceRel))
|
109
|
+
File.join(parts) + (Rake::application.preproFlags ? ".i" : ".o")
|
110
|
+
end
|
111
|
+
|
112
|
+
def get_dep_file(object)
|
113
|
+
object[0..-3] + ".o.d"
|
114
|
+
end
|
115
|
+
|
116
|
+
def get_source_type(source)
|
117
|
+
ex = File.extname(source)
|
118
|
+
[:CPP, :C, :ASM].each do |t|
|
119
|
+
return t if tcs[:COMPILER][t][:SOURCE_FILE_ENDINGS].include?(ex)
|
120
|
+
end
|
121
|
+
nil
|
122
|
+
end
|
123
|
+
|
124
|
+
def get_sources_task_name
|
125
|
+
"Objects of #{name}"
|
126
|
+
end
|
127
|
+
|
128
|
+
def parse_includes(deps)
|
129
|
+
#deps look like "test.o: test.cpp test.h" -> remove .o and .cpp from list
|
130
|
+
return deps.gsub(/\\\n/,'').split()[2..-1]
|
131
|
+
end
|
132
|
+
|
133
|
+
def convert_depfile(depfile)
|
134
|
+
deps_string = read_file_or_empty_string(depfile)
|
135
|
+
deps = parse_includes(deps_string)
|
136
|
+
if deps.nil?
|
137
|
+
return # ok, because next run the source will be recompiled due to invalid depfile
|
138
|
+
end
|
139
|
+
expanded_deps = deps.map do |d|
|
140
|
+
tmp = d.gsub(/[\\]/,'/')
|
141
|
+
deps_in_depFiles << tmp
|
142
|
+
tmp
|
143
|
+
end
|
144
|
+
|
145
|
+
FileUtils.mkpath File.dirname(depfile)
|
146
|
+
File.open(depfile, 'wb') do |f|
|
147
|
+
f.write(expanded_deps.to_yaml)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def apply_depfile(depfile,outfileTask)
|
152
|
+
deps = nil
|
153
|
+
begin
|
154
|
+
deps = YAML.load_file(depfile)
|
155
|
+
deps.each do |d|
|
156
|
+
deps_in_depFiles << d
|
157
|
+
f = file d
|
158
|
+
f.ignore_missing_file
|
159
|
+
end
|
160
|
+
outfileTask.enhance(deps)
|
161
|
+
rescue
|
162
|
+
# may happen if depfile was not converted the last time
|
163
|
+
def outfileTask.needed?
|
164
|
+
true
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def create_object_file_tasks()
|
170
|
+
|
171
|
+
sources_to_build = {}
|
172
|
+
|
173
|
+
exclude_files = Set.new
|
174
|
+
exclude_sources.each do |p|
|
175
|
+
if p.include?".."
|
176
|
+
Printer.printError "Error: Exclude source file pattern '#{p}' must not include '..'"
|
177
|
+
return nil
|
178
|
+
end
|
179
|
+
|
180
|
+
Dir.glob(p).each {|f| exclude_files << f}
|
181
|
+
end
|
182
|
+
files = Set.new # do not build the same file twice
|
183
|
+
|
184
|
+
sources.each do |f|
|
185
|
+
if f.include?".."
|
186
|
+
Printer.printError "Error: Source file '#{f}' must not include '..'"
|
187
|
+
return nil
|
188
|
+
end
|
189
|
+
|
190
|
+
next if exclude_files.include?(f)
|
191
|
+
next if files.include?(f)
|
192
|
+
files << f
|
193
|
+
sources_to_build[f] = tcs4source(f)
|
194
|
+
end
|
195
|
+
|
196
|
+
source_patterns.each do |p|
|
197
|
+
if p.include?".."
|
198
|
+
Printer.printError "Error: Source file pattern '#{p}' must not include '..'"
|
199
|
+
return nil
|
200
|
+
end
|
201
|
+
|
202
|
+
globRes = Dir.glob(p)
|
203
|
+
if (globRes.length == 0)
|
204
|
+
Printer.printWarning "Warning: Source file pattern '#{p}' did not match to any file"
|
205
|
+
end
|
206
|
+
globRes.each do |f|
|
207
|
+
next if exclude_files.include?(f)
|
208
|
+
next if files.include?(f)
|
209
|
+
files << f
|
210
|
+
t = tcs4source(f)
|
211
|
+
t = tcs4source(p) if t == nil
|
212
|
+
sources_to_build[f] = t
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
ordered = sources_to_build.keys.sort()
|
217
|
+
dirs = []
|
218
|
+
filemap = {}
|
219
|
+
ordered.reverse.each do |o|
|
220
|
+
d = File.dirname(o)
|
221
|
+
if filemap.include?(d)
|
222
|
+
filemap[d] << o
|
223
|
+
else
|
224
|
+
filemap[d] = [o]
|
225
|
+
dirs << d
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
obj_tasks = []
|
230
|
+
dirs.each do |d|
|
231
|
+
filemap[d].reverse.each do |f|
|
232
|
+
obj_task = create_object_file_task(f, sources_to_build[f])
|
233
|
+
obj_tasks << obj_task unless obj_task.nil?
|
234
|
+
end
|
235
|
+
end
|
236
|
+
obj_tasks
|
237
|
+
end
|
238
|
+
|
239
|
+
def create_object_file_task(sourceRel, the_tcs)
|
240
|
+
if File.is_absolute?(sourceRel)
|
241
|
+
sourceRel = File.rel_from_to_project(@project_dir, sourceRel, false)
|
242
|
+
end
|
243
|
+
|
244
|
+
type = get_source_type(sourceRel)
|
245
|
+
return nil if type.nil?
|
246
|
+
|
247
|
+
objectRel = get_object_file(sourceRel)
|
248
|
+
@objects << objectRel
|
249
|
+
object = File.expand_path(objectRel)
|
250
|
+
source = File.expand_path(sourceRel)
|
251
|
+
|
252
|
+
depStr = ""
|
253
|
+
dep_file = nil
|
254
|
+
if type != :ASM
|
255
|
+
dep_file = get_dep_file(objectRel)
|
256
|
+
dep_file = "\""+dep_file+"\"" if dep_file.include?" "
|
257
|
+
depStr = the_tcs[:COMPILER][type][:DEP_FLAGS]
|
258
|
+
end
|
259
|
+
|
260
|
+
res = typed_file_task Rake::Task::OBJECT, object => source do
|
261
|
+
compiler = the_tcs[:COMPILER][type]
|
262
|
+
|
263
|
+
if Rake::application.preproFlags and compiler[:PREPRO_FLAGS] == ""
|
264
|
+
Printer.printInfo("Info: No preprocessor option available for " + sourceRel)
|
265
|
+
else
|
266
|
+
|
267
|
+
i_array = the_tcs == @tcs ? @include_string[type] : get_include_string(the_tcs, type)
|
268
|
+
d_array = the_tcs == @tcs ? @define_string[type] : get_define_string(the_tcs, type)
|
269
|
+
|
270
|
+
cmd = [compiler[:COMMAND]]
|
271
|
+
cmd += compiler[:COMPILE_FLAGS].split(" ")
|
272
|
+
if dep_file
|
273
|
+
cmd += depStr.split(" ")
|
274
|
+
if the_tcs[:COMPILER][type][:DEP_FLAGS_SPACE]
|
275
|
+
cmd << dep_file
|
276
|
+
else
|
277
|
+
cmd[cmd.length-1] << dep_file
|
278
|
+
end
|
279
|
+
end
|
280
|
+
cmd += Cxxproject::Utils::flagSplit(compiler[:FLAGS])
|
281
|
+
cmd += i_array
|
282
|
+
cmd += d_array
|
283
|
+
cmd += (compiler[:OBJECT_FILE_FLAG] + objectRel).split(" ")
|
284
|
+
cmd += compiler[:PREPRO_FLAGS].split(" ") if Rake::application.preproFlags
|
285
|
+
cmd << sourceRel
|
286
|
+
|
287
|
+
if Cxxproject::Utils.old_ruby?
|
288
|
+
cmd.map! {|c| ((c.include?" ") ? ("\""+c+"\"") : c )}
|
289
|
+
cmdLine = cmd.join(" ")
|
290
|
+
if cmdLine.length > 8000
|
291
|
+
inputName = objectRel+".tmp"
|
292
|
+
File.open(inputName,"wb") { |f| f.write(cmd[1..-1].join(" ")) }
|
293
|
+
inputName = "\""+inputName+"\"" if inputName.include?" "
|
294
|
+
consoleOutput = `#{compiler[:COMMAND] + " @" + inputName}`
|
295
|
+
else
|
296
|
+
consoleOutput = `#{cmd.join(" ")} 2>&1`
|
297
|
+
end
|
298
|
+
else
|
299
|
+
rd, wr = IO.pipe
|
300
|
+
cmd << {
|
301
|
+
:err=>wr,
|
302
|
+
:out=>wr
|
303
|
+
}
|
304
|
+
sp = spawn(*cmd)
|
305
|
+
cmd.pop
|
306
|
+
consoleOutput = ProcessHelper.readOutput(sp, rd, wr)
|
307
|
+
end
|
308
|
+
|
309
|
+
process_result(cmd, consoleOutput, compiler[:ERROR_PARSER], "Compiling #{sourceRel}")
|
310
|
+
|
311
|
+
convert_depfile(dep_file) if dep_file
|
312
|
+
|
313
|
+
check_config_file()
|
314
|
+
end
|
315
|
+
end
|
316
|
+
enhance_with_additional_files(res)
|
317
|
+
add_output_dir_dependency(object, res, false)
|
318
|
+
apply_depfile(dep_file, res) if depStr != ""
|
319
|
+
res
|
320
|
+
end
|
321
|
+
|
322
|
+
def enhance_with_additional_files(task)
|
323
|
+
task.enhance(file_dependencies)
|
324
|
+
task.enhance(@config_files)
|
325
|
+
end
|
326
|
+
|
327
|
+
def process_console_output(console_output, error_parser)
|
328
|
+
ret = false
|
329
|
+
if not console_output.empty?
|
330
|
+
if error_parser
|
331
|
+
begin
|
332
|
+
error_descs, console_output_full = error_parser.scan_lines(console_output, @project_dir)
|
333
|
+
|
334
|
+
console_output = console_output_full if Rake::application.consoleOutput_fullnames
|
335
|
+
|
336
|
+
ret = error_descs.any? { |e| e.severity == ErrorParser::SEVERITY_ERROR }
|
337
|
+
|
338
|
+
console_output.gsub!(/[\r]/, "")
|
339
|
+
highlighter = @tcs[:CONSOLE_HIGHLIGHTER]
|
340
|
+
if (highlighter and highlighter.enabled?)
|
341
|
+
puts highlighter.format(console_output, error_descs, error_parser)
|
342
|
+
else
|
343
|
+
puts console_output
|
344
|
+
end
|
345
|
+
|
346
|
+
Rake.application.idei.set_errors(error_descs)
|
347
|
+
rescue Exception => e
|
348
|
+
Printer.printWarning "Parsing output failed (maybe language not set to English?): " + e.message
|
349
|
+
puts "Original output:"
|
350
|
+
puts console_output
|
351
|
+
end
|
352
|
+
end
|
353
|
+
end
|
354
|
+
ret
|
355
|
+
end
|
356
|
+
|
357
|
+
def prepare_tasks_for_objects
|
358
|
+
if (@output_dir_abs)
|
359
|
+
CLEAN.include(@output_dir + "/objects/" + @name)
|
360
|
+
end
|
361
|
+
|
362
|
+
@objects = []
|
363
|
+
t = multitask get_sources_task_name
|
364
|
+
t.type = Rake::Task::SOURCEMULTI
|
365
|
+
t.transparent_timestamp = true
|
366
|
+
t.set_building_block(self)
|
367
|
+
t
|
368
|
+
end
|
369
|
+
|
370
|
+
end
|
371
|
+
end
|