fortran_dependencies 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 44dbac005646f5c1f69e22b41a8bc406019ccbce
4
+ data.tar.gz: 6126656a72b400d1b4ea4aed981e15d5eab56e2d
5
+ SHA512:
6
+ metadata.gz: 962ec87f99cb91c0f385f6696a90441c0cc7eb89a56d425dd1658a05c5a567a6592fd39cab26026e9bd1b62806692e87f575994745fb2a9907e1d6dbbf90a82a
7
+ data.tar.gz: 7628050a04d0c3300ee7b3e0d2cb9c128b031d221c7f1f7149e1715fca8238ec9ce6856c915aeed6ed2ff7f9aa5a7b844403c96b7030d7bb9515c6f2df6363e3
@@ -0,0 +1,32 @@
1
+ == 1.1.0 / 2016-01-15
2
+
3
+ * 1 minor enhancement
4
+ * parse included (inlined) files for module use statments
5
+
6
+ == 1.1.0 / 2009-10-28
7
+
8
+ * 1 minor enhancement
9
+ * allow two modules to be defined per source file
10
+
11
+ == 1.0.3 / 2007-11-16
12
+
13
+ * 1 bug fix
14
+ * forgot release notes.
15
+
16
+ == 1.0.2 / 2007-11-16
17
+
18
+ * 1 bug fix
19
+ * repaired gem spec author field (thanks to Eric Hodel).
20
+
21
+ == 1.0.1 / 2007-08-20
22
+
23
+ * 1 minor enhancement
24
+ * stripped './' from source file names to appease windoze.
25
+
26
+ * 1 minor enhancement
27
+ * stripped './' from source file names to appease windoze.
28
+
29
+ == 1.0.0 / 2007-07-26
30
+
31
+ * 1 major enhancement
32
+ * Birthday!
@@ -0,0 +1,263 @@
1
+ == LICENSE
2
+
3
+ NASA OPEN SOURCE AGREEMENT VERSION 1.3
4
+
5
+ THIS OPEN SOURCE AGREEMENT ("AGREEMENT") DEFINES THE RIGHTS OF USE,
6
+ REPRODUCTION, DISTRIBUTION, MODIFICATION AND REDISTRIBUTION OF CERTAIN
7
+ COMPUTER SOFTWARE ORIGINALLY RELEASED BY THE UNITED STATES GOVERNMENT
8
+ AS REPRESENTED BY THE GOVERNMENT AGENCY LISTED BELOW ("GOVERNMENT
9
+ AGENCY"). THE UNITED STATES GOVERNMENT, AS REPRESENTED BY GOVERNMENT
10
+ AGENCY, IS AN INTENDED THIRD-PARTY BENEFICIARY OF ALL SUBSEQUENT
11
+ DISTRIBUTIONS OR REDISTRIBUTIONS OF THE SUBJECT SOFTWARE. ANYONE WHO
12
+ USES, REPRODUCES, DISTRIBUTES, MODIFIES OR REDISTRIBUTES THE SUBJECT
13
+ SOFTWARE, AS DEFINED HEREIN, OR ANY PART THEREOF, IS, BY THAT ACTION,
14
+ ACCEPTING IN FULL THE RESPONSIBILITIES AND OBLIGATIONS CONTAINED IN
15
+ THIS AGREEMENT.
16
+
17
+ Government Agency: NASA Langley Research Center
18
+ Government Agency Original Software Designation: LAR-17081-1
19
+ Government Agency Original Software Title: fUnit
20
+ User Registration Requested: please see clause 3.F.
21
+ Government Agency Point of Contact: please see clause 5.F.
22
+
23
+ 1. DEFINITIONS
24
+
25
+ A. "Contributor" means Government Agency, as the developer of the
26
+ Original Software, and any entity that makes a Modification.
27
+
28
+ B. "Covered Patents" mean patent claims licensable by a Contributor
29
+ that are necessarily infringed by the use or sale of its Modification
30
+ alone or when combined with the Subject Software.
31
+
32
+ C. "Display" means the showing of a copy of the Subject Software,
33
+ either directly or by means of an image, or any other device.
34
+
35
+ D. "Distribution" means conveyance or transfer of the Subject
36
+ Software, regardless of means, to another.
37
+
38
+ E. "Larger Work" means computer software that combines Subject
39
+ Software, or portions thereof, with software separate from the Subject
40
+ Software that is not governed by the terms of this Agreement.
41
+
42
+ F. "Modification" means any alteration of, including addition to or
43
+ deletion from, the substance or structure of either the Original
44
+ Software or Subject Software, and includes derivative works, as that
45
+ term is defined in the Copyright Statute, 17 USC 101. However, the
46
+ act of including Subject Software as part of a Larger Work does not in
47
+ and of itself constitute a Modification.
48
+
49
+ G. "Original Software" means the computer software first released
50
+ under this Agreement by Government Agency with Government Agency
51
+ designation NASA and entitled fUnit, including source code,
52
+ object code and accompanying documentation, if any.
53
+
54
+ H. "Recipient" means anyone who acquires the Subject Software under
55
+ this Agreement, including all Contributors.
56
+
57
+ I. "Redistribution" means Distribution of the Subject Software after a
58
+ Modification has been made.
59
+
60
+ J. "Reproduction" means the making of a counterpart, image or copy of
61
+ the Subject Software.
62
+
63
+ K. "Sale" means the exchange of the Subject Software for money or
64
+ equivalent value.
65
+
66
+ L. "Subject Software" means the Original Software, Modifications, or
67
+ any respective parts thereof.
68
+
69
+ M. "Use" means the application or employment of the Subject Software
70
+ for any purpose.
71
+
72
+ 2. GRANT OF RIGHTS
73
+
74
+ A. Under Non-Patent Rights: Subject to the terms and conditions of
75
+ this Agreement, each Contributor, with respect to its own contribution
76
+ to the Subject Software, hereby grants to each Recipient a
77
+ non-exclusive, world-wide, royalty-free license to engage in the
78
+ following activities pertaining to the Subject Software:
79
+
80
+ 1. Use
81
+ 2. Distribution
82
+ 3. Reproduction
83
+ 4. Modification
84
+ 5. Redistribution
85
+ 6. Display
86
+
87
+ B. Under Patent Rights: Subject to the terms and conditions of this
88
+ Agreement, each Contributor, with respect to its own contribution to
89
+ the Subject Software, hereby grants to each Recipient under Covered
90
+ Patents a non-exclusive, world-wide, royalty-free license to engage in
91
+ the following activities pertaining to the Subject Software:
92
+
93
+ 1. Use
94
+ 2. Distribution
95
+ 3. Reproduction
96
+ 4. Sale
97
+ 5. Offer for Sale
98
+
99
+ C. The rights granted under Paragraph B. also apply to the combination
100
+ of a Contributor's Modification and the Subject Software if, at the
101
+ time the Modification is added by the Contributor, the addition of
102
+ such Modification causes the combination to be covered by the Covered
103
+ Patents. It does not apply to any other combinations that include a
104
+ Modification.
105
+
106
+ D. The rights granted in Paragraphs A. and B. allow the Recipient to
107
+ sublicense those same rights. Such sublicense must be under the same
108
+ terms and conditions of this Agreement.
109
+
110
+ 3. OBLIGATIONS OF RECIPIENT
111
+
112
+ A. Distribution or Redistribution of the Subject Software must be made
113
+ under this Agreement except for additions covered under paragraph 3H.
114
+
115
+ 1. Whenever a Recipient distributes or redistributes the Subject
116
+ Software, a copy of this Agreement must be included with each copy
117
+ of the Subject Software; and
118
+
119
+ 2. If Recipient distributes or redistributes the Subject Software in
120
+ any form other than source code, Recipient must also make the
121
+ source code freely available, and must provide with each copy of
122
+ the Subject Software information on how to obtain the source code
123
+ in a reasonable manner on or through a medium customarily used for
124
+ software exchange.
125
+
126
+ B. Each Recipient must ensure that the following copyright notice
127
+ appears prominently in the Subject Software:
128
+
129
+ Copyright 2007 United States Government as represented by
130
+ NASA Langley Research Center. No copyright is claimed in
131
+ the United States under Title 17, U.S. Code. All Other Rights
132
+ Reserved.
133
+
134
+ C. Each Contributor must characterize its alteration of the Subject
135
+ Software as a Modification and must identify itself as the originator
136
+ of its Modification in a manner that reasonably allows subsequent
137
+ Recipients to identify the originator of the Modification. In
138
+ fulfillment of these requirements, Contributor must include a file
139
+ (e.g., a change log file) that describes the alterations made and the
140
+ date of the alterations, identifies Contributor as originator of the
141
+ alterations, and consents to characterization of the alterations as a
142
+ Modification, for example, by including a statement that the
143
+ Modification is derived, directly or indirectly, from Original
144
+ Software provided by Government Agency. Once consent is granted, it
145
+ may not thereafter be revoked.
146
+
147
+ D. A Contributor may add its own copyright notice to the Subject
148
+ Software. Once a copyright notice has been added to the Subject
149
+ Software, a Recipient may not remove it without the express permission
150
+ of the Contributor who added the notice.
151
+
152
+ E. A Recipient may not make any representation in the Subject Software
153
+ or in any promotional, advertising or other material that may be
154
+ construed as an endorsement by Government Agency or by any prior
155
+ Recipient of any product or service provided by Recipient, or that may
156
+ seek to obtain commercial advantage by the fact of Government Agency's
157
+ or a prior Recipient's participation in this Agreement.
158
+
159
+ F. In an effort to track usage and maintain accurate records of the
160
+ Subject Software, each Recipient, upon receipt of the Subject Software,
161
+ is requested to provide Government Agency, by e-mail to the Government
162
+ Agency Point of Contact listed in clause 5.F., the following information:
163
+ name, institution (if applicable), postal code, and country.
164
+ Recipient's name and personal information shall be used for statistical
165
+ purposes only. Once a Recipient makes a Modification available, it is
166
+ requested that the Recipient inform Government Agency, by e-mail to the
167
+ Government Agency Point of Contact listed in clause 5.F., how to
168
+ access the Modification.
169
+
170
+ G. Each Contributor represents that that its Modification is believed
171
+ to be Contributor's original creation and does not violate any
172
+ existing agreements, regulations, statutes or rules, and further that
173
+ Contributor has sufficient rights to grant the rights conveyed by this
174
+ Agreement.
175
+
176
+ H. A Recipient may choose to offer, and to charge a fee for, warranty,
177
+ support, indemnity and/or liability obligations to one or more other
178
+ Recipients of the Subject Software. A Recipient may do so, however,
179
+ only on its own behalf and not on behalf of Government Agency or any
180
+ other Recipient. Such a Recipient must make it absolutely clear that
181
+ any such warranty, support, indemnity and/or liability obligation is
182
+ offered by that Recipient alone. Further, such Recipient agrees to
183
+ indemnify Government Agency and every other Recipient for any
184
+ liability incurred by them as a result of warranty, support, indemnity
185
+ and/or liability offered by such Recipient.
186
+
187
+ I. A Recipient may create a Larger Work by combining Subject Software
188
+ with separate software not governed by the terms of this agreement and
189
+ distribute the Larger Work as a single product. In such case, the
190
+ Recipient must make sure Subject Software, or portions thereof,
191
+ included in the Larger Work is subject to this Agreement.
192
+
193
+ J. Notwithstanding any provisions contained herein, Recipient is
194
+ hereby put on notice that export of any goods or technical data from
195
+ the United States may require some form of export license from the
196
+ U.S. Government. Failure to obtain necessary export licenses may
197
+ result in criminal liability under U.S. laws. Government Agency
198
+ neither represents that a license shall not be required nor that, if
199
+ required, it shall be issued. Nothing granted herein provides any
200
+ such export license.
201
+
202
+ 4. DISCLAIMER OF WARRANTIES AND LIABILITIES; WAIVER AND INDEMNIFICATION
203
+
204
+ A. No Warranty: THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY
205
+ WARRANTY OF ANY KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY,
206
+ INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE
207
+ WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF
208
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR FREEDOM FROM
209
+ INFRINGEMENT, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL BE ERROR
210
+ FREE, OR ANY WARRANTY THAT DOCUMENTATION, IF PROVIDED, WILL CONFORM TO
211
+ THE SUBJECT SOFTWARE. THIS AGREEMENT DOES NOT, IN ANY MANNER,
212
+ CONSTITUTE AN ENDORSEMENT BY GOVERNMENT AGENCY OR ANY PRIOR RECIPIENT
213
+ OF ANY RESULTS, RESULTING DESIGNS, HARDWARE, SOFTWARE PRODUCTS OR ANY
214
+ OTHER APPLICATIONS RESULTING FROM USE OF THE SUBJECT SOFTWARE.
215
+ FURTHER, GOVERNMENT AGENCY DISCLAIMS ALL WARRANTIES AND LIABILITIES
216
+ REGARDING THIRD-PARTY SOFTWARE, IF PRESENT IN THE ORIGINAL SOFTWARE,
217
+ AND DISTRIBUTES IT "AS IS."
218
+
219
+ B. Waiver and Indemnity: RECIPIENT AGREES TO WAIVE ANY AND ALL CLAIMS
220
+ AGAINST THE UNITED STATES GOVERNMENT, ITS CONTRACTORS AND
221
+ SUBCONTRACTORS, AS WELL AS ANY PRIOR RECIPIENT. IF RECIPIENT'S USE OF
222
+ THE SUBJECT SOFTWARE RESULTS IN ANY LIABILITIES, DEMANDS, DAMAGES,
223
+ EXPENSES OR LOSSES ARISING FROM SUCH USE, INCLUDING ANY DAMAGES FROM
224
+ PRODUCTS BASED ON, OR RESULTING FROM, RECIPIENT'S USE OF THE SUBJECT
225
+ SOFTWARE, RECIPIENT SHALL INDEMNIFY AND HOLD HARMLESS THE UNITED
226
+ STATES GOVERNMENT, ITS CONTRACTORS AND SUBCONTRACTORS, AS WELL AS ANY
227
+ PRIOR RECIPIENT, TO THE EXTENT PERMITTED BY LAW. RECIPIENT'S SOLE
228
+ REMEDY FOR ANY SUCH MATTER SHALL BE THE IMMEDIATE, UNILATERAL
229
+ TERMINATION OF THIS AGREEMENT.
230
+
231
+ 5. GENERAL TERMS
232
+
233
+ A. Termination: This Agreement and the rights granted hereunder will
234
+ terminate automatically if a Recipient fails to comply with these
235
+ terms and conditions, and fails to cure such noncompliance within
236
+ thirty (30) days of becoming aware of such noncompliance. Upon
237
+ termination, a Recipient agrees to immediately cease use and
238
+ distribution of the Subject Software. All sublicenses to the Subject
239
+ Software properly granted by the breaching Recipient shall survive any
240
+ such termination of this Agreement.
241
+
242
+ B. Severability: If any provision of this Agreement is invalid or
243
+ unenforceable under applicable law, it shall not affect the validity
244
+ or enforceability of the remainder of the terms of this Agreement.
245
+
246
+ C. Applicable Law: This Agreement shall be subject to United States
247
+ federal law only for all purposes, including, but not limited to,
248
+ determining the validity of this Agreement, the meaning of its
249
+ provisions and the rights, obligations and remedies of the parties.
250
+
251
+ D. Entire Understanding: This Agreement constitutes the entire
252
+ understanding and agreement of the parties relating to release of the
253
+ Subject Software and may not be superseded, modified or amended except
254
+ by further written agreement duly executed by the parties.
255
+
256
+ E. Binding Authority: By accepting and using the Subject Software
257
+ under this Agreement, a Recipient affirms its authority to bind the
258
+ Recipient to all terms and conditions of this Agreement and that that
259
+ Recipient hereby agrees to all terms and conditions herein.
260
+
261
+ F. Point of Contact: Any Recipient contact with Government Agency is
262
+ to be directed to the designated representative as follows:
263
+ Bil.Kleb@NASA.gov
@@ -0,0 +1,7 @@
1
+ History.txt
2
+ License.txt
3
+ Manifest.txt
4
+ README.txt
5
+ Rakefile
6
+ lib/fortran.rb
7
+ test/test_fortran.rb
@@ -0,0 +1,31 @@
1
+ fortran
2
+
3
+ * http://nasarb.rubyforge.org/fortran
4
+ * http://rubyforge.org/projects/nasarb
5
+ * mailto:Bil.Kleb@nasa.gov
6
+
7
+ == DESCRIPTION:
8
+
9
+ Fortran 90/95/2003 utilities.
10
+
11
+ Currently, only provides Fortran 90/95/2003 dependencies.
12
+
13
+ == SYNOPSIS:
14
+
15
+ require 'rubygems'
16
+ require 'fortran'
17
+
18
+ Fortran::Dependencies.new( 'main.f90' ).dependencies
19
+
20
+ == REQUIREMENTS:
21
+
22
+ * Ruby with Rubygems
23
+
24
+ == INSTALL:
25
+
26
+ * <tt>sudo gem install fortran</tt>
27
+
28
+ == LICENSE
29
+
30
+ Released under the NASA Open Source Agreement -- see License.txt[link:files/License_txt.html] for details.
31
+
@@ -0,0 +1,173 @@
1
+ module Fortran
2
+
3
+ ##
4
+ # This version of Fortran library
5
+
6
+ VERSION = '1.2.0'
7
+
8
+ ##
9
+ # Find Fortran dependencies
10
+
11
+ class Dependencies
12
+
13
+ OPTIONS = { :search_paths => [ '.', '../lib' ],
14
+ :ignore_files => %r{ },
15
+ :ignore_modules => %r{ },
16
+ :ignore_symlinks => true }
17
+
18
+ USE_MODULE_REGEX = /^\s*use\s+(\w+)/i
19
+ MODULE_DEF_REGEX = /^\s*module\s+(\w+)/i
20
+ MODULE_INCLUDE_REGEX = /\s*include\s+('|")(\w+\.(f|F)90)('|")/i
21
+
22
+ FILE_EXTENSION = /\.f90$/i
23
+
24
+ attr_reader :file_dependencies, :source_files
25
+
26
+ def initialize( config=OPTIONS )
27
+ @config = config
28
+ OPTIONS.each{ |opt,default| @config[opt] = default unless @config.has_key? opt }
29
+ @parsed, @file_dependencies, @source_files = [], {}, []
30
+ @hash = build_hash_of_modules_in_files
31
+ @included_files = build_hash_of_non_module_files
32
+ self
33
+ end
34
+
35
+ def modules_used_in( file )
36
+ modules = IO.readlines( file ).map do |line|
37
+ $1.downcase if line.match USE_MODULE_REGEX
38
+ end.uniq.compact
39
+ end
40
+
41
+ def modules_defined_in( file )
42
+ modules = IO.readlines( file ).map do |line|
43
+ $1.downcase if line.match MODULE_DEF_REGEX
44
+ end.uniq.compact
45
+ end
46
+
47
+ def files_included_in( file )
48
+ files = IO.readlines( file ).map do |line|
49
+ $2 if line.match MODULE_INCLUDE_REGEX
50
+ end.uniq.compact
51
+ end
52
+
53
+ def build_dictionary_of_modules( files )
54
+ file_containing_module = {}
55
+ files.each do |file|
56
+ modules_defined_in( file ).each{ |mod| file_containing_module[mod]=file }
57
+ end
58
+ file_containing_module
59
+ end
60
+
61
+ def find_fortran_files
62
+ source = @config[:search_paths].map{ |path| Dir[path+"/*.[fF]90"] }
63
+ source.flatten!.uniq!
64
+ source.delete_if{ |file| File.lstat(file).symlink? } if @config[:ignore_symlinks]
65
+ source.delete_if{ |file| file.match @config[:ignore_files] }
66
+ source.map!{ |file| file.sub(/^\.\//,'') }# strip leading ./
67
+ end
68
+
69
+ def build_hash_of_non_module_files
70
+ files = find_fortran_files
71
+ included_files = {}
72
+ files.each do |file|
73
+ unless file_is_module?(file)
74
+ included_files[File.basename(file)] = file
75
+ end
76
+ end
77
+ included_files
78
+ end
79
+
80
+ def file_is_module?(file)
81
+ IO.readlines( file ).map do |line|
82
+ return true if line.match MODULE_DEF_REGEX
83
+ end
84
+ return false
85
+ end
86
+
87
+ def build_hash_of_modules_in_files
88
+ build_dictionary_of_modules find_fortran_files
89
+ end
90
+
91
+ def modules_in_included_files( file )
92
+ modules = files_included_in( file ).map do |included_file|
93
+ modules_used_in(@included_files[included_file])
94
+ end.flatten.uniq.compact
95
+ end
96
+
97
+ def makefile_dependency_line( source )
98
+ real_source = source.sub(/PHYSICS_DUMMY/,'PHYSICS_MODULES')# FIXME: What's this?!
99
+ source_no_path = File.basename source
100
+ @source_files.push source_no_path.gsub(%r|^.*/|,'')
101
+ output = ''
102
+ if (File.expand_path(source) != File.expand_path(source_no_path))
103
+ output += source_no_path+ ": " + real_source + "\n"
104
+ output += "\tln -sf "+real_source+" .\n"
105
+ end
106
+ output += source.gsub(FILE_EXTENSION, ".o").gsub(%r|^.*/|,'' ) +
107
+ ": " + source.gsub(%r|^.*/|,"" )
108
+ modules_used_in( source ).each do |use|
109
+ unless @hash[use]
110
+ unless use.match @config[:ignore_modules]
111
+ $stderr.puts 'Warning: unable to locate module #{use} used in #{source}.'
112
+ $stderr.puts ' set :search_paths or :ignore_module_regex options.'
113
+ end
114
+ next
115
+ end
116
+ output = output + " \\\n " +
117
+ @hash[use].gsub(FILE_EXTENSION, ".o").gsub(%r|^.*/|,'' )
118
+ end
119
+ output+"\n"
120
+ end
121
+
122
+ def dependencies( start )
123
+ modules = modules_used_in( start )
124
+ @parsed = @parsed || [start]
125
+ new_source_files = modules.collect{ |mod| @hash[mod] }.compact
126
+ makefile_dependency_line(start) +
127
+ new_source_files.collect do |file|
128
+ next if @parsed.include?(file)
129
+ @parsed.push file
130
+ dependencies file
131
+ end.to_s
132
+ end
133
+
134
+ def source_file_dependencies( head_f90 )
135
+ modules_head_uses = modules_used_in( head_f90 )
136
+ modules_head_uses += modules_in_included_files( head_f90 )
137
+ required_f90s = modules_head_uses.map{ |mod| @hash[mod] }.compact
138
+ required_f90s.delete_if{ |f| f == head_f90 }
139
+ @file_dependencies[head_f90] = required_f90s
140
+ required_f90s.each do |required_f90|
141
+ next if @parsed.include?(required_f90)
142
+ source_file_dependencies( required_f90 )
143
+ end
144
+ @parsed.push head_f90
145
+ end
146
+
147
+ def required_source_files( head_f90 )
148
+ @parsed.clear
149
+ source_file_dependencies( head_f90 )
150
+ sources = []
151
+ until @file_dependencies.empty? do
152
+ no_dependents_pair = @file_dependencies.detect{ |h,d| d == [] }
153
+ no_dependents = no_dependents_pair.first
154
+ sources.push no_dependents
155
+ @file_dependencies.delete(no_dependents){ |el| "#{el} not found" }
156
+ @file_dependencies.each_value{ |deps| deps.delete(no_dependents) }
157
+ end
158
+ sources
159
+ end
160
+
161
+ end # class
162
+
163
+ end # module
164
+
165
+ #--
166
+ # Copyright 2007 United States Government as represented by
167
+ # NASA Langley Research Center. No copyright is claimed in
168
+ # the United States under Title 17, U.S. Code. All Other Rights
169
+ # Reserved.
170
+ #
171
+ # This file is governed by the NASA Open Source Agreement.
172
+ # See License.txt for details.
173
+ #++
@@ -0,0 +1,323 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # For a given directory, this routine will find the
4
+ # dependency levels of resident *90 files and various
5
+ # code complexify measures per Lakos' /Large Scale
6
+ # C++ Software Design/ book.
7
+ #
8
+ # Usage:
9
+ #
10
+ # To do an entire directory,
11
+ #
12
+ # HEFSS.rps/FUN3D_90
13
+ # ../Ruby/CASE_tools/analyze_dependencies.rb
14
+ #
15
+ # If a main.*90 is found, the results will be sorted by level
16
+ # and a HTML summary page will be produced to add navigation.
17
+ #
18
+ # To do a set of files, pass their names as arguments,
19
+ #
20
+ # ../Ruby/CASE_tools/analyze_dependencies.rb main.F90 project.f90 [..]
21
+ #
22
+ # Results, consising of text and Graphviz dot files,
23
+ # are deposited in a subdirectory according to DROP_DIR
24
+ # set below.
25
+
26
+ SEARCH_PATH = %w[ ../LibF90 ../PHYSICS_MODULES ../PHYSICS_DEPS . ]
27
+ DROP_DIR = 'Lakos'
28
+
29
+ require 'fortran'
30
+
31
+ ##
32
+ # add a deep clone method to completely duplicate hashes
33
+
34
+ class Object
35
+ def deep_clone; Marshal::load(Marshal.dump(self)); end
36
+ end
37
+
38
+ ##
39
+ # add a cleaning method for FUN3D file names
40
+
41
+ class String
42
+ def fun3d_clean
43
+ File.basename(self).sub(/_module/i,'').sub(/\.f90$/i,'')
44
+ end
45
+ end
46
+
47
+ class DependencyAnalyzer
48
+
49
+ attr_reader :use_deps, :tc_deps, :dd_deps, :lvl_deps,
50
+ :levels, :components, :ccd, :acd, :nccd
51
+
52
+ def initialize( head, search_path=SEARCH_PATH )
53
+ @head = head
54
+ @levels = Hash.new{ |hash,key| hash[key]=Array.new }
55
+ @tc_deps = Hash.new{ |hash,key| hash[key]=Array.new }
56
+ @use_deps = Hash.new
57
+ shorten_dependency_file_names(find_file_dependencies(head,search_path))
58
+ find_levels_of_dependencies(@use_deps.deep_clone)
59
+ find_transitive_closure_graph
60
+ compute_stats
61
+ find_direct_dependencies_graph
62
+ find_level_dependencies_graph
63
+ end
64
+
65
+ def compute_stats
66
+ @components = 0; @levels.each_value{ |v| @components += v.size }
67
+ @ccd = 0; @tc_deps.each_value{ |dependents| @ccd += dependents.size + 1 }
68
+ @acd = @ccd/@components.to_f
69
+ ccd_binary_tree = (@components+1)*(Math::log(@components+1)/Math::log(2)-1)+1
70
+ @nccd = @ccd / ccd_binary_tree
71
+ end
72
+
73
+ def find_file_dependencies( head, search_path )
74
+ depend = Fortran::Dependencies.new( :search_path => search_path )
75
+ depend.source_file_dependencies(head)
76
+ depend.file_dependencies
77
+ end
78
+
79
+ def shorten_dependency_file_names(deps)
80
+ deps.each_pair do |file,dependents|
81
+ @use_deps[file] = dependents
82
+ end
83
+ end
84
+
85
+ def find_transitive_closure_graph
86
+ # turn the hash into a sorted array to assure bottom-to-top ordering
87
+ @levels.sort.each do |pair|
88
+ components = pair.last
89
+ components.each do |component|
90
+ @tc_deps[component] = @use_deps[component].clone
91
+ @use_deps[component].each do |dependent|
92
+ @tc_deps[component].push @tc_deps[dependent].clone
93
+ end
94
+ @tc_deps[component].flatten!
95
+ @tc_deps[component].uniq!
96
+ end
97
+ end
98
+ end
99
+
100
+ def find_direct_dependencies_graph
101
+ @dd_deps = Hash.new
102
+ @tc_deps.each{|k,v| @dd_deps[k] = @tc_deps[k].clone}
103
+ # turn the hash into a sorted array to assure bottom-to-top ordering
104
+ @levels.sort.each do |pair|
105
+ components = pair.last
106
+ components.each do |component|
107
+ @dd_deps[component].each do |dependent|
108
+ @dd_deps[component] -= @dd_deps[dependent]
109
+ end
110
+ end
111
+ end
112
+ end
113
+
114
+ def level_of(component)
115
+ @levels.
116
+ select{ |level,components| components.include?(component) }.
117
+ flatten.first
118
+ end
119
+
120
+ # only the dependencies "holding up" the levels
121
+ def find_level_dependencies_graph
122
+ long_distance_dependents = Array.new
123
+ @lvl_deps = @dd_deps.deep_clone
124
+ @levels.sort.reverse.each do |pair|
125
+ level, components = pair
126
+ components.each do |component|
127
+ long_distance_dependents.clear
128
+ @dd_deps[component].each do |dependent|
129
+ long_distance_dependents << dependent if level_of(dependent) < level-1
130
+ end
131
+ @lvl_deps[component] -= long_distance_dependents
132
+ end
133
+ end
134
+ end
135
+
136
+ def find_levels_of_dependencies(deps)
137
+ level = 1
138
+ until deps.empty? do
139
+ deps.each{ |file,dependents| @levels[level] << file if dependents.empty? }
140
+ deps.delete_if{ |file,dependents| @levels[level].include?(file) }
141
+ deps.each do |file,dependents|
142
+ dependents.delete_if{ |dependent| @levels[level].include?(dependent) }
143
+ end
144
+ level += 1
145
+ end
146
+ @levels
147
+ end
148
+
149
+ def summary
150
+ result = Array.new
151
+ result << "COMPONENT:\n"
152
+ result << " #@head"
153
+ result << "\nSUMMARY:\n"
154
+ result << " Components: #@components"
155
+ result << " Levels: #{@levels.size}"
156
+ result << " CCD: #@ccd [Cumulative Component Dependency]"
157
+ result << " ACD: #{sprintf('%.1f',@acd)} (average CD)"
158
+ result << " NCCD: #{sprintf('%.2f',@nccd)} (normalized CCD -- desired: 0.85 to 1.10)"
159
+ result << "\nLEVELS:\n"
160
+ @levels.sort.each do |pair|
161
+ result << "#{pair.first}:".rjust(3)
162
+ pair.last.each{ |component| result << " #{component.sub(/\.*\//,'')}" }
163
+ end
164
+ result.join "\n"
165
+ end
166
+
167
+ def graph( deps )
168
+ graph = ''
169
+ graph << "digraph G {\n"
170
+ graph << " ratio=0.67;\n"
171
+ graph << " label=\"#{File.basename(Dir.pwd)}/#{@head}\\n"
172
+ graph << "#{Time.now}\\n"
173
+ graph << "Lakos Levels/Components/CCD/ACD/NCCD\\n"
174
+ graph << "#{@levels.size}/#@components/#@ccd/#{sprintf('%.1f',@acd)}/#{sprintf('%.2f',@nccd)}\\n"
175
+ graph << "\";\n"
176
+ # graph << " nodesep=0.3;\n"
177
+ graph << " fontname=GillSans; fontsize=24;\n"
178
+ graph << " node [fontname=GillSans,fontsize=24,shape=plaintext];\n"
179
+ graph << " edge [arrowhead=none];\n"
180
+ graph << "{ node [shape=box];"
181
+ (@levels.size).downto(2){ |lvl| graph << " #{lvl}->#{lvl-1};" }
182
+ graph << " };\n"
183
+ @levels.each do |level,components|
184
+ graph << "{ rank = same; #{level}; \"#{components.map{|c| c.fun3d_clean}.join('"; "')}\"; }\n"
185
+ end
186
+ deps.each do |file,dependents|
187
+ dependents.each do |dependent|
188
+ graph << "\"#{file.fun3d_clean}\" -> \"#{dependent.fun3d_clean}\";\n"
189
+ end
190
+ end
191
+ graph << "}"
192
+ graph
193
+ end
194
+
195
+ end # class
196
+
197
+ if $0 == __FILE__ then
198
+
199
+ require 'fileutils'
200
+
201
+ dot_capable = system("which dot") and system("which epstopdf")
202
+
203
+ Dir.mkdir DROP_DIR unless File.exist? DROP_DIR
204
+
205
+ if ARGV.empty?
206
+ directory = true
207
+ files = Dir["*90"]
208
+ else
209
+ directory = false
210
+ files = ARGV.map{|a| a.dup}
211
+ end
212
+
213
+ files.delete_if{ |f| !File.exists? f }
214
+
215
+ # sort the file list by level if the big cahuna is present
216
+ if directory
217
+ if files.include?('main.F90') then
218
+ da = DependencyAnalyzer.new( 'main.F90' )
219
+ elsif files.include?('main.f90') then
220
+ da = DependencyAnalyzer.new( 'main.f90' )
221
+ end
222
+ files.clear
223
+ da.levels.sort.reverse.each{|pair| files.push pair.last }
224
+ files.flatten!
225
+ end
226
+
227
+ File.open(File.join(DROP_DIR,'index.html'),'w') do |index|
228
+
229
+ pwd = File.basename(Dir.pwd)
230
+
231
+ index.puts "<html>"
232
+ index.puts " <head><title>#{pwd}</title></head>"
233
+ index.puts "<body>"
234
+ index.puts "<h1>#{pwd}</h1>"
235
+ index.puts "Data generated by #$0 at #{Time.now}."
236
+ index.puts "<table cellspacing=10>"
237
+ index.puts " <tr>"
238
+ index.puts " <th colspan=5>Statistics</th>"
239
+ index.puts " <th></th>"
240
+ index.puts " <th colspan=2>Dependency Plots</th>"
241
+ index.puts " </tr>"
242
+ index.puts " <tr>"
243
+ index.puts " <th>Level</th>"
244
+ index.puts " <th>#Cs</th>"
245
+ index.puts " <th>CCD</th>"
246
+ index.puts " <th>ACD</th>"
247
+ index.puts " <th>NCCD</th>"
248
+ index.puts " <th></th>"
249
+ index.puts " <th>Use</th>"
250
+ index.puts " <th>Level</th>"
251
+ index.puts " <th align=left>Source</th>"
252
+ index.puts " </tr>"
253
+
254
+ files.each_with_index do |file,number|
255
+
256
+ $stderr.puts "Analyzing #{number+1} of #{files.size}: #{file}"
257
+ $stderr.flush
258
+
259
+ da = DependencyAnalyzer.new( file )
260
+
261
+ FileUtils.copy( file, DROP_DIR )
262
+
263
+ rootname = File.join(DROP_DIR,File.basename(file).fun3d_clean.sub(/\.f90$/i,''))
264
+
265
+ File.open(rootname+'.txt', 'w'){ |f| f.puts da.summary }
266
+ File.open(rootname+'_use.dot','w'){ |f| f.puts da.graph(da.use_deps) }
267
+ File.open(rootname+'_lvl.dot','w'){ |f| f.puts da.graph(da.lvl_deps) }
268
+
269
+ if dot_capable
270
+ puts command = " dot -Tps #{rootname}_lvl.dot -o #{rootname}_lvl.ps" +
271
+ " && epstopdf #{rootname}_lvl.ps"
272
+ system command
273
+ puts command = " dot -Tps #{rootname}_use.dot -o #{rootname}_use.ps" +
274
+ " && epstopdf #{rootname}_use.ps"
275
+ system command
276
+ end
277
+
278
+ root = File.basename(rootname)
279
+
280
+ index.puts " <tr>"
281
+ index.puts " <td align=right>#{da.levels.size}</td>"
282
+ index.puts " <td align=right>#{da.components}</td>"
283
+ index.puts " <td align=right>#{da.ccd}</td>"
284
+ index.puts " <td align=right>#{sprintf('%.1f',da.acd)}</td>"
285
+ index.puts " <td align=right>#{sprintf('%.2f',da.nccd)}</td>"
286
+ index.puts " <td><a href='#{root}.txt'>(details)</a></td>"
287
+ index.puts " <td><a href='#{root}_use.dot'>dot</a>|" +
288
+ "<a href='#{root}_use.ps'>PS</a>|" +
289
+ "<a href='#{root}_use.pdf'>PDF</a></td>"
290
+ index.puts " <td><a href='#{root}_lvl.dot'>dot</a>|" +
291
+ "<a href='#{root}_lvl.ps'>PS</a>|" +
292
+ "<a href='#{root}_lvl.pdf'>PDF</a></td>"
293
+ index.puts " <td><a href='#{File.basename(file)}'>#{File.basename(file)}</a></td>"
294
+ index.puts " </tr>"
295
+
296
+ end
297
+
298
+ if files.size > 20
299
+ index.puts " <tr>"
300
+ index.puts " <th>Level</th>"
301
+ index.puts " <th>#Cs</th>"
302
+ index.puts " <th>CCD</th>"
303
+ index.puts " <th>ACD</th>"
304
+ index.puts " <th>NCCD</th>"
305
+ index.puts " <th></th>"
306
+ index.puts " <th>Use</th>"
307
+ index.puts " <th>Level</th>"
308
+ index.puts " <th align=left>Source</th>"
309
+ index.puts " </tr>"
310
+ index.puts " <tr>"
311
+ index.puts " <th colspan=5>Statistics</th>"
312
+ index.puts " <th></th>"
313
+ index.puts " <th colspan=2>Dependency Plots</th>"
314
+ index.puts " </tr>"
315
+ end
316
+
317
+ index.puts "</table>"
318
+ index.puts "</body>"
319
+ index.puts "</html>"
320
+
321
+ end
322
+
323
+ end
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ CODES = %w[ Adapt Design Adjoint FUN3D_90 GetGrad GridMove Party PartyMPI ]
4
+
5
+ require 'fileutils'
6
+
7
+ FileUtils.rm_rf 'Lakos' if File.exist? 'Lakos'
8
+ Dir.mkdir 'Lakos'
9
+
10
+ File.open('Lakos/index.html','w') do |index|
11
+
12
+ index.puts "<h1> Lakos-Style Physical Dependency Analysis</h1>"
13
+ index.puts "<p>This snapshot brought to you by #$0.</p>"
14
+ index.puts "<p>Started: #{Time.now}.</p>"
15
+ index.puts "<ul>"
16
+
17
+ CODES.each do |code|
18
+ puts "#{code}"
19
+ puts "=" * code.length
20
+ Dir.chdir code
21
+ if system '../Ruby/CASE_tools/analyze_dependencies.rb'# add main.?90
22
+ FileUtils.mv 'Lakos', "../Lakos/#{code}", {:force=>true}
23
+ index.puts "<li><a href='#{code}/index.html'>#{code}</a></li>"
24
+ else
25
+ $stderr.puts "Failed to make dependency plots for #{code}."
26
+ end
27
+ Dir.chdir '..'
28
+ puts
29
+ end
30
+
31
+ index.puts "</ul>"
32
+ index.puts "<p>Completed: #{Time.now}.</p>"
33
+
34
+ end
35
+
36
+ FileUtils.rm_rf '/var/www/html/HEFSS/Lakos' if File.exist? '/var/www/html/HEFSS/Lakos'
37
+ FileUtils.cp_r 'Lakos', '/var/www/html/HEFSS'
@@ -0,0 +1,35 @@
1
+ require 'test/unit'
2
+ require 'lakos/analyze_dependencies'
3
+ require 'fileutils'
4
+
5
+ class TestAnalyzeDependencies < Test::Unit::TestCase
6
+
7
+ def setup
8
+ FileUtils.rm_rf 'AD_fixtures'
9
+ Dir.mkdir 'AD_fixtures'
10
+ Dir.chdir 'AD_fixtures'
11
+ File.open('m.f90','w'){|f| f.puts "program m\nuse a\nuse b\nuse d\nuse f" }
12
+ File.open('a.f90','w'){|f| f.puts "module a" }
13
+ File.open('b.f90','w'){|f| f.puts "module b\nuse c\nuse d\nuse e" }
14
+ File.open('c.f90','w'){|f| f.puts "module c" }
15
+ File.open('d.f90','w'){|f| f.puts "module d" }
16
+ File.open('e.f90','w'){|f| f.puts "module e" }
17
+ File.open('f.f90','w'){|f| f.puts "module f\nuse c\nuse e" }
18
+ @da = DependencyAnalyzer.new( 'm.f90', ['.'] )
19
+ Dir.chdir '..'
20
+ File.open('main.dot','w'){ |f| f.puts @da.graph(@da.dd_deps) }
21
+ end
22
+
23
+ def test_statistics
24
+ assert_equal( 3, @da.levels.size )
25
+ assert_equal( 7, @da.components )
26
+ assert_equal( 18, @da.ccd )
27
+ assert_in_delta( 18/7.to_f, @da.acd, Float::EPSILON )
28
+ assert_in_delta( 18/17.to_f, @da.nccd, Float::EPSILON )
29
+ end
30
+
31
+ def teardown
32
+ FileUtils.rm_rf 'AD_fixtures'
33
+ end
34
+
35
+ end
@@ -0,0 +1,186 @@
1
+ require 'test/unit'
2
+ require 'fortran_dependencies'
3
+ require 'fileutils'
4
+
5
+ class TestFortran < Test::Unit::TestCase
6
+
7
+ def setup
8
+ Dir.mkdir 'DependenciesFixture'
9
+ Dir.chdir 'DependenciesFixture' # FIXME: use block form for readability
10
+ Dir.mkdir 'lib'
11
+ Dir.chdir 'lib'
12
+ File.open('solution.f90','w') do |f|
13
+ f.puts "module solution\nuse area\nend module solution"
14
+ end
15
+ Dir.chdir '..'
16
+ Dir.mkdir 'src'
17
+ Dir.chdir 'src'
18
+ File.open('main.F90','w') do |f|
19
+ f.puts 'program whizzard'
20
+ f.puts " use grid\n use solution\n use circle"
21
+ f.puts 'end program whizzard'
22
+ end
23
+ File.open('grid.f90','w') do |f|
24
+ f.puts "module grid\nuse area\nend module grid"
25
+ end
26
+ File.open('shapes.f90','w') do |f|
27
+ f.puts "module rectangle_fun3d\nend module rectangle_fun3d"
28
+ f.puts "module circle\n use area\nend module circle"
29
+ end
30
+ File.open('area.f90','w'){ |f| f.puts "module area\nend module area" }
31
+ File.open('externalUse.f90','w') do |f|
32
+ f.puts "program user\nuse cantFindModule\nend program"
33
+ end
34
+ @dep = Fortran::Dependencies.new
35
+ end
36
+
37
+ def teardown
38
+ Dir.chdir '../..'
39
+ FileUtils.rm_rf 'DependenciesFixture'
40
+ end
41
+
42
+ def test_finds_which_modules_a_source_file_uses
43
+ assert_equal %w[grid solution circle], @dep.modules_used_in( 'main.F90' )
44
+ end
45
+
46
+ def test_finds_modules_defined_in_source_file
47
+ assert_equal %w[rectangle_fun3d circle],
48
+ @dep.modules_defined_in( 'shapes.f90' )
49
+ end
50
+
51
+ def test_create_module_definition_hash
52
+ assert_equal %w[circle rectangle_fun3d],
53
+ @dep.build_dictionary_of_modules( 'shapes.f90' ).keys.sort
54
+ end
55
+
56
+ def test_locating_all_fortran_files_in_search_path
57
+ files = %w[ ../lib/solution.f90 area.f90 externalUse.f90
58
+ grid.f90 main.F90 shapes.f90 ]
59
+ @dep.find_fortran_files.each do |file|
60
+ assert files.include?(file)
61
+ end
62
+ end
63
+
64
+ def test_build_hash_with_source_files
65
+ f90 = %w[grid.f90 ../lib/solution.f90 shapes.f90 area.f90]
66
+ hash = @dep.build_dictionary_of_modules( f90 )
67
+ assert_equal %w[ shapes.f90 shapes.f90 area.f90
68
+ ../lib/solution.f90 grid.f90 ].sort,
69
+ hash.values.sort
70
+ assert_equal %w[ rectangle_fun3d circle area solution grid ].sort,
71
+ hash.keys.sort
72
+ assert_equal hash , @dep.build_hash_of_modules_in_files
73
+ end
74
+
75
+ def test_dependency_generation_elements
76
+ directoryHash = @dep.build_hash_of_modules_in_files
77
+
78
+ source_file = "main.F90"
79
+ modules = @dep.modules_used_in( source_file )
80
+ assert_equal %w[grid solution circle], modules
81
+
82
+ new_source_files = modules.collect{ |mod| directoryHash[mod] }
83
+ assert_equal %w[ grid.f90 ../lib/solution.f90 shapes.f90],
84
+ new_source_files
85
+
86
+ new_modules = new_source_files.collect do |file|
87
+ @dep.modules_used_in( file )
88
+ end.flatten.uniq
89
+
90
+ assert_equal ["area"], new_modules
91
+ end
92
+
93
+ def test_makefile_dependency_line_generation
94
+ source_file = "main.F90"
95
+ make_golden=String.new <<-GOLDEN
96
+ main.o: main.F90 \\
97
+ grid.o \\
98
+ solution.o \\
99
+ shapes.o
100
+ GOLDEN
101
+ assert_equal make_golden, @dep.makefile_dependency_line(source_file)
102
+ end
103
+
104
+ def test_makefile_dependency_recurses_properly
105
+ make_golden=String.new <<-GOLDEN
106
+ main.o: main.F90 \\
107
+ grid.o \\
108
+ solution.o \\
109
+ shapes.o
110
+ grid.o: grid.f90 \\
111
+ area.o
112
+ area.o: area.f90
113
+ solution.f90: ../lib/solution.f90
114
+ \tln -sf ../lib/solution.f90 .
115
+ solution.o: solution.f90 \\
116
+ area.o
117
+ shapes.o: shapes.f90 \\
118
+ area.o
119
+ GOLDEN
120
+
121
+ gold_split = make_golden.split("\n")
122
+ test_split = @dep.dependencies('main.F90').split("\n")
123
+
124
+ while (gold = gold_split.shift) && (test = test_split.shift)
125
+ assert_equal gold, test
126
+ end
127
+ end
128
+
129
+ def test_source_file_dependency_hash
130
+ @dep.source_file_dependencies('main.F90')
131
+ assert_equal( 5, @dep.file_dependencies.size )
132
+ expected = {
133
+ "area.f90" => [],
134
+ "grid.f90" => ["area.f90"],
135
+ "../lib/solution.f90" => ["area.f90"],
136
+ "shapes.f90" => ["area.f90"],
137
+ "main.F90" => ["grid.f90", "../lib/solution.f90", "shapes.f90"]
138
+ }
139
+ assert_equal expected, @dep.file_dependencies
140
+ end
141
+
142
+ def test_finds_required_source_files
143
+ expected = %w[ area.f90 shapes.f90 ../lib/solution.f90
144
+ grid.f90 main.F90 ]
145
+ found = @dep.required_source_files('main.F90')
146
+ assert_equal expected.size, found.size
147
+ assert_equal 'main.F90', found.last
148
+ assert_equal 'area.f90', found.first
149
+ end
150
+
151
+ def test_finds_required_source_files_unordered
152
+ @dep.dependencies('main.F90')
153
+ sources = @dep.source_files
154
+ expected = %w[ main.F90 grid.f90 area.f90 solution.f90 shapes.f90 ]
155
+ assert_equal expected.size, sources.size
156
+ assert_equal 'shapes.f90', sources.last
157
+ assert_equal 'main.F90', sources.first
158
+ assert_equal expected, sources
159
+ end
160
+
161
+ def test_can_find_required_source_files_twice
162
+ files = %w[ main.F90 shapes.f90 area.f90
163
+ ../lib/solution.f90 grid.f90 ]
164
+ @dep.required_source_files('main.F90')
165
+ assert_equal files.sort, @dep.required_source_files('main.F90').sort
166
+ end
167
+
168
+ def test_recognizes_external_modules
169
+ file = 'externalUse.f90'
170
+ assert_equal [file], @dep.required_source_files(file).sort
171
+ end
172
+
173
+ def test_two_modules_in_a_single_source_file_uses
174
+ begin
175
+ File.open('two_modules.f90','w') do |f|
176
+ f.puts "module one\nend module one\nmodule two\n use one\nend module two"
177
+ end
178
+ dep = Fortran::Dependencies.new
179
+ assert_equal %w[one], dep.modules_used_in( 'two_modules.f90' )
180
+ dep.source_file_dependencies 'two_modules.f90'
181
+ ensure
182
+ FileUtils.rm 'two_modules.f90'
183
+ end
184
+ end
185
+
186
+ end
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fortran_dependencies
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Bil Kleb
8
+ - Mike Park
9
+ - Bill Wood
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2016-01-19 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: hoe
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 2.3.3
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - '>='
27
+ - !ruby/object:Gem::Version
28
+ version: 2.3.3
29
+ description: 'Fortran 90/95/2003 utilities. Currently, only provides Fortran 90/95/2003
30
+ dependencies. (Note: this is a fork of the original fortran gem, since the ability
31
+ to push that gem has been lost'
32
+ email: Bil.Kleb@NASA.gov
33
+ executables: []
34
+ extensions: []
35
+ extra_rdoc_files:
36
+ - History.txt
37
+ - License.txt
38
+ - Manifest.txt
39
+ - README.txt
40
+ files:
41
+ - History.txt
42
+ - License.txt
43
+ - Manifest.txt
44
+ - README.txt
45
+ - lib/fortran_dependencies.rb
46
+ - lib/lakos/analyze_dependencies.rb
47
+ - lib/lakos/mk_lakos_plots.rb
48
+ - test/lakos/test_analyze_dependencies.rb
49
+ - test/test_fortran.rb
50
+ homepage: http://nasarb.rubyforge.org/fortran
51
+ licenses: []
52
+ metadata: {}
53
+ post_install_message:
54
+ rdoc_options:
55
+ - --main
56
+ - README.txt
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - '>='
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ requirements: []
70
+ rubyforge_project: nasarb
71
+ rubygems_version: 2.4.8
72
+ signing_key:
73
+ specification_version: 2
74
+ summary: Fortran 90/95/2003 utilities.
75
+ test_files: []