#!/usr/bin/env ruby # $Id$ =begin GridFlow Copyright (c) 2001,2002,2003,2004,2005,2006 by Mathieu Bouchard This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. See file ./COPYING for further informations on licensing terms. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. =end require "rbconfig" require "mkmf" require "ftools" include Config OSX = !!( CONFIG["arch"] =~ /darwin/ ) require "win32/process" if CONFIG["arch"] =~ /mingw/ LOG = File.open "./config.log", "w" Red = "\e[0;1;31m" Green = "\e[0;1;32m" Light = "\e[0m" Dark = "\e[0;1;30m" Yellow = "\e[0;1;33;44m" $verbose=false LOG.puts "-"*64 LOG.puts "Environment Variables: " ENV.each {|k,v| LOG.puts "#{k}=#{v}" } LOG.puts "-"*64 puts if not File.exist?("./configure") puts "Run me from the right directory please." exit 1 end begin Dir.mkdir "tmp" rescue Errno::EEXIST end #----------------------------------------------------------------# class Or attr_reader :a class< "1.7" log << "error \##{ret}\n" if ret>0 return ret<=0 end $conf={ :LDSOFLAGS => ["-lm"], :BRIDGE_LDFLAGS => ["-lm"], :FEATURES => {}, :OPTIONS => [], :DEFINES => { # :RUBY_PREFIX => CONFIG['prefix'], :RUBY_PREFIX => nil, :PREFIX => "/usr/local", :CPU => nil, :RUBY_ARCH => CONFIG['arch'], :GEM_SOURCE => "../Gem/src", }, :CC => "g++", :OBJS => [], } def launch stdin,stdout,stderr,*command # -> returncode child = fork if not child then STDIN .reopen stdin if stdin STDOUT.reopen stdout if stdout STDERR.reopen stderr if stderr exec *command #!@#$ what happens with exception upon exec ? end child end def join_pid pid Process.waitpid2(pid)[1] end module Future; end class Feature $features = [] def self.add(*a,&b) $features << Feature.new(*a,&b) end def initialize(&b) instance_eval(&b) end def self.attr2(sym,&b) eval "def #{sym}(*args,&b) raise args.inspect if args.length>1 if b then @#{sym}=b.extend Future elsif args.length>0 then @#{sym}=args[0] else if Future===@#{sym} then @#{sym}.call else @#{sym} end end end" end attr2 :tag attr2 :name attr2 :status #!@#$ attr2 :uses_so attr2 :uses_bridge_so attr2 :uses_o #!@#$ attr2 :uses_h attr2 :uses_feature attr2 :test attr2 :options #!@#$ attr2 :unless_feature #!@#$ attr2 :action #!@#$ attr2 :defines #!@#$ def find_h name $C_INCLUDE_PATH.find {|x| File.exist?(x+"/"+name)} end def c_test code, link=nil, options=[], feature=nil link = (uses_so||[]).dup if not link link=link.flatten ldlpath = ENV["LD_LIBRARY_PATH"] uses_h.each {|h| find_h h or /framework/ =~ (uses_so||[]).join(" ") or raise "where is #{h} ?" } if uses_h ENV["LD_LIBRARY_PATH"] = ldlpath ? "./tmp:#{ldlpath}" : "./tmp" link[0,0]=$conf[:LDSOFLAGS].find_all {|x| String===x and /^-L/ =~ x }.flatten code=code.gsub(/#include#/) { uses_h.map {|inc| "#include <#{inc}>\n" }.join"" } log = "" log << code << "\n" binname = "tmp/#{$$}" sourcename = binname+".cpp" File.open(sourcename,"w") {|f| f.puts code } command = ["/usr/bin/env", $conf[:CC]] + $CFLAGS.split(/ /).reject{|x| x.length==0 } if not launch2 log,*(command+options+[sourcename, "-o", binname, *link]) pat = Regexp.new("^"+Regexp.quote(sourcename)+":\\d+: ") errs = log.split("\n").find_all {|l| pat =~ l } raise "gcc compilation error" if not errs or errs.length==0 errs = errs[0].gsub(pat,"") raise "gcc: #{errs}" end if not launch2 log,"tmp/#{$$}" raise "runtime error" end return true ensure LOG.puts log ENV["LD_LIBRARY_PATH"] = ldlpath if ldlpath end def asm_test code, *link log = "" log << code << "\n" File.open("tmp/#{$$}.asm","w") {|f| f.puts code } command = ["/usr/bin/env", "nasm", "tmp/#{$$}.asm", "-f", "elf", "-o", "tmp/#{$$}.o"] launch2 log,*command or return false command = ["#{$conf[:CC]}","-o","tmp/#{$$}","tmp/#{$$}.o",*link] launch2 log,*command or return false command = ["tmp/#{$$}"] launch2 log,*command or return false true ensure LOG.puts log end end #----------------------------------------------------------------# def make_expand(x) y=x.gsub(/\$\(([^\)]*)\)/) {CONFIG[$1]} if x!=y then make_expand y else y end end def read_ld_so_conf return [] unless File.exist?("/etc/ld.so.conf") x = File.open("/etc/ld.so.conf"){|f| f.read }.split("\s") x.delete_if { x.length==0 } x end def epath x; (ENV[x]||"").split(":") end $C_INCLUDE_PATH = ( epath("CPLUS_INCLUDE_PATH") + epath("C_INCLUDE_PATH") + ["/usr/include"]).uniq $LIBRARY_PATH = ( epath("LIBRARY_PATH") + ["/usr/lib","/lib"]).uniq $LD_LIBRARY_PATH = ( epath("LD_LIBRARY_PATH") + read_ld_so_conf + ["/usr/lib","/lib"]).uniq $LIBX11DIR = ["-L/usr/X11R6/lib"] $LIBX11 = ["-L/usr/X11R6/lib","-lX11"] # making it easier for everybody I hope: def prepend_path base bl = base+"/lib" bi = base+"/include" if not $LD_LIBRARY_PATH.include? bl and not $LIBRARY_PATH.include? bl then $conf[:LDSOFLAGS].unshift "-L"+bl $LD_LIBRARY_PATH.unshift bl $LIBRARY_PATH.unshift bl end #and not $CPLUS_INCLUDE_PATH.include? bi if not $C_INCLUDE_PATH.include? bi then $CFLAGS += " -I"+bi $C_INCLUDE_PATH.unshift bi end end prepend_path "/Applications/Pd.app/Contents/Resources" if OSX prepend_path "/sw" if OSX prepend_path "/usr/local" prepend_path ENV["HOME"] # prepend_path "." for var in [:$C_INCLUDE_PATH, :$LIBRARY_PATH, :$LD_LIBRARY_PATH] do LOG.puts "#{var}: #{eval(var.to_s).inspect}" end $conf[:BINDIR] = make_expand CONFIG['bindir'] LOG.puts "-"*64 $CFLAGS += " -xc++ -fno-operator-names -fno-omit-frame-pointer" $CFLAGS += " -I/usr/X11R6/include" $C_INCLUDE_PATH.unshift "/usr/X11R6/include" ruby16a = "#{CONFIG['libdir']}/ruby/#{CONFIG['MAJOR']}.#{CONFIG['MINOR']}/"\ "#{CONFIG['arch']}/#{CONFIG['LIBRUBY_A']}" ruby18a = "#{CONFIG['libdir']}/#{CONFIG['LIBRUBY_A']}" for x in [ruby16a,ruby18a] do $LIBRUBY_A = make_expand x break if File.exist? $LIBRUBY_A end FILES = [ [:directory, "base/", [:ruby, "main.rb"], [:ruby, "flow_objects.rb"], [:ruby, "test.rb"], [:ruby, "source_filter.rb"], ], [:directory, "bridge/", [:ruby, "puredata.rb"], [:ruby, "placebo.rb"], ], [:directory, "format/", [:ruby, "main.rb"], ], [:directory, "optional/", [:ruby, "usb.rb"], [:ruby, "lti.rb"], ], [:directory, "extra/", [:ruby, "smpte.rb"], [:ruby, "server_2.rb"], [:ruby, "server_1_grid.rb"], [:ruby, "server_1_ppm.rb"], [:ruby, "jmax_format.rb"], [:ruby, "puredata_format.rb"], ], ] #----------------------------------------------------------------# Feature.add { tag :gcc3 name "GNU C++ Compiler 3" options ["HAVE_GCC3"] =begin test proc { pi=File.popen "#{$conf[:CC]} -v 2>&1", "r" vline = pi.readlines.find {|l| /gcc version ([\d\.]+)/.match l } version = $1 pi.close if version < "3" then raise "version #{version} < 3" end true } =end test proc { c_test %{ #include int main () { printf("GCC_VERSION %d.%d.%d\\n", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); return !(__GNUC__>=3); }} } defines :GCC_VERSION => proc { m = /GCC_VERSION\s+(.*)/.match(File.popen("tmp/#{$$}","r"){|f| f.read }) m[1] } } Feature.add { tag :stl name "C++ Standard Template Library" test proc { c_test %{ #include int main () { std::vector foo; }} } } Feature.add { tag :gcc64 name "GNU C++ in 64-bit mode" options ["GCC64"] test proc { c_test %{ #include #include #include #define T(a) printf("%s:%ld; ",#a,(long)sizeof(a)); int main () { T(void *)T(ptrdiff_t)T(off_t)T(size_t)puts(""); T(char)T(short)T(int)T(long)T(long long)puts(""); T(float)T(double)puts(""); return !( sizeof(void*)==8 ); }} } } #----------------------------------------------------------------# Feature.add { tag :libc_stack_end name "Stack end defined by LibC" status :disabled test proc { c_test ' #include extern void *__libc_stack_end; int main () { printf("#define STACK_END 0x%0*lx",sizeof(long)*2,__libc_stack_end); return 0; } ', uses_bridge_so } defines :HAVE_LIBC_STACK_END defines :STACK_END => proc { m = /STACK_END\s+(.*)/.match(File.popen("tmp/#{$$}","r"){|f| f.read }) m[1] } } Feature.add { tag :segv_stack_end name "Stack end probed" test proc { c_test %` /* the segfault trick (by Mathieu Bouchard) */ #ifndef STACK_GROW_DIRECTION #define STACK_GROW_DIRECTION -1 #endif #include #include #include static volatile long bogus = 0; // to force *bp to be read in memory static sigjmp_buf rescue_segfault; static void trap_segfault (int patate) { siglongjmp(rescue_segfault,11); } int main () { // get any stack address volatile long * volatile bp = (volatile long *)&bp; void (*oldsegv)(int) = signal(SIGSEGV,trap_segfault); void (*oldbus)(int) = signal(SIGBUS, trap_segfault); if (!sigsetjmp(rescue_segfault,0)) for (;;bp-=STACK_GROW_DIRECTION) bogus += *bp; printf("#define STACK_END 0x%0*lx\\n",sizeof(long)*2,(long)(bp+STACK_GROW_DIRECTION)); return 0; } `, uses_bridge_so } defines :HAVE_LIBC_STACK_END defines :STACK_END => proc { m = /STACK_END\s+(.*)/.match(File.popen("tmp/#{$$}","r"){|f| f.read }) m[1] } } Feature.add { tag :wild_stack_end name "Stack end wild guess" unless_feature [:libc_stack_end,:segv_stack_end] test proc { c_test ' #include int main () { void *bp; printf("#define STACK_END 0x%0*lx",sizeof(long)*2,(long)&bp); return 0; } ', uses_bridge_so } defines :STACK_END => proc { m = /STACK_END\s+(.*)/.match(File.popen("tmp/#{$$}","r"){|f| f.read }) m[1] } } Feature.add { tag :libruby name "Ruby as a dynamic library" uses_bridge_so ["-lruby"] #uses_h ["ruby.h"] # is in special directory test proc { c_test "#include int main () { return rb_rescue==0; }", uses_bridge_so } } Feature.add { tag :librubystatic unless_feature [:libruby] name "Ruby as a static library" #uses_h ["ruby.h"] # is in special directory uses_bridge_so { lib = " #{$LIBRUBY_A} #{CONFIG['LIBS']} " lib = "-Wl,--whole-archive"+lib+"-Wl,--no-whole-archive" unless OSX [lib] } test proc { c_test "#include int main () { return rb_rescue==0; }", ["-xnone", $LIBRUBY_A, *(CONFIG['LIBS'].split)] } options ["HAVE_STATIC_RUBY"] #!@#$ useless? } #----------------------------------------------------------------# Feature.add { tag :pentium name "Pentium-compatible CPU" action proc { $conf[:DEFINES][:CPU] ||= "pentium" } test proc { (CONFIG["arch"] =~ /(i\d86|x86_64)/) or raise "#{CONFIG["arch"]} instead" c_test ' #include char get_cpuid[]={ 96,49,192,15,162,139,124,36,36,137,31, 137,87,4,137,79,8,137,71,12,97,195}; main() { char result[16]; int code; ((void(*)(char*))get_cpuid)(result); code = ((int*)result)[3]; result[12]=0; fprintf(stderr,"cpuid: name=\"%12s\", flags=0x%08x\n", result,code); return 0;}' } options ["HAVE_PENTIUM"] } Feature.add { tag :mmx uses_feature [:pentium] uses_o ["cpu/mmx.o","cpu/mmx_loader.o"] name "MMX-compatible CPU (using NASM)" test proc { asm_test ' global main extern exit align 16 SECTION .data foo: dd 42,0 SECTION .text main: lea esi,[foo] movq mm0,qword[esi] paddd mm0,qword[esi] movq qword [esi],mm0 emms cmp dword [foo], 84 je yes push long 1 call exit yes: push long 0 call exit ', '-lc' } options ["HAVE_MMX"] } Feature.add { tag :simd uses_feature [:pentium] name "SIMD (MMX/SSE/Altivec) (using GCC)" test proc { c_test ' #include typedef int v8qi __attribute__ ((mode(V8QI))); union vv8qi { v8qi v; char c[8]; }; int main () { return 0; }',nil,["-mmmx"] } options ["HAVE_SIMD"] } Feature.add { tag :profiler name "profiler (speed measurements)" uses_feature [:pentium] options ["HAVE_TSC_PROFILING"] } #----------------------------------------------------------------# Feature.add { tag :usb name "USB Library" uses_h ["usb.h"] uses_o ["optional/usb.o"] uses_so ["-lusb"] test proc { c_test " #include# int main () {return usb_open==0 || usb_get_busses==0;} " } options ["HAVE_USB"] } #----------------------------------------------------------------# Feature.add { tag :ieee1394 name "IEEE1394 Libraries for Linux (raw1394/dc1394)" status :disabled uses_o ["optional/ieee1394.o"] uses_so ["-lraw1394","-ldc1394_control"] uses_h ["libraw1394/raw1394.h","libdc1394/dc1394_control.h"] test proc { c_test " #include# int main () {return raw1394_get_libversion==0 || dc1394_get_camera_info==0;} " } options ["HAVE_1394"] uses_o ["format/dc1394.o"] } Feature.add { tag :x11 name "X11 Display Protocol" uses_so $LIBX11 uses_h ["X11/Xlib.h"] test proc { c_test " #include# int main () {return XSetErrorHandler==0;} " } uses_o ["format/x11.o"] } Feature.add { tag :x11_shm name "X11 acceleration by shared memory (XSHM plugin)" uses_feature [:x11] uses_so $LIBX11+["-lXext"] uses_h ["X11/Xlib.h","sys/shm.h","X11/extensions/XShm.h"] test proc { c_test " #include# #include #include #include int main () {return XShmPutImage==0;} " } options ["HAVE_X11_SHARED_MEMORY"] } Feature.add { tag :x11_xv status :disabled name "X11 acceleration (XVIDEO plugin)" uses_feature [:x11] uses_so $LIBX11+["-lXext","-lXv"] uses_h ["X11/Xlib.h","X11/extensions/Xv.h"] test proc { c_test " #include# int main () {return 0;} " } options ["HAVE_X11_XVIDEO"] } Feature.add { tag :opengl name "OpenGL (only as framebuffer)" uses_so $LIBX11DIR+["-lglut","-lGL","-lGLU"] uses_h ["GL/gl.h","GL/glu.h","GL/glut.h"] test proc { c_test " #include# int main () {return glutInit==0;} " } uses_o ["format/opengl.o"] } Feature.add { tag :sdl name "Simple Directmedia Layer (experimental support)" uses_so { a=["-lSDL","-lpthread"] a<<"-lobjc" if OSX a } uses_h ["SDL/SDL.h"] test proc { c_test " #include# int main () {return SDL_MapRGB==0;} " } uses_o ["format/sdl.o"] } Feature.add { tag :objcpp name "GNU/Apple ObjectiveC++ Compiler" uses_h ["objc/Object.h"] uses_so ["-lobjc"] test proc { c_test " #include# int main () { [[Object alloc] init]; } ", nil, ["-xobjective-c++"] } } Feature.add { tag :quartz name "Apple Quartz/Cocoa Display" uses_so ["-lobjc",["-framework","Cocoa"]] uses_feature [:objcpp] uses_h ["objc/Object.h","Cocoa/Cocoa.h"] test proc { c_test " #include# int main () {return CGImageRelease==0;} ", nil, ["-xobjective-c++"] } uses_o ["format/quartz.o"] } Feature.add { tag :aalib name "Ascii Art Library" uses_so ["-laa"] uses_h ["aalib.h"] test proc { c_test " #define aa_hardwareparams aa_hardware_params extern \"C\" { #include# }; int main () {return aa_init==0;} " } uses_o ["format/aalib.o"] } Feature.add { tag :jpeg name "JPEG Library" uses_so ["-ljpeg"] uses_h ["jpeglib.h"] test proc { c_test " extern \"C\" { #include #include# }; int main () { return jpeg_write_scanlines==0;} " } uses_o ["format/jpeg.o"] } Feature.add { tag :png name "PNG Library" uses_so ["-lpng","-lz"] uses_h Or[["libpng12/png.h"],["png.h"]] test proc {|f| f.c_test %` extern "C" { #include #include# }; int main () { #define T(a) printf("%s:%d; ",#a,sizeof(a)); T(png_uint_32)T(long)puts(""); if (!png_check_sig) return 1; return 0;} ` } uses_o ["format/png.o"] } #------------------------------------------------# Feature.add { tag :videodev name "Video4linux Digitizer Driver Interface" uses_h ["linux/videodev.h"] test proc { c_test " #include #include# int main () { struct video_window foo; return 0; }" } uses_o ["format/videodev.o"] } Feature.add { tag :mpeg3 name "HeroineWarrior LibMPEG3" uses_so $LIBX11DIR+["-lmpeg3","-lpthread","-lm"] uses_h Or["libmpeg3/libmpeg3.h","libmpeg3.h"] test proc {|f| f.c_test " #include# int main () { return mpeg3_open==0; } " } uses_o ["format/mpeg3.o"] } Feature.add { tag :quicktimeapple name "Apple's QuickTime" uses_so [["-framework","Quicktime"]] uses_h ["Quicktime/quicktime.h","Quicktime/movies.h"] test proc { c_test " #include# int main () { return EnterMovies==0; } " } uses_o ["format/quicktimeapple.o"] } Feature.add { tag :quicktimehw unless_feature :quicktimeapple name "Plaum's LibQuickTime" uses_so Or[ ["-lquicktime","-lpthread","-lpng","-ldl","-lglib","-lz"], ["-lquicktime","-lpthread","-lpng","-ldl","-lglib-1.2","-lz"]] f = ["quicktime.h","colormodels.h","lqt.h","lqt_version.h","lqt_codecinfo.h"] uses_h Or[ f.map{|x| "quicktime/"+x }, f.map{|x| "lqt/"+x }] test proc {|f| f.c_test %` #include #include# int main () { fprintf(stderr,"LQT_VERSION = %s\\n", #ifdef LQT_VERSION LQT_VERSION #else "(undefined)" #endif ); return quicktime_open==0; } ` } uses_o ["format/quicktimehw.o"] } Feature.add { tag :xine name "Xine movie decoder" uses_so ["-lxine"] uses_h ["xine.h"] status :disabled test proc {|f| f.c_test %` #include #include# int main () { fprintf(stderr,"Xine version = %d.%d.%d (%s)\\n", XINE_MAJOR_VERSION, XINE_MINOR_VERSION, XINE_SUB_VERSION, XINE_VERSION); return xine_new==0; }` } uses_o ["format/xine.o"] } #Feature.add { # tag :example # name "example (example file optional/example.c)" # uses_o ["optional/example.o"] # test proc {|f| # c_test %` # #include # int main () { # return 0 /* 0=ok, nonzero=bad */; }` # } #} #----------------------------------------------------------------# Feature.add { tag :puredata name "Miller Puckette's Pure Data" uses_feature [Or[:libruby,:librubystatic]] options ["HAVE_PUREDATA"] defines { path = $C_INCLUDE_PATH.find {|x| File.exist?(x+"/m_pd.h")} m = /PD_VERSION_INT\s+(.*)/.match(File.popen("tmp/#{$$}","r"){|f| f.read }) {:PUREDATA_PATH => File.dirname(path)+"/lib/pd", :PD_VERSION_INT => m[1].to_i} } uses_h ["m_pd.h"] test proc { c_test %` #include# #include int main () { printf("#define PD_VERSION_INT %d\\n", #ifdef PD_MAJOR_VERSION (int)(PD_MAJOR_VERSION*100+PD_MINOR_VERSION)); #else (int)(PD_VERSION*100)); #endif return 0; } ` } } #--------------------------------# Feature.add { tag :gem name "PureData GEM (source code)" # uses_h [$conf[:DEFINES][:GEM_SOURCE]+"/src/Base/GemBase.h"] uses_feature [:puredata] uses_o ["optional/gem.o"] test proc { # hack $C_INCLUDE_PATH.unshift $conf[:DEFINES][ :GEM_SOURCE] $CFLAGS += " -I"+$conf[:DEFINES][ :GEM_SOURCE] c_test %` #include "Base/GemBase.h" int main () { return 0; } ` } } #--------------------------------# $features_h = {} $features.each {|f| $features_h[f.tag]=f } def usage log = "" log << "usage: ./configure " log << "[--use-compiler compiler] [--use-compiler-option option]* " log << "[--use-cpu cpu] [--lite] [--debug] [--debug-harder]" log << "[--ruby-prefix directory] [--gem-source directory]" # [--puredata-prefix directory] " $features_h.keys.map {|k| k.to_s }.sort.each {|k| log << "[--no-#{k}] " } $features_h.keys.map {|k| k.to_s }.sort.each {|k| log << "[--force-#{k}] " } puts while log.length>0 do puts log.slice!(/^.{1,70} /) end end while ARGV.length>0 do arg=ARGV.shift case arg when /=/ i=arg.index '=' ARGV.unshift arg[0..i-1], arg[i+1..-1] when /^--no-/ name = arg[5..-1].intern puts "there is no feature called #{name}" if not $features_h[name] puts "--no: won't check for feature #{name}" $features_h.delete name when /^--force-/ name = arg[8..-1].intern puts "there is no feature called #{name}" if not $features_h[name] puts "--force: assuming #{name} is there" $features_h[name].test nil when "--static" # experimental $conf[:STATIC]=true $conf[:LDSOFLAGS] << "-static" # ARGV.unshift "--no-libruby" when "--debug" puts "Debug Mode (more error checking; less speed)" $conf[:OPTIONS].push :HAVE_DEBUG $CFLAGS += " -fno-inline" when "--debug-harder" puts "Debug Harder Mode (even more error checking; even less speed)" $conf[:OPTIONS].push :HAVE_DEBUG $conf[:OPTIONS].push :HAVE_DEBUG_HARDER $CFLAGS += " -fno-inline" when "--lite" puts "Lite Mode (no float, no int64)" $conf[:OPTIONS].push :HAVE_LITE when "--help"; usage; exit 0 when "--prefix", "--ruby-prefix" : $conf[:DEFINES][:RUBY_PREFIX]=ARGV.shift when "--pd-prefix", "--puredata-prefix": $conf[:DEFINES][ :PD_PREFIX]=ARGV.shift when "--gem-source" : $conf[:DEFINES][ :GEM_SOURCE]=ARGV.shift when "--use-compiler" $conf[:CC] = ARGV.shift when "--use-compiler-option" $CFLAGS += " "+ARGV.shift when "--use-cpu" $conf[:DEFINES][:CPU] = ARGV.shift when "--verbose" $verbose=true when "--bindir" $conf[:BINDIR] = ARGV.shift else puts "unknown option \"#{arg}\""; usage; exit 1 end end # the ||= lines are patches for old versions of ruby. CONFIG["ruby_version"] ||= "$(MAJOR).$(MINOR)" CONFIG["rubylibdir"] ||= "$(libdir)/ruby/$(ruby_version)" CONFIG["archdir"] ||= CONFIG["rubylibdir"] + "/" + CONFIG["arch"] $CFLAGS += " -I" + (make_expand CONFIG["archdir"]) #--------------------------------# DUAL = Object.new DUAL.instance_eval { def self.print x LOG .puts x; LOG .flush STDERR.print x; STDERR.flush end def self.puts x self.print x+"\n" end } def try feature if Or===feature.uses_so k=1 feature.uses_so.a.each {|i| e=feature.dup; e.uses_so i; e.name(e.name+" (try \##{k})") r=try e; return r if r k+=1 } return false end if Or===feature.uses_h feature.uses_h.a.each {|i| e=feature.dup; e.uses_h i; e.name(e.name+" <#{i.to_a[0]}>") r=try e; return r if r } return false end LOG.puts "", "-"*64 line = "[#{feature.tag}] #{feature.name}: " DUAL.print Light + "[#{Yellow}#{feature.tag}#{Light}] #{feature.name}: " arrow = "-"*([78-line.length,0].max)+ "> " #DUAL.print Dark + arrow +Red (feature.uses_feature||[]).find {|f| if not ( if Or===f then f.a.find {|x| $conf[:FEATURES][x] } else $conf[:FEATURES][f] end ) then DUAL.puts Red+arrow+"disabled (would need #{f})" return end } if feature.status==:disabled then DUAL.puts Dark+arrow+"disabled (by author)"; return end if not $features_h[feature.tag] then DUAL.puts Dark+arrow+"disabled (by user)"; return end fu = feature.unless_feature || [] fu = [fu] if not Array===fu for f in fu || [] do if $conf[:FEATURES][f] then DUAL.puts Dark+arrow+"disabled (using #{f} instead)" return end end if feature.test begin tresult = feature.test.call(feature) rescue StandardError => e end if tresult DUAL.puts Green+arrow+"found "+(if tresult!=true then " (#{tresult})" else "" end) if tresult == "static" feature.uses_so.map! {|x| "-Wl,--whole-archive #{x} -Wl,--no-whole-archive" } if feature.uses_so feature.uses_bridge_so.map! {|x| "-Wl,--whole-archive #{x} -Wl,--no-whole-archive" } if feature.uses_bridge_so end else DUAL.puts Red+arrow+"missing "+(if e then (if $verbose then "(#{e} @ #{e.backtrace.join', '})" else "(#{e})" end) else "(return false)" end) if e LOG.puts e.inspect LOG.puts e.backtrace end return false end else puts Green+arrow+"enabled" $conf[:FEATURES][feature.tag] = feature feature.action.call if feature.action end feature.action.call if feature.action $conf[:FEATURES][feature.tag] = feature $conf[:LDSOFLAGS].concat(feature.uses_so||[]) $conf[:BRIDGE_LDFLAGS].concat(feature.uses_bridge_so||[]) $conf[:OBJS].concat(feature.uses_o||[]) $conf[:OPTIONS].concat(feature.options||[]) for k,v in feature.defines||{} do $conf[:DEFINES][k]=(if Proc===v then v[] else v end) end true end DUAL.puts "This is the GridFlow 0.8.1 configurator within Ruby version #{RUBY_VERSION}" begin $features.each {|feature| try feature } ensure #!@#$ note: see END{} (duplication) system "/bin/rm -f tmp/#{$$} tmp/#{$$}.c tmp/#{$$}.o tmp/#{$$}.asm" end puts Light $conf[:LDSOFLAGS].uniq! $conf[:BRIDGE_LDFLAGS].uniq! $CFLAGS += " -falign-functions=16" if $conf[:FEATURES][:gcc3] #if not $conf[:FEATURES][:gcc3] # puts "You should install gcc 3.x; gcc 2.9.x is no longer supported" # puts "(you might use --force-gcc3 to pretend at your own risk)" # exit 1 #end #--------------------------------# LOG.puts "-"*64 for z in [:BRIDGE_LDFLAGS, :LDSOFLAGS, :OPTIONS, :DEFINES, :OBJS] do LOG.puts "#{z}: #{$conf[z].inspect}" end LOG.puts "-"*64 RUBY = "$(RUBY_INSTALL_NAME)" def my_install_files(f,base,entries,obase="$(sitelibdir)/gridflow/#{base}") entries.each {|type,name,*rest| if Array===name then name,oname=name else oname=name end case type when :ruby f.puts "\t$(INSTALL_DATA) #{base+name} #{obase}/#{oname}" when :directory if oname[0,1]!="/" then oname="#{obase}/#{oname}" end f.puts "\t$(INSTALL_DIR) #{oname}" my_install_files(f,base+name,rest,oname) end } end def my_uninstall_files(f,base,entries,obase="$(sitelibdir)/gridflow/#{base}") entries.each {|type,name,*rest| if Array===name then name,oname=name else oname=name end case type when :ruby f.puts "\trm #{obase}/#{oname}" when :directory my_uninstall_files(f,base+name,rest) end } end def make_makefile f puts "" f.puts "RUBY = #{RUBY}" f.puts "ruby-all::", "" f.puts "ruby-install::" my_install_files(f,"",FILES) f.puts "\tcp bin/jmax2pd $(gfbindir); chmod 755 $(gfbindir)/jmax2pd\n" f.puts f.puts "ruby-uninstall::" my_uninstall_files(f,"",FILES) f.puts end puts "generating ./config.make" File.open("./config.make","w") {|f| f.puts " RUBYARCH=#{CONFIG['arch']} " f.puts "BRIDGE_LDFLAGS = " + $conf[:BRIDGE_LDFLAGS].flatten.join(" ") + " " + $LDFLAGS if OSX then f.puts "BRIDGE_LDFLAGS += -bundle -flat_namespace" else f.puts "BRIDGE_LDFLAGS += -rdynamic -shared" end $CFLAGS += " -mtune=$(CPU)" if $conf[:DEFINES][:CPU] $CFLAGS += " -march=$(CPU)" if $conf[:DEFINES][:CPU] #$CFLAGS += " -fforce-addr" #$CFLAGS += " -fprefetch-loop-arrays" #$CFLAGS += " -falign-jumps=4" #$CFLAGS += " -falign-loops=4" $CFLAGS += " -DMACOSX" if OSX f.puts "CFLAGS += " + $CFLAGS for k in $conf[:OPTIONS] do f.puts "#{k}=yes" end for k,v in $conf[:DEFINES] do f.puts "#{k}=#{v}" end $sources = %w( base/grid.c base/main.c base/number.c base/bitpacking.c base/flow_objects.c base/flow_objects_for_image.c base/flow_objects_for_matrix.c ) #for o in $conf[:OBJS] do # o=o.downcase.chomp(".o") # x = o.downcase+".c" # x = o.downcase+".m" if not File.exist?(x) # #raise "woops, missing file #{o.downcase}.*" if not File.exist?(x) and # # o!="cpu/mmx" # $sources << x #end f.puts "SOURCES = #{$sources.join(" ")} \\" f.puts "" } # end open config.make #--------------------------------# puts "generating config.h" File.open("config.h","w") {|f| f.puts " \#ifndef __CONFIG_H \#define __CONFIG_H /* this file was auto-generated by gridflow/configure */ " f.puts "#define STARTUP_LIST(PRE) \\" f.puts $conf[:OBJS].map {|o| "PRE startup_#{File.basename(o,'.o')}();" }.join("\\\n") for k in $conf[:OPTIONS] do f.puts "\#define #{k}" end for k,v in $conf[:DEFINES] do f.puts "\#define #{k} "+v.inspect end def include_here(f,a,b) return unless $conf[:FEATURES][b] f.puts "\#ifdef #{a}_INCLUDE_HERE" for inc in $conf[:FEATURES][b].uses_h.to_a do f.puts "\#include <#{inc}>" end f.puts "\#endif" end include_here f,"LIBMPEG", :mpeg3 include_here f,"QUICKTIMEHW",:quicktimehw f.puts " \#define RUBY_BINDIR #{make_expand(CONFIG['bindir']).inspect} \#endif /* __CONFIG_H */" } #--------------------------------# #puts "generating config.rb" #File.open("config.rb","w") {|f| f.puts %{ #\# this file was auto-generated by gridflow/configure #}} #----------------------------------------------------------------# # Some fairly nontrivial abuse of black magic. $LOCAL_LIBS = $conf[:LDSOFLAGS].flatten.join(" ") $objs = $sources.collect{|i| i.sub(/.[cm]$/,".o") } $objs[$objs.index("base/number.o"),1] = (1..3).map {|i| "base/number.#{i}.o" } dir_config("gridflow") create_makefile("gridflow") mf = File.readlines("Makefile").join"" common_deps1 = "$(COMMON_DEPS)" common_deps2 = common_deps1 + " base/grid.h.fcs" mf.sub!(/^.c.o:\s*\n\t(.*)\n/) { comp=$1 comp.sub!(/\(CC\)/,'(CXX)') comp << " -o $@" if not comp =~ /-o\s*\$@/ comp2 = comp.gsub /-c/,'-xobjective-c++ -c' "%.h.fcs: %.h #{common_deps1}\n\truby -w base/source_filter.rb $< $@\n\n"+ "%.c.fcs: %.c #{common_deps2}\n\truby -w base/source_filter.rb $< $@\n\n"+ "%.m.fcs: %.m #{common_deps2}\n\truby -w base/source_filter.rb $< $@\n\n"+ "%.o: %.c.fcs #{common_deps2}\n\t#{comp}\n"+ "%.1.o: %.c.fcs #{common_deps2}\n\t#{comp.gsub /-c/,'-DPASS1 -c'}\n"+ "%.2.o: %.c.fcs #{common_deps2}\n\t#{comp.gsub /-c/,'-DPASS2 -c'}\n"+ "%.3.o: %.c.fcs #{common_deps2}\n\t#{comp.gsub /-c/,'-DPASS3 -c'}\n"+ "%.o: %.m.fcs #{common_deps2}\n\t#{comp2}\n" } mf.gsub!(/^.SUFFIXES:.*$/, ".SUFFIXES:\n\n") or mf<<".SUFFIXES:\n\n" mf << ".PRECIOUS: %.h.fcs %.c.fcs %.m.fcs\n" mf.gsub! /DESTDIR/, 'RUBYDESTDIR' mf.gsub! /\*\.o/, "*.o */*.o" # GAAAH!!! if RUBY_VERSION >= "1.8" then mf.gsub!(/^((site-)?install:.*)/) {$1+" $(RUBYARCHDIR)/$(DLLIB) install2"} else mf.gsub!(/^((site-)?install:.*)/) {$1+" install2"} end mf.gsub!(/^install:.*/) {"install:site-install"} # should i keep this line? mf.sub!(/^all:(.*)$/) { "all: #{$1} all2" } mf.sub! /^clean:/,"clean: clean2 " mf.sub! /CC = gcc\n/, "CC = gcc\nCXX = #{$conf[:CC]}\n" mf.sub! /^(OBJS = .*)$/, "\\1 #{$conf[:OBJS].join' '}" mf[0,0] = "COMMON_DEPS = config.make Makefile Makefile.gf base/source_filter.rb\n"+ "gfbindir = #{$conf[:BINDIR]}\n" mf.sub!(/^site-install:\s*install/,"site-install: ") rp=$conf[:DEFINES][:RUBY_PREFIX] if rp mf.sub! /^prefix\s*=.*$/, "prefix = " + make_expand(rp) mf.sub! /^sitedir\s*=.*$/, "sitedir = " + make_expand(rp) end mf.sub! /^LDSHARED = g?cc/, "LDSHARED = $(CXX)" # Adam Lindsay's Mac attempts. mf.sub! /-no-precomp/, "-no-cpp-precomp" # for proper operation on Cygwin mf.sub! /--driver-name=gcc/, "--driver-name=#{$conf[:CC]}" # remove gcc3.2 warning about -I/usr/include mf.sub!(/^CPPFLAGS = (.*)$/) { cpp = "CPPFLAGS = " + make_expand($1).sub(%r"-I\s*/usr/include","") } f = File.open("Makefile","w") f.puts "include config.make" f.puts mf f.puts "include Makefile.gf" make_makefile f f.close #--------------------------------# puts "delegating to: devices4ruby/extconf.rb" r=$conf[:DEFINES][:RUBY_PREFIX] a=[] a<<"--prefix"<