Mxx_ru 1.3.0 → 1.3.1

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