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,1029 @@
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/ex'
30
+ require 'mxx_ru/util'
31
+
32
+ module Mxx_ru
33
+ module Cpp
34
+
35
+ # Class, describing object file.
36
+ class Obj_info
37
+ # The name of object file.
38
+ attr_reader :name
39
+ # The name of source file.
40
+ attr_reader :source
41
+ # The list of additional compiler options for that file.
42
+ # Array of String.
43
+ attr_reader :options
44
+
45
+ def initialize( a_name, a_source, a_options )
46
+ @name = a_name
47
+ @source = a_source
48
+ @options = a_options
49
+ end
50
+ end # class Obj_info
51
+
52
+ # Base class for any target for which full path must be calculated.
53
+ class Target_with_full_path
54
+ def initialize( name, path )
55
+ @target_path = path
56
+ @target_name = name
57
+ end
58
+
59
+ def full_name
60
+ @full_name = File.join( @target_path, @target_name ) unless @full_name
61
+ @full_name
62
+ end
63
+ end
64
+
65
+ # Class, describing mswin-res-����.
66
+ class Mswin_res_info < Target_with_full_path
67
+ attr_reader :file_name
68
+ attr_reader :path
69
+
70
+ def initialize( a_file_name, a_path )
71
+ super( a_file_name, a_path )
72
+
73
+ # File name of mswin-res-file without a folder.
74
+ @file_name = a_file_name
75
+ # Folder where mswin-res-file should be.
76
+ @path = a_path
77
+ end
78
+ end # class Mswin_res_info
79
+
80
+ # Class, describing a library.
81
+ class Lib_info < Target_with_full_path
82
+ attr_reader :file_name
83
+ attr_reader :path
84
+ attr_reader :link_name
85
+
86
+ def initialize( a_file_name, a_path, a_link_name )
87
+ super( a_file_name, a_path )
88
+
89
+ # File name of library file without a folder.
90
+ @file_name = a_file_name
91
+ # Folder where library file should be.
92
+ @path = a_path
93
+ # The name should be passed to the linker.
94
+ @link_name = a_link_name
95
+ end
96
+ end # class Lib_info
97
+
98
+ # Class, describing EXE-file.
99
+ class Exe_info < Target_with_full_path
100
+ attr_reader :file_name
101
+ attr_reader :path
102
+
103
+ def initialize( a_file_name, a_path )
104
+ super( a_file_name, a_path )
105
+
106
+ # File name of exe file without a folder.
107
+ @file_name = a_file_name
108
+ # Folder where exe file should be.
109
+ @path = a_path
110
+ end
111
+ end # class Exe_info
112
+
113
+ # Class, describing a shared library.
114
+ class Dll_info < Target_with_full_path
115
+ # File name of dll file without a folder.
116
+ attr_reader :dll_file_name
117
+ # Folder where dll file should be.
118
+ attr_reader :dll_path
119
+ # The name should be passed to the linker. (import library name)
120
+ # It may be nil if inport library isn't used.
121
+ attr_reader :link_name
122
+ # The folder name, where linker should look for import library.
123
+ # It may be nil if inport library isn't used.
124
+ attr_reader :link_path
125
+
126
+ def initialize(
127
+ a_dll_file_name,
128
+ a_dll_path,
129
+ a_link_name,
130
+ a_link_path )
131
+
132
+ super( a_dll_file_name, a_dll_path )
133
+
134
+ @dll_file_name = a_dll_file_name
135
+ @dll_path = a_dll_path
136
+ @link_name = a_link_name
137
+ @link_path = a_link_path
138
+ end
139
+ end # class Dll_info
140
+
141
+
142
+ # Class, incapsulating all lists required for linker.
143
+ class Linker_lists
144
+ # Object files.
145
+ attr_reader :objs
146
+ # Compiled resources.
147
+ attr_reader :resources
148
+ # Libraries required.
149
+ attr_reader :libs
150
+ # Search paths for libraries.
151
+ attr_reader :lib_paths
152
+ # Linker options.
153
+ attr_reader :linker_options
154
+
155
+ def initialize
156
+ @objs = Array.new
157
+ @resources = Array.new
158
+ @libs = Array.new
159
+ @lib_paths = Array.new
160
+ @linker_options = Array.new
161
+ end
162
+
163
+ def add_objs( a_objs )
164
+ push_to( @objs, a_objs )
165
+ end
166
+
167
+ def add_resources( a_resources )
168
+ push_to( @resources, a_resources )
169
+ end
170
+
171
+ def add_libs( a_libs )
172
+ push_to( @libs, a_libs )
173
+ end
174
+
175
+ def add_lib_paths( a_lib_paths )
176
+ push_to( @lib_paths, a_lib_paths )
177
+ end
178
+
179
+ def add_linker_options( a_linker_options )
180
+ push_to( @linker_options, a_linker_options )
181
+ end
182
+
183
+ protected
184
+ def push_to( to, what )
185
+ to << what
186
+ to.flatten!
187
+ to.uniq!
188
+ end
189
+ end # class Linker_lists
190
+
191
+ # Class, incapsulating DLL dependencies.
192
+ #
193
+ # When someone is linking to the DLL on mswin platform, then it
194
+ # depends only from import library of that DLL.
195
+ # But when someone is linking to the DLL on unix platform, then it
196
+ # depends from all libraries DLL depends to.
197
+ # Exact details knows concrete toolset implementation only.
198
+ # Therefore, after DLL building base toolset class addresses to it's
199
+ # derivative with requirement to build all dependencies lists.
200
+ # These lists are returned as an object of Dll_requirements type.
201
+ class Dll_requirements
202
+ # Required libraries list.
203
+ attr_reader :libs
204
+ # Libraries search paths.
205
+ attr_reader :lib_paths
206
+
207
+ def initialize
208
+ @libs = Array.new
209
+ @lib_paths = Array.new
210
+ end
211
+
212
+ def add_libs( a_libs )
213
+ push_to( @libs, a_libs )
214
+ end
215
+
216
+ def add_lib_paths( a_lib_paths )
217
+ push_to( @lib_paths, a_lib_paths )
218
+ end
219
+
220
+ protected
221
+ def push_to( to, what )
222
+ to << what
223
+ to.flatten!
224
+ end # Dll_requirements
225
+ end
226
+
227
+ # Base toolset class.
228
+ # Toolset is a compiler and tool set for compiling an application.
229
+ class Toolset
230
+
231
+ # Exception, thrown in case of unknown toolset tag value.
232
+ class Unknown_tag_ex < Mxx_ru::Ex
233
+ def initialize( a_tag_name )
234
+ super( "Unknown or missing toolset tag: '#{a_tag_name}" )
235
+ end
236
+ end
237
+
238
+ private
239
+ # Toolset name.
240
+ @name = nil
241
+ # Tag map. Key and value are the String objects.
242
+ @tags = nil
243
+
244
+ public
245
+ # Constructor.
246
+ #
247
+ # [_a_name_] Toolset name.
248
+ def initialize( a_name )
249
+ @name = a_name
250
+ @tags = Hash.new
251
+ end
252
+
253
+ # Set tag value.
254
+ # Previous value is changed to the new one.
255
+ #
256
+ # [_a_name_] Tag name.
257
+ # [_a_value_] Value. Should be a string.
258
+ def setup_tag( a_name, a_value )
259
+ @tags[ a_name ] = a_value
260
+ end
261
+
262
+ # Get tag value.
263
+ # If tag wasn't found in a tag map, a_default value is returned.
264
+ # If a_default == nil, then exception is thrown in a case of missing tag.
265
+ def tag( a_name, a_default = nil )
266
+ if !@tags.key?( a_name )
267
+ if nil == a_default
268
+ raise Unknown_tag_ex.new( a_name )
269
+ end
270
+
271
+ return a_default
272
+ end
273
+ return @tags[ a_name ]
274
+ end
275
+
276
+ # Set all compiler, linker, archiver, etc options required,
277
+ # taking all current modes, such as runtime_mode, rtl_mode,
278
+ # rtti_mode, threading_mode etc into account.
279
+ # Target parameter should be an object of a class, inherited from
280
+ # Mxx_ru::Cpp::Target.
281
+ #
282
+ # Throws Abstract_method_ex exception in a base class.
283
+ #
284
+ def setup_mandatory_options( target )
285
+ raise Abstract_method_ex.new( "Mxx_ru::Cpp::Toolset::setup_mandatory_options" )
286
+ end
287
+
288
+ # Perform C++ files compilation.
289
+ # Target parameter should be an object of a class, inherited from
290
+ # Mxx_ru::Cpp::Target.
291
+ def make_objs( target )
292
+ # Creating all object file names.
293
+ c_objs = make_obj_names( target.mxx_c_files, target )
294
+ cpp_objs = make_obj_names( target.mxx_cpp_files, target )
295
+
296
+ # Defining object files, which is necessary to build or rebuild.
297
+ c_objs_to_build = detect_objs_to_rebuild( c_objs )
298
+ cpp_objs_to_build = detect_objs_to_rebuild( cpp_objs )
299
+
300
+ # Performing a compilation, if it's required.
301
+ if c_objs_to_build.size
302
+ build_objs( c_objs_to_build, target,
303
+ target.mxx_all_c_compiler_options,
304
+ :make_c_obj_command_lines )
305
+ end
306
+ if cpp_objs_to_build.size
307
+ build_objs( cpp_objs_to_build, target,
308
+ target.mxx_all_cpp_compiler_options,
309
+ :make_cpp_obj_command_lines )
310
+ end
311
+
312
+ # It's required to store all object file names back to the target,
313
+ # because they are required for linking.
314
+ c_objs.each { |o| target.obj_file( o.name ) }
315
+ cpp_objs.each { |o| target.obj_file( o.name ) }
316
+
317
+ # Also informing if some object files were rebuilt.
318
+ state = Target_state::EXISTS
319
+ state = Target_state::REBUILT if ( c_objs_to_build.size() ||
320
+ cpp_objs_to_build.size() )
321
+
322
+ return Target_state.new( state )
323
+ end
324
+
325
+ # Remove object files.
326
+ def clean_objs( target )
327
+ # Creating all object file names.
328
+ c_objs = make_obj_names( target.mxx_c_files, target )
329
+ cpp_objs = make_obj_names( target.mxx_cpp_files, target )
330
+
331
+ c_objs.each { |o| Mxx_ru::Util::delete_file( o.name ) }
332
+ cpp_objs.each { |o| Mxx_ru::Util::delete_file( o.name ) }
333
+ end
334
+
335
+ # Perform resource files compilation.
336
+ # Target parameter should be an object of a class, inherited from
337
+ # Mxx_ru::Cpp::Target.
338
+ def make_mswin_res( target )
339
+ # Creating the name of res file and storing it in the target.
340
+ res_info = make_mswin_res_name(
341
+ target.mxx_mswin_rc_file.name, target )
342
+
343
+ full_name = res_info.full_name
344
+
345
+ target.mswin_res_file( full_name )
346
+
347
+ # Determining it's status.
348
+ state = Target_state::detect( full_name,
349
+ [ target.mxx_mswin_rc_file.name ] +
350
+ target.mxx_mswin_rc_file.depends )
351
+ if state.state != Target_state::EXISTS
352
+ cmd_lines = make_mswin_res_command_lines(
353
+ full_name, target.mxx_mswin_rc_file.name,
354
+ target.mxx_all_mswin_rc_options, target )
355
+
356
+ Mxx_ru::Abstract_target::run( cmd_lines, [ full_name ] )
357
+
358
+ state = Mxx_ru::Target_state.new( Mxx_ru::Target_state::REBUILT )
359
+ end
360
+
361
+ return state
362
+ end
363
+
364
+ # Remove resource files compilation results.
365
+ def clean_mswin_res( target )
366
+ # Creating the name of res file.
367
+ res_info = make_mswin_res_name(
368
+ target.mxx_mswin_rc_file.name, target )
369
+
370
+ full_name = res_info.full_name
371
+
372
+ Mxx_ru::Util::delete_file( full_name )
373
+
374
+ clean_mswin_res_specific_files( full_name, res_info, target )
375
+ end
376
+
377
+ # Perform cleanup of files specific for mswin-res.
378
+ # Does nothing in a base class.
379
+ #
380
+ # [_a_res_file_] Full name of mswin-res-file.
381
+ # [_a_res_info_] Formatted information for res-file.
382
+ # [_a_target_] Target, for which mswin-res-file is defined.
383
+ def clean_mswin_res_specific_files(
384
+ a_res_file,
385
+ a_res_info,
386
+ a_target )
387
+ end
388
+
389
+ # Perform static library build.
390
+ # Target parameter should be an object of a class, inherited from
391
+ # Mxx_ru::Cpp::Target.
392
+ def make_lib( target )
393
+ # Creating result file name. Also determining in which folder
394
+ # lib should be. The name of that folder should be included in
395
+ # libraries search paths of given target.
396
+ lib_info = make_lib_name( target.mxx_target_name, target )
397
+
398
+ # Determining target status.
399
+ lib_file = lib_info.full_name
400
+
401
+ lib_state = Mxx_ru::Target_state::detect(
402
+ lib_file, target.mxx_obj_files )
403
+ if Mxx_ru::Target_state::EXISTS != lib_state.state
404
+ # File should be rebuilt.
405
+ cmd_lines = make_lib_command_lines(
406
+ lib_file, target.mxx_obj_files,
407
+ target.mxx_all_librarian_options, target )
408
+
409
+ Mxx_ru::Abstract_target::run( cmd_lines, [ lib_file ] )
410
+
411
+ lib_state = Mxx_ru::Target_state.new( Mxx_ru::Target_state::REBUILT )
412
+ end
413
+
414
+ # Full library file name should be included in files list, created by
415
+ # given target.
416
+ target.mxx_add_full_target_name( lib_file )
417
+
418
+ # For a library, in a dependency list the library itself may be included.
419
+ target.mxx_add_required_lib( lib_info.link_name )
420
+ target.mxx_add_required_lib_path( lib_info.path )
421
+
422
+ # And all libraries and folders from all subordinated projects.
423
+ target.mxx_required_prjs.each { |d|
424
+ if d.kind_of?( Mxx_ru::Binary_target )
425
+ d.mxx_required_libs.each { |l|
426
+ target.mxx_add_required_lib( l )
427
+ }
428
+ d.mxx_required_lib_paths.each { |p|
429
+ target.mxx_add_required_lib_path( p )
430
+ }
431
+ end
432
+ }
433
+
434
+ return lib_state
435
+ end
436
+
437
+ # Perform cleanup of static library.
438
+ # Target parameter should be an object of a class, inherited from
439
+ # Mxx_ru::Cpp::Target.
440
+ def clean_lib( target )
441
+ # Creating result file name. Also determining in which folder
442
+ # lib should be.
443
+ lib_info = make_lib_name( target.mxx_target_name, target )
444
+
445
+ lib_file = lib_info.full_name
446
+
447
+ Mxx_ru::Util::delete_file( lib_file )
448
+
449
+ clean_lib_specific_files( lib_file, lib_info, target )
450
+ end
451
+
452
+ # Perform a cleanup of auxiliary files, specific for static library
453
+ # on given platform. Does nothing in a base class, but may be redefined
454
+ # by a child class.
455
+ #
456
+ # [_a_lib_file_] Full name of library file.
457
+ # [_a_lib_info_] Lib_info, created for the file.
458
+ # [_a_target_] Target, library is created for.
459
+ def clean_lib_specific_files(
460
+ a_lib_file,
461
+ a_lib_info,
462
+ a_target )
463
+ end
464
+
465
+ # Perform dynamic library build.
466
+ # Target parameter should be an object of a class, inherited from
467
+ # Mxx_ru::Cpp::Target.
468
+ def make_dll( target )
469
+ # Creating result file name.
470
+ dll_info = make_dll_name( target.mxx_target_name, target )
471
+
472
+ # Creating dependencies list.
473
+ all_depend_files = create_executable_depend_list( target )
474
+
475
+ # This values will be required later during a calculation of
476
+ # dependencies of that DLL.
477
+ link_lists = prepare_linker_lists( target )
478
+
479
+ dll_file = dll_info.full_name
480
+
481
+ dll_state = Mxx_ru::Target_state::detect(
482
+ dll_file, all_depend_files )
483
+ if Mxx_ru::Target_state::EXISTS != dll_state.state
484
+ # Target should be rebuilt.
485
+
486
+ cmd_lines = make_dll_command_lines(
487
+ dll_file, dll_info, link_lists, target )
488
+
489
+ Mxx_ru::Abstract_target::run( cmd_lines, [ dll_file ] )
490
+
491
+ dll_state = Mxx_ru::Target_state.new( Mxx_ru::Target_state::REBUILT )
492
+ end
493
+
494
+ # Full library file name should be included in files list, created by
495
+ # given target.
496
+ target.mxx_add_full_target_name( dll_file )
497
+
498
+ # Determining dependencies list for all who will link this DLL.
499
+ dll_requirements = make_dll_requirements(
500
+ dll_file, dll_info, link_lists, target )
501
+
502
+ dll_requirements.libs.each { |l|
503
+ target.mxx_add_required_lib( l ) }
504
+ dll_requirements.lib_paths.each { |p|
505
+ target.mxx_add_required_lib_path( p ) }
506
+
507
+ return dll_state
508
+ end
509
+
510
+ # Perform dynamic library cleanup.
511
+ # Target parameter should be an object of a class, inherited from
512
+ # Mxx_ru::Cpp::Target.
513
+ def clean_dll( target )
514
+ # Creating result file name.
515
+ dll_info = make_dll_name( target.mxx_target_name, target )
516
+
517
+ dll_file = dll_info.full_name
518
+
519
+ Mxx_ru::Util::delete_file( dll_file )
520
+
521
+ clean_dll_specific_files( dll_file, dll_info, target )
522
+ end
523
+
524
+ # Perform a cleanup of auxiliary files, specific for static library
525
+ # on given platform. Does nothing in a base class, but may be redefined
526
+ # by a child class if import library may be created on given platform.
527
+ #
528
+ # [_a_dll_file_] Full library file name.
529
+ # [_a_dll_info_] Dll_info, created for the file.
530
+ # [_a_target_] Target, the library is created for.
531
+ def clean_dll_specific_files(
532
+ a_dll_file,
533
+ a_dll_info,
534
+ a_target )
535
+ end
536
+
537
+ # Perform executable file build.
538
+ # Target parameter should be an object of a class, inherited from
539
+ # Mxx_ru::Cpp::Target.
540
+ def make_exe( target )
541
+ # Creating result file name.
542
+ exe_info = make_exe_name( target.mxx_target_name, target )
543
+
544
+ # Creating dependencies list.
545
+ all_depend_files = create_executable_depend_list( target )
546
+
547
+ exe_file = exe_info.full_name
548
+
549
+ exe_state = Mxx_ru::Target_state::detect(
550
+ exe_file, all_depend_files )
551
+ if Mxx_ru::Target_state::EXISTS != exe_state.state
552
+ # Target should be rebuilt.
553
+
554
+ link_lists = prepare_linker_lists( target )
555
+ cmd_lines = make_exe_command_lines(
556
+ exe_file, exe_info, link_lists, target )
557
+
558
+ Mxx_ru::Abstract_target::run( cmd_lines, [ exe_file ] )
559
+
560
+ exe_state = Mxx_ru::Target_state.new( Mxx_ru::Target_state::REBUILT )
561
+ end
562
+
563
+ # Full library file name should be included in files list, created by
564
+ # given target.
565
+ target.mxx_add_full_target_name( exe_file )
566
+
567
+ return exe_state
568
+ end
569
+
570
+ # Perform executable file cleanup.
571
+ # Target parameter should be an object of a class, inherited from
572
+ # Mxx_ru::Cpp::Target.
573
+ def clean_exe( target )
574
+ # Creating result file name.
575
+ exe_info = make_exe_name( target.mxx_target_name, target )
576
+
577
+ exe_file = exe_info.full_name
578
+
579
+ Mxx_ru::Util::delete_file( exe_file )
580
+
581
+ clean_exe_specific_files( exe_file, exe_info, target )
582
+ end
583
+
584
+ # Perform a cleanup of auxiliary files, specific for static library
585
+ # on given platform. Does nothing in a base class, but may be redefined
586
+ # by a child class.
587
+ #
588
+ # [_a_exe_file_] Full file name.
589
+ # [_a_exe_info_] Exe_info, created for the file.
590
+ # [_a_target_] Target, the file is created for.
591
+ def clean_exe_specific_files(
592
+ a_exe_file,
593
+ a_exe_info,
594
+ a_target )
595
+ end
596
+
597
+ # Get file extension for an object file.
598
+ # Should be redefined in a child class.
599
+ #
600
+ # Abstract_method_ex exception is thrown in a base class.
601
+ #
602
+ def obj_file_ext()
603
+ raise Abstract_method_ex.new( "Mxx_ru::Cpp::Toolset::obj_file_ext" )
604
+ end
605
+
606
+ # Create command line for C file compilation.
607
+ # Returns Array of String with command lines.
608
+ # Should be redefined in a child class.
609
+ #
610
+ # Abstract_method_ex exception is thrown in a base class.
611
+ #
612
+ # [_obj_name_] Object file name.
613
+ # [_source_name_] Source file name.
614
+ # [_compiler_options_] Compiler options list. Array of String.
615
+ # [_target_] Target, which contains object file given.
616
+ def make_c_obj_command_lines(
617
+ obj_name,
618
+ source_name,
619
+ compiler_options,
620
+ target )
621
+
622
+ raise Abstract_method_ex.new(
623
+ "Mxx_ru::Cpp::Toolset::make_c_obj_command_lines" )
624
+ end
625
+
626
+ # Create command line for C++ file compilation.
627
+ # Returns Array of String with command lines.
628
+ # Should be redefined in a child class.
629
+ #
630
+ # Abstract_method_ex exception is thrown in a base class.
631
+ #
632
+ # [_obj_name_] Object file name.
633
+ # [_source_name_] Source file name.
634
+ # [_compiler_options_] Compiler options list. Array of String.
635
+ # [_target_] Target, which contains object file given.
636
+ def make_cpp_obj_command_lines(
637
+ obj_name,
638
+ source_name,
639
+ compiler_options,
640
+ target )
641
+
642
+ raise Abstract_method_ex.new(
643
+ "Mxx_ru::Cpp::Toolset::make_c_obj_command_lines" )
644
+ end
645
+
646
+ # Create command line for resource file compilation.
647
+ # Returns Array of String with command lines.
648
+ # Should be redefined in a child class.
649
+ #
650
+ # Abstract_method_ex exception is thrown in a base class.
651
+ #
652
+ # [_res_name_] Full file name of resulting res file.
653
+ # [_rc_file_] Source resource file.
654
+ # [_rc_options_] Resource compiler options.
655
+ # [_target_] Target, resources are required for.
656
+ def make_mswin_res_command_lines(
657
+ res_name,
658
+ rc_file,
659
+ rc_options,
660
+ target )
661
+
662
+ raise Abstract_method_ex.new(
663
+ "Mxx_ru::Cpp::Toolset::make_mswin_res_command_lines" )
664
+ end
665
+
666
+ # Get static library file name.
667
+ #
668
+ # Abstract_method_ex exception is thrown in a base class.
669
+ #
670
+ def lib_file_name( source_name )
671
+ raise Abstract_method_ex.new(
672
+ "Mxx_ru::Cpp::Toolset::lib_file_name" )
673
+ end
674
+
675
+ # Get static library name, which should be passed to the linker.
676
+ #
677
+ # Abstract_method_ex exception is thrown in a base class.
678
+ #
679
+ def lib_link_name( source_name )
680
+ raise Abstract_method_ex.new(
681
+ "Mxx_ru::Cpp::Toolset::lib_link_name" )
682
+ end
683
+
684
+ # Create command line for static library build.
685
+ # Returns Array of String with command lines.
686
+ # Should be redefined in a child class.
687
+ #
688
+ # Abstract_method_ex exception is thrown in a base class.
689
+ #
690
+ # [_lib_name_] Result library file name.
691
+ # [_obj_files_] Object file names, which should be included in the library.
692
+ # [_librarian_options_] Archiver options list. Array of String.
693
+ # [_target_] Target, the library is created for.
694
+ def make_lib_command_lines(
695
+ lib_name,
696
+ obj_files,
697
+ librarian_options,
698
+ target )
699
+
700
+ raise Abstract_method_ex.new(
701
+ "Mxx_ru::Cpp::Toolset::make_lib_command_lines" )
702
+ end
703
+
704
+ # Get shared library file name.
705
+ #
706
+ # Abstract_method_ex exception is thrown in a base class.
707
+ #
708
+ def dll_file_name( source_name )
709
+ raise Abstract_method_ex.new(
710
+ "Mxx_ru::Cpp::Toolset::dll_file_name" )
711
+ end
712
+
713
+ # Get shared library name, which should be passed to the linker.
714
+ # May return nil if no import library defined.
715
+ #
716
+ # Abstract_method_ex exception is thrown in a base class.
717
+ #
718
+ # [_dll_real_name_] The name, returned on previous reference to
719
+ # dll_file_name.
720
+ # [_target_] Target, the library is created for.
721
+ def implib_link_name(
722
+ dll_real_name,
723
+ target )
724
+ raise Abstract_method_ex.new(
725
+ "Mxx_ru::Cpp::Toolset::implib_link_name" )
726
+ end
727
+
728
+ # Get folder name containing import library, which should be passed
729
+ # to the linker.
730
+ # Executed only if previous implib_link_name returned other then nil value.
731
+ # May return nil, if no import library defined.
732
+ # Should be redefined in a child class.
733
+ #
734
+ # Abstract_method_ex exception is thrown in a base class.
735
+ #
736
+ # [_dll_real_name_] The name, returned on previous reference to
737
+ # dll_file_name.
738
+ # [_dll_real_path_] Folder name, DLL will be in.
739
+ # [_target_] Target, the library is created for.
740
+ def implib_link_path(
741
+ dll_real_name,
742
+ dll_real_path,
743
+ target )
744
+ raise Abstract_method_ex.new(
745
+ "Mxx_ru::Cpp::Toolset::implib_link_path" )
746
+ end
747
+
748
+ # Create command line for DLL build.
749
+ # Returns Array of String with command lines.
750
+ # Should be redefined in a child class.
751
+ #
752
+ # Abstract_method_ex exception is thrown in a base class.
753
+ #
754
+ # [_a_dll_name_] DLL result file name.
755
+ # [_a_dll_info_] DLL description.
756
+ # [_a_linker_lists_] Lists required for linker.
757
+ # [_a_target_] Target, the library is created for.
758
+ def make_dll_command_lines(
759
+ a_dll_name,
760
+ a_dll_info,
761
+ a_linker_lists,
762
+ a_target )
763
+
764
+ raise Abstract_method_ex.new(
765
+ "Mxx_ru::Cpp::Toolset::make_dll_command_lines" )
766
+ end
767
+
768
+ # Create dependencies list from DLL given.
769
+ # Returns Dll_requirements object.
770
+ #
771
+ # Abstract_method_ex exception is thrown in a base class.
772
+ #
773
+ # [_a_dll_name_] DLL result file name.
774
+ # [_a_dll_info_] DLL description.
775
+ # [_a_linker_lists_] Lists required for linker.
776
+ # [_a_target_] Target, the library is created for.
777
+ def make_dll_requirements(
778
+ a_dll_name,
779
+ a_dll_info,
780
+ a_linker_lists,
781
+ a_target )
782
+
783
+ raise Abstract_method_ex.new(
784
+ "Mxx_ru::Cpp::Toolset::make_dll_requirements" )
785
+ end
786
+
787
+ # Get executable file name.
788
+ #
789
+ # Abstract_method_ex exception is thrown in a base class.
790
+ #
791
+ def exe_file_name( source_name )
792
+ raise Abstract_method_ex.new(
793
+ "Mxx_ru::Cpp::Toolset::exe_file_name" )
794
+ end
795
+
796
+ # Create command line for EXE build.
797
+ # Returns Array of String with command lines.
798
+ # Should be redefined in a child class.
799
+ #
800
+ # Abstract_method_ex exception is thrown in a base class.
801
+ #
802
+ # [_a_exe_name_] EXE result file name.
803
+ # [_a_exe_info_] EXE description.
804
+ # [_a_linker_lists_] Lists required for linker.
805
+ # [_a_target_] Target, the executable is created for.
806
+ def make_exe_command_lines(
807
+ a_exe_name,
808
+ a_exe_info,
809
+ a_linker_lists,
810
+ a_target )
811
+
812
+ raise Abstract_method_ex.new(
813
+ "Mxx_ru::Cpp::Toolset::make_exe_command_lines" )
814
+ end
815
+
816
+ # toolset name accessor.
817
+ def name
818
+ return @name
819
+ end
820
+
821
+ protected
822
+ # Creating object file names.
823
+ # Returns array of Obj_info objects.
824
+ def make_obj_names( sources, target )
825
+ obj_names = Array.new
826
+ sources.each { |s|
827
+ # Get file name with extension.
828
+ only_name = File::basename( s.name )
829
+ # Get file name without extension.
830
+ only_name = Mxx_ru::Util::remove_file_ext( only_name )
831
+
832
+ # Get source folder name.
833
+ source_path = File::dirname( s.name )
834
+ # Get target folder name for object file.
835
+ dest_path = target.mxx_obj_placement.get_obj(
836
+ source_path, self, target )
837
+ # Object file name creation.
838
+ obj_names.push( Obj_info.new(
839
+ File::join( dest_path, only_name + obj_file_ext() ),
840
+ s,
841
+ s.compiler_options ) )
842
+ }
843
+ return obj_names
844
+ end
845
+
846
+ # Definition of object files, required to build (if absent)
847
+ # or rebuild (if outdated).
848
+ # Returns array of Obj_info objects.
849
+ #
850
+ # [_objs_] Array of Obj_info
851
+ def detect_objs_to_rebuild( objs )
852
+
853
+ obj_names = Array.new
854
+ objs.each { |o|
855
+ obj_state = Mxx_ru::Target_state::detect(
856
+ o.name, [ o.source.name ] + o.source.depends )
857
+ if Mxx_ru::Target_state::EXISTS != obj_state.state
858
+ # File should be rebuilt.
859
+ obj_names << o
860
+ end
861
+ }
862
+
863
+ return obj_names
864
+ end
865
+
866
+ # Compilation of object files given.
867
+ #
868
+ # [_objs_to_build_] Array of Obj_info.
869
+ # [_target_] Target object, contatining these object files.
870
+ # [_lang_specific_options_] C or C++ specific compiler options. Array of String.
871
+ # [_a_method_name_] Method name, which should be executed for command line build
872
+ # of source file compilation.
873
+ def build_objs(
874
+ objs_to_build,
875
+ target,
876
+ lang_specific_options,
877
+ a_method_name )
878
+
879
+ all_files_options = target.mxx_all_compiler_options +
880
+ lang_specific_options;
881
+ all_files_options.flatten!
882
+ all_files_options.uniq!
883
+
884
+ objs_to_build.each { |o|
885
+ # Creating command line to execute compiler.
886
+ compiler_options = all_files_options + o.options;
887
+ compiler_options.flatten!
888
+ compiler_options.uniq!
889
+
890
+ cmd_lines = self.send( a_method_name,
891
+ o.name, o.source.name,
892
+ compiler_options,
893
+ target )
894
+
895
+ # Executing.
896
+ Mxx_ru::Abstract_target::run( cmd_lines, [ o.name ] )
897
+ }
898
+
899
+ end
900
+
901
+ # Creating file name for compiled resources.
902
+ # Returns Mswin_res_info object.
903
+ def make_mswin_res_name( rc_file, target )
904
+ source_name = Mxx_ru::Util::remove_file_ext(
905
+ File::basename( rc_file ) )
906
+ source_path = File::dirname( rc_file )
907
+
908
+ real_name = mswin_res_file_name( source_name )
909
+ dest_path = target.mxx_obj_placement.get_mswin_res(
910
+ source_path, self, target )
911
+
912
+ return Mswin_res_info.new( real_name, dest_path )
913
+ end
914
+
915
+ # Creating static library file name.
916
+ # Returns Lib_info object.
917
+ def make_lib_name( lib_name, target )
918
+ source_name = File::basename( lib_name )
919
+ source_path = File::dirname( lib_name )
920
+
921
+ real_name = lib_file_name( source_name )
922
+ link_name = lib_link_name( source_name )
923
+ dest_path = target.mxx_obj_placement.get_lib(
924
+ source_path, self, target )
925
+
926
+ return Lib_info.new(
927
+ real_name, dest_path, link_name )
928
+ end
929
+
930
+ # Creating shared library file name.
931
+ # Returns Dll_info object.
932
+ def make_dll_name( dll_name, target )
933
+ source_name = File::basename( dll_name )
934
+ source_path = File::dirname( dll_name )
935
+
936
+ dll_real_name = dll_file_name( source_name )
937
+ dll_dest_path = target.mxx_obj_placement.get_dll(
938
+ source_path, self, target )
939
+
940
+ link_name = implib_link_name( dll_real_name, target )
941
+ link_path = nil
942
+ if nil != link_name
943
+ link_path = implib_link_path(
944
+ dll_real_name, dll_dest_path, target )
945
+ end
946
+
947
+ return Dll_info.new(
948
+ dll_real_name, dll_dest_path, link_name, link_path )
949
+ end
950
+
951
+ # Creating executable file name.
952
+ # Returns Exe_info object.
953
+ def make_exe_name( exe_name, target )
954
+ source_name = File::basename( exe_name )
955
+ source_path = File::dirname( exe_name )
956
+
957
+ real_name = exe_file_name( source_name )
958
+ dest_path = target.mxx_obj_placement.get_exe(
959
+ source_path, self, target )
960
+
961
+ return Exe_info.new(
962
+ real_name, dest_path )
963
+ end
964
+
965
+ # Creating full dependencies file list for resulting EXE or DLL file.
966
+ def create_executable_depend_list( target )
967
+ all_depend_files = Array.new
968
+ target.mxx_required_prjs.each { |d|
969
+ depends = d.mxx_full_targets_names
970
+ if nil != depends
971
+ all_depend_files << depends
972
+ end
973
+ }
974
+ all_depend_files << target.mxx_obj_files
975
+
976
+ if target.mxx_mswin_res_file
977
+ all_depend_files << target.mxx_mswin_res_file
978
+ end
979
+
980
+ all_depend_files.flatten!
981
+
982
+ return all_depend_files
983
+ end
984
+
985
+ # Creating all lists required for linker.
986
+ # Returns Linker_lists object.
987
+ def prepare_linker_lists( target )
988
+ result = Linker_lists.new
989
+
990
+ result.add_objs( target.mxx_obj_files )
991
+ result.add_resources( target.mxx_mswin_res_file )
992
+ result.add_libs( target.mxx_required_libs )
993
+ result.add_lib_paths( target.mxx_required_lib_paths )
994
+
995
+ target.mxx_required_prjs.each { |d|
996
+ if d.kind_of?( Mxx_ru::Binary_target )
997
+ result.add_libs( d.mxx_required_libs )
998
+ result.add_lib_paths( d.mxx_required_lib_paths )
999
+ end
1000
+ }
1001
+
1002
+ result.add_linker_options( target.mxx_all_linker_options )
1003
+
1004
+ return result
1005
+ end
1006
+
1007
+ end # class Toolset
1008
+
1009
+ # Current toolset.
1010
+ @@current_toolset = nil
1011
+
1012
+ # Set current toolset.
1013
+ def Cpp.setup_toolset( toolset )
1014
+ raise Mxx_ru.Invalid_cast_ex.new(
1015
+ 'Expected Mxx_ru::Cpp::Toolset' ) if
1016
+ !( toolset.kind_of?( Mxx_ru::Cpp::Toolset ) )
1017
+
1018
+ @@current_toolset = toolset
1019
+ end
1020
+
1021
+ # Get current toolset.
1022
+ def Cpp.toolset
1023
+ return @@current_toolset
1024
+ end
1025
+
1026
+ end # module Cpp
1027
+
1028
+ end # module Mxx_ru
1029
+