Mxx_ru 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (147) hide show
  1. data/COPYING +26 -0
  2. data/NEWS +52 -0
  3. data/README +21 -0
  4. data/Rakefile +32 -0
  5. data/examples/exe_and_lib/main.cpp +15 -0
  6. data/examples/exe_and_lib/prj.rb +11 -0
  7. data/examples/exe_and_lib/say.cpp +13 -0
  8. data/examples/exe_and_lib/say.hpp +11 -0
  9. data/examples/exe_and_lib/say.rb +7 -0
  10. data/examples/exe_dll_lib/inout.cpp +15 -0
  11. data/examples/exe_dll_lib/inout.hpp +26 -0
  12. data/examples/exe_dll_lib/inout.rb +18 -0
  13. data/examples/exe_dll_lib/main.cpp +23 -0
  14. data/examples/exe_dll_lib/prj.rb +11 -0
  15. data/examples/exe_dll_lib/say.cpp +13 -0
  16. data/examples/exe_dll_lib/say.hpp +12 -0
  17. data/examples/exe_dll_lib/say.rb +9 -0
  18. data/examples/exe_dll_lib_2/build.rb +7 -0
  19. data/examples/exe_dll_lib_2/inout/inout.cpp +15 -0
  20. data/examples/exe_dll_lib_2/inout/inout.hpp +26 -0
  21. data/examples/exe_dll_lib_2/inout/prj.rb +16 -0
  22. data/examples/exe_dll_lib_2/main/main.cpp +23 -0
  23. data/examples/exe_dll_lib_2/main/prj.rb +9 -0
  24. data/examples/exe_dll_lib_2/say/prj.rb +8 -0
  25. data/examples/exe_dll_lib_2/say/say.cpp +13 -0
  26. data/examples/exe_dll_lib_2/say/say.hpp +12 -0
  27. data/examples/simple_exe/main.cpp +26 -0
  28. data/examples/simple_exe/prj.rb +7 -0
  29. data/lib/mxx_ru/abstract_target.rb +283 -0
  30. data/lib/mxx_ru/binary_target.rb +89 -0
  31. data/lib/mxx_ru/binary_unittest.rb +130 -0
  32. data/lib/mxx_ru/cpp/analyzer.rb +230 -0
  33. data/lib/mxx_ru/cpp/composite.rb +106 -0
  34. data/lib/mxx_ru/cpp/detect_toolset.rb +122 -0
  35. data/lib/mxx_ru/cpp/mode.rb +85 -0
  36. data/lib/mxx_ru/cpp/obj_placement.rb +321 -0
  37. data/lib/mxx_ru/cpp/qt.rb +333 -0
  38. data/lib/mxx_ru/cpp/rucodegen.rb +114 -0
  39. data/lib/mxx_ru/cpp/source_file.rb +71 -0
  40. data/lib/mxx_ru/cpp/target.rb +1371 -0
  41. data/lib/mxx_ru/cpp/toolset.rb +1029 -0
  42. data/lib/mxx_ru/cpp/toolsets/bcc_win32_5.rb +52 -0
  43. data/lib/mxx_ru/cpp/toolsets/bcc_win32_family.rb +451 -0
  44. data/lib/mxx_ru/cpp/toolsets/c89_etk_nsk.rb +56 -0
  45. data/lib/mxx_ru/cpp/toolsets/c89_nsk.rb +56 -0
  46. data/lib/mxx_ru/cpp/toolsets/c89_nsk_family.rb +273 -0
  47. data/lib/mxx_ru/cpp/toolsets/gcc_cygwin.rb +54 -0
  48. data/lib/mxx_ru/cpp/toolsets/gcc_family.rb +382 -0
  49. data/lib/mxx_ru/cpp/toolsets/gcc_linux.rb +60 -0
  50. data/lib/mxx_ru/cpp/toolsets/gcc_mingw.rb +144 -0
  51. data/lib/mxx_ru/cpp/toolsets/gcc_sparc_solaris.rb +87 -0
  52. data/lib/mxx_ru/cpp/toolsets/vc7.rb +62 -0
  53. data/lib/mxx_ru/cpp/toolsets/vc8.rb +452 -0
  54. data/lib/mxx_ru/cpp/toolsets/vc_family.rb +428 -0
  55. data/lib/mxx_ru/cpp.rb +36 -0
  56. data/lib/mxx_ru/ex.rb +134 -0
  57. data/lib/mxx_ru/makestyle_generator.rb +138 -0
  58. data/lib/mxx_ru/textfile_unittest.rb +284 -0
  59. data/lib/mxx_ru/util.rb +258 -0
  60. data/tests/c/pcre/chartables.c +183 -0
  61. data/tests/c/pcre/config.h +99 -0
  62. data/tests/c/pcre/dftables.c +167 -0
  63. data/tests/c/pcre/get.c +349 -0
  64. data/tests/c/pcre/internal.h +677 -0
  65. data/tests/c/pcre/maketables.c +140 -0
  66. data/tests/c/pcre/pcre.c +8304 -0
  67. data/tests/c/pcre/pcre.h +193 -0
  68. data/tests/c/pcre/pcre.rb +14 -0
  69. data/tests/c/pcre/pcredemo.c +316 -0
  70. data/tests/c/pcre/pcregrep.c +642 -0
  71. data/tests/c/pcre/pcreposix.c +305 -0
  72. data/tests/c/pcre/pcreposix.h +88 -0
  73. data/tests/c/pcre/pcretest.c +1483 -0
  74. data/tests/c/pcre/perltest +211 -0
  75. data/tests/c/pcre/printint.c +360 -0
  76. data/tests/c/pcre/study.c +472 -0
  77. data/tests/cpp/mswin_res_dll/build.rb +14 -0
  78. data/tests/cpp/mswin_res_dll/dll.cpp +17 -0
  79. data/tests/cpp/mswin_res_dll/dll.rb +30 -0
  80. data/tests/cpp/mswin_res_dll/dll.rc +48 -0
  81. data/tests/cpp/mswin_res_dll/h/dll.hpp +8 -0
  82. data/tests/cpp/mswin_res_dll/h/res.h +3 -0
  83. data/tests/cpp/mswin_res_dll/main.cpp +13 -0
  84. data/tests/cpp/mswin_res_dll/main.rb +20 -0
  85. data/tests/cpp/mswin_res_dll/res/tree_fol.bmp +0 -0
  86. data/tests/cpp/mswin_res_dll/res/tree_state_1.bmp +0 -0
  87. data/tests/cpp/mswin_res_dll/res/tree_state_2.bmp +0 -0
  88. data/tests/cpp/mswin_res_exe/build.rb +23 -0
  89. data/tests/cpp/mswin_res_exe/h/res.h +3 -0
  90. data/tests/cpp/mswin_res_exe/main.cpp +17 -0
  91. data/tests/cpp/mswin_res_exe/main.rc +48 -0
  92. data/tests/cpp/mswin_res_exe/res/tree_fol.bmp +0 -0
  93. data/tests/cpp/mswin_res_exe/res/tree_state_1.bmp +0 -0
  94. data/tests/cpp/mswin_res_exe/res/tree_state_2.bmp +0 -0
  95. data/tests/cpp/rucodegen/host_config.cpp +20 -0
  96. data/tests/cpp/rucodegen/host_config.rb +14 -0
  97. data/tests/cpp/rucodegen/impl/conn_params.cpp +7 -0
  98. data/tests/cpp/rucodegen/impl/conn_params.rb +14 -0
  99. data/tests/cpp/rucodegen/impl/h/conn_params.hpp +10 -0
  100. data/tests/cpp/rucodegen/prj.rb +17 -0
  101. data/tests/cpp/textfile_unittest/build.rb +8 -0
  102. data/tests/cpp/textfile_unittest/etalons/out_0.txt +0 -0
  103. data/tests/cpp/textfile_unittest/etalons/out_1.txt +1 -0
  104. data/tests/cpp/textfile_unittest/etalons/out_128.txt +128 -0
  105. data/tests/cpp/textfile_unittest/main.cpp +89 -0
  106. data/tests/cpp/textfile_unittest/prj.rb +8 -0
  107. data/tests/cpp/textfile_unittest/prj.ut.rb +18 -0
  108. data/tests/cpp/toolset_name.rb +6 -0
  109. data/tests/cpp/vc_cleanup/cout.log +72 -0
  110. data/tests/cpp/vc_cleanup/dll_hi.cpp +5 -0
  111. data/tests/cpp/vc_cleanup/exe_hi.cpp +10 -0
  112. data/tests/cpp/vc_cleanup/lib_hi.cpp +5 -0
  113. data/tests/cpp/vc_cleanup/prj_dll_no_implib.rb +10 -0
  114. data/tests/cpp/vc_cleanup/prj_dll_no_implib_simple_target_root.rb +11 -0
  115. data/tests/cpp/vc_cleanup/prj_dll_with_implib.rb +11 -0
  116. data/tests/cpp/vc_cleanup/prj_dll_with_implib_simple_target_root.rb +14 -0
  117. data/tests/cpp/vc_cleanup/prj_exe_no_implib.rb +10 -0
  118. data/tests/cpp/vc_cleanup/prj_exe_no_implib_simple_target_root.rb +11 -0
  119. data/tests/cpp/vc_cleanup/prj_lib.rb +10 -0
  120. data/tests/cpp/vc_cleanup/prj_lib_with_simple_target_root.rb +11 -0
  121. data/tests/cpp/vc_cleanup/tc_vc_cleanup.rb +60 -0
  122. data/tests/mxx_ru/change_default_value/ignoring_by_build_root/build.rb +8 -0
  123. data/tests/mxx_ru/change_default_value/ignoring_by_build_root/child_1.rb +5 -0
  124. data/tests/mxx_ru/change_default_value/ignoring_by_child_1/build.rb +7 -0
  125. data/tests/mxx_ru/change_default_value/ignoring_by_child_1/child_1.rb +5 -0
  126. data/tests/mxx_ru/change_default_value/ignoring_by_child_1/child_2.rb +5 -0
  127. data/tests/mxx_ru/change_default_value/ok/build.rb +8 -0
  128. data/tests/mxx_ru/change_default_value/ok/child_1.rb +8 -0
  129. data/tests/mxx_ru/tc_makestyle_generator.rb +117 -0
  130. data/tests/mxx_ru/vc8/tc_actual_manifest.rb +230 -0
  131. data/tests/mxx_ru/vc8/tc_append_mt_commands.rb +104 -0
  132. data/tests/mxx_ru/vc8/tc_default_manifest.rb +17 -0
  133. data/tests/mxx_ru/vc8/tc_define_manifest.rb +173 -0
  134. data/tests/mxx_ru/vc8/tc_drop_default_manifest.rb +16 -0
  135. data/tests/mxx_ru/vc8/tc_invalid_params.rb +81 -0
  136. data/tests/mxx_ru/vc8/ts_vc8.rb +10 -0
  137. data/tests/qt/aclock/aclock.cpp +148 -0
  138. data/tests/qt/aclock/aclock.h +45 -0
  139. data/tests/qt/aclock/main.cpp +28 -0
  140. data/tests/qt/aclock/prj.rb +21 -0
  141. data/tests/qt/iconview/main.cpp +76 -0
  142. data/tests/qt/iconview/prj.rb +21 -0
  143. data/tests/qt/toplevel/main.cpp +9 -0
  144. data/tests/qt/toplevel/options.ui +587 -0
  145. data/tests/qt/toplevel/options.ui.h +98 -0
  146. data/tests/qt/toplevel/prj.rb +21 -0
  147. metadata +241 -0
@@ -0,0 +1,1371 @@
1
+ #--
2
+ # Copyright (c) 1996-2004, Yauheni Akhotnikau
3
+ # Copyright (c) 2004-2006, JSC Intervale
4
+ # Copyright (c) 2006, The Mxx_ru Project
5
+ # All rights reserved.
6
+ #
7
+ # Redistribution and use in source and binary forms, with or without modification,
8
+ # are permitted provided that the following conditions are met:
9
+ #
10
+ # 1. Redistributions of source code must retain the above copyright notice,
11
+ # this list of conditions and the following disclaimer.
12
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ # this list of conditions and the following disclaimer in the documentation
14
+ # and/or other materials provided with the distribution.
15
+ # 3. The name of the author may not be used to endorse or promote products derived
16
+ # from this software without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
19
+ # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20
+ # AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
21
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
+ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26
+ # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ #++
28
+
29
+ require 'mxx_ru/binary_target'
30
+ require 'mxx_ru/cpp/mode'
31
+ require 'mxx_ru/cpp/source_file'
32
+ require 'mxx_ru/cpp/obj_placement'
33
+ require 'mxx_ru/cpp/analyzer'
34
+
35
+ # Base class for all targets of C/C++ projects.
36
+ module Mxx_ru
37
+
38
+ module Cpp
39
+ # Runtime mode types.
40
+
41
+ # Default mode.
42
+ # Nor debug information nor optimization options are set.
43
+ RUNTIME_DEFAULT = "default"
44
+ # Release mode. Optimization is turned on.
45
+ RUNTIME_RELEASE = "release"
46
+ # Debug mode. Debug information is generated.
47
+ RUNTIME_DEBUG = "debug"
48
+
49
+ # RTTI mode types.
50
+
51
+ # Default RTTI mode. No RTTI options are passed to compiler.
52
+ RTTI_DEFAULT = "default"
53
+ # RTTI mode should be enabled.
54
+ RTTI_ENABLED = "enabled"
55
+ # RTTI mode should be disabled.
56
+ RTTI_DISABLED = "disabled"
57
+
58
+ # RTL mode types.
59
+
60
+ # Default compiler libraries are used.
61
+ RTL_DEFAULT = "default"
62
+ # Use shared runtime library.
63
+ RTL_SHARED = "shared"
64
+ # Use static runtime library.
65
+ RTL_STATIC = "static"
66
+
67
+ # Threading mode types.
68
+
69
+ # Default compiler threading mode.
70
+ THREADING_DEFAULT = "default"
71
+ # Multithreading is used.
72
+ THREADING_MULTI = "multi"
73
+ # Multithreading is not used.
74
+ THREADING_SINGLE = "single"
75
+
76
+ # Screen mode types.
77
+
78
+ # Console application.
79
+ SCREEN_CONSOLE = "console"
80
+ # Windowed application.
81
+ SCREEN_WINDOW = "window"
82
+
83
+ # Optimization modes.
84
+
85
+ # Optimization by size.
86
+ OPTIM_SIZE = "size"
87
+ # Optimization by speed.
88
+ OPTIM_SPEED = "speed"
89
+
90
+ # Auxiliary class, intended to store objects like
91
+ # runtime_mode, rtl_mode, etc, with information about
92
+ # who has set this or that mode.
93
+ class Global_single_value_option
94
+ attr_reader :name
95
+ attr_reader :default_value
96
+ attr_reader :value
97
+ attr_reader :who
98
+
99
+ # [_a_name_] Name.
100
+ # [_a_default_value_] Default value.
101
+ # [_a_available_values_] Available values. Array of String.
102
+ def initialize(
103
+ a_name,
104
+ a_default_value,
105
+ a_available_values )
106
+
107
+ @name = a_name
108
+ @default_value = a_default_value
109
+ @default_value_changer = nil
110
+ @available_values = a_available_values
111
+ @value = @default_value
112
+ @who = "n/a"
113
+ end
114
+
115
+ # Change default value.
116
+ #
117
+ # Description of this change is printed to standard output.
118
+ #
119
+ # [_a_value_] new default value.
120
+ # [_a_who_] who tries to change value.
121
+ def change_default( a_value, a_who )
122
+ check_value( a_value, a_who )
123
+
124
+ if nil == @default_value_changer
125
+ need_change_current = ( @value == @default_value )
126
+ @default_value = a_value
127
+ @default_value_changer = a_who
128
+ @value = @default_value if need_change_current
129
+ elsif a_value != @default_value
130
+ puts "WARNING: ignoring change default value for '#{@name}' to " +
131
+ "'#{a_value}' by '#{a_who}'; default value already changed by " +
132
+ "'#{@default_value_changer}'"
133
+ end
134
+ end
135
+
136
+ # Value change.
137
+ # If new value is the same as default, value change try is ignored.
138
+ #
139
+ # [_a_value_] New value.
140
+ # [_a_who_] Who tries to change value.
141
+ def change(
142
+ a_value,
143
+ a_who )
144
+
145
+ if a_value != @default_value
146
+ check_value( a_value, a_who )
147
+
148
+ if @value == @default_value
149
+ # Value did not change till now.
150
+ @value = a_value
151
+ @who = a_who
152
+ else
153
+ # Value is already changed. It is necessary to be convinced,
154
+ # that values are the same. Otherwise there is a conflict.
155
+ if a_value != @value
156
+ raise Mxx_ru::Global_option_conflict_ex.new(
157
+ @name, @value, @who, a_value, a_who )
158
+ end
159
+ end
160
+ end
161
+ end
162
+
163
+ protected
164
+ # Search value in available values. Raise exceptions if value
165
+ # not found.
166
+ def check_value( value, who )
167
+ if !@available_values.include?( value )
168
+ raise Mxx_ru::Global_option_disallowed_value_ex.new(
169
+ @name, @available_values, value, who )
170
+ end
171
+ end
172
+ end # class Global_single_value_option
173
+
174
+ # Auxiliary class for a storage of options, which can be broken on 3 groups:
175
+ # global, local and upspread.
176
+ # Examples of such options are: defines, include_paths,
177
+ # compiler_options, linker_options, ...
178
+ class Spreadable_option
179
+ # A name of a method, which should be used for reception of all options.
180
+ ALL_OPT_METHOD = "all"
181
+ # A name of a method, which should be used for reception of all upspread options.
182
+ ALL_UPSPREAD_METHOD = "all_upspreads"
183
+
184
+ # The global tick counter which is used for check that cached values are still correct.
185
+ # Is increased at each reference to add.
186
+ @@last_change_time = 1
187
+ # Global hash, in which the time of last change of options with a concrete name is fixed.
188
+ @@cache_times = Hash.new
189
+
190
+ # Set new time of change of value of an option.
191
+ # This method is intended for use at change of global options, which are stored
192
+ # separately from spreadable-options, but which values are included
193
+ # in values of spreadable-options.
194
+ def Spreadable_option.refresh_option_change_time( a_option_name )
195
+ @@last_change_time = @@last_change_time + 1
196
+ @@cache_times[ a_option_name ] = @@last_change_time
197
+ end
198
+
199
+ # Constructor.
200
+ #
201
+ # [_a_option_name_] The name of an option, which serves the given object.
202
+ # This name will be used for fixation of time of caching
203
+ # in @@cache_times object.
204
+ def initialize( a_option_name )
205
+
206
+ @@cache_times[ a_option_name ] = 1
207
+
208
+ # Own name.
209
+ @name = a_option_name
210
+
211
+ # Own options.
212
+ @locals = Array.new
213
+ # Spreadable options.
214
+ @upspreads = Array.new
215
+
216
+ # Cached value of all method.
217
+ @all_cache_value = Array.new
218
+ # @@last_change_time value at caching moment in all method.
219
+ @all_cache_time = 0
220
+
221
+ # Cached value of all_upspread method.
222
+ @all_upspread_cache_value = Array.new
223
+ # @@last_change_time value at caching moment in all_upspread method.
224
+ @all_upspread_cache_time = 0
225
+
226
+ end
227
+
228
+ # Add option.
229
+ #
230
+ # [_a_option_] Added value.
231
+ # [_a_mode_] Local or upspread option.
232
+ # Is set by values Mxx_ru::Cpp::Target::OPT_LOCAL,
233
+ # Mxx_ru::Cpp::Target::OPT_UPSPEAD.
234
+ def add(
235
+ a_option,
236
+ a_mode = Mxx_ru::Cpp::Target::OPT_LOCAL )
237
+ add_unique_to( a_option, check_opt_mode( a_mode ) )
238
+ end
239
+
240
+ # To get only upspread options..
241
+ def upspeads_only
242
+ return @upspreads
243
+ end
244
+
245
+ # To generate the list of all options.
246
+ #
247
+ # [_a_globals_] The storage of global options, from which is necessary to take values.
248
+ # [_a_subprojects_] The list of all subordinated projects.
249
+ # Array of Mxx_ru::Abstract_target.
250
+ # [_a_upspreads_method_] The name of a method, which needs to be called from
251
+ # the subordinated project, to get it's list of all upspread options.
252
+ def all(
253
+ a_globals,
254
+ a_subprojects,
255
+ a_upspreads_method )
256
+
257
+ if @all_cache_time < @@cache_times[ @name ]
258
+ # It is necessary to calculate cache anew.
259
+ r = Array.new
260
+ r << a_globals << @locals
261
+
262
+ # At the same time it is possible to update cache of upspread-options.
263
+ if @all_upspread_cache_time < @@cache_times[ @name ]
264
+ u = Array.new
265
+ u << @upspreads
266
+
267
+ a_subprojects.each { |p|
268
+ if p.kind_of?( Mxx_ru::Cpp::Target )
269
+ u << p.send( a_upspreads_method )
270
+ end
271
+ }
272
+
273
+ @all_upspread_cache_time = @@last_change_time
274
+ @all_upspread_cache_value = u.flatten.uniq
275
+ end
276
+
277
+ r << @all_upspread_cache_value
278
+
279
+ @all_cache_value = r.flatten.uniq
280
+ @all_cache_time = @@last_change_time
281
+ end
282
+
283
+ return @all_cache_value
284
+ end
285
+
286
+ # To generate the list of all upspread options.
287
+ #
288
+ # [_a_subprojects_] The list of all subordinated projects.
289
+ # Array of Mxx_ru::Abstract_target.
290
+ # [_a_upspreads_method_] The name of a method, which needs to be called from
291
+ # the subordinated project, to get it's list of all upspread options.
292
+ def all_upspreads(
293
+ a_subprojects,
294
+ a_upspreads_method )
295
+
296
+ if @all_upspread_cache_time < @@cache_times[ @name ]
297
+ # It is necessary to calculate cache anew.
298
+ r = Array.new
299
+ r << @upspreads
300
+
301
+ a_subprojects.each { |p|
302
+ if p.kind_of?( Mxx_ru::Cpp::Target )
303
+ r << p.send( a_upspreads_method )
304
+ end
305
+ }
306
+
307
+ @all_upspread_cache_value = r.flatten.uniq
308
+ @all_upspread_cache_time = @@last_change_time
309
+ end
310
+
311
+ return @all_upspread_cache_value
312
+ end
313
+
314
+ protected
315
+ # Add value to Array, if that value is still is not present there.
316
+ def add_unique_to( what, to )
317
+ if !to.include?( what )
318
+ to.push( what )
319
+
320
+ Spreadable_option::refresh_option_change_time( @name )
321
+ end
322
+ end
323
+
324
+ # Check up value of a mode parameter on equality
325
+ # either OPT_UPSPREAD, or OPT_LOCAL and return object of Array type,
326
+ # in which it is necessary to place value.
327
+ #
328
+ # [_a_mode_] mode parameter value for check.
329
+ def check_opt_mode(
330
+ a_mode )
331
+ if Mxx_ru::Cpp::Target::OPT_UPSPREAD == a_mode
332
+ return @upspreads
333
+ elsif Mxx_ru::Cpp::Target::OPT_LOCAL == a_mode
334
+ return @locals
335
+ else
336
+ raise Mxx_ru::Invalid_value_ex.new(
337
+ "invalid option mode #{a_mode}" )
338
+ end
339
+ end
340
+ end
341
+
342
+ # Target type (exe, lib, dll, unittest, composite etc.).
343
+ # The real type of the target is defined by a derivative class.
344
+ class Target_type
345
+ def name
346
+ raise Abstract_method_ex.new( "Mxx_ru::Cpp::Target_type::name" )
347
+ end
348
+ end
349
+
350
+ # Target type is application.
351
+ class Exe_target_type < Target_type
352
+ TYPE = "exe"
353
+
354
+ def name
355
+ return TYPE
356
+ end
357
+ end
358
+
359
+ # Target type is static library (lib).
360
+ class Lib_target_type < Target_type
361
+ TYPE = "lib"
362
+
363
+ def name
364
+ return TYPE
365
+ end
366
+ end
367
+
368
+ # Target type is shared library (dll).
369
+ class Dll_target_type < Target_type
370
+ TYPE = "dll"
371
+
372
+ def name
373
+ return TYPE
374
+ end
375
+ end
376
+
377
+ # Base class for all targets of C/C++ projects.
378
+ class Target < Mxx_ru::Binary_target
379
+ # Description of obj_placement object installed.
380
+ # Used to store global obj_placement.
381
+ class Global_obj_placement_info
382
+ # Global obj_placement.
383
+ attr_reader :placement
384
+ # Who was set obj_placement.
385
+ attr_reader :who
386
+
387
+ def initialize
388
+ @placement = nil
389
+ @who = nil
390
+ end
391
+
392
+ # Change option value.
393
+ # If placement already set, exception thrown.
394
+ def change( a_placement, a_who )
395
+ if nil != a_placement && nil != @placement
396
+ raise Mxx_ru::Global_option_conflict_ex.new(
397
+ "global_obj_placement",
398
+ @placement.class.name,
399
+ @who,
400
+ a_placement.class.name,
401
+ a_who )
402
+ end
403
+
404
+ @placement = a_placement
405
+ @who = a_who
406
+ end
407
+ end
408
+
409
+ # Action class to store option in Array.
410
+ class Global_option_inserter
411
+
412
+ # [_a_option_name_] Name of option served. It is necessary for
413
+ # referecne to
414
+ # Spreadable_option.refresh_option_change_time
415
+ # method.
416
+ # [_a_receiver_] Where to add value.
417
+ def initialize(
418
+ a_option_name,
419
+ a_receiver )
420
+ @option_name = a_option_name
421
+ @receiver = a_receiver
422
+ end
423
+
424
+ def call( *args )
425
+ @receiver.push( *args )
426
+
427
+ Spreadable_option::refresh_option_change_time( @option_name )
428
+ end
429
+ end # class Global_option_inserter
430
+
431
+ # Action class to store option in Spreadable_option object.
432
+ class Spreadable_option_inserter
433
+
434
+ # [_a_receiver_] Where to add value.
435
+ def initialize(
436
+ a_receiver )
437
+ @receiver = a_receiver
438
+ end
439
+
440
+ def call( *args )
441
+ @receiver.send( "add", *args )
442
+ end
443
+ end # class Spreadable_option_inserter
444
+
445
+ # Action class to get all option values (local, global and upspread)
446
+ # from Spreadable_option object.
447
+ class Spreadable_option_all_extractor
448
+
449
+ # [_a_option_] In whom to call a "call" method.
450
+ # [_a_globals_] Whence to take values of global options.
451
+ # [_a_target_] The target, from which is necessary to take the list
452
+ # of subordinated projects.
453
+ # [_a_upspreads_only_method_] A method which should be called on
454
+ # subordinated projects for extracting
455
+ # the values of their upspreadable options.
456
+ def initialize(
457
+ a_option,
458
+ a_globals,
459
+ a_target,
460
+ a_upspreads_only_method )
461
+
462
+ @option = a_option
463
+ @globals = a_globals
464
+ @target = a_target
465
+ @upspreads_only_method = a_upspreads_only_method
466
+ end
467
+
468
+ def call( *args )
469
+ return @option.all( @globals, @target.mxx_required_prjs,
470
+ @upspreads_only_method )
471
+ end
472
+ end # class Spreadable_option_all_extractor
473
+
474
+ # Action class to get upspreadable option values only
475
+ # from Spreadable_option object.
476
+ class Spreadable_option_upspread_extractor
477
+
478
+ # [_a_option_] In whom to call a "call" method.
479
+ # [_a_target_] The target, from which is necessary to take the list
480
+ # of subordinated projects.
481
+ # [_a_upspreads_only_method_] A method which should be called on
482
+ # subordinated projects for extracting
483
+ # the values of their upspreadable options.
484
+ def initialize(
485
+ a_option,
486
+ a_target,
487
+ a_upspreads_only_method )
488
+
489
+ @option = a_option
490
+ @target = a_target
491
+ @upspreads_only_method = a_upspreads_only_method
492
+ end
493
+
494
+ def call( *args )
495
+ return @option.all_upspreads( @target.mxx_required_prjs,
496
+ @upspreads_only_method )
497
+ end
498
+ end # class Spreadable_option_all_extractor
499
+
500
+ # Runtime mode storage.
501
+ @@mxx_runtime_mode = Global_single_value_option.new(
502
+ "runtime_mode", RUNTIME_DEFAULT,
503
+ [ RUNTIME_RELEASE, RUNTIME_DEBUG ] )
504
+ # RTTI mode storage.
505
+ @@mxx_rtti_mode = Global_single_value_option.new(
506
+ "rtti_mode", RTTI_DEFAULT,
507
+ [ RTTI_ENABLED, RTTI_DISABLED ] )
508
+ # RTL mode storage.
509
+ @@mxx_rtl_mode = Global_single_value_option.new(
510
+ "rtl_mode", RTL_DEFAULT,
511
+ [ RTL_SHARED, RTL_STATIC ] )
512
+ # Threading mode storage.
513
+ @@mxx_threading_mode = Global_single_value_option.new(
514
+ "threading_mode", THREADING_DEFAULT,
515
+ [ THREADING_MULTI, THREADING_SINGLE ] )
516
+
517
+ # The storage of global description of obj_placement.
518
+ @@mxx_global_obj_placement = Global_obj_placement_info.new
519
+
520
+ # Global options storage.
521
+ # The key is a String, the value is Array of String.
522
+ @@mxx_globals = Hash.new
523
+
524
+ # Attribute that the option should be upspreadable.
525
+ OPT_UPSPREAD = "upspread"
526
+ # Attribute that the option should be local.
527
+ OPT_LOCAL = "local"
528
+
529
+ # Path, the name of result of a target is related to.
530
+ # If contains an empty value, target should be defined using a full path.
531
+ # Otherwise the value of mxx_target_root is concatenated with a given target name.
532
+ attr_reader :mxx_target_root
533
+ # Path, the names of source files are related to.
534
+ attr_reader :mxx_sources_root
535
+ # Screen mode. Console by default.
536
+ attr_reader :mxx_screen_mode
537
+ # The list of source C-files.
538
+ # Array of Mxx_ru::Cpp::Cpp_source_file objects.
539
+ attr_reader :mxx_c_files
540
+ # The list of source C++-files.
541
+ # Array of Mxx_ru::Cpp::Cpp_source_file objects.
542
+ attr_reader :mxx_cpp_files
543
+ # Object files list.
544
+ attr_reader :mxx_obj_files
545
+ # Name of mswin resource file.
546
+ # Should be object of Mxx-ru::Cpp::Mswin_rc_file type.
547
+ # May contain nil value, if resources are not used.
548
+ attr_reader :mxx_mswin_rc_file
549
+ # The name of compiled mswin resource file.
550
+ # Should be a string.
551
+ # May contain nil value, if resources are not used.
552
+ attr_reader :mxx_mswin_res_file
553
+ # Import library folder.
554
+ # May contain nil value.
555
+ attr_reader :mxx_implib_path
556
+ # The name to get target result.
557
+ # Should not contain file extension.
558
+ attr_reader :mxx_target_name
559
+ # Optimization mode. By default, speed optimization is used.
560
+ attr_reader :mxx_optimization
561
+
562
+ # Generator for methods to manipulation with 'runtime_mode',
563
+ # 'rtti_mode', 'rtl_mode', 'threading_mode' and so on.
564
+ #
565
+ # By default generates 3 methods:
566
+ # # Setter
567
+ # def <option>( value ); ...; end
568
+ # # Setter for default value.
569
+ # def default_<option>( value ); ...; end
570
+ # # Getter
571
+ # def mxx_<option>; ...; end
572
+ #
573
+ # If no_getter == :nogetter then getter method not generated.
574
+ def self.global_option_methods( option, getter = :withgetter )
575
+ class_eval %Q{
576
+ def #{option}( value )
577
+ @@mxx_#{option}.change( value, prj_alias )
578
+ end
579
+ def default_#{option}( value )
580
+ @@mxx_#{option}.change_default( value, prj_alias )
581
+ end
582
+ }
583
+ class_eval %Q{
584
+ def mxx_#{option}
585
+ @@mxx_#{option}.value
586
+ end
587
+ } unless getter == :nogetter
588
+ end
589
+
590
+ # Constructor
591
+ # [_a_prj_alias_] Project identifier.
592
+ def initialize( a_prj_alias )
593
+
594
+ super( a_prj_alias )
595
+
596
+ @mxx_target_root = ""
597
+
598
+ @mxx_sources_root = File.dirname( a_prj_alias )
599
+
600
+ @mxx_screen_mode = SCREEN_CONSOLE
601
+
602
+ @mxx_c_files = Array.new
603
+ @mxx_cpp_files = Array.new
604
+
605
+ @mxx_mswin_rc_file = nil
606
+ @mxx_mswin_res_file = nil
607
+
608
+ @mxx_obj_files = Array.new
609
+
610
+ # The storage of local options.
611
+ # The key is a String, the value is Spreadable_option.
612
+ @mxx_locals = Hash.new
613
+
614
+ @mxx_implib_path = nil
615
+
616
+ # Object, which defines accommodation of object files.
617
+ @mxx_obj_placement = nil
618
+
619
+ @mxx_target_name = nil
620
+
621
+ @mxx_optimization = OPTIM_SPEED
622
+
623
+ # Result of work of the previous reference to a build method.
624
+ # During a repeted calls of build method target build is not performed,
625
+ # and this value is returned.
626
+ @mxx_last_build_result = nil
627
+
628
+ # True if toolset has completely defined all compiler and linker options required.
629
+ @mxx_all_options_defined = false
630
+
631
+ # Action list for methods, which are implemented through
632
+ # overloaded method_missing method.
633
+ @mxx_missing_actions = Hash.new
634
+
635
+ add_spreadable_option( "compiler_option" )
636
+ add_spreadable_option( "cpp_compiler_option" )
637
+ add_spreadable_option( "c_compiler_option" )
638
+ add_spreadable_option( "linker_option" )
639
+ add_spreadable_option( "librarian_option" )
640
+ add_spreadable_option( "define" )
641
+ add_spreadable_option( "include_path" )
642
+ add_spreadable_option( "mswin_rc_option" )
643
+ add_spreadable_option( "mswin_rc_include_path" )
644
+ add_spreadable_option( "mswin_rc_define" )
645
+ add_spreadable_option( "mswin_rlink_option" )
646
+
647
+ end
648
+
649
+ # Overloading standard reaction to absence of a method in a class.
650
+ # A number of methods are implemented with a help of that trick.
651
+ # Actions for such methods should be defined in @mxx_missing_actions.
652
+ def method_missing( a_meth_id, *args )
653
+ meth_name = a_meth_id.id2name
654
+ caller = @mxx_missing_actions[ meth_name ]
655
+ if caller
656
+ r = caller.call( *args )
657
+ else
658
+ super( a_meth_id, *args )
659
+ end
660
+ end
661
+
662
+ # A simple way to get access to the toolset.
663
+ # In a class, inherited from Mxx_ru::Cpp::Target is more convinient
664
+ # to call toolset method, instead of Mxx_ru::Cpp::toolset function.
665
+ # Just calling Mxx_ru::Cpp::toolset function.
666
+ def toolset()
667
+ return Mxx_ru::Cpp::toolset()
668
+ end
669
+
670
+ global_option_methods :runtime_mode, :nogetter
671
+
672
+ # runtime_mode accessor (custom implementation).
673
+ def mxx_runtime_mode
674
+ # If runtime_mode is set to RUNTIME_DEFAULT (i.e.
675
+ # wasn't changed in a projects), then check of command line options
676
+ # is required (--mxx-cpp-release, --mxx-cpp-debug).
677
+ result = @@mxx_runtime_mode.value
678
+ if @@mxx_runtime_mode.default_value == result
679
+ if Mxx_ru::Cpp::Mode.instance.is_release &&
680
+ Mxx_ru::Cpp::Mode.instance.is_debug
681
+ # This is an invalid combination of flags.
682
+ raise Mxx_ru::Invalid_value_ex.new(
683
+ "#{Mxx_ru::Cpp::MXXCPPARG_RELEASE} and " +
684
+ "#{Mxx_ru::Cpp::MXXCPPARG_DEBUG} cannot be used " +
685
+ "together" )
686
+ elsif Mxx_ru::Cpp::Mode.instance.is_release
687
+ result = RUNTIME_RELEASE
688
+ elsif Mxx_ru::Cpp::Mode.instance.is_debug
689
+ result = RUNTIME_DEBUG
690
+ end
691
+ end
692
+
693
+ return result
694
+ end
695
+
696
+ global_option_methods :rtti_mode
697
+ global_option_methods :rtl_mode
698
+ global_option_methods :threading_mode
699
+
700
+ # Set global obj_placement.
701
+ # If gloval obj_placement was already set before, exception is thrown.
702
+ def global_obj_placement( a_placement )
703
+ @@mxx_global_obj_placement.change( a_placement, prj_alias )
704
+ end
705
+
706
+ # Set local obj_placement.
707
+ # It's impossible to simultaneously set global and local obj_placement.
708
+ def obj_placement( a_placement )
709
+ @mxx_obj_placement = a_placement
710
+ end
711
+
712
+ # Get obj_placement object, which should be used.
713
+ #
714
+ # If both global and local obj_placement are set, exception is thrown.
715
+ #
716
+ # If global or local obj_placement is defined, it is returned.
717
+ #
718
+ # If nor global nor local obj_placement is set, local obj_placement is created
719
+ # with a help of Mxx_ru::Cpp::default_obj_placement function and it's returned.
720
+ def mxx_obj_placement
721
+ if nil != @mxx_obj_placement &&
722
+ nil != @@mxx_global_obj_placement.placement
723
+ raise Mxx_ru::Invalid_value_ex.new(
724
+ "Global and local obj_placement object exists! " +
725
+ "Global created by: #{@@mxx_global_obj_placement.who}. " +
726
+ "Local created by: #{prj_alias}" )
727
+ end
728
+
729
+ if nil != @@mxx_global_obj_placement.placement
730
+ return @@mxx_global_obj_placement.placement
731
+ end
732
+
733
+ if nil == @mxx_obj_placement
734
+ @mxx_obj_placement = Mxx_ru::Cpp::default_obj_placement
735
+ end
736
+
737
+ return @mxx_obj_placement
738
+ end
739
+
740
+ # Change path, the names of target results are related to.
741
+ #
742
+ # NOTE: This method should be called BEFORE target method!
743
+ #
744
+ # If target_root is called after target method,
745
+ # then _a_root_ given is added to the name already was set.
746
+ def target_root( a_root )
747
+ @mxx_target_root = a_root
748
+ if @mxx_target_name
749
+ @mxx_target_name = File.join(
750
+ [ @mxx_target_root, @mxx_target_name ] )
751
+ end
752
+ end
753
+
754
+ # Set a name from which target name would be created.
755
+ def target( a_target )
756
+ @mxx_target_name = create_full_target_file_name( a_target )
757
+ end
758
+
759
+ # Change source files path.
760
+ # If empty string is set, then full file names are required.
761
+ # If block is defined, then path is changed only during a block
762
+ # execution, then old path value is restored.
763
+ #
764
+ # Returns previous mxx_sources_root value. Is actual for a case,
765
+ # when method is called without block parameter.
766
+ def sources_root( a_root )
767
+ old_root = @mxx_sources_root.clone
768
+ if block_given?
769
+ @mxx_sources_root = File.join( [ @mxx_sources_root, a_root ] )
770
+ yield
771
+ @mxx_sources_root = old_root
772
+ else
773
+ @mxx_sources_root = a_root
774
+ end
775
+
776
+ return old_root
777
+ end
778
+
779
+ # Set screen mode.
780
+ def screen_mode( a_mode )
781
+ if SCREEN_CONSOLE == a_mode || SCREEN_WINDOW == a_mode
782
+ @mxx_screen_mode = a_mode
783
+ else
784
+ raise Mxx_ru::Unsupported_mode_ex.new(
785
+ "Unsupported screen mode: #{a_mode}" )
786
+ end
787
+ end
788
+
789
+ # Add one C-file to the target.
790
+ #
791
+ # [_a_file_name_] The name of a file added.
792
+ # [_a_options_] Optional list of a compiler options for that file.
793
+ # When command line would be created, this options would
794
+ # be concatenated with others.
795
+ def c_source( a_file_name, a_options = nil )
796
+ @mxx_c_files.push( Cpp_source_file.new(
797
+ create_full_src_file_name( a_file_name ), a_options ) )
798
+ end
799
+
800
+ # Add one C++-file to the target.
801
+ #
802
+ # [_a_file_name_] The name of a file added.
803
+ # [_a_options_] Optional list of a compiler options for that file.
804
+ # When command line would be created, this options would
805
+ # be concatenated with others.
806
+ def cpp_source( a_file_name, a_options = nil )
807
+ @mxx_cpp_files.push( Cpp_source_file.new(
808
+ create_full_src_file_name( a_file_name ), a_options ) )
809
+ end
810
+
811
+ # Set mswin resource file name.
812
+ #
813
+ # [_a_rc_file_] The name of rc-file.
814
+ # [_a_depends_] Optional dependencies list. Should be Array of String.
815
+ def mswin_rc_file(
816
+ a_rc_file,
817
+ a_depends =nil )
818
+
819
+ @mxx_mswin_rc_file = Mswin_rc_file.new( a_rc_file, a_depends )
820
+ end
821
+
822
+ # Set compiled mswin resource file name.
823
+ def mswin_res_file( a_res_file )
824
+ @mxx_mswin_res_file = String.new( a_res_file )
825
+ end
826
+
827
+ # Add object file to the target.
828
+ def obj_file( file_name )
829
+ @mxx_obj_files.push( String.new( file_name ) )
830
+ end
831
+
832
+ # Add the library required.
833
+ # If a_path is other then nil, then it's value is added to the list
834
+ # of a folders, the libraries should be searched in.
835
+ def lib( a_library, a_path = nil )
836
+ mxx_add_required_lib( a_library )
837
+ if a_path
838
+ mxx_add_required_lib_path( a_path )
839
+ end
840
+ end
841
+
842
+ # Set import library location.
843
+ def implib_path( name )
844
+ @mxx_implib_path = name.clone
845
+ end
846
+
847
+ # Set optimization mode required.
848
+ def optimization( a_mode )
849
+ if OPTIM_SIZE != a_mode && OPTIM_SPEED != a_mode
850
+ raise Mxx_ru::Invalid_value_ex.new(
851
+ "Unknown optimization mode: '#{a_mode}'" )
852
+ else
853
+ @mxx_optimization = a_mode.clone
854
+ end
855
+ end
856
+
857
+ # Perform build of the target.
858
+ def build
859
+ if nil == @mxx_last_build_result
860
+
861
+ if !@mxx_all_options_defined
862
+ # It's necessary, that toolset has defined all the options
863
+ # taking all current modes into account.
864
+ Mxx_ru::Cpp::toolset.setup_mandatory_options( self )
865
+ @mxx_all_options_defined = true
866
+ end
867
+
868
+ Mxx_ru::Cpp::Mode.instance.before_subprj_processing
869
+ # The build of subordinated projects performed automatically
870
+ # taking dry-run mode into account.
871
+ required_prjs_state = build_required_projects
872
+ Mxx_ru::Cpp::Mode.instance.after_subprj_processing
873
+
874
+ run_generators
875
+ if !Mxx_ru::Cpp::Mode.instance.is_no_depends_analyzer
876
+ run_depends_analyzer
877
+ end
878
+ objs_state = compile_sources
879
+
880
+ res_state = compile_resources
881
+
882
+ link_state = link_target(
883
+ required_prjs_state,
884
+ objs_state, res_state )
885
+
886
+ # The status of the target is determined by result of target linking.
887
+ @mxx_last_build_result = link_state
888
+ end
889
+
890
+ return @mxx_last_build_result
891
+ end
892
+
893
+ # Perform target's cleanup.
894
+ def clean
895
+ if nil == @mxx_last_build_result
896
+
897
+ if !@mxx_all_options_defined
898
+ # It's necessary, that toolset has defined all the options
899
+ # taking all current modes into account.
900
+ Mxx_ru::Cpp::toolset.setup_mandatory_options( self )
901
+ @mxx_all_options_defined = true
902
+ end
903
+
904
+ Mxx_ru::Cpp::Mode.instance.before_subprj_processing
905
+ # The cleanup of subordinated projects performed automatically
906
+ # taking dry-run mode into account.
907
+ clean_required_prjs
908
+ Mxx_ru::Cpp::Mode.instance.after_subprj_processing
909
+
910
+ clean_generators
911
+ clean_objs
912
+ clean_resources
913
+ clean_target
914
+
915
+ @mxx_last_build_result = Mxx_ru::Target_state.new(
916
+ Mxx_ru::Target_state::ABSENT )
917
+ end
918
+ end
919
+
920
+ # Get the target type.
921
+ # Should be overloaded in child classes.
922
+ # Object, inherited from Mxx_ru::Cpp::Target_type is returned.
923
+ def target_type
924
+ raise Abstract_method_ex.new( "Mxx_ru::Cpp::Target::target_type" )
925
+ end
926
+
927
+ # Creation of a complete name of a resulting file
928
+ # taking the value of mxx_target_root into account
929
+ def create_full_target_file_name( a_file_name )
930
+ if "" == mxx_target_root
931
+ return a_file_name
932
+ else
933
+ return File.join( [ mxx_target_root, a_file_name ] )
934
+ end
935
+ end
936
+
937
+ # Creation of a complete name of a source file
938
+ # taking the value of mxx_sources_root into account
939
+ def create_full_src_file_name( a_file_name )
940
+ if "" == mxx_sources_root
941
+ return a_file_name
942
+ else
943
+ return File.join( [ mxx_sources_root, a_file_name ] )
944
+ end
945
+ end
946
+
947
+ protected
948
+ # Start of all generators of source files.
949
+ def run_generators
950
+ mxx_generators.each { |g| g.build( self ) }
951
+ end
952
+
953
+ # Start of C++ dependencies analyzer.
954
+ def run_depends_analyzer
955
+ analyzer = Analyzer::Cpp_analyzer.instance
956
+
957
+ # We prepare the analyzer to start.
958
+ sources = Array.new
959
+ mxx_c_files.each { |s| sources << s.name }
960
+ mxx_cpp_files.each { |s| sources << s.name }
961
+ analyzer.add_sources( sources )
962
+
963
+ analyzer.add_include_paths( mxx_all_include_paths )
964
+
965
+ # Performing analisys.
966
+ analyzer.analyze
967
+
968
+ # Getting results of analysis.
969
+ mxx_c_files.each { |s|
970
+ depends = analyzer.get_depends_for( s.name )
971
+ s.depends << depends
972
+ s.depends.flatten!
973
+ }
974
+
975
+ mxx_cpp_files.each { |s|
976
+ depends = analyzer.get_depends_for( s.name )
977
+ s.depends << depends
978
+ s.depends.flatten!
979
+ }
980
+ end
981
+
982
+ # Start of source files compiler.
983
+ # Returns Mxx_ru::Target_state.
984
+ def compile_sources
985
+ return Mxx_ru::Cpp::toolset().make_objs( self )
986
+ end
987
+
988
+ # Start of resource files compiler.
989
+ # Returns nothing.
990
+ def compile_resources
991
+ # We proceed from the assumption, that on one platform
992
+ # some different types of resource files simultaneously can not be used.
993
+ if @mxx_mswin_rc_file
994
+ return Mxx_ru::Cpp::toolset().make_mswin_res( self )
995
+ end
996
+
997
+ return Mxx_ru::Target_state.new( Target_state::EXISTS )
998
+ end
999
+
1000
+ # Start of target linking.
1001
+ #
1002
+ # [_required_prjs_state_] Build results of all subprojects required.
1003
+ # Object of Mxx_ru::Target_state type.
1004
+ # [_objs_state_] Compilation results of all object files
1005
+ # Object of Mxx_ru::Target_state type.
1006
+ # [_res_state_] Compilation results of all resource files.
1007
+ # Object of Mxx_ru::Target_state type.
1008
+ def link_target(
1009
+ required_prjs_state,
1010
+ objs_state,
1011
+ res_state )
1012
+
1013
+ state = nil
1014
+ toolset = Mxx_ru::Cpp::toolset
1015
+ if nil == target_type
1016
+ raise Mxx_ru::Unsupported_target_type_ex.new(
1017
+ self.class.name, "nil" )
1018
+ elsif target_type.name == Lib_target_type::TYPE
1019
+ state = toolset.make_lib( self )
1020
+ elsif target_type.name == Dll_target_type::TYPE
1021
+ state = toolset.make_dll( self )
1022
+ elsif target_type.name == Exe_target_type::TYPE
1023
+ state = toolset.make_exe( self )
1024
+ else
1025
+ raise Mxx_ru::Unsupported_target_type_ex.new(
1026
+ self.class.name, target_type.name )
1027
+ end
1028
+
1029
+ return state
1030
+ end
1031
+
1032
+ def clean_generators
1033
+ mxx_generators.each { |g| g.clean( self ) }
1034
+ end
1035
+
1036
+ def clean_objs
1037
+ Mxx_ru::Cpp::toolset().clean_objs( self )
1038
+ end
1039
+
1040
+ def clean_resources
1041
+ if @mxx_mswin_rc_file
1042
+ Mxx_ru::Cpp::toolset().clean_mswin_res( self )
1043
+ end
1044
+ end
1045
+
1046
+ def clean_target
1047
+ toolset = Mxx_ru::Cpp::toolset
1048
+ if nil == target_type
1049
+ raise Mxx_ru::Unsupported_target_type_ex.new(
1050
+ self.class.name, "nil" )
1051
+ elsif target_type.name == Lib_target_type::TYPE
1052
+ state = toolset.clean_lib( self )
1053
+ elsif target_type.name == Dll_target_type::TYPE
1054
+ state = toolset.clean_dll( self )
1055
+ elsif target_type.name == Exe_target_type::TYPE
1056
+ state = toolset.clean_exe( self )
1057
+ else
1058
+ raise Mxx_ru::Unsupported_target_type_ex.new(
1059
+ self.class.name, target_type.name )
1060
+ end
1061
+ end
1062
+
1063
+ # Create the necessary description of an option,
1064
+ # which can have global, local and upspreadable value.
1065
+ #
1066
+ # [_a_option_desc_] The main component of a name of absent methods.
1067
+ def add_spreadable_option(
1068
+ a_option_desc )
1069
+
1070
+ globals = @@mxx_globals[ a_option_desc ]
1071
+ if nil == globals
1072
+ @@mxx_globals[ a_option_desc ] = globals = Array.new
1073
+ end
1074
+
1075
+ locals = Spreadable_option.new( a_option_desc )
1076
+ @mxx_locals[ a_option_desc ] = locals
1077
+
1078
+ meth_global = "global_#{a_option_desc}"
1079
+ meth_local = a_option_desc
1080
+ meth_all = "mxx_all_#{a_option_desc}s"
1081
+ meth_upspreads = "mxx_upspread_#{a_option_desc}s"
1082
+
1083
+ @mxx_missing_actions[ meth_global ] =
1084
+ Global_option_inserter.new( a_option_desc, globals )
1085
+ @mxx_missing_actions[ meth_local ] =
1086
+ Spreadable_option_inserter.new( locals )
1087
+ @mxx_missing_actions[ meth_all ] =
1088
+ Spreadable_option_all_extractor.new( locals,
1089
+ globals, self, meth_upspreads )
1090
+ @mxx_missing_actions[ meth_upspreads ] =
1091
+ Spreadable_option_upspread_extractor.new(
1092
+ locals, self, meth_upspreads )
1093
+ end
1094
+
1095
+ def add_unique_to( what, to )
1096
+ if !to.include?( what )
1097
+ to.push( what )
1098
+ end
1099
+ end
1100
+
1101
+ end # class Target
1102
+
1103
+ # Base class for targets that may be lib or dll.
1104
+ #
1105
+ # In that cases for a project should be defined special target class.
1106
+ # The class constructor should define two blocks:
1107
+ # * one of them is called if developer wants to build target
1108
+ # as a static library. Block is run during as_lib method call;
1109
+ # * second is called if developer wants to build target
1110
+ # as a shared library. Block is run during as_dll method call;
1111
+ #
1112
+ # For example:
1113
+ #
1114
+ # class Prj < Mxx_ru::Cpp::Lib_or_dll_target
1115
+ # TAG = "threads_1/prj.rb"
1116
+ # def initialize( a_alias = TAG )
1117
+ # super( a_alias, TAG )
1118
+ #
1119
+ # target( "threads.1.3" )
1120
+ #
1121
+ # threading_mode( Mxx_ru::Cpp::THREADING_MULTI )
1122
+ #
1123
+ # init_dll_block(
1124
+ # Proc.new {
1125
+ # rtl_mode( Mxx_ru::Cpp::RTL_SHARED )
1126
+ # implib_path( "lib" )
1127
+ # define( "THREADS_1__DLL", OPT_UPSPREAD )
1128
+ # })
1129
+ #
1130
+ # cpp_source( "threads.cpp" )
1131
+ # cpp_source( "micro_time.cpp" )
1132
+ #
1133
+ # if toolset.tag( "target_os" ) == "mswin"
1134
+ # define( "__WIN32__" )
1135
+ # cpp_source( "win32/os_thread.cpp" )
1136
+ # elsif toolset.tag( "target_os" ) == "unix"
1137
+ # cpp_source( "posix/os_thread.cpp" )
1138
+ # end
1139
+ #
1140
+ # define( "THREADS_1__PRJ" )
1141
+ # end
1142
+ # end
1143
+ #
1144
+ # After definition of such class for the target, project may allow
1145
+ # to use itself by the other projects using two methods.
1146
+ #
1147
+ # == Manual execution of as_lib, as_dll methods
1148
+ #
1149
+ # If project defines one class only, inherited from Lib_or_dll_target,
1150
+ # then all clients of that project should explicitly call as_lib or as_dll
1151
+ # method during a reference to required_prj:
1152
+ #
1153
+ # class My_prj < Mxx_ru::Cpp::Exe_target
1154
+ # def initialize( a_alias = "my_prj.rb" )
1155
+ # super( a_alias )
1156
+ # required_prj( "threads_1/prj.rb" ).as_dll( self )
1157
+ # end
1158
+ # end
1159
+ #
1160
+ # Such approach is not good because if in composite project several
1161
+ # projects at the same time uses threads_1/prj.rb, then in one of them
1162
+ # it's easy to forget to call as_dll. And it wouldn't be incorrect,
1163
+ # because as_dll may be called by other projects in composite project.
1164
+ #
1165
+ # == Definition of auxiliary target classes
1166
+ #
1167
+ # To make usage of target that may be lib or dll easier, project may
1168
+ # define two auxiliary classes, which would call methods as_lib and as_dll
1169
+ # inside their constructors:
1170
+ #
1171
+ # class Prj < Mxx_ru::Cpp::Lib_or_dll_target
1172
+ # def initialize( a_alias = "threads_1/prj.rb" )
1173
+ # super( a_alias, "threads_1" )
1174
+ # ...
1175
+ # end
1176
+ # end
1177
+ # class Lib < Prj
1178
+ # def super( a_alias = "threads_1/lib.rb" )
1179
+ # super( a_alias )
1180
+ # as_lib
1181
+ # end
1182
+ # end
1183
+ # class Dll < Prj
1184
+ # def super( a_alias = "threads_1/dll.rb" )
1185
+ # super( a_alias )
1186
+ # as_dll
1187
+ # end
1188
+ # end
1189
+ #
1190
+ # Then for using the target it would be enough to do that:
1191
+ # class My_prj < Mxx_ru::Cpp::Exe_target
1192
+ # def initialize( a_alias = "my_prj.rb" )
1193
+ # super( a_alias )
1194
+ # required_prj( "threads_1/dll.rb" )
1195
+ # end
1196
+ # end
1197
+ #
1198
+ class Lib_or_dll_target < Target
1199
+ # Exception type, which is thrown if target type is undefined.
1200
+ class Type_not_defined_ex < Mxx_ru::Ex
1201
+ # [_a_prj_alias_] Project alias, for which target type should be defined.
1202
+ def initialize( a_prj_alias )
1203
+ super( "#{a_prj_alias}: type of target not defined yet" )
1204
+ end
1205
+ end
1206
+
1207
+ # Exception type, which is thrown if target type was already defined.
1208
+ class Type_already_defined_ex < Mxx_ru::Ex
1209
+ # [_a_prj_tag_] Target identifier, for which type is established.
1210
+ # [_a_type_] Already defined target type.
1211
+ def initialize( a_prj_alias, a_type )
1212
+ super( "#{a_prj_alias}: type of target already defined " +
1213
+ "as #{a_type}" )
1214
+ end
1215
+ end
1216
+
1217
+ # Map describing unique target identifiers and their types.
1218
+ # Used to avoid conflicts, when the same target is inside composite project
1219
+ # as both lib and dll.
1220
+ @@mxx_tags = Hash.new
1221
+
1222
+ # Constructor.
1223
+ #
1224
+ # [_a_prj_alias_] Project alias.
1225
+ # [_a_prj_tag_] Unique value, which identifies target given.
1226
+ # This value used to avoid conflicts in the next situations:
1227
+ # class Prj < Mxx_ru::Cpp::Lib_or_dll_target ... end
1228
+ # class Lib < Prj ... end
1229
+ # class Dll < Prj ... end
1230
+ # class My_exe < Mxx_ru::Cpp::Exe_target
1231
+ # def initialize( a_alias = "my_exe.rb" )
1232
+ # super( a_alias )
1233
+ # required_prj( "threads_1/dll.rb" )
1234
+ # end
1235
+ # end
1236
+ # class My_dll < Mxx_ru::Cpp::Dll_target
1237
+ # def initialize( a_alias = "my_dll.rb" )
1238
+ # super( a_alias )
1239
+ # required_prj( "threads_1/lib.rb" )
1240
+ # end
1241
+ # end
1242
+ # If both My_exe and My_dll are used in one composite project,
1243
+ # then it's a conflict of usage of threads_1/dll.rb and threads_1/lib.rb.
1244
+ def initialize( a_prj_alias, a_prj_tag )
1245
+ super( a_prj_alias )
1246
+
1247
+ @mxx_prj_tag = a_prj_tag
1248
+
1249
+ # Block, which is run if lib is a target.
1250
+ @mxx_init_lib_block = nil
1251
+ # Block, which is run if dll is a target.
1252
+ @mxx_init_dll_block = nil
1253
+ # Target type should be defined or by as_lib method, or by as_dll method.
1254
+ @mxx_target_type = nil
1255
+
1256
+ end
1257
+
1258
+ # Set lib as target type.
1259
+ def as_lib
1260
+ if ensure_type_not_set_yet( Lib_target_type::TYPE )
1261
+ @mxx_target_type = Lib_target_type.new
1262
+ if nil != @mxx_init_lib_block
1263
+ @mxx_init_lib_block.call
1264
+ end
1265
+ end
1266
+ end
1267
+
1268
+ # Set dll as target type.
1269
+ def as_dll
1270
+ if ensure_type_not_set_yet( Dll_target_type::TYPE )
1271
+ @mxx_target_type = Dll_target_type.new
1272
+ if nil != @mxx_init_dll_block
1273
+ @mxx_init_dll_block.call
1274
+ end
1275
+ end
1276
+ end
1277
+
1278
+ # Return current value of mxx_target_type.
1279
+ def target_type
1280
+ if nil == @mxx_target_type
1281
+ raise Type_not_defined_ex.new( prj_alias )
1282
+ end
1283
+
1284
+ return @mxx_target_type
1285
+ end
1286
+
1287
+ protected
1288
+ # Set initialization block for lib.
1289
+ # This block will be executed in as_lib method.
1290
+ def init_lib_block( a_block )
1291
+ @mxx_init_lib_block = a_block
1292
+ end
1293
+
1294
+ # Set initialization block for dll.
1295
+ # This block will be executed in as_dll method.
1296
+ def init_dll_block( a_block )
1297
+ @mxx_init_dll_block = a_block
1298
+ end
1299
+
1300
+ private
1301
+ # If someone already defined other target type, exception is thrown.
1302
+ # If already defined target type is the same, false returned.
1303
+ # If target type is not defined, true is returned.
1304
+ #
1305
+ # [_a_type_name_] Name of target type defined.
1306
+ def ensure_type_not_set_yet( a_type_name )
1307
+ if @@mxx_tags.key?( @mxx_prj_tag ) &&
1308
+ @@mxx_tags[ @mxx_prj_tag ] != a_type_name
1309
+ raise Type_already_defined_ex.new(
1310
+ @mxx_prj_tag, a_type_name )
1311
+ end
1312
+
1313
+ @@mxx_tags[ @mxx_prj_tag ] = a_type_name
1314
+
1315
+ return ( nil == @mxx_target_type )
1316
+ end
1317
+ end # class Lib_or_dll_target
1318
+
1319
+ # Lib is a target type.
1320
+ class Lib_target < Lib_or_dll_target
1321
+ def initialize( a_prj_alias, &block )
1322
+ super( a_prj_alias, a_prj_alias )
1323
+
1324
+ as_lib
1325
+
1326
+ instance_eval( &block ) if block
1327
+ end
1328
+ end
1329
+
1330
+ # Dll is a target type.
1331
+ class Dll_target < Lib_or_dll_target
1332
+ def initialize( a_prj_alias, &block )
1333
+ super( a_prj_alias, a_prj_alias )
1334
+
1335
+ as_dll
1336
+
1337
+ instance_eval( &block ) if block
1338
+ end
1339
+ end
1340
+
1341
+ # Exe is a target type.
1342
+ class Exe_target < Target
1343
+
1344
+ def initialize( a_alias, &block )
1345
+ super( a_alias )
1346
+
1347
+ instance_eval( &block ) if block
1348
+ end
1349
+
1350
+ def target_type
1351
+ return Exe_target_type.new
1352
+ end
1353
+ end
1354
+
1355
+ # Generator for generating method for simple way of describing targets.
1356
+ def Cpp.generate_simple_target_method( target_type )
1357
+ target_class_name = target_type.to_s.capitalize
1358
+ class_eval %Q{
1359
+ def Cpp.#{target_type}( prj_alias, &block )
1360
+ Mxx_ru::setup_target #{target_class_name}.new( prj_alias, &block )
1361
+ end
1362
+ }
1363
+ end
1364
+
1365
+ generate_simple_target_method :lib_target
1366
+ generate_simple_target_method :dll_target
1367
+ generate_simple_target_method :exe_target
1368
+
1369
+ end # module Cpp
1370
+ end # module Mxx_ru
1371
+