mirror of https://github.com/zeldaret/tp.git
Add clangd support for VS Code (#2207)
* Add clangd support for VS Code * Revert accidental change
This commit is contained in:
parent
7ec2d80414
commit
0db466edfa
|
@ -1,13 +1,35 @@
|
|||
# IDE folders
|
||||
.idea/
|
||||
.vs/
|
||||
|
||||
# Caches
|
||||
__pycache__
|
||||
.idea
|
||||
.vscode
|
||||
.ninja_*
|
||||
.mypy_cache
|
||||
*.exe
|
||||
build
|
||||
build.ninja
|
||||
objdiff.json
|
||||
.cache/
|
||||
|
||||
# Original files
|
||||
orig/*/*
|
||||
!orig/*/.gitkeep
|
||||
*.dol
|
||||
*.rel
|
||||
*.elf
|
||||
*.o
|
||||
*.map
|
||||
*.MAP
|
||||
|
||||
# Build files
|
||||
build/
|
||||
.ninja_*
|
||||
build.ninja
|
||||
|
||||
# decompctx output
|
||||
ctx.*
|
||||
*.ctx
|
||||
|
||||
# Generated configs
|
||||
objdiff.json
|
||||
compile_commands.json
|
||||
|
||||
# Miscellaneous
|
||||
/*.txt
|
||||
ctx.c
|
||||
*.exe
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"recommendations": [
|
||||
"llvm-vs-code-extensions.vscode-clangd",
|
||||
"ms-python.black-formatter",
|
||||
"ms-python.flake8",
|
||||
],
|
||||
"unwantedRecommendations": [
|
||||
"ms-vscode.cmake-tools",
|
||||
"ms-vscode.cpptools-extension-pack",
|
||||
"ms-vscode.cpptools",
|
||||
]
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"[c]": {
|
||||
"files.encoding": "utf8",
|
||||
"editor.defaultFormatter": "llvm-vs-code-extensions.vscode-clangd"
|
||||
},
|
||||
"[cpp]": {
|
||||
"files.encoding": "utf8",
|
||||
"editor.defaultFormatter": "llvm-vs-code-extensions.vscode-clangd"
|
||||
},
|
||||
"[python]": {
|
||||
"editor.defaultFormatter": "ms-python.black-formatter"
|
||||
},
|
||||
"editor.tabSize": 4,
|
||||
"files.autoSave": "onFocusChange",
|
||||
"files.insertFinalNewline": true,
|
||||
"files.trimFinalNewlines": true,
|
||||
"files.associations": {
|
||||
"*.inc": "c",
|
||||
".clangd": "yaml"
|
||||
},
|
||||
// Disable C/C++ IntelliSense, use clangd instead
|
||||
"C_Cpp.intelliSenseEngine": "disabled",
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
// Use Ctrl+Shift+B to run build tasks.
|
||||
// Or "Run Build Task" in the Command Palette.
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "ninja",
|
||||
"type": "shell",
|
||||
"command": "ninja",
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
|
@ -249,9 +249,9 @@ struct TLinkList_factory : public TLinkList<T, I> {
|
|||
virtual T* Do_create() = 0;
|
||||
virtual void Do_destroy(T*) = 0;
|
||||
void Clear_destroy() {
|
||||
while (!empty()) {
|
||||
T* item = &front();
|
||||
pop_front();
|
||||
while (!this->empty()) {
|
||||
T* item = &this->front();
|
||||
this->pop_front();
|
||||
Do_destroy(item);
|
||||
}
|
||||
}
|
||||
|
@ -298,16 +298,16 @@ struct TEnumerator2 {
|
|||
};
|
||||
|
||||
template <typename T, int I>
|
||||
struct TContainerEnumerator : public TEnumerator2<TLinkList<T, I>::iterator, T> {
|
||||
struct TContainerEnumerator : public TEnumerator2<typename TLinkList<T, I>::iterator, T> {
|
||||
inline TContainerEnumerator(TLinkList<T, I>* param_0)
|
||||
: TEnumerator2<TLinkList<T, I>::iterator, T>(param_0->begin(), param_0->end()) {}
|
||||
: TEnumerator2<typename TLinkList<T, I>::iterator, T>(param_0->begin(), param_0->end()) {}
|
||||
};
|
||||
|
||||
|
||||
template <typename T, int I>
|
||||
struct TContainerEnumerator_const : public TEnumerator2<TLinkList<T, I>::const_iterator, const T> {
|
||||
struct TContainerEnumerator_const : public TEnumerator2<typename TLinkList<T, I>::const_iterator, const T> {
|
||||
inline TContainerEnumerator_const(const TLinkList<T, I>* param_0)
|
||||
: TEnumerator2<TLinkList<T, I>::const_iterator, const T>(param_0->begin(), param_0->end()) {}
|
||||
: TEnumerator2<typename TLinkList<T, I>::const_iterator, const T>(param_0->begin(), param_0->end()) {}
|
||||
};
|
||||
|
||||
}; // namespace JGadget
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#define DOL2ASM
|
||||
|
||||
// this helps remove useless error from the linter when using vscode.
|
||||
#ifndef IN_VSCODE_EDITOR
|
||||
#ifdef __MWERKS__
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define SECTION_INIT extern "C" __declspec(section ".init")
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
volatile u16 __DSPRegs[32] : 0xCC005000;
|
||||
volatile u32 __AIRegs[8] : 0xCC006C00;
|
||||
volatile u16 __DSPRegs[32] AT_ADDRESS(0xCC005000);
|
||||
volatile u32 __AIRegs[8] AT_ADDRESS(0xCC006C00);
|
||||
|
||||
#define DSP_TASK_FLAG_CLEARALL 0x00000000
|
||||
#define DSP_TASK_FLAG_ATTACHED 0x00000001
|
||||
|
|
|
@ -4,6 +4,6 @@
|
|||
#include "dolphin/types.h"
|
||||
|
||||
typedef void (*DVDLowCallback)(u32 intType);
|
||||
vu32 __DIRegs[16] : 0xCC006000;
|
||||
vu32 __DIRegs[16] AT_ADDRESS(0xCC006000);
|
||||
|
||||
#endif /* DVDLOW_H */
|
||||
|
|
|
@ -9,7 +9,7 @@ extern "C" {
|
|||
|
||||
typedef struct OSContext OSContext;
|
||||
|
||||
vu32 __EXIRegs[16] : 0xCC006800;
|
||||
vu32 __EXIRegs[16] AT_ADDRESS(0xCC006800);
|
||||
|
||||
#define EXI_MEMORY_CARD_59 0x00000004
|
||||
#define EXI_MEMORY_CARD_123 0x00000008
|
||||
|
|
|
@ -58,7 +58,7 @@ typedef union {
|
|||
} PPCWGPipe;
|
||||
|
||||
#define GXFIFO_ADDR 0xCC008000
|
||||
volatile PPCWGPipe GXWGFifo : GXFIFO_ADDR;
|
||||
volatile PPCWGPipe GXWGFifo AT_ADDRESS(GXFIFO_ADDR);
|
||||
|
||||
#define GX_WRITE_U8(data) GXWGFifo.u8 = data;
|
||||
#define GX_WRITE_U32(data) GXWGFifo.u32 = data;
|
||||
|
|
|
@ -65,19 +65,19 @@ extern "C" {
|
|||
#define OS_CONSOLE_PC_EMULATOR 0x10000001
|
||||
#define OS_CONSOLE_EMULATOR 0x10000000
|
||||
|
||||
volatile u16 __OSDeviceCode : 0x800030E6;
|
||||
volatile u16 __OSDeviceCode AT_ADDRESS(0x800030E6);
|
||||
|
||||
volatile u32 OS_PI_INTR_CAUSE : 0xCC003000;
|
||||
volatile u32 OS_PI_INTR_MASK : 0xCC003004;
|
||||
volatile u32 OS_PI_INTR_CAUSE AT_ADDRESS(0xCC003000);
|
||||
volatile u32 OS_PI_INTR_MASK AT_ADDRESS(0xCC003004);
|
||||
|
||||
volatile u16 OS_MI_INTR_MASK : 0xCC00401C;
|
||||
volatile u16 OS_MI_INTR_MASK AT_ADDRESS(0xCC00401C);
|
||||
|
||||
volatile u16 OS_DSP_DMA_ADDR_HI : 0xCC005030;
|
||||
volatile u16 OS_DSP_DMA_ADDR_LO : 0xCC005032;
|
||||
volatile u16 OS_DSP_INTR_MASK : 0xCC00500A;
|
||||
volatile u16 OS_DSP_DMA_ADDR_HI AT_ADDRESS(0xCC005030);
|
||||
volatile u16 OS_DSP_DMA_ADDR_LO AT_ADDRESS(0xCC005032);
|
||||
volatile u16 OS_DSP_INTR_MASK AT_ADDRESS(0xCC00500A);
|
||||
|
||||
volatile u16 OS_ARAM_DMA_ADDR_HI : 0xCC005020;
|
||||
volatile u16 OS_ARAM_DMA_ADDR_LO : 0xCC005022;
|
||||
volatile u16 OS_ARAM_DMA_ADDR_HI AT_ADDRESS(0xCC005020);
|
||||
volatile u16 OS_ARAM_DMA_ADDR_LO AT_ADDRESS(0xCC005022);
|
||||
|
||||
BOOL OSIsThreadSuspended(OSThread* thread);
|
||||
|
||||
|
|
|
@ -151,8 +151,8 @@ typedef struct OSContext {
|
|||
/* 0x1C4 */ f64 ps[32];
|
||||
} OSContext;
|
||||
|
||||
OSContext* OS_CURRENT_CONTEXT : 0x800000D4;
|
||||
OSContext* OS_CURRENT_FPU_CONTEXT : 0x800000D8;
|
||||
OSContext* OS_CURRENT_CONTEXT AT_ADDRESS(0x800000D4);
|
||||
OSContext* OS_CURRENT_FPU_CONTEXT AT_ADDRESS(0x800000D8);
|
||||
|
||||
void __OSLoadFPUContext(void);
|
||||
void __OSSaveFPUContext(s32 unused0, s32 unused1, OSContext* context);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef OSLINK_H
|
||||
#define OSLINK_H
|
||||
|
||||
#include "dolphin/types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -18,14 +19,14 @@ typedef struct OSSectionInfo OSSectionInfo;
|
|||
typedef struct OSImportInfo OSImportInfo;
|
||||
typedef struct OSRel OSRel;
|
||||
|
||||
OSModuleQueue __OSModuleList : 0x800030C8;
|
||||
void* __OSStringTable : 0x800030D0;
|
||||
|
||||
struct OSModuleQueue {
|
||||
OSModuleInfo* head;
|
||||
OSModuleInfo* tail;
|
||||
};
|
||||
|
||||
OSModuleQueue __OSModuleList AT_ADDRESS(0x800030C8);
|
||||
void* __OSStringTable AT_ADDRESS(0x800030D0);
|
||||
|
||||
struct OSModuleLink {
|
||||
OSModuleInfo* next;
|
||||
OSModuleInfo* prev;
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
vu32 __PIRegs[12] : 0xCC003000;
|
||||
vu32 __PIRegs[12] AT_ADDRESS(0xCC003000);
|
||||
|
||||
#define OS_RESETCODE_RESTART 0x80000000
|
||||
#define OS_RESETCODE_SYSTEM 0x40000000
|
||||
|
|
|
@ -75,8 +75,8 @@ struct OSThread {
|
|||
|
||||
typedef void (*OSSwitchThreadCallback)(OSThread* from, OSThread* to);
|
||||
|
||||
OSThreadQueue OS_THREAD_QUEUE : 0x800000DC;
|
||||
OSThread* OS_CURRENT_THREAD : 0x800000E4;
|
||||
OSThreadQueue OS_THREAD_QUEUE AT_ADDRESS(0x800000DC);
|
||||
OSThread* OS_CURRENT_THREAD AT_ADDRESS(0x800000E4);
|
||||
|
||||
static void DefaultSwitchThreadCallback(OSThread* from, OSThread* to);
|
||||
OSSwitchThreadCallback OSSetSwitchThreadCallback(OSSwitchThreadCallback func);
|
||||
|
|
|
@ -10,7 +10,7 @@ extern "C" {
|
|||
typedef s64 OSTime;
|
||||
typedef u32 OSTick;
|
||||
|
||||
OSTime OS_SYSTEM_TIME : 0x800030D8;
|
||||
OSTime OS_SYSTEM_TIME AT_ADDRESS(0x800030D8);
|
||||
|
||||
typedef struct OSCalendarTime {
|
||||
/* 0x00 */ s32 seconds;
|
||||
|
@ -32,7 +32,7 @@ OSTime __OSTimeToSystemTime(OSTime time);
|
|||
void GetDates(s32 days, OSCalendarTime* ct);
|
||||
void OSTicksToCalendarTime(OSTime ticks, OSCalendarTime* ct);
|
||||
|
||||
extern u32 __OSBusClock : 0x800000F8;
|
||||
extern u32 __OSBusClock AT_ADDRESS(0x800000F8);
|
||||
|
||||
#define OS_BUS_CLOCK (__OSBusClock)
|
||||
#define OS_CORE_CLOCK (*(u32*)0x800000FC)
|
||||
|
|
|
@ -120,7 +120,7 @@ BOOL SITransfer(s32 chan, void* output, u32 outputBytes, void* input, u32 inputB
|
|||
u32 SIGetType(s32 chan);
|
||||
u32 SIGetTypeAsync(s32 chan, SITypeAndStatusCallback callback);
|
||||
|
||||
vu32 __SIRegs[64] : 0xCC006400;
|
||||
vu32 __SIRegs[64] AT_ADDRESS(0xCC006400);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -42,4 +42,10 @@ typedef int BOOL;
|
|||
#define FLOAT_MIN (1.175494351e-38f)
|
||||
#define FLOAT_MAX (3.40282346638528860e+38f)
|
||||
|
||||
#endif
|
||||
#ifdef __MWERKS__
|
||||
#define AT_ADDRESS(xyz) : (xyz)
|
||||
#else
|
||||
#define AT_ADDRESS(xyz)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -138,7 +138,7 @@ u32 VIGetRetraceCount();
|
|||
u32 VIGetDTVStatus();
|
||||
u32 VIGetTvFormat(void);
|
||||
|
||||
vu16 __VIRegs[59] : 0xCC002000;
|
||||
vu16 __VIRegs[59] AT_ADDRESS(0xCC002000);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#define _SDA_BASE_(dummy) 0
|
||||
#define _SDA2_BASE_(dummy) 0
|
||||
|
||||
#ifndef IN_VSCODE_EDITOR
|
||||
#ifdef __MWERKS__
|
||||
#define GLUE(a, b) a##b
|
||||
#define GLUE2(a, b) GLUE(a, b)
|
||||
#define STATIC_ASSERT(cond) typedef char GLUE2(static_assertion_failed, __LINE__)[(cond) ? 1 : -1]
|
||||
|
|
|
@ -23,4 +23,4 @@ typedef long ptrdiff_t;
|
|||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -19,7 +19,7 @@ extern "C" void* __va_arg(_va_list_struct*, int);
|
|||
void* __va_arg(_va_list_struct*, int);
|
||||
#endif
|
||||
|
||||
#if IN_VSCODE_EDITOR
|
||||
#ifndef __MWERKS__
|
||||
#define __builtin_va_info(...)
|
||||
#define _var_arg_typeof(...)
|
||||
#endif
|
||||
|
@ -37,4 +37,4 @@ void* __va_arg(_va_list_struct*, int);
|
|||
|
||||
#define __va_copy(a, b) (*(a) = *(b))
|
||||
|
||||
#endif /* __VA_ARG_H */
|
||||
#endif /* __VA_ARG_H */
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include "dolphin/card/CARDPriv.h"
|
||||
#include "dolphin/os/OSRtc.h"
|
||||
|
||||
u8 GameChoice : 0x800030E3;
|
||||
u8 GameChoice AT_ADDRESS(0x800030E3);
|
||||
|
||||
static BOOL IsCard(u32 id);
|
||||
static s32 DoMount(s32 chan);
|
||||
|
@ -395,4 +395,4 @@ s32 CARDUnmount(s32 chan) {
|
|||
}
|
||||
DoUnmount(chan, CARD_RESULT_NOCARD);
|
||||
return CARD_RESULT_READY;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -678,7 +678,7 @@ asm void __OSPSInit(void){
|
|||
// clang-format on
|
||||
}
|
||||
|
||||
vu32 __DIRegs[16] : 0xCC006000;
|
||||
vu32 __DIRegs[16] AT_ADDRESS(0xCC006000);
|
||||
#define DI_CONFIG_IDX 0x9
|
||||
#define DI_CONFIG_CONFIG_MASK 0xFF
|
||||
|
||||
|
@ -690,4 +690,4 @@ u32 __OSGetDIConfig(void) {
|
|||
/* 8033A874-8033A8A0 3351B4 002C+00 1/1 11/11 0/0 .text OSRegisterVersion */
|
||||
void OSRegisterVersion(const char* version) {
|
||||
OSReport("%s\n", version);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -104,7 +104,7 @@ static void Callback(s32, DVDCommandBlock*) {
|
|||
Prepared = TRUE;
|
||||
}
|
||||
|
||||
OSExecParams* osExecParams : 0x800030f0;
|
||||
OSExecParams* osExecParams AT_ADDRESS(0x800030f0);
|
||||
|
||||
static int IsStreamEnabled() {
|
||||
if (DVDGetCurrentDiskID()->is_streaming) {
|
||||
|
@ -148,7 +148,7 @@ static void StopStreaming() {
|
|||
}
|
||||
|
||||
/* 8033CCFC-8033CDC0 33763C 00C4+00 1/1 0/0 0/0 .text GetApploaderPosition */
|
||||
s32 __OSAppLoaderOffset : 0x800030f4;
|
||||
s32 __OSAppLoaderOffset AT_ADDRESS(0x800030f4);
|
||||
|
||||
static int GetApploaderPosition(void) {
|
||||
static s32 apploaderPosition;
|
||||
|
@ -220,9 +220,9 @@ static BOOL IsNewApploader(AppLoaderStruct* header) {
|
|||
return strncmp(header->date, "2004/02/01", 10) > 0 ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
extern volatile u32 BOOT_REGION_START : 0x812FDFF0;
|
||||
extern volatile u32 BOOT_REGION_END : 0x812FDFEC;
|
||||
extern volatile u8 g_unk_800030E2 : 0x800030E2;
|
||||
extern volatile u32 BOOT_REGION_START AT_ADDRESS(0x812FDFF0);
|
||||
extern volatile u32 BOOT_REGION_END AT_ADDRESS(0x812FDFEC);
|
||||
extern volatile u8 g_unk_800030E2 AT_ADDRESS(0x800030E2);
|
||||
|
||||
/* 8033CDC0-8033D244 337700 0484+00 1/1 0/0 0/0 .text __OSBootDolSimple */
|
||||
void __OSBootDolSimple(u32 doloffset, u32 restartCode, void* regionStart, void* regionEnd, BOOL argsUseDefault, s32 argc, char** argv) {
|
||||
|
@ -312,4 +312,4 @@ void __OSBootDol(u32 doloffset, u32 restartCode, const char** argv) {
|
|||
}
|
||||
|
||||
__OSBootDolSimple(-1, restartCode, saveStart, saveEnd, FALSE, argvlen, argvToPass);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
#include "dolphin/exi/EXIBios.h"
|
||||
#include "dolphin/os.h"
|
||||
|
||||
vu32 __PIRegs[12] : 0xCC003000;
|
||||
vu16 __MEMRegs[64] : 0xCC004000;
|
||||
vu32 __PIRegs[12] AT_ADDRESS(0xCC003000);
|
||||
vu16 __MEMRegs[64] AT_ADDRESS(0xCC004000);
|
||||
|
||||
/* 8033D6F4-8033D700 338034 000C+00 2/2 200/200 5/5 .text OSDisableInterrupts */
|
||||
asm BOOL OSDisableInterrupts(void) {
|
||||
|
@ -445,4 +445,4 @@ static asm void ExternalInterruptHandler(register __OSInterrupt type, register O
|
|||
stwu r1, -8(r1)
|
||||
b __OSDispatchInterrupt
|
||||
// clang-format on
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#define TRUNC(n, a) (((u32)(n)) & ~((a)-1))
|
||||
#define ROUND(n, a) (((u32)(n) + (a)-1) & ~((a)-1))
|
||||
|
||||
vu16 __MEMRegs[64] : 0xCC004000;
|
||||
vu16 __MEMRegs[64] AT_ADDRESS(0xCC004000);
|
||||
|
||||
extern OSErrorHandlerEx __OSErrorTable[16];
|
||||
|
||||
|
@ -216,4 +216,4 @@ void __OSInitMemoryProtection() {
|
|||
|
||||
__OSUnmaskInterrupts(OS_INTERRUPTMASK_MEM_ADDRESS);
|
||||
OSRestoreInterrupts(enabled);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "dolphin/os/OSReset.h"
|
||||
#include "dolphin/os.h"
|
||||
|
||||
vu16 __VIRegs[59] : 0xCC002000;
|
||||
vu16 __VIRegs[59] AT_ADDRESS(0xCC002000);
|
||||
OSThreadQueue __OSActiveThreadQueue : (OS_BASE_CACHED | 0x00DC);
|
||||
|
||||
extern OSExecParams __OSRebootParams;
|
||||
|
@ -217,4 +217,4 @@ u32 OSGetResetCode(void) {
|
|||
return 0x80000000 | __OSRebootParams.restartCode;
|
||||
|
||||
return ((__PIRegs[9] & ~7) >> 3);
|
||||
}
|
||||
}
|
||||
|
|
347
tools/project.py
347
tools/project.py
|
@ -17,7 +17,7 @@ import os
|
|||
import platform
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import IO, Any, Dict, List, Optional, Set, Tuple, Union, cast
|
||||
from typing import IO, Any, Dict, Iterable, List, Optional, Set, Tuple, cast
|
||||
|
||||
from . import ninja_syntax
|
||||
from .ninja_syntax import serialize_path
|
||||
|
@ -155,6 +155,9 @@ class ProjectConfig:
|
|||
self.custom_build_steps: Optional[Dict[str, List[Dict[str, Any]]]] = (
|
||||
None # Custom build steps, types are ["pre-compile", "post-compile", "post-link", "post-build"]
|
||||
)
|
||||
self.generate_compile_commands: bool = (
|
||||
True # Generate compile_commands.json for clangd
|
||||
)
|
||||
|
||||
# Progress output, progress.json and report.json config
|
||||
self.progress = True # Enable progress output
|
||||
|
@ -200,9 +203,40 @@ class ProjectConfig:
|
|||
out[obj.name] = obj.resolve(self, lib)
|
||||
return out
|
||||
|
||||
# Gets the output path for build-related files.
|
||||
def out_path(self) -> Path:
|
||||
return self.build_dir / str(self.version)
|
||||
|
||||
# Gets the path to the compilers directory.
|
||||
# Exits the program if neither `compilers_path` nor `compilers_tag` is provided.
|
||||
def compilers(self) -> Path:
|
||||
if self.compilers_path:
|
||||
return self.compilers_path
|
||||
elif self.compilers_tag:
|
||||
return self.build_dir / "compilers"
|
||||
else:
|
||||
sys.exit("ProjectConfig.compilers_tag missing")
|
||||
|
||||
# Gets the wrapper to use for compiler commands, if set.
|
||||
def compiler_wrapper(self) -> Optional[Path]:
|
||||
wrapper = self.wrapper
|
||||
|
||||
if self.use_wibo():
|
||||
wrapper = self.build_dir / "tools" / "wibo"
|
||||
if not is_windows() and wrapper is None:
|
||||
wrapper = Path("wine")
|
||||
|
||||
return wrapper
|
||||
|
||||
# Determines whether or not to use wibo as the compiler wrapper.
|
||||
def use_wibo(self) -> bool:
|
||||
return (
|
||||
self.wibo_tag is not None
|
||||
and sys.platform == "linux"
|
||||
and platform.machine() in ("i386", "x86_64")
|
||||
and self.wrapper is None
|
||||
)
|
||||
|
||||
|
||||
def is_windows() -> bool:
|
||||
return os.name == "nt"
|
||||
|
@ -214,13 +248,26 @@ CHAIN = "cmd /c " if is_windows() else ""
|
|||
EXE = ".exe" if is_windows() else ""
|
||||
|
||||
|
||||
def make_flags_str(flags: Optional[Union[str, List[str]]]) -> str:
|
||||
def file_is_asm(path: Path) -> bool:
|
||||
return path.suffix.lower() == ".s"
|
||||
|
||||
|
||||
def file_is_c(path: Path) -> bool:
|
||||
return path.suffix.lower() == ".c"
|
||||
|
||||
|
||||
def file_is_cpp(path: Path) -> bool:
|
||||
return path.suffix.lower() in (".cc", ".cp", ".cpp", ".cxx")
|
||||
|
||||
|
||||
def file_is_c_cpp(path: Path) -> bool:
|
||||
return file_is_c(path) or file_is_cpp(path)
|
||||
|
||||
|
||||
def make_flags_str(flags: Optional[List[str]]) -> str:
|
||||
if flags is None:
|
||||
return ""
|
||||
elif isinstance(flags, list):
|
||||
return " ".join(flags)
|
||||
else:
|
||||
return flags
|
||||
return " ".join(flags)
|
||||
|
||||
|
||||
# Load decomp-toolkit generated config.json
|
||||
|
@ -253,13 +300,14 @@ def load_build_config(
|
|||
return build_config
|
||||
|
||||
|
||||
# Generate build.ninja and objdiff.json
|
||||
# Generate build.ninja, objdiff.json and compile_commands.json
|
||||
def generate_build(config: ProjectConfig) -> None:
|
||||
config.validate()
|
||||
objects = config.objects()
|
||||
build_config = load_build_config(config, config.out_path() / "config.json")
|
||||
generate_build_ninja(config, objects, build_config)
|
||||
generate_objdiff_config(config, objects, build_config)
|
||||
generate_compile_commands(config, objects, build_config)
|
||||
|
||||
|
||||
# Generate build.ninja
|
||||
|
@ -406,16 +454,10 @@ def generate_build_ninja(
|
|||
else:
|
||||
sys.exit("ProjectConfig.sjiswrap_tag missing")
|
||||
|
||||
wrapper = config.compiler_wrapper()
|
||||
# Only add an implicit dependency on wibo if we download it
|
||||
wrapper = config.wrapper
|
||||
wrapper_implicit: Optional[Path] = None
|
||||
if (
|
||||
config.wibo_tag is not None
|
||||
and sys.platform == "linux"
|
||||
and platform.machine() in ("i386", "x86_64")
|
||||
and config.wrapper is None
|
||||
):
|
||||
wrapper = build_tools_path / "wibo"
|
||||
if wrapper is not None and config.use_wibo():
|
||||
wrapper_implicit = wrapper
|
||||
n.build(
|
||||
outputs=wrapper,
|
||||
|
@ -426,15 +468,11 @@ def generate_build_ninja(
|
|||
"tag": config.wibo_tag,
|
||||
},
|
||||
)
|
||||
if not is_windows() and wrapper is None:
|
||||
wrapper = Path("wine")
|
||||
wrapper_cmd = f"{wrapper} " if wrapper else ""
|
||||
|
||||
compilers = config.compilers()
|
||||
compilers_implicit: Optional[Path] = None
|
||||
if config.compilers_path:
|
||||
compilers = config.compilers_path
|
||||
elif config.compilers_tag:
|
||||
compilers = config.build_dir / "compilers"
|
||||
if config.compilers_path is None and config.compilers_tag is not None:
|
||||
compilers_implicit = compilers
|
||||
n.build(
|
||||
outputs=compilers,
|
||||
|
@ -445,8 +483,6 @@ def generate_build_ninja(
|
|||
"tag": config.compilers_tag,
|
||||
},
|
||||
)
|
||||
else:
|
||||
sys.exit("ProjectConfig.compilers_tag missing")
|
||||
|
||||
binutils_implicit = None
|
||||
if config.binutils_path:
|
||||
|
@ -660,7 +696,6 @@ def generate_build_ninja(
|
|||
n.comment(f"Link {self.name}")
|
||||
if self.module_id == 0:
|
||||
elf_path = build_path / f"{self.name}.elf"
|
||||
dol_path = build_path / f"{self.name}.dol"
|
||||
elf_ldflags = f"$ldflags -lcf {serialize_path(self.ldscript)}"
|
||||
if config.generate_map:
|
||||
elf_map = map_path(elf_path)
|
||||
|
@ -725,17 +760,36 @@ def generate_build_ninja(
|
|||
source_added: Set[Path] = set()
|
||||
|
||||
def c_build(obj: Object, src_path: Path) -> Optional[Path]:
|
||||
cflags_str = make_flags_str(obj.options["cflags"])
|
||||
if obj.options["extra_cflags"] is not None:
|
||||
extra_cflags_str = make_flags_str(obj.options["extra_cflags"])
|
||||
cflags_str += " " + extra_cflags_str
|
||||
used_compiler_versions.add(obj.options["mw_version"])
|
||||
|
||||
# Avoid creating duplicate build rules
|
||||
if obj.src_obj_path is None or obj.src_obj_path in source_added:
|
||||
return obj.src_obj_path
|
||||
source_added.add(obj.src_obj_path)
|
||||
|
||||
cflags = obj.options["cflags"]
|
||||
extra_cflags = obj.options["extra_cflags"]
|
||||
|
||||
# Add appropriate language flag if it doesn't exist already
|
||||
# Added directly to the source so it flows to other generation tasks
|
||||
if not any(flag.startswith("-lang") for flag in cflags) and (
|
||||
extra_cflags is None
|
||||
or not any(flag.startswith("-lang") for flag in extra_cflags)
|
||||
):
|
||||
# Ensure extra_cflags is a unique instance,
|
||||
# and insert into there to avoid modifying shared sets of flags
|
||||
if extra_cflags is None:
|
||||
extra_cflags = []
|
||||
extra_cflags = obj.options["extra_cflags"] = list(extra_cflags)
|
||||
if file_is_cpp(src_path):
|
||||
extra_cflags.insert(0, "-lang=c++")
|
||||
else:
|
||||
extra_cflags.insert(0, "-lang=c")
|
||||
|
||||
cflags_str = make_flags_str(cflags)
|
||||
if extra_cflags is not None:
|
||||
extra_cflags_str = make_flags_str(extra_cflags)
|
||||
cflags_str += " " + extra_cflags_str
|
||||
used_compiler_versions.add(obj.options["mw_version"])
|
||||
|
||||
# Add MWCC build rule
|
||||
lib_name = obj.options["lib"]
|
||||
n.comment(f"{obj.name}: {lib_name} (linked {obj.completed})")
|
||||
|
@ -767,7 +821,7 @@ def generate_build_ninja(
|
|||
if obj.options["host"] and obj.host_obj_path is not None:
|
||||
n.build(
|
||||
outputs=obj.host_obj_path,
|
||||
rule="host_cc" if src_path.suffix == ".c" else "host_cpp",
|
||||
rule="host_cc" if file_is_c(src_path) else "host_cpp",
|
||||
inputs=src_path,
|
||||
variables={
|
||||
"basedir": os.path.dirname(obj.host_obj_path),
|
||||
|
@ -827,10 +881,10 @@ def generate_build_ninja(
|
|||
link_built_obj = obj.completed
|
||||
built_obj_path: Optional[Path] = None
|
||||
if obj.src_path is not None and obj.src_path.exists():
|
||||
if obj.src_path.suffix in (".c", ".cp", ".cpp"):
|
||||
if file_is_c_cpp(obj.src_path):
|
||||
# Add MWCC & host build rules
|
||||
built_obj_path = c_build(obj, obj.src_path)
|
||||
elif obj.src_path.suffix == ".s":
|
||||
elif file_is_asm(obj.src_path):
|
||||
# Add assembler build rule
|
||||
built_obj_path = asm_build(obj, obj.src_path, obj.src_obj_path)
|
||||
else:
|
||||
|
@ -1274,30 +1328,20 @@ def generate_objdiff_config(
|
|||
|
||||
cflags = obj.options["cflags"]
|
||||
reverse_fn_order = False
|
||||
if type(cflags) is list:
|
||||
for flag in cflags:
|
||||
if not flag.startswith("-inline "):
|
||||
continue
|
||||
for value in flag.split(" ")[1].split(","):
|
||||
if value == "deferred":
|
||||
reverse_fn_order = True
|
||||
elif value == "nodeferred":
|
||||
reverse_fn_order = False
|
||||
for flag in cflags:
|
||||
if not flag.startswith("-inline "):
|
||||
continue
|
||||
for value in flag.split(" ")[1].split(","):
|
||||
if value == "deferred":
|
||||
reverse_fn_order = True
|
||||
elif value == "nodeferred":
|
||||
reverse_fn_order = False
|
||||
|
||||
# Filter out include directories
|
||||
def keep_flag(flag):
|
||||
return not flag.startswith("-i ") and not flag.startswith("-I ")
|
||||
# Filter out include directories
|
||||
def keep_flag(flag):
|
||||
return not flag.startswith("-i ") and not flag.startswith("-I ")
|
||||
|
||||
cflags = list(filter(keep_flag, cflags))
|
||||
|
||||
# Add appropriate lang flag
|
||||
if obj.src_path is not None and not any(
|
||||
flag.startswith("-lang") for flag in cflags
|
||||
):
|
||||
if obj.src_path.suffix in (".cp", ".cpp"):
|
||||
cflags.insert(0, "-lang=c++")
|
||||
else:
|
||||
cflags.insert(0, "-lang=c")
|
||||
cflags = list(filter(keep_flag, cflags))
|
||||
|
||||
compiler_version = COMPILER_MAP.get(obj.options["mw_version"])
|
||||
if compiler_version is None:
|
||||
|
@ -1388,6 +1432,199 @@ def generate_objdiff_config(
|
|||
json.dump(cleandict(objdiff_config), w, indent=2, default=unix_path)
|
||||
|
||||
|
||||
def generate_compile_commands(
|
||||
config: ProjectConfig,
|
||||
objects: Dict[str, Object],
|
||||
build_config: Optional[Dict[str, Any]],
|
||||
) -> None:
|
||||
if build_config is None or not config.generate_compile_commands:
|
||||
return
|
||||
|
||||
# The following code attempts to convert mwcc flags to clang flags
|
||||
# for use with clangd.
|
||||
|
||||
# Flags to ignore explicitly
|
||||
CFLAG_IGNORE: Set[str] = {
|
||||
# Search order modifier
|
||||
# Has a different meaning to Clang, and would otherwise
|
||||
# be picked up by the include passthrough prefix
|
||||
"-I-",
|
||||
"-i-",
|
||||
}
|
||||
CFLAG_IGNORE_PREFIX: Tuple[str, ...] = tuple()
|
||||
|
||||
# Flags to replace
|
||||
CFLAG_REPLACE: Dict[str, str] = {}
|
||||
CFLAG_REPLACE_PREFIX: Tuple[Tuple[str, str], ...] = (
|
||||
# Includes
|
||||
("-i ", "-I"),
|
||||
("-I ", "-I"),
|
||||
("-I+", "-I"),
|
||||
# Defines
|
||||
("-d ", "-D"),
|
||||
("-D ", "-D"),
|
||||
("-D+", "-D"),
|
||||
)
|
||||
|
||||
# Flags with a finite set of options
|
||||
CFLAG_REPLACE_OPTIONS: Tuple[Tuple[str, Dict[str, Tuple[str, ...]]], ...] = (
|
||||
# Exceptions
|
||||
(
|
||||
"-Cpp_exceptions",
|
||||
{
|
||||
"off": ("-fno-cxx-exceptions",),
|
||||
"on": ("-fcxx-exceptions",),
|
||||
},
|
||||
),
|
||||
# RTTI
|
||||
(
|
||||
"-RTTI",
|
||||
{
|
||||
"off": ("-fno-rtti",),
|
||||
"on": ("-frtti",),
|
||||
},
|
||||
),
|
||||
# Language configuration
|
||||
(
|
||||
"-lang",
|
||||
{
|
||||
"c": ("--language=c", "--std=c89"),
|
||||
"c99": ("--language=c", "--std=c99"),
|
||||
"c++": ("--language=c++", "--std=c++98"),
|
||||
"cplus": ("--language=c++", "--std=c++98"),
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
# Flags to pass through
|
||||
CFLAG_PASSTHROUGH: Set[str] = set()
|
||||
CFLAG_PASSTHROUGH_PREFIX: Tuple[str, ...] = (
|
||||
"-I", # includes
|
||||
"-D", # defines
|
||||
)
|
||||
|
||||
clangd_config = []
|
||||
|
||||
def add_unit(build_obj: Dict[str, Any]) -> None:
|
||||
obj = objects.get(build_obj["name"])
|
||||
if obj is None:
|
||||
return
|
||||
|
||||
# Skip unresolved objects
|
||||
if (
|
||||
obj.src_path is None
|
||||
or obj.src_obj_path is None
|
||||
or not file_is_c_cpp(obj.src_path)
|
||||
):
|
||||
return
|
||||
|
||||
# Gather cflags for source file
|
||||
cflags: list[str] = []
|
||||
|
||||
def append_cflags(flags: Iterable[str]) -> None:
|
||||
# Match a flag against either a set of concrete flags, or a set of prefixes.
|
||||
def flag_match(
|
||||
flag: str, concrete: Set[str], prefixes: Tuple[str, ...]
|
||||
) -> bool:
|
||||
if flag in concrete:
|
||||
return True
|
||||
|
||||
for prefix in prefixes:
|
||||
if flag.startswith(prefix):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
# Determine whether a flag should be ignored.
|
||||
def should_ignore(flag: str) -> bool:
|
||||
return flag_match(flag, CFLAG_IGNORE, CFLAG_IGNORE_PREFIX)
|
||||
|
||||
# Determine whether a flag should be passed through.
|
||||
def should_passthrough(flag: str) -> bool:
|
||||
return flag_match(flag, CFLAG_PASSTHROUGH, CFLAG_PASSTHROUGH_PREFIX)
|
||||
|
||||
# Attempts replacement for the given flag.
|
||||
def try_replace(flag: str) -> bool:
|
||||
replacement = CFLAG_REPLACE.get(flag)
|
||||
if replacement is not None:
|
||||
cflags.append(replacement)
|
||||
return True
|
||||
|
||||
for prefix, replacement in CFLAG_REPLACE_PREFIX:
|
||||
if flag.startswith(prefix):
|
||||
cflags.append(flag.replace(prefix, replacement, 1))
|
||||
return True
|
||||
|
||||
for prefix, options in CFLAG_REPLACE_OPTIONS:
|
||||
if not flag.startswith(prefix):
|
||||
continue
|
||||
|
||||
# "-lang c99" and "-lang=c99" are both generally valid option forms
|
||||
option = flag.removeprefix(prefix).removeprefix("=").lstrip()
|
||||
replacements = options.get(option)
|
||||
if replacements is not None:
|
||||
cflags.extend(replacements)
|
||||
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
for flag in flags:
|
||||
# Ignore flags first
|
||||
if should_ignore(flag):
|
||||
continue
|
||||
|
||||
# Then find replacements
|
||||
if try_replace(flag):
|
||||
continue
|
||||
|
||||
# Pass flags through last
|
||||
if should_passthrough(flag):
|
||||
cflags.append(flag)
|
||||
continue
|
||||
|
||||
append_cflags(obj.options["cflags"])
|
||||
if isinstance(obj.options["extra_cflags"], list):
|
||||
append_cflags(obj.options["extra_cflags"])
|
||||
|
||||
unit_config = {
|
||||
"directory": Path.cwd(),
|
||||
"file": obj.src_path,
|
||||
"output": obj.src_obj_path,
|
||||
"arguments": [
|
||||
"clang",
|
||||
"-nostdinc",
|
||||
"-fno-builtin",
|
||||
"--target=powerpc-eabi",
|
||||
*cflags,
|
||||
"-c",
|
||||
obj.src_path,
|
||||
"-o",
|
||||
obj.src_obj_path,
|
||||
],
|
||||
}
|
||||
clangd_config.append(unit_config)
|
||||
|
||||
# Add DOL units
|
||||
for unit in build_config["units"]:
|
||||
add_unit(unit)
|
||||
|
||||
# Add REL units
|
||||
for module in build_config["modules"]:
|
||||
for unit in module["units"]:
|
||||
add_unit(unit)
|
||||
|
||||
# Write compile_commands.json
|
||||
with open("compile_commands.json", "w", encoding="utf-8") as w:
|
||||
|
||||
def default_format(o):
|
||||
if isinstance(o, Path):
|
||||
return o.resolve().as_posix()
|
||||
return str(o)
|
||||
|
||||
json.dump(clangd_config, w, indent=2, default=default_format)
|
||||
|
||||
|
||||
# Calculate, print and write progress to progress.json
|
||||
def calculate_progress(config: ProjectConfig) -> None:
|
||||
config.validate()
|
||||
|
|
Loading…
Reference in New Issue