Determine the build target automatically
This commit is contained in:
		
							
								
								
									
										3
									
								
								TODO
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								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). | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user