Skip to content

Commit 9684e31

Browse files
committed
Setup C++ compilation with support for a subset of the C++ STL
1 parent a7f3d8c commit 9684e31

35 files changed

Lines changed: 1576 additions & 25 deletions

.vscode/c_cpp_properties.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"name": "Mod",
55
"includePath": [
66
"${workspaceFolder}/include",
7+
"${workspaceFolder}/include/libc",
78
"${workspaceFolder}/include/dummy_headers",
89
"${workspaceFolder}/mm-decomp/include",
910
"${workspaceFolder}/mm-decomp/src",
@@ -12,7 +13,8 @@
1213
"defines": [
1314
"F3DEX_GBI_2",
1415
"_LANGUAGE_C",
15-
"MIPS"
16+
"MIPS",
17+
"_HAS_EXCEPTIONS=0"
1618
],
1719
"compilerPath": "clang",
1820
"cStandard": "c99",

Makefile

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@ BUILD_DIR := build
44
# as Apple Clang does not support MIPS architecture
55
ifeq ($(OS),Windows_NT)
66
CC := clang
7+
CXX := clang++
78
LD := ld.lld
89
else ifneq ($(shell uname),Darwin)
910
CC := clang
11+
CXX := clang++
1012
LD := ld.lld
1113
else
1214
CC ?= clang
15+
CXX ?= clang++
1316
LD ?= ld.lld
1417
endif
1518

@@ -21,19 +24,32 @@ ARCHFLAGS := -target mips -mips2 -mabi=32 -O2 -G0 -mno-abicalls -mno-odd-spreg -
2124
WARNFLAGS := -Wall -Wextra -Wno-incompatible-library-redeclaration -Wno-unused-parameter -Wno-unknown-pragmas -Wno-unused-variable \
2225
-Wno-missing-braces -Wno-unsupported-floating-point-opt -Werror=section
2326
CFLAGS := $(ARCHFLAGS) $(WARNFLAGS) -D_LANGUAGE_C -nostdinc -ffunction-sections
27+
CXXFLAGS := $(ARCHFLAGS) $(WARNFLAGS) -D_LANGUAGE_C_PLUS_PLUS -stdlib=libc++ -fno-rtti -fno-exceptions -std=c++20 -ffunction-sections -DLIBC_ASSERT_H
2428
CPPFLAGS := -DMIPS -DF3DEX_GBI_2 -DF3DEX_GBI_PL -DGBI_DOWHILE -I include -I include/dummy_headers \
2529
-I mm-decomp/include -I mm-decomp/src -I mm-decomp/extracted/n64-us -idirafter include/libc -idirafter mm-decomp/include/libc
2630
LDFLAGS := -nostdlib -T $(LDSCRIPT) -Map $(BUILD_DIR)/mod.map --unresolved-symbols=ignore-all --emit-relocs -e 0 --no-nmagic -gc-sections
2731

32+
ifeq ($(OS),Windows_NT)
33+
else ifneq ($(shell uname),Darwin)
34+
# Intercept specific includes on Linux to prevent them from including the glibc counterparts.
35+
# This is done this way because -nostdinc would prevent a system install of libc++ from being included as well.
36+
CXXFLAGS += -I include/libc/stdlib_override
37+
else
38+
endif
39+
2840
rwildcard = $(foreach d,$(wildcard $(1:=/*)),$(call rwildcard,$d,$2) $(filter $(subst *,%,$2),$d))
2941
getdirs = $(sort $(dir $(1)))
3042

3143
C_SRCS := $(call rwildcard,src,*.c)
3244
C_OBJS := $(addprefix $(BUILD_DIR)/, $(C_SRCS:.c=.o))
3345
C_DEPS := $(addprefix $(BUILD_DIR)/, $(C_SRCS:.c=.d))
3446

35-
ALL_OBJS := $(C_OBJS)
36-
ALL_DEPS := $(C_DEPS)
47+
CXX_SRCS := $(call rwildcard,src,*.cpp)
48+
CXX_OBJS := $(addprefix $(BUILD_DIR)/, $(CXX_SRCS:.cpp=.o))
49+
CXX_DEPS := $(addprefix $(BUILD_DIR)/, $(CXX_SRCS:.cpp=.d))
50+
51+
ALL_OBJS := $(C_OBJS) $(CXX_OBJS)
52+
ALL_DEPS := $(C_DEPS) $(CXX_DEPS)
3753
BUILD_DIRS := $(call getdirs,$(ALL_OBJS))
3854

3955
all: $(TARGET)
@@ -51,6 +67,9 @@ endif
5167
$(C_OBJS): $(BUILD_DIR)/%.o : %.c | $(BUILD_DIRS)
5268
$(CC) $(CFLAGS) $(CPPFLAGS) $< -MMD -MF $(@:.o=.d) -c -o $@
5369

70+
$(CXX_OBJS): $(BUILD_DIR)/%.o : %.cpp | $(BUILD_DIRS)
71+
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $< -MMD -MF $(@:.o=.d) -c -o $@
72+
5473
clean:
5574
ifeq ($(OS),Windows_NT)
5675
if exist $(BUILD_DIR) rmdir /S /Q $(BUILD_DIR)

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ See [this document](https://hackmd.io/fMDiGEJ9TBSjomuZZOgzNg) for an explanation
1111
You'll need to install `clang` and `make` to build this template.
1212
* On Windows, using [chocolatey](https://chocolatey.org/) to install both is recommended. The packages are `llvm` and `make` respectively.
1313
* The LLVM 19.1.0 [llvm-project](https://github.com/llvm/llvm-project) release binary, which is also what chocolatey provides, does not support MIPS correctly. The solution is to install 18.1.8 instead, which can be done in chocolatey by specifying `--version 18.1.8` or by downloading the 18.1.8 release directly.
14-
* On Linux, these can both be installed using your distro's package manager. You may also need to install your distro's package for the `lld` linker. On Debian/Ubuntu based distros this will be the `lld` package.
14+
* On Linux, these can both be installed using your distro's package manager. You may also need to install your distro's package for the `lld` linker. On Debian/Ubuntu based distros this will be the `lld` package. If you want to use the supported subset of the C++ STL, you'll also need to install libc++. On Debian/Ubuntu based distros this will be the `libc++-dev` package.
1515
* On MacOS, these can both be installed using Homebrew. Apple clang won't work, as you need a mips target for building the mod code.
1616

1717
On Linux and MacOS, you'll need to also ensure that you have the `zip` utility installed.

include/__config_site

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef _LIBCPP___CONFIG_SITE
10+
#define _LIBCPP___CONFIG_SITE
11+
12+
#define _LIBCPP_ABI_VERSION 1
13+
#define _LIBCPP_ABI_NAMESPACE __1
14+
/* #undef _LIBCPP_ABI_FORCE_ITANIUM */
15+
/* #undef _LIBCPP_ABI_FORCE_MICROSOFT */
16+
#define _LIBCPP_HAS_NO_THREADS
17+
#define _LIBCPP_HAS_NO_MONOTONIC_CLOCK
18+
/* #undef _LIBCPP_HAS_MUSL_LIBC */
19+
/* #undef _LIBCPP_HAS_THREAD_API_PTHREAD */
20+
/* #undef _LIBCPP_HAS_THREAD_API_EXTERNAL */
21+
/* #undef _LIBCPP_HAS_THREAD_API_WIN32 */
22+
/* #undef _LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS */
23+
#define _LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS
24+
#define _LIBCPP_NO_VCRUNTIME
25+
/* #undef _LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION */
26+
#define _LIBCPP_HAS_NO_FILESYSTEM
27+
#define _LIBCPP_HAS_NO_RANDOM_DEVICE
28+
#define _LIBCPP_HAS_NO_LOCALIZATION
29+
#define _LIBCPP_HAS_NO_UNICODE
30+
/* #undef _LIBCPP_HAS_NO_WIDE_CHARACTERS */
31+
#define _LIBCPP_HAS_NO_STD_MODULES
32+
#define _LIBCPP_HAS_NO_TIME_ZONE_DATABASE
33+
/* #undef _LIBCPP_INSTRUMENTED_WITH_ASAN */
34+
35+
// PSTL backends
36+
#define _LIBCPP_PSTL_BACKEND_SERIAL
37+
/* #undef _LIBCPP_PSTL_BACKEND_STD_THREAD */
38+
/* #undef _LIBCPP_PSTL_BACKEND_LIBDISPATCH */
39+
40+
#define _LIBCPP_PSTL_CPU_BACKEND_SERIAL
41+
42+
// Hardening.
43+
#define _LIBCPP_HARDENING_MODE_DEFAULT 2
44+
45+
// __USE_MINGW_ANSI_STDIO gets redefined on MinGW
46+
#ifdef __clang__
47+
# pragma clang diagnostic push
48+
# pragma clang diagnostic ignored "-Wmacro-redefined"
49+
#endif
50+
51+
52+
53+
#ifdef __clang__
54+
# pragma clang diagnostic pop
55+
#endif
56+
57+
#endif // _LIBCPP___CONFIG_SITE

include/libc/errno.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#ifndef LIBC_ERRNO_H
2+
#define LIBC_ERRNO_H
3+
4+
extern int __errno;
5+
#define errno __errno
6+
7+
#endif

include/libc/limits.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#ifndef LIBC_LIMITS_H
2+
#define LIBC_LIMITS_H
3+
4+
#define CHAR_BIT 8
5+
#define CHAR_WIDTH CHAR_BIT
6+
7+
#define FLT_MAX 3.40282347e+38f
8+
#define SHRT_MAX 32767.0f
9+
10+
#define SCHAR_WIDTH (CHAR_BIT)
11+
#define SHORT_WIDTH (CHAR_BIT * sizeof(short))
12+
#define INT_WIDTH (CHAR_BIT * sizeof(int))
13+
#define LONG_WIDTH (CHAR_BIT * sizeof(long))
14+
#define LLONG_WIDTH (CHAR_BIT * sizeof(long long))
15+
16+
#define SCHAR_MIN (-(1LL << (SCHAR_WIDTH - 1)))
17+
#define SHORT_MIN (-(1LL << (SHORT_WIDTH - 1)))
18+
#define INT_MIN (-(1LL << (INT_WIDTH - 1)))
19+
#define LONG_MIN (-(1LL << (LONG_WIDTH - 1)))
20+
#define LLONG_MIN (2 * -(1LL << (LLONG_WIDTH - 2)))
21+
22+
#define SCHAR_MAX (-(SCHAR_MIN + 1))
23+
#define SHORT_MAX (-(SHORT_MIN + 1))
24+
#define INT_MAX (-(INT_MIN + 1))
25+
#define LONG_MAX (-(LONG_MIN + 1))
26+
#define LLONG_MAX (-(LLONG_MIN + 1))
27+
28+
#define UCHAR_WIDTH (CHAR_BIT)
29+
#define USHRT_WIDTH (CHAR_BIT * sizeof(unsigned short))
30+
#define UINT_WIDTH (CHAR_BIT * sizeof(unsigned int))
31+
#define ULONG_WIDTH (CHAR_BIT * sizeof(unsigned long))
32+
#define ULLONG_WIDTH (CHAR_BIT * sizeof(unsigned long long))
33+
34+
#define UCHAR_MAX ((unsigned char)-1)
35+
#define USHRT_MAX ((unsigned short)-1)
36+
#define UINT_MAX ((unsigned int)-1)
37+
#define ULONG_MAX ((unsigned long)-1)
38+
#define ULLONG_MAX ((unsigned long long)-1)
39+
40+
#endif

include/libc/math.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#ifndef LIBC_MATH_H
2+
#define LIBC_MATH_H
3+
4+
// Types
5+
6+
typedef float float_t;
7+
typedef double double_t;
8+
9+
// Constants
10+
11+
#define HUGE_VALF (__builtin_huge_valf())
12+
#define HUGE_VAL (__builtin_huge_val())
13+
#define HUGE_VALL (__builtin_huge_vall())
14+
#define INFINITY (__builtin_inff())
15+
#define NAN (__builtin_nanf(""))
16+
17+
#define FP_NAN 0
18+
#define FP_INFINITE 1
19+
#define FP_ZERO 2
20+
#define FP_SUBNORMAL 3
21+
#define FP_NORMAL 4
22+
23+
#define M_PI 3.14159265358979323846
24+
#define M_PIf 3.14159265358979323846f
25+
26+
// Functions
27+
28+
#define fpclassify(x) __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, x)
29+
#define fabsf(f) __builtin_fabsf((float)(f))
30+
31+
#endif

include/libc/stddef.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#ifndef LIBC_STDDEF_H
2+
#define LIBC_STDDEF_H
3+
4+
typedef signed int ptrdiff_t;
5+
6+
// typedef double max_align_t;
7+
8+
#if !defined(_SIZE_T)
9+
#define _SIZE_T
10+
#if defined(_MIPS_SZLONG) && (_MIPS_SZLONG == 64)
11+
typedef unsigned long size_t;
12+
#else
13+
typedef unsigned int size_t;
14+
#endif
15+
#endif
16+
17+
#ifndef NULL
18+
#define NULL ((void*)0)
19+
#endif
20+
21+
#define offsetof(structure, member) __builtin_offsetof (structure, member)
22+
23+
#endif /* STDDEF_H */

include/libc/stdint.h

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#ifndef LIBC_STDINT_H
2+
#define LIBC_STDINT_H
3+
4+
typedef signed long long intmax_t;
5+
typedef unsigned long long uintmax_t;
6+
7+
typedef unsigned char uint8_t;
8+
typedef signed char int8_t;
9+
10+
typedef unsigned short uint16_t;
11+
typedef signed short int16_t;
12+
13+
typedef unsigned int uint32_t;
14+
typedef signed int int32_t;
15+
16+
typedef unsigned long long uint64_t;
17+
typedef signed long long int64_t;
18+
19+
typedef signed long intptr_t;
20+
typedef unsigned long uintptr_t;
21+
22+
typedef uint8_t uint_least8_t;
23+
typedef uint16_t uint_least16_t;
24+
typedef uint32_t uint_least32_t;
25+
typedef uint64_t uint_least64_t;
26+
typedef int8_t int_least8_t;
27+
typedef int16_t int_least16_t;
28+
typedef int32_t int_least32_t;
29+
typedef int64_t int_least64_t;
30+
31+
typedef uint8_t uint_fast8_t;
32+
typedef uint16_t uint_fast16_t;
33+
typedef uint32_t uint_fast32_t;
34+
typedef uint64_t uint_fast64_t;
35+
typedef int8_t int_fast8_t;
36+
typedef int16_t int_fast16_t;
37+
typedef int32_t int_fast32_t;
38+
typedef int64_t int_fast64_t;
39+
40+
#define INT8_MIN (-0x80)
41+
#define INT16_MIN (-0x8000)
42+
#define INT32_MIN (-0x80000000)
43+
#define INT64_MIN (-0x8000000000000000)
44+
45+
#define INT8_MAX 0x7F
46+
#define INT16_MAX 0x7FFF
47+
#define INT32_MAX 0x7FFFFFFF
48+
#define INT64_MAX 0x7FFFFFFFFFFFFFFF
49+
50+
#define SIZE_MAX ((1ULL << (sizeof(void*) * 8)) - 1)
51+
52+
#define UINT8_MAX 0xFF
53+
#define UINT16_MAX 0xFFFF
54+
#define UINT32_MAX 0xFFFFFFFF
55+
#define UINT64_MAX 0xFFFFFFFFFFFFFFFF
56+
57+
#define INTPTR_MIN (-0x80000000)
58+
#define INTPTR_MAX 0x7FFFFFFF
59+
#define UINTPTR_MAX 0xFFFFFFFF
60+
61+
#define INT8_C(x) ((int_least8_t)(x))
62+
#define INT16_C(x) ((int_least16_t)(x))
63+
#define INT32_C(x) ((int_least32_t)(x))
64+
#define INT64_C(x) ((int_least64_t)(x))
65+
66+
#define INTMAX_C(x) ((intmax_t)(x))
67+
68+
#define UINT8_C(x) ((uint_least8_t)(x))
69+
#define UINT16_C(x) ((uint_least16_t)(x))
70+
#define UINT32_C(x) ((uint_least32_t)(x))
71+
#define UINT64_C(x) ((uint_least64_t)(x))
72+
73+
#define UINTMAX_C(x) ((uintmax_t)(x))
74+
75+
76+
#endif /* STDINT_H */

include/libc/stdio.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#ifndef LIBC_STDIO_H
2+
#define LIBC_STDIO_H
3+
4+
#include "stddef.h"
5+
6+
typedef struct _iobuf {
7+
int dummy;
8+
} FILE;
9+
10+
#define EOF (-1)
11+
#define WEOF (-1)
12+
13+
int remove(const char *filename);
14+
size_t fwrite( const void* __restrict__ buffer, size_t size, size_t count, FILE* __restrict__ stream );
15+
16+
int fflush(FILE* stream);
17+
int fputc(int c, FILE* stream);
18+
int fputs(const char* __restrict__ s, FILE* __restrict__ stream);
19+
int fprintf(FILE* __restrict__ stream, const char* __restrict__ format, ...);
20+
21+
extern FILE __stdout;
22+
extern FILE __stderr;
23+
24+
#define stdout &__stdout
25+
#define stderr &__stderr
26+
27+
#endif

0 commit comments

Comments
 (0)