Mxx_ru 1.1.0

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.
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
+