feat: hosted libstdc++ for x86_64-montauk - full C++ on MontaukOS
The cross toolchain now builds real hosted C++: std::string, vector, unique_ptr, iostreams and exceptions all work in a plain x86_64-montauk-g++ invocation with no special flags. This is the library that native cc1plus will link against for the GCC self-host. crt1 now runs .preinit_array/.init_array before main and hooks .fini_array through atexit (main returns via exit(), so destructors run on both exit paths). Global constructors and libgcc's eh_frame registration both ride this. GCC is reconfigured with --enable-initfini-array (modern arrays instead of .ctors), --with-newlib (satisfies libstdc++'s crossconfig for unknown hosts), --disable-wchar_t and --disable-libstdcxx-pch; the montauk gcc patch grows a hunk keeping os/generic ctype under --with-newlib (the Montauk libc is not newlib). libc additions harvested by the libstdc++ build: mbtowc/wctomb, strxfrm, strtok/strtok_r, a real vfscanf/fscanf/scanf (character- driven with widths and l/ll; also unblocks gprof later), fgetpos/ fsetpos/setbuf/fpos_t, modf plus the C99 float math variants (acosf..tanhf, hypot/hypotf as wrappers), FP_* classification macros, the full POSIX errno vocabulary, complete DT_* dirent types, and mbstate_t. The SDK ships the real libstdc++.a (was an empty stand-in), the C++ headers at 0:/sdk/include/c++, and cxx-test.elf (global ctor, string, vector+sort, unique_ptr, throw/catch; exits 0 on 5/5). Ramdisk sits at 1571 files, within the 2048 table. Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
@@ -12,4 +12,4 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define MONTAUK_BUILD_NUMBER 16
|
||||
#define MONTAUK_BUILD_NUMBER 18
|
||||
|
||||
@@ -401,8 +401,10 @@ ifneq ($(wildcard $(NATIVE_BIN)/as),)
|
||||
cp lib/libc/liblibc.a $(BINDIR)/sdk/lib/libc.a
|
||||
cp lib/libc/crt1.o lib/libc/crti.o lib/libc/crtn.o $(BINDIR)/sdk/lib/
|
||||
ar rcs $(BINDIR)/sdk/lib/libm.a
|
||||
ar rcs $(BINDIR)/sdk/lib/libstdc++.a
|
||||
cp ../toolchain/local/x86_64-montauk/lib/libstdc++.a $(BINDIR)/sdk/lib/libstdc++.a
|
||||
cp -r ../toolchain/local/x86_64-montauk/include/c++ $(BINDIR)/sdk/include/c++
|
||||
../toolchain/local/bin/x86_64-montauk-gcc -O2 ../toolchain/files/tls-test.c -o $(BINDIR)/sdk/bin/tls-test.elf
|
||||
../toolchain/local/bin/x86_64-montauk-g++ -O2 ../toolchain/files/cxx-test.cpp -o $(BINDIR)/sdk/bin/cxx-test.elf
|
||||
else
|
||||
@echo "devkit: toolchain/native/ not built; skipping native dev tools"
|
||||
endif
|
||||
|
||||
@@ -9,8 +9,13 @@ extern "C" {
|
||||
|
||||
#define NAME_MAX 255
|
||||
#define DT_UNKNOWN 0
|
||||
#define DT_FIFO 1
|
||||
#define DT_CHR 2
|
||||
#define DT_DIR 4
|
||||
#define DT_BLK 6
|
||||
#define DT_REG 8
|
||||
#define DT_LNK 10
|
||||
#define DT_SOCK 12
|
||||
|
||||
struct dirent {
|
||||
unsigned char d_type;
|
||||
|
||||
@@ -49,8 +49,47 @@ extern int errno;
|
||||
#define ENOTEMPTY 39
|
||||
#define ELOOP 40
|
||||
#define EWOULDBLOCK EAGAIN
|
||||
#define ETXTBSY 26
|
||||
#define ENOMSG 42
|
||||
#define EIDRM 43
|
||||
#define ENOSTR 60
|
||||
#define ENODATA 61
|
||||
#define ETIME 62
|
||||
#define ENOSR 63
|
||||
#define ENOLINK 67
|
||||
#define EPROTO 71
|
||||
#define EMULTIHOP 72
|
||||
#define EBADMSG 74
|
||||
#define EOVERFLOW 75
|
||||
#define EILSEQ 84
|
||||
#define ENOTSOCK 88
|
||||
#define EDESTADDRREQ 89
|
||||
#define EMSGSIZE 90
|
||||
#define EPROTOTYPE 91
|
||||
#define ENOPROTOOPT 92
|
||||
#define EPROTONOSUPPORT 93
|
||||
#define EOPNOTSUPP 95 /* == ENOTSUP, Linux numbering */
|
||||
#define EAFNOSUPPORT 97
|
||||
#define EADDRINUSE 98
|
||||
#define EADDRNOTAVAIL 99
|
||||
#define ENETDOWN 100
|
||||
#define ENETUNREACH 101
|
||||
#define ENETRESET 102
|
||||
#define ECONNABORTED 103
|
||||
#define ECONNRESET 104
|
||||
#define ENOBUFS 105
|
||||
#define EISCONN 106
|
||||
#define ENOTCONN 107
|
||||
#define ETIMEDOUT 110
|
||||
#define ECONNREFUSED 111
|
||||
#define EHOSTUNREACH 113
|
||||
#define EALREADY 114
|
||||
#define EINPROGRESS 115
|
||||
#define ESTALE 116
|
||||
#define EDQUOT 122
|
||||
#define ECANCELED 125
|
||||
#define EOWNERDEAD 130
|
||||
#define ENOTRECOVERABLE 131
|
||||
#define ENOTSUP 95
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -11,8 +11,47 @@ extern "C" {
|
||||
#define INFINITY __builtin_inff()
|
||||
#define NAN __builtin_nanf("")
|
||||
|
||||
/* C99 floating-point classification. */
|
||||
#define FP_NAN 0
|
||||
#define FP_INFINITE 1
|
||||
#define FP_ZERO 2
|
||||
#define FP_SUBNORMAL 3
|
||||
#define FP_NORMAL 4
|
||||
|
||||
#define fpclassify(x) \
|
||||
__builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, \
|
||||
FP_ZERO, x)
|
||||
#define isnan(x) __builtin_isnan(x)
|
||||
#define isinf(x) __builtin_isinf(x)
|
||||
#define isfinite(x) __builtin_isfinite(x)
|
||||
#define isnormal(x) __builtin_isnormal(x)
|
||||
#define signbit(x) __builtin_signbit(x)
|
||||
|
||||
double fabs(double x);
|
||||
double frexp(double x, int *exp);
|
||||
|
||||
/* C89 modf and the C99 float variants assumed by hosted libstdc++
|
||||
(--with-newlib crossconfig). The float forms wrap the double
|
||||
implementations. */
|
||||
double modf(double x, double *iptr);
|
||||
float modff(float x, float *iptr);
|
||||
double hypot(double x, double y);
|
||||
float hypotf(float x, float y);
|
||||
float acosf(float x);
|
||||
float asinf(float x);
|
||||
float atanf(float x);
|
||||
float atan2f(float y, float x);
|
||||
float coshf(float x);
|
||||
float expf(float x);
|
||||
float fmodf(float x, float y);
|
||||
float frexpf(float x, int *exp);
|
||||
float ldexpf(float x, int exp);
|
||||
float logf(float x);
|
||||
float log10f(float x);
|
||||
float powf(float x, float y);
|
||||
float sinhf(float x);
|
||||
float tanf(float x);
|
||||
float tanhf(float x);
|
||||
double ldexp(double x, int n);
|
||||
long double ldexpl(long double x, int n);
|
||||
double floor(double x);
|
||||
|
||||
@@ -39,6 +39,15 @@ extern FILE *stderr;
|
||||
int putc(int c, FILE *stream);
|
||||
void rewind(FILE *stream);
|
||||
int getchar(void);
|
||||
typedef long fpos_t;
|
||||
|
||||
int fgetpos(FILE *stream, fpos_t *pos);
|
||||
int fsetpos(FILE *stream, const fpos_t *pos);
|
||||
void setbuf(FILE *stream, char *buf);
|
||||
int fscanf(FILE *stream, const char *fmt, ...);
|
||||
int scanf(const char *fmt, ...);
|
||||
int vfscanf(FILE *stream, const char *fmt, va_list ap);
|
||||
|
||||
int fileno(FILE *stream);
|
||||
FILE *fdopen(int fd, const char *mode);
|
||||
|
||||
|
||||
@@ -63,6 +63,8 @@ char *mktemp(char *template_);
|
||||
char *realpath(const char *path, char *resolved);
|
||||
size_t mbstowcs(wchar_t *dst, const char *src, size_t n);
|
||||
int mblen(const char *s, size_t n);
|
||||
int mbtowc(wchar_t *pwc, const char *s, size_t n);
|
||||
int wctomb(char *s, wchar_t wc);
|
||||
double strtod(const char *nptr, char **endptr);
|
||||
float strtof(const char *nptr, char **endptr);
|
||||
long double strtold(const char *nptr, char **endptr);
|
||||
|
||||
@@ -31,6 +31,9 @@ char *strpbrk(const char *s, const char *accept);
|
||||
int strcasecmp(const char *s1, const char *s2);
|
||||
int strncasecmp(const char *s1, const char *s2, size_t n);
|
||||
int strcoll(const char *s1, const char *s2);
|
||||
size_t strxfrm(char *dest, const char *src, size_t n);
|
||||
char *strtok(char *str, const char *delim);
|
||||
char *strtok_r(char *str, const char *delim, char **saveptr);
|
||||
char *strstr(const char *haystack, const char *needle);
|
||||
const char *strerror(int errnum);
|
||||
|
||||
|
||||
@@ -11,6 +11,11 @@ extern "C" {
|
||||
|
||||
typedef unsigned int wint_t;
|
||||
|
||||
/* Opaque shift state for the (byte-oriented) C locale. */
|
||||
typedef struct {
|
||||
unsigned long __opaque;
|
||||
} mbstate_t;
|
||||
|
||||
#define WEOF ((wint_t)-1)
|
||||
|
||||
/* Byte-oriented C locale only: one byte, one character. */
|
||||
|
||||
@@ -36,6 +36,38 @@ static inline long _sys2(long nr, long a1, long a2) {
|
||||
|
||||
extern int main(int argc, char** argv);
|
||||
|
||||
/* Global constructor/destructor tables. The linker provides these
|
||||
boundary symbols whenever .preinit_array/.init_array/.fini_array
|
||||
sections exist; the weak references make them all optional so plain
|
||||
C programs keep working unchanged. Frame registration for C++
|
||||
exceptions (crtbegin's frame_dummy) also arrives via .init_array. */
|
||||
extern void (*__preinit_array_start[])(void) __attribute__((weak));
|
||||
extern void (*__preinit_array_end[])(void) __attribute__((weak));
|
||||
extern void (*__init_array_start[])(void) __attribute__((weak));
|
||||
extern void (*__init_array_end[])(void) __attribute__((weak));
|
||||
extern void (*__fini_array_start[])(void) __attribute__((weak));
|
||||
extern void (*__fini_array_end[])(void) __attribute__((weak));
|
||||
|
||||
extern int atexit(void (*fn)(void));
|
||||
extern void exit(int status);
|
||||
|
||||
static void _run_init_arrays(void) {
|
||||
for (void (**f)(void) = __preinit_array_start; f < __preinit_array_end; f++) {
|
||||
(*f)();
|
||||
}
|
||||
for (void (**f)(void) = __init_array_start; f < __init_array_end; f++) {
|
||||
(*f)();
|
||||
}
|
||||
}
|
||||
|
||||
/* Destructors run in reverse registration order, hooked through
|
||||
atexit so they also run when the program calls exit() directly. */
|
||||
static void _run_fini_array(void) {
|
||||
for (void (**f)(void) = __fini_array_end; f > __fini_array_start; f--) {
|
||||
(*(f - 1))();
|
||||
}
|
||||
}
|
||||
|
||||
void _start(void) {
|
||||
/* Static: 4 KiB args + 256 argv slots would crowd a 32 KiB stack. */
|
||||
static char argbuf[4096];
|
||||
@@ -77,6 +109,13 @@ void _start(void) {
|
||||
|
||||
argv[argc] = 0;
|
||||
|
||||
_sys1(SYS_EXIT, (long)main(argc, argv));
|
||||
if (__fini_array_start != __fini_array_end) {
|
||||
atexit(_run_fini_array);
|
||||
}
|
||||
_run_init_arrays();
|
||||
|
||||
/* exit() (not raw SYS_EXIT) so the atexit chain - including the
|
||||
fini-array walker registered above - runs on return from main. */
|
||||
exit(main(argc, argv));
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -3148,6 +3148,48 @@ unsigned int sleep(unsigned int seconds) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ========================================================================
|
||||
math.h: modf and C99 float variants (wrappers over the double
|
||||
implementations; assumed present by hosted libstdc++)
|
||||
======================================================================== */
|
||||
|
||||
double modf(double x, double *iptr) {
|
||||
double i = (x < 0.0) ? ceil(x) : floor(x);
|
||||
*iptr = i;
|
||||
return x - i;
|
||||
}
|
||||
|
||||
float modff(float x, float *iptr) {
|
||||
double di;
|
||||
double r = modf((double)x, &di);
|
||||
*iptr = (float)di;
|
||||
return (float)r;
|
||||
}
|
||||
|
||||
double hypot(double x, double y) {
|
||||
return sqrt(x * x + y * y);
|
||||
}
|
||||
|
||||
float hypotf(float x, float y) {
|
||||
return (float)hypot((double)x, (double)y);
|
||||
}
|
||||
|
||||
float acosf(float x) { return (float)acos((double)x); }
|
||||
float asinf(float x) { return (float)asin((double)x); }
|
||||
float atanf(float x) { return (float)atan((double)x); }
|
||||
float atan2f(float y, float x) { return (float)atan2((double)y, (double)x); }
|
||||
float coshf(float x) { return (float)cosh((double)x); }
|
||||
float expf(float x) { return (float)exp((double)x); }
|
||||
float fmodf(float x, float y) { return (float)fmod((double)x, (double)y); }
|
||||
float frexpf(float x, int *e) { return (float)frexp((double)x, e); }
|
||||
float ldexpf(float x, int e) { return (float)ldexp((double)x, e); }
|
||||
float logf(float x) { return (float)log((double)x); }
|
||||
float log10f(float x) { return (float)log10((double)x); }
|
||||
float powf(float x, float y) { return (float)pow((double)x, (double)y); }
|
||||
float sinhf(float x) { return (float)sinh((double)x); }
|
||||
float tanf(float x) { return (float)tan((double)x); }
|
||||
float tanhf(float x) { return (float)tanh((double)x); }
|
||||
|
||||
/* ========================================================================
|
||||
POSIX additions for hosted programs (native binutils/gcc ports)
|
||||
======================================================================== */
|
||||
@@ -3232,6 +3274,61 @@ size_t mbstowcs(wchar_t *dst, const char *src, size_t n) {
|
||||
return i;
|
||||
}
|
||||
|
||||
/* Byte-oriented C locale: one byte, one character. */
|
||||
int mbtowc(wchar_t *pwc, const char *s, size_t n) {
|
||||
if (s == NULL) return 0; /* no shift states */
|
||||
if (n == 0) return -1;
|
||||
if (*s == '\0') {
|
||||
if (pwc != NULL) *pwc = 0;
|
||||
return 0;
|
||||
}
|
||||
if (pwc != NULL) *pwc = (wchar_t)(unsigned char)*s;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int wctomb(char *s, wchar_t wc) {
|
||||
if (s == NULL) return 0;
|
||||
*s = (char)wc;
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *strtok_r(char *str, const char *delim, char **saveptr) {
|
||||
char *s = (str != NULL) ? str : *saveptr;
|
||||
if (s == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
s += strspn(s, delim);
|
||||
if (*s == '\0') {
|
||||
*saveptr = NULL;
|
||||
return NULL;
|
||||
}
|
||||
char *tok = s;
|
||||
s += strcspn(s, delim);
|
||||
if (*s != '\0') {
|
||||
*s++ = '\0';
|
||||
*saveptr = s;
|
||||
} else {
|
||||
*saveptr = NULL;
|
||||
}
|
||||
return tok;
|
||||
}
|
||||
|
||||
char *strtok(char *str, const char *delim) {
|
||||
static char *_strtok_save;
|
||||
return strtok_r(str, delim, &_strtok_save);
|
||||
}
|
||||
|
||||
/* No collation beyond byte order in the C locale: transform = copy. */
|
||||
size_t strxfrm(char *dest, const char *src, size_t n) {
|
||||
size_t len = strlen(src);
|
||||
if (n > 0) {
|
||||
size_t c = (len < n - 1) ? len : n - 1;
|
||||
memcpy(dest, src, c);
|
||||
dest[c] = '\0';
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int mblen(const char *s, size_t n) {
|
||||
if (s == NULL) return 0;
|
||||
if (n == 0) return -1;
|
||||
@@ -3316,6 +3413,180 @@ char *realpath(const char *path, char *resolved) {
|
||||
return resolved;
|
||||
}
|
||||
|
||||
int fgetpos(FILE *stream, fpos_t *pos) {
|
||||
if (stream == NULL || pos == NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
long p = ftell(stream);
|
||||
if (p < 0) return -1;
|
||||
*pos = (fpos_t)p;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fsetpos(FILE *stream, const fpos_t *pos) {
|
||||
if (stream == NULL || pos == NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
return fseek(stream, (long)*pos, SEEK_SET);
|
||||
}
|
||||
|
||||
/* Streams are unbuffered in this libc; buffering hints are no-ops. */
|
||||
void setbuf(FILE *stream, char *buf) {
|
||||
(void)stream; (void)buf;
|
||||
}
|
||||
|
||||
/* Character-driven scanf core over FILE (fgetc/ungetc). Supports the
|
||||
same conversions as sscanf: %d %i %u %x %s %c %% with field widths
|
||||
and the l/ll length modifiers. */
|
||||
int vfscanf(FILE *stream, const char *fmt, va_list ap) {
|
||||
int matched = 0;
|
||||
int c;
|
||||
|
||||
while (*fmt) {
|
||||
if (isspace((unsigned char)*fmt)) {
|
||||
/* Whitespace in the format skips any input whitespace. */
|
||||
do {
|
||||
c = fgetc(stream);
|
||||
} while (c != EOF && isspace(c));
|
||||
if (c != EOF) ungetc(c, stream);
|
||||
fmt++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*fmt != '%') {
|
||||
c = fgetc(stream);
|
||||
if (c == EOF) goto done;
|
||||
if ((char)c != *fmt) {
|
||||
ungetc(c, stream);
|
||||
goto done;
|
||||
}
|
||||
fmt++;
|
||||
continue;
|
||||
}
|
||||
|
||||
fmt++;
|
||||
if (*fmt == '%') {
|
||||
c = fgetc(stream);
|
||||
if (c != '%') {
|
||||
if (c != EOF) ungetc(c, stream);
|
||||
goto done;
|
||||
}
|
||||
fmt++;
|
||||
continue;
|
||||
}
|
||||
|
||||
int width = 0;
|
||||
while (isdigit((unsigned char)*fmt)) {
|
||||
width = width * 10 + (*fmt++ - '0');
|
||||
}
|
||||
int is_long = 0;
|
||||
if (*fmt == 'l') { is_long = 1; fmt++; }
|
||||
if (*fmt == 'l') { fmt++; } /* ll behaves as l on LP64 */
|
||||
|
||||
if (*fmt == 'd' || *fmt == 'i' || *fmt == 'u' || *fmt == 'x' ||
|
||||
*fmt == 'X') {
|
||||
int base = (*fmt == 'x' || *fmt == 'X') ? 16 : 10;
|
||||
do {
|
||||
c = fgetc(stream);
|
||||
} while (c != EOF && isspace(c));
|
||||
if (c == EOF) goto done;
|
||||
|
||||
int neg = 0;
|
||||
int n = 0;
|
||||
if ((*fmt == 'd' || *fmt == 'i') && (c == '-' || c == '+')) {
|
||||
neg = (c == '-');
|
||||
c = fgetc(stream);
|
||||
}
|
||||
if (base == 16 && c == '0') {
|
||||
int c2 = fgetc(stream);
|
||||
if (c2 == 'x' || c2 == 'X') {
|
||||
c = fgetc(stream);
|
||||
} else if (c2 != EOF) {
|
||||
ungetc(c2, stream);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long val = 0;
|
||||
int any = 0;
|
||||
for (;;) {
|
||||
int digit = -1;
|
||||
if (c >= '0' && c <= '9') digit = c - '0';
|
||||
else if (base == 16 && c >= 'a' && c <= 'f') digit = c - 'a' + 10;
|
||||
else if (base == 16 && c >= 'A' && c <= 'F') digit = c - 'A' + 10;
|
||||
if (digit < 0 || (width > 0 && n >= width)) break;
|
||||
val = val * (unsigned long)base + (unsigned long)digit;
|
||||
any = 1;
|
||||
n++;
|
||||
c = fgetc(stream);
|
||||
if (c == EOF) break;
|
||||
}
|
||||
if (c != EOF) ungetc(c, stream);
|
||||
if (!any) goto done;
|
||||
|
||||
if (*fmt == 'd' || *fmt == 'i') {
|
||||
long sv = neg ? -(long)val : (long)val;
|
||||
if (is_long) *va_arg(ap, long *) = sv;
|
||||
else *va_arg(ap, int *) = (int)sv;
|
||||
} else {
|
||||
if (is_long) *va_arg(ap, unsigned long *) = val;
|
||||
else *va_arg(ap, unsigned int *) = (unsigned int)val;
|
||||
}
|
||||
matched++;
|
||||
} else if (*fmt == 's') {
|
||||
do {
|
||||
c = fgetc(stream);
|
||||
} while (c != EOF && isspace(c));
|
||||
if (c == EOF) goto done;
|
||||
char *dst = va_arg(ap, char *);
|
||||
int n = 0;
|
||||
while (c != EOF && !isspace(c) && (width == 0 || n < width)) {
|
||||
*dst++ = (char)c;
|
||||
n++;
|
||||
c = fgetc(stream);
|
||||
}
|
||||
*dst = '\0';
|
||||
if (c != EOF) ungetc(c, stream);
|
||||
if (n == 0) goto done;
|
||||
matched++;
|
||||
} else if (*fmt == 'c') {
|
||||
int n = (width > 0) ? width : 1;
|
||||
char *dst = va_arg(ap, char *);
|
||||
int got = 0;
|
||||
while (got < n) {
|
||||
c = fgetc(stream);
|
||||
if (c == EOF) break;
|
||||
dst[got++] = (char)c;
|
||||
}
|
||||
if (got < n) goto done;
|
||||
matched++;
|
||||
} else {
|
||||
goto done; /* unsupported conversion */
|
||||
}
|
||||
fmt++;
|
||||
}
|
||||
|
||||
done:
|
||||
return (matched == 0) ? EOF : matched;
|
||||
}
|
||||
|
||||
int fscanf(FILE *stream, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
int r = vfscanf(stream, fmt, ap);
|
||||
va_end(ap);
|
||||
return r;
|
||||
}
|
||||
|
||||
int scanf(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
int r = vfscanf(stdin, fmt, ap);
|
||||
va_end(ap);
|
||||
return r;
|
||||
}
|
||||
|
||||
int putc(int c, FILE *stream) {
|
||||
return fputc(c, stream);
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -128,10 +128,15 @@ cp "${REPO_DIR}/programs/lib/libc/crt1.o" \
|
||||
"${REPO_DIR}/programs/lib/libc/crti.o" \
|
||||
"${REPO_DIR}/programs/lib/libc/crtn.o" "${SYSROOT}/usr/lib/"
|
||||
cp "${REPO_DIR}/programs/lib/libc/liblibc.a" "${SYSROOT}/usr/lib/libc.a"
|
||||
# Empty stand-ins: math functions live inside libc.a, and there is no
|
||||
# libstdc++ yet, but the g++ driver links -lstdc++ -lm unconditionally.
|
||||
# libm is an empty stand-in (math lives inside libc.a; the g++ driver
|
||||
# links -lm unconditionally). libstdc++ is copied from the toolchain
|
||||
# once built - the empty stand-in only bridges the first bootstrap.
|
||||
ar rcs "${SYSROOT}/usr/lib/libm.a"
|
||||
ar rcs "${SYSROOT}/usr/lib/libstdc++.a"
|
||||
if [[ -f "${PREFIX}/x86_64-montauk/lib/libstdc++.a" ]]; then
|
||||
cp "${PREFIX}/x86_64-montauk/lib/libstdc++.a" "${SYSROOT}/usr/lib/libstdc++.a"
|
||||
else
|
||||
ar rcs "${SYSROOT}/usr/lib/libstdc++.a"
|
||||
fi
|
||||
green "Sysroot ready."
|
||||
|
||||
# ── Build Binutils ────────────────────────────────────────────────────────────
|
||||
@@ -177,13 +182,19 @@ else
|
||||
--disable-multilib \
|
||||
--disable-gcov \
|
||||
--with-gnu-as \
|
||||
--with-gnu-ld
|
||||
--with-gnu-ld \
|
||||
--with-newlib \
|
||||
--enable-initfini-array \
|
||||
--disable-wchar_t \
|
||||
--disable-libstdcxx-pch
|
||||
make -j"${JOBS}" all-gcc
|
||||
make -j"${JOBS}" all-target-libgcc
|
||||
make install-gcc
|
||||
make install-target-libgcc
|
||||
make -j"${JOBS}" all-target-libstdc++-v3
|
||||
make install-target-libstdc++-v3
|
||||
)
|
||||
green "GCC installed."
|
||||
green "GCC and libstdc++ installed."
|
||||
fi
|
||||
|
||||
# ── Done ──────────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
|
||||
static int ctor_ran = 0;
|
||||
struct Global { Global() { ctor_ran = 42; } };
|
||||
static Global g;
|
||||
|
||||
int main() {
|
||||
int score = 0;
|
||||
if (ctor_ran == 42) { puts("global ctor: OK"); score++; }
|
||||
|
||||
std::string s = "montauk";
|
||||
s += "-cxx";
|
||||
if (s == "montauk-cxx" && s.size() == 11) { puts("std::string: OK"); score++; }
|
||||
|
||||
std::vector<int> v{5, 3, 1, 4, 2};
|
||||
std::sort(v.begin(), v.end());
|
||||
if (v.front() == 1 && v.back() == 5) { puts("std::vector+sort: OK"); score++; }
|
||||
|
||||
auto p = std::make_unique<std::string>("heap");
|
||||
if (*p == "heap") { puts("unique_ptr/new: OK"); score++; }
|
||||
|
||||
try {
|
||||
throw std::runtime_error("caught!");
|
||||
} catch (const std::exception& e) {
|
||||
if (std::string(e.what()) == "caught!") { puts("exceptions: OK"); score++; }
|
||||
}
|
||||
|
||||
printf("%d/5 passed\n", score);
|
||||
return (score == 5) ? 0 : 1;
|
||||
}
|
||||
@@ -47,3 +47,15 @@
|
||||
*-musl* )
|
||||
# IF there is no include fixing,
|
||||
# THEN create a no-op fixer and exit
|
||||
--- a/libstdc++-v3/configure
|
||||
+++ b/libstdc++-v3/configure
|
||||
@@ -27340,6 +27340,9 @@
|
||||
# on a hosted environment.
|
||||
if test "x${with_newlib}" = "xyes"; then
|
||||
os_include_dir="os/newlib"
|
||||
+ case "${host}" in
|
||||
+ *-montauk*) os_include_dir="os/generic" ;; # Montauk libc is not newlib
|
||||
+ esac
|
||||
$as_echo "#define HAVE_HYPOT 1" >>confdefs.h
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user