1(*quietdec := true; 2app load ["Mosml", "Process", "Path", "FileSys", "Timer", "Real", "Int", 3 "Bool", "OS"] ; 4open Mosml; 5*) 6val _ = PolyML.Compiler.prompt1:=""; 7val _ = PolyML.Compiler.prompt2:=""; 8val _ = PolyML.print_depth 0; 9 10(* utility functions *) 11fun warn s = TextIO.output(TextIO.stdErr, s ^ "\n") 12fun die s = (TextIO.output(TextIO.stdErr, s ^ "\n"); 13 OS.Process.exit OS.Process.failure) 14 15val _ = if PolyML.Compiler.compilerVersionNumber < 551 then 16 die "Must be running PolyML with version >= 5.5.1\n" 17 else () 18 19fun readdir s = let 20 val ds = OS.FileSys.openDir s 21 fun recurse acc = 22 case OS.FileSys.readDir ds of 23 NONE => acc 24 | SOME s => recurse (s::acc) 25in 26 recurse [] before OS.FileSys.closeDir ds 27end; 28 29fun mem x [] = false 30 | mem x (h::t) = x = h orelse mem x t 31 32fun frontlast [] = raise Fail "frontlast: failure" 33 | frontlast [h] = ([], h) 34 | frontlast (h::t) = let val (f,l) = frontlast t in (h::f, l) end; 35 36fun check_dir nm privs candidate = let 37 open OS.FileSys 38 val p = OS.Path.concat(candidate,nm) 39in 40 if access(p, privs) then SOME (OS.Path.dir (fullPath p)) else NONE 41end 42val check_poly = check_dir "poly" [OS.FileSys.A_EXEC] 43val check_libpoly = check_dir "libpolymain.a" [OS.FileSys.A_READ] 44fun check_polyc c = 45 Option.map (fn p => OS.Path.concat(p,"polyc")) 46 (check_dir "polyc" [OS.FileSys.A_EXEC] c) 47 48fun findpartial f [] = NONE 49 | findpartial f (h::t) = 50 case f h of NONE => findpartial f t | x => x 51 52(* sleeping, with an action every second *) 53fun delay limit action = let 54 fun loop cnt = 55 if cnt >= limit then () 56 else (action cnt; 57 Posix.Process.sleep (Time.fromSeconds 1); 58 loop (cnt + 1)) 59in 60 loop 0 61end; 62 63fun determining s = 64 (print (s^" "); delay 1 (fn _ => ())); 65 66(* action starts here *) 67print "\nHOL smart configuration.\n\n"; 68 69val poly = "" 70val polyc = NONE : string option 71val polymllibdir = ""; 72val DOT_PATH = SOME ""; 73val MLTON = SOME ""; 74val POLY_LDFLAGS = [] : string list; 75val POLY_LDFLAGS_STATIC = [] : string list; 76 77val _ = let 78 val override = "tools-poly/poly-includes.ML" 79in 80 if OS.FileSys.access (override, [OS.FileSys.A_READ]) then 81 (print ("[Using override file "^override^"]\n\n"); 82 use override) 83 else () 84end; 85 86print "Determining configuration parameters: "; 87 88val currentdir = OS.FileSys.getDir(); 89 90fun dirify {arcs,isAbs,vol} = 91 OS.Path.toString {arcs = #1 (frontlast arcs), isAbs = isAbs, vol = vol}; 92 93determining "holdir"; 94 95val holdir = let 96 val cdir_files = readdir currentdir 97in 98 if mem "sigobj" cdir_files andalso mem "std.prelude" cdir_files then 99 currentdir 100 else if mem "smart-configure.sml" cdir_files andalso 101 mem "configure.sml" cdir_files 102 then dirify (OS.Path.fromString currentdir) 103 else die "\n\n*** Couldn't determine holdir; \ 104 \please run me from the root HOL directory" 105end; 106 107val _ = let 108in 109 OS.FileSys.chDir (OS.Path.concat (holdir, "tools-poly")); 110 use "poly/Mosml.sml"; 111 OS.FileSys.chDir currentdir 112end; 113 114val OS = let 115 val _ = determining "OS" 116 val {vol,...} = OS.Path.fromString currentdir 117in 118 if vol = "" then (* i.e. Unix *) 119 case Mosml.run "uname" ["-a"] "" of 120 Mosml.Success s => if String.isPrefix "Linux" s then 121 "linux" 122 else if String.isPrefix "SunOS" s then 123 "solaris" 124 else if String.isPrefix "Darwin" s then 125 "macosx" 126 else 127 "unix" 128 | Mosml.Failure s => (print "\nRunning uname failed with message: "; 129 print s; 130 OS.Process.exit OS.Process.failure) 131 else "winNT" 132end 133 134fun which arg = 135 let 136 open OS.FileSys 137 val sepc = if OS = "winNT" then #";" else #":" 138 fun check p = 139 let 140 val fname = OS.Path.concat(p, arg) 141 in 142 if access (fname, [A_READ, A_EXEC]) then 143 SOME 144 (OS.Path.mkAbsolute{path = fname, relativeTo = OS.FileSys.getDir()}) 145 else NONE 146 end 147 in 148 case OS.Process.getEnv "PATH" of 149 SOME path => 150 let 151 val paths = (if OS = "winNT" then ["."] else []) @ 152 String.fields (fn c => c = sepc) path 153 in 154 findpartial check paths 155 end 156 | NONE => if OS = "winNT" then check "." else NONE 157 end 158 159val polyinstruction = 160 "Please write file tools-poly/poly-includes.ML to specify it \ 161 \properly.\n\ 162 \This file should include a line of the form\n\n\ 163 \ val poly = \"path-to-poly\";" 164val (poly,polycopt) = 165 if poly = "" then let 166 val _ = determining "poly" 167 val nm = CommandLine.name() 168 val p as {arcs, isAbs, vol} = OS.Path.fromString nm 169 val cand = 170 if isAbs then SOME (dirify p) 171 else if length arcs > 1 then 172 SOME (OS.Path.mkAbsolute { path = dirify p, 173 relativeTo = OS.FileSys.getDir()}) 174 else (* examine PATH variable *) 175 case OS.Process.getEnv "PATH" of 176 NONE => NONE 177 | SOME elist => let 178 val sep = case OS of "winNT" => #";" | _ => #":" 179 val search_these = String.fields (fn c => c = sep) elist 180 in 181 findpartial check_poly search_these 182 end 183 in 184 case cand of 185 NONE => die 186 ("\n\nYou ran poly on the commandline, but it doesn't seem \ 187 \to be in your PATH.\n\ 188 \I need to know where your poly executable is.\n" ^ 189 polyinstruction) 190 | SOME c => let 191 in 192 case check_poly c of 193 SOME p => (OS.Path.concat(p,"poly"), check_polyc p) 194 | NONE => 195 die ("\n\nI tried to figure out where your poly executable is\ 196 \n\by examining your command-line.\n\ 197 \But directory "^c^ 198 "doesn't seem to contain a poly executable after \ 199 \all\n" ^ 200 polyinstruction) 201 end 202 end 203 else 204 case check_poly (OS.Path.dir poly) of 205 NONE => die ("\n\nYour overrides file specifies bogus location '" 206 ^poly^ 207 "'\nas the location of the poly executable.\n"^ 208 polyinstruction) 209 | SOME p => (OS.Path.concat(p, "poly"), check_polyc p) 210 211val polyc = 212 case polycopt of 213 NONE => die ("Couldn't find polyc executable\n" ^ polyinstruction) 214 | SOME p => p 215 216val polylibsister = let 217 val p as {arcs,isAbs,vol} = OS.Path.fromString poly 218 val (dirname, _) = frontlast arcs 219 val (parent, probably_bin) = frontlast dirname 220 val _ = if probably_bin <> "bin" then 221 warn "\nSurprised that poly is not in a \"bin\" directory" 222 else () 223in 224 OS.Path.toString { arcs = parent @ ["lib"], vol = vol, isAbs = isAbs } 225end 226 227val polylibinstruction = 228 "Please write file tools-poly/poly-includes.ML to specify it.\n\ 229 \This file should include a line of the form\n\n\ 230 \ val polymllibdir = \"path-to-dir-containing-libpolymain.a\";" 231 232val polymllibdir = 233 if polymllibdir = "" then let 234 val _ = determining "polymllibdir" 235 in 236 case check_libpoly polylibsister of 237 SOME c => c 238 | NONE => die ("\n\nLooked in poly's sister lib directory "^ 239 polylibsister ^ 240 "\nand couldn't find libpolymain.a\n" ^ 241 polylibinstruction) 242 243 end 244 else 245 case check_libpoly polymllibdir of 246 SOME c => c 247 | NONE => die ("\n\nYour overrides file specifies bogus location '" 248 ^polymllibdir ^ 249 "'\nas the location of libpolymain.a\n" ^ 250 polylibinstruction); 251 252val DOT_PATH = if DOT_PATH = SOME "" then which "dot" else DOT_PATH; 253 254val dynlib_available = false; 255 256val MLTON = if MLTON = SOME "" then which "mlton" else MLTON; 257 258print "\n"; 259 260fun verdict (prompt, value) = 261 if value = "" then 262 (print ("\n*** No value for "^prompt^ 263 "!! Write a tools-poly/poly-includes.ML file to fix this\n"); 264 OS.Process.exit OS.Process.failure) 265 else 266 (print (StringCvt.padRight #" " 20 (prompt^":")); 267 print value; 268 print "\n"); 269 270fun optverdict (prompt, optvalue) = 271 (print (StringCvt.padRight #" " 20 (prompt ^ ":")); 272 print (case optvalue of NONE => "NONE" | SOME p => "SOME "^p); 273 print "\n"); 274 275verdict ("OS", OS); 276verdict ("poly", poly); 277verdict ("polyc", polyc); 278verdict ("polymllibdir", polymllibdir); 279verdict ("holdir", holdir); 280optverdict ("DOT_PATH", DOT_PATH); 281optverdict ("MLTON", MLTON); 282 283print "\nConfiguration will begin with above values. If they are wrong\n"; 284print "press Control-C.\n\n"; 285 286delay 3 287 (fn n => print ("\rWill continue in "^Int.toString (3 - n)^" seconds.")) 288 handle Interrupt => (print "\n"; OS.Process.exit OS.Process.failure); 289 290print "\n"; 291 292val configfile = OS.Path.concat (OS.Path.concat (holdir, "tools-poly"), "configure.sml"); 293 294 295use configfile handle Fail s => die s; 296