jart / cosmopolitan

build-once run-anywhere c library
ISC License
18.26k stars 625 forks source link

`__stderrp` is not defined #1157

Open renatoathaydes opened 5 months ago

renatoathaydes commented 5 months ago

I was trying to compile some Nim code using cosmocc, and it turns out the generated C code can't be compiled due to errors like this:

@snim@slib@ssystem.nim.c:1055:18: error: ‘__stderrp’ undeclared (first use in this function); did you mean ‘stderr’?
 1055 |         rawWrite(__stderrp, "out of memory\012");
      |                  ^~~~~~~~~
      |                  stderr

I created the following C file to reproduce the issue:

#include <stdio.h>

int main(void) {
  return fputs("hello world\n", __stderrp);
}

Compiling with gcc, this runs correctly.

But with cosmocc I get this error:

./hello.c: In function ‘main’:
./hello.c:4:33: error: ‘__stderrp’ undeclared (first use in this function); did you mean ‘stderr’?
    4 |   return fputs("hello world\n", __stderrp);
      |                                 ^~~~~~~~~
      |                                 stderr
./hello.c:4:33: note: each undeclared identifier is reported only once for each function it appears in
/Users/renatoathaydes/programming/apps/cosmocc/bin/cosmocc: line 396:  8053 Terminated: 15          ( set -- "$CC_AARCH64" -o"$OUTPUT_AARCH64" $PLATFORM $PREDEF $CFLAGS_AARCH64 $CPPFLAGS_AARCH64 "$@" $DEPENDENCY_FLAGS_AARCH64 $FLAGS_AARCH64 $PRECIOUS; log_command "$@"; "$@" || exit; set -- "$BIN/fixupobj" "$OUTPUT_AARCH64"; log_command "$@"; exec "$@" ) 2> "$out2"

Sorry if I am being ignorant, but it appears to me __stderrp, given it is used even by stdio.h (which uses that to define stderr), is required to be defined by the C standard itself (I would love to check the standard but I don't know where to look)?

If I am just wrong, could you help me get around this problem anyway?

renatoathaydes commented 5 months ago

My actual objective is to compile a small Nim program to C using cosmocc, and then generate an actuallyportable binary for it... so perhaps my original program in Nim could help find out what is needed for this to work.

This is the nim file http_client.nim I want to compile (just a silly example, but this does most of what the real program needs to do):

import std/httpclient
import std/os

if paramCount() != 1:
  quit "Please provide a single argument: URL to request."

var url = paramStr(1)
if url == "":
  quit "Please enter an URL!"

echo "URL: ", url
var client = newHttpClient()
try:
  echo client.getContent(url)
finally:
  client.close()

I am using this file (nim.cfg in the same directory as the nim file) to force Nim to use my local cosmocc installation for compiling:

gcc.path = "/Users/renatoathaydes/programming/apps/cosmocc/bin/"
gcc.exe = "cosmocc"
gcc.linkerexe = "cosmocc"

And finally, the Nim compiler command:

nim c --cc:gcc --threads:off --app:console -d:ssl -d:release http_client.nim
ahgamut commented 5 months ago

what happens if you #define __stderrp stderr?

renatoathaydes commented 5 months ago

I was able to compile the code in Nim using this header file (I called it cosmocc.h):

#ifndef __stdinp
#define __stdinp stdin
#endif

#ifndef __stderrp
#define __stderrp stderr
#endif

#ifndef __stdoutp
#define __stdoutp stdout
#endif

And then telling the C compiler to auto-include it... which can be done by using --passc:-include when invoking the Nim compiler (or by adding the equivalent pragma):

▶ nim c --cc:gcc --passc:"-include cosmocc.h" -d:release main.nim

Perhaps Cosmopolitan could define this by default to avoid this same problem with other tools?