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 +1 -1
- data/lib/smithy/description.rb +2 -2
- data/lib/smithy/download_cache.rb +2 -2
- data/lib/smithy/file_operations.rb +8 -8
- data/lib/smithy/formula.rb +7 -6
- data/lib/smithy/formula_command.rb +32 -8
- data/lib/smithy/helpers.rb +5 -5
- data/lib/smithy/package.rb +2 -2
- data/lib/smithy_version.rb +1 -1
- data/man/man1/smithy.1 +1 -1
- data/man/man5/smithyformula.5 +931 -0
- data/smithy.rdoc +1 -1
- metadata +20 -35
data/bin/smithy
CHANGED
data/lib/smithy/description.rb
CHANGED
@@ -215,7 +215,7 @@ module Smithy
|
|
215
215
|
d.write(@content)
|
216
216
|
d.close
|
217
217
|
end
|
218
|
-
puts "updated ".rjust(12)
|
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)
|
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)
|
82
|
+
puts "downloaded ".rjust(12).color(:green) + downloaded_file_path
|
83
83
|
return true
|
84
84
|
else
|
85
|
-
puts "download ".rjust(12).color(:green)
|
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)
|
41
|
+
puts "create ".rjust(12).color(:green) + file
|
42
42
|
end
|
43
43
|
def notice_exist(file)
|
44
|
-
puts "exists ".rjust(12).color(:blue)
|
44
|
+
puts "exists ".rjust(12).color(:blue) + file
|
45
45
|
end
|
46
46
|
def notice_using(file)
|
47
|
-
puts "using ".rjust(12).color(:blue)
|
47
|
+
puts "using ".rjust(12).color(:blue) + file
|
48
48
|
end
|
49
49
|
def notice_link(file1, file2)
|
50
|
-
puts "link ".rjust(12)
|
50
|
+
puts "link ".rjust(12) + file1 + " -> " + file2
|
51
51
|
end
|
52
52
|
def notice_identical(file)
|
53
|
-
puts "identical ".rjust(12).color(:blue)
|
53
|
+
puts "identical ".rjust(12).color(:blue) + file
|
54
54
|
end
|
55
55
|
def notice_conflict(file)
|
56
|
-
puts "conflict ".rjust(12).color(:red)
|
56
|
+
puts "conflict ".rjust(12).color(:red) + file
|
57
57
|
end
|
58
58
|
def notice_force(file)
|
59
|
-
puts "force ".rjust(12).color(:yellow)
|
59
|
+
puts "force ".rjust(12).color(:yellow) + file
|
60
60
|
end
|
61
61
|
def notice_skip(file)
|
62
|
-
puts "skip ".rjust(12)
|
62
|
+
puts "skip ".rjust(12) + file
|
63
63
|
end
|
64
64
|
|
65
65
|
class FileOperations
|
data/lib/smithy/formula.rb
CHANGED
@@ -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
|
-
|
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 =~
|
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]
|
data/lib/smithy/helpers.rb
CHANGED
@@ -37,7 +37,7 @@
|
|
37
37
|
|
38
38
|
module Smithy
|
39
39
|
def notice(message)
|
40
|
-
STDOUT.puts "==> ".color(:blue)
|
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.
|
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)
|
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)
|
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
|
data/lib/smithy/package.rb
CHANGED
@@ -365,7 +365,7 @@ module Smithy
|
|
365
365
|
case magic_bytes
|
366
366
|
when /^PK\003\004/ # .zip archive
|
367
367
|
`unzip #{archive}`
|
368
|
-
|
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)
|
485
|
+
puts "exists ".rjust(12) + f
|
486
486
|
end
|
487
487
|
FileOperations.make_executable file[:dest], options if f =~ /#{ExecutableBuildFileNames.join('|')}/
|
488
488
|
else
|
data/lib/smithy_version.rb
CHANGED
data/man/man1/smithy.1
CHANGED
@@ -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
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.
|
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:
|
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.
|
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.
|
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.
|
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.
|
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:
|
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:
|
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:
|
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:
|
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: -
|
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: -
|
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.
|