// TODO Merge util/build.c into here. str options #option; str target #option; void Setup(bool forAutomation) { SystemShellEnableLogging(false); assert PathCreateLeadingDirectories("bin/dependency_files"); assert PathCreateLeadingDirectories("bin/Logs"); assert PathCreateLeadingDirectories("bin/generated_code"); assert PathCreateLeadingDirectories("bin/cache"); assert PathCreateLeadingDirectories("bin/Object Files"); if SystemGetHostName() == "Cygwin" { LogError("Building on Cygwin is not supported. Use the Windows Subsystem for Linux instead."); assert false; } if SystemShellEvaluate("shasum -a 256 util/test.txt") != "2c5622dbbf2552e0e66424a302bde0918e09379afce47eef1a21ef0198990fed util/test.txt\n" { Log(TextColorError() + "--------------------------------------------------------------------"); Log(TextColorError() + " The source has been corrupted!! "); Log(TextColorError() + " Please check that you have disabled any automatic line-ending or "); Log(TextColorError() + " encoding conversions in Git and archive extraction tools you use. "); Log(TextColorError() + "--------------------------------------------------------------------"); assert false; } if StringContains(PathGetDefaultPrefix(), " ") { LogError("The path to your essence directory, '%PathGetDefaultPrefix()%', contains spaces."); assert false; } if !SystemShellExecute("which gcc > /dev/null") { LogError("GCC was not found."); assert false; } if !SystemShellExecute("which nasm > /dev/null") { LogError("Nasm was not found."); assert false; } if !SystemShellExecute("which make > /dev/null") { LogError("Make was not found."); assert false; } if target == "" { target = "TARGET_X86_64"; } assert SystemShellExecute("gcc -o bin/build -g util/build.c -pthread -DPARALLEL_BUILD -D%target% " + "-Wall -Wextra -Wno-missing-field-initializers"); if forAutomation { assert FileWriteAll("bin/build_config.ini", "accepted_license=1\nautomated_build=1\n"); assert SystemShellExecute("bin/build get-toolchain"); assert FileAppend("bin/build_config.ini", "\nautomated_build=1\n"); assert FileWriteAll("bin/commit.txt", StringSlice(StringSplitByCharacter(SystemShellEvaluate("git log"), "\n", true)[0], 8, 15)); } } void Start() { Setup(false); SystemShellExecute("bin/build %options%"); Log(""); } void GenerateOVF() { str[] template = StringSplitByCharacter(FileReadAll("util/automation/template.ovf"), "$", true); assert template:len() == 5; str uuid1 = UUIDGenerate(); str uuid2 = UUIDGenerate(); int driveSize = FileGetSize("bin/drive"); assert driveSize > 0; str result = template[0] + "%driveSize%" + template[1] + uuid1 + template[2] + uuid2 + template[3] + uuid1 + template[4]; assert FileWriteAll("bin/ova/Essence.ovf", result); } void DeleteUnneededDirectoriesForDebugInfo() { PathDeleteRecursively("cross"); PathDeleteRecursively("Essence"); PathDeleteRecursively("bin/ova"); PathDeleteRecursively("bin/cache"); PathDeleteRecursively("bin/freetype"); PathDeleteRecursively("bin/harfbuzz"); PathDeleteRecursively("bin/musl"); PathDeleteRecursively("bin/root/Applications/POSIX/lib"); PathDeleteRecursively(".git"); } void AutomationBuild() { // TODO: // Copy the source onto the drive for self hosting. // Producing installer images (including for real hardware). Setup(true); // Create directories. assert PathCreateLeadingDirectories("bin/ova"); assert PathCreateLeadingDirectories("root/Demo Content"); assert PathCreateLeadingDirectories("root/API Samples"); assert PathCreateLeadingDirectories("Essence/Licenses"); // Setup the config file. assert FileWriteAll("bin/config.ini", "Flag.DEBUG_BUILD=0\n" + "Flag.ENABLE_POSIX_SUBSYSTEM=1\n" + "General.wallpaper=0:/Demo Content/Abstract.jpg\n" + "General.window_color=5\n"); // Setup toolchain, build the system and ports. assert SystemShellExecute("bin/build build-optimised"); assert SystemShellExecute("bin/build build-optional-ports > /dev/null"); // Copy a few sample files. assert PathCopyRecursively("res/Sample Images", "root/Demo Content"); assert PathCopyRecursively("help", "root/Demo Content/Documentation"); assert FileCopy("bin/noodle.rom", "root/Demo Content/Noodle.uxn"); assert FileCopy("res/A Study in Scarlet.txt", "root/Demo Content/A Study in Scarlet.txt"); assert FileCopy("res/Theme Source.dat", "root/Demo Content/Theme.designer"); assert FileCopy("res/Flip.bochsrc", "root/Demo Content/Flip.bochsrc"); assert FileCopy("res/Flip.img", "root/Demo Content/Flip.img"); assert FileCopy("res/Teapot.obj", "root/Demo Content/Teapot.obj"); assert FileCopy("res/Fonts/Atkinson Hyperlegible Regular.ttf", "root/Demo Content/Atkinson Hyperlegible Regular.ttf"); // Copy API samples. assert SystemShellExecute("python util/automation/genapisamples.py"); // TODO Replace. // Enable extra applications and build them. assert FileWriteAll("bin/extra_applications.ini", "util/designer2.ini\n" + "util/build_core.ini\n" + "ports/uxn/emulator.ini\n" + "ports/bochs/bochs.ini\n" + "ports/mesa/obj_viewer.ini\n"); assert SystemShellExecute("bin/build build-optimised"); // Create a virtual machine file. assert SystemShellExecute("qemu-img convert -f raw bin/drive -O vmdk -o adapter_type=lsilogic,subformat=streamOptimized,compat6 " + "bin/ova/Essence-disk001.vmdk"); GenerateOVF(); assert SystemShellExecuteWithWorkingDirectory("bin/ova", "tar -cf Essence.ova Essence.ovf Essence-disk001.vmdk"); // Copy licenses. assert FileCopy("LICENSE.md", "Essence/Licenses/Essence License.txt"); assert FileCopy("util/nanosvg.h", "Essence/Licenses/nanosvg.h"); assert FileCopy("util/hsluv.h", "Essence/Licenses/hsluv.h"); assert FileCopy("util/stb_ds.h", "Essence/Licenses/stb_ds.h"); assert FileCopy("util/stb_truetype.h", "Essence/Licenses/stb_truetype.h"); assert FileCopy("res/Fonts/Hack License.md", "Essence/Licenses/Hack License.md"); assert FileCopy("res/Fonts/Inter License.txt", "Essence/Licenses/Inter License.txt"); assert FileCopy("res/Fonts/Atkinson Hyperlegible License.txt", "Essence/Licenses/Atkinson Hyperlegible License.txt"); assert FileCopy("res/Fonts/OpenDyslexic License.txt", "Essence/Licenses/OpenDyslexic License.txt"); assert FileCopy("res/elementary Icons License.txt", "Essence/Licenses/elementary Icons License.txt"); assert FileCopy("res/Sample Images/Licenses.txt", "Essence/Licenses/Sample Images.txt"); assert FileCopy("res/Keyboard Layouts/License.txt", "Essence/Licenses/Keyboard Layouts.txt"); assert FileCopy("ports/acpica/licensing.txt", "Essence/Licenses/ACPICA.txt"); assert FileCopy("ports/bochs/COPYING", "Essence/Licenses/Bochs.txt"); assert FileCopy("ports/efitoolkit/LICENSE", "Essence/Licenses/EFI.txt"); assert FileCopy("ports/freetype/FTL.TXT", "Essence/Licenses/FreeType.txt"); assert FileCopy("ports/harfbuzz/LICENSE", "Essence/Licenses/HarfBuzz.txt"); assert FileCopy("ports/md4c/LICENSE.md", "Essence/Licenses/Md4c.txt"); assert FileCopy("ports/musl/COPYRIGHT", "Essence/Licenses/Musl.txt"); assert FileCopy("ports/uxn/LICENSE", "Essence/Licenses/Uxn.txt"); assert FileCopy("bin/BusyBox License.txt", "Essence/Licenses/BusyBox.txt"); assert FileCopy("bin/Mesa License.html", "Essence/Licenses/Mesa.html"); assert FileCopy("bin/Nasm License.txt", "Essence/Licenses/Nasm.txt"); assert FileCopy("bin/GCC License.txt", "Essence/Licenses/GCC.txt"); assert FileCopy("bin/Binutils License.txt", "Essence/Licenses/Binutils.txt"); assert FileCopy("bin/GMP License.txt", "Essence/Licenses/GMP.txt"); assert FileCopy("bin/MPFR License.txt", "Essence/Licenses/GMPF.txt"); assert FileCopy("bin/MPC License.txt", "Essence/Licenses/MPC.txt"); assert FileCopy("bin/FFmpeg License/COPYING.GPLv2", "Essence/Licenses/FFmpeg GPLv2.txt"); assert FileCopy("bin/FFmpeg License/COPYING.GPLv3", "Essence/Licenses/FFmpeg GPLv3.txt"); assert FileCopy("bin/FFmpeg License/COPYING.LGPLv2.1", "Essence/Licenses/FFmpeg LGPLv2.1.txt"); assert FileCopy("bin/FFmpeg License/COPYING.LGPLv3", "Essence/Licenses/FFmpeg LGPLv3.txt"); assert FileCopy("bin/FFmpeg License/LICENSE.md", "Essence/Licenses/FFmpeg.md"); // Compress the result. assert PathMove("bin/ova/Essence.ova", "Essence/Essence.ova"); assert PathMove("bin/drive", "Essence/drive"); assert FileCopy("bin/commit.txt", "Essence/commit.txt"); assert SystemShellExecute("tar -cJf ../Essence.tar.xz Essence/"); // Compress the debug info. DeleteUnneededDirectoriesForDebugInfo(); assert SystemShellExecuteWithWorkingDirectory("..", "tar -cJf debug_info.tar.xz essence"); } void AutomationBuildDefault() { Setup(true); assert SystemShellExecute("bin/build build"); } void AutomationBuildMinimal() { Setup(true); assert FileWriteAll("bin/config.ini", "Flag.DEBUG_BUILD=0\n" + "BuildCore.NoImportPOSIX=1\n" + "BuildCore.RequiredFontsOnly=1\n" + "Emulator.PrimaryDriveMB=32\n" + "Dependency.ACPICA=0\n" + "Dependency.stb_image=0\n" + "Dependency.stb_image_write=0\n" + "Dependency.stb_sprintf=0\n" + "Dependency.FreeTypeAndHarfBuzz=0\n"); assert SystemShellExecute("bin/build build-optimised"); } void AutomationRunTests() { Setup(true); str[] buildConfig = StringSplitByCharacter(FileReadAll("bin/build_config.ini"), "\n", true); buildConfig:find_and_delete("automated_build=1"); assert FileWriteAll("bin/build_config.ini", StringJoin(buildConfig, "\n", false)); assert FileWriteAll("bin/config.ini", "Flag.ENABLE_POSIX_SUBSYSTEM=1\n"); assert FileWriteAll("bin/extra_applications.ini", "desktop/api_tests.ini\n"); assert SystemShellExecute("bin/build build"); assert SystemShellExecute("bin/build build-port busybox"); assert SystemShellExecute("bin/build run-tests"); DeleteUnneededDirectoriesForDebugInfo(); PathDelete("bin/drive"); }