Class: Fortran::Dependencies
- Inherits:
-
Object
- Object
- Fortran::Dependencies
- Defined in:
- lib/fortran.rb
Overview
Find Fortran dependencies
Constant Summary collapse
- OPTIONS =
{ :search_paths => [ '.', '../lib' ], :ignore_files => %r{ }, :ignore_modules => %r{ }, :ignore_symlinks => true }
- USE_MODULE_REGEX =
/^\s*use\s+(\w+)/i
- MODULE_DEF_REGEX =
/^\s*module\s+(\w+)/i
- MODULE_INCLUDE_REGEX =
/\s*include\s+('|")(\w+\.(f|F)90)('|")/i
- FILE_EXTENSION =
/\.f90$/i
Instance Attribute Summary collapse
-
#file_dependencies ⇒ Object
readonly
Returns the value of attribute file_dependencies.
-
#inlined_dependencies ⇒ Object
readonly
Returns the value of attribute inlined_dependencies.
-
#source_files ⇒ Object
readonly
Returns the value of attribute source_files.
Instance Method Summary collapse
- #build_dictionary_of_modules(array_of_file_names) ⇒ Object
- #build_hash_of_modules_in_files ⇒ Object
- #build_hash_of_non_module_files ⇒ Object
- #dependencies(start) ⇒ Object
- #file_is_module?(file) ⇒ Boolean
- #files_included_in(file) ⇒ Object
- #find_fortran_files ⇒ Object
- #included_files_in_module(file) ⇒ Object
-
#initialize(config = OPTIONS) ⇒ Dependencies
constructor
A new instance of Dependencies.
- #makefile_dependency_line(source) ⇒ Object
- #modules_defined_in(file) ⇒ Object
- #modules_in_included_files(file) ⇒ Object
- #modules_used_in(file) ⇒ Object
- #required_source_files(head_f90) ⇒ Object
- #source_file_dependencies(head_f90) ⇒ Object
Constructor Details
#initialize(config = OPTIONS) ⇒ Dependencies
Returns a new instance of Dependencies.
26 27 28 29 30 31 32 33 34 |
# File 'lib/fortran.rb', line 26 def initialize( config=OPTIONS ) @config = config OPTIONS.each{ |opt,default| @config[opt] = default unless @config.has_key? opt } @parsed, @file_dependencies, @source_files = [], {}, [] @inlined_dependencies = {} @hash = build_hash_of_modules_in_files @included_files = build_hash_of_non_module_files self end |
Instance Attribute Details
#file_dependencies ⇒ Object (readonly)
Returns the value of attribute file_dependencies
24 25 26 |
# File 'lib/fortran.rb', line 24 def file_dependencies @file_dependencies end |
#inlined_dependencies ⇒ Object (readonly)
Returns the value of attribute inlined_dependencies
24 25 26 |
# File 'lib/fortran.rb', line 24 def inlined_dependencies @inlined_dependencies end |
#source_files ⇒ Object (readonly)
Returns the value of attribute source_files
24 25 26 |
# File 'lib/fortran.rb', line 24 def source_files @source_files end |
Instance Method Details
#build_dictionary_of_modules(array_of_file_names) ⇒ Object
54 55 56 57 58 59 60 |
# File 'lib/fortran.rb', line 54 def build_dictionary_of_modules( array_of_file_names ) file_containing_module = {} array_of_file_names.each do |file| modules_defined_in( file ).each{ |mod| file_containing_module[mod]=file } end file_containing_module end |
#build_hash_of_modules_in_files ⇒ Object
88 89 90 |
# File 'lib/fortran.rb', line 88 def build_hash_of_modules_in_files build_dictionary_of_modules find_fortran_files end |
#build_hash_of_non_module_files ⇒ Object
70 71 72 73 74 75 76 77 78 79 |
# File 'lib/fortran.rb', line 70 def build_hash_of_non_module_files files = find_fortran_files included_files = {} files.each do |file| unless file_is_module?(file) included_files[File.basename(file)] = file end end included_files end |
#dependencies(start) ⇒ Object
129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/fortran.rb', line 129 def dependencies( start ) modules = modules_used_in( start ) @parsed = @parsed || [start] new_source_files = modules.collect{ |mod| @hash[mod] }.compact makefile_dependency_line(start) + new_source_files.collect do |file| next if @parsed.include?(file) @parsed.push file dependencies file end.join end |
#file_is_module?(file) ⇒ Boolean
81 82 83 84 85 86 |
# File 'lib/fortran.rb', line 81 def file_is_module?(file) IO.readlines( file ).map do |line| return true if line.match MODULE_DEF_REGEX end return false end |
#files_included_in(file) ⇒ Object
48 49 50 51 52 |
# File 'lib/fortran.rb', line 48 def files_included_in( file ) IO.readlines( file ).map do |line| $2 if line.match MODULE_INCLUDE_REGEX end.uniq.compact end |
#find_fortran_files ⇒ Object
62 63 64 65 66 67 68 |
# File 'lib/fortran.rb', line 62 def find_fortran_files source = @config[:search_paths].map{ |path| Dir[path+"/*.[fF]90"] } source.flatten!.uniq! source.delete_if{ |file| File.lstat(file).symlink? } if @config[:ignore_symlinks] source.delete_if{ |file| file.match @config[:ignore_files] } source.map!{ |file| file.sub(/^\.\//,'') }# strip leading ./ end |
#included_files_in_module(file) ⇒ Object
98 99 100 101 102 |
# File 'lib/fortran.rb', line 98 def included_files_in_module( file ) files_included_in( file ).map do |included_file| @included_files[included_file] end.flatten.uniq.compact end |
#makefile_dependency_line(source) ⇒ Object
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/fortran.rb', line 104 def makefile_dependency_line( source ) real_source = source.sub(/PHYSICS_DUMMY/,'PHYSICS_MODULES')# FIXME: What's this?! source_no_path = File.basename source @source_files.push source_no_path.gsub(%r|^.*/|,'') output = '' if (File.(source) != File.(source_no_path)) output += source_no_path+ ": " + real_source + "\n" output += "\tln -sf "+real_source+" .\n" end output += source.gsub(FILE_EXTENSION, ".o").gsub(%r|^.*/|,'' ) + ": " + source.gsub(%r|^.*/|,"" ) modules_used_in( source ).each do |use| unless @hash[use] unless use.match @config[:ignore_modules] $stderr.puts 'Warning: unable to locate module #{use} used in #{source}.' $stderr.puts ' set :search_paths or :ignore_module_regex options.' end next end output = output + " \\\n " + @hash[use].gsub(FILE_EXTENSION, ".o").gsub(%r|^.*/|,'' ) end output+"\n" end |
#modules_defined_in(file) ⇒ Object
42 43 44 45 46 |
# File 'lib/fortran.rb', line 42 def modules_defined_in( file ) IO.readlines( file ).map do |line| $1.downcase if line.match MODULE_DEF_REGEX end.uniq.compact end |
#modules_in_included_files(file) ⇒ Object
92 93 94 95 96 |
# File 'lib/fortran.rb', line 92 def modules_in_included_files( file ) files_included_in( file ).map do |included_file| modules_used_in(@included_files[included_file]) end.flatten.uniq.compact end |
#modules_used_in(file) ⇒ Object
36 37 38 39 40 |
# File 'lib/fortran.rb', line 36 def modules_used_in( file ) IO.readlines( file ).map do |line| $1.downcase if line.match USE_MODULE_REGEX end.uniq.compact end |
#required_source_files(head_f90) ⇒ Object
157 158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/fortran.rb', line 157 def required_source_files( head_f90 ) @parsed.clear source_file_dependencies( head_f90 ) sources = [] until @file_dependencies.empty? do no_dependents_pair = @file_dependencies.detect{ |h,d| d == [] } no_dependents = no_dependents_pair.first sources.push no_dependents @file_dependencies.delete(no_dependents){ |el| "#{el} not found" } @file_dependencies.each_value{ |deps| deps.delete(no_dependents) } end sources end |
#source_file_dependencies(head_f90) ⇒ Object
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/fortran.rb', line 141 def source_file_dependencies( head_f90 ) modules_head_uses = modules_used_in( head_f90 ) modules_head_uses += modules_in_included_files( head_f90 ) required_f90s = modules_head_uses.map{ |mod| @hash[mod] }.compact required_f90s.delete_if{ |f| f == head_f90 } required_inlined = included_files_in_module( head_f90 ) required_inlined.delete_if{ |f| f == head_f90 } @file_dependencies[head_f90] = required_f90s @inlined_dependencies[head_f90] = required_inlined required_f90s.each do |required_f90| next if @parsed.include?(required_f90) source_file_dependencies( required_f90 ) end @parsed.push head_f90 end |