(* run-cc.sml * * This code is part of the Diderot Project (http://diderot-language.cs.uchicago.edu) * * COPYRIGHT (c) 2015 The University of Chicago * All rights reserved. * * Support for running the C compiler to compile and link the generated code. *) structure RunCC : sig (* compile ("base", cflags) -- compiles the file "base.c" to produce "base.o". *) val compile : string * string list -> unit (* linkExec ("base", opts) -- links base.o to create an executable using the * given options (libraries, etc.) *) val linkExec : string * string list -> unit (* linkLib ("base", opts) -- links base.o to create using the given options (libraries, etc.) *) val linkLib : string * string list -> unit end = struct fun system cmd = ( Log.msg(cmd ^ "\n"); if OS.Process.isSuccess(OS.Process.system cmd) then () else raise Fail "error compiling/linking") fun compile (baseName, cflags) = let val cFile = OS.Path.joinBaseExt{base=baseName, ext=SOME"c"} val cmd = String.concatWith " " ([Paths.cc, "-c"] @ cflags @ [cFile]) in PhaseTimer.withTimer Timers.timeCC system cmd end fun linkExec (baseName, ldOpts) = let val objFile = OS.Path.joinBaseExt{base=baseName, ext=SOME"o"} val exeFile = baseName val cmd = String.concatWith " " ([Paths.cc, "-o", exeFile, objFile] @ ldOpts) in PhaseTimer.withTimer Timers.timeCC system cmd end fun linkLib (baseName, ldOpts) = let val objFile = OS.Path.joinBaseExt{base=baseName, ext=SOME"o"} val tmpFile = let (* on Linux systems, the rename fails if the src and dst are on * different devices, so we create the temp file in the same * directory as the final target. *) val {file, ...} = OS.Path.splitDirFile(OS.FileSys.tmpName()) val {dir, ...} = OS.Path.splitDirFile baseName in OS.Path.joinDirFile{ dir = dir, file = OS.Path.joinBaseExt{ base = file, ext = SOME "o" } } end val cmd = String.concatWith " " ([Paths.ld, "-r", "-o", tmpFile, objFile] @ ldOpts) fun link () = ( system cmd; Log.msg(concat["rename ", tmpFile, " to ", objFile, "\n"]); OS.FileSys.rename{old=tmpFile, new=objFile} handle ex => (OS.FileSys.remove tmpFile; raise ex)) in PhaseTimer.withTimer Timers.timeCC link () end end