tioga 1.4
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/Tioga_README +372 -0
- data/lgpl.txt +504 -0
- data/split/Dtable/defs.h +33 -0
- data/split/Dtable/dtable.c +1928 -0
- data/split/Dtable/dtable_intern.h +144 -0
- data/split/Dtable/dvector.h +61 -0
- data/split/Dtable/extconf.rb +4 -0
- data/split/Dtable/include/dtable.h +35 -0
- data/split/Dtable/lib/Dtable_extras.rb +90 -0
- data/split/Dtable/namespace.h +47 -0
- data/split/Dtable/safe_double.h +104 -0
- data/split/Dtable/symbols.c +92 -0
- data/split/Dtable/symbols.h +52 -0
- data/split/Dvector/defs.h +33 -0
- data/split/Dvector/dvector.c +5486 -0
- data/split/Dvector/dvector_intern.h +142 -0
- data/split/Dvector/extconf.rb +4 -0
- data/split/Dvector/include/dvector.h +61 -0
- data/split/Dvector/lib/Dvector_extras.rb +328 -0
- data/split/Dvector/lib/Numeric_extras.rb +134 -0
- data/split/Dvector/namespace.h +47 -0
- data/split/Dvector/safe_double.h +104 -0
- data/split/Dvector/symbols.c +92 -0
- data/split/Dvector/symbols.h +52 -0
- data/split/Flate/defs.h +33 -0
- data/split/Flate/extconf.rb +19 -0
- data/split/Flate/flate.c +156 -0
- data/split/Flate/flate_intern.h +97 -0
- data/split/Flate/include/flate.h +98 -0
- data/split/Flate/namespace.h +47 -0
- data/split/Flate/safe_double.h +104 -0
- data/split/Flate/symbols.c +92 -0
- data/split/Flate/symbols.h +52 -0
- data/split/Function/defs.h +33 -0
- data/split/Function/dvector.h +61 -0
- data/split/Function/extconf.rb +4 -0
- data/split/Function/function.c +988 -0
- data/split/Function/joint_qsort.c +258 -0
- data/split/Function/lib/Function_extras.rb +44 -0
- data/split/Function/namespace.h +47 -0
- data/split/Function/safe_double.h +104 -0
- data/split/Function/symbols.c +92 -0
- data/split/Function/symbols.h +52 -0
- data/split/Tioga/axes.c +774 -0
- data/split/Tioga/defs.h +33 -0
- data/split/Tioga/dtable.h +35 -0
- data/split/Tioga/dvector.h +61 -0
- data/split/Tioga/extconf.rb +4 -0
- data/split/Tioga/figures.c +672 -0
- data/split/Tioga/figures.h +855 -0
- data/split/Tioga/flate.h +98 -0
- data/split/Tioga/init.c +524 -0
- data/split/Tioga/lib/Arcs_and_Circles.rb +64 -0
- data/split/Tioga/lib/ColorConstants.rb +274 -0
- data/split/Tioga/lib/Colorbars.rb +10 -0
- data/split/Tioga/lib/Colormaps.rb +105 -0
- data/split/Tioga/lib/Coordinate_Conversions.rb +194 -0
- data/split/Tioga/lib/Creating_Paths.rb +94 -0
- data/split/Tioga/lib/Doc.rb +91 -0
- data/split/Tioga/lib/Executive.rb +515 -0
- data/split/Tioga/lib/FigMkr.rb +2224 -0
- data/split/Tioga/lib/FigureConstants.rb +125 -0
- data/split/Tioga/lib/Figures_and_Plots.rb +268 -0
- data/split/Tioga/lib/Images.rb +278 -0
- data/split/Tioga/lib/Legends.rb +190 -0
- data/split/Tioga/lib/MarkerConstants.rb +122 -0
- data/split/Tioga/lib/Markers.rb +129 -0
- data/split/Tioga/lib/Page_Frame_Bounds.rb +567 -0
- data/split/Tioga/lib/Rectangles.rb +94 -0
- data/split/Tioga/lib/Shading.rb +100 -0
- data/split/Tioga/lib/Special_Paths.rb +307 -0
- data/split/Tioga/lib/Strokes.rb +129 -0
- data/split/Tioga/lib/TeX_Text.rb +454 -0
- data/split/Tioga/lib/TexPreamble.rb +358 -0
- data/split/Tioga/lib/Titles_and_Labels.rb +306 -0
- data/split/Tioga/lib/Transparency.rb +89 -0
- data/split/Tioga/lib/Using_Paths.rb +164 -0
- data/split/Tioga/lib/Utils.rb +74 -0
- data/split/Tioga/lib/X_and_Y_Axes.rb +749 -0
- data/split/Tioga/lib/irb_tioga.rb +122 -0
- data/split/Tioga/lib/tioga.rb +1 -0
- data/split/Tioga/lib/tioga_ui.rb +5 -0
- data/split/Tioga/lib/tioga_ui_cmds.rb +793 -0
- data/split/Tioga/makers.c +989 -0
- data/split/Tioga/mk_tioga_sty.rb +53 -0
- data/split/Tioga/namespace.h +47 -0
- data/split/Tioga/pdf_font_dicts.c +18253 -0
- data/split/Tioga/pdfcolor.c +486 -0
- data/split/Tioga/pdfcoords.c +505 -0
- data/split/Tioga/pdffile.c +342 -0
- data/split/Tioga/pdfimage.c +536 -0
- data/split/Tioga/pdfpath.c +914 -0
- data/split/Tioga/pdfs.h +229 -0
- data/split/Tioga/pdftext.c +443 -0
- data/split/Tioga/safe_double.h +104 -0
- data/split/Tioga/symbols.c +92 -0
- data/split/Tioga/symbols.h +52 -0
- data/split/Tioga/texout.c +380 -0
- data/split/defs.h +33 -0
- data/split/extconf.rb +107 -0
- data/split/mkmf2.rb +1612 -0
- data/split/namespace.h +47 -0
- data/split/safe_double.h +104 -0
- data/split/scripts/tioga +4 -0
- data/split/symbols.c +92 -0
- data/split/symbols.h +52 -0
- data/tests/dtable_test.data +6 -0
- data/tests/dvector_read_test.data +1 -0
- data/tests/dvector_test.data +101 -0
- data/tests/tc_Dtable.rb +221 -0
- data/tests/tc_Dvector.rb +791 -0
- data/tests/tc_FMkr.rb +162 -0
- data/tests/tc_Flate.rb +45 -0
- data/tests/tc_Function.rb +111 -0
- data/tests/ts_Tioga.rb +38 -0
- metadata +163 -0
data/split/defs.h
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**********************************************************************
|
|
2
|
+
|
|
3
|
+
defs.h:
|
|
4
|
+
some definitions that are used everywhere and that depend on some
|
|
5
|
+
HAVE_* macros.
|
|
6
|
+
|
|
7
|
+
Copyright (C) 2006 Vincent Fourmond
|
|
8
|
+
|
|
9
|
+
This program is free software; you can redistribute it and/or modify
|
|
10
|
+
it under the terms of the GNU General Library Public License as published
|
|
11
|
+
by the Free Software Foundation; either version 2 of the License, or
|
|
12
|
+
(at your option) any later version.
|
|
13
|
+
|
|
14
|
+
This program is distributed in the hope that it will be useful,
|
|
15
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
16
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
17
|
+
GNU Library General Public License for more details.
|
|
18
|
+
|
|
19
|
+
You should have received a copy of the GNU Library General Public License
|
|
20
|
+
along with this program; if not, write to the Free Software
|
|
21
|
+
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
22
|
+
|
|
23
|
+
**********************************************************************/
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
#ifdef HAVE_ISNAN
|
|
27
|
+
/* we use isnan and isinf, which are much faster than the workaround */
|
|
28
|
+
#define is_okay_number(x) (! isnan(x) && ! isinf(x))
|
|
29
|
+
#else
|
|
30
|
+
#define is_okay_number(x) ((x) - (x) == 0.0)
|
|
31
|
+
#define isnan(x) ((x) != (x))
|
|
32
|
+
/* yes, as funny as it may look NaN != NaN, and that's the only one */
|
|
33
|
+
#endif
|
data/split/extconf.rb
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# main Tioga installation file
|
|
2
|
+
|
|
3
|
+
require './mkmf2.rb'
|
|
4
|
+
|
|
5
|
+
# Now, if you want to install the include file, you need to
|
|
6
|
+
# set the EXTCONF_RB_INCLUDE
|
|
7
|
+
if ENV.key?("EXTCONF_RB_INCLUDE")
|
|
8
|
+
include = ENV["EXTCONF_RB_INCLUDE"]
|
|
9
|
+
else
|
|
10
|
+
include = nil
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# install Dvector include and library files into base dirs,
|
|
14
|
+
# and builds Dvector.so
|
|
15
|
+
setup_dir("Dvector", "Dobjects",
|
|
16
|
+
"Dobjects/Dvector", include) do |l,b,i|
|
|
17
|
+
b.add_sources("symbols.c")
|
|
18
|
+
end
|
|
19
|
+
# the same for Dtable
|
|
20
|
+
setup_dir("Dtable", "Dobjects",
|
|
21
|
+
"Dobjects/Dtable", include) do |l,b,i|
|
|
22
|
+
b.add_sources("symbols.c")
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
setup_dir("Flate", "", "Flate", include) do |l,b,i|
|
|
26
|
+
b.add_sources("symbols.c")
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
setup_dir("Function", "Dobjects",
|
|
31
|
+
"Dobjects/Function", include) do |l,b,i|
|
|
32
|
+
b.add_sources("symbols.c")
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
# We declare Tioga by hand, as an automatic generation would not
|
|
37
|
+
# take lib/TexPreamble.rb into accound (missing).
|
|
38
|
+
declare_library("Tioga",
|
|
39
|
+
"Tioga/lib/tioga.rb",
|
|
40
|
+
"Tioga/lib/ColorConstants.rb",
|
|
41
|
+
"Tioga/lib/FigMkr.rb",
|
|
42
|
+
"Tioga/lib/FigureConstants.rb",
|
|
43
|
+
"Tioga/lib/MarkerConstants.rb",
|
|
44
|
+
"Tioga/lib/irb_tioga.rb",
|
|
45
|
+
"Tioga/lib/tioga_ui_cmds.rb",
|
|
46
|
+
"Tioga/lib/tioga_ui.rb",
|
|
47
|
+
"Tioga/lib/Utils.rb",
|
|
48
|
+
"Tioga/lib/TexPreamble.rb")
|
|
49
|
+
|
|
50
|
+
declare_binary_library("Tioga/FigureMaker",
|
|
51
|
+
"Tioga/**/*.c", "symbols.c")
|
|
52
|
+
|
|
53
|
+
# The preamble stuff:
|
|
54
|
+
custom_rule("Tioga/lib/TexPreamble.rb",
|
|
55
|
+
[ "cd Tioga; " + Mkmf2.config_var("RUBY_INSTALL_NAME") +
|
|
56
|
+
" mk_tioga_sty.rb"],
|
|
57
|
+
["Tioga/lib/ColorConstants.rb",
|
|
58
|
+
"Tioga/tioga.sty.in", "Tioga/mk_tioga_sty.rb"]
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
# we check the presence of zlib library
|
|
62
|
+
unless have_header("zlib.h") and have_library("z", "compress", "zlib.h")
|
|
63
|
+
puts <<"EON"
|
|
64
|
+
Error: you should have zlib (including development files) installed to
|
|
65
|
+
build and run Tioga. You can get it there:
|
|
66
|
+
|
|
67
|
+
http://www.zlib.net/
|
|
68
|
+
|
|
69
|
+
If that doesn't solve your problem, please report it on the Tioga tracker:
|
|
70
|
+
|
|
71
|
+
http://rubyforge.org/tracker/?group_id=701
|
|
72
|
+
|
|
73
|
+
EON
|
|
74
|
+
exit 1
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
unless have_header("ieee754.h")
|
|
78
|
+
puts "You lack the ieee754.h header file, which might mean lower " +
|
|
79
|
+
"reliability when Marshalling Dvectors and Dtables"
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Looking for the presence of the is_nan (implies the rest -- isfinite)
|
|
83
|
+
have_func("isnan","math.h")
|
|
84
|
+
|
|
85
|
+
# Installing scripts
|
|
86
|
+
declare_exec 'scripts/tioga'
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
if Config::CONFIG["target"] =~ /darwin/i
|
|
90
|
+
# Installing MacOS specific scripts:
|
|
91
|
+
# Creating the script
|
|
92
|
+
puts "MacOS specific installation"
|
|
93
|
+
custom_rule("repreview",
|
|
94
|
+
[ "echo '#!/bin/sh' > repreview",
|
|
95
|
+
"echo \"osascript '$(EXEC_INSTALL_DIR)/Reload_Preview_Document.scpt'\" '$$*' >> repreview"
|
|
96
|
+
])
|
|
97
|
+
declare_exec 'repreview'
|
|
98
|
+
declare_exec 'scripts/Reload_Preview_Document.scpt'
|
|
99
|
+
else
|
|
100
|
+
puts "Skipping MacOS-specific files"
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
write_makefile
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
|
data/split/mkmf2.rb
ADDED
|
@@ -0,0 +1,1612 @@
|
|
|
1
|
+
require 'rbconfig'
|
|
2
|
+
require 'fileutils'
|
|
3
|
+
|
|
4
|
+
# some global variables:
|
|
5
|
+
$LOCAL_LIBS = ""
|
|
6
|
+
|
|
7
|
+
# A string extension from old mkmf.rb
|
|
8
|
+
class String
|
|
9
|
+
def quote
|
|
10
|
+
/\s/ =~ self ? "\"#{self}\"" : self
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# and a new function, that can come in useful in several places:
|
|
14
|
+
def sanitize
|
|
15
|
+
return self.tr("a-z./\055", "A-Z___")
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# An array extension from old mkmf.rb
|
|
20
|
+
class Array
|
|
21
|
+
def quote
|
|
22
|
+
map {|s| s.quote}
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
=begin rdoc
|
|
28
|
+
:title: Mkmf2: a better replacement for mkmf
|
|
29
|
+
=end
|
|
30
|
+
|
|
31
|
+
=begin rdoc
|
|
32
|
+
|
|
33
|
+
=Mkmf2: a drop-in replacement for mkmf
|
|
34
|
+
|
|
35
|
+
Mkmf2 aims at replacing the functionnality of the old mkmf, with a better and
|
|
36
|
+
cleaner code. It hopefully will keep all the previous mkmf files working,
|
|
37
|
+
while providing
|
|
38
|
+
* better control over the Makefiles produced;
|
|
39
|
+
* installation to <tt>$HOME</tt>;
|
|
40
|
+
* uninstallation;
|
|
41
|
+
* more flexibility.
|
|
42
|
+
|
|
43
|
+
==Background
|
|
44
|
+
|
|
45
|
+
Mkmf2 was written to supplement a missing feature on the old +mkmf.rb+: it is
|
|
46
|
+
not possible to install include files along with the library, and not easy
|
|
47
|
+
to make several libraries, that link each other, and install them... So here
|
|
48
|
+
comes mkmf2.rb !
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
==Bugs
|
|
52
|
+
|
|
53
|
+
There are probably a huge number of bugs, or missing features, or
|
|
54
|
+
misleading features. In case you find one, please file a request
|
|
55
|
+
in the mkmf2 project on rubyforge, at the address
|
|
56
|
+
http://rubyforge.org/tracker/?group_id=1391
|
|
57
|
+
|
|
58
|
+
But before, please, check out the latest cvs version at
|
|
59
|
+
http://rubyforge.org/scm/?group_id=1391
|
|
60
|
+
and make sure the bug is still there...
|
|
61
|
+
|
|
62
|
+
==Note to anyone who wishes to contribute
|
|
63
|
+
|
|
64
|
+
Please, document any code you add, and keep the
|
|
65
|
+
changelog up to date...
|
|
66
|
+
|
|
67
|
+
==Copyright
|
|
68
|
+
|
|
69
|
+
This module is copyright 2006 by Vincent Fourmond. You can use and
|
|
70
|
+
redistribute it under the terms of the General Public License version 2.
|
|
71
|
+
As a special exception, you can distribute any verbatim copy along with
|
|
72
|
+
a program, provided that this program depends on mkmf2 to install.
|
|
73
|
+
|
|
74
|
+
=end
|
|
75
|
+
|
|
76
|
+
module Mkmf2
|
|
77
|
+
|
|
78
|
+
include Config
|
|
79
|
+
|
|
80
|
+
# The CVS tag used for the release.
|
|
81
|
+
CVS_TAG = '$Name$'
|
|
82
|
+
|
|
83
|
+
# The module version; it is computed from CVS_TAG
|
|
84
|
+
VERSION = CVS_TAG.match(/\D+(.*?)\s*\$?$/)[1].tr('_-','..')
|
|
85
|
+
|
|
86
|
+
# The entities: a list of Mkmf2::MfEntity representing what
|
|
87
|
+
# we are currently building.
|
|
88
|
+
@@entities = []
|
|
89
|
+
|
|
90
|
+
# User-defined rules:
|
|
91
|
+
@@user_rules = []
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
# we first start the module with a whole bunch of small subclasses
|
|
95
|
+
# that will come in really useful later.
|
|
96
|
+
|
|
97
|
+
# This class provides a crude functionnality for defining a rule
|
|
98
|
+
# in a Makefile.
|
|
99
|
+
class MfRule
|
|
100
|
+
attr_accessor :name, :rule, :dependencies
|
|
101
|
+
|
|
102
|
+
# converts this rule to a string that can be readily printed to
|
|
103
|
+
# the Makefile
|
|
104
|
+
def to_s
|
|
105
|
+
return "#{@name}: #{@dependencies.join ' '}" +
|
|
106
|
+
if @rule.empty? # we don't need a second line
|
|
107
|
+
"\n"
|
|
108
|
+
else
|
|
109
|
+
"\n\t#{@rule.join "\n\t"}\n"
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# +name+:: the name of the rule.
|
|
114
|
+
# +rule+::
|
|
115
|
+
# a string or an array of lines; strings are split if necessary
|
|
116
|
+
# +deps+:: a string or an array of dependencies
|
|
117
|
+
def initialize(name, rule = nil, deps = nil)
|
|
118
|
+
@name = name
|
|
119
|
+
|
|
120
|
+
if rule.is_a? Array
|
|
121
|
+
@rule = rule
|
|
122
|
+
elsif rule.nil?
|
|
123
|
+
@rule = []
|
|
124
|
+
else
|
|
125
|
+
@rule = rule.split /\s*\n\t?\s*/
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
if deps.is_a? Array
|
|
129
|
+
@dependencies = deps
|
|
130
|
+
elsif deps.nil?
|
|
131
|
+
@dependencies = []
|
|
132
|
+
else
|
|
133
|
+
@dependencies = deps.split /\s+/
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# A small class to include comments into the Makefile, just to help anyone
|
|
140
|
+
# who has to debug something. And it annoys me not to be able to clearly
|
|
141
|
+
# read the output of the test.rb script !
|
|
142
|
+
class MfComment < MfRule
|
|
143
|
+
|
|
144
|
+
# The actual text of the comment.
|
|
145
|
+
attr_accessor :text
|
|
146
|
+
|
|
147
|
+
# +str+ is the text meant to be displayed in the makefile. If it is nil
|
|
148
|
+
# the rule just ends up being a blank line, to allow for easy separation
|
|
149
|
+
# of the rules.
|
|
150
|
+
def initialize(str = nil)
|
|
151
|
+
@text = str
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def to_s
|
|
155
|
+
if @text.nil?
|
|
156
|
+
return "\n"
|
|
157
|
+
else
|
|
158
|
+
lines = @text.to_s.split '\n'
|
|
159
|
+
lines.unshift ""
|
|
160
|
+
return "#{lines.join "\n# "}\n"
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
# An MfEntity object reprensents something that is part of the package.
|
|
169
|
+
# In this way, it needs to provide:
|
|
170
|
+
#
|
|
171
|
+
# * a way to *install* itself;
|
|
172
|
+
# * a way to *uninstall* itself;
|
|
173
|
+
# * a way to *clean* the source directory;
|
|
174
|
+
# * and, possibly, a way to *build* itself.
|
|
175
|
+
#
|
|
176
|
+
# This class should be subclassed for objects that need building.
|
|
177
|
+
# It should be enough though for many simple objects.
|
|
178
|
+
#
|
|
179
|
+
# The module will hold a list of all the MfEntities, and use them in turn
|
|
180
|
+
# to create the Makefile.
|
|
181
|
+
class MfEntity
|
|
182
|
+
|
|
183
|
+
# +install_files+ is a hash that associates files in the building
|
|
184
|
+
# tree to files where the installation is done. To be more precise
|
|
185
|
+
# the install path for the files is expressed relative to
|
|
186
|
+
# +install_path+
|
|
187
|
+
attr_accessor :install_files
|
|
188
|
+
|
|
189
|
+
# This name has to be registered by Mkmf2.register_name. Its lowercase
|
|
190
|
+
# version will be used to name the targets (install_#{name}), etc.), and
|
|
191
|
+
# it's uppercase version can be used as a prefix to name Makefile
|
|
192
|
+
# variables, that we can for instance depend on.
|
|
193
|
+
attr_accessor :name
|
|
194
|
+
|
|
195
|
+
# It represents the type of the entity. It should be a valid entry
|
|
196
|
+
# for Mkmf2.install_path.
|
|
197
|
+
attr_accessor :kind
|
|
198
|
+
|
|
199
|
+
# It is used to ask Mkmf2.install_files for the right rule for
|
|
200
|
+
# installing files (they can be data, scripts, programs, and so on...)
|
|
201
|
+
attr_accessor :install_rule
|
|
202
|
+
|
|
203
|
+
# The +name+ parameter is turned into a unique name and ends up as
|
|
204
|
+
# an identifier for the stuffs related to this element in the Makefile.
|
|
205
|
+
# The +install+ parameter directly becomes install_files.
|
|
206
|
+
# The +kind+ parameter describes the kind of thing we're going
|
|
207
|
+
# to install. See Mkmf2.install_path.
|
|
208
|
+
|
|
209
|
+
def initialize(name, install, kind = 'lib',
|
|
210
|
+
install_rule = 'install_data')
|
|
211
|
+
|
|
212
|
+
# we append kind to avoid overlaps in case of
|
|
213
|
+
# a malchosen name (even if this is guaranteed by register_name),
|
|
214
|
+
# it will look better.
|
|
215
|
+
@name = Mkmf2::register_name(kind + "_" + name)
|
|
216
|
+
@install_files = install.dup
|
|
217
|
+
@kind = kind
|
|
218
|
+
@install_rule = install_rule
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
# Returns the install path for the current object. The implementation
|
|
222
|
+
# should call Mkmf2.install_path with an appropriate argument.
|
|
223
|
+
def install_path
|
|
224
|
+
return Mkmf2::install_path(@kind)
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
# Returns an array containing
|
|
229
|
+
# * a string as the first element which should be appendended
|
|
230
|
+
# as a dependency for the install target
|
|
231
|
+
# * a set of MfRules, describing what need to be done
|
|
232
|
+
# for that peculiar install.
|
|
233
|
+
|
|
234
|
+
def install_rules
|
|
235
|
+
rules = ["install_#{@name.downcase}"]
|
|
236
|
+
|
|
237
|
+
rules.push MfComment.new("installation rules for #{name}")
|
|
238
|
+
|
|
239
|
+
rules.push MfRule.new("install_#{@name.downcase}",
|
|
240
|
+
Mkmf2.install_files_rules(@install_rule,
|
|
241
|
+
install_path,
|
|
242
|
+
@install_files),
|
|
243
|
+
["$(#{@name.upcase}_SOURCE_FILES)",
|
|
244
|
+
"$(#{@name.upcase}_INSTALL_DIRS)"]
|
|
245
|
+
)
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
# Rules for uninstalling the entity.
|
|
249
|
+
# See install_rules for the return values.
|
|
250
|
+
def uninstall_rules
|
|
251
|
+
rules = ["uninstall_#{@name.downcase}"]
|
|
252
|
+
|
|
253
|
+
rules.push MfComment.new("uninstallation rules for #{name}")
|
|
254
|
+
files = [] # the rules to remove the installed files
|
|
255
|
+
dirs = [] # the directories created during install
|
|
256
|
+
@install_files.each_value do |v|
|
|
257
|
+
dest = File.join(install_path,v)
|
|
258
|
+
files.push Mkmf2.rule('remove',dest)
|
|
259
|
+
dirs << File.dirname(dest)
|
|
260
|
+
end
|
|
261
|
+
dirs.uniq!
|
|
262
|
+
for dir in dirs
|
|
263
|
+
files << Mkmf2.rule('remove_path',dir)
|
|
264
|
+
end
|
|
265
|
+
rules.push MfRule.new("uninstall_#{@name.downcase}",
|
|
266
|
+
files)
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
# Rules for cleaning the source directory. See #install_rules for
|
|
270
|
+
# an explanation about return values. This implementation does
|
|
271
|
+
# nothing, as there is nothing to be built.
|
|
272
|
+
def clean_rules
|
|
273
|
+
return []
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
# Rules for building the entity. See #install_rules for
|
|
277
|
+
# an explanation about return values.
|
|
278
|
+
def build_rules
|
|
279
|
+
return []
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
# Returns all the variables that should be added to the Makefile.
|
|
283
|
+
# It should return a simple hash containing the values.
|
|
284
|
+
def variables
|
|
285
|
+
# we need to define this variable:
|
|
286
|
+
ret = {}
|
|
287
|
+
install = []
|
|
288
|
+
source = []
|
|
289
|
+
dirs = []
|
|
290
|
+
@install_files.each do |k,f|
|
|
291
|
+
file = File.join(install_path,f)
|
|
292
|
+
install << file
|
|
293
|
+
source << k
|
|
294
|
+
dirs << File.dirname(file) + "/"
|
|
295
|
+
end
|
|
296
|
+
dirs.uniq!
|
|
297
|
+
ret["#{@name.upcase}_INSTALL_FILES"] =
|
|
298
|
+
Mkmf2.pretty_print_list(install,"#{@name.upcase}_INSTALL_FILES=")
|
|
299
|
+
ret["#{@name.upcase}_INSTALL_DIRS"] =
|
|
300
|
+
Mkmf2.pretty_print_list(dirs,"#{@name.upcase}_INSTALL_DIRS=")
|
|
301
|
+
ret["#{@name.upcase}_SOURCE_FILES"] =
|
|
302
|
+
Mkmf2.pretty_print_list(source,"#{@name.upcase}_SOURCE_FILES=")
|
|
303
|
+
return ret
|
|
304
|
+
end
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
# The class to create libraries that need to be built (that is basically
|
|
308
|
+
# why I wrote the whole stuff !).
|
|
309
|
+
class MfBinaryLibEntity < MfEntity
|
|
310
|
+
|
|
311
|
+
# The source files of the library.
|
|
312
|
+
attr_accessor :sources
|
|
313
|
+
|
|
314
|
+
# The object files for the library
|
|
315
|
+
attr_accessor :objects
|
|
316
|
+
|
|
317
|
+
# The name of the file produced in the source directory.
|
|
318
|
+
attr_accessor :target_file
|
|
319
|
+
|
|
320
|
+
# The libraries on which the linking does depend
|
|
321
|
+
attr_accessor :lib_depends
|
|
322
|
+
|
|
323
|
+
# Supplementary command-line arguments for the linking step.
|
|
324
|
+
# It will be used for instance to store library info.
|
|
325
|
+
attr_accessor :suppl_args
|
|
326
|
+
|
|
327
|
+
# +name+:: of the binary library produce, for instance "Biniou/Bidule"
|
|
328
|
+
# +sources+:: sources of the files, defaults to all the potential
|
|
329
|
+
# +C+/+C\+\++ in the current directory.
|
|
330
|
+
# The sources are further expanded with Dir.glob.
|
|
331
|
+
# If you give then name of a directory, it will be
|
|
332
|
+
# expanded
|
|
333
|
+
# +target_file+:: how the files built in the current directory
|
|
334
|
+
# will be called. Defaults to the same file name
|
|
335
|
+
# as +name+.
|
|
336
|
+
# +lib_depends+:: an array of objects, which designate ruby binary
|
|
337
|
+
# libraries that this library does depend on;
|
|
338
|
+
|
|
339
|
+
def initialize(name, sources = nil, target_file = nil,
|
|
340
|
+
lib_depends = nil)
|
|
341
|
+
if sources.nil?
|
|
342
|
+
sources = ["."]
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
@sources = []
|
|
346
|
+
add_sources(sources)
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
if target_file.nil?
|
|
350
|
+
@target_file = File.basename(name) + ".#{CONFIG["DLEXT"]}"
|
|
351
|
+
else
|
|
352
|
+
@target_file = target_file
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
install_hash = { @target_file => name + ".#{CONFIG["DLEXT"]}" }
|
|
356
|
+
# Then, we call the function of the parent
|
|
357
|
+
super(name, install_hash,'bin_lib','install_bin')
|
|
358
|
+
@suppl_args = ""
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
# Adds source files to the library. Can come in useful inside a block
|
|
362
|
+
def add_sources(*sources)
|
|
363
|
+
# we flatten the array, just to make sure everything is top-level
|
|
364
|
+
sources.flatten!
|
|
365
|
+
|
|
366
|
+
# We expand directory into the files in them
|
|
367
|
+
# (no subdirs)
|
|
368
|
+
sources.collect! do |f|
|
|
369
|
+
if File.directory?(f)
|
|
370
|
+
temp = []
|
|
371
|
+
for ext in Mkmf2.source_files_extensions
|
|
372
|
+
temp << File.join(f,"*.#{ext}")
|
|
373
|
+
end
|
|
374
|
+
temp
|
|
375
|
+
else
|
|
376
|
+
f
|
|
377
|
+
end
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
# Then, we expand the files:
|
|
381
|
+
for f in sources
|
|
382
|
+
files = Dir.glob(f)
|
|
383
|
+
if files.empty?
|
|
384
|
+
@sources << f
|
|
385
|
+
else
|
|
386
|
+
@sources += files
|
|
387
|
+
end
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
# and we update the list of current object files
|
|
391
|
+
@objects = @sources.collect do |f|
|
|
392
|
+
f.gsub(/\.[^.]+$/, ".#{CONFIG["OBJEXT"]}")
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
end
|
|
396
|
+
#
|
|
397
|
+
def build_rules
|
|
398
|
+
return [#"build_#{@name.downcase}",
|
|
399
|
+
@target_file,
|
|
400
|
+
# better to write this way... more clear on the
|
|
401
|
+
# zsh command-line completion ;-) !
|
|
402
|
+
MfRule.new(@target_file,
|
|
403
|
+
Mkmf2.rule('build_library',
|
|
404
|
+
"$(#{name.upcase}_OBJS)",
|
|
405
|
+
@suppl_args),
|
|
406
|
+
"$(#{name.upcase}_OBJS)")
|
|
407
|
+
]
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
# This removes the object files for the target...
|
|
411
|
+
def clean_rules
|
|
412
|
+
rules = ["clean_#{@name.downcase}"]
|
|
413
|
+
|
|
414
|
+
rules.push MfComment.new("cleaning rules for #{name}")
|
|
415
|
+
files = [] # the rules to clean the files
|
|
416
|
+
@objects.each do |v|
|
|
417
|
+
files.push Mkmf2.rule('remove',v)
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
files.push Mkmf2.rule('remove', @target_file)
|
|
421
|
+
rules.push MfRule.new("clean_#{@name.downcase}",
|
|
422
|
+
files)
|
|
423
|
+
return rules
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
def variables
|
|
427
|
+
vars = super
|
|
428
|
+
# We add the object list variable
|
|
429
|
+
vars["#{name.upcase}_OBJS"] =
|
|
430
|
+
Mkmf2.pretty_print_list(@objects,"#{name.upcase}_OBJS=")
|
|
431
|
+
return vars
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
# Returns a list of the potential source files extensions.
|
|
437
|
+
def Mkmf2.source_files_extensions
|
|
438
|
+
return Mkmf2.cpp_files_extensions +
|
|
439
|
+
Mkmf2.c_files_extensions
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
# Return the extensions for C++ files.
|
|
443
|
+
def Mkmf2.cpp_files_extensions
|
|
444
|
+
return %w{cpp cc cxx}
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
# Return extensions for C files.
|
|
448
|
+
def Mkmf2.c_files_extensions
|
|
449
|
+
return %w{c}
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
|
|
453
|
+
# This function declares a shared binary library that will be built
|
|
454
|
+
# and installed using the appropriate functions.
|
|
455
|
+
#
|
|
456
|
+
# +libname+ is what is usually passed as an argument to the
|
|
457
|
+
# +create_makefile+ function of the old
|
|
458
|
+
#
|
|
459
|
+
# +sources+ is the source files. They are processed using Dir.glob, so
|
|
460
|
+
# they can contain wildcards.
|
|
461
|
+
#
|
|
462
|
+
# This function contends itselfs to *declare* the library, it does not
|
|
463
|
+
# *build* it, as this will be done by +make+.
|
|
464
|
+
|
|
465
|
+
def declare_binary_library(libname, *sources, &b)
|
|
466
|
+
add_entity(MfBinaryLibEntity.new(libname, sources), &b)
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
def add_entity(entity)
|
|
470
|
+
yield entity if block_given?
|
|
471
|
+
@@entities << entity
|
|
472
|
+
return entity
|
|
473
|
+
end
|
|
474
|
+
|
|
475
|
+
# This function declares a Ruby library, namely files that want
|
|
476
|
+
# to be installed directly in the rubylibdir (or equivalent, depending
|
|
477
|
+
# on the user settings).
|
|
478
|
+
# +target_dir+:: the target directory, relative to the installation
|
|
479
|
+
# directory;
|
|
480
|
+
# +files+:: the files to install. Defaults to "lib/**.rb"
|
|
481
|
+
#
|
|
482
|
+
# For instance,
|
|
483
|
+
# declare_library("Biniou", "toto.rb")
|
|
484
|
+
# will install the file "Biniou/toto.rb" in the common library
|
|
485
|
+
# directory.
|
|
486
|
+
|
|
487
|
+
def declare_library(target_dir,*files, &b)
|
|
488
|
+
if files.empty?
|
|
489
|
+
files << "lib/**/*.rb"
|
|
490
|
+
end
|
|
491
|
+
declare_file_set(target_dir, files, 'lib', false, &b)
|
|
492
|
+
end
|
|
493
|
+
|
|
494
|
+
# Declares a set of files that should be executed directly be the user.
|
|
495
|
+
def declare_exec(*files, &b)
|
|
496
|
+
# No need for a target directory.
|
|
497
|
+
declare_file_set("", files, 'exec', true, 'install_script',&b)
|
|
498
|
+
end
|
|
499
|
+
|
|
500
|
+
# Declares a documentation that doesn't need to be built. For the arguments,
|
|
501
|
+
# see #declare_library.
|
|
502
|
+
def declare_doc(target_dir, *files,&b)
|
|
503
|
+
if files.empty?
|
|
504
|
+
files << "doc/**/*"
|
|
505
|
+
end
|
|
506
|
+
declare_file_set(target_dir, files, 'doc', false,&b)
|
|
507
|
+
end
|
|
508
|
+
|
|
509
|
+
# Declares a set of include files to be installed. Defaults to
|
|
510
|
+
# all the files in the include subdirectory.
|
|
511
|
+
def declare_includes(target_dir,*files,&b)
|
|
512
|
+
if files.empty?
|
|
513
|
+
files << "include/**/*.h"
|
|
514
|
+
end
|
|
515
|
+
declare_file_set(target_dir, files, 'include', true,&b)
|
|
516
|
+
end
|
|
517
|
+
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
# The main place for declaring files to be installed.
|
|
521
|
+
# +target_dir+:: the target directory relative to the install path
|
|
522
|
+
# if it is nil or empty, then just install in the
|
|
523
|
+
# base directory.
|
|
524
|
+
# +files+:: the source files
|
|
525
|
+
# +kind+:: the kind of target (see again and again install_path)
|
|
526
|
+
# +basename+:: wether or not to strip the leading directories ?
|
|
527
|
+
# +skip+:: a regular expression (or whatever object that has a ===
|
|
528
|
+
# method that matches strings) saying wich files should
|
|
529
|
+
# be excluded. Defaults to /~$/.
|
|
530
|
+
# _base_dir_:: a source base directory to be stripped from the target
|
|
531
|
+
# name
|
|
532
|
+
|
|
533
|
+
def declare_file_set(target_dir, files, kind = 'lib',
|
|
534
|
+
basename = true,
|
|
535
|
+
rule = 'install_data',
|
|
536
|
+
skip = /~$/, delete = /((^.*\/)?lib\/)?/,
|
|
537
|
+
base_dir = false, &b)
|
|
538
|
+
source_files = []
|
|
539
|
+
for glob in files
|
|
540
|
+
# If glob looks like a glob, we use Dir.glob, else we add it
|
|
541
|
+
# without modification
|
|
542
|
+
if glob =~ /\*|\[|\?/
|
|
543
|
+
source_files += Dir[glob]
|
|
544
|
+
else
|
|
545
|
+
source_files << glob
|
|
546
|
+
end
|
|
547
|
+
end
|
|
548
|
+
install_hash = {}
|
|
549
|
+
for f in source_files
|
|
550
|
+
next if skip === f
|
|
551
|
+
next if File.directory? f
|
|
552
|
+
filename = if basename
|
|
553
|
+
File.basename(f)
|
|
554
|
+
else
|
|
555
|
+
f.dup
|
|
556
|
+
end
|
|
557
|
+
filename.gsub!(delete, '')
|
|
558
|
+
|
|
559
|
+
if target_dir.nil? or target_dir.empty?
|
|
560
|
+
install_hash[f] = filename
|
|
561
|
+
else
|
|
562
|
+
install_hash[f] = File.join(target_dir, filename)
|
|
563
|
+
end
|
|
564
|
+
end
|
|
565
|
+
add_entity(MfEntity.new(target_dir, install_hash,
|
|
566
|
+
kind, rule), &b)
|
|
567
|
+
end
|
|
568
|
+
|
|
569
|
+
@@model = "local"
|
|
570
|
+
|
|
571
|
+
# Sets the model for directory installation. There are for now
|
|
572
|
+
# three values:
|
|
573
|
+
# local:: for a standard installation (like the default in mkmf.rb)
|
|
574
|
+
# dist:: to use in a packageing system
|
|
575
|
+
# home:: to install to a home directory (basically, prefix= <tt>$HOME</tt>)
|
|
576
|
+
#
|
|
577
|
+
# Please do not modify @@model directly.
|
|
578
|
+
|
|
579
|
+
def Mkmf2.set_model(model = "local")
|
|
580
|
+
@@model = model
|
|
581
|
+
end
|
|
582
|
+
|
|
583
|
+
# Sets up a whole bunch of variables necessary for installation, depending
|
|
584
|
+
# on the current value of the @@model parameter. This is the place where we
|
|
585
|
+
# setup the variables used by the installation process, namely:
|
|
586
|
+
# +RUBYLIB_INSTALL_DIR+:: the directory where the text libraries
|
|
587
|
+
# are to be installed;
|
|
588
|
+
# +RUBYARCHLIB_INSTALL_DIR+:: the directory where architecture
|
|
589
|
+
# dependent libraries are installed;
|
|
590
|
+
# +INCLUDE_INSTALL_DIR+:: the directory where include files should go
|
|
591
|
+
# if necessary;
|
|
592
|
+
# And for now, that is all.
|
|
593
|
+
def setup_model
|
|
594
|
+
case @@model
|
|
595
|
+
when "home"
|
|
596
|
+
# I made a mistake for the home scheme.
|
|
597
|
+
# we ensure the prefix is set to $HOME
|
|
598
|
+
MAKEFILE_CONFIG["RUBYLIB_INSTALL_DIR"] =
|
|
599
|
+
"$(DESTDIR)$(HOME)/lib/ruby"
|
|
600
|
+
# For the HOME scheme, binaries and .rb files go
|
|
601
|
+
# to the same directory.
|
|
602
|
+
MAKEFILE_CONFIG["RUBYARCHLIB_INSTALL_DIR"] =
|
|
603
|
+
"$(DESTDIR)$(HOME)/lib/ruby"
|
|
604
|
+
MAKEFILE_CONFIG["INCLUDE_INSTALL_DIR"] =
|
|
605
|
+
"$(DESTDIR)$(HOME)/include"
|
|
606
|
+
MAKEFILE_CONFIG["EXEC_INSTALL_DIR"] =
|
|
607
|
+
"$(DESTDIR)$(HOME)/bin"
|
|
608
|
+
|
|
609
|
+
when "dist"
|
|
610
|
+
# shares some code with the previous item, don't forget to
|
|
611
|
+
# update *BOTH* !
|
|
612
|
+
MAKEFILE_CONFIG["RUBYLIB_INSTALL_DIR"] =
|
|
613
|
+
"$(DESTDIR)$(rubylibdir)"
|
|
614
|
+
MAKEFILE_CONFIG["RUBYARCHLIB_INSTALL_DIR"] =
|
|
615
|
+
"$(DESTDIR)$(archdir)"
|
|
616
|
+
MAKEFILE_CONFIG["INCLUDE_INSTALL_DIR"] =
|
|
617
|
+
"$(DESTDIR)$(includedir)"
|
|
618
|
+
MAKEFILE_CONFIG["EXEC_INSTALL_DIR"] =
|
|
619
|
+
File.join("$(prefix)", "bin")
|
|
620
|
+
|
|
621
|
+
when "local"
|
|
622
|
+
MAKEFILE_CONFIG["RUBYLIB_INSTALL_DIR"] =
|
|
623
|
+
"$(sitelibdir)"
|
|
624
|
+
MAKEFILE_CONFIG["RUBYARCHLIB_INSTALL_DIR"] =
|
|
625
|
+
"$(sitearchdir)"
|
|
626
|
+
|
|
627
|
+
# To make the base directory for installation, I propose
|
|
628
|
+
# to strip all the directories containing ruby from the
|
|
629
|
+
# $(sitedir) directory and strip one more directory.
|
|
630
|
+
|
|
631
|
+
basedir = MAKEFILE_CONFIG["sitedir"]
|
|
632
|
+
while File.basename(basedir) =~ /ruby/
|
|
633
|
+
basedir = File.dirname(basedir)
|
|
634
|
+
end
|
|
635
|
+
# Strip one more:
|
|
636
|
+
basedir = File.dirname(basedir)
|
|
637
|
+
MAKEFILE_CONFIG["basedir"] = basedir
|
|
638
|
+
MAKEFILE_CONFIG["INCLUDE_INSTALL_DIR"] =
|
|
639
|
+
"$(basedir)/include"
|
|
640
|
+
MAKEFILE_CONFIG["EXEC_INSTALL_DIR"] =
|
|
641
|
+
"$(basedir)/bin"
|
|
642
|
+
end
|
|
643
|
+
|
|
644
|
+
end
|
|
645
|
+
|
|
646
|
+
|
|
647
|
+
# Returns the installation path for a given thing (+what+). This function
|
|
648
|
+
# basically returns a simple MAKEFILE_CONFIG variable, which has otherwise
|
|
649
|
+
# been setup by setup_model. What is available for now:
|
|
650
|
+
# +lib+:: where to install .rb library
|
|
651
|
+
# +bin_lib+:: where to install binary libs
|
|
652
|
+
# +include+:: include files
|
|
653
|
+
|
|
654
|
+
def Mkmf2.install_path(what)
|
|
655
|
+
# we should definitely append a $(DESTDIR) to every single
|
|
656
|
+
# directory we return, since it will make debugging
|
|
657
|
+
|
|
658
|
+
case what
|
|
659
|
+
when 'lib'
|
|
660
|
+
return Mkmf2.config_var('RUBYLIB_INSTALL_DIR')
|
|
661
|
+
when 'exec'
|
|
662
|
+
return Mkmf2.config_var('EXEC_INSTALL_DIR')
|
|
663
|
+
when 'bin_lib'
|
|
664
|
+
return Mkmf2.config_var('RUBYARCHLIB_INSTALL_DIR')
|
|
665
|
+
when 'include'
|
|
666
|
+
return Mkmf2.config_var('INCLUDE_INSTALL_DIR')
|
|
667
|
+
else
|
|
668
|
+
raise "Unkown installation directory specification: #{what}"
|
|
669
|
+
end
|
|
670
|
+
end
|
|
671
|
+
|
|
672
|
+
@@registered_names = {} # a hash containing already registered names
|
|
673
|
+
# to avoid namespace clobbering.
|
|
674
|
+
|
|
675
|
+
# Register a new name, making sure the name returned is unique.
|
|
676
|
+
def Mkmf2.register_name(name)
|
|
677
|
+
# first, transform all that is not letter into underscore
|
|
678
|
+
name.gsub!(/[^a-zA-Z]/,'_')
|
|
679
|
+
# pretty-print a bit
|
|
680
|
+
name.gsub!(/^_|_$/,'')
|
|
681
|
+
name.gsub!(/_+/, '_')
|
|
682
|
+
name.downcase!
|
|
683
|
+
# then, increment the number
|
|
684
|
+
if @@registered_names[name]
|
|
685
|
+
i = 1
|
|
686
|
+
while @@registered_names["#{name}_#{i}"]
|
|
687
|
+
i += 1
|
|
688
|
+
end
|
|
689
|
+
name = "#{name}_#{i}"
|
|
690
|
+
end
|
|
691
|
+
@@registered_names[name] = true
|
|
692
|
+
return name
|
|
693
|
+
end
|
|
694
|
+
|
|
695
|
+
|
|
696
|
+
# Stores which configuration variables are used
|
|
697
|
+
@@config_variables_used = []
|
|
698
|
+
# Returns the given config key, that will be used to write a rule
|
|
699
|
+
# in the Makefile. For better output, the function does store a list of
|
|
700
|
+
# all the config variables which are in use, and simply outputs
|
|
701
|
+
# +$(VARIABLE)+.
|
|
702
|
+
def Mkmf2.config_var(str)
|
|
703
|
+
@@config_variables_used << str
|
|
704
|
+
return "$(#{str})"
|
|
705
|
+
end
|
|
706
|
+
|
|
707
|
+
# This hash says which of the "CONFIG" variables we should make available
|
|
708
|
+
# as a global variable -- and use it back to output the variables. If non
|
|
709
|
+
# nil, the second part says which name it should have as global variable.
|
|
710
|
+
MKMF_GLOBAL_VARIABLES = {
|
|
711
|
+
"CFLAGS" => nil,
|
|
712
|
+
"CXXFLAGS" => nil,
|
|
713
|
+
"LDFLAGS" => nil,
|
|
714
|
+
"DLDFLAGS" => nil,
|
|
715
|
+
"CPPFLAGS" => nil,
|
|
716
|
+
"LIBS" => nil,
|
|
717
|
+
"LIBRUBYARG" => nil,
|
|
718
|
+
"LOCAL_LIBS" => nil,
|
|
719
|
+
"libs" => nil,
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
|
|
723
|
+
# Takes the config variables, turn them into global variables.
|
|
724
|
+
def config_to_global
|
|
725
|
+
for var,name in MKMF_GLOBAL_VARIABLES
|
|
726
|
+
name = var if name.nil?
|
|
727
|
+
value = MAKEFILE_CONFIG[var].to_s # make sure its a string
|
|
728
|
+
# in case it doesn't exist there...
|
|
729
|
+
# Nice trick to get around quoting...
|
|
730
|
+
block = eval "proc {|x| $#{name} = x}"
|
|
731
|
+
block.call(value)
|
|
732
|
+
end
|
|
733
|
+
$LIBRUBYARG = "" # seems the default in mkmf.rb
|
|
734
|
+
end
|
|
735
|
+
|
|
736
|
+
# Takes the global variables taken from the config, and put them back into
|
|
737
|
+
# the config hash.
|
|
738
|
+
def global_to_config
|
|
739
|
+
for var,name in MKMF_GLOBAL_VARIABLES
|
|
740
|
+
name = var if name.nil?
|
|
741
|
+
value = eval "$#{name}"
|
|
742
|
+
MAKEFILE_CONFIG[var] = value
|
|
743
|
+
end
|
|
744
|
+
end
|
|
745
|
+
|
|
746
|
+
|
|
747
|
+
|
|
748
|
+
# A constant to get a configuration variable
|
|
749
|
+
MAKE_VARIABLE = /\$\((\w+)\)/
|
|
750
|
+
|
|
751
|
+
# List config variables referenced to by the string _str_. If
|
|
752
|
+
# hash is specified, only config variables that are keys of this hash
|
|
753
|
+
# will be listed.
|
|
754
|
+
def subvars(str, hash = nil)
|
|
755
|
+
vars = []
|
|
756
|
+
str.gsub(MAKE_VARIABLE) { |k|
|
|
757
|
+
# we add the key to the list only if it exists, else the
|
|
758
|
+
# environment variable gets overridden by what is written
|
|
759
|
+
# in the Makefile (for $HOME, for instance)
|
|
760
|
+
vars << $1 if ( hash.nil? || hash.key?($1) )
|
|
761
|
+
}
|
|
762
|
+
return vars
|
|
763
|
+
end
|
|
764
|
+
|
|
765
|
+
# A way to deal with compound make variables (that is,
|
|
766
|
+
# make variables that get more than just themselves on the output)
|
|
767
|
+
|
|
768
|
+
COMPOUND_MAKE_VARIABLES = {
|
|
769
|
+
"CFLAGS" => "$(CFLAGS) $(ARCH_FLAG)",
|
|
770
|
+
"DLDFLAGS" => "$(DLDFLAGS) $(ARCH_FLAG)",
|
|
771
|
+
"LIBS" => "$(LIBRUBYARG) $(libs) $(LIBS)",
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
|
|
775
|
+
# Returns the contents of a "compound" variable.
|
|
776
|
+
def compound_var_expand(var, value = nil, hash = MAKEFILE_CONFIG)
|
|
777
|
+
if value.nil?
|
|
778
|
+
value = MAKEFILE_CONFIG[var]
|
|
779
|
+
end
|
|
780
|
+
COMPOUND_MAKE_VARIABLES[var].gsub("$(#{var})",value)
|
|
781
|
+
end
|
|
782
|
+
|
|
783
|
+
|
|
784
|
+
# Returns a string containing all the configuration variables. We
|
|
785
|
+
# use the MAKEFILE_CONFIG for more flexibility in the Makefile: the
|
|
786
|
+
# variables can then be redefined on the make command-line.
|
|
787
|
+
def output_config_variables
|
|
788
|
+
str = ""
|
|
789
|
+
keys = @@config_variables_used.uniq
|
|
790
|
+
global_to_config
|
|
791
|
+
new_keys = []
|
|
792
|
+
begin
|
|
793
|
+
# we merge the new keys with the old
|
|
794
|
+
keys += new_keys
|
|
795
|
+
keys.uniq!
|
|
796
|
+
new_keys = []
|
|
797
|
+
keys.each do |k|
|
|
798
|
+
if MAKEFILE_CONFIG.key? k
|
|
799
|
+
new_keys += subvars(MAKEFILE_CONFIG[k], MAKEFILE_CONFIG)
|
|
800
|
+
end
|
|
801
|
+
if COMPOUND_MAKE_VARIABLES.key? k
|
|
802
|
+
new_keys += subvars(COMPOUND_MAKE_VARIABLES[k], MAKEFILE_CONFIG)
|
|
803
|
+
end
|
|
804
|
+
end
|
|
805
|
+
end until (keys + new_keys).uniq.length == keys.length
|
|
806
|
+
|
|
807
|
+
for var in keys.uniq.sort
|
|
808
|
+
# We output the variable only if it is not empty: makes
|
|
809
|
+
# it a lot easier to modify them from outside...
|
|
810
|
+
if COMPOUND_MAKE_VARIABLES.key?(var)
|
|
811
|
+
str += "#{var}=#{compound_var_expand(var)}\n"
|
|
812
|
+
elsif MAKEFILE_CONFIG[var] =~ /\S/
|
|
813
|
+
str += "#{var}=#{MAKEFILE_CONFIG[var]}\n"
|
|
814
|
+
end
|
|
815
|
+
end
|
|
816
|
+
return str
|
|
817
|
+
end
|
|
818
|
+
|
|
819
|
+
|
|
820
|
+
# This hash contains replacements for basic filesystem functions
|
|
821
|
+
# based on ruby and FileUtils. They are used only if the corresponding
|
|
822
|
+
# element is missing in CONFIG. They also contains some other default
|
|
823
|
+
# values for possibly missing CONFIG keys.
|
|
824
|
+
CONFIG_DEFAULTS = {
|
|
825
|
+
# first, a short for the rest...
|
|
826
|
+
"RB_FILE_UTILS" => "$(RUBY_INSTALL_NAME) -r fileutils",
|
|
827
|
+
"INSTALL_SCRIPT" =>
|
|
828
|
+
"$(RB_FILE_UTILS) -e 'FileUtils.install(ARGV[0],ARGV[1],:mode => 0755)'",
|
|
829
|
+
"INSTALL_DATA" =>
|
|
830
|
+
"$(RB_FILE_UTILS) -e 'FileUtils.install(ARGV[0],ARGV[1],:mode => 0644)'",
|
|
831
|
+
"INSTALL_PROGRAM" => "$(INSTALL_SCRIPT) ",
|
|
832
|
+
"MAKEDIRS" =>
|
|
833
|
+
"$(RB_FILE_UTILS) -e 'FileUtils.makedirs(ARGV)'",
|
|
834
|
+
"RM" =>
|
|
835
|
+
"$(RB_FILE_UTILS) -e 'FileUtils.rm(ARGV)'",
|
|
836
|
+
"RM_PATH" => # a trick to remove a path
|
|
837
|
+
"$(RB_FILE_UTILS) -e 'd = ARGV[0]; begin ;while FileUtils.rmdir d, :verbose=>true; d = File.dirname(d);end; rescue ; end;'",
|
|
838
|
+
"DEFINES" => "",
|
|
839
|
+
"LIBARG" => "-l%s",
|
|
840
|
+
"LIBS_SUP" => "",
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
# This functions checks for missing features in the CONFIG hash and
|
|
844
|
+
# supplements them using the FILE_UTILS_COMMAND hash if necessary.
|
|
845
|
+
def check_missing_features
|
|
846
|
+
CONFIG.delete("INSTALL_SCRIPT") # Not consistent, it's better to use
|
|
847
|
+
# the Fileutils stuff
|
|
848
|
+
for key, val in CONFIG_DEFAULTS
|
|
849
|
+
if CONFIG.key?(key) and CONFIG[key] =~ /\w/
|
|
850
|
+
# everything is fine
|
|
851
|
+
else
|
|
852
|
+
# we supplement the feature.
|
|
853
|
+
MAKEFILE_CONFIG[key] = val
|
|
854
|
+
end
|
|
855
|
+
end
|
|
856
|
+
end
|
|
857
|
+
|
|
858
|
+
# Takes a list of CONFIG variables and returns them joined by spaces.
|
|
859
|
+
def Mkmf2.config_join(*vars)
|
|
860
|
+
return vars.collect { |v|
|
|
861
|
+
Mkmf2.config_var(v)
|
|
862
|
+
}.join(' ')
|
|
863
|
+
end
|
|
864
|
+
|
|
865
|
+
|
|
866
|
+
# Returns the way to represent the dependencies of a rule in the
|
|
867
|
+
# Makefile.
|
|
868
|
+
def Mkmf2.mf_deps
|
|
869
|
+
return " $(@D)"
|
|
870
|
+
end
|
|
871
|
+
|
|
872
|
+
# Returns the way to represent the current target in the Makefile.
|
|
873
|
+
def Mkmf2.mf_target
|
|
874
|
+
return " $@"
|
|
875
|
+
end
|
|
876
|
+
|
|
877
|
+
# A small helper function to write quickly rules, based on a configuration
|
|
878
|
+
# item.
|
|
879
|
+
def Mkmf2.mf_rule(cfg,*args)
|
|
880
|
+
if args.empty?
|
|
881
|
+
return Mkmf2.config_var(cfg) +
|
|
882
|
+
Mkmf2.mf_deps + Mkmf2.mf_target
|
|
883
|
+
else
|
|
884
|
+
return Mkmf2.config_var(cfg) + ' ' + args.join(' ')
|
|
885
|
+
end
|
|
886
|
+
end
|
|
887
|
+
|
|
888
|
+
# This function returns the common build rules for C and C++ files.
|
|
889
|
+
def Mkmf2.common_build_rules
|
|
890
|
+
rules = []
|
|
891
|
+
for ext in Mkmf2.c_files_extensions
|
|
892
|
+
rules << MfRule.new(".#{ext}.#{CONFIG["OBJEXT"]}",
|
|
893
|
+
Mkmf2.config_join("CC",
|
|
894
|
+
"CFLAGS",
|
|
895
|
+
"CPPFLAGS",
|
|
896
|
+
"INCLUDEDIRS",
|
|
897
|
+
"DEFINES") +
|
|
898
|
+
" -c $< #{CONFIG["OUTFLAG"]} $@"
|
|
899
|
+
)
|
|
900
|
+
end
|
|
901
|
+
|
|
902
|
+
# The same, but with C++:
|
|
903
|
+
for ext in Mkmf2.cpp_files_extensions
|
|
904
|
+
rules << MfRule.new(".#{ext}.#{CONFIG["OBJEXT"]}",
|
|
905
|
+
Mkmf2.config_join("CXX",
|
|
906
|
+
"CXXFLAGS",
|
|
907
|
+
"CPPFLAGS",
|
|
908
|
+
"INCLUDEDIRS",
|
|
909
|
+
"DEFINES") +
|
|
910
|
+
" -c $< #{CONFIG["OUTFLAG"]} $@"
|
|
911
|
+
)
|
|
912
|
+
end
|
|
913
|
+
# A simple rule for making directories:
|
|
914
|
+
rules << MfRule.new("%/",
|
|
915
|
+
Mkmf2.config_join("MAKEDIRS") + " $@")
|
|
916
|
+
return rules
|
|
917
|
+
end
|
|
918
|
+
|
|
919
|
+
# Now, the infrastructure for dealing with include and library
|
|
920
|
+
# directories:
|
|
921
|
+
@@include_path = [Mkmf2.config_var("rubylibdir"),
|
|
922
|
+
Mkmf2.config_var("archdir"),
|
|
923
|
+
'.',
|
|
924
|
+
File.join('.','include')
|
|
925
|
+
]
|
|
926
|
+
|
|
927
|
+
|
|
928
|
+
# Adds one or more +paths+ to the current include path.
|
|
929
|
+
def add_include_path(*paths)
|
|
930
|
+
@@include_path += paths.flatten
|
|
931
|
+
end
|
|
932
|
+
|
|
933
|
+
def output_include_path
|
|
934
|
+
return @@include_path.collect {|v|
|
|
935
|
+
"-I#{v}"
|
|
936
|
+
}.join(' ')
|
|
937
|
+
end
|
|
938
|
+
|
|
939
|
+
@@library_path = []
|
|
940
|
+
|
|
941
|
+
# Adds one or more +paths+ to the current library path.
|
|
942
|
+
def add_library_path(*paths)
|
|
943
|
+
@@library_path += paths.flatten
|
|
944
|
+
end
|
|
945
|
+
|
|
946
|
+
def output_library_path
|
|
947
|
+
return @@library_path.collect {|v|
|
|
948
|
+
"-L#{v}"
|
|
949
|
+
}.join(' ')
|
|
950
|
+
end
|
|
951
|
+
|
|
952
|
+
# I know this is bad design, but that's the best I think of for now.
|
|
953
|
+
# This function better be called before using MAKEFILE_CONFIG directly.
|
|
954
|
+
def update_makefile_config
|
|
955
|
+
global_to_config
|
|
956
|
+
setup_paths_variables
|
|
957
|
+
end
|
|
958
|
+
|
|
959
|
+
# Sets up the various variables pertaining to include
|
|
960
|
+
# and library paths.
|
|
961
|
+
def setup_paths_variables
|
|
962
|
+
MAKEFILE_CONFIG["INCLUDEDIRS"] = output_include_path
|
|
963
|
+
MAKEFILE_CONFIG["LIBDIRS"] = output_library_path
|
|
964
|
+
end
|
|
965
|
+
|
|
966
|
+
# A recommandation for line size in the Makefile
|
|
967
|
+
MAKEFILE_LINE_SIZE = 40
|
|
968
|
+
|
|
969
|
+
# Returns a string where all the elements are joined together. The lines
|
|
970
|
+
# will break if they exceed +line_size+, but the elements themselves
|
|
971
|
+
# will not be broken. They will be indented
|
|
972
|
+
def Mkmf2.pretty_print_list(list, indent = 0,
|
|
973
|
+
line_size = MAKEFILE_LINE_SIZE)
|
|
974
|
+
if indent.is_a? String
|
|
975
|
+
indent = indent.length
|
|
976
|
+
end
|
|
977
|
+
lines = []
|
|
978
|
+
for elem in list
|
|
979
|
+
if lines.last.nil? ||
|
|
980
|
+
(lines.last + elem).length > line_size
|
|
981
|
+
lines << elem.dup # necessary to force ruby to create
|
|
982
|
+
else
|
|
983
|
+
lines.last.concat(' ' + elem)
|
|
984
|
+
end
|
|
985
|
+
end
|
|
986
|
+
return lines.join("\\\n#{' ' * indent}")
|
|
987
|
+
end
|
|
988
|
+
|
|
989
|
+
|
|
990
|
+
# Returns the string corresponding to a rule, given by the string +rule+,
|
|
991
|
+
# which can take the following values:
|
|
992
|
+
# +install_data+:: returns the rule for installing a data file to a
|
|
993
|
+
# given place
|
|
994
|
+
# +install_script+:: the rule for installing code at a given place
|
|
995
|
+
# +remove+:: to remove files
|
|
996
|
+
# +directory+:: to create a directory
|
|
997
|
+
# +build_library+:: to build a library; in that case, the first argument
|
|
998
|
+
# is the name of the target, and the ones after
|
|
999
|
+
# the objects.
|
|
1000
|
+
#
|
|
1001
|
+
# the optional arguments are the arguments to the rule, if they exist. Else,
|
|
1002
|
+
# they default to $(@D) $@ (or something like that).
|
|
1003
|
+
|
|
1004
|
+
def Mkmf2.rule(rule, *args)
|
|
1005
|
+
case rule
|
|
1006
|
+
when 'install_data'
|
|
1007
|
+
return Mkmf2.mf_rule("INSTALL_DATA",args)
|
|
1008
|
+
when 'install_script'
|
|
1009
|
+
return Mkmf2.mf_rule("INSTALL_SCRIPT",args)
|
|
1010
|
+
when 'install_bin'
|
|
1011
|
+
return Mkmf2.mf_rule("INSTALL_PROGRAM",args)
|
|
1012
|
+
when 'remove'
|
|
1013
|
+
return "-" + Mkmf2.mf_rule("RM",args)
|
|
1014
|
+
when 'remove_path'
|
|
1015
|
+
return "-" + Mkmf2.mf_rule("RM_PATH", args)
|
|
1016
|
+
when 'directory' # to create a directory
|
|
1017
|
+
return Mkmf2.mf_rule("MAKEDIRS", args)
|
|
1018
|
+
when 'build_library'
|
|
1019
|
+
return Mkmf2.mf_rule("LDSHARED",
|
|
1020
|
+
Mkmf2.config_join("DLDFLAGS",
|
|
1021
|
+
"LIBDIRS"),
|
|
1022
|
+
CONFIG["OUTFLAG"],
|
|
1023
|
+
"$@", # the target,
|
|
1024
|
+
args, # and the source
|
|
1025
|
+
# The libraries should better come in the end,
|
|
1026
|
+
# since for instance the standard linux ld
|
|
1027
|
+
# does only link with the symbols that have been
|
|
1028
|
+
# reported missing in the previous files.
|
|
1029
|
+
Mkmf2.config_join("LIBRUBYARG_SHARED",
|
|
1030
|
+
# we shouldn't forget this one !!
|
|
1031
|
+
"LOCAL_LIBS",
|
|
1032
|
+
"LIBS",
|
|
1033
|
+
# and then, the global libraries
|
|
1034
|
+
# that have been added using
|
|
1035
|
+
# have_library
|
|
1036
|
+
"LIBS_SUP")
|
|
1037
|
+
)
|
|
1038
|
+
end
|
|
1039
|
+
end
|
|
1040
|
+
|
|
1041
|
+
@@directories = {}
|
|
1042
|
+
# Register a directory that we might need to create. Make sure that
|
|
1043
|
+
# the rules don't appear twice.
|
|
1044
|
+
def Mkmf2.register_dir(dir)
|
|
1045
|
+
if ! @@directories.key?(dir)
|
|
1046
|
+
@@directories[dir] = true
|
|
1047
|
+
end
|
|
1048
|
+
end
|
|
1049
|
+
|
|
1050
|
+
# Return the rules to create the necessary directories
|
|
1051
|
+
def directory_rules
|
|
1052
|
+
rules = []
|
|
1053
|
+
for dir in @@directories.keys
|
|
1054
|
+
rules << MfRule.new(dir, Mkmf2.rule('directory',dir))
|
|
1055
|
+
end
|
|
1056
|
+
return rules
|
|
1057
|
+
end
|
|
1058
|
+
|
|
1059
|
+
|
|
1060
|
+
# A small helper function to extract the install directory name
|
|
1061
|
+
# for one file. +file+ is the file, +install_dir+ where we want to
|
|
1062
|
+
# install it. This should take care of messy dots.
|
|
1063
|
+
def Mkmf2.dest_dir(file, install_dir)
|
|
1064
|
+
dir = File::dirname(file)
|
|
1065
|
+
if dir == "."
|
|
1066
|
+
return install_dir
|
|
1067
|
+
else
|
|
1068
|
+
return File.join(install_dir,dir)
|
|
1069
|
+
end
|
|
1070
|
+
end
|
|
1071
|
+
|
|
1072
|
+
# A helper function for MfEntity instances that will have to install
|
|
1073
|
+
# files into directories.
|
|
1074
|
+
# +rule+:: the rule to use, see Mkmf2::rule
|
|
1075
|
+
# +install_path+:: the installation path
|
|
1076
|
+
# +files+:: a hash containing original -> destination pairs.
|
|
1077
|
+
|
|
1078
|
+
def Mkmf2.install_files(rule, install_path,files)
|
|
1079
|
+
rules = []
|
|
1080
|
+
files.each do |k,v|
|
|
1081
|
+
destdir = Mkmf2.dest_dir(v, install_path)
|
|
1082
|
+
Mkmf2.register_dir(destdir)
|
|
1083
|
+
rules.push(MfRule.new(File.join(install_path,v),
|
|
1084
|
+
Mkmf2::rule(rule, k,
|
|
1085
|
+
File.join(install_path,v)),
|
|
1086
|
+
[k,destdir]))
|
|
1087
|
+
# depends on both the file
|
|
1088
|
+
# that will be installed and the directory where to install it.
|
|
1089
|
+
end
|
|
1090
|
+
|
|
1091
|
+
return rules
|
|
1092
|
+
end
|
|
1093
|
+
|
|
1094
|
+
# The companion of install_files, returning a list of strings
|
|
1095
|
+
# rather than MfRules. Bascially behaves the same way. It is probably
|
|
1096
|
+
# a better thing to use this function now.
|
|
1097
|
+
def Mkmf2.install_files_rules(rule, install_path,files)
|
|
1098
|
+
rules = []
|
|
1099
|
+
files.each do |k,v|
|
|
1100
|
+
dir = File::dirname(v)
|
|
1101
|
+
Mkmf2.register_dir(Mkmf2.dest_dir(v,install_path))
|
|
1102
|
+
rules.push Mkmf2::rule(rule, k, File.join(install_path,v))
|
|
1103
|
+
|
|
1104
|
+
# depends on both the file
|
|
1105
|
+
# that will be installed and the directory where to install it.
|
|
1106
|
+
end
|
|
1107
|
+
|
|
1108
|
+
return rules
|
|
1109
|
+
end
|
|
1110
|
+
|
|
1111
|
+
# Small helper function for write_makefile. +target+ is
|
|
1112
|
+
# a hash containing a "deps" array and a "rules" array
|
|
1113
|
+
# which are created in case of need.
|
|
1114
|
+
def unwrap_rules(target, source)
|
|
1115
|
+
# we first make sure that the keys exist, even if we don't
|
|
1116
|
+
# have anything to append to them.
|
|
1117
|
+
if ! target.has_key? "deps"
|
|
1118
|
+
target["deps"] = []
|
|
1119
|
+
end
|
|
1120
|
+
if ! target.has_key? "rules"
|
|
1121
|
+
target["rules"] = []
|
|
1122
|
+
end
|
|
1123
|
+
|
|
1124
|
+
return if source.empty?
|
|
1125
|
+
target["deps"] << source.shift
|
|
1126
|
+
target["rules"] += source
|
|
1127
|
+
end
|
|
1128
|
+
|
|
1129
|
+
# Writes the Makefile using @@entities -- and others...
|
|
1130
|
+
def write_makefile(file_name = "Makefile")
|
|
1131
|
+
puts "Writing #{file_name}"
|
|
1132
|
+
|
|
1133
|
+
install = {}
|
|
1134
|
+
uninstall = {}
|
|
1135
|
+
build = {}
|
|
1136
|
+
clean = {}
|
|
1137
|
+
vars = []
|
|
1138
|
+
|
|
1139
|
+
|
|
1140
|
+
|
|
1141
|
+
for entity in @@entities
|
|
1142
|
+
t = entity.install_rules
|
|
1143
|
+
unwrap_rules(install,t)
|
|
1144
|
+
|
|
1145
|
+
t = entity.uninstall_rules
|
|
1146
|
+
unwrap_rules(uninstall,t)
|
|
1147
|
+
|
|
1148
|
+
t = entity.build_rules
|
|
1149
|
+
unwrap_rules(build,t)
|
|
1150
|
+
|
|
1151
|
+
t = entity.clean_rules
|
|
1152
|
+
unwrap_rules(clean,t)
|
|
1153
|
+
|
|
1154
|
+
vars << entity.variables
|
|
1155
|
+
end
|
|
1156
|
+
|
|
1157
|
+
# Common rules:
|
|
1158
|
+
common = Mkmf2.common_build_rules()
|
|
1159
|
+
|
|
1160
|
+
# Setup the path variables:
|
|
1161
|
+
setup_paths_variables
|
|
1162
|
+
dir_rules = directory_rules()
|
|
1163
|
+
|
|
1164
|
+
# OK, now, everything is prepared, we just need to create the
|
|
1165
|
+
# makefile and output everything into it...
|
|
1166
|
+
|
|
1167
|
+
f = open(file_name, File::WRONLY|File::CREAT|File::TRUNC)
|
|
1168
|
+
|
|
1169
|
+
|
|
1170
|
+
# First, the variables in use:
|
|
1171
|
+
f.puts "# Configurations variables, from rbconfig.rb"
|
|
1172
|
+
f.puts output_config_variables
|
|
1173
|
+
|
|
1174
|
+
# build has to be the first target so that simply
|
|
1175
|
+
# invoking make does the building, but not the installing.
|
|
1176
|
+
# now, the main rules
|
|
1177
|
+
f.puts "\n\n# main rules"
|
|
1178
|
+
# we force the dependence on build for install so that
|
|
1179
|
+
# ruby library files don't get installed before the c code is
|
|
1180
|
+
# compiled...
|
|
1181
|
+
# build is output first so that invoking make without
|
|
1182
|
+
# arguments builds.
|
|
1183
|
+
f.print MfRule.new("build", nil, build["deps"]).to_s
|
|
1184
|
+
f.print MfRule.new("install", nil, ["build"] + install["deps"]).to_s
|
|
1185
|
+
f.print MfRule.new("uninstall", nil, uninstall["deps"]).to_s
|
|
1186
|
+
f.print MfRule.new("clean",
|
|
1187
|
+
[Mkmf2.rule('remove',"**/*~")], # remove archive files
|
|
1188
|
+
# by default in the clean target.
|
|
1189
|
+
clean["deps"]).to_s
|
|
1190
|
+
|
|
1191
|
+
# Add a distclean rule, to make debuild happy.
|
|
1192
|
+
f.print <<"EOR"
|
|
1193
|
+
distclean: clean
|
|
1194
|
+
\t@-$(RM) Makefile extconf.h conftest.* mkmf2.log
|
|
1195
|
+
\t@-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
|
|
1196
|
+
EOR
|
|
1197
|
+
|
|
1198
|
+
# Phony targets:
|
|
1199
|
+
f.puts ".PHONY: build install uninstall"
|
|
1200
|
+
|
|
1201
|
+
f.puts "\n\n# Common rules:"
|
|
1202
|
+
common.each {|v|
|
|
1203
|
+
f.print v.to_s
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
|
|
1207
|
+
# We write the variables:
|
|
1208
|
+
f.puts "\n\n# entities-dependent variables"
|
|
1209
|
+
for v in vars
|
|
1210
|
+
v.each do |k,v|
|
|
1211
|
+
f.print "#{k}=#{v}\n"
|
|
1212
|
+
end
|
|
1213
|
+
end
|
|
1214
|
+
|
|
1215
|
+
f.puts "\n\n# Rules to make directories"
|
|
1216
|
+
|
|
1217
|
+
# directory rules
|
|
1218
|
+
for rule in dir_rules
|
|
1219
|
+
f.print rule.to_s
|
|
1220
|
+
end
|
|
1221
|
+
|
|
1222
|
+
f.puts "\n\n# entities-dependent rules"
|
|
1223
|
+
# We write the rules
|
|
1224
|
+
for rule in (install['rules'] +
|
|
1225
|
+
uninstall['rules'] +
|
|
1226
|
+
build['rules'] + clean['rules'])
|
|
1227
|
+
f.print rule.to_s
|
|
1228
|
+
end
|
|
1229
|
+
|
|
1230
|
+
if @@user_rules.length > 0
|
|
1231
|
+
f.puts "\n\n# User-defined rules"
|
|
1232
|
+
for rule in @@user_rules
|
|
1233
|
+
f.puts rule.to_s
|
|
1234
|
+
end
|
|
1235
|
+
end
|
|
1236
|
+
|
|
1237
|
+
|
|
1238
|
+
f.close # not necessary, but good practice ;-) ??
|
|
1239
|
+
|
|
1240
|
+
end
|
|
1241
|
+
|
|
1242
|
+
# Adds a custom rule to the Makefile. If only the first argument
|
|
1243
|
+
# is specified, it is written as is to the Makefile. If at least the
|
|
1244
|
+
# second or the third is non-nil, a MfRule is created with the arguments
|
|
1245
|
+
# and written to the Makefile.
|
|
1246
|
+
def custom_rule(str, rule = nil, deps = nil)
|
|
1247
|
+
if rule || deps
|
|
1248
|
+
@@user_rules << MfRule.new(str, rule, deps)
|
|
1249
|
+
else
|
|
1250
|
+
@@user_rules << str
|
|
1251
|
+
end
|
|
1252
|
+
end
|
|
1253
|
+
|
|
1254
|
+
# *The* compatibility function with the mkmf.rb !
|
|
1255
|
+
def create_makefile(target)
|
|
1256
|
+
declare_library(File.dirname(target))
|
|
1257
|
+
declare_binary_library(target, "**/*.c")
|
|
1258
|
+
|
|
1259
|
+
write_makefile
|
|
1260
|
+
end
|
|
1261
|
+
|
|
1262
|
+
# A function to ease the task of producing several libraries from the
|
|
1263
|
+
# same source tree. It sets up a library context for one directory,
|
|
1264
|
+
# adding it to the include path, and taking care of the files in:
|
|
1265
|
+
# +lib/+:: the ruby library files;
|
|
1266
|
+
# +include/+:: the include files
|
|
1267
|
+
#
|
|
1268
|
+
# +dir+ is the directory in the source, +target_dir+ the base directory
|
|
1269
|
+
# for target files. It is pretty rudimentary, but should do the job
|
|
1270
|
+
# for many cases (and especially Tioga ;-) !). +name+ is the name
|
|
1271
|
+
# of the binary library. If nil, doesn't try to build a binary library.
|
|
1272
|
+
# +include_dir+ is the target name for includes. If +nil+, doesn't
|
|
1273
|
+
# try to install them.
|
|
1274
|
+
#
|
|
1275
|
+
# You can use either the return value or a block to change somehow the
|
|
1276
|
+
# behavior of the different objects produced (like adding a binary library
|
|
1277
|
+
# for instance).
|
|
1278
|
+
|
|
1279
|
+
def setup_dir(dir, target_dir, bin_name = nil,
|
|
1280
|
+
include_dir = nil)
|
|
1281
|
+
add_include_path(dir, File.join(dir, 'include'))
|
|
1282
|
+
|
|
1283
|
+
lib = declare_library(target_dir, "#{dir}/lib/**/*.rb")
|
|
1284
|
+
binlib = declare_binary_library(bin_name,
|
|
1285
|
+
"#{dir}/**/*.c") if ! bin_name.nil?
|
|
1286
|
+
include = declare_includes(include_dir,
|
|
1287
|
+
"#{dir}/include/**/*.h") if ! include_dir.nil?
|
|
1288
|
+
yield lib, binlib, include if block_given?
|
|
1289
|
+
[lib, binlib, include]
|
|
1290
|
+
end
|
|
1291
|
+
|
|
1292
|
+
# the module variable that will hold the command-line arguments:
|
|
1293
|
+
# even with a similar name, the contents of this variable will
|
|
1294
|
+
# be quite different from the old $configure_args
|
|
1295
|
+
@@configure_args = {}
|
|
1296
|
+
|
|
1297
|
+
# Parses command-line arguments, wiping the ones that we understood.
|
|
1298
|
+
def parse_cmdline
|
|
1299
|
+
$*.delete_if do |arg|
|
|
1300
|
+
if arg =~ /^--(.*)/ # does look like a command-line argument...
|
|
1301
|
+
case $1
|
|
1302
|
+
when "local" # installation to sitedir
|
|
1303
|
+
Mkmf2.set_model("local")
|
|
1304
|
+
true
|
|
1305
|
+
when "dist"
|
|
1306
|
+
Mkmf2.set_model("dist")
|
|
1307
|
+
true
|
|
1308
|
+
when "home"
|
|
1309
|
+
Mkmf2.set_model("home")
|
|
1310
|
+
true
|
|
1311
|
+
when /^--with(.*)/ # this is my understanding of the
|
|
1312
|
+
# with-config stuff. It is a complete rewrite, I don't like
|
|
1313
|
+
# much the old code
|
|
1314
|
+
rhs = $1 # right-hand side
|
|
1315
|
+
case rhs
|
|
1316
|
+
when /-([\w-]+)=(.*)/
|
|
1317
|
+
@@configure_args[$1] = $2
|
|
1318
|
+
when /out-([\w-]+)$/
|
|
1319
|
+
@@configure_args[$1] = false
|
|
1320
|
+
when /-([\w-]+)$/
|
|
1321
|
+
@@configure_args[$1] = true
|
|
1322
|
+
else
|
|
1323
|
+
raise "Argument #{arg} not understood"
|
|
1324
|
+
end
|
|
1325
|
+
else
|
|
1326
|
+
false
|
|
1327
|
+
end
|
|
1328
|
+
else
|
|
1329
|
+
false
|
|
1330
|
+
end
|
|
1331
|
+
end
|
|
1332
|
+
end
|
|
1333
|
+
|
|
1334
|
+
# This function is a try at reproducing the functionnality of the
|
|
1335
|
+
# old mkmf.rb's dir_config. It is not a copy, and might not work
|
|
1336
|
+
# well in all situations. Basically, if --with-target-dir has been
|
|
1337
|
+
# specified, use dir/include dir/lib. If --with-target-(include|lib)
|
|
1338
|
+
# have been specified, use them !
|
|
1339
|
+
def dir_config(target)
|
|
1340
|
+
ldir = nil
|
|
1341
|
+
idir = nil
|
|
1342
|
+
if @@configure_args.key?("#{target}-lib")
|
|
1343
|
+
ldir = @@configure_args["#{target}-lib"]
|
|
1344
|
+
elsif @@configure_args.key?("#{target}-dir")
|
|
1345
|
+
ldir = File::join(@@configure_args["#{target}-dir"], "lib")
|
|
1346
|
+
end
|
|
1347
|
+
if ldir
|
|
1348
|
+
add_library_path(ldir.split(File::PATH_SEPARATOR))
|
|
1349
|
+
end
|
|
1350
|
+
|
|
1351
|
+
if @@configure_args.key?("#{target}-include")
|
|
1352
|
+
idir = @@configure_args["#{target}-include"]
|
|
1353
|
+
elsif @@configure_args.key?("#{target}-dir")
|
|
1354
|
+
idir = File::join(@@configure_args["#{target}-dir"], "include")
|
|
1355
|
+
end
|
|
1356
|
+
if idir
|
|
1357
|
+
add_include_path(idir.split(File::PATH_SEPARATOR))
|
|
1358
|
+
end
|
|
1359
|
+
return [idir, ldir]
|
|
1360
|
+
end
|
|
1361
|
+
|
|
1362
|
+
###########################################################################
|
|
1363
|
+
# This module is copied verbatim from the old mkmf.rb code. It comes dead #
|
|
1364
|
+
# useful for logging things. I hope it will not cause licence conflicts. #
|
|
1365
|
+
###########################################################################
|
|
1366
|
+
|
|
1367
|
+
module Logging
|
|
1368
|
+
@log = nil
|
|
1369
|
+
@logfile = 'mkmf2.log'
|
|
1370
|
+
@orgerr = $stderr.dup
|
|
1371
|
+
@orgout = $stdout.dup
|
|
1372
|
+
@postpone = 0
|
|
1373
|
+
|
|
1374
|
+
def self::open
|
|
1375
|
+
@log ||= File::open(@logfile, 'w')
|
|
1376
|
+
@log.sync = true
|
|
1377
|
+
$stderr.reopen(@log)
|
|
1378
|
+
$stdout.reopen(@log)
|
|
1379
|
+
yield
|
|
1380
|
+
ensure
|
|
1381
|
+
$stderr.reopen(@orgerr)
|
|
1382
|
+
$stdout.reopen(@orgout)
|
|
1383
|
+
end
|
|
1384
|
+
|
|
1385
|
+
def self::message(*s)
|
|
1386
|
+
@log ||= File::open(@logfile, 'w')
|
|
1387
|
+
@log.sync = true
|
|
1388
|
+
@log.printf(*s)
|
|
1389
|
+
end
|
|
1390
|
+
|
|
1391
|
+
def self::logfile file
|
|
1392
|
+
@logfile = file
|
|
1393
|
+
if @log and not @log.closed?
|
|
1394
|
+
@log.flush
|
|
1395
|
+
@log.close
|
|
1396
|
+
@log = nil
|
|
1397
|
+
end
|
|
1398
|
+
end
|
|
1399
|
+
|
|
1400
|
+
def self::postpone
|
|
1401
|
+
tmplog = "mkmftmp#{@postpone += 1}.log"
|
|
1402
|
+
open do
|
|
1403
|
+
log, *save = @log, @logfile, @orgout, @orgerr
|
|
1404
|
+
@log, @logfile, @orgout, @orgerr = nil, tmplog, log, log
|
|
1405
|
+
begin
|
|
1406
|
+
log.print(open {yield})
|
|
1407
|
+
@log.close
|
|
1408
|
+
File::open(tmplog) {|t| FileUtils.copy_stream(t, log)}
|
|
1409
|
+
ensure
|
|
1410
|
+
@log, @logfile, @orgout, @orgerr = log, *save
|
|
1411
|
+
@postpone -= 1
|
|
1412
|
+
rm_f tmplog
|
|
1413
|
+
end
|
|
1414
|
+
end
|
|
1415
|
+
end
|
|
1416
|
+
end
|
|
1417
|
+
|
|
1418
|
+
# Also from old mkmf.rb
|
|
1419
|
+
CONFTEST_C = "conftest.c"
|
|
1420
|
+
|
|
1421
|
+
def xsystem(command)
|
|
1422
|
+
Logging::open do
|
|
1423
|
+
puts command.quote
|
|
1424
|
+
system(command)
|
|
1425
|
+
end
|
|
1426
|
+
end
|
|
1427
|
+
|
|
1428
|
+
# Also from old mkmf.rb
|
|
1429
|
+
def log_src(src)
|
|
1430
|
+
Logging::message <<"EOM", src
|
|
1431
|
+
checked program was:
|
|
1432
|
+
/* begin */
|
|
1433
|
+
%s/* end */
|
|
1434
|
+
|
|
1435
|
+
EOM
|
|
1436
|
+
end
|
|
1437
|
+
|
|
1438
|
+
# Also from old mkmf.rb
|
|
1439
|
+
def create_tmpsrc(src)
|
|
1440
|
+
src = yield(src) if block_given?
|
|
1441
|
+
src = src.sub(/[^\n]\z/, "\\&\n")
|
|
1442
|
+
open(CONFTEST_C, "wb") do |cfile|
|
|
1443
|
+
cfile.print src
|
|
1444
|
+
end
|
|
1445
|
+
src
|
|
1446
|
+
end
|
|
1447
|
+
|
|
1448
|
+
# Also from old mkmf.rb
|
|
1449
|
+
def try_do(src, command, &b)
|
|
1450
|
+
src = create_tmpsrc(src, &b)
|
|
1451
|
+
xsystem(command)
|
|
1452
|
+
ensure
|
|
1453
|
+
log_src(src)
|
|
1454
|
+
end
|
|
1455
|
+
|
|
1456
|
+
# Also from old mkmf.rb
|
|
1457
|
+
def checking_for(m, fmt = nil)
|
|
1458
|
+
f = caller[0][/in `(.*)'$/, 1] and f << ": " #` for vim
|
|
1459
|
+
m = "checking for #{m}... "
|
|
1460
|
+
print m
|
|
1461
|
+
a = r = nil
|
|
1462
|
+
Logging::postpone do
|
|
1463
|
+
r = yield
|
|
1464
|
+
a = (fmt ? fmt % r : r ? "yes" : "no") << "\n"
|
|
1465
|
+
"#{f}#{m}-------------------- #{a}\n"
|
|
1466
|
+
end
|
|
1467
|
+
puts a
|
|
1468
|
+
$stdout.flush
|
|
1469
|
+
Logging::message "--------------------\n\n"
|
|
1470
|
+
r
|
|
1471
|
+
end
|
|
1472
|
+
|
|
1473
|
+
# also taken straight from mkmf.rb
|
|
1474
|
+
def rm_f(*files)
|
|
1475
|
+
FileUtils.rm_f(Dir[files.join("\0")])
|
|
1476
|
+
end
|
|
1477
|
+
|
|
1478
|
+
# A small wrapper around Config::expand which diminishes the size of the code
|
|
1479
|
+
# and makes sure the MAKEFILE_CONFIG hash is updated.
|
|
1480
|
+
def expand_vars(str)
|
|
1481
|
+
update_makefile_config
|
|
1482
|
+
string = Config::expand(str,MAKEFILE_CONFIG)
|
|
1483
|
+
# then, we need to turn all the remaining $(THING) into $THING, so that
|
|
1484
|
+
# the shell doesn't spawn subshells ?
|
|
1485
|
+
return string.gsub(/\$\((\w+)\)/) { "$#$1" }
|
|
1486
|
+
end
|
|
1487
|
+
|
|
1488
|
+
# Add defines to the build
|
|
1489
|
+
def add_define(d)
|
|
1490
|
+
MAKEFILE_CONFIG["DEFINES"] +=
|
|
1491
|
+
" -D_#{d}"
|
|
1492
|
+
end
|
|
1493
|
+
|
|
1494
|
+
# This is a compatibility function with the previous mkmf.rb. It does check
|
|
1495
|
+
# for the presence of a header in the current include directories. If found,
|
|
1496
|
+
# it returns true and sets the define HAVE_...
|
|
1497
|
+
def have_header(header, &b)
|
|
1498
|
+
checking_for header do
|
|
1499
|
+
if try_do("#include <#{header}>",
|
|
1500
|
+
expand_vars("$(CPP) $(INCLUDEDIRS) " \
|
|
1501
|
+
"$(CPPFLAGS) $(CFLAGS) $(DEFINES) "\
|
|
1502
|
+
"#{CONFTEST_C} $(CPPOUTFILE)"),&b)
|
|
1503
|
+
add_define("HAVE_#{header.sanitize}")
|
|
1504
|
+
true
|
|
1505
|
+
else
|
|
1506
|
+
false
|
|
1507
|
+
end
|
|
1508
|
+
end
|
|
1509
|
+
ensure
|
|
1510
|
+
rm_f("conftest*")
|
|
1511
|
+
end
|
|
1512
|
+
|
|
1513
|
+
# The same as have_header, but fails if the header is not found...
|
|
1514
|
+
def require_header(header, message = nil ,&b)
|
|
1515
|
+
if ! have_header(header,&b)
|
|
1516
|
+
if message
|
|
1517
|
+
puts message
|
|
1518
|
+
end
|
|
1519
|
+
raise "Header #{header} not found, stopping\n"
|
|
1520
|
+
end
|
|
1521
|
+
end
|
|
1522
|
+
|
|
1523
|
+
def mkmf2_init
|
|
1524
|
+
check_missing_features
|
|
1525
|
+
parse_cmdline
|
|
1526
|
+
setup_model
|
|
1527
|
+
config_to_global
|
|
1528
|
+
end
|
|
1529
|
+
|
|
1530
|
+
def headers(header)
|
|
1531
|
+
headers = ""
|
|
1532
|
+
if header
|
|
1533
|
+
if header.is_a?(Array)
|
|
1534
|
+
header.each {|h|
|
|
1535
|
+
headers += "#include <#{h.to_s}>\n"
|
|
1536
|
+
}
|
|
1537
|
+
else
|
|
1538
|
+
headers += "#include <#{header.to_s}>\n"
|
|
1539
|
+
end
|
|
1540
|
+
end
|
|
1541
|
+
return headers
|
|
1542
|
+
end
|
|
1543
|
+
|
|
1544
|
+
# Tries to link the given code with the extra flags given
|
|
1545
|
+
def try_link(code, extras = "")
|
|
1546
|
+
return try_do(code,
|
|
1547
|
+
expand_vars("$(CC) $(OUTFLAG)conftest $(INCFLAGS) " +
|
|
1548
|
+
"#{CONFTEST_C} " +
|
|
1549
|
+
" -I$(hdrdir) $(CPPFLAGS) $(CFLAGS) $(src)" +
|
|
1550
|
+
" $(LIBPATH) $(LDFLAGS) $(ARCH_FLAG) " +
|
|
1551
|
+
" $(LOCAL_LIBS) $(LIBS) $(LIBS_SUP) #{extras}"
|
|
1552
|
+
)
|
|
1553
|
+
)
|
|
1554
|
+
ensure
|
|
1555
|
+
rm_f("conftest*")
|
|
1556
|
+
end
|
|
1557
|
+
|
|
1558
|
+
def try_func(func, extra, h)
|
|
1559
|
+
headers = headers(h)
|
|
1560
|
+
|
|
1561
|
+
try_link(<<"SRC", extra) or try_link(<<"SRC", extra)
|
|
1562
|
+
#{headers}
|
|
1563
|
+
/*top*/
|
|
1564
|
+
int main() { return 0; }
|
|
1565
|
+
int t() { #{func}(); return 0; }
|
|
1566
|
+
SRC
|
|
1567
|
+
#{headers}
|
|
1568
|
+
/*top*/
|
|
1569
|
+
int main() { return 0; }
|
|
1570
|
+
int t() { void ((*volatile p)()); p = (void ((*)()))#{func}; return 0; }
|
|
1571
|
+
SRC
|
|
1572
|
+
end
|
|
1573
|
+
|
|
1574
|
+
|
|
1575
|
+
# Compatibility function from mkmf.rb. Checks if the compiler
|
|
1576
|
+
# can find the given function in the given library. If the function
|
|
1577
|
+
# is not given, we look for main but it's definitely not a good idea.
|
|
1578
|
+
# +header+ is a header that can be included to get the prototype for
|
|
1579
|
+
# this function. It can possibly be an array, in which case it is
|
|
1580
|
+
# interpreted as a list of headers that should be included.
|
|
1581
|
+
|
|
1582
|
+
def have_library(lib, func = nil, header=nil, &b)
|
|
1583
|
+
if func.nil?
|
|
1584
|
+
func = "main"
|
|
1585
|
+
end
|
|
1586
|
+
libarg = "#{MAKEFILE_CONFIG["LIBARG"]%lib}"
|
|
1587
|
+
checking_for "#{func}() in #{libarg}" do
|
|
1588
|
+
if try_func(func, libarg, header)
|
|
1589
|
+
add_define("HAVE_#{lib.sanitize}")
|
|
1590
|
+
MAKEFILE_CONFIG["LIBS_SUP"] += " #{libarg}"
|
|
1591
|
+
true
|
|
1592
|
+
else
|
|
1593
|
+
false
|
|
1594
|
+
end
|
|
1595
|
+
end
|
|
1596
|
+
end
|
|
1597
|
+
|
|
1598
|
+
# Returns true if a function could be found
|
|
1599
|
+
def have_func(func, header = nil)
|
|
1600
|
+
checking_for "#{func}() " do
|
|
1601
|
+
if try_func(func, "", header)
|
|
1602
|
+
add_define("HAVE_#{func.sanitize}")
|
|
1603
|
+
true
|
|
1604
|
+
else
|
|
1605
|
+
false
|
|
1606
|
+
end
|
|
1607
|
+
end
|
|
1608
|
+
end
|
|
1609
|
+
end
|
|
1610
|
+
|
|
1611
|
+
include Mkmf2
|
|
1612
|
+
mkmf2_init
|