software_smithy 1.6.3 → 1.6.4

Sign up to get free protection for your applications and to get access to all the features.
data/bin/smithy CHANGED
@@ -58,7 +58,7 @@ require 'active_support/core_ext/string'
58
58
  require 'active_support/inflector'
59
59
 
60
60
  # require 'debugger' #XXX
61
- # require 'pp' #XXX
61
+ # require 'awesome_print' #XXX
62
62
  # require 'pry'
63
63
  # require 'pry-doc'
64
64
 
@@ -215,7 +215,7 @@ module Smithy
215
215
  d.write(@content)
216
216
  d.close
217
217
  end
218
- puts "updated ".rjust(12).bright + description_output
218
+ puts "updated ".rjust(12) + description_output
219
219
 
220
220
  #TODO update category list
221
221
 
@@ -269,7 +269,7 @@ module Smithy
269
269
  end
270
270
  end
271
271
 
272
- puts "updated ".rjust(12).bright + output
272
+ puts "updated ".rjust(12) + output
273
273
  end
274
274
 
275
275
  end
@@ -79,10 +79,10 @@ module Smithy
79
79
  raise "curl cannot be located, without it files cannot be downloaded" if curl.blank?
80
80
 
81
81
  if downloaded?
82
- puts "downloaded ".rjust(12).color(:green).bright + downloaded_file_path
82
+ puts "downloaded ".rjust(12).color(:green) + downloaded_file_path
83
83
  return true
84
84
  else
85
- puts "download ".rjust(12).color(:green).bright + url
85
+ puts "download ".rjust(12).color(:green) + url
86
86
  end
87
87
 
88
88
  args = ['-qf#L']
@@ -38,28 +38,28 @@
38
38
  module Smithy
39
39
  FILE_NOTICE_COLUMNS = 12
40
40
  def notice_create(file)
41
- puts "create ".rjust(12).color(:green).bright + file
41
+ puts "create ".rjust(12).color(:green) + file
42
42
  end
43
43
  def notice_exist(file)
44
- puts "exists ".rjust(12).color(:blue).bright + file
44
+ puts "exists ".rjust(12).color(:blue) + file
45
45
  end
46
46
  def notice_using(file)
47
- puts "using ".rjust(12).color(:blue).bright + file
47
+ puts "using ".rjust(12).color(:blue) + file
48
48
  end
49
49
  def notice_link(file1, file2)
50
- puts "link ".rjust(12).bright + file1 + " -> " + file2
50
+ puts "link ".rjust(12) + file1 + " -> " + file2
51
51
  end
52
52
  def notice_identical(file)
53
- puts "identical ".rjust(12).color(:blue).bright + file
53
+ puts "identical ".rjust(12).color(:blue) + file
54
54
  end
55
55
  def notice_conflict(file)
56
- puts "conflict ".rjust(12).color(:red).bright + file
56
+ puts "conflict ".rjust(12).color(:red) + file
57
57
  end
58
58
  def notice_force(file)
59
- puts "force ".rjust(12).color(:yellow).bright + file
59
+ puts "force ".rjust(12).color(:yellow) + file
60
60
  end
61
61
  def notice_skip(file)
62
- puts "skip ".rjust(12).bright + file
62
+ puts "skip ".rjust(12) + file
63
63
  end
64
64
 
65
65
  class FileOperations
@@ -26,12 +26,14 @@ module Smithy
26
26
 
27
27
  # setup module environment by purging and loading only what's needed
28
28
  def initialize_modules
29
- @modules = nil # re-evaluate modules block
30
- @module_commands = nil # re-evaluate module_commands block
31
29
  @module_setup = ""
30
+ @module_commands = @modules = nil # re-evaluates the blocks
31
+
32
32
  raise "please specify modules OR modules_command, not both" if modules.present? && module_commands.present?
33
33
  raise "module_commands method must return an array" if module_commands.present? && module_commands.class != Array
34
+
34
35
  if ENV["MODULESHOME"]
36
+ @module_commands = @modules = nil # re-evaluates the blocks
35
37
  @modulecmd = "modulecmd sh"
36
38
  @modulecmd = "#{ENV["MODULESHOME"]}/bin/modulecmd sh" if File.exists?("#{ENV["MODULESHOME"]}/bin/modulecmd")
37
39
  if modules.present?
@@ -122,9 +124,8 @@ module Smithy
122
124
  end
123
125
 
124
126
  def module_is_available?(mod)
125
- return false unless @modulecmd
126
-
127
- if `#{@modulecmd} avail #{mod} 2>&1` =~ /#{mod}/
127
+ module_avail = `#{module_setup} #{@modulecmd} avail #{mod} 2>&1`
128
+ if module_avail =~ /#{mod}/
128
129
  true
129
130
  else
130
131
  false
@@ -133,7 +134,7 @@ module Smithy
133
134
 
134
135
  def module_environment_variable(mod, var)
135
136
  module_display = `#{module_setup} #{@modulecmd} display #{mod} 2>&1`
136
- if module_display =~ /(\S+)\s+#{var}\s+(.*)$/
137
+ if module_display =~ /^(\S+)\s+#{var}\s+(.*)$/
137
138
  return $2.strip
138
139
  else
139
140
  return ""
@@ -9,6 +9,7 @@ module Smithy
9
9
  unless @formula_directories
10
10
  @formula_directories = [ File.join(Smithy::Config.homedir, ".smithy/formulas") ]
11
11
  if Smithy::Config.global[:"formula-directories"]
12
+ raise "The formula-directories option in $SMITHY_CONFIG should be an array" if Smithy::Config.global[:"formula-directories"].class != Array
12
13
  Smithy::Config.global[:"formula-directories"].reverse.each do |dir|
13
14
  @formula_directories << dir
14
15
  end
@@ -81,16 +82,39 @@ module Smithy
81
82
  raise "unknown formula #{formula_name}" unless formula_names.include?(formula_name)
82
83
 
83
84
  require formula_file_path(formula_name)
84
-
85
- formula_class = "#{formula_name.underscore.camelize}Formula".constantize
86
- version = formula_class.version if version.blank?
87
- build = operating_system if build.blank?
88
- p = Package.new :path => [name, version, build].join("/"), :group_writable => !formula_class.disable_group_writable
89
-
90
- f = "#{formula_name.underscore.camelize}Formula".constantize.new(p)
85
+ f = "#{formula_name.underscore.camelize}Formula".constantize.new
91
86
  # Set the actual formula file path, otherwise it's just formula.rb
92
87
  f.formula_file = formula_file_path(formula_name)
93
88
 
89
+ guessing_new_name = true if version.blank? || build.blank?
90
+ version = f.version if version.blank?
91
+ build = operating_system if build.blank?
92
+
93
+ if guessing_new_name
94
+ guessed_install_path = File.join(
95
+ # Smithy::Config.global[:full_software_root_path],
96
+ [name, version, build].join("/") )
97
+
98
+ use_guessed_name = false
99
+ while use_guessed_name == false do
100
+ prompt = Readline.readline("Did you mean #{guessed_install_path} ? (enter \"h\" for help) [ynh] ")
101
+ case prompt.downcase
102
+ when "y"
103
+ use_guessed_name = true
104
+ when "n"
105
+ notice_warn "Please re-run with a full target name including version and build name."
106
+ raise "Aborting install"
107
+ when "h"
108
+ puts " y - yes, continue"
109
+ puts " n - no, abort"
110
+ puts " h - help, show this help"
111
+ end
112
+ end
113
+ end
114
+
115
+ p = Package.new :path => [name, version, build].join("/"), :group_writable => f.group_writable?
116
+ f.set_package(p) if p.valid?
117
+
94
118
  return f
95
119
  end
96
120
 
@@ -161,7 +185,7 @@ module Smithy
161
185
  def self.new_command(options,args)
162
186
  @formula_name = options[:name]
163
187
  @formula_name = url_filename_basename(args.first) unless options[:name]
164
- @formula_name = @formula_name.camelize
188
+ @formula_name = @formula_name.underscore.camelize
165
189
  @formula_url = args.first
166
190
  @formula_homepage = options[:homepage]
167
191
  @formula_homepage = "#{URI(@formula_url).scheme}://#{URI(@formula_url).host}/" unless options[:homepage]
@@ -37,7 +37,7 @@
37
37
 
38
38
  module Smithy
39
39
  def notice(message)
40
- STDOUT.puts "==> ".color(:blue).bright+message.bright #if STDOUT.tty?
40
+ STDOUT.puts "==> ".color(:blue)+message #if STDOUT.tty?
41
41
  end
42
42
 
43
43
  def notice_warn(message)
@@ -49,12 +49,12 @@ module Smithy
49
49
  end
50
50
 
51
51
  def notice_command(command, comment, width=40)
52
- STDOUT.puts command.bright.ljust(width)+comment.color(:blue) #if STDOUT.tty?
52
+ STDOUT.puts command.ljust(width)+comment.color(:blue) #if STDOUT.tty?
53
53
  end
54
54
 
55
55
  def notice_success(message)
56
56
  # if STDOUT.tty?
57
- STDOUT.puts "==> ".color(:green).bright + message.color(:green)
57
+ STDOUT.puts "==> ".color(:green) + message.color(:green)
58
58
  # else
59
59
  # STDOUT.puts message
60
60
  # end
@@ -69,7 +69,7 @@ module Smithy
69
69
  end
70
70
 
71
71
  def notice_exception(message)
72
- STDERR.puts "==> ERROR: ".color(:red).bright + message
72
+ STDERR.puts "==> ERROR: ".color(:red) + message
73
73
  end
74
74
 
75
75
  def process_ouput(stdout, stderr, suppress_stdout = false, log_file = nil)
@@ -161,7 +161,7 @@ module Smithy
161
161
  b = "sles#{version}.#{patch}"
162
162
  end
163
163
 
164
- if `gcc --version` =~ /gcc \((.*)\) ([\d\.]+)/
164
+ if `gcc --version 2>&1` =~ /gcc \((.*)\) ([\d\.]+)/
165
165
  b << "_gnu#{$2}"
166
166
  end
167
167
  return b
@@ -365,7 +365,7 @@ module Smithy
365
365
  case magic_bytes
366
366
  when /^PK\003\004/ # .zip archive
367
367
  `unzip #{archive}`
368
- when /^\037\213/, /^BZh/, /^\037\235/ # gzip/bz2/compress compressed
368
+ else
369
369
  `tar xf #{archive}`
370
370
  end
371
371
 
@@ -482,7 +482,7 @@ module Smithy
482
482
  if File.size(f) == 0
483
483
  puts "empty ".rjust(12).color(:yellow) + f
484
484
  else
485
- puts "exists ".rjust(12).bright + f
485
+ puts "exists ".rjust(12) + f
486
486
  end
487
487
  FileOperations.make_executable file[:dest], options if f =~ /#{ExecutableBuildFileNames.join('|')}/
488
488
  else
@@ -36,5 +36,5 @@
36
36
  # }}}
37
37
 
38
38
  module Smithy
39
- VERSION = '1.6.3'
39
+ VERSION = '1.6.4'
40
40
  end
data/man/man1/smithy.1 CHANGED
@@ -1,7 +1,7 @@
1
1
  .\" generated with Ronn/v0.7.3
2
2
  .\" http://github.com/rtomayko/ronn/tree/0.7.3
3
3
  .
4
- .TH "SMITHY" "1" "August 2013" "" ""
4
+ .TH "SMITHY" "1" "November 2013" "" ""
5
5
  .
6
6
  .SH "NAME"
7
7
  \fBsmithy\fR \- build, test, and install software with ease
@@ -0,0 +1,931 @@
1
+ .\" generated with Ronn/v0.7.3
2
+ .\" http://github.com/rtomayko/ronn/tree/0.7.3
3
+ .
4
+ .TH "SMITHYFORMULA" "5" "November 2013" "" ""
5
+ .
6
+ .SH "NAME"
7
+ \fBsmithyformula\fR \- writing formulas for smithy
8
+ .
9
+ .SH "DESCRIPTION"
10
+ The main goal of formulas is to consolidate all knowledge required to build a software package\. This can include:
11
+ .
12
+ .IP "\(bu" 4
13
+ defining dependencies
14
+ .
15
+ .IP "\(bu" 4
16
+ loading or swapping modules
17
+ .
18
+ .IP "\(bu" 4
19
+ setting environment variables
20
+ .
21
+ .IP "\(bu" 4
22
+ applying patches
23
+ .
24
+ .IP "\(bu" 4
25
+ creating or changing makefiles
26
+ .
27
+ .IP "\(bu" 4
28
+ running the compilation
29
+ .
30
+ .IP "\(bu" 4
31
+ running tests
32
+ .
33
+ .IP "\(bu" 4
34
+ defining a modulefile
35
+ .
36
+ .IP "" 0
37
+ .
38
+ .P
39
+ Once written it\'s easy to see everything required to build a given piece of software\. Reproducing those steps is as simple as running one command but only if the formula is as complete as possible\.
40
+ .
41
+ .P
42
+ It\'s common for build scripts to run the compilation but omit patches, changes to makefile, or any other modification to the source\. With formulas it\'s easy to make patches and output any files needed to compile software\.
43
+ .
44
+ .SH "CREATING NEW FORMULAS"
45
+ The best way to create a new formula is to start with a working example\. There are many complete working examples in the smithy_formulas repo \fIhttps://github\.com/AnthonyDiGirolamo/smithy_formulas\fR\.
46
+ .
47
+ .P
48
+ If you want to create a new formula from scratch you can use the \fBsmithy formula new\fR subcommand\. For more info on this command run \fBsmithy help formula new\fR\. To create a new formula file you need to know the homepage and a url to download the file\. To create a new formula for subversion you might run:
49
+ .
50
+ .IP "" 4
51
+ .
52
+ .nf
53
+
54
+ smithy formula new \e
55
+ \-\-name=subversion \e
56
+ \-\-homepage=http://subversion\.apache\.org/ \e
57
+ http://mirror\.cogentco\.com/pub/apache/subversion/subversion\-1\.7\.8\.tar\.bz2
58
+ .
59
+ .fi
60
+ .
61
+ .IP "" 0
62
+ .
63
+ .P
64
+ The format of the new sub\-command is \fBsmithy formula new [command options] URL\fR\. The options and arguments are:
65
+ .
66
+ .TP
67
+ \fB\-\-name\fR
68
+ This is the name used for the formula file and class, if omitted smithy will try to guess the name based on the download URL
69
+ .
70
+ .TP
71
+ \fB\-\-homepage\fR
72
+ This should be the main homepage for the software
73
+ .
74
+ .TP
75
+ \fBURL\fR
76
+ A download URL for the software, this argument is required but may be "none" if you plan to checkout the code through a version control system or copy from another location as part of the formula
77
+ .
78
+ .P
79
+ This will create a formula file inside \fB~/\.smithy/formulas\fR or the first formula directory specified in the \fB$SMITHY_CONFIG\fR file\. In either case, the full path to that file will be displayed\.
80
+ .
81
+ .SH "STRUCTURE"
82
+ Formulas attempt to create a domain specific language with the support of a full programming language, ruby\. The structure of a formula is the same as a ruby class\. For example:
83
+ .
84
+ .IP "" 4
85
+ .
86
+ .nf
87
+
88
+ class SubversionFormula < Formula
89
+
90
+ end
91
+ .
92
+ .fi
93
+ .
94
+ .IP "" 0
95
+ .
96
+ .P
97
+ Every method call that defines the formula will happen between these two lines\.
98
+ .
99
+ .SS "FORMULA FILE AND CLASS NAMING"
100
+ Formulas follow a specifc naming scheme\. The filename should end in \fB\'_formula\.rb\'\fR and start with the name of the software in all lowercase characters\. The class name should be the same name specified in the file but CamelCased \fIhttp://en\.wikipedia\.org/wiki/CamelCase\fR and end in \fB\'Formula\'\fR\.
101
+ .
102
+ .SS "RUBY BASICS"
103
+ We will cover most of the basics you need for formula writing here but if you would like more info on ruby you might read through Ruby in Twenty Minutes \fIhttp://www\.ruby\-lang\.org/en/documentation/quickstart/\fR or try another source on the Ruby Documentation \fIhttp://www\.ruby\-lang\.org/en/documentation/\fR page\.
104
+ .
105
+ .SH "FORMULA DSL METHODS"
106
+ These methods should be defined at the highest level of the formula file, right after the \fBclass GitFormula < Formula\fR line\.
107
+ .
108
+ .SS "homepage"
109
+ \fBREQUIRED\fR \- Defines the homepage, e\.g\. "http://git\-scm\.com/"
110
+ .
111
+ .SS "url"
112
+ \fBREQUIRED\fR \- The full URL to download a package, e\.g\. "http://git\-core\.googlecode\.com/files/git\-1\.8\.3\.4\.tar\.gz" may also be "none"
113
+ .
114
+ .SS "sha1,sha256,md5"
115
+ A hash of the downloaded file to verify the download performed correctly, e\.g\. \fBsha1 "fe633d02f7d964842d7ea804278b75120fc60c11"\fR
116
+ .
117
+ .SS "version"
118
+ Manually define the version number, if omitted smithy will guess the version number from the url\. This works best when the filename in a url follows the name\-version\.tar\.\.\. format\.
119
+ .
120
+ .SS "disable_group_writable"
121
+ Calling this method within the formula will skip setting group writable file permissions after the build is complete\. It\'s equivalent to running smithy with the \fB\-\-disable\-group\-writable\fR option\. See \fBsmithy help\fR for more info on global command line options\.
122
+ .
123
+ .SS "depends_on"
124
+ This method expects either a single string or an array of strings that define dependencies for this formula\. e\.g\.
125
+ .
126
+ .IP "" 4
127
+ .
128
+ .nf
129
+
130
+ depends_on "curl"
131
+ depends_on [ "cmake", "qt", "openssl", "sqlite" ]
132
+ depends_on %w{ cmake qt openssl sqlite }
133
+ .
134
+ .fi
135
+ .
136
+ .IP "" 0
137
+ .
138
+ .P
139
+ Using this method ensures that if a given dependency is not met smithy will abort the installation\. It also provides a way to query dependent packages information within the install method later on\. For example if you write \fBdepends_on "curl"\fR in your formula you gain access to an object named curl inside the install method\. This allows you to do things like:
140
+ .
141
+ .IP "" 4
142
+ .
143
+ .nf
144
+
145
+ system "\./configure \-\-prefix=#{prefix} \-\-with\-curl=#{curl\.prefix}"
146
+ .
147
+ .fi
148
+ .
149
+ .IP "" 0
150
+ .
151
+ .P
152
+ In the above example \fB#{curl\.prefix}\fR is an example of a ruby interpolated string, everything between the \fB#{ }\fR is ruby code\. \fBcurl\.prefix\fR will return a string with the location curl is installed in\.
153
+ .
154
+ .P
155
+ The strings passed to \fBdepends_on\fR are just the locations of installed software\. If you required a specific version of a dependency you could use specify the version or build numbers of existing installed software\. e\.g\.
156
+ .
157
+ .IP "" 4
158
+ .
159
+ .nf
160
+
161
+ depends_on [ "cmake/2\.8\.11\.2/sles11\.1_gnu4\.3\.4", "qt/4\.8\.5", "sqlite" ]
162
+ .
163
+ .fi
164
+ .
165
+ .IP "" 0
166
+ .
167
+ .P
168
+ Assuming your software root is \fB/sw/xk6\fR smithy would look for the above software installs in \fB/sw/xk6/cmake/2\.8\.11\.2/sles11\.1_gnu4\.3\.4\fR \fB/sw/xk6/qt/4\.8\.5/*\fR and \fB/sw/xk6/sqlite/*/*\fR\. The \fB*\fR works similar to shell globbing\. If you needed to install a python module that depends on a specific version of another python module you might use:
169
+ .
170
+ .IP "" 4
171
+ .
172
+ .nf
173
+
174
+ depends_on [ "python/3\.3\.0", "python_numpy/1\.7\.1/*python3\.3\.0*" ]
175
+ .
176
+ .fi
177
+ .
178
+ .IP "" 0
179
+ .
180
+ .P
181
+ This would require a given formula to have access to both \fB/sw/xk6/python/3\.3\.0/*\fR and a python module with a build name that includes \fBpython3\.3\.0\fR located at \fB/sw/x6/python_numpy/1\.7\.1/*python3\.3\.0*\fR
182
+ .
183
+ .P
184
+ You will also probably need to specifiy dependencies conditionally upon the type of build you are performing\. It\'s recommended to add the type of build to the build name when installing\. Given that, you can key off build names to specify dependencies\. Taking the python example further, lets extend it to support multiple versions of python\. You can pass a ruby block to the \fBdepends_on\fR method to make it more dynamic\. The syntax for this is:
185
+ .
186
+ .IP "" 4
187
+ .
188
+ .nf
189
+
190
+ depends_on do
191
+ \.\.\.
192
+ end
193
+ .
194
+ .fi
195
+ .
196
+ .IP "" 0
197
+ .
198
+ .P
199
+ Any ruby code may go in here the last executed line of the block should be an array of strings containting the dependencies\. Lets use a ruby case statement for this:
200
+ .
201
+ .IP "" 4
202
+ .
203
+ .nf
204
+
205
+ depends_on do
206
+ case build_name
207
+ when /python3\.3/
208
+ [ "python/3\.3\.0", "python_numpy/1\.7\.1/*python3\.3\.0*" ]
209
+ when /python2\.7/
210
+ [ "python/2\.7\.3", "python_numpy/1\.7\.1/*python2\.7\.3*" ]
211
+ end
212
+ end
213
+ .
214
+ .fi
215
+ .
216
+ .IP "" 0
217
+ .
218
+ .P
219
+ In this example case statement switches on the \fBbuild_name\fR\. The \fBwhen /python3\.3/\fR will be true if the \fBbuild_name\fR contains the \fBpython3\.3\fR\. The \fB/python3\.3/\fR syntax is a regular expression\.
220
+ .
221
+ .P
222
+ This allows the formula to set it\'s dependencies based off the type of build thats being performed\. Lets say this formula is \fBpython_matplotlib\fR\. You could run either of these commands to install it and expect the dependencies to be set correctly:
223
+ .
224
+ .IP "" 4
225
+ .
226
+ .nf
227
+
228
+ smithy formula install python_matplotlib/1\.2\.3/python3\.3\.0
229
+ smithy formula install python_matplotlib/1\.2\.3/python2\.7\.3
230
+ .
231
+ .fi
232
+ .
233
+ .IP "" 0
234
+ .
235
+ .SS "module_commands"
236
+ This method defines the module commands that must be run before \fIsystem\fR calls within the \fIdef install\fR part of the modulefile\. It expects an array of strings with each string being a module command\. e\.g\.
237
+ .
238
+ .IP "" 4
239
+ .
240
+ .nf
241
+
242
+ module_commands [ "load szip", "load hdf5" ]
243
+ .
244
+ .fi
245
+ .
246
+ .IP "" 0
247
+ .
248
+ .P
249
+ A more complicated example:
250
+ .
251
+ .IP "" 4
252
+ .
253
+ .nf
254
+
255
+ module_commands [
256
+ "unload PE\-gnu PE\-pgi PE\-intel PE\-cray",
257
+ "load PE\-gnu",
258
+ "load cmake/2\.8\.11\.2",
259
+ "load git",
260
+ "swap gcc gcc/4\.7\.1",
261
+ "swap ompi ompi/1\.6\.3"
262
+ ]
263
+ .
264
+ .fi
265
+ .
266
+ .IP "" 0
267
+ .
268
+ .P
269
+ \fBmodule_commands\fR also accepts ruby blocks the syntax for this is:
270
+ .
271
+ .IP "" 4
272
+ .
273
+ .nf
274
+
275
+ module_commands do
276
+ \.\.\.
277
+ end
278
+ .
279
+ .fi
280
+ .
281
+ .IP "" 0
282
+ .
283
+ .P
284
+ This can be used to dynamically set which modules to load based on the \fBbuild_name\fR\. Here is an example that loads the correct python version:
285
+ .
286
+ .IP "" 4
287
+ .
288
+ .nf
289
+
290
+ module_commands do
291
+ commands = [ "unload python" ]
292
+
293
+ case build_name
294
+ when /python3\.3/
295
+ commands << "load python/3\.3\.0"
296
+ when /python2\.7/
297
+ commands << "load python/2\.7\.3"
298
+ end
299
+
300
+ commands << "load python_numpy"
301
+ commands << "load szip"
302
+ commands << "load hdf5/1\.8\.8"
303
+ commands
304
+ end
305
+ .
306
+ .fi
307
+ .
308
+ .IP "" 0
309
+ .
310
+ .P
311
+ This block starts by creating a variable named \fBcommands\fR as an array with a single item \fB"unload python"\fR\. Next a case statement is used to determine which version of python we are compiling for\. \fBcommands << "load python/3\.3\.0"\fR will append \fB"load python/3\.3\.0"\fR to the end of the array\. See the ruby documentation on the Array Class method \fIhttp://www\.ruby\-doc\.org/core\-2\.0/Array\.html#method\-i\-3C\-3C\fR for more info on the \fB<<\fR operator\. After that, it appends a few more modules to load\. The last line of the block must be the array itself so that when the block is evaluated by smithy, it recieves the expected value\.
312
+ .
313
+ .P
314
+ Assuming this is a formula for \fBpython_h5py\fR running \fBsmithy formula install python_h5py/2\.1\.3/python3\.3\fR results in an array containing: \fB[ "unload python", "load python/3\.3\.0", "load python_numpy", "load szip", "load hdf5/1\.8\.8" ]\fR
315
+ .
316
+ .SS "modules"
317
+ This command is similar to the \fImodule_commands\fR method\. It accepts an array of strings with the names of modulefiles that must be loaded\. It\'s different from \fImodule_commands\fR in that it expects only names of modules and loads them in the order specified\. Additionally it runs a \fBmodule purge\fR to unload all modules before loading the passed array of modules\. e\.g\.
318
+ .
319
+ .IP "" 4
320
+ .
321
+ .nf
322
+
323
+ modules [ "java" ]
324
+ .
325
+ .fi
326
+ .
327
+ .IP "" 0
328
+ .
329
+ .P
330
+ This line would run \fBmodule purge\fR and \fBmodule load java\fR before any \fIsystem\fR command\. \fImodules\fR also accepts ruby blocks similar to \fImodule_commands\fR and \fIdepends_on\fR\. Here is an example using ruby blocks:
331
+ .
332
+ .P
333
+ modules do
334
+ .
335
+ .IP "" 4
336
+ .
337
+ .nf
338
+
339
+ mods = [ ]
340
+ case build_name
341
+ when /gnu/
342
+ mods << "PrgEnv\-gnu"
343
+ when /pgi/
344
+ mods << "PrgEnv\-pgi"
345
+ when /intel/
346
+ mods << "PrgEnv\-intel"
347
+ when /cray/
348
+ mods << "PrgEnv\-cray"
349
+ end
350
+ mods
351
+ .
352
+ .fi
353
+ .
354
+ .IP "" 0
355
+ .
356
+ .P
357
+ end
358
+ .
359
+ .P
360
+ This block would result in the formula running \fBmodule purge\fR followed by \fBmodule load PrgEnv\-gnu\fR if the \fBbuild_name\fR contains gnu and similarly for pgi, intel, and cray\.
361
+ .
362
+ .SS "modulefile"
363
+ This method expects the a string that represents the modulefile\. Generally modulefiles in smithy take two forms ones that point to a single build and ones that use multiple builds and set the build based on a users environment (already loaded modules)\. It\'s recommended to have one modulefile per application version and set multiple builds dynamically inside the modulefile\.
364
+ .
365
+ .P
366
+ Writing modulefiles is a topic in and of itself\. For details on the modulefile format see the modulefile(4) manpage \fIhttp://modules\.sourceforge\.net/man/modulefile\.html\fR Modulefiles are written in tcl and can take many forms\.
367
+ .
368
+ .P
369
+ Here is an example of a modulefile that points to a single build\. It\'s convenient to use heredoc string quoting in ruby so that the string can span multiple lines\. e\.g\.
370
+ .
371
+ .IP "" 4
372
+ .
373
+ .nf
374
+
375
+ modulefile <<\-MODULEFILE\.strip_heredoc
376
+ #%Module
377
+ proc ModulesHelp { } {
378
+ puts stderr "<%= @package\.name %> <%= @package\.version %>"
379
+ puts stderr ""
380
+ }
381
+ module\-whatis "<%= @package\.name %> <%= @package\.version %>"
382
+
383
+ set PREFIX <%= @package\.prefix %>
384
+
385
+ prepend\-path PATH $PREFIX/bin
386
+ prepend\-path LD_LIBRARY_PATH $PREFIX/lib
387
+ prepend\-path MANPATH $PREFIX/share/man
388
+ MODULEFILE
389
+ .
390
+ .fi
391
+ .
392
+ .IP "" 0
393
+ .
394
+ .P
395
+ The \fB<<\-MODULEFILE\.strip_heredoc\fR syntax denotes the beginning for a multi\-line string\. The string ends with \fBMODULEFILE\fR\. You can substitute any word for \fBMODULEFILE\fR\. The \fB\.strip_heredoc\fR method removes leading whitespace from the string so the output isn\'t unecessarily indented\.
396
+ .
397
+ .P
398
+ The modulefile definition uses the erb format \fIhttp://ruby\-doc\.org/stdlib\-2\.0/libdoc/erb/rdoc/ERB\.html\fR Anything between the \fB<%= \.\.\. %>\fR delimiters will be interpreted as ruby code\. There are a few helper methods that you can use inside these delimiters see the next section titled \fIMODULEFILE HELPER METHODS\fR for details\.
399
+ .
400
+ .P
401
+ A more complicated modulefile may examine already loaded modules to determine which build to load\. For instance if the user has gcc or a gnu programming environment module loaded then your modulefile will want to load the gnu build\. Here is an example designed to dynamically set the build:
402
+ .
403
+ .IP "" 4
404
+ .
405
+ .nf
406
+
407
+ #%Module
408
+ proc ModulesHelp { } {
409
+ puts stderr "<%= @package\.name %> <%= @package\.version %>"
410
+ puts stderr ""
411
+ }
412
+ # One line description
413
+ module\-whatis "<%= @package\.name %> <%= @package\.version %>"
414
+
415
+ <% if @builds\.size > 1 %>
416
+ <%= module_build_list @package, @builds %>
417
+
418
+ set PREFIX <%= @package\.version_directory %>/$BUILD
419
+ <% else %>
420
+ set PREFIX <%= @package\.prefix %>
421
+ <% end %>
422
+
423
+ # Helpful ENV Vars
424
+ setenv <%= @package\.name\.upcase %>_DIR $PREFIX
425
+ setenv <%= @package\.name\.upcase %>_LIB "\-L$PREFIX/lib"
426
+ setenv <%= @package\.name\.upcase %>_INC "\-I$PREFIX/include"
427
+
428
+ # Common Paths
429
+ prepend\-path PATH $PREFIX/bin
430
+ prepend\-path LD_LIBRARY_PATH $PREFIX/lib
431
+ prepend\-path MANPATH $PREFIX/share/man
432
+ prepend\-path INFOPATH $PREFIX/info
433
+ prepend\-path PKG_CONFIG_PATH $PREFIX/lib/pkgconfig
434
+ prepend\-path PYTHONPATH $PREFIX/lib/python2\.7/site\-packages
435
+ prepend\-path PERL5PATH $PREFIX/lib/perl5/site_perl
436
+ .
437
+ .fi
438
+ .
439
+ .IP "" 0
440
+ .
441
+ .P
442
+ The main difference from the first example is the \fB<%= if @builds\.size > 1 %>\fR block\. This basically checks to see if we have installed multiple builds or not\. If that condition is true everything up until the \fB<% else %>\fR will be put in the modulefile\. Otherwise, if we have only one build, \fBset PREFIX <%= @package\.prefix %>\fR will be put in the modulefile\.
443
+ .
444
+ .SS "def install"
445
+ \fBREQUIRED\fR \- This is the method that runs the software installation process\. It normally runs system commands, performs patches, and sets environment variables\. e\.g\.
446
+ .
447
+ .IP "" 4
448
+ .
449
+ .nf
450
+
451
+ def install
452
+ system "\./configure"
453
+ system "make"
454
+ system "make install"
455
+ end
456
+ .
457
+ .fi
458
+ .
459
+ .IP "" 0
460
+ .
461
+ .P
462
+ The contents of the install method depends heavily on the software being installed\. For a list of additional helper methods for use inside install see the \fIFORMULA HELPER METHODS\fR section\.
463
+ .
464
+ .SH "MODULEFILE HELPER METHODS"
465
+ .
466
+ .SS "<code><%= @package\.name %></code>"
467
+ This will return the name of the application being installed\. It is the same as the APPLICATION part of the \fBsmithy formula install APPLICATION/VERSION/BUILD\fR command\.
468
+ .
469
+ .SS "<code><%= @package\.version %></code>"
470
+ Similar to the above, this returns the version number\.
471
+ .
472
+ .SS "<code><%= @package\.build_name %></code>"
473
+ Same as the name and version methods, this will return the build name of the applcation\.
474
+ .
475
+ .SS "<code><%= @package\.prefix %></code>"
476
+ This line will return the full prefix to an application\. If we run \fBsmithy formula install bzip2/1\.0\.4/pgi13\.4\fR and our software\-root is \fB/sw/xk6\fR this command will return \fB/sw/xk6/bzip2/1\.0\.4/pgi13\.4\fR
477
+ .
478
+ .SS "<code><%= @builds %></code>"
479
+ The \fB@builds\fR variable is an array of strings that contain the list of available builds for a given application\. Say we have a bzip2 formula and ran the following installs:
480
+ .
481
+ .IP "" 4
482
+ .
483
+ .nf
484
+
485
+ smithy formula install bzip2/1\.0\.4/gnu4\.3\.4
486
+ smithy formula install bzip2/1\.0\.4/gnu4\.7\.2
487
+ smithy formula install bzip2/1\.0\.4/pgi13\.4
488
+ smithy formula install bzip2/1\.0\.4/intel12
489
+ .
490
+ .fi
491
+ .
492
+ .IP "" 0
493
+ .
494
+ .P
495
+ The directory structure for the above builds would look like (assuming \fB/sw/xk6\fR is the software\-root):
496
+ .
497
+ .IP "" 4
498
+ .
499
+ .nf
500
+
501
+ /sw/xk6/bzip2/1\.0\.4
502
+ `\-\-\- modulefile
503
+ | `\-\-\- bzip2
504
+ | `\-\-\- 1\.0\.4
505
+ `\-\-\- gnu4\.3\.4
506
+ | `\-\-\- bin
507
+ | `\-\-\- include
508
+ | `\-\-\- lib
509
+ | `\-\-\- source
510
+ | `\-\-\- share
511
+ `\-\-\- gnu4\.7\.2
512
+ | `\-\-\- bin
513
+ | `\-\-\- include
514
+ | `\-\-\- lib
515
+ | `\-\-\- source
516
+ | `\-\-\- share
517
+ `\-\-\- pgi13\.4
518
+ | `\-\-\- bin
519
+ | `\-\-\- include
520
+ | `\-\-\- lib
521
+ | `\-\-\- source
522
+ | `\-\-\- share
523
+ `\-\-\- intel12
524
+ `\-\-\- bin
525
+ `\-\-\- include
526
+ `\-\-\- lib
527
+ `\-\-\- source
528
+ `\-\-\- share
529
+ .
530
+ .fi
531
+ .
532
+ .IP "" 0
533
+ .
534
+ .P
535
+ The \fB@builds\fR array would then be \fB[ "gnu4\.3\.4", "gnu4\.7\.2", "pgi13\.4", "intel12" ]\fR\. This lets you figure out what builds exist and use them in your modulefile\.
536
+ .
537
+ .SS "<code><%= @builds\.size %></code>"
538
+ size \fIhttp://ruby\-doc\.org/core\-2\.0/Array\.html#method\-i\-size\fR is a standard ruby method that counts the number of elements in an array\. For the above example this would return \fB4\fR\.
539
+ .
540
+ .SS "<code><%= module_build_list @package, @builds %></code>"
541
+ This is a helper method in smithy that will generate the tcl necessary to conditionally load builds based on what compiler programming environment modules a user has loaded\. It takes \fB@package\fR and \fB@builds\fR as arguments\. Using the above bzip2 example the result of using this method would be:
542
+ .
543
+ .IP "" 4
544
+ .
545
+ .nf
546
+
547
+ if [ is\-loaded PrgEnv\-gnu ] {
548
+ if [ is\-loaded gcc/4\.3\.4 ] {
549
+ set BUILD gnu4\.3\.4
550
+ } elseif [ is\-loaded gcc/4\.7\.2 ] {
551
+ set BUILD gnu4\.7\.2
552
+ } else {
553
+ set BUILD gnu4\.7\.2
554
+ }
555
+ } elseif [ is\-loaded PrgEnv\-pgi ] {
556
+ set BUILD pgi13\.4
557
+ } elseif [ is\-loaded PrgEnv\-intel ] {
558
+ set BUILD intel12
559
+ } elseif [ is\-loaded PrgEnv\-cray ] {
560
+ puts stderr "Not implemented for the cray compiler"
561
+ }
562
+ if {![info exists BUILD]} {
563
+ puts stderr "[module\-info name] is only available for the following environments:"
564
+ puts stderr "gnu4\.3\.4"
565
+ puts stderr "gnu4\.7\.2"
566
+ puts stderr "intel12"
567
+ puts stderr "pgi13\.4"
568
+ break
569
+ }
570
+ .
571
+ .fi
572
+ .
573
+ .IP "" 0
574
+ .
575
+ .SS "<code><% if \.\.\. %></code>"
576
+ This is standard erb ruby code\. Delimiters like \fB<% \.\.\. %>\fR do NOT put their results in the final modulefile, they are only used for control flow\. Delimiters with the extra = sign \fB<%= \.\.\. %>\fR will put their results in the final modulefile\.
577
+ .
578
+ .P
579
+ This is best used to conditionally render content to the modulefile and takes the form:
580
+ .
581
+ .IP "" 4
582
+ .
583
+ .nf
584
+
585
+ <% if @builds\.size > 1 %>
586
+ \.\.\.
587
+ <% else %>
588
+ \.\.\.
589
+ <% end %>
590
+ .
591
+ .fi
592
+ .
593
+ .IP "" 0
594
+ .
595
+ .P
596
+ Where \fB@builds\.size > 1\fR can be any expression which returns true or false\. If the if condition is true then the lines between the if and else will be put in the modulefile, otherwise lines between the else and end will be used\.
597
+ .
598
+ .SH "FORMULA HELPER METHODS"
599
+ These methods are designed to be used within the \fIdef install\fR method of a formula file or within a block passed to one \fIFORMULA DSL METHODS\fR\.
600
+ .
601
+ .SS "name"
602
+ This will return the name of the application being installed\. It is the same as the APPLICATION part of the smithy formula install APPLICATION/VERSION/BUILD command\. It can be used as a variable as well as inside of a string using the \fB#{ \.\.\. }\fR delimiters\. e\.g\. \fB"#{name}"\fR
603
+ .
604
+ .SS "version"
605
+ Similar to the above, this returns the version number\.
606
+ .
607
+ .SS "build_name"
608
+ Same as the name and version methods, this will return the build name of the applcation\.
609
+ .
610
+ .SS "prefix"
611
+ This line will return the full prefix to an application\. If we run smithy formula install bzip2/1\.0\.4/pgi13\.4 and our software\-root is /sw/xk6 this command will return /sw/xk6/bzip2/1\.0\.4/pgi13\.4
612
+ .
613
+ .SS "system"
614
+ This method accepts a string or multiple strings separated by commas\. It will run the given command in a subshell and setup the modules as defined by the \fImodule_commands\fR or \fImodules\fR methods\. Each call to system is independent from the last\. Modules are reloaded and environment variables are reset\.
615
+ .
616
+ .SS "module_list"
617
+ This method will run \fBmodule list\fR and print it\'s output durring the install process\. Useful for verifying the modules loaded are the ones you want\.
618
+ .
619
+ .SS "module_is_available?"
620
+ This method will check if a given modulename is available on the system you are performing the installation on\. It takes one string argument, the module name\. It can be used within the \fIdef install\fR, \fIdepends_on\fR, \fImodule_commands\fR, or \fImodules\fR methods\.
621
+ .
622
+ .IP "" 4
623
+ .
624
+ .nf
625
+
626
+ if module_is_available?("hdf5/1\.8\.8")
627
+ \.\.\.
628
+ end
629
+ .
630
+ .fi
631
+ .
632
+ .IP "" 0
633
+ .
634
+ .SS "module_environment_variable"
635
+ Using this method will return the contents of an environment varible set by a modulefile\. It takes two string arguments, the module name and the environment variable name\. For example, if you wished to get the value of the \fB$HDF5_DIR\fR variable set within the \fBhdf5/1\.8\.8\fR module you could run:
636
+ .
637
+ .IP "" 4
638
+ .
639
+ .nf
640
+
641
+ hdf5_prefix = module_environment_variable("hdf5/1\.8\.8", "HDF5_DIR")
642
+ .
643
+ .fi
644
+ .
645
+ .IP "" 0
646
+ .
647
+ .P
648
+ Using this method to get environment variable set by modules is necessary since the modules are only set before running a \fIsystem\fR command\. See \fISetting Environment Variables\fR for more info\. It can be used within the \fIdef install\fR, \fIdepends_on\fR, \fImodule_commands\fR, or \fImodules\fR methods\.
649
+ .
650
+ .P
651
+ By combining the [module_is_available?][] and \fImodule_environment_variable\fR methods you can conditionally retrieve the contents of environment variables set within a given module\.
652
+ .
653
+ .IP "" 4
654
+ .
655
+ .nf
656
+
657
+ if module_is_available?("hdf5/1\.8\.8")
658
+ hdf5_prefix = module_environment_variable("hdf5/1\.8\.8", "HDF5_DIR")
659
+ end
660
+ .
661
+ .fi
662
+ .
663
+ .IP "" 0
664
+ .
665
+ .SS "patch"
666
+ The patch method is a convinience method to apply patches to code\. Behind the scenes it creates a file named \fBpatch\.diff\fR with the passed content and runs \fBpatch \-p1 <patch\.diff\fR\. Using the heredoc syntax works best to strip leading whitespace\. For example:
667
+ .
668
+ .IP "" 4
669
+ .
670
+ .nf
671
+
672
+ patch <<\-EOF\.strip_heredoc
673
+ diff \-\-git a/CMake/cdat_modules/cairo_external\.cmake b/CMake/cdat_modules/cairo_external\.cmake
674
+ index e867fb2\.\.22fb40c 100644
675
+ \-\-\- a/CMake/cdat_modules/cairo_external\.cmake
676
+ +++ b/CMake/cdat_modules/cairo_external\.cmake
677
+ @@ \-1,7 +1,7 @@
678
+
679
+ set(Cairo_source "${CMAKE_CURRENT_BINARY_DIR}/build/Cairo")
680
+ set(Cairo_install "${cdat_EXTERNALS}")
681
+ \-set(Cairo_conf_args \-\-disable\-static)
682
+ +set(Cairo_conf_args \-\-enable\-gobject=no \-\-disable\-static)
683
+
684
+ ExternalProject_Add(Cairo
685
+ DOWNLOAD_DIR ${CDAT_PACKAGE_CACHE_DIR}
686
+ EOF
687
+ .
688
+ .fi
689
+ .
690
+ .IP "" 0
691
+ .
692
+ .P
693
+ Any input you provide must be compatible with the patch command\. You can use interpolated strings \fB#{ \.\.\. }\fR to modify the content of patches as well:
694
+ .
695
+ .IP "" 4
696
+ .
697
+ .nf
698
+
699
+ patch <<\-EOF\.strip_heredoc
700
+ diff \-\-git a/Makefile\.in b/Makefile\.in
701
+ new file mode 100644
702
+ index 0000000\.\.1235d4b
703
+ \-\-\- /dev/null
704
+ +++ b/Makefile\.in
705
+ @@ \-0,0 +1,12 @@
706
+ +SHELL = /bin/sh
707
+ +PLAT = LINUX
708
+ +BLLIB = #{acml_prefix}/gfortran64/lib/libacml\.a
709
+ +CBLIB = #{prefix}/lib/libcblas\.a
710
+ +CC = gcc
711
+ +FC = gfortran
712
+ +LOADER = $(FC)
713
+ +CFLAGS = \-O3 \-DADD_
714
+ +FFLAGS = \-O3
715
+ +ARCH = ar
716
+ +ARCHFLAGS = r
717
+ +RANLIB = ranlib
718
+ EOF
719
+ .
720
+ .fi
721
+ .
722
+ .IP "" 0
723
+ .
724
+ .SH "COMMON OPERATIONS"
725
+ .
726
+ .SS "Change Working Directory"
727
+ Changing the working directory accomplished by the Dir\.chdir \fIhttp://ruby\-doc\.org/core\-1\.9\.3/Dir\.html#method\-c\-chdir\fR method\. It takes one argument as a string\. It\'s best to always work from the prefix of the installation\. You can concatenate strings using a \fB+\fR sign\.
728
+ .
729
+ .IP "" 4
730
+ .
731
+ .nf
732
+
733
+ Dir\.chdir prefix
734
+ Dir\.chdir prefix+"/source"
735
+ .
736
+ .fi
737
+ .
738
+ .IP "" 0
739
+ .
740
+ .SS "Running Shell Commands"
741
+ In ruby you can execute any shell command using backtick delimiters\. Commands run using this method will NOT load any required modulefiles\. It will however return the standard output as a string
742
+ .
743
+ .IP "" 4
744
+ .
745
+ .nf
746
+
747
+ `ln \-svf file1 file2`
748
+ results = `ln \-svf file1 file2`
749
+ .
750
+ .fi
751
+ .
752
+ .IP "" 0
753
+ .
754
+ .P
755
+ If you need modulefiles loaded use the \fIsystem\fR command instead\.
756
+ .
757
+ .IP "" 4
758
+ .
759
+ .nf
760
+
761
+ system "ln \-svf file1 file2"
762
+ .
763
+ .fi
764
+ .
765
+ .IP "" 0
766
+ .
767
+ .P
768
+ There are many ruby methods available that are the equivalent of running the shell counterparts\. See the these pages for more info:
769
+ .
770
+ .IP "\(bu" 4
771
+ FileUtils Class \fIhttp://www\.ruby\-doc\.org/stdlib\-2\.0/libdoc/fileutils/rdoc/FileUtils\.html\fR
772
+ .
773
+ .IP "\(bu" 4
774
+ Dir Class \fIhttp://ruby\-doc\.org/core\-1\.9\.3/Dir\.html\fR
775
+ .
776
+ .IP "\(bu" 4
777
+ File Class \fIhttp://www\.ruby\-doc\.org/core\-2\.0/File\.html\fR
778
+ .
779
+ .IP "" 0
780
+ .
781
+ .SS "Setting Environment Variables"
782
+ Ruby provides the ENV \fIhttp://www\.ruby\-doc\.org/core\-2\.0/ENV\.html\fR hash for accessing and setting environment variables\. Here is an example of setting environment variables:
783
+ .
784
+ .IP "" 4
785
+ .
786
+ .nf
787
+
788
+ ENV["CC"] = "gcc"
789
+ ENV["CXX"] = "g++"
790
+ ENV["F77"] = "gfortran"
791
+ ENV["F90"] = "gfortran"
792
+ ENV["FC"] = "gfortran"
793
+ .
794
+ .fi
795
+ .
796
+ .IP "" 0
797
+ .
798
+ .P
799
+ And getting their values back:
800
+ .
801
+ .IP "" 4
802
+ .
803
+ .nf
804
+
805
+ cppflags = ENV["CPPFLAGS"]
806
+ .
807
+ .fi
808
+ .
809
+ .IP "" 0
810
+ .
811
+ .P
812
+ This works with one caveat, you cannot access or modify variables set by modules loaded by the formula\. Modules are loaded and reset before each \fIsystem\fR command\.
813
+ .
814
+ .P
815
+ If you need to access the contents of an evironment variable set by a module use the \fImodule_environment_variable\fR helper method\.
816
+ .
817
+ .P
818
+ If you need to change the contents of an environment variable set by a loaded module you will need to make it part of the system command\. For example, say you loaded the \fBnetcdf\fR module and needed to change the \fB$NETCDF_DIR\fR variable\. You could run any of these:
819
+ .
820
+ .IP "" 4
821
+ .
822
+ .nf
823
+
824
+ system "NETCDF_DIR=/opt/cray/netcdf/4\.2\.0/generic \./configure"
825
+ system "export NETCDF_DIR=/opt/cray/netcdf/4\.2\.0/generic ;",
826
+ "\./configure"
827
+ system "export NETCDF_DIR=/opt/cray/netcdf/4\.2\.0/generic
828
+ \./configure"
829
+ .
830
+ .fi
831
+ .
832
+ .IP "" 0
833
+ .
834
+ .SS "Creating Files"
835
+ Using ruby to create files is simple\. With this and the \fB#{ \.\.\. }\fR delimiters you can add dynamic content to the files you write\. The basic syntax for writing files is:
836
+ .
837
+ .IP "" 4
838
+ .
839
+ .nf
840
+
841
+ File\.open("path/to/file", "w+") do |file|
842
+ file\.write "\.\.\."
843
+ end
844
+ .
845
+ .fi
846
+ .
847
+ .IP "" 0
848
+ .
849
+ .P
850
+ This syntax uses a ruby block with an argument\. \fBFile\.open("\.\.\.", "w+")\fR passes the file handle to the block as a variable named \fBfile\fR\. Between the \fBdo |file|\fR and \fBend\fR lines is the block\. When ruby reaches the end of the block the file is closed\.
851
+ .
852
+ .P
853
+ The \fB"w+"\fR argument tells ruby to open the file with read\-write and truncate the existing file to zero length or create a new file for reading and writing\. See this page \fIhttp://www\.ruby\-doc\.org/core\-2\.0/IO\.html#method\-c\-new\-label\-IO+Open+Mode\fR for more info on the different modes\.
854
+ .
855
+ .P
856
+ Here is a good example from the mpi4py formula \fIhttps://github\.com/AnthonyDiGirolamo/smithy_formulas/blob/master/python_mpi4py_cray_formula\.rb\fR
857
+ .
858
+ .IP "" 4
859
+ .
860
+ .nf
861
+
862
+ File\.open("mpi\.cfg", "w+") do |f|
863
+ f\.write <<\-EOF\.strip_heredoc
864
+ [cray]
865
+ mpi_dir = /opt/cray/mpt/5\.6\.3/gni/mpich2\-gnu/47
866
+ mpicc = cc
867
+ mpicxx = CC
868
+ EOF
869
+ end
870
+ .
871
+ .fi
872
+ .
873
+ .IP "" 0
874
+ .
875
+ .P
876
+ This will create a new file named "mpi\.cfg" in the current working directory\. If you wanted to make it a bit more dynamic you might wish to set the contents based on an environment variable like this:
877
+ .
878
+ .IP "" 4
879
+ .
880
+ .nf
881
+
882
+ mpidir = module_environment_variable("cray\-mpich2", "CRAY_MPICH2_DIR")
883
+ File\.open("mpi\.cfg", "w+") do |f|
884
+ f\.write <<\-EOF\.strip_heredoc
885
+ [cray]
886
+ mpi_dir = #{mpidir}
887
+ mpicc = cc
888
+ mpicxx = CC
889
+ EOF
890
+ end
891
+ .
892
+ .fi
893
+ .
894
+ .IP "" 0
895
+ .
896
+ .SS "Putting it Together"
897
+ You can combine these methods in many ways\. This bit of code is from the uvcdat formula \fIhttps://github\.com/AnthonyDiGirolamo/smithy_formulas/blob/master/uvcdat_formula\.rb\fR and creates symlinks from an openssl installaion into a directory under the uvcdat prefix\.
898
+ .
899
+ .IP "" 4
900
+ .
901
+ .nf
902
+
903
+ Dir\.chdir prefix
904
+ openssl_files = %w{
905
+ include/openssl
906
+ lib/pkgconfig/libcrypto\.pc
907
+ lib/pkgconfig/libssl\.pc
908
+ lib/pkgconfig/openssl\.pc
909
+ lib/engines
910
+ lib/libcrypto\.a
911
+ lib/libcrypto\.so
912
+ lib/libcrypto\.so\.1\.0\.0
913
+ lib/libssl\.a
914
+ lib/libssl\.so
915
+ lib/libssl\.so\.1\.0\.0
916
+ }
917
+ FileUtils\.mkdir_p "Externals/include"
918
+ FileUtils\.mkdir_p "Externals/lib/pkgconfig"
919
+ openssl_files\.each do |file|
920
+ system "ln \-sf #{openssl\.prefix}/#{file} #{prefix}/Externals/#{file}"
921
+ end
922
+ .
923
+ .fi
924
+ .
925
+ .IP "" 0
926
+ .
927
+ .P
928
+ It begins by changing the working directory to the installation prefix\. Then, creates an array of strings named \fBopenssl_files\fR containing relative paths to files needing to be symlinked\. It then creates directories that might not exist yet using FileUtils\.mkdir_p \fIhttp://www\.ruby\-doc\.org/stdlib\-2\.0/libdoc/fileutils/rdoc/FileUtils\.html#method\-c\-mkdir_p\fR\. Then it iterates through the \fBopenssl_files\fR array and runs one \fIsystem\fR command per array element\. That system command uses an \fBopenssl\.prefix\fR method that is made available by the \fIdepends_on\fR defined earlier in the formula to get the location of the openssl installation\.
929
+ .
930
+ .SH "SEE ALSO"
931
+ smithy(1)
data/smithy.rdoc CHANGED
@@ -1,6 +1,6 @@
1
1
  == smithy - Smithy will help you build, test, and install software with ease.
2
2
 
3
- v1.6.3
3
+ v1.6.4
4
4
 
5
5
  === Global Options
6
6
  === --arch NAME
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: software_smithy
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.3
4
+ version: 1.6.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-09-18 00:00:00.000000000 Z
12
+ date: 2014-07-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: awesome_print
@@ -59,22 +59,6 @@ dependencies:
59
59
  - - ! '>='
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
- - !ruby/object:Gem::Dependency
63
- name: debugger
64
- requirement: !ruby/object:Gem::Requirement
65
- none: false
66
- requirements:
67
- - - ! '>='
68
- - !ruby/object:Gem::Version
69
- version: '0'
70
- type: :development
71
- prerelease: false
72
- version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
- requirements:
75
- - - ! '>='
76
- - !ruby/object:Gem::Version
77
- version: '0'
78
62
  - !ruby/object:Gem::Dependency
79
63
  name: rake
80
64
  requirement: !ruby/object:Gem::Requirement
@@ -178,7 +162,7 @@ dependencies:
178
162
  requirements:
179
163
  - - '='
180
164
  - !ruby/object:Gem::Version
181
- version: 2.7.0
165
+ version: 2.10.0
182
166
  type: :runtime
183
167
  prerelease: false
184
168
  version_requirements: !ruby/object:Gem::Requirement
@@ -186,55 +170,55 @@ dependencies:
186
170
  requirements:
187
171
  - - '='
188
172
  - !ruby/object:Gem::Version
189
- version: 2.7.0
173
+ version: 2.10.0
190
174
  - !ruby/object:Gem::Dependency
191
175
  name: kramdown
192
176
  requirement: !ruby/object:Gem::Requirement
193
177
  none: false
194
178
  requirements:
195
- - - ! '>='
179
+ - - '='
196
180
  - !ruby/object:Gem::Version
197
- version: 1.1.0
181
+ version: 1.4.0
198
182
  type: :runtime
199
183
  prerelease: false
200
184
  version_requirements: !ruby/object:Gem::Requirement
201
185
  none: false
202
186
  requirements:
203
- - - ! '>='
187
+ - - '='
204
188
  - !ruby/object:Gem::Version
205
- version: 1.1.0
189
+ version: 1.4.0
206
190
  - !ruby/object:Gem::Dependency
207
191
  name: open4
208
192
  requirement: !ruby/object:Gem::Requirement
209
193
  none: false
210
194
  requirements:
211
- - - ! '>='
195
+ - - '='
212
196
  - !ruby/object:Gem::Version
213
- version: '0'
197
+ version: 1.3.4
214
198
  type: :runtime
215
199
  prerelease: false
216
200
  version_requirements: !ruby/object:Gem::Requirement
217
201
  none: false
218
202
  requirements:
219
- - - ! '>='
203
+ - - '='
220
204
  - !ruby/object:Gem::Version
221
- version: '0'
205
+ version: 1.3.4
222
206
  - !ruby/object:Gem::Dependency
223
207
  name: rainbow
224
208
  requirement: !ruby/object:Gem::Requirement
225
209
  none: false
226
210
  requirements:
227
- - - ! '>='
211
+ - - '='
228
212
  - !ruby/object:Gem::Version
229
- version: '0'
213
+ version: 1.1.4
230
214
  type: :runtime
231
215
  prerelease: false
232
216
  version_requirements: !ruby/object:Gem::Requirement
233
217
  none: false
234
218
  requirements:
235
- - - ! '>='
219
+ - - '='
236
220
  - !ruby/object:Gem::Version
237
- version: '0'
221
+ version: 1.1.4
238
222
  - !ruby/object:Gem::Dependency
239
223
  name: activesupport
240
224
  requirement: !ruby/object:Gem::Requirement
@@ -314,6 +298,7 @@ files:
314
298
  - lib/smithy/package.rb
315
299
  - lib/smithy_version.rb
316
300
  - man/man1/smithy.1
301
+ - man/man5/smithyformula.5
317
302
  - smithy.rdoc
318
303
  homepage: https://github.com/AnthonyDiGirolamo/smithy
319
304
  licenses:
@@ -336,7 +321,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
336
321
  version: '0'
337
322
  segments:
338
323
  - 0
339
- hash: -3602502256992475544
324
+ hash: -3203549928499552605
340
325
  required_rubygems_version: !ruby/object:Gem::Requirement
341
326
  none: false
342
327
  requirements:
@@ -345,10 +330,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
345
330
  version: '0'
346
331
  segments:
347
332
  - 0
348
- hash: -3602502256992475544
333
+ hash: -3203549928499552605
349
334
  requirements: []
350
335
  rubyforge_project:
351
- rubygems_version: 1.8.23
336
+ rubygems_version: 1.8.23.2
352
337
  signing_key:
353
338
  specification_version: 3
354
339
  summary: Smithy can help maintain a collection of software installed from source.