use a real build system (if you can call it that)

This commit is contained in:
maksw committed 2026-05-30 11:44:09 +02:00
1 parent bfe2b55142
commit a01772d637
5 files changed
+3513 -321

No files matched your search

+4 -2
View File
@@ -1,5 +1,7 @@
vc140.pdb
build.obj
bin/
obj/
qemu.log
disk.vhd
disk.vhd
code/build/build.exe
code/build/build.exe.old
Binary file not shown.
+6 -319
View File
@@ -1,322 +1,9 @@
@echo off
setlocal enabledelayedexpansion
set ROOT=%~dp0.
set SRC=%ROOT%\code
set PUBLIC=%SRC%\public
set COMMON=%SRC%\common
set KERNEL=%SRC%\kernel
set HAL=%KERNEL%\hal
set USER=%SRC%\user
set DRIVERS=%SRC%\drivers
set THIRD_PARTY=%SRC%\third_party
set VHD=%~dp0disk.vhd
if not exist "%VHD%" (
call mkimage.bat
:: If the build system binary doesn't exist, bootstrap it!
if not exist "code\build\build.exe" (
echo Bootstrapping build system...
cl.exe /nologo /Fe"code\build\build.exe" "code\build\build.c"
)
if exist "obj" rd /s /q "obj"
if exist "bin" rd /s /q "bin"
mkdir "obj\boot" 2>nul
mkdir "obj\kernel" 2>nul
mkdir "obj\lwip" 2>nul
mkdir "obj\hal" 2>nul
mkdir "obj\syscall" 2>nul
mkdir "obj\win32" 2>nul
mkdir "obj\posix" 2>nul
mkdir "obj\drivers" 2>nul
mkdir "obj\init" 2>nul
mkdir "obj\shell_win32" 2>nul
mkdir "obj\shell_posix" 2>nul
mkdir "obj\shell_native" 2>nul
mkdir "obj\async_apc" 2>nul
mkdir "obj\async_cancel" 2>nul
mkdir "obj\edit" 2>nul
mkdir "obj\httpget" 2>nul
mkdir "obj\tcpserve" 2>nul
mkdir "obj\udp" 2>nul
mkdir "obj\resolve" 2>nul
mkdir "obj\ping" 2>nul
mkdir "obj\doom" 2>nul
mkdir "obj\video" 2>nul
mkdir "bin" 2>nul
set INCLUDES=/I"%PUBLIC%" /I"%COMMON%\include" /I"%KERNEL%\include"
set CFLAGS=/nologo /W3 /WX /Od /GS- /Gs999999 /Gz /Gy /EHsc- /GR- /Oi /Zi /std:c17 /D_CRT_SECURE_NO_WARNINGS /D_CRT_NONSTDC_NO_WARNINGS %INCLUDES%
set KERNEL_CFLAGS=%CFLAGS%
rem lwIP is third-party freestanding C. Compile it into lwip.sys without /WX,
rem and silence expected MSVC warnings from packed protocol headers and macros.
set LWIP_ROOT=%DRIVERS%\net\lwip
set LWIP_DRIVER_CFLAGS=%CFLAGS:/WX =% /I"%LWIP_ROOT%\include" /I"%THIRD_PARTY%\lwip\src\include" /wd4005 /wd4100 /wd4103 /wd4127 /wd4244 /wd4267 /wd4706
set LFLAGS=/nologo /NODEFAULTLIB /DEBUG
:: ---- Assemble ASM files ----
echo Assembling...
ml64 /nologo /c /Fo"obj\kernel\ke_switch.obj" "%KERNEL%\ke_switch.asm" || exit /b 1
ml64 /nologo /c /Fo"obj\kernel\ke_syscall_asm.obj" "%KERNEL%\ke_syscall.asm" || exit /b 1
ml64 /nologo /c /Fo"obj\kernel\ke_gdt_reload.obj" "%KERNEL%\ke_gdt_reload.asm" || exit /b 1
for %%f in (%SRC%\boot\uefi\*.asm) do (
ml64 /nologo /c /Fo"obj\boot\%%~nf.obj" "%%f" || exit /b 1
)
ml64 /nologo /c /Fo"obj\syscall\stubs.obj" "%USER%\syscall\syscall_stubs.asm" || exit /b 1
:: ---- Compile shared freestanding support ----
cl /nologo /c /Fo"obj\libc.obj" "%COMMON%\libc.c" || exit /b 1
cl %CFLAGS% /MP /c /Fo"obj\\" "%COMMON%\printf.c" "%COMMON%\ini_parser.c" || exit /b 1
:: ---- Compile bootloader ----
echo Compiling bootloader...
cl %CFLAGS% /MP /c /I"%SRC%\boot\uefi\include" /Fo"obj\boot\\" "%SRC%\boot\uefi\*.c" || exit /b 1
:: ---- Link bootloader ----
echo Linking bootx64.efi...
link %LFLAGS% /SUBSYSTEM:EFI_APPLICATION /ENTRY:UefiMain /OUT:"bin\bootx64.efi" ^
/PDB:"bin\bootx64.pdb" %SRC%\boot\uefi\efilib.lib obj\ini_parser.obj obj\libc.obj obj\boot\*.obj || exit /b 1
:: ---- Compile HAL ----
echo Compiling hal...
cl %CFLAGS% /MP /c /Fo"obj\hal\\" "%HAL%\*.c" || exit /b 1
:: ---- Link hal.dll ----
echo Linking hal.dll...
link %LFLAGS% /DLL /OUT:"bin\hal.dll" /ENTRY:HalInitialize /IGNORE:4216 obj\printf.obj obj\libc.obj obj\hal\*.obj || exit /b 1
:: ---- Compile kernel ----
echo Compiling kernel...
cl %KERNEL_CFLAGS% /MP /c /Fo"obj\kernel\\" "%KERNEL%\*.c" || exit /b 1
:: ---- Link kernel.exe ----
echo Linking kernel.exe...
link %LFLAGS% /SUBSYSTEM:NATIVE /ENTRY:KernelMain /OUT:"bin\kernel.exe" /PDB:"bin\kernel.pdb" ^
bin\hal.lib obj\ini_parser.obj obj\printf.obj obj\libc.obj obj\kernel\*.obj || exit /b 1
:: ---- Compile syscall.dll ----
echo Compiling syscall.dll...
link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL ^
/OUT:"bin\syscall.dll" obj\syscall\stubs.obj || exit /b 1
:: ---- Compile win32.dll ----
echo Compiling win32.dll...
cl %CFLAGS% /MP /c /Fo"obj\win32\\" "%USER%\personalities\win32\*.c" || exit /b 1
link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL ^
/OUT:"bin\win32.dll" bin\syscall.lib obj\libc.obj obj\win32\*.obj || exit /b 1
:: ---- Compile posix.dll ----
echo Compiling posix.dll...
cl %CFLAGS% /MP /c /Fo"obj\posix\\" "%USER%\personalities\posix\*.c" || exit /b 1
link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL ^
/OUT:"bin\posix.dll" bin\syscall.lib obj\libc.obj obj\posix\*.obj || exit /b 1
:: ---- Compile drivers ----
echo Compiling drivers...
echo Compiling ide.sys...
cl %CFLAGS% /c /Fo"obj\drivers\ide.obj" "%DRIVERS%\storage\ide\ide.c" || exit /b 1
link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL /OUT:"bin\ide.sys" /ENTRY:DriverEntry ^
bin\hal.lib bin\kernel.lib obj\libc.obj obj\drivers\ide.obj || exit /b 1
echo Compiling ahci.sys...
cl %CFLAGS% /c /Fo"obj\drivers\ahci.obj" "%DRIVERS%\storage\ahci\ahci.c" || exit /b 1
link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL /OUT:"bin\ahci.sys" /ENTRY:DriverEntry ^
bin\hal.lib bin\kernel.lib obj\libc.obj obj\drivers\ahci.obj || exit /b 1
echo Compiling fat32.sys...
cl %CFLAGS% /c /Fo"obj\drivers\fat32.obj" "%DRIVERS%\fs\fat32\fat32.c" || exit /b 1
link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL /OUT:"bin\fat32.sys" /ENTRY:DriverEntry ^
bin\hal.lib bin\kernel.lib obj\libc.obj obj\drivers\fat32.obj || exit /b 1
echo Compiling lwip.sys...
set "LWIP_FILES="
for /f "usebackq tokens=* delims=" %%f in ("%LWIP_ROOT%\lwip_sources.txt") do (
set "LWIP_FILE=%%f"
if not "!LWIP_FILE!"=="" if not "!LWIP_FILE:~0,1!"=="#" (
set "LWIP_WIN_FILE=!LWIP_FILE:/=\!"
set "LWIP_FILES=!LWIP_FILES! "%SRC%\!LWIP_WIN_FILE!""
)
)
cl %LWIP_DRIVER_CFLAGS% /MP /c /Fo"obj\lwip\\" !LWIP_FILES! || exit /b 1
link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL /OUT:"bin\lwip.sys" /ENTRY:DriverEntry ^
bin\hal.lib bin\kernel.lib obj\libc.obj obj\lwip\*.obj || exit /b 1
echo Compiling usb.sys...
cl %CFLAGS% /c /Fo"obj\drivers\usb.obj" "%DRIVERS%\bus\usb\usb.c" || exit /b 1
link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL /OUT:"bin\usb.sys" /ENTRY:DriverEntry ^
bin\hal.lib bin\kernel.lib obj\libc.obj obj\drivers\usb.obj || exit /b 1
echo Compiling rtl816x.sys...
cl %CFLAGS% /c /Fo"obj\drivers\rtl816x.obj" "%DRIVERS%\net\rtl816x\rtl816x.c" || exit /b 1
link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL /OUT:"bin\rtl816x.sys" /ENTRY:DriverEntry ^
bin\hal.lib bin\kernel.lib obj\libc.obj obj\drivers\rtl816x.obj || exit /b 1
echo Compiling rtl8139.sys...
cl %CFLAGS% /c /Fo"obj\drivers\rtl8139.obj" "%DRIVERS%\net\rtl8139\rtl8139.c" || exit /b 1
link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL /OUT:"bin\rtl8139.sys" /ENTRY:DriverEntry ^
bin\hal.lib bin\kernel.lib obj\libc.obj obj\drivers\rtl8139.obj || exit /b 1
:: ---- Compile init ----
echo Compiling init...
cl %CFLAGS% /MP /c /Fo"obj\init\\" "%USER%\system\init\*.c" || exit /b 1
link %LFLAGS% /SUBSYSTEM:NATIVE /ENTRY:_start ^
/OUT:"bin\init.exe" /PDB:"bin\init.pdb" bin\syscall.lib obj\libc.obj obj\init\init.obj || exit /b 1
:: ---- Compile shell_win32 ----
echo Compiling shell_win32...
cl %CFLAGS% /MP /c /Fo"obj\shell_win32\\" "%USER%\apps\shell_win32\*.c" || exit /b 1
link %LFLAGS% /SUBSYSTEM:NATIVE /ENTRY:main ^
/OUT:"bin\shell_win32.exe" /PDB:"bin\shell_win32.pdb" bin\win32.lib obj\libc.obj obj\shell_win32\*.obj || exit /b 1
:: ---- Compile shell_posix ----
echo Compiling shell_posix...
cl %CFLAGS% /MP /c /Fo"obj\shell_posix\\" "%USER%\apps\shell_posix\*.c" || exit /b 1
link %LFLAGS% /SUBSYSTEM:NATIVE /ENTRY:main ^
/OUT:"bin\shell_posix.exe" /PDB:"bin\shell_posix.pdb" bin\posix.lib obj\libc.obj obj\shell_posix\*.obj || exit /b 1
:: ---- Compile shell_native ----
echo Compiling shell_native...
cl %CFLAGS% /MP /c /Fo"obj\shell_native\\" "%USER%\apps\shell_native\*.c" || exit /b 1
link %LFLAGS% /SUBSYSTEM:NATIVE /ENTRY:main ^
/OUT:"bin\shell_native.exe" /PDB:"bin\shell_native.pdb" bin\syscall.lib obj\libc.obj obj\shell_native\*.obj || exit /b 1
:: ---- Compile async_apc ----
echo Compiling async_apc...
cl %CFLAGS% /MP /c /Fo"obj\async_apc\\" "%USER%\tests\async_apc\*.c" || exit /b 1
link %LFLAGS% /SUBSYSTEM:NATIVE /ENTRY:main ^
/OUT:"bin\async_apc.exe" /PDB:"bin\async_apc.pdb" bin\syscall.lib obj\libc.obj obj\async_apc\*.obj || exit /b 1
:: ---- Compile async_cancel ----
echo Compiling async_cancel...
cl %CFLAGS% /MP /c /Fo"obj\async_cancel\\" "%USER%\tests\async_cancel\*.c" || exit /b 1
link %LFLAGS% /SUBSYSTEM:NATIVE /ENTRY:main ^
/OUT:"bin\async_cancel.exe" /PDB:"bin\async_cancel.pdb" bin\syscall.lib obj\libc.obj obj\async_cancel\*.obj || exit /b 1
:: ---- Compile edit ----
echo Compiling edit...
cl %CFLAGS% /MP /c /Fo"obj\edit\\" "%USER%\apps\edit\*.c" || exit /b 1
link %LFLAGS% /SUBSYSTEM:NATIVE /ENTRY:main ^
/OUT:"bin\edit.exe" /PDB:"bin\edit.pdb" bin\syscall.lib obj\libc.obj obj\edit\*.obj || exit /b 1
:: ---- Compile httpget ----
echo Compiling httpget...
cl %CFLAGS% /MP /c /Fo"obj\httpget\\" "%USER%\apps\httpget\*.c" || exit /b 1
link %LFLAGS% /SUBSYSTEM:NATIVE /ENTRY:main ^
/OUT:"bin\httpget.exe" /PDB:"bin\httpget.pdb" bin\syscall.lib obj\libc.obj obj\httpget\*.obj || exit /b 1
:: ---- Compile tcpserve ----
echo Compiling tcpserve...
cl %CFLAGS% /MP /c /Fo"obj\tcpserve\\" "%USER%\apps\tcpserve\*.c" || exit /b 1
link %LFLAGS% /SUBSYSTEM:NATIVE /ENTRY:main ^
/OUT:"bin\tcpserve.exe" /PDB:"bin\tcpserve.pdb" bin\syscall.lib obj\libc.obj obj\tcpserve\*.obj || exit /b 1
:: ---- Compile udp ----
echo Compiling udp...
cl %CFLAGS% /MP /c /Fo"obj\udp\\" "%USER%\apps\udp\*.c" || exit /b 1
link %LFLAGS% /SUBSYSTEM:NATIVE /ENTRY:main ^
/OUT:"bin\udp.exe" /PDB:"bin\udp.pdb" bin\syscall.lib obj\libc.obj obj\udp\*.obj || exit /b 1
:: ---- Compile resolve ----
echo Compiling resolve...
cl %CFLAGS% /MP /c /Fo"obj\resolve\\" "%USER%\apps\resolve\*.c" || exit /b 1
link %LFLAGS% /SUBSYSTEM:NATIVE /ENTRY:main ^
/OUT:"bin\resolve.exe" /PDB:"bin\resolve.pdb" bin\syscall.lib obj\libc.obj obj\resolve\*.obj || exit /b 1
:: ---- Compile ping ----
echo Compiling ping...
cl %CFLAGS% /MP /c /Fo"obj\ping\\" "%USER%\apps\ping\*.c" || exit /b 1
link %LFLAGS% /SUBSYSTEM:NATIVE /ENTRY:main ^
/OUT:"bin\ping.exe" /PDB:"bin\ping.pdb" bin\syscall.lib obj\libc.obj obj\ping\*.obj || exit /b 1
:: ---- Compile doom ----
echo Compiling doom...
cl %CFLAGS% /MP /c /Fo"obj\doom\\" "%USER%\apps\doom\*.c" || exit /b 1
link %LFLAGS% /SUBSYSTEM:NATIVE /ENTRY:main ^
/OUT:"bin\doom.exe" /PDB:"bin\doom.pdb" bin\syscall.lib obj\libc.obj obj\doom\*.obj || exit /b 1
:: ---- Compile video player ----
echo Compiling video...
cl %CFLAGS% /MP /c /Fo"obj\video\\" "%USER%\apps\video\*.c" || exit /b 1
link %LFLAGS% /SUBSYSTEM:NATIVE /ENTRY:main ^
/OUT:"bin\video.exe" /PDB:"bin\video.pdb" bin\win32.lib obj\libc.obj %USER%\apps\video\bink2w64.lib obj\video\*.obj || exit /b 1
:: ---- Mount disk image ----
echo Mounting disk.vhd...
set DPS=%TEMP%\ntlite_mnt_%RANDOM%.txt
(
echo select vdisk file="%VHD%"
echo attach vdisk
echo select partition 1
echo format fs=fat32 quick
echo assign letter=Z
echo select partition 2
echo format fs=fat32 quick
echo assign letter=Y
echo exit
) > "%DPS%"
diskpart /s "%DPS%"
del "%DPS%"
if not exist "Z:\" (
echo ERROR: Could not mount disk.vhd as Z:
echo If Z: is already in use, change the letter in build.bat and mkimage.bat.
exit /b 1
)
set DEST=Z:
set DEST2=Y:
:: ---- Copy to ESP layout ----
echo Assembling ESP...
mkdir "%DEST%\apps" 2>nul
mkdir "%DEST2%\apps" 2>nul
mkdir "%DEST%\system" 2>nul
mkdir "%DEST%\drivers" 2>nul
mkdir "%DEST%\EFI\BOOT" 2>nul
copy /y "bin\bootx64.efi" "%DEST%\EFI\BOOT\"
copy /y "bin\kernel.exe" "%DEST%\system\colonel.exe"
copy /y "bin\hal.dll" "%DEST%\system\"
copy /y "bin\syscall.dll" "%DEST%\system\"
copy /y "bin\win32.dll" "%DEST%\system\"
copy /y "bin\posix.dll" "%DEST%\system\"
copy /y "%SRC%\settings.ini" "%DEST%\system\"
copy /y "bin\ide.sys" "%DEST%\drivers\"
copy /y "bin\ahci.sys" "%DEST%\drivers\"
copy /y "bin\fat32.sys" "%DEST%\drivers\"
copy /y "bin\lwip.sys" "%DEST%\drivers\"
copy /y "bin\usb.sys" "%DEST%\drivers\"
copy /y "bin\rtl816x.sys" "%DEST%\drivers\"
copy /y "bin\rtl8139.sys" "%DEST%\drivers\"
copy /y "bin\init.exe" "%DEST%\system\"
copy /y "bin\shell_win32.exe" "%DEST%\apps\"
copy /y "bin\shell_posix.exe" "%DEST%\apps\"
copy /y "bin\shell_native.exe" "%DEST%\apps\"
copy /y "bin\async_apc.exe" "%DEST2%\apps\"
copy /y "bin\async_cancel.exe" "%DEST2%\apps\"
copy /y "bin\edit.exe" "%DEST%\apps\"
copy /y "bin\httpget.exe" "%DEST%\apps\"
copy /y "bin\tcpserve.exe" "%DEST%\apps\"
copy /y "bin\udp.exe" "%DEST%\apps\"
copy /y "bin\resolve.exe" "%DEST%\apps\"
copy /y "bin\ping.exe" "%DEST%\apps\"
copy /y "bin\doom.exe" "%DEST%\apps\"
copy /y "bin\video.exe" "%DEST%\apps\"
copy /y "%SRC%\boot.ini" "%DEST%\"
copy /y "%DRIVERS%\drivers.ini" "%DEST%\drivers\"
if exist "%USER%\apps\video\bink2w64.dll" copy /y "%USER%\apps\video\bink2w64.dll" "%DEST%\apps\"
if exist "%USER%\apps\video\video.bk2" copy /y "%USER%\apps\video\video.bk2" "%DEST%\apps\"
if exist "%USER%\apps\doom\doom1.wad" copy /y "%USER%\apps\doom\doom1.wad" "%DEST%\apps\"
:: ---- Unmount disk image ----
echo Unmounting disk.vhd...
set DPS=%TEMP%\ntlite_umnt_%RANDOM%.txt
(
echo select vdisk file="%VHD%"
echo detach vdisk
echo exit
) > "%DPS%"
diskpart /s "%DPS%"
del "%DPS%"
echo.
echo Build complete.
:: Run the build system, passing any args along
"code\build\build.exe" %*
+217
View File
@@ -0,0 +1,217 @@
#define NOB_IMPLEMENTATION
#include "nob.h"
// Replicate your compiler and linker flags
const char *CFLAGS = "/nologo /W3 /WX /Od /GS- /Gs999999 /Gz /Gy /EHsc- /GR- /Oi /Z7 /std:c17 /D_CRT_SECURE_NO_WARNINGS /D_CRT_NONSTDC_NO_WARNINGS /Icode\\public /Icode\\common\\include /Icode\\kernel\\include";
const char *LWIP_CFLAGS = "/nologo /W3 /Od /GS- /Gs999999 /Gz /Gy /EHsc- /GR- /Oi /Z7 /std:c17 /D_CRT_SECURE_NO_WARNINGS /D_CRT_NONSTDC_NO_WARNINGS /Icode\\public /Icode\\common\\include /Icode\\kernel\\include /Icode\\drivers\\net\\lwip\\include /Icode\\third_party\\lwip\\src\\include /wd4005 /wd4100 /wd4103 /wd4127 /wd4244 /wd4267 /wd4706";
const char *LFLAGS = "/nologo /NODEFAULTLIB /DEBUG";
void create_layout() {
const char *dirs[] = {
"obj", "bin", "obj\\boot", "obj\\kernel", "obj\\lwip", "obj\\hal",
"obj\\syscall", "obj\\win32", "obj\\posix", "obj\\drivers", "obj\\init",
"obj\\shell_win32", "obj\\shell_posix", "obj\\shell_native",
"obj\\async_apc", "obj\\async_cancel", "obj\\edit", "obj\\httpget",
"obj\\tcpserve", "obj\\udp", "obj\\resolve", "obj\\ping", "obj\\doom", "obj\\video"
};
for (size_t i = 0; i < NOB_ARRAY_LEN(dirs); i++) nob_mkdir_if_not_exists(dirs[i]);
}
// Helper to run a shell command string and wait for it
bool run_sync(const char *cmd_str) {
Nob_Cmd cmd = {0};
nob_cmd_append(&cmd, "cmd.exe", "/c", cmd_str);
bool ok = nob_cmd_run_sync(cmd);
nob_cmd_free(cmd);
return ok;
}
// Helper to launch a shell command into the background
Nob_Proc run_async(const char *cmd_str) {
Nob_Cmd cmd = {0};
nob_cmd_append(&cmd, "cmd.exe", "/c", cmd_str);
Nob_Proc proc = nob_cmd_run_async(cmd);
nob_cmd_free(cmd);
return proc;
}
int main(int argc, char **argv) {
// Magic macro: Checks if build.c is newer than build.exe and recompiles itself if so
NOB_GO_REBUILD_URSELF(argc, argv);
// 1. Initial Checks & Setup
if (!nob_file_exists("disk.vhd")) {
nob_log(NOB_INFO, "disk.vhd missing, calling mkimage.bat...");
if (!run_sync("mkimage.bat")) return 1;
}
create_layout();
// 2. Sequential Phase (Bootloader, Core Kernel, and DLLs)
nob_log(NOB_INFO, "--- Building Core Subsystems ---");
const char *core_tasks[] = {
"ml64 /nologo /c /Foobj\\kernel\\ke_switch.obj code\\kernel\\ke_switch.asm",
"ml64 /nologo /c /Foobj\\kernel\\ke_syscall_asm.obj code\\kernel\\ke_syscall.asm",
"ml64 /nologo /c /Foobj\\kernel\\ke_gdt_reload.obj code\\kernel\\ke_gdt_reload.asm",
"ml64 /nologo /c /Foobj\\syscall\\stubs.obj code\\user\\syscall\\syscall_stubs.asm",
"for %f in (code\\boot\\uefi\\*.asm) do ml64 /nologo /c /Fo\"obj\\boot\\%~nf.obj\" \"%f\"",
nob_temp_sprintf("cl %s /MP /c /Foobj\\ code\\common\\printf.c code\\common\\ini_parser.c", CFLAGS),
"cl /nologo /c /Foobj\\libc.obj code\\common\\libc.c",
// Bootloader
nob_temp_sprintf("cl %s /MP /c /Icode\\boot\\uefi\\include /Foobj\\boot\\ code\\boot\\uefi\\*.c && link %s /SUBSYSTEM:EFI_APPLICATION /ENTRY:UefiMain /OUT:bin\\bootx64.efi code\\boot\\uefi\\efilib.lib obj\\ini_parser.obj obj\\libc.obj obj\\boot\\*.obj", CFLAGS, LFLAGS),
// HAL
nob_temp_sprintf("cl %s /MP /c /Foobj\\hal\\ code\\kernel\\hal\\*.c && link %s /DLL /OUT:bin\\hal.dll /ENTRY:HalInitialize /IGNORE:4216 obj\\printf.obj obj\\libc.obj obj\\hal\\*.obj", CFLAGS, LFLAGS),
// Kernel
nob_temp_sprintf("cl %s /MP /c /Foobj\\kernel\\ code\\kernel\\*.c && link %s /SUBSYSTEM:NATIVE /ENTRY:KernelMain /OUT:bin\\kernel.exe bin\\hal.lib obj\\ini_parser.obj obj\\printf.obj obj\\libc.obj obj\\kernel\\*.obj", CFLAGS, LFLAGS),
// Subsystem DLLs
"link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL /OUT:bin\\syscall.dll obj\\syscall\\stubs.obj",
nob_temp_sprintf("cl %s /MP /c /Foobj\\win32\\ code\\user\\personalities\\win32\\*.c && link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL /OUT:bin\\win32.dll bin\\syscall.lib obj\\libc.obj obj\\win32\\*.obj", CFLAGS),
nob_temp_sprintf("cl %s /MP /c /Foobj\\posix\\ code\\user\\personalities\\posix\\*.c && link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL /OUT:bin\\posix.dll bin\\syscall.lib obj\\libc.obj obj\\posix\\*.obj", CFLAGS)
};
for (size_t i = 0; i < NOB_ARRAY_LEN(core_tasks); i++) {
if (!run_sync(core_tasks[i])) return 1;
}
// 3. Parallel Phase (Drivers and Applications)
nob_log(NOB_INFO, "--- Compiling Drivers and Apps in Parallel ---");
Nob_Procs procs = {0};
// Queue standalone Drivers
const char *drivers[][2] = {
{"ide", "storage\\ide"},
{"ahci", "storage\\ahci"},
{"fat32", "fs\\fat32"},
{"usb", "bus\\usb"},
{"rtl816x", "net\\rtl816x"},
{"rtl8139", "net\\rtl8139"}
};
for (size_t i = 0; i < NOB_ARRAY_LEN(drivers); i++) {
const char *name = drivers[i][0];
const char *path = drivers[i][1];
const char *cmd = nob_temp_sprintf(
"cl %s /c /Foobj\\drivers\\%s.obj code\\drivers\\%s\\%s.c && link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL /OUT:bin\\%s.sys /ENTRY:DriverEntry bin\\hal.lib bin\\kernel.lib obj\\libc.obj obj\\drivers\\%s.obj",
CFLAGS, name, path, name, name, name
);
nob_da_append(&procs, run_async(cmd));
}
// Parse lwIP Sources and Queue it
Nob_String_Builder sb = {0}, lwip_files = {0};
if (nob_read_entire_file("code\\drivers\\net\\lwip\\lwip_sources.txt", &sb)) {
Nob_String_View sv = nob_sv_from_parts(sb.items, sb.count);
while (sv.count > 0) {
Nob_String_View line = nob_sv_trim(nob_sv_chop_by_delim(&sv, '\n'));
if (line.count > 0 && line.data[0] != '#') {
nob_sb_append_cstr(&lwip_files, "code\\");
for (size_t i = 0; i < line.count; i++) nob_sb_append_buf(&lwip_files, &(char){line.data[i] == '/' ? '\\' : line.data[i]}, 1);
nob_sb_append_cstr(&lwip_files, " ");
}
}
nob_sb_append_null(&lwip_files);
nob_da_append(&procs, run_async(nob_temp_sprintf("cl %s /MP /c /Foobj\\lwip\\ %s && link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL /OUT:bin\\lwip.sys /ENTRY:DriverEntry bin\\hal.lib bin\\kernel.lib obj\\libc.obj obj\\lwip\\*.obj", LWIP_CFLAGS, lwip_files.items)));
}
// Queue Subsystem Applications
const char *apps[][4] = {
// Folder, Libs, Name, Optional Extra Link Args
{"system\\init", "bin\\syscall.lib obj\\libc.obj", "init", "/ENTRY:_start"},
{"apps\\shell_win32", "bin\\win32.lib obj\\libc.obj", "shell_win32", "/ENTRY:main"},
{"apps\\shell_posix", "bin\\posix.lib obj\\libc.obj", "shell_posix", "/ENTRY:main"},
{"apps\\shell_native", "bin\\syscall.lib obj\\libc.obj", "shell_native", "/ENTRY:main"},
{"tests\\async_apc", "bin\\syscall.lib obj\\libc.obj", "async_apc", "/ENTRY:main"},
{"tests\\async_cancel", "bin\\syscall.lib obj\\libc.obj", "async_cancel", "/ENTRY:main"},
{"apps\\edit", "bin\\syscall.lib obj\\libc.obj", "edit", "/ENTRY:main"},
{"apps\\httpget", "bin\\syscall.lib obj\\libc.obj", "httpget", "/ENTRY:main"},
{"apps\\tcpserve", "bin\\syscall.lib obj\\libc.obj", "tcpserve", "/ENTRY:main"},
{"apps\\udp", "bin\\syscall.lib obj\\libc.obj", "udp", "/ENTRY:main"},
{"apps\\resolve", "bin\\syscall.lib obj\\libc.obj", "resolve", "/ENTRY:main"},
{"apps\\ping", "bin\\syscall.lib obj\\libc.obj", "ping", "/ENTRY:main"},
{"apps\\doom", "bin\\syscall.lib obj\\libc.obj", "doom", "/ENTRY:main"},
{"apps\\video", "bin\\win32.lib obj\\libc.obj code\\user\\apps\\video\\bink2w64.lib", "video", "/ENTRY:main"}
};
for (size_t i = 0; i < NOB_ARRAY_LEN(apps); i++) {
const char *cmd = nob_temp_sprintf(
"cl %s /MP /c /Foobj\\%s\\ code\\user\\%s\\*.c && link %s /SUBSYSTEM:NATIVE %s /OUT:bin\\%s.exe /PDB:bin\\%s.pdb %s obj\\%s\\*.obj",
CFLAGS, apps[i][2], apps[i][0], LFLAGS, apps[i][3], apps[i][2], apps[i][2], apps[i][1], apps[i][2]
);
nob_da_append(&procs, run_async(cmd));
}
// Wait for everything to link simultaneously
if (!nob_procs_wait(procs)) {
nob_log(NOB_ERROR, "One or more parallel build jobs failed!");
return 1;
}
// 4. Mounting & Packing Image
nob_log(NOB_INFO, "--- Mounting disk.vhd ---");
// Resolve the absolute path to disk.vhd for diskpart
char vhd_path[MAX_PATH];
GetFullPathNameA("disk.vhd", MAX_PATH, vhd_path, NULL);
const char *diskpart_mnt = nob_temp_sprintf(
"select vdisk file=\"%s\"\nattach vdisk\n"
"select partition 1\nformat fs=fat32 quick\nassign letter=Z\n"
"select partition 2\nformat fs=fat32 quick\nassign letter=Y\nexit\n",
vhd_path
);
nob_write_entire_file("mnt.txt", diskpart_mnt, strlen(diskpart_mnt));
if (!run_sync("diskpart /s mnt.txt")) return 1;
nob_log(NOB_INFO, "--- Assembling ESP ---");
_mkdir("Z:\\apps"); _mkdir("Y:\\apps");
_mkdir("Z:\\system"); _mkdir("Z:\\drivers");
_mkdir("Z:\\EFI"); _mkdir("Z:\\EFI\\BOOT");
const char *copies[][2] = {
{"bin\\bootx64.efi", "Z:\\EFI\\BOOT\\bootx64.efi"}, {"bin\\kernel.exe", "Z:\\system\\colonel.exe"},
{"bin\\hal.dll", "Z:\\system\\hal.dll"}, {"bin\\syscall.dll", "Z:\\system\\syscall.dll"},
{"bin\\win32.dll", "Z:\\system\\win32.dll"}, {"bin\\posix.dll", "Z:\\system\\posix.dll"},
{"code\\settings.ini", "Z:\\system\\settings.ini"}, {"bin\\init.exe", "Z:\\system\\init.exe"},
{"bin\\ide.sys", "Z:\\drivers\\ide.sys"}, {"bin\\ahci.sys", "Z:\\drivers\\ahci.sys"},
{"bin\\fat32.sys", "Z:\\drivers\\fat32.sys"}, {"bin\\lwip.sys", "Z:\\drivers\\lwip.sys"},
{"bin\\usb.sys", "Z:\\drivers\\usb.sys"}, {"bin\\rtl816x.sys", "Z:\\drivers\\rtl816x.sys"},
{"bin\\rtl8139.sys", "Z:\\drivers\\rtl8139.sys"}, {"code\\drivers\\drivers.ini", "Z:\\drivers\\drivers.ini"},
{"code\\boot.ini", "Z:\\boot.ini"},
{"bin\\shell_win32.exe", "Z:\\apps\\shell_win32.exe"}, {"bin\\shell_posix.exe", "Z:\\apps\\shell_posix.exe"},
{"bin\\shell_native.exe", "Z:\\apps\\shell_native.exe"}, {"bin\\edit.exe", "Z:\\apps\\edit.exe"},
{"bin\\httpget.exe", "Z:\\apps\\httpget.exe"}, {"bin\\tcpserve.exe", "Z:\\apps\\tcpserve.exe"},
{"bin\\udp.exe", "Z:\\apps\\udp.exe"}, {"bin\\resolve.exe", "Z:\\apps\\resolve.exe"},
{"bin\\ping.exe", "Z:\\apps\\ping.exe"}, {"bin\\doom.exe", "Z:\\apps\\doom.exe"},
{"bin\\video.exe", "Z:\\apps\\video.exe"},
{"bin\\async_apc.exe", "Y:\\apps\\async_apc.exe"}, {"bin\\async_cancel.exe", "Y:\\apps\\async_cancel.exe"}
};
for (size_t i = 0; i < NOB_ARRAY_LEN(copies); i++) nob_copy_file(copies[i][0], copies[i][1]);
if (nob_file_exists("code\\user\\apps\\video\\bink2w64.dll")) nob_copy_file("code\\user\\apps\\video\\bink2w64.dll", "Z:\\apps\\bink2w64.dll");
if (nob_file_exists("code\\user\\apps\\video\\video.bk2")) nob_copy_file("code\\user\\apps\\video\\video.bk2", "Z:\\apps\\video.bk2");
if (nob_file_exists("code\\user\\apps\\doom\\doom1.wad")) nob_copy_file("code\\user\\apps\\doom\\doom1.wad", "Z:\\apps\\doom1.wad");
nob_log(NOB_INFO, "--- Unmounting disk.vhd ---");
const char *diskpart_umnt = nob_temp_sprintf(
"select vdisk file=\"%s\"\ndetach vdisk\nexit\n",
vhd_path
);
nob_write_entire_file("umnt.txt", diskpart_umnt, strlen(diskpart_umnt));
run_sync("diskpart /s umnt.txt");
remove("mnt.txt");
remove("umnt.txt");
nob_log(NOB_INFO, "Build complete!");
return 0;
}
+3286
View File
File diff suppressed because it is too large. Load diff