Class: CGenerator::Library
- Inherits:
-
Template
- Object
- Accumulator
- Template
- CGenerator::Library
- Defined in:
- lib/cgen/cgen.rb
Direct Known Subclasses
Defined Under Namespace
Classes: CommitError, RbDefineAccumulator, RbDefineAllocAccumulator
Instance Attribute Summary collapse
-
#include_dirs ⇒ Object
readonly
Array of dirs which will be searched for extra include files.
-
#include_file ⇒ Object
readonly
Returns the template for the main include file of the library.
-
#init_library_function ⇒ Object
readonly
Returns a Function template object.
-
#purge_source_dir ⇒ Object
The #purge_source_dir attribute controls what happens to .c, .h, and .o files in the source dir of the library that are not among those generated as part of the library.
-
#show_times_flag ⇒ Object
Returns the value of attribute show_times_flag.
-
#source_file ⇒ Object
readonly
Returns the template for the main source file of the library.
Attributes inherited from Accumulator
Instance Method Summary collapse
-
#add_file(name, opts = {}) ⇒ Object
Creates templates for two files, a source (.c) file and an include (.h) file that will be generated in the same dir as the library.
-
#after_commit(&block) ⇒ Object
Schedules block to run after Library#commit.
- #assert_uncommitted ⇒ Object
-
#before_commit(&block) ⇒ Object
Schedules block to run before Library#commit.
- #build_wrapper ⇒ Object
-
#commit(build = true) ⇒ Object
Writes the files to disk, and makes and loads the library.
-
#committed? ⇒ Boolean
True if the library has been committed.
-
#declare(*args) ⇒ Object
(also: #declare_static)
call-seq: declare :x => “int x”, …
- #declare_extern(*args) ⇒ Object
-
#declare_extern_struct(struct_name, *rest) ⇒ Object
See #declare_struct.
-
#declare_module(mod, cfile = nil) ⇒ Object
(also: #declare_class)
call-seq: declare_class cl declare_module mod declare_symbol sym.
-
#declare_struct(struct_name, *rest) ⇒ Object
(also: #declare_static_struct)
call-seq: declare_struct name, attributes=nil declare_extern_struct name, attributes=nil.
-
#declare_symbol(sym, cfile = nil) ⇒ Object
See #declare_module.
-
#define(*args) ⇒ Object
(also: #define_c_function)
call-seq: define_c_function .
-
#define_c_global_function(*args) ⇒ Object
See #define_c_method.
-
#define_c_method(*args) ⇒ Object
call-seq: define_c_method mod, name, subclass define_c_module_function mod, name, subclass define_c_global_function name, subclass define_c_singleton_method mod, name, subclass define_c_class_method mod, name, subclass.
-
#define_c_module_function(*args) ⇒ Object
See #define_c_method.
-
#define_c_singleton_method(*args) ⇒ Object
(also: #define_c_class_method)
See #define_c_method.
-
#empty? ⇒ Boolean
True if no content has been added to the library.
-
#extconf {|a| ... } ⇒ Object
Override #extconf if you want to do more than just #create_makefile.
-
#include(*args) ⇒ Object
call-seq: include “file1.h”, “<file2.h>”, …
-
#initialize(name) ⇒ Library
constructor
A new instance of Library.
- #library ⇒ Object
-
#literal_symbol(sym, cfile = nil) ⇒ Object
Like Library#declare_symbol, but converts the ID to a VALUE at library initialization time.
- #loadlib ⇒ Object
-
#make(arg = nil) ⇒ Object
use -j and -l make switches for multiprocessor builds (man sysconf) see www.gnu.org/manual/make/html_chapter/make_5.html#SEC47.
- #make_program ⇒ Object
- #makedepend ⇒ Object
- #mkmf ⇒ Object
- #print_update_reason(template, template_str, file_data) ⇒ Object
-
#process_times ⇒ Object
—————- :section: Build methods.
-
#setup(*args) ⇒ Object
call-seq: setup key => “statements”, …
-
#show_times(message) ⇒ Object
If the attribute #show_times_flag is set to true, print the user and system times (and child user and child system on some platforms) and real time for each major step of the commit process.
-
#update_file(f, template) ⇒ Object
Called by write on each .c and .h file to actually write
templateto the open filef. -
#use_work_dir(dir_name) ⇒ Object
Changes into
dir_name, creating it first if necessary. - #write ⇒ Object
Methods inherited from Template
Methods inherited from Accumulator
#accept?, #add, #add_one, #add_one_really, #inspect, #inspect_one, #output, #output_one, #separator, #to_s
Constructor Details
#initialize(name) ⇒ Library
Returns a new instance of Library.
605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 |
# File 'lib/cgen/cgen.rb', line 605 def initialize name super name @show_times_flag = @purge_source_dir = false @committed = false @source_file = nil @include_dirs = [] @rtime = Time.now.to_f @ptime = process_times unless name =~ /\A[A-Za-z_]\w*\z/ raise NameError, "\n Not a valid library name: '#{name}'." + "\n Name must be a C identifier." end @include_file, @source_file = add_file "libmain" @include_file.include '<ruby.h>' @init_library_function = define_c_function "Init_" + name @init_library_function.scope :extern @init_library_function.body \ rb_define_method!, rb_define_module_function!, rb_define_global_function!, rb_define_singleton_method!, rb_define_alloc_func! ## odd, putting an accum inside ## a template which is not the parent end |
Instance Attribute Details
#include_dirs ⇒ Object (readonly)
Array of dirs which will be searched for extra include files. Example:
lib.include_dirs << "/home/me/include"
603 604 605 |
# File 'lib/cgen/cgen.rb', line 603 def include_dirs @include_dirs end |
#include_file ⇒ Object (readonly)
Returns the template for the main include file of the library. Usually, there is no need to access this directly.
580 581 582 |
# File 'lib/cgen/cgen.rb', line 580 def include_file @include_file end |
#init_library_function ⇒ Object (readonly)
Returns a Function template object. This function is called when the library is loaded. Method definitions put stuff here to register methods with Ruby. Usually, there is no need to bother this guy directly. Use Library#setup instead.
576 577 578 |
# File 'lib/cgen/cgen.rb', line 576 def init_library_function @init_library_function end |
#purge_source_dir ⇒ Object
The #purge_source_dir attribute controls what happens to .c, .h, and .o files in the source dir of the library that are not among those generated as part of the library. If this is set to :delete, then those files are deleted. Other true values cause the .c, .h, and .o files to be renamed with the .hide extension. (Note that this makes it difficult to keep manually written C files in the same dir.) False flag values (the default) cause CGen to leave the files untouched.
Note that, regardless of this setting, #mkmf will construct a Makefile which lists all .c files that are in the source dir. If you do not delete obsolete files, they will be compiled into your library!
599 600 601 |
# File 'lib/cgen/cgen.rb', line 599 def purge_source_dir @purge_source_dir end |
#show_times_flag ⇒ Object
Returns the value of attribute show_times_flag.
586 587 588 |
# File 'lib/cgen/cgen.rb', line 586 def show_times_flag @show_times_flag end |
#source_file ⇒ Object (readonly)
Returns the template for the main source file of the library. Usually, there is no need to access this directly.
584 585 586 |
# File 'lib/cgen/cgen.rb', line 584 def source_file @source_file end |
Instance Method Details
#add_file(name, opts = {}) ⇒ Object
Creates templates for two files, a source (.c) file and an include (.h) file that will be generated in the same dir as the library. The base file name is taken from the argument. Returns an array containing the include file template and the source file template, in that order.
Functions can be added to the source file by calling #define_method and similar methods on the source file template. Their rb_init calls are done in #init_library_function in the main library source file. The new source file automatically #includes the library’s main header file, as well as its own header file, and the library’s main source file also #includes the new header file. Declarations can be added to the header file by calling #declare on it, but in many cases this is taken care of automatically.
665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 |
# File 'lib/cgen/cgen.rb', line 665 def add_file name, opts = {} pair = @pile.detect {|p| p[0].name == name + ".h"} if not pair new_include_file = CFile.new name + ".h", self new_source_file = CFile.new name + ".c", self, new_include_file if @source_file new_source_file.include @include_file unless opts[:independent] @source_file.include new_include_file end new_source_file.include new_include_file pair = [new_include_file, new_source_file] add pair # for inspect and commit end return pair end |
#after_commit(&block) ⇒ Object
Schedules block to run after Library#commit. The before blocks are run in the same order in which they were scheduled; the after blocks run in the reverse order (analogously with BEGIN/END). Each block is evaluated in the context in which it was created (instance_eval is not used), and it is passed the library as an argument.
715 716 717 |
# File 'lib/cgen/cgen.rb', line 715 def after_commit(&block) (@after_commit ||= []) << block end |
#assert_uncommitted ⇒ Object
685 686 687 688 689 |
# File 'lib/cgen/cgen.rb', line 685 def assert_uncommitted if @committed raise CommitError, "\nLibrary #{@name} has already been committed." end end |
#before_commit(&block) ⇒ Object
Schedules block to run before Library#commit. The before blocks are run in the same order in which they were scheduled; the after blocks run in the reverse order (analogously with BEGIN/END). Each block is evaluated in the context in which it was created (instance_eval is not used), and it is passed the library as an argument.
706 707 708 |
# File 'lib/cgen/cgen.rb', line 706 def before_commit(&block) (@before_commit ||= []) << block end |
#build_wrapper ⇒ Object
1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 |
# File 'lib/cgen/cgen.rb', line 1016 def build_wrapper if File.exists? @name unless File.directory? @name raise CommitError, "Library #{@name}: Can't mkdir; file exists." end else Dir.mkdir @name end Dir.chdir @name do yield end ### this is fragile--should record abs path when Lib is created end |
#commit(build = true) ⇒ Object
Writes the files to disk, and makes and loads the library.
Note that #commit must be called after all C code definitions for the library, but before instantiation of any objects that use those definitions. If a definition occurs after commit, or if instantiation occurs before commit, then a CGenerator::Library::CommitError is raised, with an appropriate message. Sometimes, this forces you to use many small libraries, each committed just in time for use. See examples/fixed-array.rb.
727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 |
# File 'lib/cgen/cgen.rb', line 727 def commit(build = true) assert_uncommitted while @before_commit bc = @before_commit; @before_commit = nil bc.each {|block| block[self]} end @committed = true if build @logname ||= "make.log" show_times "precommit" show_times "write" do write end show_times "makedepend" do makedepend end show_times "mkmf" do mkmf end show_times "make" do make end end show_times "loadlib" do loadlib end while @after_commit ac = @after_commit; @after_commit = nil ac.reverse.each {|block| block[self]} end end |
#committed? ⇒ Boolean
True if the library has been committed.
692 693 694 |
# File 'lib/cgen/cgen.rb', line 692 def committed? @committed end |
#declare(*args) ⇒ Object Also known as: declare_static
call-seq:
declare :x => "int x", ...
declare_extern :x => "int x", ...
Puts the string in the declaration area of the .c or .h file, respectively. The declaration area is before the function definitions, and after the structure declarations.
1203 1204 1205 |
# File 'lib/cgen/cgen.rb', line 1203 def declare(*args) @source_file.declare(*args) end |
#declare_extern(*args) ⇒ Object
1208 1209 1210 |
# File 'lib/cgen/cgen.rb', line 1208 def declare_extern(*args) @include_file.declare(*args) end |
#declare_extern_struct(struct_name, *rest) ⇒ Object
See #declare_struct.
1224 1225 1226 |
# File 'lib/cgen/cgen.rb', line 1224 def declare_extern_struct struct_name, *rest @include_file.declare_struct struct_name, *rest end |
#declare_module(mod, cfile = nil) ⇒ Object Also known as: declare_class
call-seq:
declare_class cl
declare_module mod
declare_symbol sym
Define a C variable which will be initialized to refer to the class, module, or symbol. These accumulators return the name of the C variable which will be generated and initialized to the ID of the symbol, and this return value can be interpolated into C calls to the Ruby API. (The arguments are the actual Ruby objects.) This is very useful in #rb_ivar_get/#rb_ivar_set calls, and it avoids doing the lookup more than once:
...
declare :my_ivar => "VALUE my_ivar"
body %{
my_ivar = rb_ivar_get(shadow->self, #{declare_symbol :@my_ivar});
rb_ivar_set(shadow->self, #{declare_symbol :@my_ivar}, Qnil);
}
The second declaration notices that the library already has a variable that will be initialized to the ID of the symbol, and uses it.
1259 1260 1261 1262 1263 1264 1265 |
# File 'lib/cgen/cgen.rb', line 1259 def declare_module mod, cfile = nil c_name = "module_#{CGenerator::make_c_name mod.to_s}" declare mod => "VALUE #{c_name}" (cfile || self).declare_extern mod => "extern VALUE #{c_name}" setup mod => "#{c_name} = rb_path2class(\"#{mod}\")" c_name.intern end |
#declare_struct(struct_name, *rest) ⇒ Object Also known as: declare_static_struct
call-seq:
declare_struct name, attributes=nil
declare_extern_struct name, attributes=nil
Returns a Structure template, which generates to a typedefed C struct in the .c or .h file. The #declare method of this template is used to add members.
1218 1219 1220 |
# File 'lib/cgen/cgen.rb', line 1218 def declare_struct struct_name, *rest @source_file.declare_struct struct_name, *rest end |
#declare_symbol(sym, cfile = nil) ⇒ Object
See #declare_module.
1269 1270 1271 1272 1273 1274 1275 |
# File 'lib/cgen/cgen.rb', line 1269 def declare_symbol sym, cfile = nil c_name = "ID_#{CGenerator::make_c_name sym}" declare sym => "ID #{c_name}" (cfile || self).declare_extern sym => "extern ID #{c_name}" setup sym => "#{c_name} = rb_intern(\"#{sym}\")" c_name.intern end |
#define(*args) ⇒ Object Also known as: define_c_function
call-seq:
define_c_function
Defines a plain ol’ C function. Returns a Function template (see below), or a template of the specified type, if given.
1233 1234 1235 |
# File 'lib/cgen/cgen.rb', line 1233 def define(*args) @source_file.define(*args) end |
#define_c_global_function(*args) ⇒ Object
See #define_c_method.
1176 1177 1178 |
# File 'lib/cgen/cgen.rb', line 1176 def define_c_global_function(*args) @source_file.define_c_global_function(*args) end |
#define_c_method(*args) ⇒ Object
call-seq:
define_c_method mod, name, subclass
define_c_module_function mod, name, subclass
define_c_global_function name, subclass
define_c_singleton_method mod, name, subclass
define_c_class_method mod, name, subclass
Defines a function of the specified name and type in the given class/module (or in the global scope), and returns the function template (often used with #instance_eval to add arguments, code, etc.). The subclass argument is optional and allows the template to belong to a subclass of the function template it would normally belong to.
For example,
define_c_method String, "reverse"
The arguments accepted by the method automatically include self. By default, arguments are passed as individual C arguments, but the can be passed in a Ruby or C array. The latter has the advantage of argument parsing (based on rb_scan_args), defaults, and typechecking. See Method#c_array_args. #define_c_class_method is just an alias for #define_c_singleton_method.
1166 1167 1168 |
# File 'lib/cgen/cgen.rb', line 1166 def define_c_method(*args) @source_file.define_c_method(*args) end |
#define_c_module_function(*args) ⇒ Object
See #define_c_method.
1171 1172 1173 |
# File 'lib/cgen/cgen.rb', line 1171 def define_c_module_function(*args) @source_file.define_c_module_function(*args) end |
#define_c_singleton_method(*args) ⇒ Object Also known as: define_c_class_method
See #define_c_method.
1181 1182 1183 |
# File 'lib/cgen/cgen.rb', line 1181 def define_c_singleton_method(*args) @source_file.define_c_singleton_method(*args) end |
#empty? ⇒ Boolean
True if no content has been added to the library.
697 698 699 |
# File 'lib/cgen/cgen.rb', line 697 def empty? @init_library_function.empty? ## is this enough? end |
#extconf {|a| ... } ⇒ Object
Override #extconf if you want to do more than just #create_makefile. Note that #create_makefile recognizes all .c files in the library directory, and generates a makefile that compiles them and links them into the dynamic library.
Yields the array of lines being constructed so that additional configuration can be added. See the ruby documentation on mkmf.
1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 |
# File 'lib/cgen/cgen.rb', line 1036 def extconf # :yields: lines_array a = [] a << "require 'mkmf'" a << "$CFLAGS = \"#$CFLAGS\"" if defined?($CFLAGS) include_dirs.each do |dir| a << %{$INCFLAGS << " -I#{dir}"} end yield a if block_given? a << "create_makefile '#{@name}'" end |
#include(*args) ⇒ Object
call-seq:
include "file1.h", "<file2.h>", ...
Insert the include statement(s) at the top of the library’s main .c file. For convenience, <ruby.h> is included automatically, as is the header file of the library itself.
1192 1193 1194 |
# File 'lib/cgen/cgen.rb', line 1192 def include(*args) @source_file.include(*args) end |
#library ⇒ Object
1310 1311 1312 |
# File 'lib/cgen/cgen.rb', line 1310 def library self end |
#literal_symbol(sym, cfile = nil) ⇒ Object
Like Library#declare_symbol, but converts the ID to a VALUE at library initialization time. Useful for looking up hash values keyed by symbol objects, for example. sym is a string or symbol.
1280 1281 1282 1283 1284 1285 1286 |
# File 'lib/cgen/cgen.rb', line 1280 def literal_symbol sym, cfile = nil c_name = "SYM_#{CGenerator::make_c_name sym}" declare sym => "VALUE #{c_name}" (cfile || self).declare_extern sym => "extern VALUE #{c_name}" setup sym => "#{c_name} = ID2SYM(rb_intern(\"#{sym}\"))" c_name.intern end |
#loadlib ⇒ Object
1047 1048 1049 1050 1051 |
# File 'lib/cgen/cgen.rb', line 1047 def loadlib require File.join(".", @name, @name) rescue ScriptError, StandardError => e raise e.class, "\nCgen: problem loading library:\n" + e. end |
#make(arg = nil) ⇒ Object
use -j and -l make switches for multiprocessor builds (man sysconf) see www.gnu.org/manual/make/html_chapter/make_5.html#SEC47
981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 |
# File 'lib/cgen/cgen.rb', line 981 def make arg = nil build_wrapper do unless system "#{make_program} #{arg} >>#{@logname} 2>&1" raise CommitError, "\n Make #{arg} failed for #{@name}." + "\n Transcript is saved in #{@name}/#{@logname} and follows:" + "\n " + "_" * 60 + "\n" + File.read(@logname).tabto(3).gsub(/^ /, " |") + " " + "_" * 60 + "\n" end if arg == 'clean' or arg == 'distclean' File.delete(@logname) rescue SystemCallError if arg == 'distclean' for template in @pile.flatten do File.delete(template.name) rescue SystemCallError end end end end end |
#make_program ⇒ Object
1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 |
# File 'lib/cgen/cgen.rb', line 1003 def make_program case RUBY_PLATFORM when /mswin/i "nmake" when /mingw/i "make" # "mingw32-make" is the MSYS-independent, MSVC native version # which is supposedly less useful else "make" end end |
#makedepend ⇒ Object
892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 |
# File 'lib/cgen/cgen.rb', line 892 def makedepend return if /mswin/i =~ RUBY_PLATFORM ## what else can we do? build_wrapper do cpat = "*.c" chpat = "*.[ch]" dep = "depend" return if Dir[cpat].all? {|f| test ?<, f, dep} cfg = RbConfig::CONFIG dirs = [cfg["sitearchdir"], cfg["archdir"], cfg["includedir"], *include_dirs] case cfg["CC"] when /gcc/ makedepend_cmd = "#{cfg["CC"]} -MM #{cpat} -I#{dirs.join " -I"} >#{dep} 2>#{@logname}" else makedepend_cmd = "touch #{dep} && \ makedepend -f#{dep} #{cpat} -I#{dirs.join " -I"} >#{@logname} 2>&1" end result = system makedepend_cmd unless result log_data = File.read(@logname) rescue nil msg = "\n `#{makedepend_cmd}` failed for #{@name}." if log_data msg << "\n Transcript is saved in #{@name}/#{@logname} and follows:" + "\n " + "_" * 60 + "\n" + log_data.tabto(3).gsub(/^ /, " |") + " " + "_" * 60 + "\n" else msg << "\n No log available.\n" end raise CommitError, msg end end end |
#mkmf ⇒ Object
934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 |
# File 'lib/cgen/cgen.rb', line 934 def mkmf need_to_make_clean = false # Need to do this in a separate process because mkmf.rb pollutes # the global namespace. build_wrapper do require 'rbconfig' ruby = RbConfig::CONFIG["RUBY_INSTALL_NAME"] old_contents = File.read("extconf.rb") rescue nil contents = extconf require 'stringio' s = StringIO.new s.puts(contents) s.rewind contents = s.read if old_contents != contents File.open("extconf.rb", "w") do |f| f.puts contents end need_to_make_clean = true end ## it would be better to capture the output of extconf.rb before ## it writes it to Makefile, but mkmf.rb is not written that way :( if File.exist?("Makefile") old_makefile = File.read("Makefile") require 'fileutils' FileUtils.mv("Makefile", "Makefile.old") end system %{ #{ruby} extconf.rb > #{@logname} } if old_makefile and old_makefile == File.read("Makefile") FileUtils.rm("Makefile") FileUtils.mv("Makefile.old", "Makefile") end end make "clean" if need_to_make_clean end |
#print_update_reason(template, template_str, file_data) ⇒ Object
852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 |
# File 'lib/cgen/cgen.rb', line 852 def print_update_reason template, template_str, file_data puts "\nUpdating file #{template.name}" if file_data == nil puts "File on disk is empty" return end s = file_data t = template_str slines = s.split "\n" tlines = t.split "\n" i = 0 sline = slines[i] tline = tlines[i] catch :done do while sline and tline if sline != tline puts "Line #{i+1}", "On disk: #{sline.inspect}", "In memory: #{tline.inspect}", "" throw :done end i += 1 sline = slines[i] tline = tlines[i] end if sline == nil and tline == nil puts "Very strange, no difference found!" else if slines.size > tlines.size puts "file on disk is longer" else puts "file in memory is longer" end end end end |
#process_times ⇒ Object
:section: Build methods
Methods used during commit to control the build chain. In sequence, #commit calls these methods:
* #write dumps each file template to disk, if needed
* #makedepend executes +makedepend+
* #mkmf calls Library#extconf
* #make executes the system's +make+ program
* #loadlib load the library that has been built
These methods can be overridden, but are more typically called via commit or sometimes directly. The argument to #make is interpolated into the system call as a command line argument to the make program. If the argument is ‘clean’ or ‘distclean’ then the make log is deleted; if the argument is ‘distclean’ then all .c and .h files generated by #write are deleted (additional user-supplied .c and .h files in the library dir are not affected).
776 777 778 |
# File 'lib/cgen/cgen.rb', line 776 def process_times RUBY_VERSION.to_f >= 1.7 ? Process.times : Time.times end |
#setup(*args) ⇒ Object
call-seq:
setup key => "statements", ...
Inserts code in the #init_library_function, which is called when the library is loaded. The key is used for redundancy checking, as in the #declare accumulators. Note that hashes are unordered, so constructs like
setup :x => "...", :y => "..."
can result in unpredictable order. To avoid this, use several #setup calls.
1298 1299 1300 |
# File 'lib/cgen/cgen.rb', line 1298 def setup(*args) @init_library_function.setup(*args) end |
#show_times(message) ⇒ Object
If the attribute #show_times_flag is set to true, print the user and system times (and child user and child system on some platforms) and real time for each major step of the commit process. Display message.
783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 |
# File 'lib/cgen/cgen.rb', line 783 def show_times yield if block_given? if @show_times_flag unless @show_times_started printf "\n%20s %6s %6s %6s %6s %7s\n", "__step__", "utime", "stime", "cutime", "cstime", "real" @show_times_started = true end ptime = self.process_times rtime = Time.now.to_f printf "%20s %6.2f %6.2f %6.2f %6.2f %7.3f\n", , ptime.utime - @ptime.utime, ptime.stime - @ptime.stime, ptime.cutime - @ptime.cutime, ptime.cstime - @ptime.cstime, rtime - @rtime @ptime = ptime @rtime = rtime end end |
#update_file(f, template) ⇒ Object
Called by write on each .c and .h file to actually write template to the open file f. The default behavior is to compare the existing data with the generated data, and leave the file untouched if nothing changed. Subclasses may have more efficient ways of doing this. (For instance, check a version indicator in the file on disk, perhaps stored using the file’s preamble accumulator. It is even possible to defer some entries in the template until after this check has been made: code that only needs to be regenerated if some specification has changed)
839 840 841 842 843 844 845 846 847 848 849 850 |
# File 'lib/cgen/cgen.rb', line 839 def update_file f, template template_str = template.to_s file_data = f.gets(nil) ## sysread is faster? unless file_data == template_str if defined?($CGEN_VERBOSE) and $CGEN_VERBOSE print_update_reason(template, template_str, file_data) end f.rewind f.print template_str f.truncate f.pos end end |
#use_work_dir(dir_name) ⇒ Object
Changes into dir_name, creating it first if necessary. Does nothing if already in a directory of that name. Often used with “tmp”.
640 641 642 643 644 645 646 647 648 649 650 |
# File 'lib/cgen/cgen.rb', line 640 def use_work_dir dir_name if File.basename(Dir.pwd) == dir_name yield else require 'fileutils' FileUtils.makedirs dir_name Dir.chdir dir_name do yield end end end |
#write ⇒ Object
802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 |
# File 'lib/cgen/cgen.rb', line 802 def write build_wrapper do templates = @pile.flatten.sort_by { |t| t.name } if @purge_source_dir # hide or delete files not listed in templates files = Dir["*.{c,h,o}"] template_files = templates.map { |t| t.name } template_files += template_files.grep(/\.c$/).map { |f| f.sub(/\.c$/, ".o") } for file in files - template_files if @purge_source_dir == :delete File.delete(file) rescue SystemCallError else File.rename(file, file + ".hide") rescue SystemCallError end end end for template in templates do begin File.open(template.name, 'r+') {|f| update_file f, template} rescue SystemCallError File.open(template.name, 'w+') {|f| update_file f, template} end end end end |