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