diff options
-rw-r--r-- | compiler/vmgen.nim | 1 | ||||
m--------- | csources | 0 | ||||
-rw-r--r-- | koch.nim | 2 | ||||
-rw-r--r-- | lib/posix/posix.nim | 2 | ||||
-rw-r--r-- | lib/pure/asyncio.nim | 10 | ||||
-rw-r--r-- | lib/pure/osproc.nim | 2 | ||||
-rw-r--r-- | lib/pure/rawsockets.nim | 2 | ||||
-rw-r--r-- | lib/pure/sockets.nim | 2 | ||||
-rw-r--r-- | lib/windows/winlean.nim | 2 | ||||
-rw-r--r-- | tools/fakedeps.nim | 18 | ||||
-rw-r--r-- | tools/trimcc.nim | 207 |
11 files changed, 157 insertions, 91 deletions
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index fac3cf1bf..e0e34306c 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -1126,6 +1126,7 @@ proc checkCanEval(c: PCtx; n: PNode) = # we need to ensure that we don't evaluate 'x' here: # proc foo() = var x ... let s = n.sym + if {sfCompileTime, sfGlobal} <= s.flags: return if s.kind in {skVar, skTemp, skLet, skParam, skResult} and not s.isOwnedBy(c.prc.sym) and s.owner != c.module: cannotEval(n) diff --git a/csources b/csources new file mode 160000 +Subproject b0bcf88e26730b23d22e2663adf1babb05bd5a7 diff --git a/koch.nim b/koch.nim index f24d9bfbb..a94920429 100644 --- a/koch.nim +++ b/koch.nim @@ -332,7 +332,7 @@ proc temp(args: string) = proc showHelp() = quit(HelpText % [NimVersion & repeatChar(44-len(NimVersion)), - CompileDate, CompileTime]) + CompileDate, CompileTime], QuitSuccess) var op = initOptParser() op.next() diff --git a/lib/posix/posix.nim b/lib/posix/posix.nim index c3085f0fb..8c1c258db 100644 --- a/lib/posix/posix.nim +++ b/lib/posix/posix.nim @@ -2382,7 +2382,7 @@ proc hstrerror*(herrnum: cint): cstring {.importc, header: "<netdb.h>".} proc FD_CLR*(a1: cint, a2: var TFdSet) {.importc, header: "<sys/select.h>".} proc FD_ISSET*(a1: cint | SocketHandle, a2: var TFdSet): cint {. importc, header: "<sys/select.h>".} -proc fdSet*(a1: cint | SocketHandle, a2: var TFdSet) {. +proc FD_SET*(a1: cint | SocketHandle, a2: var TFdSet) {. importc: "FD_SET", header: "<sys/select.h>".} proc FD_ZERO*(a1: var TFdSet) {.importc, header: "<sys/select.h>".} diff --git a/lib/pure/asyncio.nim b/lib/pure/asyncio.nim index bb0d29fc4..0dbc0a3d5 100644 --- a/lib/pure/asyncio.nim +++ b/lib/pure/asyncio.nim @@ -91,11 +91,11 @@ import sockets, os ## getSocket(s).accept(client) when defined(windows): - from winlean import TimeVal, SocketHandle, fdSet, FD_ZERO, TFdSet, - fdSet, FD_ISSET, select + from winlean import TimeVal, SocketHandle, FD_SET, FD_ZERO, TFdSet, + FD_ISSET, select else: - from posix import TimeVal, SocketHandle, fdSet, FD_ZERO, TFdSet, - fdSet, FD_ISSET, select + from posix import TimeVal, SocketHandle, FD_SET, FD_ZERO, TFdSet, + FD_ISSET, select type DelegateObj* = object @@ -556,7 +556,7 @@ proc createFdSet(fd: var TFdSet, s: seq[Delegate], m: var int) = FD_ZERO(fd) for i in items(s): m = max(m, int(i.fd)) - fdSet(i.fd, fd) + FD_SET(i.fd, fd) proc pruneSocketSet(s: var seq[Delegate], fd: var TFdSet) = var i = 0 diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim index f47df73ca..0557b26f7 100644 --- a/lib/pure/osproc.nim +++ b/lib/pure/osproc.nim @@ -887,7 +887,7 @@ elif not defined(useNimRtl): FD_ZERO(fd) for i in items(s): m = max(m, int(i.outHandle)) - fdSet(cint(i.outHandle), fd) + FD_SET(cint(i.outHandle), fd) proc pruneProcessSet(s: var seq[Process], fd: var TFdSet) = var i = 0 diff --git a/lib/pure/rawsockets.nim b/lib/pure/rawsockets.nim index 5756ca23d..62a011999 100644 --- a/lib/pure/rawsockets.nim +++ b/lib/pure/rawsockets.nim @@ -372,7 +372,7 @@ proc createFdSet(fd: var TFdSet, s: seq[SocketHandle], m: var int) = FD_ZERO(fd) for i in items(s): m = max(m, int(i)) - fdSet(i, fd) + FD_SET(i, fd) proc pruneSocketSet(s: var seq[SocketHandle], fd: var TFdSet) = var i = 0 diff --git a/lib/pure/sockets.nim b/lib/pure/sockets.nim index 6975f07c0..36389edcc 100644 --- a/lib/pure/sockets.nim +++ b/lib/pure/sockets.nim @@ -936,7 +936,7 @@ proc createFdSet(fd: var TFdSet, s: seq[Socket], m: var int) = FD_ZERO(fd) for i in items(s): m = max(m, int(i.fd)) - fdSet(i.fd, fd) + FD_SET(i.fd, fd) proc pruneSocketSet(s: var seq[Socket], fd: var TFdSet) = var i = 0 diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim index cc633d90b..76d17bc4a 100644 --- a/lib/windows/winlean.nim +++ b/lib/windows/winlean.nim @@ -536,7 +536,7 @@ proc WSAFDIsSet(s: SocketHandle, set: var TFdSet): bool {. proc FD_ISSET*(socket: SocketHandle, set: var TFdSet): cint = result = if WSAFDIsSet(socket, set): 1'i32 else: 0'i32 -proc fdSet*(socket: SocketHandle, s: var TFdSet) = +proc FD_SET*(socket: SocketHandle, s: var TFdSet) = if s.fd_count < FD_SETSIZE: s.fd_array[int(s.fd_count)] = socket inc(s.fd_count) diff --git a/tools/fakedeps.nim b/tools/fakedeps.nim new file mode 100644 index 000000000..80623fafb --- /dev/null +++ b/tools/fakedeps.nim @@ -0,0 +1,18 @@ +import strutils, os, pegs, strtabs, math, threadpool, times + +proc fakeCppDep(x: ptr float) {.importcpp: "fakeCppDep", header: "<vector>".} +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()) + +proc main = + fakedeps() +when isMainModule: + main() \ No newline at end of file diff --git a/tools/trimcc.nim b/tools/trimcc.nim index b6bf282b6..276ea1dbe 100644 --- a/tools/trimcc.nim +++ b/tools/trimcc.nim @@ -1,34 +1,17 @@ -# Trim C compiler installation to a minimum - -import strutils, os, pegs, strtabs, math, threadpool, times +# Trim C compiler installation to a minimum -proc fakeCppDep(x: ptr float) {.importcpp: "fakeCppDep", header: "<vector>".} +import strutils, os, pegs, strtabs, math, threadpool, times 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 +crtbegin.o crtend.o crt2.o dllcrt2.o libgcc_s_dw2-1.dll libgcc_s_sjlj-1.dll +libgcc_s_seh-1.dll 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" @@ -40,88 +23,152 @@ proc includes(headerpath, headerfile: string, whitelist: StringTableRef) = if whitelist[m] != "processed": whitelist[m] = "found" -proc processIncludes(dir: string, whitelist: StringTableRef) = - for kind, path in walkDir(dir): - case kind +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 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) + 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 +proc gatherFiles(dir: string, whitelist: StringTableRef, result: var seq[string]) = + for kind, path in walkDir(dir): + case kind of pcFile: - let name = extractFilename(path) + 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 = - let (dir, name, ext) = splitFile(f) - return dir / "trim_" & name & ext + of pcDir: + gatherFiles(path, whitelist, result) + else: + discard + +proc gatherEmptyFolders(dir: string, whitelist: StringTableRef, result: var seq[string]) = + var empty = true + for kind, path in walkDir(dir): + case kind + of pcFile: + empty = false + of pcDir: + let (none, name) = splitPath(path) + if not whitelist.hasKey(name): + gatherEmptyFolders(path, whitelist, result) + empty = false + else: + discard + if empty: + result.add(dir) + +proc newName(f: string): string = + 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 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) + c1 = r"nim c --verbosity:0 --force_build koch" + c2 = r"nim c --verbosity:0 --force_build --threads:on --out:tempOne.exe trimcc" + c3 = r"nim c --verbosity:0 --force_build --threads:on --out:tempTwo.exe fakeDeps" + c4 = r".\koch.exe" + c5 = r".\tempOne.exe" + c6 = r".\tempTwo.exe" + result = execShellCmd(c1) == 0 and execShellCmd(c2) == 0 and + execShellCmd(c3) == 0 and execShellCmd(c4) == 0 and + execShellCmd(c5) == 0 and execShellCmd(c6) == 0 + +proc trialDeletion(files: seq[string], a, b: int, whitelist: StringTableRef): bool = + result = true + var single = (a == min(b, files.high)) + for path in files[a .. min(b, files.high)]: + try: + moveFile(dest=newName(path), source=path) + except OSError: + return false + + # Test if compilation still works, even with the moved files. 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)) + for path in files[a .. min(b, files.high)]: + try: + removeFile(newName(path)) + echo "Optional: ", path + except OSError: + echo "Warning, couldn't move ", path + moveFile(dest=path, source=newName(path)) + return false + else: + for path in files[a .. min(b, files.high)]: + echo "Required: ", path + moveFile(dest=path, source=newName(path)) + if single: + whitelist[path] = "found" + result = false proc main(dir: string) = + # Construct a whitelist of files to not remove 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: + if oldLen == whitelist.len: + break + + # Remove batches of files + var nearlyDone = false + while true: + # Gather files to test + var allFiles = newSeq[string]() + gatherFiles(dir, whitelist, allFiles) + + # Determine the initial size of groups to check + var + maxBucketSize = len(allFiles) + bucketSize = 1 + + # Loop through the list of files, deleting batches var i = 0 while i < allFiles.len: - trialDeletion(allFiles, i, i+BucketSize-1) - inc i, BucketSize - else: - for x in allFiles: echo x + var success = trialDeletion(allFiles, i, i+bucketSize-1, whitelist) + inc i, bucketSize + + # If we aren't on the last pass, adjust the batch size based on success + if not nearlyDone: + if success: + bucketSize = min(bucketSize * 2, maxBucketSize) + else: + bucketSize = max(bucketSize div 2, 1) + echo "Bucket size is now ", bucketSize -proc fakeTimeDep() = echo(times.getDateStr()) + # After looping through all the files, check if we need to break. + if nearlyDone: + break + if bucketSize == 1: + nearlyDone = true + + while true: + var + emptyFolders = newSeq[string]() + changed = false -proc fakedeps() = - var x = 0.4 - {.emit: "#if 0\n".} - fakeCppDep(addr x) - {.emit: "#endif\n".} + gatherEmptyFolders(dir, whitelist, emptyFolders) + for path in emptyFolders: + removeDir(path) + if not ccStillWorks(): + createDir(path) + whitelist[path] = "found" + else: + changed = true + if not changed: + break - # this is not true: - if math.sin(x) > 0.6: - spawn(fakeTimeDep()) - if paramCount() == 1: doAssert ccStillWorks() - fakedeps() - main(paramStr(1)) -else: - quit "Usage: trimcc c_compiler_directory" + main(paramStr(1)) +else: + quit "Usage: trimcc c_compiler_directory", QuitSuccess |