diff --git a/TODO b/TODO index 2bc1002..b35e3f4 100644 --- a/TODO +++ b/TODO @@ -13,6 +13,3 @@ - Error message with an empty file wrongly says that a ")" is expected. - Support any expressions for constants. - Name analysis should fail if there are undefined symbols. - -# Toolchain -- Try to guess the build platform (x86_64-slackware-linux is hard coded). diff --git a/tools/index.js b/tools/index.js index 6460749..ee8c673 100644 --- a/tools/index.js +++ b/tools/index.js @@ -3,19 +3,44 @@ import path from 'node:path' import childProcess from 'node:child_process' import process from 'process' import os from 'os' +import { Buffer } from 'node:buffer' // Define constants. const tmp = path.resolve('./build/tools') const target = 'riscv32-unknown-linux-gnu' -const build = 'x86_64-slackware-linux' const baseDirectory = path.resolve('./tools') const busyboxVersion = '1.36.1' const kernelVersion = '5.15.158' -const gccVersion = '13.2.0' +const gccVersion = '14.1.0' const binutilsVersion = '2.42' const glibcVersion = '2.39' +function findBuildTarget () { + const env = { + LANG: 'en_US.UTF-8' + } + const gccV = childProcess.spawn('gcc', ['--verbose'], { stdio: ['ignore', 'ignore', 'pipe'], env }) + const buffers = [] + + gccV.stderr.on('data', function (data) { + buffers.push(data) + }) + + + return new Promise(function (resolve, reject) { + gccV.on('exit', function () { + const [_, target] = Buffer.concat(buffers) + .toString() + .split('\n') + .find(line => line.startsWith('Target: ')) + .split(' ') + + resolve(target) + }) + }) +} + function createImage (rootfs) { const rootExt4 = path.join(tmp, 'rootfs.ext4') @@ -112,7 +137,7 @@ async function buildInit (sysroot) { childProcess.execFileSync('riscv32-unknown-linux-gnu-g++', compilerArguments, { stdio: 'inherit', env }) } -async function buildGlibc (sysroot, rootfs) { +async function buildGlibc (sysroot, rootfs, options) { const sourceDirectory = await downloadAndUnarchive( new URL(`https://ftp.gnu.org/gnu/glibc/glibc-${glibcVersion}.tar.xz`) ) @@ -120,7 +145,7 @@ async function buildGlibc (sysroot, rootfs) { '--prefix=/usr', '--libdir=/usr/lib', `--host=${target}`, - `--build=${build}`, + `--build=${options.build}`, `--enable-kernel=${kernelVersion}`, `--with-headers=${path.join(rootfs, 'usr/include')}`, '--disable-nscd' @@ -166,9 +191,9 @@ async function buildCrossBinutils (sysroot) { return sourceDirectory } -async function buildGCC1 (sysroot, rootfs) { +async function buildGCC1 (sysroot, rootfs, options) { const sourceDirectory = await downloadAndUnarchive( - new URL(`https://download.dlackware.com/slackware/slackware64-current/source/d/gcc/gcc-${gccVersion}.tar.xz`) + new URL(`https://gcc.gnu.org/pub/gcc/releases/gcc-${gccVersion}/gcc-${gccVersion}.tar.xz`) ) const cwd = path.join(path.dirname(sourceDirectory), 'build-gcc'); await fs.mkdir(cwd) @@ -201,8 +226,8 @@ async function buildGCC1 (sysroot, rootfs) { '--with-newlib', '--without-headers', `--target=${target}`, - `--build=${build}`, - `--host=${build}` + `--build=${options.build}`, + `--host=${options.build}` ] const flags = '-O2 -fPIC' const env = { @@ -222,14 +247,14 @@ async function buildGCC1 (sysroot, rootfs) { return sourceDirectory } -async function buildBinutils (sourceDirectory, sysroot, rootfs) { +async function buildBinutils (sourceDirectory, sysroot, rootfs, options) { const cwd = path.join(path.dirname(sourceDirectory), 'build-binutils'); await fs.rm(cwd, { recursive: true, force: true }) await fs.mkdir(cwd) const configureOptions = [ '--prefix=/usr', - `--build=${build}`, + `--build=${options.build}`, `--host=${target}`, `--with-build-sysroot=${rootfs}`, '--disable-nls', @@ -253,7 +278,7 @@ async function buildBinutils (sourceDirectory, sysroot, rootfs) { return sourceDirectory } -async function buildGCC2 (sourceDirectory, sysroot, rootfs) { +async function buildGCC2 (sourceDirectory, sysroot, rootfs, options) { const cwd = path.join(path.dirname(sourceDirectory), 'build-gcc'); await fs.rm(cwd, { recursive: true, force: true }) await fs.mkdir(cwd) @@ -276,8 +301,8 @@ async function buildGCC2 (sourceDirectory, sysroot, rootfs) { '--with-default-libstdcxx-abi=new', '--disable-nls', `--target=${target}`, - `--build=${build}`, - `--host=${build}` + `--build=${options.build}`, + `--host=${options.build}` ] const flags = '-O2 -fPIC' const env = { @@ -295,7 +320,7 @@ async function buildGCC2 (sourceDirectory, sysroot, rootfs) { childProcess.execFileSync('make', ['install'], { stdio: 'inherit', env, cwd }) } -async function buildGCC3 (sourceDirectory, sysroot, rootfs) { +async function buildGCC3 (sourceDirectory, sysroot, rootfs, options) { const cwd = path.join(path.dirname(sourceDirectory), 'build-gcc'); await fs.rm(cwd, { recursive: true, force: true }) await fs.mkdir(cwd) @@ -318,7 +343,7 @@ async function buildGCC3 (sourceDirectory, sysroot, rootfs) { '--with-default-libstdcxx-abi=new', '--disable-nls', `--target=${target}`, - `--build=${build}`, + `--build=${options.build}`, `--host=${target}` ] const flags = '-O2 -fPIC' @@ -351,23 +376,27 @@ async function createRoot (rootfs) { const sysroot = path.join(tmp, 'sysroot') const rootfs = path.join(tmp, 'rootfs') +const options = { + build: await findBuildTarget() +} + for (const targetDirectory of [tmp, sysroot, rootfs]) { await fs.rm(targetDirectory, { recursive: true, force: true }) await fs.mkdir(targetDirectory) } const binutilsSource = await buildCrossBinutils(sysroot) -const gccSource = await buildGCC1(sysroot, rootfs) +const gccSource = await buildGCC1(sysroot, rootfs, options) const kernelImage = await buildKernel(sysroot, rootfs) -await buildGlibc(sysroot, rootfs) -await buildBinutils(binutilsSource, sysroot, rootfs) -await buildGCC2(gccSource, sysroot, rootfs) +await buildGlibc(sysroot, rootfs, options) +await buildBinutils(binutilsSource, sysroot, rootfs, options) +await buildGCC2(gccSource, sysroot, rootfs, options) buildInit (sysroot) await buildBusyBox(sysroot, rootfs) await createRoot(rootfs) -await buildGCC3(gccSource, sysroot, rootfs) +await buildGCC3(gccSource, sysroot, rootfs, options) createImage(rootfs) console.log(kernelImage)