diff options
-rw-r--r-- | tools/trimcc.nim | 138 |
1 files changed, 118 insertions, 20 deletions
diff --git a/tools/trimcc.nim b/tools/trimcc.nim index 4d9686195..b6bf282b6 100644 --- a/tools/trimcc.nim +++ b/tools/trimcc.nim @@ -1,29 +1,127 @@ # Trim C compiler installation to a minimum -import strutils, os +import strutils, os, pegs, strtabs, math, threadpool, times + +proc fakeCppDep(x: ptr float) {.importcpp: "fakeCppDep", header: "<vector>".} + +const + Essential = """gcc.exe g++.exe gdb.exe ld.exe as.exe c++.exe cpp.exe cc1.exe +crtbegin.o crtend.o crt2.o dllcrt2.o +libexpat-1.dll libwinpthread-1.dll + +aio.h +dlfcn.h +fcntl.h fenv.h fmtmsg.h fnmatch.h ftw.h +errno.h +glob.h gtmath.h +if.h in.h ipc.h +langinfo.h locale.h +math.h mman.h +netdb.h nl_types.h +poll.h pthread.h pwd.h +sched.h select.h semaphore.h signal.h +socket.h spawn.h stat.h statvfs.h stdio.h stdlib.h string.h strings.h +tcp.h time.h types.h +ucontext.h uio.h utsname.h unistd.h +wait.h +varargs.h +windows.h +zlib.h +""".split + BucketSize = 40 + +proc includes(headerpath, headerfile: string, whitelist: StringTableRef) = + whitelist[headerfile] = "processed" + for line in lines(headerpath): + if line =~ peg"""s <- ws '#include' ws ('"' / '<') {[^">]+} ('"' / '>') ws + comment <- '/*' @ '*/' / '//' .* + ws <- (comment / \s+)* """: + let m = matches[0].extractFilename + if whitelist[m] != "processed": + whitelist[m] = "found" + +proc processIncludes(dir: string, whitelist: StringTableRef) = + for kind, path in walkDir(dir): + case kind + of pcFile: + let name = extractFilename(path) + if ('.' notin name and "include" in path) or ("c++" in path): + let n = whitelist[name] + if n != "processed": whitelist[name] = "found" + if name.endswith(".h"): + let n = whitelist[name] + if n == "found": includes(path, name, whitelist) + of pcDir: processIncludes(path, whitelist) + else: discard + +proc gatherFiles(dir: string, whitelist: StringTableRef, result: var seq[string]) = + for kind, path in walkDir(dir): + case kind + of pcFile: + let name = extractFilename(path) + if not whitelist.hasKey(name): + result.add(path) + of pcDir: gatherFiles(path, whitelist, result) + else: discard proc newName(f: string): string = - var (dir, name, ext) = splitFile(f) + let (dir, name, ext) = splitFile(f) return dir / "trim_" & name & ext + +proc ccStillWorks(): bool = + const + c1 = r"nim c --force_build koch" + c2 = r"nim c --force_build --threads:on --out:temp.exe tools/trimcc" + result = execShellCmd(c1) == 0 and execShellCmd(c2) == 0 -proc walker(dir: string) = - for kind, path in walkDir(dir): - case kind - of pcFile: - moveFile(dest=newName(path), source=path) - # test if installation still works: - if execShellCmd(r"nimrod c --force_build koch") == 0: - echo "Optional: ", path - removeFile(newName(path)) - else: - echo "Required: ", path - # copy back: - moveFile(dest=path, source=newName(path)) - of pcDir: - walker(path) - else: discard +proc trialDeletion(files: seq[string], a, b: int) = + for i in a .. min(b, files.high): + let path = files[i] + moveFile(dest=newName(path), source=path) + if ccStillWorks(): + for i in a .. min(b, files.high): + let path = files[i] + echo "Optional: ", path + removeFile(newName(path)) + else: for i in a .. min(b, files.high): + let path = files[i] + echo "Required: ", path + # copy back: + moveFile(dest=path, source=newName(path)) + +proc main(dir: string) = + var whitelist = newStringTable(modeCaseInsensitive) + for e in Essential: + whitelist[e] = "found" + while true: + let oldLen = whitelist.len + processIncludes(dir, whitelist) + if oldLen == whitelist.len: break + var allFiles: seq[string] = @[] + gatherFiles(dir, whitelist, allFiles) + when true: + var i = 0 + while i < allFiles.len: + trialDeletion(allFiles, i, i+BucketSize-1) + inc i, BucketSize + else: + for x in allFiles: echo x + +proc fakeTimeDep() = echo(times.getDateStr()) + +proc fakedeps() = + var x = 0.4 + {.emit: "#if 0\n".} + fakeCppDep(addr x) + {.emit: "#endif\n".} + + # this is not true: + if math.sin(x) > 0.6: + spawn(fakeTimeDep()) -if paramCount() == 1: - walker(paramStr(1)) +if paramCount() == 1: + doAssert ccStillWorks() + fakedeps() + main(paramStr(1)) else: quit "Usage: trimcc c_compiler_directory" |