I'm trying to compile my nim-libnx project for Windows, and it always seems to hang on the last object compilation. If I execute the command on it's own in the command line, it works fine, although it spits out a bunch of warnings (but that should be irrelevant).
The command in question is:
aarch64-none-elf-gcc -MMD -MP -MF C:\\Users\\Joey.DESKTOP-K6K357J\\Downloads\\nim-libnx\\nimcache\\helloworld\\stdlib_system.c.d
-c -g -Wall -O2 -ffunction-sections -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE -D__SWITCH__
-IC:\\Users\\Joey.DESKTOP-K6K357J\\Downloads\\nim-libnx\\src\\libnx\\wrapper\\nx\\include
-IC:\\Users\\Joey.DESKTOP-K6K357J\\Downloads\\nim-libnx\\src\\libnx\\wrapper\\nx\\include\\switch
-IC:\\Users\\Joey.DESKTOP-K6K357J\\Downloads\\nim-libnx\\src\\libnx\\wrapper\\nx\\include\\switch\\arm
-IC:\\Users\\Joey.DESKTOP-K6K357J\\Downloads\\nim-libnx\\src\\libnx\\wrapper\\nx\\include\\switch\\kernel
-IC:\\Users\\Joey.DESKTOP-K6K357J\\Downloads\\nim-libnx\\src\\libnx\\wrapper\\nx\\include\\switch\\services
-IC:\\Users\\Joey.DESKTOP-K6K357J\\Downloads\\nim-libnx\\src\\libnx\\wrapper\\nx\\include\\switch\\audio
-IC:\\Users\\Joey.DESKTOP-K6K357J\\Downloads\\nim-libnx\\src\\libnx\\wrapper\\nx\\include\\switch\\gfx
-IC:\\Users\\Joey.DESKTOP-K6K357J\\Downloads\\nim-libnx\\src\\libnx\\wrapper\\nx\\include\\switch\\runtime
-IC:\\Users\\Joey.DESKTOP-K6K357J\\Downloads\\nim-libnx\\src\\libnx\\wrapper\\nx\\include\\switch\\runtime\\util
-IC:\\Users\\Joey.DESKTOP-K6K357J\\Downloads\\nim-libnx\\src\\libnx\\wrapper\\nx\\include\\switch\\runtime\\devices
-IC:\\devkitPro\\devkitA64\\aarch64-none-elf\\include
-IC:\\Nim\\lib
-o C:\\Users\\Joey.DESKTOP-K6K357J\\Downloads\\nim-libnx\\nimcache\\helloworld\\stdlib_system.c.o
C:\\Users\\Joey.DESKTOP-K6K357J\\Downloads\\nim-libnx\\nimcache\\helloworld\\stdlib_system.c
I've managed to track down the offending line in the compiler that hangs the compilation. In osproc.nim, there is this section:
while ecount > 0:
var rexit = -1
when defined(windows):
# waiting for all children, get result if any child exits
var ret = waitForMultipleObjects(int32(wcount), addr(w), 0'i32, ### <- This is the line where it hangs
INFINITE)
waitForMultipleObjects is just a Windows system call, but it seems to hang for some reason. Now, just above that section, there is this section:
while i < m:
if beforeRunEvent != nil:
beforeRunEvent(i)
q[i] = startProcess(cmds[i], options = options + {poEvalCommand})
when defined(windows):
w[i] = q[i].fProcessHandle
inc(i)
If I change this line:
q[i] = startProcess(cmds[i], options = options + {poEvalCommand})
to this:
q[i] = startProcess(cmds[i], options = options + {poEvalCommand, poParentStreams})
and recompile the compiler and run my compilation, it finishes fine, although it shows the warnings just like when I run the command manually.
@Araq, this is probably a question for you, but would I be able to change this line without any repercussions? Or maybe there is a better way due to something I don't understand about Windows?
Or perhaps maybe one of these lines would be a better location? (in extccomp.nim, line 746):
else:
tryExceptOSErrorMessage(conf, "invocation of external compiler program failed."):
if optListCmd in conf.globalOptions or conf.verbosity > 1:
res = execProcesses(cmds, {poEchoCmd, poStdErrToStdOut, poUsePath}, #<- here
conf.numberOfProcessors, afterRunEvent=runCb)
elif conf.verbosity == 1:
res = execProcesses(cmds, {poStdErrToStdOut, poUsePath}, #<- or here
conf.numberOfProcessors, prettyCb, afterRunEvent=runCb)
else:
res = execProcesses(cmds, {poStdErrToStdOut, poUsePath}, #<- or here.
conf.numberOfProcessors, afterRunEvent=runCb)
I couldn't find out why poParentStreams makes the compilation work though. Anyone know what that switch does besides use the parent streams?
Ah, I found this comment in osprocs.nim:
proc waitForExit*(p: Process, timeout: int = -1): int {.rtl,
extern: "nosp$1", tags: [].}
## waits for the process to finish and returns `p`'s error code.
##
## **Warning**: Be careful when using waitForExit for processes created without
## poParentStreams because they may fill output buffers, causing deadlock.
##
## On posix, if the process has exited because of a signal, 128 + signal
## number will be returned.
Now I understand. Since there are warnings printed, it's likely the output buffers are getting filled and causing a deadlock. So what I need to do is remove warnings by adding -w to the aarch64-none-elf-gcc call. Tested it and it works very well!