From 03ed4ebbab6ef92cce4d80e42d21fbdeacd21b3c Mon Sep 17 00:00:00 2001 From: chacha Date: Fri, 27 Mar 2026 23:11:33 +0100 Subject: [PATCH] start v2 --- .gitignore | 35 + .vscode/launch.json | 38 + .vscode/python.env | 2 + .vscode/settings.json | 6 + .vscode/tasks.json | 100 + Dockerfile | 225 --- Jenkinsfile | 385 ++-- LICENSE.md | 675 ------- README.md | 49 +- .../glide.ref => artifacts/bases/.gitkeep | 0 .../icons.ref => artifacts/features/.gitkeep | 0 .../ut99.ref => artifacts/profiles/.gitkeep | 0 .../chroot/README-common-base.txt | 1 + bases/retrodebian-common/entry.py | 37 + bases/retrodebian-common/entry.sh | 2 + bases/retrodebian-common/generate.sh | 8 + .../hooks/05-common-base.sh | 2 + .../packageslists/common-base.list | 2 + .../voodoo2/chroot/etc/retrodebian-base.conf | 1 + bases/voodoo2/entry.py | 54 + bases/voodoo2/entry.sh | 17 + bases/voodoo2/generate.sh | 7 + bases/voodoo2/hooks/10-sample-base.sh | 4 + .../voodoo2/packages/sample-base_1.0_all.deb | 1 + bases/voodoo2/packageslists/sample-base.list | 1 + builder/bash/common.sh | 34 + builder/bash/run_entry.sh | 18 + builder/bash/run_generate.sh | 16 + builder/bash/run_profile_build.sh | 22 + builder/bash/run_profile_config.sh | 21 + builder/py/build.py | 388 ++++ builder/py/retrobuilder/__init__.py | 9 + builder/py/retrobuilder/context.py | 80 + builder/py/retrobuilder/entrypoints.py | 57 + builder/py/retrobuilder/envfile.py | 16 + builder/py/retrobuilder/loader.py | 81 + builder/py/retrobuilder/model.py | 100 + builder/py/retrobuilder/operations.py | 115 ++ builder/py/retrobuilder/paths.py | 35 + buildglidepkg.sh | 149 -- config-kernel | 1713 ----------------- deps/theme-AdwaitaDark.tar | Bin 28663 -> 0 bytes desktop | 70 - editions/voodoo2/splash-source.png | Bin 706048 -> 0 bytes .../usr/share/retrodebian/sample-feature.txt | 1 + features/sample-feature/entry.py | 54 + features/sample-feature/entry.sh | 17 + features/sample-feature/generate.sh | 7 + .../sample-feature/hooks/20-sample-feature.sh | 4 + .../packages/sample-feature_1.0_all.deb | 1 + .../packageslists/sample-feature.list | 1 + games/ut99/ut | 297 --- games/ut99/ut-install-436.run | Bin 6225010 -> 0 bytes .../etc/apt/sources.list.d/etch-backport.list | 1 - internal/rootfs/etc/environment | 18 - .../etc/init.d/retrodebian-fluxbox-watch-menu | 34 - .../etc/init.d/retrodebian-xorg-autoconfig | 34 - internal/rootfs/etc/ld.so.conf.d/99local.conf | 1 - internal/rootfs/etc/skel/.Xresources | 27 - internal/rootfs/etc/skel/.bash_profile | 3 - internal/rootfs/etc/skel/.bashrc | 14 - internal/rootfs/etc/skel/.fluxbox/init | 10 - internal/rootfs/etc/skel/.fluxbox/keys | 94 - internal/rootfs/etc/skel/.fluxbox/startup | 13 - internal/rootfs/etc/skel/.gtkrc-2.0 | 30 - internal/rootfs/etc/skel/.ideskrc | 38 - internal/rootfs/etc/skel/.idesktop/Files.lnk | 10 - .../rootfs/etc/skel/.idesktop/TaskManager.lnk | 10 - .../rootfs/etc/skel/.idesktop/Terminal.lnk | 10 - .../rootfs/etc/skel/.idesktop/TextEdit.lnk | 10 - internal/rootfs/etc/skel/.idesktop/UT99.lnk | 10 - .../etc/skel/.idesktop/V2TMUMemTester.lnk | 10 - internal/rootfs/etc/skel/.pcmanfm/mime_info | 36 - internal/rootfs/etc/skel/.profile | 4 - internal/rootfs/etc/skel/.xinitrc | 15 - internal/rootfs/etc/skel/.xscreensaver | 328 ---- .../rootfs/etc/udev/rules.d/z99_3dfx.rules | 1 - .../rootfs/opt/retrodebian/bin/set-resolution | 21 - .../fluxbox/retrodebian-menu.section | 26 - .../opt/retrodebian/fluxbox/update-menu.sh | 42 - .../opt/retrodebian/fluxbox/watch-menu.sh | 13 - .../rootfs/opt/retrodebian/xorg/autoconfig.sh | 128 -- .../01000-mouse-qemu-tablet.sh.disabled | 33 - .../xorg/mouse-detect.d/02000-mouse-wacom.sh | 33 - .../mouse-detect.d/03000-mouse-synaptics.sh | 33 - .../09900-mouse-proc-handler.sh | 33 - .../mouse-detect.d/99999-mouse-fallback.sh | 18 - .../xorg/video-detect.d/01000-i810.sh | 23 - .../xorg/video-detect.d/01050-i740.sh | 23 - .../01100-3dfx-banshee-voodoo345.sh | 26 - .../video-detect.d/02000-nvidia-generic.sh | 18 - .../xorg/video-detect.d/03000-ati-generic.sh | 18 - .../xorg/video-detect.d/04000-s3-trio.sh | 26 - .../xorg/video-detect.d/04100-s3-virge.sh | 26 - .../xorg/video-detect.d/05000-sis-generic.sh | 26 - .../video-detect.d/06000-matrox-generic.sh | 18 - .../video-detect.d/07000-s3-savage-generic.sh | 26 - .../xorg/video-detect.d/08000-via-generic.sh | 18 - .../video-detect.d/09000-rendition-generic.sh | 18 - .../video-detect.d/09050-trident-generic.sh | 15 - .../video-detect.d/09100-tseng-generic.sh | 15 - .../video-detect.d/09200-rendition-generic.sh | 15 - .../video-detect.d/09300-cirrus-generic.sh | 15 - .../video-detect.d/09400-chips-generic.sh | 15 - .../09500-siliconmotion-generic.sh | 15 - .../video-detect.d/09600-neomagic-generic.sh | 15 - .../xorg/video-detect.d/09700-apm-generic.sh | 15 - .../xorg/video-detect.d/09710-ark-generic.sh | 15 - .../video-detect.d/09720-glint-generic.sh | 21 - .../xorg/video-detect.d/09730-i128-generic.sh | 15 - .../video-detect.d/09740-cyrix-generic.sh | 15 - .../xorg/video-detect.d/09750-nsc-generic.sh | 21 - .../video-detect.d/09800-vmware-generic.sh | 15 - .../video-detect.d/09980-fbdev-fallback.sh | 21 - .../video-detect.d/09999-vesa-fallback.sh | 16 - .../xorg/video-detect.d/99999-vga-fallback.sh | 16 - .../opt/retrodebian/xorg/xorg.conf.template | 119 -- internal/rootfs/usr/lib/urxvt/perl/clipboard | 127 -- live/.gitkeep | 0 neofetch | 675 ------- nvidia.patch | 55 - profiles/demo.py | 9 + unionfs-2.2.3_for_2.6.24.diff.gz | Bin 76789 -> 0 bytes update-initramfs.sh | 17 - wallpaper.jpg | Bin 151008 -> 0 bytes zzz-config-live.sh | 79 - 126 files changed, 1594 insertions(+), 6127 deletions(-) create mode 100644 .gitignore create mode 100644 .vscode/launch.json create mode 100644 .vscode/python.env create mode 100644 .vscode/settings.json create mode 100644 .vscode/tasks.json delete mode 100644 Dockerfile delete mode 100644 LICENSE.md rename .docker-cache/glide.ref => artifacts/bases/.gitkeep (100%) rename .docker-cache/icons.ref => artifacts/features/.gitkeep (100%) rename .docker-cache/ut99.ref => artifacts/profiles/.gitkeep (100%) create mode 100644 bases/retrodebian-common/chroot/README-common-base.txt create mode 100644 bases/retrodebian-common/entry.py create mode 100644 bases/retrodebian-common/entry.sh create mode 100644 bases/retrodebian-common/generate.sh create mode 100644 bases/retrodebian-common/hooks/05-common-base.sh create mode 100644 bases/retrodebian-common/packageslists/common-base.list create mode 100644 bases/voodoo2/chroot/etc/retrodebian-base.conf create mode 100644 bases/voodoo2/entry.py create mode 100644 bases/voodoo2/entry.sh create mode 100644 bases/voodoo2/generate.sh create mode 100644 bases/voodoo2/hooks/10-sample-base.sh create mode 100644 bases/voodoo2/packages/sample-base_1.0_all.deb create mode 100644 bases/voodoo2/packageslists/sample-base.list create mode 100644 builder/bash/common.sh create mode 100644 builder/bash/run_entry.sh create mode 100644 builder/bash/run_generate.sh create mode 100644 builder/bash/run_profile_build.sh create mode 100644 builder/bash/run_profile_config.sh create mode 100644 builder/py/build.py create mode 100644 builder/py/retrobuilder/__init__.py create mode 100644 builder/py/retrobuilder/context.py create mode 100644 builder/py/retrobuilder/entrypoints.py create mode 100644 builder/py/retrobuilder/envfile.py create mode 100644 builder/py/retrobuilder/loader.py create mode 100644 builder/py/retrobuilder/model.py create mode 100644 builder/py/retrobuilder/operations.py create mode 100644 builder/py/retrobuilder/paths.py delete mode 100755 buildglidepkg.sh delete mode 100644 config-kernel delete mode 100644 deps/theme-AdwaitaDark.tar delete mode 100644 desktop delete mode 100644 editions/voodoo2/splash-source.png create mode 100644 features/sample-feature/chroot/usr/share/retrodebian/sample-feature.txt create mode 100644 features/sample-feature/entry.py create mode 100644 features/sample-feature/entry.sh create mode 100644 features/sample-feature/generate.sh create mode 100644 features/sample-feature/hooks/20-sample-feature.sh create mode 100644 features/sample-feature/packages/sample-feature_1.0_all.deb create mode 100644 features/sample-feature/packageslists/sample-feature.list delete mode 100644 games/ut99/ut delete mode 100644 games/ut99/ut-install-436.run delete mode 100644 internal/rootfs/etc/apt/sources.list.d/etch-backport.list delete mode 100644 internal/rootfs/etc/environment delete mode 100644 internal/rootfs/etc/init.d/retrodebian-fluxbox-watch-menu delete mode 100644 internal/rootfs/etc/init.d/retrodebian-xorg-autoconfig delete mode 100644 internal/rootfs/etc/ld.so.conf.d/99local.conf delete mode 100644 internal/rootfs/etc/skel/.Xresources delete mode 100644 internal/rootfs/etc/skel/.bash_profile delete mode 100644 internal/rootfs/etc/skel/.bashrc delete mode 100644 internal/rootfs/etc/skel/.fluxbox/init delete mode 100644 internal/rootfs/etc/skel/.fluxbox/keys delete mode 100644 internal/rootfs/etc/skel/.fluxbox/startup delete mode 100644 internal/rootfs/etc/skel/.gtkrc-2.0 delete mode 100644 internal/rootfs/etc/skel/.ideskrc delete mode 100644 internal/rootfs/etc/skel/.idesktop/Files.lnk delete mode 100644 internal/rootfs/etc/skel/.idesktop/TaskManager.lnk delete mode 100644 internal/rootfs/etc/skel/.idesktop/Terminal.lnk delete mode 100644 internal/rootfs/etc/skel/.idesktop/TextEdit.lnk delete mode 100644 internal/rootfs/etc/skel/.idesktop/UT99.lnk delete mode 100644 internal/rootfs/etc/skel/.idesktop/V2TMUMemTester.lnk delete mode 100644 internal/rootfs/etc/skel/.pcmanfm/mime_info delete mode 100644 internal/rootfs/etc/skel/.profile delete mode 100644 internal/rootfs/etc/skel/.xinitrc delete mode 100644 internal/rootfs/etc/skel/.xscreensaver delete mode 100644 internal/rootfs/etc/udev/rules.d/z99_3dfx.rules delete mode 100644 internal/rootfs/opt/retrodebian/bin/set-resolution delete mode 100644 internal/rootfs/opt/retrodebian/fluxbox/retrodebian-menu.section delete mode 100644 internal/rootfs/opt/retrodebian/fluxbox/update-menu.sh delete mode 100644 internal/rootfs/opt/retrodebian/fluxbox/watch-menu.sh delete mode 100644 internal/rootfs/opt/retrodebian/xorg/autoconfig.sh delete mode 100644 internal/rootfs/opt/retrodebian/xorg/mouse-detect.d/01000-mouse-qemu-tablet.sh.disabled delete mode 100644 internal/rootfs/opt/retrodebian/xorg/mouse-detect.d/02000-mouse-wacom.sh delete mode 100644 internal/rootfs/opt/retrodebian/xorg/mouse-detect.d/03000-mouse-synaptics.sh delete mode 100644 internal/rootfs/opt/retrodebian/xorg/mouse-detect.d/09900-mouse-proc-handler.sh delete mode 100644 internal/rootfs/opt/retrodebian/xorg/mouse-detect.d/99999-mouse-fallback.sh delete mode 100644 internal/rootfs/opt/retrodebian/xorg/video-detect.d/01000-i810.sh delete mode 100644 internal/rootfs/opt/retrodebian/xorg/video-detect.d/01050-i740.sh delete mode 100644 internal/rootfs/opt/retrodebian/xorg/video-detect.d/01100-3dfx-banshee-voodoo345.sh delete mode 100644 internal/rootfs/opt/retrodebian/xorg/video-detect.d/02000-nvidia-generic.sh delete mode 100644 internal/rootfs/opt/retrodebian/xorg/video-detect.d/03000-ati-generic.sh delete mode 100644 internal/rootfs/opt/retrodebian/xorg/video-detect.d/04000-s3-trio.sh delete mode 100644 internal/rootfs/opt/retrodebian/xorg/video-detect.d/04100-s3-virge.sh delete mode 100644 internal/rootfs/opt/retrodebian/xorg/video-detect.d/05000-sis-generic.sh delete mode 100644 internal/rootfs/opt/retrodebian/xorg/video-detect.d/06000-matrox-generic.sh delete mode 100644 internal/rootfs/opt/retrodebian/xorg/video-detect.d/07000-s3-savage-generic.sh delete mode 100644 internal/rootfs/opt/retrodebian/xorg/video-detect.d/08000-via-generic.sh delete mode 100644 internal/rootfs/opt/retrodebian/xorg/video-detect.d/09000-rendition-generic.sh delete mode 100644 internal/rootfs/opt/retrodebian/xorg/video-detect.d/09050-trident-generic.sh delete mode 100644 internal/rootfs/opt/retrodebian/xorg/video-detect.d/09100-tseng-generic.sh delete mode 100644 internal/rootfs/opt/retrodebian/xorg/video-detect.d/09200-rendition-generic.sh delete mode 100644 internal/rootfs/opt/retrodebian/xorg/video-detect.d/09300-cirrus-generic.sh delete mode 100644 internal/rootfs/opt/retrodebian/xorg/video-detect.d/09400-chips-generic.sh delete mode 100644 internal/rootfs/opt/retrodebian/xorg/video-detect.d/09500-siliconmotion-generic.sh delete mode 100644 internal/rootfs/opt/retrodebian/xorg/video-detect.d/09600-neomagic-generic.sh delete mode 100644 internal/rootfs/opt/retrodebian/xorg/video-detect.d/09700-apm-generic.sh delete mode 100644 internal/rootfs/opt/retrodebian/xorg/video-detect.d/09710-ark-generic.sh delete mode 100644 internal/rootfs/opt/retrodebian/xorg/video-detect.d/09720-glint-generic.sh delete mode 100644 internal/rootfs/opt/retrodebian/xorg/video-detect.d/09730-i128-generic.sh delete mode 100644 internal/rootfs/opt/retrodebian/xorg/video-detect.d/09740-cyrix-generic.sh delete mode 100644 internal/rootfs/opt/retrodebian/xorg/video-detect.d/09750-nsc-generic.sh delete mode 100644 internal/rootfs/opt/retrodebian/xorg/video-detect.d/09800-vmware-generic.sh delete mode 100644 internal/rootfs/opt/retrodebian/xorg/video-detect.d/09980-fbdev-fallback.sh delete mode 100644 internal/rootfs/opt/retrodebian/xorg/video-detect.d/09999-vesa-fallback.sh delete mode 100644 internal/rootfs/opt/retrodebian/xorg/video-detect.d/99999-vga-fallback.sh delete mode 100644 internal/rootfs/opt/retrodebian/xorg/xorg.conf.template delete mode 100644 internal/rootfs/usr/lib/urxvt/perl/clipboard create mode 100644 live/.gitkeep delete mode 100644 neofetch delete mode 100644 nvidia.patch create mode 100644 profiles/demo.py delete mode 100644 unionfs-2.2.3_for_2.6.24.diff.gz delete mode 100644 update-initramfs.sh delete mode 100644 wallpaper.jpg delete mode 100644 zzz-config-live.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7f48236 --- /dev/null +++ b/.gitignore @@ -0,0 +1,35 @@ +# Python +__pycache__/ +*.py[cod] +*.pyo + +# VS Code +.vscode/* +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/settings.json +!.vscode/python.env + +# Build workdirs +/live/* +!/live/.gitkeep + +/artifacts/features/* +!/artifacts/features/.gitkeep +/artifacts/bases/* +!/artifacts/bases/.gitkeep +/artifacts/profiles/* +!/artifacts/profiles/.gitkeep + +# Optional final outputs +/outputs/* +!/outputs/.gitkeep + +# Local env / debug +.env +.env.* +*.log + +# OS junk +.DS_Store +Thumbs.db \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..88dc986 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,38 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "RetroDebian: debug run-local (demo, fake legacy)", + "type": "python", + "request": "launch", + "program": "${workspaceFolder}/builder/py/build.py", + "args": [ + "run-local", + "--profile", + "demo" + ], + "cwd": "${workspaceFolder}", + "console": "integratedTerminal", + "justMyCode": false, + "env": { + "RETRODEBIAN_FAKE_LEGACY_TOOLS": "1", + "PYTHONPATH": "${workspaceFolder}/builder/py" + } + }, + { + "name": "RetroDebian: debug validate", + "type": "python", + "request": "launch", + "program": "${workspaceFolder}/builder/py/build.py", + "args": [ + "validate" + ], + "cwd": "${workspaceFolder}", + "console": "integratedTerminal", + "justMyCode": false, + "env": { + "PYTHONPATH": "${workspaceFolder}/builder/py" + } + } + ] +} diff --git a/.vscode/python.env b/.vscode/python.env new file mode 100644 index 0000000..17260e1 --- /dev/null +++ b/.vscode/python.env @@ -0,0 +1,2 @@ +PYTHONPATH=${workspaceFolder}/builder/py +RETRODEBIAN_FAKE_LEGACY_TOOLS=1 diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..6ea3122 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "python.analysis.extraPaths": [ + "${workspaceFolder}/builder/py" + ], + "python.envFile": "${workspaceFolder}/.vscode/python.env" +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..ae9d9c2 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,100 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "RetroDebian: validate", + "type": "shell", + "command": "python3", + "args": [ + "builder/py/build.py", + "validate" + ], + "options": { + "cwd": "${workspaceFolder}" + }, + "problemMatcher": [] + }, + { + "label": "RetroDebian: list profiles", + "type": "shell", + "command": "python3", + "args": [ + "builder/py/build.py", + "list", + "profiles" + ], + "options": { + "cwd": "${workspaceFolder}" + }, + "problemMatcher": [] + }, + { + "label": "RetroDebian: run-local (demo, fake legacy)", + "type": "shell", + "command": "python3", + "args": [ + "builder/py/build.py", + "run-local", + "--profile", + "demo" + ], + "options": { + "cwd": "${workspaceFolder}", + "env": { + "RETRODEBIAN_FAKE_LEGACY_TOOLS": "1", + "PYTHONPATH": "${workspaceFolder}/builder/py" + } + }, + "problemMatcher": [] + }, + { + "label": "RetroDebian: run-local (pick profile, fake legacy)", + "type": "shell", + "command": "python3", + "args": [ + "builder/py/build.py", + "run-local", + "--profile", + "${input:retrodebianProfile}" + ], + "options": { + "cwd": "${workspaceFolder}", + "env": { + "RETRODEBIAN_FAKE_LEGACY_TOOLS": "1", + "PYTHONPATH": "${workspaceFolder}/builder/py" + } + }, + "problemMatcher": [] + }, + { + "label": "RetroDebian: run-local (pick profile, real legacy tools)", + "type": "shell", + "command": "python3", + "args": [ + "builder/py/build.py", + "run-local", + "--profile", + "${input:retrodebianProfile}" + ], + "options": { + "cwd": "${workspaceFolder}", + "env": { + "RETRODEBIAN_FAKE_LEGACY_TOOLS": "0", + "PYTHONPATH": "${workspaceFolder}/builder/py" + } + }, + "problemMatcher": [] + } + ], + "inputs": [ + { + "id": "retrodebianProfile", + "type": "pickString", + "description": "Choose the RetroDebian profile to build locally", + "options": [ + "demo" + ], + "default": "demo" + } + ] +} diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index fbb60c5..0000000 --- a/Dockerfile +++ /dev/null @@ -1,225 +0,0 @@ -FROM i386/alpine:latest AS glide-fetcher -ARG CACHE_BUST=38 -RUN apk add --no-cache git ca-certificates -COPY .docker-cache/glide.ref /tmp/glide.ref -WORKDIR /src -RUN cat /tmp/glide.ref > /dev/null && \ - echo "$CACHE_BUST" > /dev/null && \ - git clone --depth 1 --branch retrodebian --single-branch https://gitea.chacha.ddns.net/chacha/glide.git && \ - rm -Rf glide/.git - -FROM i386/alpine:latest AS icons-fetcher -ARG CACHE_BUST=11 -RUN apk add --no-cache git ca-certificates -COPY .docker-cache/icons.ref /tmp/icons.ref -WORKDIR /root -RUN cat /tmp/icons.ref > /dev/null && \ - echo "$CACHE_BUST" > /dev/null && \ - git clone --depth 1 --branch main --single-branch https://gitea.chacha.ddns.net/chacha/icons-collection.git && \ - rm -Rf icons-collection/.git - -# building a modified Kernel + modules + libs -FROM lpenz/debian-etch-i386-minbase AS packages-builder -ARG DEBIAN_FRONTEND=noninteractive -ARG ARCH=i386 -ARG CONCURRENCY_LEVEL=4 - -# Preparing Environment -RUN (echo "deb http://archive.debian.org/debian etch main non-free" > /etc/apt/sources.list) && \ - (echo "deb-src http://archive.debian.org/debian etch main non-free" >> /etc/apt/sources.list) && \ - mkdir -p /usr/src/modules &&\ - apt-get update && \ - apt-get install -y aptitude build-essential quilt cvs unzip git-core ncurses-dev\ - linux-headers-2.6.24-etchnhalf.1-686 \ - squashfs-source-etchnhalf \ - linux-source-2.6.24 && \ - apt-get build-dep -y linux-image-2.6.24-etchnhalf.1-686 && \ - apt-get clean - -# Preparing Kernel + patchs + modules -WORKDIR /usr/src -COPY unionfs-2.2.3_for_2.6.24.diff.gz ./ -COPY nvidia.patch ./ -COPY --from=glide-fetcher /src/glide glide -RUN tar xjf linux-source-2.6.24.tar.bz2 && \ - tar xjf etchnhalf/squashfs.tar.bz2 && \ - ln -s linux-headers-2.6.24-etchnhalf.1-686/ linux-headers && \ - mv glide/Device3Dfx modules/ &&\ - wget http://archive.debian.org/debian-archive/debian/pool/non-free/n/nvidia-graphics-drivers-legacy-71xx/nvidia-kernel-legacy-71xx-source_71.86.15-3_i386.deb && \ - dpkg-deb -x nvidia-kernel-legacy-71xx-source_71.86.15-3_i386.deb / && \ - tar xjf nvidia-kernel-legacy-71xx.tar.bz2 && \ - rm nvidia-kernel-legacy-71xx-source_71.86.15-3_i386.deb && \ - patch -d modules/nvidia-kernel-legacy-71xx -p1 < nvidia.patch - -# Building Kernel + patchs + modules -WORKDIR /usr/src/linux-source-2.6.24 -COPY config-kernel ./ -RUN (zcat /usr/src/unionfs-2.2.3_for_2.6.24.diff.gz | patch -p1) && \ - (cat config-kernel > .config) && \ - make oldconfig &&\ - make-kpkg --initrd --arch $ARCH kernel_headers kernel_image modules_image - -# Modified urxvt terminal -WORKDIR /usr/src -RUN apt-get build-dep -y rxvt-unicode && \ - apt-get source rxvt-unicode &&\ - cd rxvt-unicode-* && \ - cp debian/rules debian/rules.orig && \ - cp debian/changelog debian/changelog.orig && \ - sed -i '/\.\/configure/ s/$/ --disable-iso14755/' debian/rules && \ - perl -0pi -e 's/#if ENABLE_FRILLS \|\| ISO_14755\n\s*\/\/ ISO 14755 support/#if 0\n \/\/ ISO 14755 support/' src/command.C && \ - sed -i '1s/^\([^)]* (\)\([^)]*\)\(.*\)$/\1\2+retrodebian1\3/' debian/changelog && \ - dpkg-buildpackage -us -uc -b - -FROM packages-builder AS voodoo-builder -# Building userspace libs -# 3Dfx -WORKDIR /usr/src -COPY buildglidepkg.sh ./ -RUN apt-get install -y nasm && \ - chmod +x buildglidepkg.sh -# cvg / voodoo2 -WORKDIR /usr/src/glide -RUN find . -type f \( -name 'fxgasm.h' -o -name 'fxinline.h' -o -name 'fxgasm' \) -exec rm -f {} \; -# glide2x -RUN mv swlibs glide2x/ -WORKDIR /usr/src/glide/glide2x/ -RUN make -f makefile.linux FX_GLIDE_HW=cvg clean -RUN make -f makefile.linux FX_GLIDE_HW=cvg USE_X86=1 USE_MMX=0 -RUN mv swlibs ../glide3x/ -## glide3x -WORKDIR /usr/src/glide/glide3x/ -RUN make -f makefile.linux FX_GLIDE_HW=cvg clean -RUN make -f makefile.linux FX_GLIDE_HW=cvg USE_X86=1 USE_MMX=1 -RUN mv swlibs ../ -WORKDIR /usr/src/ -RUN /usr/src/buildglidepkg.sh cvg - -## h3 / voodoo3 & Banshee -#WORKDIR /usr/src/glide -#RUN echo test3 && find . -type f -name 'fxgasm.h' -#RUN find . -type f \( -name 'fxgasm.h' -o -name 'fxinline.h' -o -name 'fxgasm' \) -exec rm -f {} \; -#RUN apt-get install -y libx11-dev x11proto-xf86dga-dev libxxf86vm-dev libxxf86dga-dev -### glide2x -#RUN mv swlibs glide2x/ -#WORKDIR /usr/src/glide/glide2x/ -#RUN make -f makefile.linux clean -#RUN make -f makefile.linux FX_GLIDE_HW=h3 USE_X86=1 USE_MMX=1 -## glide3x -#RUN mv swlibs ../glide3x/ -#WORKDIR /usr/src/glide/glide3x/ -#RUN make -f makefile.linux clean -#RUN make -f makefile.linux FX_GLIDE_HW=h3 USE_X86=1 USE_MMX=1 -#RUN mv swlibs ../ -#WORKDIR /usr/src/ -#RUN /usr/src/buildglidepkg.sh h3 - -## sst1 / voodoo1 -#WORKDIR /usr/src/glide -#RUN find . -type f \( -name 'fxgasm.h' -o -name 'fxinline.h' -o -name 'fxgasm' \) -exec rm -f {} \; -## glide2x -#RUN mv swlibs glide2x/ -#WORKDIR /usr/src/glide/glide2x/ -#RUN make -f makefile.linux clean -#RUN make -f makefile.linux FX_GLIDE_HW=sst1 USE_X86=1 USE_MMX=1 -## glide3x -#RUN mv swlibs ../glide3x/ -#WORKDIR /usr/src/glide/glide3x/ -#RUN make -f makefile.linux clean -#RUN make -f makefile.linux FX_GLIDE_HW=sst1 USE_X86=1 USE_MMX=1 -#RUN mv swlibs ../ -#WORKDIR /usr/src/ -#RUN /usr/src/buildglidepkg.sh sst1 - -# sst96 / voodoo Rush -# cannot build driver because of missing xf86rush lib... -#WORKDIR /usr/src/ -#WORKDIR /usr/src/glide -#RUN find . -type f \( -name 'fxgasm.h' -o -name 'fxinline.h' -o -name 'fxgasm' \) -exec rm -f {} \; -# # glide2x -# RUN mv swlibs glide2x/ -# WORKDIR /usr/src/glide/glide2x/ -# RUN make -f Makefile.linux clean -# RUN make -f Makefile.linux FX_GLIDE_HW=sst96 -# # glide3x -# RUN mv swlibs ../glide3x/ -# WORKDIR /usr/src/glide/glide3x/ -# RUN make -f Makefile.linux clean -# RUN make -f Makefile.linux FX_GLIDE_HW=sst96 USE_X86=1 USE_MMX=1 -# RUN mv swlibs ../ -#WORKDIR /usr/src/ -#RUN /usr/src/buildglidepkg.sh sst96 - -#RUN rm *.gz *.bz2 && rm -Rf glide && rm -rf /var/lib/apt/lists/* - -FROM i386/alpine:latest AS ut99-builder -RUN apk add --no-cache git ca-certificates dos2unix -ARG CACHE_BUST=10 -COPY .docker-cache/ut99.ref /tmp/ut99.ref -# Package UT99 -WORKDIR /root -RUN cat /tmp/ut99.ref > /dev/null && \ - echo "$CACHE_BUST" && \ - git clone --depth 1 --branch master --single-branch https://gitea.chacha.ddns.net/chacha/UT99-Official.git ut-game && \ - rm -Rf ut-game/.git -COPY games/ut99/ut-install-436.run ./ -RUN chmod +x ut-install-436.run && \ - ./ut-install-436.run --target ./ut || true && \ - tar xzf ./ut/data.tar.gz -C ut-game && \ - cp ./ut/bin/x86/ut ut-game/ && \ - rm ut-game/System/*.frt && \ - rm ut-game/System/*.itt && \ - rm ut-game/System/*.est && \ - rm ut-game/System/*.exe && \ - rm ut-game/System/*.dll && \ - rm ut-game/System/*.url && \ - rm ut-game/System/*.bat && \ - rm ut-game/System/de.* && \ - rm ut-game/System/UnrealTournament.ini && \ - rm ut-game/System/Default.ini && \ - rm ut-game/System/libSDL-1.1.so.0 && \ - rm ut-game/Sounds/*est_uax && \ - rm ut-game/Sounds/*frt_uax && \ - rm ut-game/Sounds/*itt_uax && \ - rm ut-game/DoConfig.py && \ - rm ut-game/DoConfig.sh && \ - rm -Rf ut-game/Web && \ - rm -Rf ut-game/Help/* &&\ - tar xzf ./ut/Glide.ini.tar.gz -C ut-game && \ - mv ut-game/System/UnrealTournament.ini ut-game/System/Default-glide.ini && \ - ls -al ./ut/ && \ - tar xzf ./ut/OpenGL.ini.tar.gz -C ut-game && \ - cp ut-game/System/UnrealTournament.ini ut-game/System/Default.ini && \ - mv ut-game/System/UnrealTournament.ini ut-game/System/Default-opengl.ini && \ - dos2unix ut-game/System/*.ini -COPY games/ut99/ut ./ut-game/ut -RUN chmod a+x,o-w ./ut-game/ut - -# Note: we need to use Lenny because of live-helper -# it allows creating Etch live image though ! -FROM lpenz/debian-lenny-i386-minbase -WORKDIR /root -COPY --from=packages-builder /usr/src/*.deb . -COPY --from=voodoo-builder /usr/src/*.deb . -COPY --from=ut99-builder /root/ut-game ./ut-game -COPY --from=icons-fetcher /root/icons-collection ./icons-collection -COPY /deps ./deps -COPY update-initramfs.sh . -COPY zzz-config-live.sh . -COPY desktop . -COPY wallpaper.jpg . -COPY neofetch . -COPY editions ./editions -COPY internal ./internal -RUN apt-get update && \ - apt-get -y --force-yes install live-helper genisoimage syslinux squashfs-tools aptitude && \ - apt-get clean -# rm -rf /var/lib/apt/lists/* -WORKDIR /root/live - -#FROM voodoo-builder -#WORKDIR /usr/src -#RUN apt-get build-dep -y debian-edu-artwork-usplash && \ -# apt-get source debian-edu-artwork-usplash &&\ -# ls -al && \ -# cd debian-edu-artwork-* \ No newline at end of file diff --git a/Jenkinsfile b/Jenkinsfile index a6056a9..c1bd1ab 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,226 +1,207 @@ pipeline { - agent { - label 'pyDABFActory-CIAgent' + agent any + + parameters { + booleanParam(name: 'BUILD_ALL_PROFILES', defaultValue: true, description: 'Build all profiles one by one') + string(name: 'PROFILE', defaultValue: 'demo', description: 'Profile to build when BUILD_ALL_PROFILES is false') + string(name: 'PYTHON_IMAGE', defaultValue: 'python:3.11-alpine', description: 'Default image for Python/control-plane steps') + string(name: 'ETCH_IMAGE', defaultValue: '', description: 'Default Etch image when ETCH_DOCKERFILE is empty') + string(name: 'ETCH_DOCKERFILE', defaultValue: '', description: 'Optional default Dockerfile path for Etch runtime') + string(name: 'LENNY_IMAGE', defaultValue: '', description: 'Default Lenny image when LENNY_DOCKERFILE is empty') + string(name: 'LENNY_DOCKERFILE', defaultValue: '', description: 'Optional default Dockerfile path for Lenny runtime') } + stages { - stage('GIT get refs and download some standard things') { - agent { - docker { - image 'alpine:3.21' - reuseNode true - } - } + stage('Validate builder') { steps { - sh ''' - set -eu - apk add --no-cache git jq curl - - mkdir -p .docker-cache - - git ls-remote https://gitea.chacha.ddns.net/chacha/glide.git refs/heads/retrodebian \ - | awk '{print $1}' > .docker-cache/glide.ref - test -s .docker-cache/glide.ref - echo "glide ref: $(cat .docker-cache/glide.ref)" - - git ls-remote https://gitea.chacha.ddns.net/chacha/UT99-Official.git refs/heads/master \ - | awk '{print $1}' > .docker-cache/ut99.ref - test -s .docker-cache/ut99.ref - echo "ut99 ref: $(cat .docker-cache/ut99.ref)" - - git ls-remote https://gitea.chacha.ddns.net/chacha/icons-collection.git refs/heads/main \ - | awk '{print $1}' > .docker-cache/icons.ref - test -s .docker-cache/icons.ref - echo "icons ref: $(cat .docker-cache/icons.ref)" - - curl -s "https://gitea.chacha.ddns.net/api/v1/repos/chacha/V2TMUMemTester/releases" \ - | jq -r 'map(select(.draft == false)) | .[0].assets[] | select(.name=="v2-tmu-memtester") | .browser_download_url' \ - | xargs -n1 curl -L -o v2-tmu-memtester - - chmod +x v2-tmu-memtester - ''' + script { + docker.image(params.PYTHON_IMAGE).inside { + sh 'python3 builder/py/build.py validate' + } + } } } - stage('Convert splash images') - { - agent { - docker { - image 'alpine:3.21' - reuseNode true - } - } + + stage('Build common features') { steps { - sh ''' - set -eu - apk add --no-cache imagemagick - found_edition=0 - for edition_dir in editions/*; do - [ -d "$edition_dir" ] || continue - found_edition=1 - set -- "$edition_dir"/splash-source.* - if [ ! -e "$1" ]; then - echo "ERROR: missing splash-source.* in $edition_dir" >&2 - exit 1 - fi - if [ $# -ne 1 ]; then - echo "ERROR: multiple splash-source.* files in $edition_dir" >&2 - exit 1 - fi - src="$1" - out="$edition_dir/splash.jpg" - echo "Converting $src -> $out" - magick "$src" \ - -resize 640x480! \ - -background black \ - -alpha remove -alpha off \ - -colorspace sRGB \ - -strip \ - -quality 95 \ - "$out" - done - - if [ "$found_edition" -eq 0 ]; then - echo "ERROR: no edition directory found under editions/" >&2 - exit 1 - fi - ''' - } - } - stage('Create live') - { - agent { - dockerfile { - filename 'Dockerfile' - dir '.' - label 'pyDABFActory-CIAgent' - args '--privileged --security-opt seccomp=unconfined --security-opt apparmor=unconfined -u root:root' - reuseNode true - } - } - stages { - stage('Configure ISO') { - steps { - dir('root') - { - sh 'rm -Rf live artifacts' + script { + def resolveDefaultRuntimeImage = { String runtimeName, String imageName, String dockerfilePath -> + if (dockerfilePath?.trim()) { + return docker.build("retrodebian/${runtimeName}:${env.BUILD_TAG}", "-f ${dockerfilePath} .").imageName() } - dir('root/live') - { - sh ''' - set -e - deb="$(ls -1 /root/linux-image-*.deb | head -n1)" - kernpkg="$(dpkg-deb -f "$deb" Package)" - echo "$kernpkg" + if (!imageName?.trim()) { + error("Missing default image for runtime ${runtimeName}") + } + return imageName.trim() + } - deb="$(ls -1 /root/squashfs-modules-*.deb | head -n1)" - squashfspkg="$(dpkg-deb -f "$deb" Package)" - echo "$squashfspkg" + def resolveModuleRuntimeImage = { String runtimeName, String kind, String name, String phase, String defaultImage -> + def overrideImage = '' + def overrideDockerfile = '' + def overrideContext = '' + docker.image(params.PYTHON_IMAGE).inside { + overrideImage = sh(script: "python3 builder/py/build.py module-docker --kind ${kind} --name ${name} --phase ${phase} image", returnStdout: true).trim() + overrideDockerfile = sh(script: "python3 builder/py/build.py module-docker --kind ${kind} --name ${name} --phase ${phase} dockerfile", returnStdout: true).trim() + overrideContext = sh(script: "python3 builder/py/build.py module-docker --kind ${kind} --name ${name} --phase ${phase} docker_context", returnStdout: true).trim() + } + if (overrideDockerfile) { + def tag = overrideImage ? overrideImage : "retrodebian/${runtimeName}-${kind}-${name}-${phase}:${env.BUILD_TAG}" + def contextPath = overrideContext ? overrideContext : '.' + return docker.build(tag, "-f ${overrideDockerfile} ${contextPath}").imageName() + } + if (overrideImage) { + return overrideImage + } + return defaultImage + } - lh_config \ - -a i386 \ - --distribution etch \ - --apt apt \ - --apt-options "--yes --force-yes" \ - --apt-secure false \ - --apt-recommends false \ - --linux-packages "squashfs-modules-2.6.24 linux-image-2.6.24 device3dfx-modules-2.6.24" \ - --packages-lists "desktop" \ - --mirror-bootstrap http://archive.debian.org/debian/ \ - --mirror-binary http://archive.debian.org/debian/ \ - --mirror-binary-security http://archive.debian.org/debian-security/ \ - --mirror-chroot http://archive.debian.org/debian/ \ - --mirror-chroot-security http://archive.debian.org/debian-security/ \ - --binary-images iso \ - --bootloader syslinux \ - --syslinux-timeout 5 \ - --syslinux-menu true \ - --bootstrap debootstrap \ - --debconf-frontend noninteractive \ - --debian-installer live \ - --bootappend-live "elevator=deadline" \ - --hostname RetroDebian \ - --iso-application RetroDebian \ - --syslinux-splash config/binary_syslinux/splash.jpg \ - --union-filesystem unionfs \ - --username bob \ - --templates config/templates \ - -k retrodebian1 - - cp -R /usr/share/live-helper/templates/* config/templates/ - sed -i \ - -e 's|^menu vshift.*|menu vshift 4|' \ - -e 's|^menu hshift.*|menu hshift 9|' \ - -e 's|^menu width.*|menu width 60|' \ - -e 's|^menu color sel.*|menu color sel * #ff82c059 #c01f1f1f none|' \ - -e 's|^menu color unsel.*|menu color unsel * #8082c059 #c01f1f1f none|' \ - -e 's|^menu color hotkey.*|menu color hotkey * #fff01e1e #c01f1f1f none|' \ - -e 's|^menu color tabmsg.*|menu color tabmsg * #ffB0B0B0 #00000000 none|' \ - -e 's|^menu color timeout_msg.*|menu color timeout_msg * #ffB0B0B0 #00000000 none|' \ - -e 's|^menu color timeout.*|menu color timeout * #ffff0000 #00000000 none|' \ - config/templates/syslinux/menu/header.cfg - - cp -R /root/internal/rootfs/* config/chroot_local-includes + def pythonDefaultImage = params.PYTHON_IMAGE.trim() + def etchDefaultImage = resolveDefaultRuntimeImage('etch-default', params.ETCH_IMAGE, params.ETCH_DOCKERFILE) + def lennyDefaultImage = resolveDefaultRuntimeImage('lenny-default', params.LENNY_IMAGE, params.LENNY_DOCKERFILE) - chmod +x /root/update-initramfs.sh - chmod +x /root/zzz-config-live.sh - cp /root/update-initramfs.sh config/chroot_local-hooks - cp /root/zzz-config-live.sh config/chroot_local-hooks - cp /root/linux-image-*.deb config/chroot_local-packages/ - cp /root/rxvt-unicode_*.deb config/chroot_local-packages/ - cp /root/device3dfx-*.deb config/chroot_local-packages/ - cp /root/squashfs-modules-*.deb config/chroot_local-packages/ - cp /root/libglide*-cvg*_i386.deb config/chroot_local-packages/ - cp /root/desktop config/chroot_local-packageslists/ - mkdir -p config/chroot_local-includes/usr/share/wallpapers - cp /root/wallpaper.jpg config/chroot_local-includes/usr/share/wallpapers/retrodebian.jpg - mkdir -p config/chroot_local-includes/usr/local/bin - cp /root/neofetch config/chroot_local-includes/usr/local/bin/neofetch - chmod +x config/chroot_local-includes/usr/local/bin/neofetch - cp /root/editions/voodoo2/splash.jpg config/binary_syslinux/ - cp "$WORKSPACE/v2-tmu-memtester" config/chroot_local-includes/usr/local/bin/ - ''' + def featureNames = [] + docker.image(pythonDefaultImage).inside { + def raw = sh(script: 'python3 builder/py/build.py list features', returnStdout: true).trim() + featureNames = raw ? raw.split('\n').findAll { it?.trim() } : [] + } + + for (featureName in featureNames) { + stage("Feature ${featureName}") { + def pythonImagePre = resolveModuleRuntimeImage('python', 'feature', featureName, 'pre-gen', pythonDefaultImage) + docker.image(pythonImagePre).inside { + sh "python3 builder/py/build.py run-python-phase --kind feature --phase pre-gen --profile ${params.PROFILE} --feature ${featureName}" + sh "python3 builder/py/build.py export-env --kind feature --phase pre-gen --profile ${params.PROFILE} --feature ${featureName} --output artifacts/features/${featureName}/runtime.env" + } + def etchImage = resolveModuleRuntimeImage('etch', 'feature', featureName, 'generate', etchDefaultImage) + docker.image(etchImage).inside { + sh "builder/bash/run_generate.sh features/${featureName} artifacts/features/${featureName}/runtime.env" + } + def pythonImagePost = resolveModuleRuntimeImage('python', 'feature', featureName, 'post-gen', pythonDefaultImage) + docker.image(pythonImagePost).inside { + sh "python3 builder/py/build.py run-python-phase --kind feature --phase post-gen --profile ${params.PROFILE} --feature ${featureName}" + } } } - } - stage('Configure games') { - steps { - dir('root/live') { - sh ''' - mkdir -p config/chroot_local-includes/usr/local/games/ut99/ - ls -al /root - cp -R /root/ut-game/* config/chroot_local-includes/usr/local/games/ut99/ - mkdir -p config/chroot_local-includes/usr/share/icons - cp /root/icons-collection/small/ut99.png config/chroot_local-includes/usr/share/icons/ - ''' + + def profileNames = [] + docker.image(pythonDefaultImage).inside { + if (params.BUILD_ALL_PROFILES) { + def raw = sh(script: 'python3 builder/py/build.py list profiles', returnStdout: true).trim() + profileNames = raw ? raw.split('\n').findAll { it?.trim() } : [] + } else { + profileNames = [params.PROFILE] } } - } - stage('Build ISO') { - steps { - dir('root/live') - { - sh 'lh_build' - } - } - } - stage('Save artifacts') { - steps { - dir('root') - { - sh ''' - mkdir artifacts - mv /root/*.deb artifacts/ - ''' + + for (profileName in profileNames) { + stage("Profile ${profileName}") { + def baseName = '' + def baseChain = [] + def featureList = [] + docker.image(pythonDefaultImage).inside { + baseName = sh(script: "python3 builder/py/build.py profile-info --profile ${profileName} base", returnStdout: true).trim() + def chainRaw = sh(script: "python3 builder/py/build.py profile-info --profile ${profileName} base-chain", returnStdout: true).trim() + baseChain = chainRaw ? chainRaw.split('\n').findAll { it?.trim() } : [] + def featuresRaw = sh(script: "python3 builder/py/build.py profile-info --profile ${profileName} features", returnStdout: true).trim() + featureList = featuresRaw ? featuresRaw.split('\n').findAll { it?.trim() } : [] + } + + for (baseItem in baseChain) { + stage("Base ${profileName} / ${baseItem}") { + def pythonImagePre = resolveModuleRuntimeImage('python', 'base', baseItem, 'pre-gen', pythonDefaultImage) + docker.image(pythonImagePre).inside { + sh "python3 builder/py/build.py run-python-phase --kind base --phase pre-gen --profile ${profileName} --base ${baseItem}" + sh "python3 builder/py/build.py export-env --kind base --phase pre-gen --profile ${profileName} --base ${baseItem} --output artifacts/bases/${baseItem}/runtime.env" + } + def etchImage = resolveModuleRuntimeImage('etch', 'base', baseItem, 'generate', etchDefaultImage) + docker.image(etchImage).inside { + sh "builder/bash/run_generate.sh bases/${baseItem} artifacts/bases/${baseItem}/runtime.env" + } + def pythonImagePost = resolveModuleRuntimeImage('python', 'base', baseItem, 'post-gen', pythonDefaultImage) + docker.image(pythonImagePost).inside { + sh "python3 builder/py/build.py run-python-phase --kind base --phase post-gen --profile ${profileName} --base ${baseItem}" + } + } + } + + docker.image(pythonDefaultImage).inside { + sh "python3 builder/py/build.py prepare-profile --profile ${profileName}" + sh "python3 builder/py/build.py export-env --kind profile --phase config --profile ${profileName} --output artifacts/profiles/${profileName}/profile-config.env" + } + docker.image(lennyDefaultImage).inside { + sh "builder/bash/run_profile_config.sh artifacts/profiles/${profileName}/profile-config.env" + } + docker.image(pythonDefaultImage).inside { + sh "python3 builder/py/build.py inject-resources --kind base --name ${baseName}" + } + + def basePreFeaturePythonImage = resolveModuleRuntimeImage('python', 'base', baseName, 'pre-feature', pythonDefaultImage) + docker.image(basePreFeaturePythonImage).inside { + sh "python3 builder/py/build.py run-python-phase --kind base --phase pre-feature --profile ${profileName} --base ${baseName}" + sh "python3 builder/py/build.py export-env --kind base --phase pre-feature --profile ${profileName} --base ${baseName} --output artifacts/bases/${baseName}/pre-feature.env" + } + def basePreFeatureLennyImage = resolveModuleRuntimeImage('lenny', 'base', baseName, 'pre-feature', lennyDefaultImage) + docker.image(basePreFeatureLennyImage).inside { + sh "builder/bash/run_entry.sh bases/${baseName} artifacts/bases/${baseName}/pre-feature.env pre-feature" + } + + for (featureName in featureList) { + stage("Inject ${profileName} / ${featureName}") { + docker.image(pythonDefaultImage).inside { + sh "python3 builder/py/build.py save-feature-metadata --profile ${profileName} --feature ${featureName}" + } + def featurePreInjPythonImage = resolveModuleRuntimeImage('python', 'feature', featureName, 'pre-inj', pythonDefaultImage) + docker.image(featurePreInjPythonImage).inside { + sh "python3 builder/py/build.py run-python-phase --kind feature --phase pre-inj --profile ${profileName} --feature ${featureName}" + sh "python3 builder/py/build.py export-env --kind feature --phase pre-inj --profile ${profileName} --feature ${featureName} --output artifacts/features/${featureName}/pre-inj.env" + } + def featurePreInjLennyImage = resolveModuleRuntimeImage('lenny', 'feature', featureName, 'pre-inj', lennyDefaultImage) + docker.image(featurePreInjLennyImage).inside { + sh "builder/bash/run_entry.sh features/${featureName} artifacts/features/${featureName}/pre-inj.env pre-inj" + } + docker.image(pythonDefaultImage).inside { + sh "python3 builder/py/build.py inject-resources --kind feature --name ${featureName}" + sh "python3 builder/py/build.py export-env --kind feature --phase post-inj --profile ${profileName} --feature ${featureName} --output artifacts/features/${featureName}/post-inj.env" + } + def featurePostInjLennyImage = resolveModuleRuntimeImage('lenny', 'feature', featureName, 'post-inj', lennyDefaultImage) + docker.image(featurePostInjLennyImage).inside { + sh "builder/bash/run_entry.sh features/${featureName} artifacts/features/${featureName}/post-inj.env post-inj" + } + def featurePostInjPythonImage = resolveModuleRuntimeImage('python', 'feature', featureName, 'post-inj', pythonDefaultImage) + docker.image(featurePostInjPythonImage).inside { + sh "python3 builder/py/build.py run-python-phase --kind feature --phase post-inj --profile ${profileName} --feature ${featureName}" + } + } + } + + def basePostFeaturePythonImage = resolveModuleRuntimeImage('python', 'base', baseName, 'post-feature', pythonDefaultImage) + docker.image(basePostFeaturePythonImage).inside { + sh "python3 builder/py/build.py run-python-phase --kind base --phase post-feature --profile ${profileName} --base ${baseName}" + sh "python3 builder/py/build.py export-env --kind base --phase post-feature --profile ${profileName} --base ${baseName} --output artifacts/bases/${baseName}/post-feature.env" + sh "python3 builder/py/build.py profile-pre-build --profile ${profileName}" + sh "python3 builder/py/build.py export-env --kind profile --phase build --profile ${profileName} --output artifacts/profiles/${profileName}/profile-build.env" + } + def basePostFeatureLennyImage = resolveModuleRuntimeImage('lenny', 'base', baseName, 'post-feature', lennyDefaultImage) + docker.image(basePostFeatureLennyImage).inside { + sh "builder/bash/run_entry.sh bases/${baseName} artifacts/bases/${baseName}/post-feature.env post-feature" + } + docker.image(lennyDefaultImage).inside { + sh "builder/bash/run_profile_build.sh artifacts/profiles/${profileName}/profile-build.env" + } + docker.image(pythonDefaultImage).inside { + sh "python3 builder/py/build.py profile-finalize --profile ${profileName}" + } } } } } } } + post { - success { - archiveArtifacts artifacts: 'root/live/*.iso', fingerprint: true - archiveArtifacts artifacts: 'root/artifacts/*.deb', fingerprint: true - deleteDir() + always { + archiveArtifacts artifacts: 'artifacts/**/*', allowEmptyArchive: true + archiveArtifacts artifacts: 'live/**/*', allowEmptyArchive: true } } -} \ No newline at end of file +} diff --git a/LICENSE.md b/LICENSE.md deleted file mode 100644 index 496acdb..0000000 --- a/LICENSE.md +++ /dev/null @@ -1,675 +0,0 @@ -# GNU GENERAL PUBLIC LICENSE - -Version 3, 29 June 2007 - -Copyright (C) 2007 Free Software Foundation, Inc. - - -Everyone is permitted to copy and distribute verbatim copies of this -license document, but changing it is not allowed. - -## Preamble - -The GNU General Public License is a free, copyleft license for -software and other kinds of works. - -The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom -to share and change all versions of a program--to make sure it remains -free software for all its users. We, the Free Software Foundation, use -the GNU General Public License for most of our software; it applies -also to any other work released this way by its authors. You can apply -it to your programs, too. - -When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - -To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you -have certain responsibilities if you distribute copies of the -software, or if you modify it: responsibilities to respect the freedom -of others. - -For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - -Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - -For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - -Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the -manufacturer can do so. This is fundamentally incompatible with the -aim of protecting users' freedom to change the software. The -systematic pattern of such abuse occurs in the area of products for -individuals to use, which is precisely where it is most unacceptable. -Therefore, we have designed this version of the GPL to prohibit the -practice for those products. If such problems arise substantially in -other domains, we stand ready to extend this provision to those -domains in future versions of the GPL, as needed to protect the -freedom of users. - -Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish -to avoid the special danger that patents applied to a free program -could make it effectively proprietary. To prevent this, the GPL -assures that patents cannot be used to render the program non-free. - -The precise terms and conditions for copying, distribution and -modification follow. - -## TERMS AND CONDITIONS - -### 0. Definitions. - -"This License" refers to version 3 of the GNU General Public License. - -"Copyright" also means copyright-like laws that apply to other kinds -of works, such as semiconductor masks. - -"The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - -To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of -an exact copy. The resulting work is called a "modified version" of -the earlier work or a work "based on" the earlier work. - -A "covered work" means either the unmodified Program or a work based -on the Program. - -To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - -To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user -through a computer network, with no transfer of a copy, is not -conveying. - -An interactive user interface displays "Appropriate Legal Notices" to -the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - -### 1. Source Code. - -The "source code" for a work means the preferred form of the work for -making modifications to it. "Object code" means any non-source form of -a work. - -A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - -The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - -The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - -The Corresponding Source need not include anything that users can -regenerate automatically from other parts of the Corresponding Source. - -The Corresponding Source for a work in source code form is that same -work. - -### 2. Basic Permissions. - -All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - -You may make, run and propagate covered works that you do not convey, -without conditions so long as your license otherwise remains in force. -You may convey covered works to others for the sole purpose of having -them make modifications exclusively for you, or provide you with -facilities for running those works, provided that you comply with the -terms of this License in conveying all material for which you do not -control copyright. Those thus making or running the covered works for -you must do so exclusively on your behalf, under your direction and -control, on terms that prohibit them from making any copies of your -copyrighted material outside their relationship with you. - -Conveying under any other circumstances is permitted solely under the -conditions stated below. Sublicensing is not allowed; section 10 makes -it unnecessary. - -### 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - -No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - -When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such -circumvention is effected by exercising rights under this License with -respect to the covered work, and you disclaim any intention to limit -operation or modification of the work as a means of enforcing, against -the work's users, your or third parties' legal rights to forbid -circumvention of technological measures. - -### 4. Conveying Verbatim Copies. - -You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - -You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - -### 5. Conveying Modified Source Versions. - -You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these -conditions: - -- a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. -- b) The work must carry prominent notices stating that it is - released under this License and any conditions added under - section 7. This requirement modifies the requirement in section 4 - to "keep intact all notices". -- c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. -- d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - -A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - -### 6. Conveying Non-Source Forms. - -You may convey a covered work in object code form under the terms of -sections 4 and 5, provided that you also convey the machine-readable -Corresponding Source under the terms of this License, in one of these -ways: - -- a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. -- b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the Corresponding - Source from a network server at no charge. -- c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. -- d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. -- e) Convey the object code using peer-to-peer transmission, - provided you inform other peers where the object code and - Corresponding Source of the work are being offered to the general - public at no charge under subsection 6d. - -A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - -A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, -family, or household purposes, or (2) anything designed or sold for -incorporation into a dwelling. In determining whether a product is a -consumer product, doubtful cases shall be resolved in favor of -coverage. For a particular product received by a particular user, -"normally used" refers to a typical or common use of that class of -product, regardless of the status of the particular user or of the way -in which the particular user actually uses, or expects or is expected -to use, the product. A product is a consumer product regardless of -whether the product has substantial commercial, industrial or -non-consumer uses, unless such uses represent the only significant -mode of use of the product. - -"Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to -install and execute modified versions of a covered work in that User -Product from a modified version of its Corresponding Source. The -information must suffice to ensure that the continued functioning of -the modified object code is in no case prevented or interfered with -solely because modification has been made. - -If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - -The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or -updates for a work that has been modified or installed by the -recipient, or for the User Product in which it has been modified or -installed. Access to a network may be denied when the modification -itself materially and adversely affects the operation of the network -or violates the rules and protocols for communication across the -network. - -Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - -### 7. Additional Terms. - -"Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - -When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - -Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders -of that material) supplement the terms of this License with terms: - -- a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or -- b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or -- c) Prohibiting misrepresentation of the origin of that material, - or requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or -- d) Limiting the use for publicity purposes of names of licensors - or authors of the material; or -- e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or -- f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions - of it) with contractual assumptions of liability to the recipient, - for any liability that these contractual assumptions directly - impose on those licensors and authors. - -All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - -If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - -Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; the -above requirements apply either way. - -### 8. Termination. - -You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - -However, if you cease all violation of this License, then your license -from a particular copyright holder is reinstated (a) provisionally, -unless and until the copyright holder explicitly and finally -terminates your license, and (b) permanently, if the copyright holder -fails to notify you of the violation by some reasonable means prior to -60 days after the cessation. - -Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - -Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - -### 9. Acceptance Not Required for Having Copies. - -You are not required to accept this License in order to receive or run -a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - -### 10. Automatic Licensing of Downstream Recipients. - -Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - -An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - -You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - -### 11. Patents. - -A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - -A contributor's "essential patent claims" are all patent claims owned -or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - -Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - -In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - -If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - -If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - -A patent license is "discriminatory" if it does not include within the -scope of its coverage, prohibits the exercise of, or is conditioned on -the non-exercise of one or more of the rights that are specifically -granted under this License. You may not convey a covered work if you -are a party to an arrangement with a third party that is in the -business of distributing software, under which you make payment to the -third party based on the extent of your activity of conveying the -work, and under which the third party grants, to any of the parties -who would receive the covered work from you, a discriminatory patent -license (a) in connection with copies of the covered work conveyed by -you (or copies made from those copies), or (b) primarily for and in -connection with specific products or compilations that contain the -covered work, unless you entered into that arrangement, or that patent -license was granted, prior to 28 March 2007. - -Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - -### 12. No Surrender of Others' Freedom. - -If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under -this License and any other pertinent obligations, then as a -consequence you may not convey it at all. For example, if you agree to -terms that obligate you to collect a royalty for further conveying -from those to whom you convey the Program, the only way you could -satisfy both those terms and this License would be to refrain entirely -from conveying the Program. - -### 13. Use with the GNU Affero General Public License. - -Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - -### 14. Revised Versions of this License. - -The Free Software Foundation may publish revised and/or new versions -of the GNU General Public License from time to time. Such new versions -will be similar in spirit to the present version, but may differ in -detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies that a certain numbered version of the GNU General Public -License "or any later version" applies to it, you have the option of -following the terms and conditions either of that numbered version or -of any later version published by the Free Software Foundation. If the -Program does not specify a version number of the GNU General Public -License, you may choose any version ever published by the Free -Software Foundation. - -If the Program specifies that a proxy can decide which future versions -of the GNU General Public License can be used, that proxy's public -statement of acceptance of a version permanently authorizes you to -choose that version for the Program. - -Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - -### 15. Disclaimer of Warranty. - -THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT -WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND -PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE -DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR -CORRECTION. - -### 16. Limitation of Liability. - -IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR -CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES -ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT -NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR -LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM -TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER -PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - -### 17. Interpretation of Sections 15 and 16. - -If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - -END OF TERMS AND CONDITIONS - -## How to Apply These Terms to Your New Programs - -If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these -terms. - -To do so, attach the following notices to the program. It is safest to -attach them to the start of each source file to most effectively state -the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper -mail. - -If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands \`show w' and \`show c' should show the -appropriate parts of the General Public License. Of course, your -program's commands might be different; for a GUI interface, you would -use an "about box". - -You should also get your employer (if you work as a programmer) or -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. For more information on this, and how to apply and follow -the GNU GPL, see . - -The GNU General Public License does not permit incorporating your -program into proprietary programs. If your program is a subroutine -library, you may consider it more useful to permit linking proprietary -applications with the library. If this is what you want to do, use the -GNU Lesser General Public License instead of this License. But first, -please read . diff --git a/README.md b/README.md index d95e4f5..64b295e 100644 --- a/README.md +++ b/README.md @@ -1,45 +1,10 @@ -# RetroDebian Live +# RetroDebian Builder V2 skeleton -RetroDebian Live is a custom live distro built on **Debian Etch** for **retro gaming on classic x86 hardware**. +Generated project tree for the RetroDebian V2 workflow. -It is made for machines like the **Pentium II** and **Pentium III**, with one goal: -deliver a **fast, light, period-appropriate Linux system** for old games, old GPUs, and old hardware experiments. +Main entry points: +- `python3 builder/py/build.py validate` +- `python3 builder/py/build.py run-local --profile demo` -This is not a modern desktop squeezed onto old hardware. -It is a purpose-built retro system. - -## Features - -- Debian Etch userspace -- Custom 2.6.24-based kernel -- Live boot with SquashFS + UnionFS -- Lightweight Fluxbox desktop -- Fast startup and low overhead -- Built as a base for 3dfx, Glide, UT99, and hardware test tools - -## Current state - -The system already boots and runs as a real live distro with the custom kernel. - -The next steps are: -- desktop polish -- 3dfx integration -- custom tools -- Unreal Tournament 99 -- optional installer support - -## Philosophy - -RetroDebian Live is built around a simple idea: - -**old hardware deserves software that stays out of its way.** - -Small, responsive, understandable, and tuned for retro gaming. - -Multiple ISO will be generated, including different GPU Drivers. - -The current focus is on 3DFX Voodoo2 :) - -## Technical note - -The project is built with a custom kernel, `live-helper`, Docker, and Jenkins, with the kernel and ISO handled as separate build stages. \ No newline at end of file +The local runner uses fake legacy tools by default when `lh_config` / `lh_build` +are not available. Set `RETRODEBIAN_FAKE_LEGACY_TOOLS=0` to force hard failures. diff --git a/.docker-cache/glide.ref b/artifacts/bases/.gitkeep similarity index 100% rename from .docker-cache/glide.ref rename to artifacts/bases/.gitkeep diff --git a/.docker-cache/icons.ref b/artifacts/features/.gitkeep similarity index 100% rename from .docker-cache/icons.ref rename to artifacts/features/.gitkeep diff --git a/.docker-cache/ut99.ref b/artifacts/profiles/.gitkeep similarity index 100% rename from .docker-cache/ut99.ref rename to artifacts/profiles/.gitkeep diff --git a/bases/retrodebian-common/chroot/README-common-base.txt b/bases/retrodebian-common/chroot/README-common-base.txt new file mode 100644 index 0000000..e9133f0 --- /dev/null +++ b/bases/retrodebian-common/chroot/README-common-base.txt @@ -0,0 +1 @@ +Common base chroot payload. diff --git a/bases/retrodebian-common/entry.py b/bases/retrodebian-common/entry.py new file mode 100644 index 0000000..0710d70 --- /dev/null +++ b/bases/retrodebian-common/entry.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import sys +from pathlib import Path + +THIS_FILE = Path(__file__).resolve() +PROJECT_ROOT = THIS_FILE.parents[2] +PY_ROOT = PROJECT_ROOT / 'builder' / 'py' +if str(PY_ROOT) not in sys.path: + sys.path.insert(0, str(PY_ROOT)) + +from retrobuilder.context import BuildContext +from retrobuilder.entrypoints import BaseEntry, cli_dispatch +from retrobuilder.model import BaseSpec + +SPEC = BaseSpec( + name='retrodebian-common', + description='Common inherited base resources shared by concrete bases.', + packages=(), + package_lists=(), + docker_overrides={}, +) + + +class Entry(BaseEntry): + def pre_gen(self, ctx: BuildContext) -> None: + ctx.current_module_artifact_dir.mkdir(parents=True, exist_ok=True) + (ctx.current_module_artifact_dir / 'pre-gen.txt').write_text('common-base pre-gen\n', encoding='utf-8') + + def post_gen(self, ctx: BuildContext) -> None: + ctx.current_module_artifact_dir.mkdir(parents=True, exist_ok=True) + (ctx.current_module_artifact_dir / 'post-gen.txt').write_text('common-base post-gen\n', encoding='utf-8') + + +if __name__ == '__main__': + raise SystemExit(cli_dispatch(SPEC, Entry)) diff --git a/bases/retrodebian-common/entry.sh b/bases/retrodebian-common/entry.sh new file mode 100644 index 0000000..039e4d0 --- /dev/null +++ b/bases/retrodebian-common/entry.sh @@ -0,0 +1,2 @@ +#!/bin/sh +exit 0 diff --git a/bases/retrodebian-common/generate.sh b/bases/retrodebian-common/generate.sh new file mode 100644 index 0000000..5db7609 --- /dev/null +++ b/bases/retrodebian-common/generate.sh @@ -0,0 +1,8 @@ +#!/bin/sh +set -eu +SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) +MODULE_NAME=$(basename "$SCRIPT_DIR") +: "${CURRENT_MODULE_ARTIFACT_DIR:?CURRENT_MODULE_ARTIFACT_DIR is required}" +mkdir -p "$CURRENT_MODULE_ARTIFACT_DIR/generated" +#printf 'generated base %s\n' "$MODULE_NAME" > "$CURRENT_MODULE_ARTIFACT_DIR/generated/from-generate.txt" +exit 0 diff --git a/bases/retrodebian-common/hooks/05-common-base.sh b/bases/retrodebian-common/hooks/05-common-base.sh new file mode 100644 index 0000000..f35f07b --- /dev/null +++ b/bases/retrodebian-common/hooks/05-common-base.sh @@ -0,0 +1,2 @@ +#!/bin/sh +echo "common-base live hook" diff --git a/bases/retrodebian-common/packageslists/common-base.list b/bases/retrodebian-common/packageslists/common-base.list new file mode 100644 index 0000000..02ba91a --- /dev/null +++ b/bases/retrodebian-common/packageslists/common-base.list @@ -0,0 +1,2 @@ +# common-base package list +nano diff --git a/bases/voodoo2/chroot/etc/retrodebian-base.conf b/bases/voodoo2/chroot/etc/retrodebian-base.conf new file mode 100644 index 0000000..2d77d7c --- /dev/null +++ b/bases/voodoo2/chroot/etc/retrodebian-base.conf @@ -0,0 +1 @@ +BASE=sample-base diff --git a/bases/voodoo2/entry.py b/bases/voodoo2/entry.py new file mode 100644 index 0000000..a89d9d2 --- /dev/null +++ b/bases/voodoo2/entry.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import sys +from pathlib import Path + +THIS_FILE = Path(__file__).resolve() +PROJECT_ROOT = THIS_FILE.parents[2] +PY_ROOT = PROJECT_ROOT / 'builder' / 'py' +if str(PY_ROOT) not in sys.path: + sys.path.insert(0, str(PY_ROOT)) + +from retrobuilder.context import BuildContext +from retrobuilder.entrypoints import BaseEntry, cli_dispatch +from retrobuilder.model import BaseSpec + +SPEC = BaseSpec( + name='sample-base', + description='Sample base used to validate the V2 builder flow.', + parent='common-base', + packages=('sample-base-package',), + package_lists=('sample-base.list',), + docker_overrides={ + # Example: override the legacy pre/post-feature phase with a custom Lenny image. + # 'pre-feature': {'image': 'retrodebian/custom-lenny:latest'}, + # 'post-feature': {'dockerfile': 'bases/sample-base/Dockerfile.lenny'}, + }, +) + + +class Entry(BaseEntry): + def _marker(self, ctx: BuildContext, name: str) -> Path: + ctx.current_module_artifact_dir.mkdir(parents=True, exist_ok=True) + return ctx.current_module_artifact_dir / name + + def pre_gen(self, ctx: BuildContext) -> None: + self._marker(ctx, 'pre-gen.txt').write_text('sample-base pre-gen\n', encoding='utf-8') + + def post_gen(self, ctx: BuildContext) -> None: + self._marker(ctx, 'post-gen.txt').write_text('sample-base post-gen\n', encoding='utf-8') + + def pre_feature(self, ctx: BuildContext) -> None: + notes = ctx.live_dir / 'builder-notes' + notes.mkdir(parents=True, exist_ok=True) + (notes / 'base-pre-feature.txt').write_text('sample-base pre-feature\n', encoding='utf-8') + + def post_feature(self, ctx: BuildContext) -> None: + notes = ctx.live_dir / 'builder-notes' + notes.mkdir(parents=True, exist_ok=True) + (notes / 'base-post-feature.txt').write_text('sample-base post-feature\n', encoding='utf-8') + + +if __name__ == '__main__': + raise SystemExit(cli_dispatch(SPEC, Entry)) diff --git a/bases/voodoo2/entry.sh b/bases/voodoo2/entry.sh new file mode 100644 index 0000000..6246744 --- /dev/null +++ b/bases/voodoo2/entry.sh @@ -0,0 +1,17 @@ +#!/bin/sh +set -eu + +PHASE=${1:-} +[ -n "$PHASE" ] || { echo "Usage: entry.sh " >&2; exit 2; } + +case "$PHASE" in + pre-feature|post-feature) + mkdir -p "$LIVE_DIR/builder-notes" + printf 'sample-base entry.sh %s +' "$PHASE" > "$LIVE_DIR/builder-notes/base-entry-${PHASE}.txt" + ;; + *) + echo "Unsupported base phase: $PHASE" >&2 + exit 2 + ;; +esac diff --git a/bases/voodoo2/generate.sh b/bases/voodoo2/generate.sh new file mode 100644 index 0000000..c9415a1 --- /dev/null +++ b/bases/voodoo2/generate.sh @@ -0,0 +1,7 @@ +#!/bin/sh +set -eu + +[ -n "${CURRENT_MODULE_ARTIFACT_DIR:-}" ] || { echo "CURRENT_MODULE_ARTIFACT_DIR is required" >&2; exit 2; } +mkdir -p "$CURRENT_MODULE_ARTIFACT_DIR/generated" +printf 'generated by sample-base +' > "$CURRENT_MODULE_ARTIFACT_DIR/generated/base-artifact.txt" diff --git a/bases/voodoo2/hooks/10-sample-base.sh b/bases/voodoo2/hooks/10-sample-base.sh new file mode 100644 index 0000000..c6e7a25 --- /dev/null +++ b/bases/voodoo2/hooks/10-sample-base.sh @@ -0,0 +1,4 @@ +#!/bin/sh +set -eu +printf 'sample base chroot hook +' > /tmp/sample-base-hook.txt diff --git a/bases/voodoo2/packages/sample-base_1.0_all.deb b/bases/voodoo2/packages/sample-base_1.0_all.deb new file mode 100644 index 0000000..cfa1fc3 --- /dev/null +++ b/bases/voodoo2/packages/sample-base_1.0_all.deb @@ -0,0 +1 @@ +placeholder deb artifact for sample base diff --git a/bases/voodoo2/packageslists/sample-base.list b/bases/voodoo2/packageslists/sample-base.list new file mode 100644 index 0000000..8c0e1f8 --- /dev/null +++ b/bases/voodoo2/packageslists/sample-base.list @@ -0,0 +1 @@ +nano diff --git a/builder/bash/common.sh b/builder/bash/common.sh new file mode 100644 index 0000000..b6be69b --- /dev/null +++ b/builder/bash/common.sh @@ -0,0 +1,34 @@ +#!/bin/sh + +fail() { + echo "ERROR: $*" >&2 + exit 1 +} + +require_file() { + [ -f "$1" ] || fail "Missing file: $1" +} + +require_dir() { + [ -d "$1" ] || fail "Missing directory: $1" +} + +load_env_file() { + ENV_FILE="$1" + require_file "$ENV_FILE" + set -a + . "$ENV_FILE" + set +a +} + +maybe_fake_legacy() { + TOOL_NAME="$1" + if command -v "$TOOL_NAME" >/dev/null 2>&1; then + return 1 + fi + if [ "${RETRODEBIAN_FAKE_LEGACY_TOOLS:-1}" = "1" ]; then + echo "[fake-legacy] $TOOL_NAME not found, emulating." >&2 + return 0 + fi + fail "$TOOL_NAME not found and RETRODEBIAN_FAKE_LEGACY_TOOLS != 1" +} diff --git a/builder/bash/run_entry.sh b/builder/bash/run_entry.sh new file mode 100644 index 0000000..ecffb5f --- /dev/null +++ b/builder/bash/run_entry.sh @@ -0,0 +1,18 @@ +#!/bin/sh +set -eu + +SELF_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) +. "$SELF_DIR/common.sh" + +MODULE_DIR=${1:-} +ENV_FILE=${2:-} +PHASE=${3:-} +[ -n "$MODULE_DIR" ] || fail "Usage: run_entry.sh " +[ -n "$ENV_FILE" ] || fail "Usage: run_entry.sh " +[ -n "$PHASE" ] || fail "Usage: run_entry.sh " + +require_dir "$MODULE_DIR" +load_env_file "$ENV_FILE" +require_file "$MODULE_DIR/entry.sh" + +exec /bin/sh "$MODULE_DIR/entry.sh" "$PHASE" diff --git a/builder/bash/run_generate.sh b/builder/bash/run_generate.sh new file mode 100644 index 0000000..90f6f6b --- /dev/null +++ b/builder/bash/run_generate.sh @@ -0,0 +1,16 @@ +#!/bin/sh +set -eu + +SELF_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) +. "$SELF_DIR/common.sh" + +MODULE_DIR=${1:-} +ENV_FILE=${2:-} +[ -n "$MODULE_DIR" ] || fail "Usage: run_generate.sh " +[ -n "$ENV_FILE" ] || fail "Usage: run_generate.sh " + +require_dir "$MODULE_DIR" +load_env_file "$ENV_FILE" +require_file "$MODULE_DIR/generate.sh" + +exec /bin/sh "$MODULE_DIR/generate.sh" diff --git a/builder/bash/run_profile_build.sh b/builder/bash/run_profile_build.sh new file mode 100644 index 0000000..04edf3f --- /dev/null +++ b/builder/bash/run_profile_build.sh @@ -0,0 +1,22 @@ +#!/bin/sh +set -eu + +SELF_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) +. "$SELF_DIR/common.sh" + +ENV_FILE=${1:-} +[ -n "$ENV_FILE" ] || fail "Usage: run_profile_build.sh " +load_env_file "$ENV_FILE" + +[ -n "${LIVE_DIR:-}" ] || fail "LIVE_DIR is required" +[ -n "${PROFILE_ARTIFACT_DIR:-}" ] || fail "PROFILE_ARTIFACT_DIR is required" +mkdir -p "$PROFILE_ARTIFACT_DIR/final" + +if maybe_fake_legacy lh_build; then + OUTPUT_FILE="$PROFILE_ARTIFACT_DIR/final/${PROFILE_NAME:-profile}.iso" + printf 'fake iso for %s +' "${PROFILE_NAME:-unknown}" > "$OUTPUT_FILE" + exit 0 +fi + +exec lh_build "$LIVE_DIR" diff --git a/builder/bash/run_profile_config.sh b/builder/bash/run_profile_config.sh new file mode 100644 index 0000000..10eb38c --- /dev/null +++ b/builder/bash/run_profile_config.sh @@ -0,0 +1,21 @@ +#!/bin/sh +set -eu + +SELF_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) +. "$SELF_DIR/common.sh" + +ENV_FILE=${1:-} +[ -n "$ENV_FILE" ] || fail "Usage: run_profile_config.sh " +load_env_file "$ENV_FILE" + +[ -n "${LIVE_DIR:-}" ] || fail "LIVE_DIR is required" +mkdir -p "$LIVE_DIR" + +if maybe_fake_legacy lh_config; then + mkdir -p "$LIVE_DIR/.fake-live-helper" + printf 'fake lh_config for %s +' "${PROFILE_NAME:-unknown}" > "$LIVE_DIR/.fake-live-helper/lh_config.txt" + exit 0 +fi + +exec lh_config "$LIVE_DIR" diff --git a/builder/py/build.py b/builder/py/build.py new file mode 100644 index 0000000..097a90c --- /dev/null +++ b/builder/py/build.py @@ -0,0 +1,388 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import argparse +import os +import subprocess +import sys +from pathlib import Path + +THIS_DIR = Path(__file__).resolve().parent +PACKAGE_ROOT = THIS_DIR / 'retrobuilder' +if str(THIS_DIR) not in sys.path: + sys.path.insert(0, str(THIS_DIR)) + +from retrobuilder.context import BuildContext +from retrobuilder.envfile import write_env_file +from retrobuilder.loader import ( + load_base_chain, + load_base_entry, + load_base_spec, + load_feature_entry, + load_feature_spec, + load_profile, +) +from retrobuilder.model import DockerStageSpec +from retrobuilder.operations import ( + apply_profile_common_configuration, + clear_directory_contents, + ensure_live_structure, + inject_module_resources, + profile_finalize, + profile_pre_build, + save_feature_metadata, + save_profile_metadata, +) +from retrobuilder.paths import ( + base_artifacts_dir, + base_dir, + feature_artifacts_dir, + feature_dir, + profile_artifacts_dir, + project_root_from, +) + + +def root_dir() -> Path: + return project_root_from(Path.cwd()) + + +def list_names(path: Path) -> list[str]: + if not path.exists(): + return [] + return sorted(child.name for child in path.iterdir() if child.is_dir()) + + +def list_profiles(path: Path) -> list[str]: + if not path.exists(): + return [] + return sorted(p.stem for p in path.glob('*.py') if p.is_file()) + + +def build_context(root: Path, phase: str, kind: str, profile_name: str = '', base_name: str = '', feature_name: str = '') -> BuildContext: + live_dir = root / 'live' + artifacts_root = root / 'artifacts' + profile = load_profile(root, profile_name) if profile_name else None + base = load_base_spec(root, base_name or (profile.base if profile else '')) if (base_name or profile) else None + feature = load_feature_spec(root, feature_name) if feature_name else None + + current_name = { + 'profile': profile_name, + 'base': base.name if base else '', + 'feature': feature.name if feature else '', + }[kind] + current_dir = { + 'profile': root / 'profiles' / f'{profile_name}.py', + 'base': base_dir(root, base.name if base else base_name), + 'feature': feature_dir(root, feature.name if feature else feature_name), + }[kind] + current_artifact_dir = { + 'profile': profile_artifacts_dir(root, profile_name), + 'base': base_artifacts_dir(root, base.name if base else base_name), + 'feature': feature_artifacts_dir(root, feature.name if feature else feature_name), + }[kind] + + return BuildContext( + project_root=root, + live_dir=live_dir, + artifacts_root=artifacts_root, + phase=phase, + current_kind=kind, + current_name=current_name, + current_module_dir=current_dir, + current_module_artifact_dir=current_artifact_dir, + profile_name=profile.name if profile else profile_name, + profile_artifact_dir=profile_artifacts_dir(root, profile.name) if profile else None, + base_name=base.name if base else '', + base_dir=base_dir(root, base.name) if base else None, + base_artifact_dir=base_artifacts_dir(root, base.name) if base else None, + feature_name=feature.name if feature else '', + feature_dir=feature_dir(root, feature.name) if feature else None, + feature_artifact_dir=feature_artifacts_dir(root, feature.name) if feature else None, + profile_features=tuple(profile.features) if profile else (), + ) + + +def run_python_phase(args: argparse.Namespace) -> int: + root = root_dir() + ctx = build_context(root, args.phase, args.kind, args.profile or '', args.base or '', args.feature or '') + if args.kind == 'base': + entry_cls = load_base_entry(root, ctx.base_name) + elif args.kind == 'feature': + entry_cls = load_feature_entry(root, ctx.feature_name) + else: + raise ValueError(f'Unsupported kind {args.kind}') + entry = entry_cls() + method = getattr(entry, args.phase.replace('-', '_')) + method(ctx) + return 0 + + +def export_env(args: argparse.Namespace) -> int: + root = root_dir() + kind = args.kind + ctx = build_context(root, args.phase, kind, args.profile or '', args.base or '', args.feature or '') + values = ctx.to_env() + values['RETRODEBIAN_FAKE_LEGACY_TOOLS'] = os.environ.get('RETRODEBIAN_FAKE_LEGACY_TOOLS', '1') + write_env_file(Path(args.output), values) + return 0 + + +def cmd_validate(args: argparse.Namespace) -> int: + root = root_dir() + for profile_name in list_profiles(root / 'profiles'): + profile = load_profile(root, profile_name) + load_base_spec(root, profile.base) + for feature_name in profile.features: + load_feature_spec(root, feature_name) + print('Validation OK') + return 0 + + +def cmd_list(args: argparse.Namespace) -> int: + root = root_dir() + if args.what == 'features': + values = list_names(root / 'features') + elif args.what == 'bases': + values = list_names(root / 'bases') + else: + values = list_profiles(root / 'profiles') + for value in values: + print(value) + return 0 + + +def _load_module_spec(root: Path, kind: str, name: str): + if kind == 'base': + return load_base_spec(root, name) + if kind == 'feature': + return load_feature_spec(root, name) + raise ValueError(kind) + + +def _docker_override_field(spec, phase: str, field: str) -> str: + stage = spec.docker_overrides.get(phase) + if stage is None: + return '' + value = getattr(stage, field) + return value or '' + + +def cmd_module_docker(args: argparse.Namespace) -> int: + root = root_dir() + spec = _load_module_spec(root, args.kind, args.name) + print(_docker_override_field(spec, args.phase, args.field)) + return 0 + + +def cmd_profile_info(args: argparse.Namespace) -> int: + root = root_dir() + profile = load_profile(root, args.profile) + if args.field == 'base': + print(profile.base) + elif args.field == 'base-chain': + for base_spec in load_base_chain(root, profile.base): + print(base_spec.name) + elif args.field == 'features': + for feature in profile.features: + print(feature) + else: + raise ValueError(args.field) + return 0 + + +def cmd_prepare_profile(args: argparse.Namespace) -> int: + root = root_dir() + profile = load_profile(root, args.profile) + base = load_base_spec(root, profile.base) + base_chain = load_base_chain(root, profile.base) + live_dir = root / 'live' + clear_directory_contents(live_dir) + ensure_live_structure(live_dir) + save_profile_metadata(profile_artifacts_dir(root, profile.name) / 'profile.json', profile, base, base_chain) + apply_profile_common_configuration(root, live_dir, profile) + return 0 + + +def cmd_save_feature_metadata(args: argparse.Namespace) -> int: + root = root_dir() + feature = load_feature_spec(root, args.feature) + target = profile_artifacts_dir(root, args.profile) / 'features' / f'{feature.name}.json' + save_feature_metadata(target, feature) + return 0 + + +def cmd_inject_resources(args: argparse.Namespace) -> int: + root = root_dir() + live_dir = root / 'live' + ensure_live_structure(live_dir) + if args.kind == 'base': + for base_spec in load_base_chain(root, args.name): + inject_module_resources(base_dir(root, base_spec.name), live_dir, base_spec.name) + else: + inject_module_resources(feature_dir(root, args.name), live_dir, args.name) + return 0 + + +def cmd_profile_common(args: argparse.Namespace) -> int: + root = root_dir() + profile = load_profile(root, args.profile) + apply_profile_common_configuration(root, root / 'live', profile) + return 0 + + +def cmd_profile_pre_build(args: argparse.Namespace) -> int: + root = root_dir() + profile_pre_build(root / 'live', args.profile) + return 0 + + +def cmd_profile_finalize(args: argparse.Namespace) -> int: + root = root_dir() + profile_finalize(root, args.profile) + return 0 + + +def _run(cmd: list[str], env: dict[str, str] | None = None) -> None: + subprocess.run(cmd, check=True, env=env) + + +def _env_and_path(root: Path, kind: str, phase: str, profile: str, base: str = '', feature: str = '') -> tuple[dict[str, str], Path]: + ctx = build_context(root, phase, kind, profile, base, feature) + values = os.environ.copy() + values.update(ctx.to_env()) + values['RETRODEBIAN_FAKE_LEGACY_TOOLS'] = values.get('RETRODEBIAN_FAKE_LEGACY_TOOLS', '1') + env_path = profile_artifacts_dir(root, profile) / 'runtime' / f'{kind}-{ctx.current_name}-{phase}.env' + write_env_file(env_path, {k: str(v) for k, v in values.items() if k in ctx.to_env() or k == 'RETRODEBIAN_FAKE_LEGACY_TOOLS'}) + return values, env_path + + +def cmd_run_local(args: argparse.Namespace) -> int: + root = root_dir() + profile = load_profile(root, args.profile) + + for feature_name in list_names(root / 'features'): + env, env_path = _env_and_path(root, 'feature', 'pre-gen', args.profile, feature=feature_name) + _run([sys.executable, str(feature_dir(root, feature_name) / 'entry.py'), 'pre-gen'], env=env) + _run([str(root / 'builder' / 'bash' / 'run_generate.sh'), str(feature_dir(root, feature_name)), str(env_path)]) + env, _ = _env_and_path(root, 'feature', 'post-gen', args.profile, feature=feature_name) + _run([sys.executable, str(feature_dir(root, feature_name) / 'entry.py'), 'post-gen'], env=env) + + env, env_path = _env_and_path(root, 'base', 'pre-gen', args.profile, base=profile.base) + _run([sys.executable, str(base_dir(root, profile.base) / 'entry.py'), 'pre-gen'], env=env) + _run([str(root / 'builder' / 'bash' / 'run_generate.sh'), str(base_dir(root, profile.base)), str(env_path)]) + env, _ = _env_and_path(root, 'base', 'post-gen', args.profile, base=profile.base) + _run([sys.executable, str(base_dir(root, profile.base) / 'entry.py'), 'post-gen'], env=env) + + _run([sys.executable, str(root / 'builder' / 'py' / 'build.py'), 'prepare-profile', '--profile', args.profile]) + env, env_path = _env_and_path(root, 'profile', 'config', args.profile) + _run([str(root / 'builder' / 'bash' / 'run_profile_config.sh'), str(env_path)]) + + _run([sys.executable, str(root / 'builder' / 'py' / 'build.py'), 'inject-resources', '--kind', 'base', '--name', profile.base]) + env, env_path = _env_and_path(root, 'base', 'pre-feature', args.profile, base=profile.base) + _run([sys.executable, str(base_dir(root, profile.base) / 'entry.py'), 'pre-feature'], env=env) + _run([str(root / 'builder' / 'bash' / 'run_entry.sh'), str(base_dir(root, profile.base)), str(env_path), 'pre-feature']) + + for feature_name in profile.features: + _run([sys.executable, str(root / 'builder' / 'py' / 'build.py'), 'save-feature-metadata', '--profile', args.profile, '--feature', feature_name]) + env, env_path = _env_and_path(root, 'feature', 'pre-inj', args.profile, feature=feature_name) + _run([sys.executable, str(feature_dir(root, feature_name) / 'entry.py'), 'pre-inj'], env=env) + _run([str(root / 'builder' / 'bash' / 'run_entry.sh'), str(feature_dir(root, feature_name)), str(env_path), 'pre-inj']) + _run([sys.executable, str(root / 'builder' / 'py' / 'build.py'), 'inject-resources', '--kind', 'feature', '--name', feature_name]) + env, env_path = _env_and_path(root, 'feature', 'post-inj', args.profile, feature=feature_name) + _run([str(root / 'builder' / 'bash' / 'run_entry.sh'), str(feature_dir(root, feature_name)), str(env_path), 'post-inj']) + _run([sys.executable, str(feature_dir(root, feature_name) / 'entry.py'), 'post-inj'], env=env) + + env, env_path = _env_and_path(root, 'base', 'post-feature', args.profile, base=profile.base) + _run([sys.executable, str(base_dir(root, profile.base) / 'entry.py'), 'post-feature'], env=env) + _run([str(root / 'builder' / 'bash' / 'run_entry.sh'), str(base_dir(root, profile.base)), str(env_path), 'post-feature']) + _run([sys.executable, str(root / 'builder' / 'py' / 'build.py'), 'profile-pre-build', '--profile', args.profile]) + + env, env_path = _env_and_path(root, 'profile', 'build', args.profile) + _run([str(root / 'builder' / 'bash' / 'run_profile_build.sh'), str(env_path)]) + _run([sys.executable, str(root / 'builder' / 'py' / 'build.py'), 'profile-finalize', '--profile', args.profile]) + print(f'Local pipeline completed for profile {args.profile}') + return 0 + + +def build_parser() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser(description='RetroDebian builder helper') + sub = parser.add_subparsers(dest='command', required=True) + + p = sub.add_parser('validate') + p.set_defaults(func=cmd_validate) + + p = sub.add_parser('list') + p.add_argument('what', choices=['features', 'bases', 'profiles']) + p.set_defaults(func=cmd_list) + + p = sub.add_parser('profile-info') + p.add_argument('--profile', required=True) + p.add_argument('field', choices=['base', 'base-chain', 'features']) + p.set_defaults(func=cmd_profile_info) + + p = sub.add_parser('module-docker') + p.add_argument('--kind', choices=['base', 'feature'], required=True) + p.add_argument('--name', required=True) + p.add_argument('--phase', required=True) + p.add_argument('field', choices=['image', 'dockerfile', 'docker_context']) + p.set_defaults(func=cmd_module_docker) + + p = sub.add_parser('run-python-phase') + p.add_argument('--kind', choices=['base', 'feature'], required=True) + p.add_argument('--phase', required=True) + p.add_argument('--profile') + p.add_argument('--base') + p.add_argument('--feature') + p.set_defaults(func=run_python_phase) + + p = sub.add_parser('export-env') + p.add_argument('--kind', choices=['profile', 'base', 'feature'], required=True) + p.add_argument('--phase', required=True) + p.add_argument('--profile', default='') + p.add_argument('--base', default='') + p.add_argument('--feature', default='') + p.add_argument('--output', required=True) + p.set_defaults(func=export_env) + + p = sub.add_parser('prepare-profile') + p.add_argument('--profile', required=True) + p.set_defaults(func=cmd_prepare_profile) + + p = sub.add_parser('save-feature-metadata') + p.add_argument('--profile', required=True) + p.add_argument('--feature', required=True) + p.set_defaults(func=cmd_save_feature_metadata) + + p = sub.add_parser('inject-resources') + p.add_argument('--kind', choices=['base', 'feature'], required=True) + p.add_argument('--name', required=True) + p.set_defaults(func=cmd_inject_resources) + + p = sub.add_parser('profile-common') + p.add_argument('--profile', required=True) + p.set_defaults(func=cmd_profile_common) + + p = sub.add_parser('profile-pre-build') + p.add_argument('--profile', required=True) + p.set_defaults(func=cmd_profile_pre_build) + + p = sub.add_parser('profile-finalize') + p.add_argument('--profile', required=True) + p.set_defaults(func=cmd_profile_finalize) + + p = sub.add_parser('run-local') + p.add_argument('--profile', required=True) + p.set_defaults(func=cmd_run_local) + + return parser + + +def main() -> int: + parser = build_parser() + args = parser.parse_args() + return args.func(args) + + +if __name__ == '__main__': + raise SystemExit(main()) diff --git a/builder/py/retrobuilder/__init__.py b/builder/py/retrobuilder/__init__.py new file mode 100644 index 0000000..d19709c --- /dev/null +++ b/builder/py/retrobuilder/__init__.py @@ -0,0 +1,9 @@ +__all__ = [ + 'context', + 'entrypoints', + 'envfile', + 'loader', + 'model', + 'operations', + 'paths', +] diff --git a/builder/py/retrobuilder/context.py b/builder/py/retrobuilder/context.py new file mode 100644 index 0000000..2704340 --- /dev/null +++ b/builder/py/retrobuilder/context.py @@ -0,0 +1,80 @@ +from __future__ import annotations + +from dataclasses import dataclass +from pathlib import Path +from typing import Mapping + + +@dataclass(frozen=True) +class BuildContext: + project_root: Path + live_dir: Path + artifacts_root: Path + phase: str + current_kind: str + current_name: str + current_module_dir: Path + current_module_artifact_dir: Path + profile_name: str = '' + profile_artifact_dir: Path | None = None + base_name: str = '' + base_dir: Path | None = None + base_artifact_dir: Path | None = None + feature_name: str = '' + feature_dir: Path | None = None + feature_artifact_dir: Path | None = None + profile_features: tuple[str, ...] = () + + def to_env(self) -> dict[str, str]: + env = { + 'PROJECT_ROOT': str(self.project_root), + 'LIVE_DIR': str(self.live_dir), + 'ARTIFACTS_ROOT': str(self.artifacts_root), + 'PHASE': self.phase, + 'CURRENT_KIND': self.current_kind, + 'CURRENT_NAME': self.current_name, + 'CURRENT_MODULE_DIR': str(self.current_module_dir), + 'CURRENT_MODULE_ARTIFACT_DIR': str(self.current_module_artifact_dir), + 'PROFILE_NAME': self.profile_name, + 'BASE_NAME': self.base_name, + 'FEATURE_NAME': self.feature_name, + 'PROFILE_FEATURES': '|'.join(self.profile_features), + } + if self.profile_artifact_dir is not None: + env['PROFILE_ARTIFACT_DIR'] = str(self.profile_artifact_dir) + if self.base_dir is not None: + env['BASE_DIR'] = str(self.base_dir) + if self.base_artifact_dir is not None: + env['BASE_ARTIFACT_DIR'] = str(self.base_artifact_dir) + if self.feature_dir is not None: + env['FEATURE_DIR'] = str(self.feature_dir) + if self.feature_artifact_dir is not None: + env['FEATURE_ARTIFACT_DIR'] = str(self.feature_artifact_dir) + return env + + @classmethod + def from_env(cls, env: Mapping[str, str]) -> 'BuildContext': + def p(name: str) -> Path | None: + value = env.get(name, '') + return Path(value) if value else None + + features = tuple(filter(None, env.get('PROFILE_FEATURES', '').split('|'))) + return cls( + project_root=Path(env['PROJECT_ROOT']), + live_dir=Path(env['LIVE_DIR']), + artifacts_root=Path(env['ARTIFACTS_ROOT']), + phase=env['PHASE'], + current_kind=env['CURRENT_KIND'], + current_name=env['CURRENT_NAME'], + current_module_dir=Path(env['CURRENT_MODULE_DIR']), + current_module_artifact_dir=Path(env['CURRENT_MODULE_ARTIFACT_DIR']), + profile_name=env.get('PROFILE_NAME', ''), + profile_artifact_dir=p('PROFILE_ARTIFACT_DIR'), + base_name=env.get('BASE_NAME', ''), + base_dir=p('BASE_DIR'), + base_artifact_dir=p('BASE_ARTIFACT_DIR'), + feature_name=env.get('FEATURE_NAME', ''), + feature_dir=p('FEATURE_DIR'), + feature_artifact_dir=p('FEATURE_ARTIFACT_DIR'), + profile_features=features, + ) diff --git a/builder/py/retrobuilder/entrypoints.py b/builder/py/retrobuilder/entrypoints.py new file mode 100644 index 0000000..7664f5e --- /dev/null +++ b/builder/py/retrobuilder/entrypoints.py @@ -0,0 +1,57 @@ +from __future__ import annotations + +import json +import sys +from abc import ABC +from pathlib import Path + +from retrobuilder.context import BuildContext + + +class BaseEntry(ABC): + def pre_gen(self, ctx: BuildContext) -> None: + return None + + def post_gen(self, ctx: BuildContext) -> None: + return None + + def pre_feature(self, ctx: BuildContext) -> None: + return None + + def post_feature(self, ctx: BuildContext) -> None: + return None + + +class FeatureEntry(ABC): + def pre_gen(self, ctx: BuildContext) -> None: + return None + + def post_gen(self, ctx: BuildContext) -> None: + return None + + def pre_inj(self, ctx: BuildContext) -> None: + return None + + def post_inj(self, ctx: BuildContext) -> None: + return None + + +def cli_dispatch(spec, entry_cls) -> int: + if len(sys.argv) < 2: + print('Usage: entry.py ', file=sys.stderr) + return 2 + + command = sys.argv[1] + if command == 'spec': + print(json.dumps(spec.to_dict(), indent=2, sort_keys=True)) + return 0 + + ctx = BuildContext.from_env(dict(__import__('os').environ)) + entry = entry_cls() + method_name = command.replace('-', '_') + method = getattr(entry, method_name, None) + if method is None: + print(f'Unsupported phase: {command}', file=sys.stderr) + return 2 + method(ctx) + return 0 diff --git a/builder/py/retrobuilder/envfile.py b/builder/py/retrobuilder/envfile.py new file mode 100644 index 0000000..6f4491e --- /dev/null +++ b/builder/py/retrobuilder/envfile.py @@ -0,0 +1,16 @@ +from __future__ import annotations + +from pathlib import Path +from typing import Mapping + + +def _escape(value: str) -> str: + value = value.replace('\\', '\\\\').replace('"', '\\"') + return f'"{value}"' + + +def write_env_file(path: Path, values: Mapping[str, str]) -> None: + path.parent.mkdir(parents=True, exist_ok=True) + with path.open('w', encoding='utf-8') as handle: + for key in sorted(values): + handle.write(f'{key}={_escape(str(values[key]))}\n') diff --git a/builder/py/retrobuilder/loader.py b/builder/py/retrobuilder/loader.py new file mode 100644 index 0000000..0360990 --- /dev/null +++ b/builder/py/retrobuilder/loader.py @@ -0,0 +1,81 @@ +from __future__ import annotations + +import importlib.util +from pathlib import Path +from types import ModuleType + +from retrobuilder.model import BaseSpec, FeatureSpec, ProfileSpec +from retrobuilder.paths import base_dir, feature_dir, profile_file + + +def _load_module(path: Path, name: str) -> ModuleType: + spec = importlib.util.spec_from_file_location(name, path) + if spec is None or spec.loader is None: + raise RuntimeError(f'Cannot load module from {path}') + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + +def load_profile(root: Path, name: str) -> ProfileSpec: + path = profile_file(root, name) + module = _load_module(path, f'profile_{name}') + profile = getattr(module, 'PROFILE', None) + if not isinstance(profile, ProfileSpec): + raise TypeError(f'{path} must define PROFILE as ProfileSpec') + return profile + + +def load_base_module(root: Path, name: str) -> ModuleType: + return _load_module(base_dir(root, name) / 'entry.py', f'base_{name}') + + +def load_feature_module(root: Path, name: str) -> ModuleType: + return _load_module(feature_dir(root, name) / 'entry.py', f'feature_{name}') + + +def load_base_spec(root: Path, name: str) -> BaseSpec: + module = load_base_module(root, name) + spec = getattr(module, 'SPEC', None) + if not isinstance(spec, BaseSpec): + raise TypeError(f'bases/{name}/entry.py must define SPEC as BaseSpec') + return spec + + +def load_base_chain(root: Path, name: str) -> list[BaseSpec]: + chain: list[BaseSpec] = [] + seen: set[str] = set() + current = name + while current: + if current in seen: + raise RuntimeError(f'Base inheritance loop detected at {current}') + seen.add(current) + spec = load_base_spec(root, current) + chain.append(spec) + current = spec.parent or '' + chain.reverse() + return chain + + +def load_feature_spec(root: Path, name: str) -> FeatureSpec: + module = load_feature_module(root, name) + spec = getattr(module, 'SPEC', None) + if not isinstance(spec, FeatureSpec): + raise TypeError(f'features/{name}/entry.py must define SPEC as FeatureSpec') + return spec + + +def load_base_entry(root: Path, name: str): + module = load_base_module(root, name) + entry_cls = getattr(module, 'Entry', None) + if entry_cls is None: + raise TypeError(f'bases/{name}/entry.py must define Entry') + return entry_cls + + +def load_feature_entry(root: Path, name: str): + module = load_feature_module(root, name) + entry_cls = getattr(module, 'Entry', None) + if entry_cls is None: + raise TypeError(f'features/{name}/entry.py must define Entry') + return entry_cls diff --git a/builder/py/retrobuilder/model.py b/builder/py/retrobuilder/model.py new file mode 100644 index 0000000..97c2521 --- /dev/null +++ b/builder/py/retrobuilder/model.py @@ -0,0 +1,100 @@ +from __future__ import annotations + +from dataclasses import dataclass, field, asdict +from typing import Any + + +def _tuple(values: Any) -> tuple[str, ...]: + if values is None: + return () + if isinstance(values, tuple): + return values + if isinstance(values, list): + return tuple(str(v) for v in values) + raise TypeError(f'Expected list/tuple/None, got {type(values)!r}') + + +@dataclass(frozen=True) +class DockerStageSpec: + image: str | None = None + dockerfile: str | None = None + docker_context: str | None = None + + def __post_init__(self) -> None: + if self.image is not None and not isinstance(self.image, str): + raise TypeError('DockerStageSpec.image must be str or None') + if self.dockerfile is not None and not isinstance(self.dockerfile, str): + raise TypeError('DockerStageSpec.dockerfile must be str or None') + if self.docker_context is not None and not isinstance(self.docker_context, str): + raise TypeError('DockerStageSpec.docker_context must be str or None') + + @classmethod + def from_value(cls, value: Any) -> 'DockerStageSpec': + if isinstance(value, DockerStageSpec): + return value + if isinstance(value, dict): + return cls( + image=value.get('image'), + dockerfile=value.get('dockerfile'), + docker_context=value.get('docker_context'), + ) + raise TypeError(f'Expected DockerStageSpec or dict, got {type(value)!r}') + + def to_dict(self) -> dict[str, Any]: + return asdict(self) + + +def _docker_overrides(values: Any) -> dict[str, DockerStageSpec]: + if values is None: + return {} + if not isinstance(values, dict): + raise TypeError(f'Expected dict/None for docker_overrides, got {type(values)!r}') + result: dict[str, DockerStageSpec] = {} + for phase, item in values.items(): + if not isinstance(phase, str): + raise TypeError('docker_overrides keys must be strings') + result[phase] = DockerStageSpec.from_value(item) + return result + + +@dataclass(frozen=True) +class ModuleSpec: + title: str = '' + description: str = '' + docker_overrides: dict[str, DockerStageSpec] = field(default_factory=dict) + + def __post_init__(self) -> None: + object.__setattr__(self, 'packages', _tuple(self.packages)) + object.__setattr__(self, 'package_lists', _tuple(self.package_lists)) + object.__setattr__(self, 'docker_overrides', _docker_overrides(self.docker_overrides)) + + def to_dict(self) -> dict[str, Any]: + payload = asdict(self) + payload['docker_overrides'] = {name: spec.to_dict() for name, spec in self.docker_overrides.items()} + return payload + + +@dataclass(frozen=True) +class BaseSpec(ModuleSpec): + parent: str | None = None + + +@dataclass(frozen=True) +class FeatureSpec(ModuleSpec): + pass + + +@dataclass(frozen=True) +class ProfileSpec: + title: str = '' + base: str + features: tuple[str, ...] = field(default_factory=tuple) + edition: str = '' + description: str = '' + splash: str | None = None + + def __post_init__(self) -> None: + object.__setattr__(self, 'features', _tuple(self.features)) + + def to_dict(self) -> dict[str, Any]: + return asdict(self) diff --git a/builder/py/retrobuilder/operations.py b/builder/py/retrobuilder/operations.py new file mode 100644 index 0000000..20532ed --- /dev/null +++ b/builder/py/retrobuilder/operations.py @@ -0,0 +1,115 @@ +from __future__ import annotations + +import json +import shutil +from pathlib import Path + +from retrobuilder.model import BaseSpec, FeatureSpec, ProfileSpec + + +LIVE_DIR_STRUCTURE = ( + 'config/chroot_local-packageslists', + 'config/chroot_local-packages', + 'config/chroot_local-includes', + 'config/chroot_local-hooks', +) + + +def ensure_live_structure(live_dir: Path) -> None: + for relative in LIVE_DIR_STRUCTURE: + (live_dir / relative).mkdir(parents=True, exist_ok=True) + + +def clear_directory_contents(path: Path) -> None: + path.mkdir(parents=True, exist_ok=True) + for child in path.iterdir(): + if child.name == '.gitkeep': + continue + if child.is_dir() and not child.is_symlink(): + shutil.rmtree(child) + else: + child.unlink() + + +def copy_tree_contents(src: Path, dst: Path) -> None: + if not src.exists(): + return + dst.mkdir(parents=True, exist_ok=True) + for child in src.iterdir(): + target = dst / child.name + if child.is_dir(): + shutil.copytree(child, target, dirs_exist_ok=True) + else: + shutil.copy2(child, target) + + +def copy_glob(src_dir: Path, pattern: str, dst_dir: Path, prefix: str = '') -> None: + if not src_dir.exists(): + return + dst_dir.mkdir(parents=True, exist_ok=True) + for src in sorted(src_dir.glob(pattern)): + if src.is_dir(): + continue + name = f'{prefix}{src.name}' if prefix else src.name + shutil.copy2(src, dst_dir / name) + + +def save_json(path: Path, payload: dict) -> None: + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text(json.dumps(payload, indent=2, sort_keys=True) + '\n', encoding='utf-8') + + +def save_profile_metadata(path: Path, profile: ProfileSpec, base: BaseSpec, base_chain: list[BaseSpec] | None = None) -> None: + save_json(path, { + 'profile': profile.to_dict(), + 'base': base.to_dict(), + 'base_chain': [item.to_dict() for item in (base_chain or [base])], + }) + + +def save_feature_metadata(path: Path, feature: FeatureSpec) -> None: + save_json(path, feature.to_dict()) + + +def apply_profile_common_configuration(root: Path, live_dir: Path, profile: ProfileSpec) -> None: + ensure_live_structure(live_dir) + notes_dir = live_dir / 'builder-notes' + notes_dir.mkdir(parents=True, exist_ok=True) + notes = [ + f'profile={profile.name}', + f'base={profile.base}', + f'features={"|".join(profile.features)}', + ] + if profile.splash: + splash_src = root / profile.splash + if splash_src.exists(): + splash_dst = notes_dir / splash_src.name + shutil.copy2(splash_src, splash_dst) + notes.append(f'splash={profile.splash}') + (notes_dir / 'profile-common.txt').write_text('\n'.join(notes) + '\n', encoding='utf-8') + + +def inject_module_resources(module_dir: Path, live_dir: Path, prefix: str) -> None: + copy_tree_contents(module_dir / 'packageslists', live_dir / 'config' / 'chroot_local-packageslists') + copy_tree_contents(module_dir / 'packages', live_dir / 'config' / 'chroot_local-packages') + copy_tree_contents(module_dir / 'chroot', live_dir / 'config' / 'chroot_local-includes') + copy_glob(module_dir / 'hooks', '*.sh', live_dir / 'config' / 'chroot_local-hooks', prefix=f'{prefix}_') + + +def profile_pre_build(live_dir: Path, profile_name: str) -> None: + marker = live_dir / 'builder-notes' / 'pre-build.txt' + marker.parent.mkdir(parents=True, exist_ok=True) + marker.write_text(f'pre-build profile={profile_name}\n', encoding='utf-8') + + +def profile_finalize(root: Path, profile_name: str) -> None: + live_dir = root / 'live' + out_dir = root / 'artifacts' / 'profiles' / profile_name / 'final' + out_dir.mkdir(parents=True, exist_ok=True) + summary = out_dir / 'summary.txt' + summary.write_text( + 'Profile finalization complete.\n' + f'profile={profile_name}\n' + f'live_exists={live_dir.exists()}\n', + encoding='utf-8', + ) diff --git a/builder/py/retrobuilder/paths.py b/builder/py/retrobuilder/paths.py new file mode 100644 index 0000000..def0fb3 --- /dev/null +++ b/builder/py/retrobuilder/paths.py @@ -0,0 +1,35 @@ +from __future__ import annotations + +from pathlib import Path + + +def project_root_from(start: Path) -> Path: + current = start.resolve() + for candidate in (current, *current.parents): + if (candidate / 'builder' / 'py').exists() and (candidate / 'profiles').exists(): + return candidate + raise RuntimeError(f'Could not locate project root from {start}') + + +def feature_dir(root: Path, name: str) -> Path: + return root / 'features' / name + + +def base_dir(root: Path, name: str) -> Path: + return root / 'bases' / name + + +def profile_file(root: Path, name: str) -> Path: + return root / 'profiles' / f'{name}.py' + + +def feature_artifacts_dir(root: Path, name: str) -> Path: + return root / 'artifacts' / 'features' / name + + +def base_artifacts_dir(root: Path, name: str) -> Path: + return root / 'artifacts' / 'bases' / name + + +def profile_artifacts_dir(root: Path, name: str) -> Path: + return root / 'artifacts' / 'profiles' / name diff --git a/buildglidepkg.sh b/buildglidepkg.sh deleted file mode 100755 index 1a2168f..0000000 --- a/buildglidepkg.sh +++ /dev/null @@ -1,149 +0,0 @@ -#!/bin/bash -set -euo pipefail - -FLAVOUR="${1:-cvg}" -ARCH="${ARCH:-i386}" -OUTDIR="${OUTDIR:-$(pwd)}" - -if [[ "$FLAVOUR" == "sst1" ]]; then - GLIDE2_SRC="/usr/src/glide/glide2x/sst1/lib/sst1" - GLIDE3_SRC="/usr/src/glide/glide3x/sst1/lib/sst1" -elif [[ "$FLAVOUR" == "sst96" ]]; then - GLIDE2_SRC="/usr/src/glide/glide2x/sst1/lib/sst96" - GLIDE3_SRC="/usr/src/glide/glide3x/sst1/lib/sst96" -else - GLIDE2_SRC="/usr/src/glide/glide2x/${FLAVOUR}/lib" - GLIDE3_SRC="/usr/src/glide/glide3x/${FLAVOUR}/lib" -fi - -PKG2="libglide2-${FLAVOUR}" -PKG3="libglide3-${FLAVOUR}" - -BUILDROOT="$(pwd)/pkg-glide" -rm -rf "${BUILDROOT}" -mkdir -p "${BUILDROOT}" "${OUTDIR}" - -find_unique_regular_file() { - local dir="$1" - local pattern="$2" - local matches=() - - while IFS= read -r -d '' f; do - matches+=("$f") - done < <(find "$dir" -maxdepth 1 -type f -name "$pattern" -print0) - - if [[ ${#matches[@]} -eq 0 ]]; then - echo "ERROR: no regular file matching '${pattern}' found in '${dir}'" >&2 - exit 1 - fi - - if [[ ${#matches[@]} -ne 1 ]]; then - echo "ERROR: multiple regular files matching '${pattern}' found in '${dir}':" >&2 - printf ' %s\n' "${matches[@]}" >&2 - exit 1 - fi - - basename "${matches[0]}" -} - -extract_glide2_pkg_version() { - local real_so="$1" - local ver="${real_so#libglide.so.}" - echo "${ver}-1" -} - -extract_glide3_pkg_version() { - local real_so="$1" - local ver="${real_so#libglide3.so.}" - echo "${ver}-1" -} - -build_pkg_glide2() { - local PKGDIR="${BUILDROOT}/${PKG2}" - local REAL_SO - local STATIC_A="libglide.a" - local PKG_VERSION - - mkdir -p "${PKGDIR}/DEBIAN" "${PKGDIR}/usr/lib" - - REAL_SO="$(find_unique_regular_file "${GLIDE2_SRC}" 'libglide.so.2.*')" - PKG_VERSION="$(extract_glide2_pkg_version "${REAL_SO}")" - - ls -al "${GLIDE2_SRC}/" - - cp -a "${GLIDE2_SRC}/${REAL_SO}" "${PKGDIR}/usr/lib/" - cp -a "${GLIDE2_SRC}/${STATIC_A}" "${PKGDIR}/usr/lib/" - - ln -s "${REAL_SO}" "${PKGDIR}/usr/lib/libglide.so.2" - ln -s "${REAL_SO}" "${PKGDIR}/usr/lib/libglide.so" - ln -s "${REAL_SO}" "${PKGDIR}/usr/lib/libglide2x.so" - - cat > "${PKGDIR}/DEBIAN/control" < -Provides: libglide2 -Conflicts: libglide2, libglide2-sst1, libglide2-cvg, libglide2-h3, libglide2-h5 -Replaces: libglide2, libglide2-sst1, libglide2-cvg, libglide2-h3, libglide2-h5 -Description: Glide 2 libraries for 3Dfx ${FLAVOUR} - Glide 2 runtime and static libraries for the 3Dfx ${FLAVOUR} family. -EOF - - sed -i "s/, ${PKG2}//" "${PKGDIR}/DEBIAN/control" - - dpkg-deb --build "${PKGDIR}" "${OUTDIR}/${PKG2}_${PKG_VERSION}_${ARCH}.deb" -} - -build_pkg_glide3() { - local PKGDIR="${BUILDROOT}/${PKG3}" - local REAL_SO - local STATIC_A="libglide3.a" - local PKG_VERSION - - mkdir -p "${PKGDIR}/DEBIAN" "${PKGDIR}/usr/lib" - - REAL_SO="$(find_unique_regular_file "${GLIDE3_SRC}" 'libglide3.so.3.*')" - PKG_VERSION="$(extract_glide3_pkg_version "${REAL_SO}")" - - ls -al "${GLIDE3_SRC}/" - - cp -a "${GLIDE3_SRC}/${REAL_SO}" "${PKGDIR}/usr/lib/" - cp -a "${GLIDE3_SRC}/${STATIC_A}" "${PKGDIR}/usr/lib/" - - ln -s "${REAL_SO}" "${PKGDIR}/usr/lib/libglide3.so.3" - ln -s "${REAL_SO}" "${PKGDIR}/usr/lib/libglide3.so" - ln -s "${REAL_SO}" "${PKGDIR}/usr/lib/libglide3x.so" - - cat > "${PKGDIR}/DEBIAN/control" < -Provides: libglide3 -Conflicts: libglide3, libglide3-sst1, libglide3-cvg, libglide3-h3, libglide3-h5 -Replaces: libglide3, libglide3-sst1, libglide3-cvg, libglide3-h3, libglide3-h5 -Description: Glide 3 libraries for 3Dfx ${FLAVOUR} - Glide 3 runtime and static libraries for the 3Dfx ${FLAVOUR} family. -EOF - - sed -i "s/, ${PKG3}//" "${PKGDIR}/DEBIAN/control" - - dpkg-deb --build "${PKGDIR}" "${OUTDIR}/${PKG3}_${PKG_VERSION}_${ARCH}.deb" -} - -build_pkg_glide2 -build_pkg_glide3 - -REAL_SO2="$(find_unique_regular_file "${GLIDE2_SRC}" 'libglide.so.2.*')" -REAL_SO3="$(find_unique_regular_file "${GLIDE3_SRC}" 'libglide3.so.3.*')" -PKG_VERSION2="$(extract_glide2_pkg_version "${REAL_SO2}")" -PKG_VERSION3="$(extract_glide3_pkg_version "${REAL_SO3}")" - -echo "Packages created:" -echo " ${OUTDIR}/${PKG2}_${PKG_VERSION2}_${ARCH}.deb" -echo " ${OUTDIR}/${PKG3}_${PKG_VERSION3}_${ARCH}.deb" \ No newline at end of file diff --git a/config-kernel b/config-kernel deleted file mode 100644 index e4a4ebb..0000000 --- a/config-kernel +++ /dev/null @@ -1,1713 +0,0 @@ -# -# Automatically generated make config: don't edit -# Linux kernel version: 2.6.24 -# Fri Mar 20 00:02:25 2026 -# -# CONFIG_64BIT is not set -CONFIG_X86_32=y -# CONFIG_X86_64 is not set -CONFIG_X86=y -CONFIG_GENERIC_TIME=y -CONFIG_GENERIC_CMOS_UPDATE=y -CONFIG_CLOCKSOURCE_WATCHDOG=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_LOCKDEP_SUPPORT=y -CONFIG_STACKTRACE_SUPPORT=y -CONFIG_SEMAPHORE_SLEEPERS=y -CONFIG_MMU=y -CONFIG_ZONE_DMA=y -CONFIG_QUICKLIST=y -CONFIG_GENERIC_ISA_DMA=y -CONFIG_GENERIC_IOMAP=y -CONFIG_GENERIC_BUG=y -CONFIG_GENERIC_HWEIGHT=y -CONFIG_ARCH_MAY_HAVE_PC_FDC=y -CONFIG_DMI=y -# CONFIG_RWSEM_GENERIC_SPINLOCK is not set -CONFIG_RWSEM_XCHGADD_ALGORITHM=y -# CONFIG_ARCH_HAS_ILOG2_U32 is not set -# CONFIG_ARCH_HAS_ILOG2_U64 is not set -CONFIG_GENERIC_CALIBRATE_DELAY=y -# CONFIG_GENERIC_TIME_VSYSCALL is not set -CONFIG_ARCH_SUPPORTS_OPROFILE=y -# CONFIG_ZONE_DMA32 is not set -CONFIG_ARCH_POPULATES_NODE_MAP=y -# CONFIG_AUDIT_ARCH is not set -CONFIG_GENERIC_HARDIRQS=y -CONFIG_GENERIC_IRQ_PROBE=y -CONFIG_X86_BIOS_REBOOT=y -CONFIG_KTIME_SCALAR=y -CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" - -# -# General setup -# -CONFIG_EXPERIMENTAL=y -CONFIG_BROKEN_ON_SMP=y -CONFIG_LOCK_KERNEL=y -CONFIG_INIT_ENV_ARG_LIMIT=32 -CONFIG_LOCALVERSION="-retrodebian1" -# CONFIG_LOCALVERSION_AUTO is not set -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -CONFIG_SYSVIPC_SYSCTL=y -CONFIG_POSIX_MQUEUE=y -# CONFIG_BSD_PROCESS_ACCT is not set -# CONFIG_TASKSTATS is not set -# CONFIG_USER_NS is not set -# CONFIG_PID_NS is not set -# CONFIG_AUDIT is not set -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -CONFIG_LOG_BUF_SHIFT=18 -# CONFIG_CGROUPS is not set -CONFIG_FAIR_GROUP_SCHED=y -CONFIG_FAIR_USER_SCHED=y -# CONFIG_FAIR_CGROUP_SCHED is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_RELAY=y -CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_SYSCTL=y -# CONFIG_EMBEDDED is not set -CONFIG_UID16=y -CONFIG_SYSCTL_SYSCALL=y -CONFIG_KALLSYMS=y -CONFIG_KALLSYMS_ALL=y -# CONFIG_KALLSYMS_EXTRA_PASS is not set -CONFIG_HOTPLUG=y -CONFIG_PRINTK=y -CONFIG_BUG=y -CONFIG_ELF_CORE=y -CONFIG_BASE_FULL=y -CONFIG_FUTEX=y -CONFIG_ANON_INODES=y -CONFIG_EPOLL=y -CONFIG_SIGNALFD=y -CONFIG_EVENTFD=y -CONFIG_SHMEM=y -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLAB=y -# CONFIG_SLUB is not set -# CONFIG_SLOB is not set -CONFIG_SLABINFO=y -CONFIG_RT_MUTEXES=y -# CONFIG_TINY_SHMEM is not set -CONFIG_BASE_SMALL=0 -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -# CONFIG_MODVERSIONS is not set -# CONFIG_MODULE_SRCVERSION_ALL is not set -CONFIG_KMOD=y -CONFIG_BLOCK=y -# CONFIG_LBD is not set -# CONFIG_BLK_DEV_IO_TRACE is not set -# CONFIG_LSF is not set -# CONFIG_BLK_DEV_BSG is not set - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -# CONFIG_IOSCHED_AS is not set -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -# CONFIG_DEFAULT_AS is not set -# CONFIG_DEFAULT_DEADLINE is not set -CONFIG_DEFAULT_CFQ=y -# CONFIG_DEFAULT_NOOP is not set -CONFIG_DEFAULT_IOSCHED="cfq" - -# -# Processor type and features -# -# CONFIG_TICK_ONESHOT is not set -# CONFIG_NO_HZ is not set -# CONFIG_HIGH_RES_TIMERS is not set -CONFIG_GENERIC_CLOCKEVENTS_BUILD=y -# CONFIG_SMP is not set -CONFIG_X86_PC=y -# CONFIG_X86_ELAN is not set -# CONFIG_X86_VOYAGER is not set -# CONFIG_X86_NUMAQ is not set -# CONFIG_X86_SUMMIT is not set -# CONFIG_X86_BIGSMP is not set -# CONFIG_X86_VISWS is not set -# CONFIG_X86_GENERICARCH is not set -# CONFIG_X86_ES7000 is not set -# CONFIG_X86_VSMP is not set -CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y -# CONFIG_PARAVIRT_GUEST is not set -# CONFIG_M386 is not set -# CONFIG_M486 is not set -# CONFIG_M586 is not set -# CONFIG_M586TSC is not set -# CONFIG_M586MMX is not set -# CONFIG_M686 is not set -CONFIG_MPENTIUMII=y -# CONFIG_MPENTIUMIII is not set -# CONFIG_MPENTIUMM is not set -# CONFIG_MPENTIUM4 is not set -# CONFIG_MK6 is not set -# CONFIG_MK7 is not set -# CONFIG_MK8 is not set -# CONFIG_MCRUSOE is not set -# CONFIG_MEFFICEON is not set -# CONFIG_MWINCHIPC6 is not set -# CONFIG_MWINCHIP2 is not set -# CONFIG_MWINCHIP3D is not set -# CONFIG_MGEODEGX1 is not set -# CONFIG_MGEODE_LX is not set -# CONFIG_MCYRIXIII is not set -# CONFIG_MVIAC3_2 is not set -# CONFIG_MVIAC7 is not set -# CONFIG_MPSC is not set -# CONFIG_MCORE2 is not set -# CONFIG_GENERIC_CPU is not set -# CONFIG_X86_GENERIC is not set -CONFIG_X86_CMPXCHG=y -CONFIG_X86_L1_CACHE_SHIFT=5 -CONFIG_X86_XADD=y -CONFIG_X86_WP_WORKS_OK=y -CONFIG_X86_INVLPG=y -CONFIG_X86_BSWAP=y -CONFIG_X86_POPAD_OK=y -CONFIG_X86_GOOD_APIC=y -CONFIG_X86_INTEL_USERCOPY=y -CONFIG_X86_USE_PPRO_CHECKSUM=y -CONFIG_X86_TSC=y -CONFIG_X86_CMOV=y -CONFIG_X86_MINIMUM_CPU_FAMILY=4 -# CONFIG_HPET_TIMER is not set -# CONFIG_PREEMPT_NONE is not set -# CONFIG_PREEMPT_VOLUNTARY is not set -CONFIG_PREEMPT=y -CONFIG_PREEMPT_BKL=y -# CONFIG_X86_UP_APIC is not set -CONFIG_X86_MCE=y -# CONFIG_X86_MCE_NONFATAL is not set -CONFIG_VM86=y -# CONFIG_TOSHIBA is not set -# CONFIG_I8K is not set -# CONFIG_X86_REBOOTFIXUPS is not set -# CONFIG_MICROCODE is not set -CONFIG_X86_MSR=y -CONFIG_X86_CPUID=y -CONFIG_NOHIGHMEM=y -# CONFIG_HIGHMEM4G is not set -# CONFIG_HIGHMEM64G is not set -CONFIG_PAGE_OFFSET=0xC0000000 -# CONFIG_X86_PAE is not set -CONFIG_ARCH_FLATMEM_ENABLE=y -CONFIG_ARCH_SPARSEMEM_ENABLE=y -CONFIG_ARCH_SELECT_MEMORY_MODEL=y -CONFIG_SELECT_MEMORY_MODEL=y -CONFIG_FLATMEM_MANUAL=y -# CONFIG_DISCONTIGMEM_MANUAL is not set -# CONFIG_SPARSEMEM_MANUAL is not set -CONFIG_FLATMEM=y -CONFIG_FLAT_NODE_MEM_MAP=y -CONFIG_SPARSEMEM_STATIC=y -# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set -CONFIG_SPLIT_PTLOCK_CPUS=4 -CONFIG_RESOURCES_64BIT=y -CONFIG_ZONE_DMA_FLAG=1 -CONFIG_BOUNCE=y -CONFIG_NR_QUICK=1 -CONFIG_VIRT_TO_BUS=y -CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 -# CONFIG_MATH_EMULATION is not set -CONFIG_MTRR=y -# CONFIG_EFI is not set -CONFIG_SECCOMP=y -# CONFIG_HZ_100 is not set -# CONFIG_HZ_250 is not set -# CONFIG_HZ_300 is not set -CONFIG_HZ_1000=y -CONFIG_HZ=1000 -# CONFIG_KEXEC is not set -CONFIG_PHYSICAL_START=0x100000 -# CONFIG_RELOCATABLE is not set -CONFIG_PHYSICAL_ALIGN=0x200000 -CONFIG_COMPAT_VDSO=y - -# -# Power management options -# -CONFIG_PM=y -# CONFIG_PM_LEGACY is not set -# CONFIG_PM_DEBUG is not set -CONFIG_PM_SLEEP=y -CONFIG_SUSPEND_UP_POSSIBLE=y -CONFIG_SUSPEND=y -CONFIG_HIBERNATION_UP_POSSIBLE=y -CONFIG_HIBERNATION=y -CONFIG_PM_STD_PARTITION="" -CONFIG_ACPI=y -CONFIG_ACPI_SLEEP=y -CONFIG_ACPI_PROCFS=y -CONFIG_ACPI_PROCFS_POWER=y -CONFIG_ACPI_SYSFS_POWER=y -CONFIG_ACPI_PROC_EVENT=y -CONFIG_ACPI_AC=y -CONFIG_ACPI_BATTERY=y -CONFIG_ACPI_BUTTON=y -CONFIG_ACPI_FAN=y -# CONFIG_ACPI_DOCK is not set -CONFIG_ACPI_PROCESSOR=y -CONFIG_ACPI_THERMAL=y -# CONFIG_ACPI_ASUS is not set -# CONFIG_ACPI_TOSHIBA is not set -CONFIG_ACPI_BLACKLIST_YEAR=0 -# CONFIG_ACPI_DEBUG is not set -CONFIG_ACPI_EC=y -CONFIG_ACPI_POWER=y -CONFIG_ACPI_SYSTEM=y -CONFIG_X86_PM_TIMER=y -CONFIG_ACPI_CONTAINER=y -# CONFIG_ACPI_SBS is not set -# CONFIG_APM is not set - -# -# CPU Frequency scaling -# -CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_TABLE=y -CONFIG_CPU_FREQ_DEBUG=y -CONFIG_CPU_FREQ_STAT=y -# CONFIG_CPU_FREQ_STAT_DETAILS is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y -# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set -# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set -# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_CPU_FREQ_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y - -# -# CPUFreq processor drivers -# -CONFIG_X86_ACPI_CPUFREQ=y -# CONFIG_X86_POWERNOW_K6 is not set -# CONFIG_X86_POWERNOW_K7 is not set -CONFIG_X86_POWERNOW_K8=y -CONFIG_X86_POWERNOW_K8_ACPI=y -# CONFIG_X86_GX_SUSPMOD is not set -# CONFIG_X86_SPEEDSTEP_CENTRINO is not set -# CONFIG_X86_SPEEDSTEP_ICH is not set -# CONFIG_X86_SPEEDSTEP_SMI is not set -# CONFIG_X86_P4_CLOCKMOD is not set -# CONFIG_X86_CPUFREQ_NFORCE2 is not set -# CONFIG_X86_LONGRUN is not set -# CONFIG_X86_LONGHAUL is not set -# CONFIG_X86_E_POWERSAVER is not set - -# -# shared options -# -CONFIG_X86_ACPI_CPUFREQ_PROC_INTF=y -# CONFIG_X86_SPEEDSTEP_LIB is not set -# CONFIG_CPU_IDLE is not set - -# -# Bus options (PCI etc.) -# -CONFIG_PCI=y -# CONFIG_PCI_GOBIOS is not set -# CONFIG_PCI_GOMMCONFIG is not set -# CONFIG_PCI_GODIRECT is not set -CONFIG_PCI_GOANY=y -CONFIG_PCI_BIOS=y -CONFIG_PCI_DIRECT=y -CONFIG_PCI_MMCONFIG=y -CONFIG_PCI_DOMAINS=y -CONFIG_PCIEPORTBUS=y -CONFIG_PCIEAER=y -# CONFIG_ARCH_SUPPORTS_MSI is not set -CONFIG_PCI_LEGACY=y -# CONFIG_PCI_DEBUG is not set -CONFIG_ISA_DMA_API=y -CONFIG_ISA=y -# CONFIG_EISA is not set -# CONFIG_MCA is not set -# CONFIG_SCx200 is not set -CONFIG_K8_NB=y -# CONFIG_PCCARD is not set -# CONFIG_HOTPLUG_PCI is not set - -# -# Executable file formats / Emulations -# -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_AOUT is not set -# CONFIG_BINFMT_MISC is not set - -# -# Networking -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -CONFIG_UNIX=y -# CONFIG_NET_KEY is not set -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_FIB_HASH=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -# CONFIG_IP_PNP_BOOTP is not set -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_XFRM_TUNNEL is not set -# CONFIG_INET_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET_XFRM_MODE_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_BEET is not set -# CONFIG_INET_LRO is not set -CONFIG_INET_DIAG=y -CONFIG_INET_TCP_DIAG=y -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_CUBIC=y -CONFIG_DEFAULT_TCP_CONG="cubic" -# CONFIG_TCP_MD5SIG is not set -# CONFIG_IPV6 is not set -# CONFIG_INET6_XFRM_TUNNEL is not set -# CONFIG_INET6_TUNNEL is not set -# CONFIG_NETWORK_SECMARK is not set -# CONFIG_NETFILTER is not set -# CONFIG_IP_DCCP is not set -# CONFIG_IP_SCTP is not set -# CONFIG_TIPC is not set -# CONFIG_ATM is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -# CONFIG_NET_TCPPROBE is not set -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set -# CONFIG_AF_RXRPC is not set - -# -# Wireless -# -# CONFIG_CFG80211 is not set -# CONFIG_WIRELESS_EXT is not set -# CONFIG_MAC80211 is not set -# CONFIG_IEEE80211 is not set -# CONFIG_RFKILL is not set -# CONFIG_NET_9P is not set - -# -# Device Drivers -# - -# -# Generic Driver Options -# -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=y -# CONFIG_DEBUG_DRIVER is not set -# CONFIG_DEBUG_DEVRES is not set -# CONFIG_SYS_HYPERVISOR is not set -# CONFIG_CONNECTOR is not set -# CONFIG_MTD is not set -# CONFIG_PARPORT is not set -CONFIG_PNP=y -# CONFIG_PNP_DEBUG is not set - -# -# Protocols -# -CONFIG_ISAPNP=y -# CONFIG_PNPBIOS is not set -CONFIG_PNPACPI=y -CONFIG_BLK_DEV=y -CONFIG_BLK_DEV_FD=y -# CONFIG_BLK_DEV_XD is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -# CONFIG_BLK_DEV_COW_COMMON is not set -CONFIG_BLK_DEV_LOOP=y -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_SX8 is not set -# CONFIG_BLK_DEV_UB is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 -# CONFIG_CDROM_PKTCDVD is not set -# CONFIG_ATA_OVER_ETH is not set -CONFIG_MISC_DEVICES=y -# CONFIG_IBM_ASM is not set -# CONFIG_PHANTOM is not set -# CONFIG_EEPROM_93CX6 is not set -# CONFIG_SGI_IOC4 is not set -# CONFIG_TIFM_CORE is not set -# CONFIG_SONY_LAPTOP is not set -# CONFIG_THINKPAD_ACPI is not set -CONFIG_IDE=y -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_IDE_SATA is not set -# CONFIG_BLK_DEV_HD_IDE is not set -CONFIG_BLK_DEV_IDEDISK=y -CONFIG_IDEDISK_MULTI_MODE=y -CONFIG_BLK_DEV_IDECD=y -# CONFIG_BLK_DEV_IDETAPE is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set -# CONFIG_BLK_DEV_IDESCSI is not set -CONFIG_BLK_DEV_IDEACPI=y -# CONFIG_IDE_TASK_IOCTL is not set -CONFIG_IDE_PROC_FS=y - -# -# IDE chipset support/bugfixes -# -CONFIG_IDE_GENERIC=y -# CONFIG_BLK_DEV_PLATFORM is not set -# CONFIG_BLK_DEV_CMD640 is not set -# CONFIG_BLK_DEV_IDEPNP is not set - -# -# PCI IDE chipsets support -# -CONFIG_BLK_DEV_IDEPCI=y -# CONFIG_IDEPCI_SHARE_IRQ is not set -CONFIG_IDEPCI_PCIBUS_ORDER=y -# CONFIG_BLK_DEV_OFFBOARD is not set -# CONFIG_BLK_DEV_GENERIC is not set -# CONFIG_BLK_DEV_OPTI621 is not set -# CONFIG_BLK_DEV_RZ1000 is not set -CONFIG_BLK_DEV_IDEDMA_PCI=y -# CONFIG_BLK_DEV_AEC62XX is not set -# CONFIG_BLK_DEV_ALI15X3 is not set -CONFIG_BLK_DEV_AMD74XX=y -CONFIG_BLK_DEV_ATIIXP=y -# CONFIG_BLK_DEV_CMD64X is not set -# CONFIG_BLK_DEV_TRIFLEX is not set -# CONFIG_BLK_DEV_CY82C693 is not set -# CONFIG_BLK_DEV_CS5520 is not set -# CONFIG_BLK_DEV_CS5530 is not set -# CONFIG_BLK_DEV_CS5535 is not set -# CONFIG_BLK_DEV_HPT34X is not set -# CONFIG_BLK_DEV_HPT366 is not set -# CONFIG_BLK_DEV_JMICRON is not set -# CONFIG_BLK_DEV_SC1200 is not set -CONFIG_BLK_DEV_PIIX=y -# CONFIG_BLK_DEV_IT8213 is not set -# CONFIG_BLK_DEV_IT821X is not set -# CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_PDC202XX_OLD is not set -CONFIG_BLK_DEV_PDC202XX_NEW=y -# CONFIG_BLK_DEV_SVWKS is not set -# CONFIG_BLK_DEV_SIIMAGE is not set -# CONFIG_BLK_DEV_SIS5513 is not set -# CONFIG_BLK_DEV_SLC90E66 is not set -# CONFIG_BLK_DEV_TRM290 is not set -# CONFIG_BLK_DEV_VIA82CXXX is not set -# CONFIG_BLK_DEV_TC86C001 is not set -# CONFIG_IDE_ARM is not set - -# -# Other IDE chipsets support -# - -# -# Note: most of these also require special kernel boot parameters -# -# CONFIG_BLK_DEV_4DRIVES is not set -# CONFIG_BLK_DEV_ALI14XX is not set -# CONFIG_BLK_DEV_DTC2278 is not set -# CONFIG_BLK_DEV_HT6560B is not set -# CONFIG_BLK_DEV_QD65XX is not set -# CONFIG_BLK_DEV_UMC8672 is not set -CONFIG_BLK_DEV_IDEDMA=y -CONFIG_IDE_ARCH_OBSOLETE_INIT=y -# CONFIG_BLK_DEV_HD is not set - -# -# SCSI device support -# -# CONFIG_RAID_ATTRS is not set -CONFIG_SCSI=y -CONFIG_SCSI_DMA=y -# CONFIG_SCSI_TGT is not set -CONFIG_SCSI_NETLINK=y -# CONFIG_SCSI_PROC_FS is not set - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=y -# CONFIG_CHR_DEV_ST is not set -# CONFIG_CHR_DEV_OSST is not set -CONFIG_BLK_DEV_SR=y -# CONFIG_BLK_DEV_SR_VENDOR is not set -CONFIG_CHR_DEV_SG=y -# CONFIG_CHR_DEV_SCH is not set - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -# CONFIG_SCSI_MULTI_LUN is not set -CONFIG_SCSI_CONSTANTS=y -# CONFIG_SCSI_LOGGING is not set -# CONFIG_SCSI_SCAN_ASYNC is not set -CONFIG_SCSI_WAIT_SCAN=m - -# -# SCSI Transports -# -CONFIG_SCSI_SPI_ATTRS=y -CONFIG_SCSI_FC_ATTRS=y -# CONFIG_SCSI_ISCSI_ATTRS is not set -# CONFIG_SCSI_SAS_LIBSAS is not set -# CONFIG_SCSI_SRP_ATTRS is not set -CONFIG_SCSI_LOWLEVEL=y -# CONFIG_ISCSI_TCP is not set -# CONFIG_BLK_DEV_3W_XXXX_RAID is not set -# CONFIG_SCSI_3W_9XXX is not set -# CONFIG_SCSI_7000FASST is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AHA152X is not set -# CONFIG_SCSI_AHA1542 is not set -# CONFIG_SCSI_AACRAID is not set -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set -CONFIG_SCSI_AIC79XX=y -CONFIG_AIC79XX_CMDS_PER_DEVICE=32 -CONFIG_AIC79XX_RESET_DELAY_MS=4000 -# CONFIG_AIC79XX_DEBUG_ENABLE is not set -CONFIG_AIC79XX_DEBUG_MASK=0 -# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set -# CONFIG_SCSI_AIC94XX is not set -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_ARCMSR is not set -# CONFIG_MEGARAID_NEWGEN is not set -# CONFIG_MEGARAID_LEGACY is not set -# CONFIG_MEGARAID_SAS is not set -# CONFIG_SCSI_HPTIOP is not set -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DTC3280 is not set -# CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -# CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_GENERIC_NCR5380 is not set -# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set -# CONFIG_SCSI_IPS is not set -# CONFIG_SCSI_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_STEX is not set -# CONFIG_SCSI_SYM53C8XX_2 is not set -# CONFIG_SCSI_IPR is not set -# CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_PSI240I is not set -# CONFIG_SCSI_QLOGIC_FAS is not set -# CONFIG_SCSI_QLOGIC_1280 is not set -# CONFIG_SCSI_QLA_FC is not set -# CONFIG_SCSI_QLA_ISCSI is not set -# CONFIG_SCSI_LPFC is not set -# CONFIG_SCSI_SEAGATE is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_DC395x is not set -# CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_ULTRASTOR is not set -# CONFIG_SCSI_NSP32 is not set -# CONFIG_SCSI_DEBUG is not set -# CONFIG_SCSI_SRP is not set -CONFIG_ATA=y -# CONFIG_ATA_NONSTANDARD is not set -CONFIG_ATA_ACPI=y -CONFIG_SATA_AHCI=y -CONFIG_SATA_SVW=y -CONFIG_ATA_PIIX=y -# CONFIG_SATA_MV is not set -CONFIG_SATA_NV=y -# CONFIG_PDC_ADMA is not set -# CONFIG_SATA_QSTOR is not set -# CONFIG_SATA_PROMISE is not set -# CONFIG_SATA_SX4 is not set -CONFIG_SATA_SIL=y -# CONFIG_SATA_SIL24 is not set -# CONFIG_SATA_SIS is not set -# CONFIG_SATA_ULI is not set -CONFIG_SATA_VIA=y -# CONFIG_SATA_VITESSE is not set -# CONFIG_SATA_INIC162X is not set -# CONFIG_PATA_ACPI is not set -# CONFIG_PATA_ALI is not set -# CONFIG_PATA_AMD is not set -# CONFIG_PATA_ARTOP is not set -# CONFIG_PATA_ATIIXP is not set -# CONFIG_PATA_CMD640_PCI is not set -# CONFIG_PATA_CMD64X is not set -# CONFIG_PATA_CS5520 is not set -# CONFIG_PATA_CS5530 is not set -# CONFIG_PATA_CS5535 is not set -# CONFIG_PATA_CS5536 is not set -# CONFIG_PATA_CYPRESS is not set -# CONFIG_PATA_EFAR is not set -# CONFIG_ATA_GENERIC is not set -# CONFIG_PATA_HPT366 is not set -# CONFIG_PATA_HPT37X is not set -# CONFIG_PATA_HPT3X2N is not set -# CONFIG_PATA_HPT3X3 is not set -# CONFIG_PATA_ISAPNP is not set -# CONFIG_PATA_IT821X is not set -# CONFIG_PATA_IT8213 is not set -# CONFIG_PATA_JMICRON is not set -# CONFIG_PATA_LEGACY is not set -# CONFIG_PATA_TRIFLEX is not set -# CONFIG_PATA_MARVELL is not set -# CONFIG_PATA_MPIIX is not set -# CONFIG_PATA_OLDPIIX is not set -# CONFIG_PATA_NETCELL is not set -# CONFIG_PATA_NS87410 is not set -# CONFIG_PATA_NS87415 is not set -# CONFIG_PATA_OPTI is not set -# CONFIG_PATA_OPTIDMA is not set -# CONFIG_PATA_PDC_OLD is not set -# CONFIG_PATA_QDI is not set -# CONFIG_PATA_RADISYS is not set -# CONFIG_PATA_RZ1000 is not set -# CONFIG_PATA_SC1200 is not set -# CONFIG_PATA_SERVERWORKS is not set -# CONFIG_PATA_PDC2027X is not set -# CONFIG_PATA_SIL680 is not set -# CONFIG_PATA_SIS is not set -# CONFIG_PATA_VIA is not set -# CONFIG_PATA_WINBOND is not set -# CONFIG_PATA_WINBOND_VLB is not set -CONFIG_MD=y -# CONFIG_BLK_DEV_MD is not set -CONFIG_BLK_DEV_DM=y -# CONFIG_DM_DEBUG is not set -# CONFIG_DM_CRYPT is not set -# CONFIG_DM_SNAPSHOT is not set -# CONFIG_DM_MIRROR is not set -# CONFIG_DM_ZERO is not set -# CONFIG_DM_MULTIPATH is not set -# CONFIG_DM_DELAY is not set -# CONFIG_DM_UEVENT is not set -CONFIG_FUSION=y -CONFIG_FUSION_SPI=y -# CONFIG_FUSION_FC is not set -# CONFIG_FUSION_SAS is not set -CONFIG_FUSION_MAX_SGE=128 -# CONFIG_FUSION_CTL is not set -# CONFIG_FUSION_LOGGING is not set - -# -# IEEE 1394 (FireWire) support -# -# CONFIG_FIREWIRE is not set -CONFIG_IEEE1394=y - -# -# Subsystem Options -# -# CONFIG_IEEE1394_VERBOSEDEBUG is not set - -# -# Controllers -# - -# -# Texas Instruments PCILynx requires I2C -# -CONFIG_IEEE1394_OHCI1394=y - -# -# Protocols -# -# CONFIG_IEEE1394_VIDEO1394 is not set -# CONFIG_IEEE1394_SBP2 is not set -# CONFIG_IEEE1394_ETH1394_ROM_ENTRY is not set -# CONFIG_IEEE1394_ETH1394 is not set -# CONFIG_IEEE1394_DV1394 is not set -CONFIG_IEEE1394_RAWIO=y -# CONFIG_I2O is not set -# CONFIG_MACINTOSH_DRIVERS is not set -CONFIG_NETDEVICES=y -CONFIG_NETDEVICES_MULTIQUEUE=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_MACVLAN is not set -# CONFIG_EQUALIZER is not set -CONFIG_TUN=y -# CONFIG_VETH is not set -# CONFIG_NET_SB1000 is not set -# CONFIG_ARCNET is not set -# CONFIG_PHYLIB is not set -CONFIG_NET_ETHERNET=y -CONFIG_MII=y -# CONFIG_HAPPYMEAL is not set -# CONFIG_SUNGEM is not set -# CONFIG_CASSINI is not set -CONFIG_NET_VENDOR_3COM=y -# CONFIG_EL1 is not set -# CONFIG_EL2 is not set -# CONFIG_ELPLUS is not set -# CONFIG_EL16 is not set -# CONFIG_EL3 is not set -# CONFIG_3C515 is not set -CONFIG_VORTEX=y -# CONFIG_TYPHOON is not set -# CONFIG_LANCE is not set -# CONFIG_NET_VENDOR_SMC is not set -# CONFIG_NET_VENDOR_RACAL is not set -CONFIG_NET_TULIP=y -# CONFIG_DE2104X is not set -CONFIG_TULIP=y -# CONFIG_TULIP_MWI is not set -# CONFIG_TULIP_MMIO is not set -# CONFIG_TULIP_NAPI is not set -# CONFIG_DE4X5 is not set -# CONFIG_WINBOND_840 is not set -# CONFIG_DM9102 is not set -# CONFIG_ULI526X is not set -# CONFIG_AT1700 is not set -# CONFIG_DEPCA is not set -# CONFIG_HP100 is not set -# CONFIG_NET_ISA is not set -# CONFIG_IBM_NEW_EMAC_ZMII is not set -# CONFIG_IBM_NEW_EMAC_RGMII is not set -# CONFIG_IBM_NEW_EMAC_TAH is not set -# CONFIG_IBM_NEW_EMAC_EMAC4 is not set -CONFIG_NET_PCI=y -# CONFIG_PCNET32 is not set -CONFIG_AMD8111_ETH=y -# CONFIG_AMD8111E_NAPI is not set -# CONFIG_ADAPTEC_STARFIRE is not set -# CONFIG_AC3200 is not set -# CONFIG_APRICOT is not set -CONFIG_B44=y -CONFIG_B44_PCI_AUTOSELECT=y -CONFIG_B44_PCICORE_AUTOSELECT=y -CONFIG_B44_PCI=y -CONFIG_FORCEDETH=y -# CONFIG_FORCEDETH_NAPI is not set -# CONFIG_CS89x0 is not set -# CONFIG_EEPRO100 is not set -CONFIG_E100=y -# CONFIG_FEALNX is not set -# CONFIG_NATSEMI is not set -# CONFIG_NE2K_PCI is not set -CONFIG_8139CP=y -CONFIG_8139TOO=y -# CONFIG_8139TOO_PIO is not set -# CONFIG_8139TOO_TUNE_TWISTER is not set -# CONFIG_8139TOO_8129 is not set -# CONFIG_8139_OLD_RX_RESET is not set -# CONFIG_SIS900 is not set -# CONFIG_EPIC100 is not set -# CONFIG_SUNDANCE is not set -# CONFIG_TLAN is not set -# CONFIG_VIA_RHINE is not set -# CONFIG_SC92031 is not set -CONFIG_NETDEV_1000=y -# CONFIG_DL2K is not set -CONFIG_E1000=y -# CONFIG_E1000_NAPI is not set -# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set -# CONFIG_E1000E is not set -# CONFIG_IP1000 is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_R8169 is not set -# CONFIG_SIS190 is not set -# CONFIG_SKGE is not set -# CONFIG_SKY2 is not set -# CONFIG_SK98LIN is not set -# CONFIG_VIA_VELOCITY is not set -CONFIG_TIGON3=y -CONFIG_BNX2=y -# CONFIG_QLA3XXX is not set -# CONFIG_ATL1 is not set -# CONFIG_NETDEV_10000 is not set -# CONFIG_TR is not set - -# -# Wireless LAN -# -# CONFIG_WLAN_PRE80211 is not set -# CONFIG_WLAN_80211 is not set - -# -# USB Network Adapters -# -# CONFIG_USB_CATC is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_RTL8150 is not set -# CONFIG_USB_USBNET is not set -# CONFIG_WAN is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set -# CONFIG_NET_FC is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_ISDN is not set -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y -CONFIG_INPUT_FF_MEMLESS=y -# CONFIG_INPUT_POLLDEV is not set - -# -# Userland interfaces -# -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSEDEV_PSAUX=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_JOYDEV=m -CONFIG_INPUT_EVDEV=y -# CONFIG_INPUT_EVBUG is not set - -# -# Input Device Drivers -# -CONFIG_INPUT_KEYBOARD=y -CONFIG_KEYBOARD_ATKBD=y -# CONFIG_KEYBOARD_SUNKBD is not set -# CONFIG_KEYBOARD_LKKBD is not set -# CONFIG_KEYBOARD_XTKBD is not set -# CONFIG_KEYBOARD_NEWTON is not set -# CONFIG_KEYBOARD_STOWAWAY is not set -CONFIG_INPUT_MOUSE=y -CONFIG_MOUSE_PS2=y -CONFIG_MOUSE_PS2_ALPS=y -CONFIG_MOUSE_PS2_LOGIPS2PP=y -CONFIG_MOUSE_PS2_SYNAPTICS=y -CONFIG_MOUSE_PS2_LIFEBOOK=y -CONFIG_MOUSE_PS2_TRACKPOINT=y -# CONFIG_MOUSE_PS2_TOUCHKIT is not set -# CONFIG_MOUSE_SERIAL is not set -# CONFIG_MOUSE_APPLETOUCH is not set -# CONFIG_MOUSE_INPORT is not set -# CONFIG_MOUSE_LOGIBM is not set -# CONFIG_MOUSE_PC110PAD is not set -# CONFIG_MOUSE_VSXXXAA is not set -CONFIG_INPUT_JOYSTICK=y -CONFIG_JOYSTICK_ANALOG=m -CONFIG_JOYSTICK_A3D=m -CONFIG_JOYSTICK_ADI=m -CONFIG_JOYSTICK_COBRA=m -CONFIG_JOYSTICK_GF2K=m -CONFIG_JOYSTICK_GRIP=m -CONFIG_JOYSTICK_GRIP_MP=m -CONFIG_JOYSTICK_GUILLEMOT=m -CONFIG_JOYSTICK_INTERACT=m -CONFIG_JOYSTICK_SIDEWINDER=m -CONFIG_JOYSTICK_TMDC=m -CONFIG_JOYSTICK_IFORCE=m -CONFIG_JOYSTICK_IFORCE_USB=y -CONFIG_JOYSTICK_IFORCE_232=y -CONFIG_JOYSTICK_WARRIOR=m -CONFIG_JOYSTICK_MAGELLAN=m -CONFIG_JOYSTICK_SPACEORB=m -CONFIG_JOYSTICK_SPACEBALL=m -CONFIG_JOYSTICK_STINGER=m -CONFIG_JOYSTICK_TWIDJOY=m -CONFIG_JOYSTICK_JOYDUMP=m -CONFIG_JOYSTICK_XPAD=m -CONFIG_JOYSTICK_XPAD_FF=y -CONFIG_INPUT_TABLET=y -# CONFIG_TABLET_USB_ACECAD is not set -# CONFIG_TABLET_USB_AIPTEK is not set -# CONFIG_TABLET_USB_GTCO is not set -# CONFIG_TABLET_USB_KBTAB is not set -CONFIG_TABLET_USB_WACOM=y -# CONFIG_INPUT_TOUCHSCREEN is not set -CONFIG_INPUT_MISC=y -CONFIG_INPUT_PCSPKR=y -# CONFIG_INPUT_WISTRON_BTNS is not set -# CONFIG_INPUT_ATLAS_BTNS is not set -# CONFIG_INPUT_ATI_REMOTE is not set -# CONFIG_INPUT_ATI_REMOTE2 is not set -# CONFIG_INPUT_KEYSPAN_REMOTE is not set -# CONFIG_INPUT_POWERMATE is not set -# CONFIG_INPUT_YEALINK is not set -# CONFIG_INPUT_UINPUT is not set - -# -# Hardware I/O ports -# -CONFIG_SERIO=y -CONFIG_SERIO_I8042=y -# CONFIG_SERIO_SERPORT is not set -# CONFIG_SERIO_CT82C710 is not set -# CONFIG_SERIO_PCIPS2 is not set -CONFIG_SERIO_LIBPS2=y -# CONFIG_SERIO_RAW is not set -CONFIG_GAMEPORT=m -CONFIG_GAMEPORT_NS558=m -# CONFIG_GAMEPORT_L4 is not set -CONFIG_GAMEPORT_EMU10K1=m -# CONFIG_GAMEPORT_FM801 is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -# CONFIG_VT_HW_CONSOLE_BINDING is not set -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_FIX_EARLYCON_MEM=y -CONFIG_SERIAL_8250_PCI=y -CONFIG_SERIAL_8250_PNP=y -CONFIG_SERIAL_8250_NR_UARTS=4 -CONFIG_SERIAL_8250_RUNTIME_UARTS=4 -# CONFIG_SERIAL_8250_EXTENDED is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -# CONFIG_SERIAL_JSM is not set -CONFIG_UNIX98_PTYS=y -CONFIG_LEGACY_PTYS=y -CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_IPMI_HANDLER is not set -CONFIG_HW_RANDOM=y -CONFIG_HW_RANDOM_INTEL=y -CONFIG_HW_RANDOM_AMD=y -CONFIG_HW_RANDOM_GEODE=y -CONFIG_HW_RANDOM_VIA=y -# CONFIG_NVRAM is not set -CONFIG_RTC=y -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set -# CONFIG_SONYPI is not set -# CONFIG_MWAVE is not set -# CONFIG_PC8736x_GPIO is not set -# CONFIG_NSC_GPIO is not set -# CONFIG_CS5535_GPIO is not set -CONFIG_RAW_DRIVER=y -CONFIG_MAX_RAW_DEVS=256 -# CONFIG_HPET is not set -# CONFIG_HANGCHECK_TIMER is not set -# CONFIG_TCG_TPM is not set -# CONFIG_TELCLOCK is not set -CONFIG_DEVPORT=y -# CONFIG_I2C is not set - -# -# SPI support -# -# CONFIG_SPI is not set -# CONFIG_SPI_MASTER is not set -# CONFIG_W1 is not set -CONFIG_POWER_SUPPLY=y -# CONFIG_POWER_SUPPLY_DEBUG is not set -# CONFIG_PDA_POWER is not set -# CONFIG_BATTERY_DS2760 is not set -# CONFIG_HWMON is not set -# CONFIG_WATCHDOG is not set - -# -# Sonics Silicon Backplane -# -CONFIG_SSB_POSSIBLE=y -CONFIG_SSB=y -CONFIG_SSB_PCIHOST_POSSIBLE=y -CONFIG_SSB_PCIHOST=y -# CONFIG_SSB_DEBUG is not set -CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y -CONFIG_SSB_DRIVER_PCICORE=y - -# -# Multifunction device drivers -# -# CONFIG_MFD_SM501 is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set -# CONFIG_DVB_CORE is not set -# CONFIG_DAB is not set - -# -# Graphics support -# -CONFIG_AGP=y -CONFIG_AGP_ALI=m -CONFIG_AGP_ATI=m -CONFIG_AGP_AMD=m -# CONFIG_AGP_AMD64 is not set -CONFIG_AGP_INTEL=m -CONFIG_AGP_NVIDIA=m -CONFIG_AGP_SIS=m -# CONFIG_AGP_SWORKS is not set -CONFIG_AGP_VIA=m -# CONFIG_AGP_EFFICEON is not set -CONFIG_DRM=m -# CONFIG_VGASTATE is not set -CONFIG_VIDEO_OUTPUT_CONTROL=y -CONFIG_FB=y -CONFIG_FB_VESA=y -CONFIG_FRAMEBUFFER_CONSOLE=y -CONFIG_LOGO=y -CONFIG_BACKLIGHT_LCD_SUPPORT=y - -# -# Display device support -# -CONFIG_DISPLAY_SUPPORT=y - -# -# Console display driver support -# -CONFIG_VGA_CONSOLE=y -CONFIG_VGACON_SOFT_SCROLLBACK=y -CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=256 -CONFIG_VIDEO_SELECT=y -# CONFIG_MDA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y - -# -# Sound -# -CONFIG_SOUND=y - -# -# Advanced Linux Sound Architecture -# -CONFIG_SND=y -CONFIG_SND_TIMER=m -CONFIG_SND_PCM=m -CONFIG_SND_HWDEP=m -CONFIG_SND_RAWMIDI=m -# CONFIG_SND_SEQUENCER is not set -CONFIG_SND_OSSEMUL=y -CONFIG_SND_MIXER_OSS=y -CONFIG_SND_PCM_OSS=y -# CONFIG_SND_RTCTIMER is not set -# CONFIG_SND_DYNAMIC_MINORS is not set -CONFIG_SND_SUPPORT_OLD_API=y -CONFIG_SND_VERBOSE_PROCFS=y -# CONFIG_SND_VERBOSE_PRINTK is not set -# CONFIG_SND_DEBUG is not set - -# -# Generic devices -# -CONFIG_SND_MPU401_UART=m -CONFIG_SND_OPL3_LIB=m -CONFIG_SND_OPL4_LIB=m -CONFIG_SND_VX_LIB=m -CONFIG_SND_AC97_CODEC=m -# CONFIG_SND_DUMMY is not set -# CONFIG_SND_MTPAV is not set -# CONFIG_SND_SERIAL_U16550 is not set -# CONFIG_SND_MPU401 is not set -CONFIG_SND_AD1848_LIB=m -CONFIG_SND_CS4231_LIB=m -CONFIG_SND_SB_COMMON=m -CONFIG_SND_SB8_DSP=m -CONFIG_SND_SB16_DSP=m - -# -# ISA devices -# -CONFIG_SND_ADLIB=m -CONFIG_SND_AD1816A=m -CONFIG_SND_AD1848=m -CONFIG_SND_ALS100=m -CONFIG_SND_AZT2320=m -CONFIG_SND_CMI8330=m -CONFIG_SND_CS4231=m -CONFIG_SND_CS4232=m -CONFIG_SND_CS4236=m -CONFIG_SND_DT019X=m -CONFIG_SND_ES968=m -CONFIG_SND_ES1688=m -CONFIG_SND_ES18XX=m -CONFIG_SND_SC6000=m -CONFIG_SND_GUS_SYNTH=m -CONFIG_SND_GUSCLASSIC=m -CONFIG_SND_GUSEXTREME=m -CONFIG_SND_GUSMAX=m -CONFIG_SND_INTERWAVE=m -CONFIG_SND_INTERWAVE_STB=m -CONFIG_SND_OPL3SA2=m -CONFIG_SND_OPTI92X_AD1848=m -CONFIG_SND_OPTI92X_CS4231=m -CONFIG_SND_OPTI93X=m -CONFIG_SND_MIRO=m -CONFIG_SND_SB8=m -CONFIG_SND_SB16=m -CONFIG_SND_SBAWE=m -CONFIG_SND_SB16_CSP=y -CONFIG_SND_SB16_CSP_FIRMWARE_IN_KERNEL=y -CONFIG_SND_SGALAXY=m -CONFIG_SND_SSCAPE=m -CONFIG_SND_WAVEFRONT=m -CONFIG_SND_WAVEFRONT_FIRMWARE_IN_KERNEL=y - -# -# PCI devices -# -CONFIG_SND_AD1889=m -CONFIG_SND_ALS300=m -CONFIG_SND_ALS4000=m -CONFIG_SND_ALI5451=m -CONFIG_SND_ATIIXP=m -CONFIG_SND_ATIIXP_MODEM=m -CONFIG_SND_AU8810=m -CONFIG_SND_AU8820=m -CONFIG_SND_AU8830=m -# CONFIG_SND_AZT3328 is not set -CONFIG_SND_BT87X=m -# CONFIG_SND_BT87X_OVERCLOCK is not set -CONFIG_SND_CA0106=m -CONFIG_SND_CMIPCI=m -CONFIG_SND_CS4281=m -CONFIG_SND_CS5530=m -CONFIG_SND_CS5535AUDIO=m -CONFIG_SND_DARLA20=m -CONFIG_SND_GINA20=m -CONFIG_SND_LAYLA20=m -CONFIG_SND_DARLA24=m -CONFIG_SND_GINA24=m -CONFIG_SND_LAYLA24=m -CONFIG_SND_MONA=m -CONFIG_SND_MIA=m -CONFIG_SND_ECHO3G=m -CONFIG_SND_INDIGO=m -CONFIG_SND_INDIGOIO=m -CONFIG_SND_INDIGODJ=m -CONFIG_SND_EMU10K1=m -CONFIG_SND_EMU10K1X=m -CONFIG_SND_ENS1370=m -CONFIG_SND_ENS1371=m -CONFIG_SND_ES1938=m -CONFIG_SND_ES1968=m -CONFIG_SND_FM801=m -# CONFIG_SND_FM801_TEA575X_BOOL is not set -CONFIG_SND_HDA_INTEL=m -CONFIG_SND_HDA_HWDEP=y -CONFIG_SND_HDA_CODEC_REALTEK=y -CONFIG_SND_HDA_CODEC_ANALOG=y -CONFIG_SND_HDA_CODEC_SIGMATEL=y -CONFIG_SND_HDA_CODEC_VIA=y -CONFIG_SND_HDA_CODEC_ATIHDMI=y -CONFIG_SND_HDA_CODEC_CONEXANT=y -CONFIG_SND_HDA_CODEC_CMEDIA=y -CONFIG_SND_HDA_CODEC_SI3054=y -CONFIG_SND_HDA_GENERIC=y -# CONFIG_SND_HDA_POWER_SAVE is not set -CONFIG_SND_HDSP=m -CONFIG_SND_HDSPM=m -CONFIG_SND_ICE1712=m -CONFIG_SND_ICE1724=m -CONFIG_SND_INTEL8X0=m -CONFIG_SND_INTEL8X0M=m -CONFIG_SND_KORG1212=m -CONFIG_SND_MAESTRO3=m -CONFIG_SND_MIXART=m -CONFIG_SND_NM256=m -CONFIG_SND_PCXHR=m -CONFIG_SND_RIPTIDE=m -CONFIG_SND_RME32=m -CONFIG_SND_RME96=m -CONFIG_SND_RME9652=m -CONFIG_SND_SONICVIBES=m -CONFIG_SND_TRIDENT=m -CONFIG_SND_VIA82XX=m -CONFIG_SND_VIA82XX_MODEM=m -CONFIG_SND_VX222=m -CONFIG_SND_YMFPCI=m -# CONFIG_SND_AC97_POWER_SAVE is not set - -# -# USB devices -# -CONFIG_SND_USB_AUDIO=m -CONFIG_SND_USB_USX2Y=m -CONFIG_SND_USB_CAIAQ=m -# CONFIG_SND_USB_CAIAQ_INPUT is not set - -# -# System on Chip audio support -# -# CONFIG_SND_SOC is not set - -# -# SoC Audio support for SuperH -# - -# -# Open Sound System -# -# CONFIG_SOUND_PRIME is not set -CONFIG_AC97_BUS=m -CONFIG_HID_SUPPORT=y -CONFIG_HID=y -# CONFIG_HID_DEBUG is not set -# CONFIG_HIDRAW is not set - -# -# USB Input Devices -# -CONFIG_USB_HID=y -# CONFIG_USB_HIDINPUT_POWERBOOK is not set -CONFIG_HID_FF=y -CONFIG_HID_PID=y -CONFIG_LOGITECH_FF=y -CONFIG_PANTHERLORD_FF=y -CONFIG_THRUSTMASTER_FF=y -CONFIG_ZEROPLUS_FF=y -# CONFIG_USB_HIDDEV is not set -CONFIG_USB_SUPPORT=y -CONFIG_USB_ARCH_HAS_HCD=y -CONFIG_USB_ARCH_HAS_OHCI=y -CONFIG_USB_ARCH_HAS_EHCI=y -CONFIG_USB=y -# CONFIG_USB_DEBUG is not set - -# -# Miscellaneous USB options -# -CONFIG_USB_DEVICEFS=y -# CONFIG_USB_DEVICE_CLASS is not set -# CONFIG_USB_DYNAMIC_MINORS is not set -# CONFIG_USB_SUSPEND is not set -# CONFIG_USB_PERSIST is not set -# CONFIG_USB_OTG is not set - -# -# USB Host Controller Drivers -# -CONFIG_USB_EHCI_HCD=y -# CONFIG_USB_EHCI_SPLIT_ISO is not set -# CONFIG_USB_EHCI_ROOT_HUB_TT is not set -# CONFIG_USB_EHCI_TT_NEWSCHED is not set -# CONFIG_USB_ISP116X_HCD is not set -CONFIG_USB_OHCI_HCD=y -# CONFIG_USB_OHCI_HCD_SSB is not set -# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set -# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set -CONFIG_USB_OHCI_LITTLE_ENDIAN=y -CONFIG_USB_UHCI_HCD=y -# CONFIG_USB_SL811_HCD is not set -# CONFIG_USB_R8A66597_HCD is not set - -# -# USB Device Class drivers -# -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set - -# -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' -# - -# -# may also be needed; see USB_STORAGE Help for more information -# -CONFIG_USB_STORAGE=y -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_ISD200 is not set -# CONFIG_USB_STORAGE_DPCM is not set -# CONFIG_USB_STORAGE_USBAT is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_STORAGE_SDDR55 is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set -# CONFIG_USB_STORAGE_ALAUDA is not set -# CONFIG_USB_STORAGE_KARMA is not set -# CONFIG_USB_LIBUSUAL is not set - -# -# USB Imaging devices -# -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_MICROTEK is not set -CONFIG_USB_MON=y - -# -# USB port drivers -# - -# -# USB Serial Converter support -# -# CONFIG_USB_SERIAL is not set - -# -# USB Miscellaneous drivers -# -# CONFIG_USB_ADUTUX is not set -# CONFIG_USB_AUERSWALD is not set -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_LEGOTOWER is not set -# CONFIG_USB_LCD is not set -# CONFIG_USB_BERRY_CHARGE is not set -# CONFIG_USB_LED is not set -# CONFIG_USB_CYPRESS_CY7C63 is not set -# CONFIG_USB_CYTHERM is not set -# CONFIG_USB_PHIDGET is not set -# CONFIG_USB_IDMOUSE is not set -# CONFIG_USB_FTDI_ELAN is not set -# CONFIG_USB_APPLEDISPLAY is not set -# CONFIG_USB_SISUSBVGA is not set -# CONFIG_USB_LD is not set -# CONFIG_USB_TRANCEVIBRATOR is not set -# CONFIG_USB_IOWARRIOR is not set -# CONFIG_USB_TEST is not set - -# -# USB DSL modem support -# - -# -# USB Gadget Support -# -# CONFIG_USB_GADGET is not set -CONFIG_MMC=m -# CONFIG_MMC_DEBUG is not set -# CONFIG_MMC_UNSAFE_RESUME is not set - -# -# MMC/SD Card Drivers -# -CONFIG_MMC_BLOCK=m -CONFIG_MMC_BLOCK_BOUNCE=y -# CONFIG_SDIO_UART is not set - -# -# MMC/SD Host Controller Drivers -# -# CONFIG_MMC_SDHCI is not set -# CONFIG_MMC_WBSD is not set -# CONFIG_MMC_TIFM_SD is not set -# CONFIG_NEW_LEDS is not set -# CONFIG_INFINIBAND is not set -# CONFIG_EDAC is not set -# CONFIG_RTC_CLASS is not set -# CONFIG_DMADEVICES is not set -# CONFIG_VIRTUALIZATION is not set - -# -# Userspace I/O -# -# CONFIG_UIO is not set - -# -# Firmware Drivers -# -# CONFIG_EDD is not set -# CONFIG_DELL_RBU is not set -# CONFIG_DCDBAS is not set -CONFIG_DMIID=y - -# -# File systems -# -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT2_FS_POSIX_ACL=y -# CONFIG_EXT2_FS_SECURITY is not set -# CONFIG_EXT2_FS_XIP is not set -CONFIG_EXT3_FS=y -CONFIG_EXT3_FS_XATTR=y -CONFIG_EXT3_FS_POSIX_ACL=y -# CONFIG_EXT3_FS_SECURITY is not set -# CONFIG_EXT4DEV_FS is not set -CONFIG_JBD=y -# CONFIG_JBD_DEBUG is not set -CONFIG_FS_MBCACHE=y -CONFIG_REISERFS_FS=y -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set -CONFIG_REISERFS_FS_XATTR=y -CONFIG_REISERFS_FS_POSIX_ACL=y -# CONFIG_REISERFS_FS_SECURITY is not set -# CONFIG_JFS_FS is not set -CONFIG_FS_POSIX_ACL=y -# CONFIG_XFS_FS is not set -# CONFIG_GFS2_FS is not set -# CONFIG_OCFS2_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -CONFIG_INOTIFY=y -CONFIG_INOTIFY_USER=y -# CONFIG_QUOTA is not set -CONFIG_DNOTIFY=y -# CONFIG_AUTOFS_FS is not set -CONFIG_AUTOFS4_FS=y -# CONFIG_FUSE_FS is not set -CONFIG_GENERIC_ACL=y - -# -# CD-ROM/DVD Filesystems -# -CONFIG_ISO9660_FS=y -CONFIG_JOLIET=y -# CONFIG_ZISOFS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y -CONFIG_VFAT_FS=y -CONFIG_FAT_DEFAULT_CODEPAGE=437 -CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -CONFIG_PROC_KCORE=y -CONFIG_PROC_SYSCTL=y -CONFIG_SYSFS=y -CONFIG_TMPFS=y -CONFIG_TMPFS_POSIX_ACL=y -CONFIG_HUGETLBFS=y -CONFIG_HUGETLB_PAGE=y -# CONFIG_CONFIGFS_FS is not set - -# -# Layered filesystems -# -CONFIG_UNION_FS=y -# CONFIG_UNION_FS_XATTR is not set -# CONFIG_UNION_FS_DEBUG is not set - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set -CONFIG_NETWORK_FILESYSTEMS=y -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -# CONFIG_NFS_V3_ACL is not set -# CONFIG_NFS_V4 is not set -# CONFIG_NFS_DIRECTIO is not set -CONFIG_NFSD=y -CONFIG_NFSD_V3=y -# CONFIG_NFSD_V3_ACL is not set -# CONFIG_NFSD_V4 is not set -CONFIG_NFSD_TCP=y -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -CONFIG_LOCKD_V4=y -CONFIG_EXPORTFS=y -CONFIG_NFS_COMMON=y -CONFIG_SUNRPC=y -# CONFIG_SUNRPC_BIND34 is not set -# CONFIG_RPCSEC_GSS_KRB5 is not set -# CONFIG_RPCSEC_GSS_SPKM3 is not set -# CONFIG_SMB_FS is not set -CONFIG_CIFS=y -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y -CONFIG_NLS=y -CONFIG_NLS_DEFAULT="iso8859-1" -CONFIG_NLS_CODEPAGE_437=y -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -# CONFIG_NLS_CODEPAGE_850 is not set -# CONFIG_NLS_CODEPAGE_852 is not set -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_936 is not set -# CONFIG_NLS_CODEPAGE_950 is not set -# CONFIG_NLS_CODEPAGE_932 is not set -# CONFIG_NLS_CODEPAGE_949 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_CODEPAGE_1250 is not set -# CONFIG_NLS_CODEPAGE_1251 is not set -CONFIG_NLS_ASCII=y -CONFIG_NLS_ISO8859_1=y -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_ISO8859_13 is not set -# CONFIG_NLS_ISO8859_14 is not set -CONFIG_NLS_ISO8859_15=y -# CONFIG_NLS_KOI8_R is not set -# CONFIG_NLS_KOI8_U is not set -CONFIG_NLS_UTF8=y -# CONFIG_DLM is not set -CONFIG_INSTRUMENTATION=y -CONFIG_PROFILING=y -CONFIG_OPROFILE=y -CONFIG_KPROBES=y -# CONFIG_MARKERS is not set - -# -# Kernel hacking -# -CONFIG_TRACE_IRQFLAGS_SUPPORT=y -# CONFIG_PRINTK_TIME is not set -CONFIG_ENABLE_WARN_DEPRECATED=y -# CONFIG_ENABLE_MUST_CHECK is not set -CONFIG_MAGIC_SYSRQ=y -CONFIG_UNUSED_SYMBOLS=y -CONFIG_DEBUG_FS=y -# CONFIG_HEADERS_CHECK is not set -CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_SHIRQ is not set -CONFIG_DETECT_SOFTLOCKUP=y -# CONFIG_SCHED_DEBUG is not set -# CONFIG_SCHEDSTATS is not set -CONFIG_TIMER_STATS=y -# CONFIG_DEBUG_SLAB is not set -CONFIG_DEBUG_PREEMPT=y -# CONFIG_DEBUG_RT_MUTEXES is not set -# CONFIG_RT_MUTEX_TESTER is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_MUTEXES is not set -# CONFIG_DEBUG_LOCK_ALLOC is not set -# CONFIG_PROVE_LOCKING is not set -# CONFIG_LOCK_STAT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set -# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set -# CONFIG_DEBUG_KOBJECT is not set -CONFIG_DEBUG_BUGVERBOSE=y -# CONFIG_DEBUG_INFO is not set -# CONFIG_DEBUG_VM is not set -# CONFIG_DEBUG_LIST is not set -# CONFIG_DEBUG_SG is not set -# CONFIG_FRAME_POINTER is not set -# CONFIG_FORCED_INLINING is not set -# CONFIG_BOOT_PRINTK_DELAY is not set -# CONFIG_RCU_TORTURE_TEST is not set -# CONFIG_LKDTM is not set -# CONFIG_FAULT_INJECTION is not set -# CONFIG_SAMPLES is not set -CONFIG_EARLY_PRINTK=y -CONFIG_DEBUG_STACKOVERFLOW=y -# CONFIG_DEBUG_STACK_USAGE is not set - -# -# Page alloc debug is incompatible with Software Suspend on i386 -# -# CONFIG_DEBUG_RODATA is not set -# CONFIG_4KSTACKS is not set -CONFIG_DOUBLEFAULT=y - -# -# Security options -# -# CONFIG_KEYS is not set -# CONFIG_SECURITY is not set -# CONFIG_SECURITY_FILE_CAPABILITIES is not set -# CONFIG_CRYPTO is not set - -# -# Library routines -# -CONFIG_BITREVERSE=y -# CONFIG_CRC_CCITT is not set -# CONFIG_CRC16 is not set -# CONFIG_CRC_ITU_T is not set -CONFIG_CRC32=y -# CONFIG_CRC7 is not set -# CONFIG_LIBCRC32C is not set -CONFIG_ZLIB_INFLATE=y -CONFIG_PLIST=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y -CONFIG_HAS_DMA=y diff --git a/deps/theme-AdwaitaDark.tar b/deps/theme-AdwaitaDark.tar deleted file mode 100644 index 5b71bb71efd568497e022db09030fd81e9709734..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28663 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 a+vod_RwsiDGRXLk#{U63z!mxc%mDyFu4C)~ diff --git a/desktop b/desktop deleted file mode 100644 index 3b3d867..0000000 --- a/desktop +++ /dev/null @@ -1,70 +0,0 @@ -xserver-xorg -xserver-xorg-input-evdev -xbase-clients -xterm -locales -gsetroot -rxvt-unicode -xfonts-base -xfonts-100dpi -xfonts-75dpi -xfonts-scalable -xfonts-terminus -xfonts-terminus-oblique -fluxbox -hicolor-icon-theme -gnome-icon-theme -gtk2-engines -menu -pcmanfm -leafpad -dbus -hal -pmount -sudo -alsa-base -alsa-utils -pciutils -usbutils -psmisc -wget -curl -less -unzip -zip -vim -ntp -htop -libsdl1.2debian -libsdl1.2debian-alsa -mesa-utils -xmms -smbclient -libopenal0a -libxft2 -cpp -inotify-tools -xpdf -gsfonts-x11 -gimageview -mplayer -xarchiver -numlockx -geany -idesk -wmnd -wmmixer -unclutter -xdialog -smbfs -xeji -gksu -xscreensaver -beep -xclip -xsel -linneighborhood -mktemp -gparted -wmcpuload -wmmemload diff --git a/editions/voodoo2/splash-source.png b/editions/voodoo2/splash-source.png deleted file mode 100644 index ef51355337b127c15b1eb32482944f6802b4dcb2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 706048 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