Building Dreamcast programs With GCC spec files
In the KallistiOS ecosystem, there are basically two ways to build
Dreamcast programs - use the CMake toolchain support, or use the compiler
wrapper scripts from the KallistiOS source tree. I was interested in the
latter, but they end up depending on a large number of environment variables,
which are traditionally sourced through $KOS_BASE/environ.sh
. Although it’s
not really a big issue to have all those environment variables, I wondered
whether there was a cleaner approach.
GCC has a spec file feature, which is a custom DSL that describes how the compiler driver should process flags for the various programs in the compilation toolchain. Since the KallistiOS compiler wrappers are basically injecting compiler flags, spec files seemed like a promising approach.
It turns out that this approach works pretty nicely, and we only need to depend
on the single $KOS_BASE
environment variable being set. I’m pretty naive
about GCC internals, but the spec file below worked for me.
*kos_header_paths:
-isystem %:getenv(KOS_BASE /include) -isystem %:getenv(KOS_BASE /kernel/arch/dreamcast/include) -isystem %:getenv(KOS_BASE /addons/include)
*kos_library_paths:
-L%:getenv(KOS_BASE /lib/dreamcast) -L%:getenv(KOS_BASE /addons/lib/dreamcast)
*kos_linker_script:
-T%:getenv(KOS_BASE /utils/ldscripts/shlelf.xc)
*kos_libs:
--start-group -lkallisti -lc %G --end-group
*kos_defines:
-D_arch_dreamcast
*kos_cc_options:
-ffunction-sections -fdata-sections -fno-builtin
*cc1_options:
+ %(kos_header_paths) %(kos_defines) %(kos_cc_options)
*cc1plus_options:
+ %(kos_header_paths) %(kos_defines) %(kos_cc_options)
*cpp_options:
+ %(kos_header_paths) %(kos_defines)
*subtarget_link_spec:
%(kos_linker_script) -Ttext=0x8c010000 --gc-sections
*link_gcc_c_sequence:
%(kos_library_paths) %(kos_libs)
I think that this makes it a lot simpler to build Dreamcast programs. In the trivial case, it can be as easy as this:
$ /usr/local/Cellar/dc-toolchain-testing/2023.05.19/sh-elf/bin/sh-elf-g++ -specs=kos-dreamcast.specs -o hello.elf hello.cpp
$ file hello.elf
hello.elf: ELF 32-bit LSB executable, Renesas SH, version 1 (SYSV), statically linked, with debug_info, not stripped
The final benefit is that this is easy to use in any old build system. You
just have to add the -specs
flag to your compiler flags, in what ever
way the build system supports.