Skip to content

Instantly share code, notes, and snippets.

@jameschubbuck
Created January 6, 2026 05:01
Show Gist options
  • Select an option

  • Save jameschubbuck/ad4031eaa978e41feecafb67e940a3c5 to your computer and use it in GitHub Desktop.

Select an option

Save jameschubbuck/ad4031eaa978e41feecafb67e940a3c5 to your computer and use it in GitHub Desktop.
Flake for CS106B
{
description = "Flake for Stanford CS106B";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
};
outputs = {
self,
nixpkgs,
}: let
system = "x86_64-linux";
pkgs = import nixpkgs {inherit system;};
qt = pkgs.qt6;
# AOT Comp
qtIncludeFlags = builtins.concatStringsSep " " [
"-I${qt.qtbase.dev}/include"
"-I${qt.qtbase.dev}/include/QtCore"
"-I${qt.qtbase.dev}/include/QtGui"
"-I${qt.qtbase.dev}/include/QtWidgets"
"-I${qt.qtbase.dev}/include/QtNetwork"
"-I${qt.qtmultimedia.dev}/include"
"-I${qt.qtmultimedia.dev}/include/QtMultimedia"
"-DQT_CORE_LIB"
"-DQT_GUI_LIB"
"-DQT_WIDGETS_LIB"
"-DQT_NETWORK_LIB"
"-DQT_MULTIMEDIA_LIB"
];
qtLibFlags = builtins.concatStringsSep " " [
"-L${qt.qtbase}/lib"
"-L${qt.qtmultimedia}/lib"
"-lQt6Core"
"-lQt6Gui"
"-lQt6Widgets"
"-lQt6Network"
"-lQt6Multimedia"
];
cs106-lib = pkgs.stdenv.mkDerivation {
pname = "cs106";
version = "2025.2";
src = pkgs.fetchzip {
url = "https://web.stanford.edu/dept/cs_edu/resources/qt/CS106.zip";
sha256 = "0fddyh8sy9vngnbd8dlif6r86y4gx7h909prsj690mi2s86px48l";
};
sourceRoot = "source/Library";
nativeBuildInputs = [
qt.qtbase
qt.wrapQtAppsHook
pkgs.pkg-config
];
buildInputs = [
qt.qtbase
qt.qtmultimedia
];
configurePhase = ''
runHook preConfigure
qmake Library.pro
runHook postConfigure
'';
buildPhase = ''
runHook preBuild
make -j$NIX_BUILD_CORES libcs106.a
runHook postBuild
'';
installPhase = ''
runHook preInstall
mkdir -p $out/lib $out/include
cp libcs106.a $out/lib/
cp collections/*.h $out/include/ 2>/dev/null || true
cp console/*.h $out/include/ 2>/dev/null || true
cp graphics/*.h $out/include/ 2>/dev/null || true
cp io/*.h $out/include/ 2>/dev/null || true
cp system/*.h $out/include/ 2>/dev/null || true
cp util/*.h $out/include/ 2>/dev/null || true
cp testing/*.h $out/include/ 2>/dev/null || true
cp private/*.h $out/include/ 2>/dev/null || true
cat > $out/include/pch.h << 'PCHEOF'
#ifndef CS106_PCH_H
#define CS106_PCH_H
#include <QApplication>
#include <QWidget>
#include <QString>
#include <QVector>
#include <QMap>
#include <QSet>
#include <QFile>
#include <QTextStream>
#include <QDebug>
#include <QTimer>
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
#include <QPainter>
#include <QImage>
#include <QPixmap>
#include <QFont>
#include <QColor>
#include <QEvent>
#include <QMouseEvent>
#include <QKeyEvent>
#include <QCloseEvent>
#include <QResizeEvent>
#include <QPushButton>
#include <QLabel>
#include <QLineEdit>
#include <QTextEdit>
#include <QCheckBox>
#include <QRadioButton>
#include <QComboBox>
#include <QSlider>
#include <QScrollBar>
#include <QScrollArea>
#include <QTableWidget>
#include <QLayout>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QGridLayout>
#include <QMainWindow>
#include <QDialog>
#include <QFileDialog>
#include <QMessageBox>
#include <QInputDialog>
#include <QColorDialog>
#include <QFontDialog>
#include <QClipboard>
#include <QUrl>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QMediaPlayer>
#include <QAudioOutput>
#include "basicgraph.h"
#include "collections.h"
#include "console.h"
#include "dawglexicon.h"
#include "deque.h"
#include "direction.h"
#include "error.h"
#include "filelib.h"
#include "gbrowserpane.h"
#include "gbutton.h"
#include "gcanvas.h"
#include "gcheckbox.h"
#include "gchooser.h"
#include "gclipboard.h"
#include "gcolor.h"
#include "gcolorchooser.h"
#include "gconsolewindow.h"
#include "gcontainer.h"
#include "gdiffimage.h"
#include "gdownloader.h"
#include "gdrawingsurface.h"
#include "gevent.h"
#include "gfilechooser.h"
#include "gfont.h"
#include "gfontchooser.h"
#include "ginteractor.h"
#include "ginteractors.h"
#include "glabel.h"
#include "glayout.h"
#include "gmath.h"
#include "gobjects.h"
#include "goptionpane.h"
#include "gradiobutton.h"
#include "graph.h"
#include "grid.h"
#include "gridlocation.h"
#include "gscrollbar.h"
#include "gscrollpane.h"
#include "gslider.h"
#include "gspacer.h"
#include "gtable.h"
#include "gtextarea.h"
#include "gtextfield.h"
#include "gthread.h"
#include "gtimer.h"
#include "gtypes.h"
#include "gwindow.h"
#include "hashcode.h"
#include "hashmap.h"
#include "hashset.h"
#include "lexicon.h"
#include "linkedlist.h"
#include "map.h"
#include "observable.h"
#include "priorityqueue.h"
#include "qtgui.h"
#include "queue.h"
#include "random.h"
#include "require.h"
#include "set.h"
#include "simpio.h"
#include "SimpleTest.h"
#include "sound.h"
#include "stack.h"
#include "strlib.h"
#include "timer.h"
#include "tokenscanner.h"
#include "urlstream.h"
#include "vector.h"
#endif // CS106_PCH_H
PCHEOF
# Compile the precompiled header
QT_CFLAGS=$(pkg-config --cflags Qt6Core Qt6Gui Qt6Widgets Qt6Network Qt6Multimedia)
g++ -std=c++17 -O2 \
-I$out/include \
$QT_CFLAGS \
-Dmain=qMain -DqMain=studentMain \
-x c++-header $out/include/pch.h \
-o $out/include/pch.h.gch
runHook postInstall
'';
};
runScript = pkgs.writeShellScriptBin "run" ''
set -e
SOURCE="$1"
shift
if [ ! -f "$SOURCE" ]; then
echo "Error: Source file '$SOURCE' not found"
exit 1
fi
SOURCE_DIR=$(dirname "$(readlink -f "$SOURCE")")
BASENAME=$(basename "$SOURCE" .cpp)
OUTPUT=$(mktemp -d)/''${BASENAME}
echo "Compiling $SOURCE..."
${pkgs.gcc}/bin/g++ \
-std=c++17 -O2 \
-include ${cs106-lib}/include/pch.h \
-I${cs106-lib}/include \
${qtIncludeFlags} \
-Dmain=qMain -DqMain=studentMain \
"$SOURCE" \
-L${cs106-lib}/lib -lcs106 -lpthread \
${qtLibFlags} \
-o "$OUTPUT"
echo "Running $BASENAME..."
echo "---"
cd "$SOURCE_DIR"
exec "$OUTPUT" "$@"
'';
in {
packages.${system} = {
cs106 = cs106-lib;
default = cs106-lib;
};
devShells.${system}.default = pkgs.mkShell {
name = "cs106b-dev";
buildInputs = [
cs106-lib
qt.qtbase
qt.qtmultimedia
pkgs.gnumake
pkgs.gdb
pkgs.pkg-config
pkgs.gcc
runScript
];
nativeBuildInputs = [
qt.wrapQtAppsHook
];
shellHook = ''
# Supress QT multimedia warnings. The nixpkgs Qt6 packages don't have support this and it's out of scope.
export QT_LOGGING_RULES="qt.qpa.wayland.textinput.warning=false;qt.multimedia.*=false;default.warning=false;kf.windowsystem.warning=false;qt.core.qfuture.continuations.warning=false"
export QT_QPA_PLATFORM_PLUGIN_PATH="${qt.qtbase}/${qt.qtbase.qtPluginPrefix}/platforms"
export QT_PLUGIN_PATH="${qt.qtbase}/${qt.qtbase.qtPluginPrefix}"
export LD_LIBRARY_PATH="${pkgs.lib.makeLibraryPath [
pkgs.stdenv.cc.cc.lib
pkgs.zlib
qt.qtbase
qt.qtmultimedia
]}:$LD_LIBRARY_PATH"
'';
};
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment