Import('env') ### Kernel kernel_env = env.Clone() kernel_env['AS'] = 'x86_64-elf-as' kernel_env['CC'] = 'x86_64-elf-gcc' kernel_env['CXX'] = 'x86_64-elf-g++' kernel_env['LD'] = 'x86_64-elf-g++' kernel_env.Append(CFLAGS = ['-ffreestanding']) kernel_env.Append(CPPDEFINES = ['__baos_kernel_source__=1']) kernel_env.Append(CXXFLAGS = ['-ffreestanding', '-fno-exceptions', '-fno-rtti', '-std=c++20']) kernel_env.Append(LINKFLAGS = ['-T', kernel_env.File('linker.ld').abspath, '-ffreestanding', '-nostdlib', '-mcmodel=large', '-mno-red-zone', '-mno-mmx', '-mno-sse', '-mno-sse2']) kernel_env.Append(CPPPATH = ['#targets/_any/include', '#targets/_any/bastl/include', 'include', '/usr/include/efi', '#targets/_any/kernel/include', '#targets/_any/stdlib/include']) def get_crt_object(name: str) -> str: import subprocess cmd = [kernel_env['CXX']] cmd.extend(kernel_env['CXXFLAGS']) cmd.append(f'-print-file-name={name}') try: result = subprocess.run(cmd, stdout=subprocess.PIPE) return result.stdout.decode('utf-8').strip() except: return "XXX_COULD_NOT_BE_DETERMINED_XXX" # TODO: better error handling? crtbegin_o = get_crt_object('crtbegin.o') crtend_o = get_crt_object('crtend.o') crti_o = kernel_env.Object(kernel_env['CRTI_PATH']) crtn_o = kernel_env.Object(kernel_env['CRTN_PATH']) kernel_env['LINKCOM'] = env['LINKCOM'].replace('$_LIBFLAGS', f'{crti_o[0].abspath} {crtbegin_o} -Wl,--start-group $_LIBFLAGS -Wl,--end-group -lgcc {crtend_o} {crtn_o[0].abspath}') kernel_isr_sources = env['KERNEL_ISR_SOURCES'] + Split(''' ''') kernel_sources = env['KERNEL_SOURCES'] + Split(''' src/kernel/boot.s src/kernel/startup.cpp ''') + [kernel_env.Object(f, CCFLAGS = kernel_env['CCFLAGS'] + ['-mgeneral-regs-only']) for f in kernel_isr_sources] kernel_target = kernel_env.File('#kernel.x86_64.bin') prog_kernel = kernel_env.Program( target = kernel_target, source = kernel_sources ) kernel_env.Depends(prog_kernel, [crti_o, crtn_o] + kernel_sources) x86_64_iso_files = [ { "source": env.File("boot/grub.cfg"), "target": "boot/grub/grub.cfg" }, { "source": env.File("#os.bin"), "target": "boot/os.bin" }, { "source": env.File("#loader.bin"), "target": "boot/loader.bin" } ] ### UEFI Loader uefi_env = env.Clone() uefi_env['AS'] = 'x86_64-w64-mingw32-as' uefi_env['CC'] = 'x86_64-w64-mingw32-gcc' uefi_env['CXX'] = 'x86_64-w64-mingw32-g++' uefi_env['LD'] = 'x86_64-w64-mingw32-g++' uefi_env.Append(CFLAGS = ['-ffreestanding']) uefi_env.Append(CXXFLAGS = ['-ffreestanding', '-fno-exceptions', '-fno-rtti', '-std=c++20']) uefi_env.Append(LINKFLAGS = ['-nostdlib', '-Wl,-dll', '-shared', '-Wl,--subsystem,10', '-e', 'efi_main']) uefi_env.Append(CPPPATH = ['/usr/include/efi', 'include']) loader_sources = Split(''' src/loader/main.cpp src/loader/miniprintf.cpp ''') loader_target = uefi_env.File('#loader.x86_64.efi') prog_loader = uefi_env.Program( target = loader_target, source = loader_sources ) ### Bootable Image def runcmd(*args, **kwargs): from subprocess import run run(*args, **kwargs, check=True) def build_img(target, source, env): fatfile = target[0].abspath runcmd(['dd', 'if=/dev/zero', f'of={fatfile}', 'bs=1K', 'count=1440']) runcmd(['mformat', '-i', fatfile, '-f', '1440', '::']) runcmd(['mmd', '-i', fatfile, '::/EFI']) runcmd(['mmd', '-i', fatfile, '::/EFI/BOOT']) runcmd(['mcopy', '-i', fatfile, loader_target.abspath, '::/EFI/BOOT/BOOTX64.EFI']) runcmd(['mcopy', '-i', fatfile, kernel_target.abspath, '::/kernel.bin']) img_target = env.File('#boot.x86_64.fat.img') cmd_image = env.Command( target = img_target, source = [prog_kernel, prog_loader], action = build_img ) def build_iso(target, source, env): import os import shutil isofile = target[0].abspath # prepare the staging folder staging_dir = env.Dir('#staging/x86_64_iso').abspath shutil.rmtree(staging_dir, ignore_errors=True) os.makedirs(staging_dir) # copy files to the staging folder shutil.copy(img_target.abspath, os.path.join(staging_dir, 'fat.img')) runcmd(['xorriso', '-as', 'mkisofs', '-R', '-f', '-e', 'fat.img', '-no-emul-boot', '-o', target[0].abspath, staging_dir]) iso_target = env.File('#system.x86_64.iso') cmd_iso = env.Command( target = iso_target, source = [cmd_image], action = build_iso ) alias_os = env.Alias('os', [cmd_iso]) env.Default(alias_os) # finally update the environment env.Append(ISO_FILES = x86_64_iso_files) Return('env')