Compare commits

..

37 Commits
master ... wfvm

Author SHA1 Message Date
4419818631 artiq-full: fix vivado.nix path 2020-06-17 22:25:42 +02:00
4bfe5420d3 artiq-board: let artiq-full pass vivado 2020-06-17 22:21:02 +02:00
b876be5ef9 artiq-board: move inputs outside inner function 2020-06-17 22:16:58 +02:00
f5429f28ae add more tracing 2020-06-17 22:10:28 +02:00
6ba6edd6f2 Revert "artiq-full: disable other jobs"
This reverts commit dcad2654a3.
2020-06-17 22:09:30 +02:00
5496b3fa05 add trace 2020-06-17 22:08:33 +02:00
c1490f2c68 add some tracing 2020-06-17 21:11:22 +02:00
dcad2654a3 artiq-full: disable other jobs 2020-06-17 19:08:20 +02:00
59d6df933e point to nix-scripts.git wfvm branch 2020-06-17 16:58:53 +02:00
f9d5fd0520 windows: disable kvm
testing under kvm...
2020-06-17 16:58:53 +02:00
2c0015979c point to my nix-scripts.git 2020-06-17 16:58:53 +02:00
adisbladis
6edecf8671 Add a sleep after install script
Sometimes files are not fully synced to disk despite the install
script exiting with success status.
2020-06-17 16:58:53 +02:00
adisbladis
1f0d703646 Remove redhat cert (leftover from WHQL) 2020-06-17 16:58:53 +02:00
adisbladis
e320bd6181 Remove nuget 2020-06-17 16:58:53 +02:00
adisbladis
73e247e5b9 Dead code removal 2020-06-17 16:58:53 +02:00
adisbladis
28da250925 Add support for incremental install of packages 2020-06-17 16:58:53 +02:00
adisbladis
7b4cd0b944 Split Qemu parameters
So we can re-use params for incremental install
2020-06-17 16:58:53 +02:00
adisbladis
6bbbd41ece Remove anaconda bundle
This one will be installed in a separate step incrementally
2020-06-17 16:58:53 +02:00
adisbladis
3e7e6941b8 Add a baseRtc option so set the VM clock 2020-06-17 16:58:53 +02:00
adisbladis
9e6775fe8d Override p7zip to fix build with nixpkgs >20.03 2020-06-17 16:58:53 +02:00
adisbladis
c147ddee56 Document pure/impure mode 2020-06-17 16:58:53 +02:00
adisbladis
34404ddf6b Switch impure mode to parameter 2020-06-17 16:58:53 +02:00
895359eade windows: remove outdated installation instructions 2020-06-17 16:58:53 +02:00
adisbladis
7e82318fd1 Remove declarative SSH keys
Windows changes the naming structure of homedir directories if it
encounters an already present homedir so this is not working as intended.
2020-06-17 16:58:53 +02:00
adisbladis
23e9666550 Fix conda base package
I'm not sure whether to include this in the default image so it's
uncommented for now
2020-06-17 16:58:53 +02:00
adisbladis
b410bd6b35 windows: Dont use deprecated method of openssh server installation
Add OpenSSH cab file extracted from Windows FOD iso
2020-06-17 16:58:53 +02:00
adisbladis
51f93e5852 windows: Fix build termination 2020-06-17 16:58:53 +02:00
adisbladis
6b4e6548e5 windows: Fix stupid quoting issues in autounattend XML
The windows XML parser is shit and bails out extremely late, making
debugging this a 1+ hour ordeal for every iteration.

Let's just write out a powershell script and be done with it.
2020-06-17 16:58:53 +02:00
adisbladis
d90a2716bd windows: Fix quoting issues in XML 2020-06-17 16:58:53 +02:00
adisbladis
a1e5d01f80 windows: Dont run in impure mode 2020-06-17 16:58:53 +02:00
adisbladis
738ce24d9c windows: Adapt tests to new build infra 2020-06-17 16:58:53 +02:00
adisbladis
9f3e515c01 windows: Add Anaconda to base windows install 2020-06-17 16:58:53 +02:00
adisbladis
fbc4530388 windows: Fix extra quote 2020-06-17 16:58:53 +02:00
adisbladis
70562bcdfd windows: Remove impureMode from autounattend
It was always a hack to circumvent pure setup not being completed.
2020-06-17 16:58:53 +02:00
adisbladis
fc3b685167 windows: Remove virtiowin & autohotkey
Let's consider these attempts of automation failures since virtio-win
cannot be reasonably automated.
Windows WHQL checks for drivers are not possible to remove.
2020-06-17 16:58:53 +02:00
adisbladis
3d0375c218 windows: Fix SSH key setup 2020-06-17 16:58:53 +02:00
adisbladis
a5d93aea35 windows: Add automated declarative windows install 2020-06-17 16:58:51 +02:00
142 changed files with 24231 additions and 1726 deletions

132
artiq-fast.nix Normal file
View File

@ -0,0 +1,132 @@
let
pkgs = import <nixpkgs> {};
artiqSrc = <artiqSrc>;
generatedNix = pkgs.runCommand "generated-nix" { buildInputs = [ pkgs.nix pkgs.git ]; }
# keep in sync with artiq-fast/pkgs/artiq-version.nix
''
cp --no-preserve=mode,ownership -R ${./artiq-fast} $out
REV=`git --git-dir ${artiqSrc}/.git rev-parse HEAD`
MAJOR_VERSION=`cat ${artiqSrc}/MAJOR_VERSION`
if [ -e ${artiqSrc}/BETA ]; then
SUFFIX=".beta"
else
SUFFIX=""
fi
COMMIT_COUNT=`git --git-dir ${artiqSrc}/.git rev-list --count HEAD`
TIMESTAMP=`git --git-dir ${artiqSrc}/.git log -1 --format=%ct`
ARTIQ_SRC_CLEAN=`mktemp -d`
cp -a ${artiqSrc}/. $ARTIQ_SRC_CLEAN
chmod -R 755 $ARTIQ_SRC_CLEAN/.git
chmod 755 $ARTIQ_SRC_CLEAN
rm -rf $ARTIQ_SRC_CLEAN/.git
HASH=`nix-hash --type sha256 --base32 $ARTIQ_SRC_CLEAN`
cat > $out/pkgs/artiq-src.nix << EOF
{ fetchgit }:
fetchgit {
url = "git://github.com/m-labs/artiq.git";
rev = "$REV";
sha256 = "$HASH";
}
EOF
echo "{ stdenv, git, fetchgit }: \"$MAJOR_VERSION.$COMMIT_COUNT.`cut -c1-8 <<< $REV`$SUFFIX\"" > $out/pkgs/artiq-version.nix
echo "{ stdenv, git, fetchgit }: \"$TIMESTAMP\"" > $out/pkgs/artiq-timestamp.nix
'';
generateTestOkHash = pkgs.runCommand "generate-test-ok-hash" { buildInputs = [ pkgs.nix ]; }
''
TMPDIR=`mktemp -d`
cp ${generatedNix}/pkgs/artiq-version.nix $TMPDIR/passed
HASH=`nix-hash --type sha256 --base32 $TMPDIR`
echo \"$HASH\" > $out
'';
artiqpkgs = import "${generatedNix}/default.nix" { inherit pkgs; };
artiqVersion = import "${generatedNix}/pkgs/artiq-version.nix" (with pkgs; { inherit stdenv fetchgit git; });
windowsRunner = overrides:
import "${generatedNix}/windows/run-test.nix" ({
inherit pkgs;
sipycoPkg = artiqpkgs.conda-sipyco;
artiqPkg = artiqpkgs.conda-artiq;
} // overrides);
jobs = (builtins.mapAttrs (key: value: pkgs.lib.hydraJob value) artiqpkgs);
in
jobs // {
generated-nix = pkgs.lib.hydraJob generatedNix; # used by artiq-full
artiq-fast = pkgs.releaseTools.channel {
name = "artiq-fast";
src = generatedNix;
constituents = builtins.attrValues jobs;
};
windows-no-hardware-tests = pkgs.stdenv.mkDerivation {
name = "windows-no-hardware-tests";
buildInputs = [ (windowsRunner {}) ];
phases = [ "buildPhase" ];
buildPhase = ''
${windowsRunner {}}/bin/run.sh
touch $out
'';
};
# HACK: Abuse fixed-output derivations to escape the sandbox and run the hardware
# unit tests, all integrated in the Hydra interface.
# One major downside of this hack is the tests are only run when generateTestOkHash
# changes, i.e. when the ARTIQ version changes (and not the dependencies).
# Impure derivations, when they land in Nix/Hydra, should improve the situation.
extended-tests = pkgs.stdenv.mkDerivation {
name = "extended-tests";
outputHashAlgo = "sha256";
outputHashMode = "recursive";
outputHash = import generateTestOkHash;
__hydraRetry = false;
buildInputs = [
(pkgs.python3.withPackages(ps: [ ps.paramiko artiqpkgs.artiq artiqpkgs.artiq-board-kc705-nist_clock ]))
artiqpkgs.binutils-or1k
artiqpkgs.openocd
pkgs.iputils
pkgs.openssh
];
phases = [ "buildPhase" ];
buildPhase =
''
export HOME=`mktemp -d`
mkdir $HOME/.ssh
cp /opt/hydra_id_rsa $HOME/.ssh/id_rsa
cp /opt/hydra_id_rsa.pub $HOME/.ssh/id_rsa.pub
echo "rpi-1,192.168.1.188 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMc7waNkP2HjL5Eo94evoxJhC8CbYj4i2n1THe5TPIR3" > $HOME/.ssh/known_hosts
chmod 600 $HOME/.ssh/id_rsa
LOCKCTL=$(mktemp -d)
mkfifo $LOCKCTL/lockctl
cat $LOCKCTL/lockctl | ${pkgs.openssh}/bin/ssh \
-i $HOME/.ssh/id_rsa \
-o UserKnownHostsFile=$HOME/.ssh/known_hosts \
sb@rpi-1 \
'flock /tmp/board_lock-kc705-1 -c "echo Ok; cat"' \
| (
# End remote flock via FIFO
atexit_unlock() {
echo > $LOCKCTL/lockctl
}
trap atexit_unlock EXIT
# Read "Ok" line when remote successfully locked
read LOCK_OK
artiq_flash -t kc705 -H rpi-1
sleep 15
# ping: socket: Operation not permitted
#ping kc705-1 -c10 -w30
export ARTIQ_ROOT=`python -c "import artiq; print(artiq.__path__[0])"`/examples/kc705_nist_clock
export ARTIQ_LOW_LATENCY=1
python -m unittest discover -v artiq.test.coredevice
${windowsRunner { testCommand = "set ARTIQ_ROOT=%cd%\\anaconda\\envs\\artiq-env\\Lib\\site-packages\\artiq\\examples\\kc705_nist_clock&&python -m unittest discover -v artiq.test.coredevice"; }}/bin/run.sh
)
mkdir $out
cp ${generatedNix}/pkgs/artiq-version.nix $out/passed
'';
};
}

101
artiq-fast/artiq-board.nix Normal file
View File

@ -0,0 +1,101 @@
# Install Vivado in /opt and add to /etc/nixos/configuration.nix:
# nix.sandboxPaths = ["/opt"];
{ pkgs
, vivado ? (builtins.trace "vivado" (import ./vivado.nix { inherit pkgs; }))
}:
let
artiqSrc = import ./pkgs/artiq-src.nix { fetchgit = pkgs.fetchgit; };
artiqpkgs = builtins.trace "artiqpkgs" (import ./default.nix { inherit pkgs; });
fetchcargo = import ./fetchcargo.nix {
inherit (pkgs) stdenv cacert git;
inherit (artiqpkgs) cargo cargo-vendor;
};
cargoDeps = fetchcargo rec {
name = "artiq-firmware-cargo-deps";
src = "${artiqSrc}/artiq/firmware";
sha256 = (import "${artiqSrc}/artiq/firmware/cargosha256.nix");
};
cargoVendored = pkgs.stdenv.mkDerivation {
name = "artiq-firmware-cargo-vendored";
src = cargoDeps;
phases = [ "unpackPhase" "installPhase" ];
installPhase =
''
mkdir -p $out/registry
cat << EOF > $out/config
[source.crates-io]
registry = "https://github.com/rust-lang/crates.io-index"
replace-with = "vendored-sources"
[source."https://github.com/m-labs/libfringe"]
git = "https://github.com/m-labs/libfringe"
rev = "b8a6d8f"
replace-with = "vendored-sources"
[source.vendored-sources]
directory = "$out/registry"
EOF
cp -R * $out/registry
'';
};
in
{ target
, variant
, buildCommand ? "python -m artiq.gateware.targets.${target} -V ${variant}"
, extraInstallCommands ? ""}:
let
# Board packages are Python modules so that they get added to the ARTIQ Python
# environment, and artiq_flash finds them.
in pkgs.python3Packages.toPythonModule (pkgs.stdenv.mkDerivation rec {
name = "artiq-board-${target}-${variant}-${version}";
version = import ./pkgs/artiq-version.nix (with pkgs; { inherit stdenv fetchgit git; });
phases = [ "buildPhase" "installCheckPhase" "installPhase" ];
buildInputs = [
vivado
pkgs.gnumake
(pkgs.python3.withPackages(ps: with ps; [ jinja2 numpy artiqpkgs.migen artiqpkgs.microscope artiqpkgs.misoc artiqpkgs.jesd204b artiqpkgs.artiq ]))
artiqpkgs.cargo
artiqpkgs.rustc
artiqpkgs.binutils-or1k
artiqpkgs.llvm-or1k
];
buildPhase =
''
export CARGO_HOME=${cargoVendored}
export TARGET_AR=or1k-linux-ar
${buildCommand}
'';
checkPhase = ''
# Search for PCREs in the Vivado output to check for errors
check_log() {
set +e
grep -Pe "$1" artiq_${target}/${variant}/gateware/vivado.log
FOUND=$?
set -e
if [ $FOUND != 1 ]; then
exit 1
fi
}
check_log "\d+ constraint not met\."
check_log "Timing constraints are not met\."
'';
installPhase =
''
TARGET_DIR=$out/${pkgs.python3Packages.python.sitePackages}/artiq/board-support/${target}-${variant}
mkdir -p $TARGET_DIR
cp artiq_${target}/${variant}/gateware/top.bit $TARGET_DIR
if [ -e artiq_${target}/${variant}/software/bootloader/bootloader.bin ]
then cp artiq_${target}/${variant}/software/bootloader/bootloader.bin $TARGET_DIR
fi
if [ -e artiq_${target}/${variant}/software/runtime ]
then cp artiq_${target}/${variant}/software/runtime/runtime.{elf,fbi} $TARGET_DIR
else cp artiq_${target}/${variant}/software/satman/satman.{elf,fbi} $TARGET_DIR
fi
${extraInstallCommands}
'';
})

View File

@ -0,0 +1,72 @@
{ pkgs, version, src, target }:
let
wfvm = import ../wfvm { inherit pkgs; };
libiconv-filename = "libiconv-1.15-h0c8e037_1006.tar.bz2";
libiconv = pkgs.fetchurl {
url = "https://anaconda.org/conda-forge/libiconv/1.15/download/win-64/${libiconv-filename}";
sha256 = "1jaxnpg5y5pkhvpp9kaq0kpvz7jlj5hynp567q35l7hpfk6xxghh";
};
build = wfvm.utils.wfvm-run {
name = "build-binutils";
image = wfvm.makeWindowsImage { installCommands = with wfvm.layers; [ anaconda3 msys2 msys2-packages ]; };
script = ''
${wfvm.utils.win-put}/bin/win-put ${libiconv} ${libiconv-filename}
${wfvm.utils.win-exec}/bin/win-exec ".\Anaconda3\scripts\activate && conda create -n build ${libiconv-filename}"
cat > meta.yaml << EOF
package:
name: binutils-${target}
version: ${version}
source:
url: ../src.tar.bz2
requirements:
run:
- libiconv
EOF
cat > bld.bat << EOF
set MSYS=C:\MSYS64
set TOOLPREF=mingw-w64-x86_64-
set TRIPLE=x86_64-pc-mingw64
set PATH=%MSYS%\usr\bin;%MSYS%\mingw64\bin;%PATH%
mkdir build
cd build
set CFLAGS=-I%PREFIX:\=/%/Library/include/
set LDFLAGS=-L%PREFIX:\=/%/Library/lib/
sh ../configure --build=%TRIPLE% ^
--prefix="%PREFIX:\=/%/Library" ^
--target=${target}
if errorlevel 1 exit 1
make -j4
if errorlevel 1 exit 1
make install
if errorlevel 1 exit 1
rem this is a copy of prefixed executables
rmdir /S /Q %PREFIX%\Library\${target}
EOF
${wfvm.utils.win-exec}/bin/win-exec "mkdir binutils"
${wfvm.utils.win-put}/bin/win-put meta.yaml ".\binutils"
${wfvm.utils.win-put}/bin/win-put bld.bat ".\binutils"
${wfvm.utils.win-put}/bin/win-put ${src} ".\src.tar.bz2"
${wfvm.utils.win-exec}/bin/win-exec ".\Anaconda3\scripts\activate build && conda build --no-anaconda-upload --no-test binutils"
${wfvm.utils.win-get}/bin/win-get ".\Anaconda3\conda-bld\win-64\binutils-${target}-${version}-0.tar.bz2"
'';
};
in
pkgs.runCommand "conda-windows-binutils-${target}" { buildInputs = [ build ]; } ''
wfvm-run-build-binutils
mkdir -p $out/win-64 $out/nix-support
cp *.tar.bz2 $out/win-64
echo file conda $out/win-64/*.tar.bz2 >> $out/nix-support/hydra-build-products
''

View File

@ -0,0 +1,66 @@
{ pkgs, version, src }:
let
wfvm = import ../wfvm { inherit pkgs; };
build = wfvm.utils.wfvm-run {
name = "build-llvm-or1k";
image = wfvm.makeWindowsImage { installCommands = with wfvm.layers; [ anaconda3 msys2 msys2-packages ]; };
script = ''
${wfvm.utils.win-exec}/bin/win-exec ".\Anaconda3\scripts\activate && conda create -n build --offline"
cat > meta.yaml << EOF
package:
name: llvm-or1k
version: ${version}
source:
url: ../src.tar
EOF
cat > bld.bat << EOF
set MSYS=C:\MSYS64
set PATH=%MSYS%\usr\bin;%MSYS%\mingw64\bin;%PATH%
set BUILD_TYPE=Release
set CMAKE_GENERATOR=MinGW Makefiles
mkdir build
cd build
cmake .. -G "%CMAKE_GENERATOR%" ^
-DCMAKE_BUILD_TYPE="%BUILD_TYPE%" ^
-DCMAKE_INSTALL_PREFIX="%LIBRARY_PREFIX%" ^
-DLLVM_BUILD_LLVM_DYLIB=ON ^
-DLLVM_TARGETS_TO_BUILD=X86;ARM ^
-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=OR1K ^
-DLLVM_ENABLE_ASSERTIONS=OFF ^
-DLLVM_INSTALL_UTILS=ON ^
-DLLVM_INCLUDE_TESTS=OFF ^
-DLLVM_INCLUDE_DOCS=OFF ^
-DLLVM_INCLUDE_EXAMPLES=OFF
if errorlevel 1 exit 1
cmake --build . --config "%BUILD_TYPE%" --parallel 4
if errorlevel 1 exit 1
cmake --build . --config "%BUILD_TYPE%" --target install
if errorlevel 1 exit 1
EOF
${wfvm.utils.win-exec}/bin/win-exec "mkdir llvm-or1k"
${wfvm.utils.win-put}/bin/win-put meta.yaml ".\llvm-or1k"
${wfvm.utils.win-put}/bin/win-put bld.bat ".\llvm-or1k"
ln -s ${src} src
tar chf src.tar src
${wfvm.utils.win-put}/bin/win-put src.tar ".\src.tar"
${wfvm.utils.win-exec}/bin/win-exec ".\Anaconda3\scripts\activate build && conda build --no-anaconda-upload --no-test llvm-or1k"
${wfvm.utils.win-get}/bin/win-get ".\Anaconda3\conda-bld\win-64\llvm-or1k-${version}-0.tar.bz2"
'';
};
in
pkgs.runCommand "conda-windows-llvm-or1k" { buildInputs = [ build ]; } ''
wfvm-run-build-llvm-or1k
mkdir -p $out/win-64 $out/nix-support
cp *.tar.bz2 $out/win-64
echo file conda $out/win-64/*.tar.bz2 >> $out/nix-support/hydra-build-products
''

View File

@ -0,0 +1,53 @@
{ pkgs, conda-windows-llvm-or1k, version, src }:
# See: https://github.com/valtron/llvm-stuff/wiki/Build-llvmlite-with-MSYS2
let
wfvm = import ../wfvm { inherit pkgs; };
build = wfvm.utils.wfvm-run {
name = "build-llvmlite-artiq";
image = wfvm.makeWindowsImage { installCommands = with wfvm.layers; [ anaconda3 msys2 msys2-packages ]; };
script = ''
${wfvm.utils.win-put}/bin/win-put "${conda-windows-llvm-or1k}/win-64/llvm-or1k-*.tar.bz2" ".\llvm-or1k.tar.bz2"
${wfvm.utils.win-exec}/bin/win-exec ".\Anaconda3\scripts\activate && conda create -n build llvm-or1k.tar.bz2"
cat > meta.yaml << EOF
package:
name: llvmlite-artiq
version: ${version}
source:
url: ../src.tar
EOF
cat > bld.bat << EOF
set MSYS=C:\MSYS64
set PATH=%MSYS%\usr\bin;%MSYS%\mingw64\bin;%PATH%
python setup.py install \
--prefix=\$PREFIX \
--single-version-externally-managed \
--record=record.txt \
--no-compile
EOF
${wfvm.utils.win-exec}/bin/win-exec "mkdir llvmlite-artiq"
${wfvm.utils.win-put}/bin/win-put meta.yaml ".\llvmlite-artiq"
${wfvm.utils.win-put}/bin/win-put bld.bat ".\llvmlite-artiq"
cp --no-preserve=mode,ownership -R ${src} src
patch -d src -p1 < ${./llvmlite-msys.diff}
tar chf src.tar src
${wfvm.utils.win-put}/bin/win-put src.tar ".\src.tar"
${wfvm.utils.win-exec}/bin/win-exec ".\Anaconda3\scripts\activate build && conda build --no-anaconda-upload --no-test llvmlite-artiq"
${wfvm.utils.win-get}/bin/win-get ".\Anaconda3\conda-bld\win-64\llvmlite-artiq-${version}-0.tar.bz2"
'';
};
in
pkgs.runCommand "conda-windows-llvmlite-artiq" { buildInputs = [ build ]; } ''
wfvm-run-build-llvmlite-artiq
mkdir -p $out/win-64 $out/nix-support
cp *.tar.bz2 $out/win-64
echo file conda $out/win-64/*.tar.bz2 >> $out/nix-support/hydra-build-products
''

View File

@ -0,0 +1,42 @@
diff --git a/ffi/CMakeLists.txt b/ffi/CMakeLists.txt
index 15470d4..11d06a5 100755
--- a/ffi/CMakeLists.txt
+++ b/ffi/CMakeLists.txt
@@ -29,6 +29,7 @@ list(REMOVE_ITEM LLVM_AVAILABLE_LIBS LTO LLVM)
# that we wish to use
# llvm_map_components_to_libnames(llvm_libs support core irreader)
llvm_map_components_to_libnames(llvm_libs all)
+list(REMOVE_ITEM llvm_libs "LTO")
# Link against LLVM libraries
target_link_libraries(llvmlite ${llvm_libs})
diff --git a/ffi/build.py b/ffi/build.py
index 9169d35..41a9a40 100755
--- a/ffi/build.py
+++ b/ffi/build.py
@@ -24,7 +24,7 @@ def try_cmake(cmake_dir, build_dir, generator):
old_dir = os.getcwd()
try:
os.chdir(build_dir)
- subprocess.check_call(['cmake', '-G', generator, cmake_dir])
+ subprocess.check_call(['cmake', '-G', generator, '-D', 'LLVM_DIR=$LLVM/lib/cmake/llvm', cmake_dir])
finally:
os.chdir(old_dir)
@@ -57,6 +57,7 @@ def find_win32_generator():
if is_64bit:
generator += ' Win64'
build_dir = tempfile.mkdtemp()
+ generator = 'MinGW Makefiles'
print("Trying generator %r" % (generator,))
try:
try_cmake(cmake_dir, build_dir, generator)
@@ -78,7 +79,7 @@ def main_win32():
# Run configuration step
try_cmake(here_dir, build_dir, generator)
subprocess.check_call(['cmake', '--build', build_dir, '--config', config])
- shutil.copy(os.path.join(build_dir, config, 'llvmlite.dll'), target_dir)
+ shutil.copy(os.path.join(build_dir, 'libllvmlite.dll'), os.path.join(target_dir, 'llvmlite.dll'))
def main_posix(kind, library_ext):

View File

@ -0,0 +1,17 @@
[
"python >=3.5.3"
"llvmlite-artiq"
"binutils-or1k-linux >=2.27"
"pythonparser >=1.1"
"scipy"
"numpy"
"prettytable"
"h5py 2.8"
"python-dateutil"
"pyqt >=5.5"
"quamash"
"pyqtgraph 0.10.0"
"pygit2"
"python-levenshtein"
"sipyco"
]

View File

@ -0,0 +1,23 @@
{ pkgs }:
let
version = import ../pkgs/artiq-version.nix (with pkgs; { inherit stdenv fetchgit git; });
fakeCondaSource = import ./fake-source.nix { inherit pkgs; } {
name = "artiq";
inherit version;
src = import ../pkgs/artiq-src.nix { fetchgit = pkgs.fetchgit; };
dependencies = import ./artiq-deps.nix;
extraYaml =
''
about:
home: https://m-labs.hk/artiq
license: LGPL
summary: 'A leading-edge control system for quantum information experiments'
'';
};
conda-artiq = import ./build.nix { inherit pkgs; } {
name = "conda-artiq";
src = fakeCondaSource;
};
in
conda-artiq

View File

@ -0,0 +1,45 @@
{ pkgs, version, src, target }:
let
fake-src = pkgs.runCommand "conda-fake-source-binutils-${target}" { }
''
mkdir -p $out/fake-conda;
cat << EOF > $out/fake-conda/meta.yaml
package:
name: binutils-${target}
version: ${version}
source:
url: ${src}
# Note: libiconv is also a build dependency, but the conda garbage won't find it
# if installed from a file (even if it shows up in conda list), as is the case
# when using this script.
requirements:
run:
- libiconv
EOF
cat << EOF > $out/fake-conda/build.sh
#!/bin/bash
set -e
mkdir build
cd build
../configure --target=${target} --prefix=\$PREFIX
make
make install
# this is a copy of prefixed executables
rm -rf $PREFIX/${target}
EOF
chmod 755 $out/fake-conda/build.sh
'';
in
import ./build.nix { inherit pkgs; } {
name = "conda-binutils-${target}";
src = fake-src;
}

View File

@ -0,0 +1,36 @@
{ pkgs, bscan_spi_bitstreams }:
let
src = pkgs.runCommand "conda-fake-source-bscan_spi_bitstreams" { }
''
mkdir -p $out/fake-conda;
# work around yet more idiotic conda behavior - build breaks if write permissions aren't set on source files.
cp --no-preserve=mode,ownership -R ${bscan_spi_bitstreams} workaround-conda
pushd workaround-conda
tar cf $out/src.tar .
popd
rm -rf workaround-conda
cat << EOF > $out/fake-conda/meta.yaml
package:
name: bscan-spi-bitstreams
version: "0.10.0"
source:
url: ../src.tar
build:
noarch: generic
binary_relocation: false
script:
- "mkdir -p \$PREFIX/share/bscan-spi-bitstreams"
- "cp *.bit \$PREFIX/share/bscan-spi-bitstreams"
EOF
'';
in
import ./build.nix { inherit pkgs; } {
name = "conda-bscan_spi_bitstreams";
inherit src;
}

View File

@ -0,0 +1,20 @@
# We need to pass the whole source to conda for the git variables to work.
# recipe must be a string pointing to a path within the source.
{ pkgs }:
{ name, src, recipe ? "fake-conda"}:
let
condaBuilderEnv = import ./builder-env.nix { inherit pkgs; };
in pkgs.stdenv.mkDerivation {
inherit name src;
buildCommand =
''
HOME=`pwd`
mkdir $out
${condaBuilderEnv}/bin/conda-builder-env -c "conda build --no-anaconda-upload --no-test --output-folder $out $src/${recipe}"
mkdir -p $out/nix-support
echo file conda $out/*/*.tar.bz2 >> $out/nix-support/hydra-build-products
'';
}

View File

@ -0,0 +1,47 @@
{ pkgs }:
with pkgs;
let
condaDeps = [ stdenv.cc xorg.libSM xorg.libICE xorg.libX11 xorg.libXau xorg.libXi xorg.libXrender libselinux libGL ];
# Use the full Anaconda distribution, which already contains conda-build and its many dependencies,
# so we don't have to manually deal with them.
condaInstaller = fetchurl {
url = "https://repo.anaconda.com/archive/Anaconda3-2019.03-Linux-x86_64.sh";
sha256 = "0fmpdd5876ylds98mydmv5klnwlzasa461k0l1f4vhbw96vm3j25";
};
condaSrcChmod = runCommand "conda-src-chmod" { } "mkdir $out; cp ${condaInstaller} $out/conda-installer.sh; chmod +x $out/conda-installer.sh";
condaInstallerEnv = buildFHSUserEnv {
name = "conda-installer-env";
targetPkgs = pkgs: ([ condaSrcChmod ] ++ condaDeps);
};
# for binutils
libiconv-filename = "libiconv-1.15-h516909a_1006.tar.bz2";
libiconv = pkgs.fetchurl {
url = "https://anaconda.org/conda-forge/libiconv/1.15/download/linux-64/${libiconv-filename}";
sha256 = "1y1g807881j95f9s6mjinf6b7mqa51vc9jf0v7cx8hn7xx4d10ik";
};
condaInstalled = runCommand "conda-installed" { }
''
${condaInstallerEnv}/bin/conda-installer-env -c "${condaSrcChmod}/conda-installer.sh -p $out -b"
substituteInPlace $out/lib/python3.7/site-packages/conda/gateways/disk/__init__.py \
--replace "os.chmod(path, 0o2775)" "pass"
# The conda garbage breaks if the package filename is prefixed with the Nix store hash.
# Symptom is "WARNING conda.core.prefix_data:_load_single_record(167): Ignoring malformed
# prefix record at: /nix/store/[...].json", and the package is not registered in the conda
# list, even though its files are installed.
ln -s ${libiconv} ${libiconv-filename}
${condaInstallerEnv}/bin/conda-installer-env -c "$out/bin/conda install ${libiconv-filename}"
'';
in
buildFHSUserEnv {
name = "conda-builder-env";
targetPkgs = pkgs: ([ condaInstalled ] ++ condaDeps ++ [
# for llvm-or1k
cmake
]
);
}

View File

@ -0,0 +1,57 @@
{ pkgs }:
{ name, version, src, extraSrcCommands ? "", dependencies ? [], extraYaml ? ""}:
pkgs.runCommand "conda-fake-source-${name}" { }
''
mkdir -p $out/fake-conda;
# work around yet more idiotic conda behavior - build breaks if write permissions aren't set on source files.
cp --no-preserve=mode,ownership -R ${src} workaround-conda
pushd workaround-conda
${extraSrcCommands}
tar cf $out/src.tar .
popd
rm -rf workaround-conda
cat << EOF > $out/fake-conda/meta.yaml
package:
name: ${name}
version: ${version}
source:
url: ../src.tar
{% set data = load_setup_py_data() %}
build:
noarch: python
entry_points:
# NOTE: conda-build cannot distinguish between console and gui scripts
{% for entry_point_type, entry_points in data.get("entry_points", dict()).items() -%}
{% for entry_point in entry_points -%}
- {{ entry_point }}
{% endfor %}
{% endfor %}
ignore_prefix_files: True
requirements:
run:
${pkgs.lib.concatStringsSep "\n" (map (s: " - ${s}") dependencies)}
${extraYaml}
EOF
cat << EOF > $out/fake-conda/build.sh
#!/bin/bash
set -e
export VERSIONEER_OVERRIDE=${version}
export LD_LIBRARY_PATH=/lib
python setup.py install \
--prefix=\$PREFIX \
--single-version-externally-managed \
--record=record.txt \
--no-compile
EOF
chmod 755 $out/fake-conda/build.sh
''

View File

@ -0,0 +1,52 @@
{ pkgs, version, src }:
let
fake-src = pkgs.runCommand "conda-fake-source-llvm-or1k" { }
''
mkdir -p $out/fake-conda;
# work around yet more idiotic conda behavior - build breaks if write permissions aren't set on source files.
cp --no-preserve=mode,ownership -R ${src} workaround-conda
pushd workaround-conda
tar cf $out/src.tar .
popd
rm -rf workaround-conda
cat << EOF > $out/fake-conda/meta.yaml
package:
name: llvm-or1k
version: ${version}
# Use the nixpkgs cmake to build, so we are less bothered by conda idiocy.
source:
url: ../src.tar
EOF
cat << EOF > $out/fake-conda/build.sh
mkdir build
cd build
cmake .. \$COMPILER32 \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=\$PREFIX \
-DLLVM_BUILD_LLVM_DYLIB=ON \
-DLLVM_LINK_LLVM_DYLIB=ON \
-DLLVM_TARGETS_TO_BUILD=X86\;ARM \
-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=OR1K \
-DLLVM_ENABLE_ASSERTIONS=OFF \
-DLLVM_INSTALL_UTILS=ON \
-DLLVM_INCLUDE_TESTS=OFF \
-DLLVM_INCLUDE_DOCS=OFF \
-DLLVM_INCLUDE_EXAMPLES=OFF
make -j2
make install
EOF
chmod 755 $out/fake-conda/build.sh
'';
in
import ./build.nix { inherit pkgs; } {
name = "conda-llvm-or1k";
src = fake-src;
}

View File

@ -0,0 +1,69 @@
{ pkgs, conda-llvm-or1k, version, src }:
let
condaBuilderEnv = import ./builder-env.nix { inherit pkgs; };
fake-src = pkgs.runCommand "conda-fake-source-llvmlite-artiq" { }
''
mkdir -p $out/fake-conda;
# work around yet more idiotic conda behavior - build breaks if write permissions aren't set on source files.
cp --no-preserve=mode,ownership -R ${src} workaround-conda
pushd workaround-conda
tar cf $out/src.tar .
popd
rm -rf workaround-conda
cat << EOF > $out/fake-conda/meta.yaml
package:
name: llvmlite-artiq
version: ${version}
source:
url: ../src.tar
# Again, we don't specify build dependencies since the conda garbage mistakenly thinks
# that they are not there if they have been installed from files.
requirements:
run:
- python
- ncurses [linux]
EOF
cat << EOF > $out/fake-conda/build.sh
#!/bin/bash
set -e
export LD_LIBRARY_PATH=/lib
python setup.py install \
--prefix=\$PREFIX \
--single-version-externally-managed \
--record=record.txt \
--no-compile
EOF
chmod 755 $out/fake-conda/build.sh
'';
in
pkgs.stdenv.mkDerivation {
name = "conda-llvmlite-artiq";
src = fake-src;
buildCommand =
''
HOME=`pwd`
mkdir $out
cat << EOF > conda-commands.sh
set -e
conda create --prefix ./conda_tmp ${conda-llvm-or1k}/*/*.tar.bz2
conda init
source .bashrc
conda activate ./conda_tmp
conda build --no-anaconda-upload --no-test --output-folder $out $src/fake-conda
EOF
${condaBuilderEnv}/bin/conda-builder-env conda-commands.sh
mkdir -p $out/nix-support
echo file conda $out/*/*.tar.bz2 >> $out/nix-support/hydra-build-products
'';
}

116
artiq-fast/default.nix Normal file
View File

@ -0,0 +1,116 @@
{ pkgs ? import <nixpkgs> {}}:
with pkgs;
let
pythonDeps = import ./pkgs/python-deps.nix { inherit (pkgs) stdenv fetchFromGitHub python3Packages; };
boards = [
{ target = "kasli"; variant = "tester"; }
{ target = "kc705"; variant = "nist_clock"; }
];
boardPackages = pkgs.lib.lists.foldr (board: start:
let
boardBinaries = import ./artiq-board.nix { inherit pkgs; } {
target = board.target;
variant = board.variant;
};
in
start // {
"artiq-board-${board.target}-${board.variant}" = boardBinaries;
}) {} boards;
mainPackages = rec {
inherit (pythonDeps) sipyco asyncserial pythonparser pyqtgraph-qt5 misoc migen microscope jesd204b migen-axi lit outputcheck;
binutils-or1k = callPackage ./pkgs/binutils.nix { platform = "or1k"; target = "or1k-linux"; };
binutils-arm = callPackage ./pkgs/binutils.nix { platform = "arm"; target = "armv7-unknown-linux-gnueabihf"; };
llvm-or1k = callPackage ./pkgs/llvm-or1k.nix {};
rustc = callPackage ./pkgs/rust/rustc-with-crates.nix
((stdenv.lib.optionalAttrs (stdenv.cc.isGNU && stdenv.hostPlatform.isi686) {
stdenv = overrideCC stdenv gcc6; # with gcc-7: undefined reference to `__divmoddi4'
}) //
{ inherit llvm-or1k; });
cargo = callPackage ./pkgs/rust/cargo.nix { inherit rustc; };
cargo-vendor = callPackage ./pkgs/rust/cargo-vendor.nix {};
llvmlite-artiq = callPackage ./pkgs/llvmlite-artiq.nix { inherit llvm-or1k; };
libartiq-support = callPackage ./pkgs/libartiq-support.nix { inherit rustc; };
artiq = callPackage ./pkgs/artiq.nix { inherit binutils-or1k llvm-or1k llvmlite-artiq libartiq-support lit outputcheck; };
artiq-env = (pkgs.python3.withPackages(ps: [ artiq ])).overrideAttrs (oldAttrs: { name = "${pkgs.python3.name}-artiq-env-${artiq.version}"; });
openocd = callPackage ./pkgs/openocd.nix {};
conda-pythonparser = import ./conda/build.nix { inherit pkgs; } {
name = "conda-pythonparser";
src = import ./conda/fake-source.nix { inherit pkgs; } {
name = "pythonparser";
inherit (pythonDeps.pythonparser) version src;
extraSrcCommands = "patch -p1 < ${./pkgs/python37hack.patch}";
dependencies = ["regex"];
};
};
conda-binutils-or1k = import ./conda/binutils.nix {
inherit pkgs;
inherit (binutils-or1k) version src;
target = "or1k-linux";
};
conda-binutils-arm = import ./conda/binutils.nix {
inherit pkgs;
inherit (binutils-arm) version src;
target = "armv7-unknown-linux-gnueabihf";
};
conda-llvm-or1k = import ./conda/llvm-or1k.nix {
inherit pkgs;
inherit (llvm-or1k) version;
src = llvm-or1k.llvm-src;
};
conda-llvmlite-artiq = import ./conda/llvmlite-artiq.nix {
inherit pkgs conda-llvm-or1k;
inherit (llvmlite-artiq) version src;
};
conda-sipyco = import ./conda/build.nix { inherit pkgs; } {
name = "conda-sipyco";
src = import ./conda/fake-source.nix { inherit pkgs; } {
name = "sipyco";
inherit (pythonDeps.sipyco) version src;
dependencies = ["numpy"];
};
};
conda-quamash = import ./conda/build.nix { inherit pkgs; } {
name = "conda-quamash";
src = import ./conda/fake-source.nix { inherit pkgs; } {
name = "quamash";
inherit (pkgs.python3Packages.quamash) version src;
};
};
conda-bscan-spi-bitstreams = import ./conda/bscan-spi-bitstreams.nix {
inherit pkgs;
inherit (openocd) bscan_spi_bitstreams;
};
conda-artiq = import ./conda/artiq.nix { inherit pkgs; };
conda-asyncserial = import ./conda/build.nix { inherit pkgs; } {
name = "conda-asyncserial";
src = import ./conda/fake-source.nix { inherit pkgs; } {
name = "asyncserial";
inherit (pythonDeps.asyncserial) version src;
dependencies = ["pyserial"];
};
};
conda-windows-binutils-or1k = import ./conda-windows/binutils.nix {
inherit pkgs;
inherit (binutils-or1k) version src;
target = "or1k-linux";
};
conda-windows-binutils-arm = import ./conda-windows/binutils.nix {
inherit pkgs;
inherit (binutils-arm) version src;
target = "armv7-unknown-linux-gnueabihf";
};
conda-windows-llvm-or1k = import ./conda-windows/llvm-or1k.nix {
inherit pkgs;
inherit (llvm-or1k) version;
src = llvm-or1k.llvm-src;
};
conda-windows-llvmlite-artiq = import ./conda-windows/llvmlite-artiq.nix {
inherit pkgs conda-windows-llvm-or1k;
inherit (llvmlite-artiq) version src;
};
};
in
mainPackages // boardPackages

35
artiq-fast/fetchcargo.nix Normal file
View File

@ -0,0 +1,35 @@
{ stdenv, cacert, git, cargo, cargo-vendor }:
{ name, src, sha256 }:
stdenv.mkDerivation {
name = "${name}-vendor";
nativeBuildInputs = [ cacert git cargo cargo-vendor ];
inherit src;
phases = "unpackPhase patchPhase installPhase";
installPhase = ''
if [[ ! -f Cargo.lock ]]; then
echo
echo "ERROR: The Cargo.lock file doesn't exist"
echo
echo "Cargo.lock is needed to make sure that cargoSha256 doesn't change"
echo "when the registry is updated."
echo
exit 1
fi
export CARGO_HOME=$(mktemp -d cargo-home.XXX)
cargo vendor
cp -ar vendor $out
'';
outputHashAlgo = "sha256";
outputHashMode = "recursive";
outputHash = sha256;
impureEnvVars = stdenv.lib.fetchers.proxyImpureEnvVars;
preferLocalBuild = true;
}

View File

@ -0,0 +1 @@
{ fetchgit }: <artiqSrc>

View File

@ -0,0 +1,14 @@
{ stdenv, git, fetchgit }:
let
artiq-timestamp = stdenv.mkDerivation {
name = "artiq-timestamp";
src = import ./artiq-src.nix { inherit fetchgit; };
buildPhase = ''
TIMESTAMP=`${git}/bin/git log -1 --format=%ct`
'';
installPhase = ''
echo -n $TIMESTAMP > $out
'';
};
in
builtins.readFile artiq-timestamp

View File

@ -0,0 +1,22 @@
{ stdenv, git, fetchgit }:
let
artiq-version = stdenv.mkDerivation {
name = "artiq-version";
src = import ./artiq-src.nix { inherit fetchgit; };
# keep in sync with ../../artiq-fast.nix
buildPhase = ''
REV=`${git}/bin/git rev-parse HEAD`
MAJOR_VERSION=`cat MAJOR_VERSION`
if [ -e BETA ]; then
SUFFIX=".beta"
else
SUFFIX=""
fi
COMMIT_COUNT=`${git}/bin/git rev-list --count HEAD`
'';
installPhase = ''
echo -n $MAJOR_VERSION.$COMMIT_COUNT.`cut -c1-8 <<< $REV`$SUFFIX > $out
'';
};
in
builtins.readFile artiq-version

29
artiq-fast/pkgs/artiq.nix Normal file
View File

@ -0,0 +1,29 @@
{ stdenv, callPackage, fetchgit, git, python3Packages, qt5Full, binutils-or1k, llvm-or1k, llvmlite-artiq, libartiq-support, lit, outputcheck }:
let
pythonDeps = callPackage ./python-deps.nix {};
in
builtins.trace "artiq" (python3Packages.buildPythonPackage rec {
name = "artiq-${version}";
version = import ./artiq-version.nix { inherit stdenv fetchgit git; };
src = import ./artiq-src.nix { inherit fetchgit; };
preBuild = "export VERSIONEER_OVERRIDE=${version}";
propagatedBuildInputs = [ binutils-or1k llvm-or1k llvmlite-artiq qt5Full ]
++ (with pythonDeps; [ sipyco pyqtgraph-qt5 pythonparser ])
++ (with python3Packages; [ pygit2 numpy dateutil quamash scipy prettytable pyserial python-Levenshtein h5py pyqt5 ]);
checkInputs = [ binutils-or1k outputcheck ];
checkPhase =
''
python -m unittest discover -v artiq.test
TESTDIR=`mktemp -d`
cp --no-preserve=mode,ownership -R ${src}/artiq/test/lit $TESTDIR
LIBARTIQ_SUPPORT=${libartiq-support}/libartiq_support.so ${lit}/bin/lit -v $TESTDIR/lit
'';
meta = with stdenv.lib; {
description = "A leading-edge control system for quantum information experiments";
homepage = https://m-labs/artiq;
license = licenses.lgpl3;
maintainers = [ maintainers.sb0 ];
};
})

View File

@ -0,0 +1,35 @@
{ stdenv, buildPackages
, fetchurl, zlib
, platform, target
}:
stdenv.mkDerivation rec {
basename = "binutils";
inherit platform;
version = "2.30";
name = "${basename}-${platform}-${version}";
src = fetchurl {
url = "https://ftp.gnu.org/gnu/binutils/binutils-${version}.tar.bz2";
sha256 = "028cklfqaab24glva1ks2aqa1zxa6w6xmc8q34zs1sb7h22dxspg";
};
configureFlags =
[ "--enable-shared" "--enable-deterministic-archives" "--target=${target}"];
outputs = [ "out" "info" "man" ];
depsBuildBuild = [ buildPackages.stdenv.cc ];
buildInputs = [ zlib ];
enableParallelBuilding = true;
meta = {
description = "Tools for manipulating binaries (linker, assembler, etc.)";
longDescription = ''
The GNU Binutils are a collection of binary tools. The main
ones are `ld' (the GNU linker) and `as' (the GNU assembler).
They also include the BFD (Binary File Descriptor) library,
`gprof', `nm', `strip', etc.
'';
homepage = http://www.gnu.org/software/binutils/;
license = stdenv.lib.licenses.gpl3Plus;
/* Give binutils a lower priority than gcc-wrapper to prevent a
collision due to the ld/as wrappers/symlinks in the latter. */
priority = "10";
};
}

View File

@ -0,0 +1,15 @@
{ stdenv, fetchgit, git, rustc }:
stdenv.mkDerivation rec {
name = "libartiq-support-${version}";
version = import ./artiq-version.nix { inherit stdenv fetchgit git; };
src = import ./artiq-src.nix { inherit fetchgit; };
buildInputs = [ rustc ];
phases = [ "buildPhase" ];
buildPhase =
''
mkdir $out
rustc ${src}/artiq/test/libartiq_support/lib.rs --out-dir $out -Cpanic=unwind -g
'';
}

View File

@ -0,0 +1,66 @@
{ stdenv
, fetchFromGitHub, runCommand
, perl, groff, cmake, libxml2, python, libffi, valgrind
}:
let
llvm-src = fetchFromGitHub {
rev = "527aa86b578da5dfb9cf4510b71f0f46a11249f7";
owner = "m-labs";
repo = "llvm-or1k";
sha256 = "0lmcg9xj66pf4mb6racipw67vm8kwm84dl861hyqnywd61kvhrwa";
};
clang-src = fetchFromGitHub {
rev = "9e996136d52ed506ed8f57ef8b13b0f0f735e6a3";
owner = "m-labs";
repo = "clang-or1k";
sha256 = "0w5f450i76y162aswi2c7jip8x3arzljaxhbqp8qfdffm0rdbjp4";
};
llvm-clang-src = runCommand "llvm-clang-src" {}
''
mkdir -p $out
mkdir -p $out/tools/clang
cp -r ${llvm-src}/* $out/
cp -r ${clang-src}/* $out/tools/clang
'';
in
stdenv.mkDerivation rec {
name = "llvm-or1k";
passthru.llvm-src = llvm-src;
src = llvm-clang-src;
version = "6.0.0";
buildInputs = [ perl groff cmake libxml2 python libffi ] ++ stdenv.lib.optional stdenv.isLinux valgrind;
preBuild = ''
NIX_BUILD_CORES=4
makeFlagsArray=(-j''$NIX_BUILD_CORES)
mkdir -p $out/
'';
cmakeFlags = with stdenv; [
"-DCMAKE_BUILD_TYPE=Release"
"-DLLVM_BUILD_LLVM_DYLIB=ON"
"-DLLVM_LINK_LLVM_DYLIB=ON"
"-DLLVM_TARGETS_TO_BUILD=X86;ARM"
"-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=OR1K"
"-DLLVM_ENABLE_ASSERTIONS=OFF"
"-DLLVM_INSTALL_UTILS=ON"
"-DLLVM_INCLUDE_TESTS=OFF"
"-DLLVM_INCLUDE_DOCS=OFF"
"-DLLVM_INCLUDE_EXAMPLES=OFF"
"-DCLANG_ENABLE_ARCMT=OFF"
"-DCLANG_ENABLE_STATIC_ANALYZER=OFF"
"-DCLANG_INCLUDE_TESTS=OFF"
"-DCLANG_INCLUDE_DOCS=OFF"
];
enableParallelBuilding = true;
meta = {
description = "Collection of modular and reusable compiler and toolchain technologies";
homepage = http://llvm.org/;
license = stdenv.lib.licenses.bsd3;
maintainers = with stdenv.lib.maintainers; [ sb0 ];
platforms = stdenv.lib.platforms.all;
};
}

View File

@ -0,0 +1,23 @@
{ stdenv, fetchFromGitHub, llvm-or1k, makeWrapper, python3, ncurses, zlib, python3Packages }:
python3Packages.buildPythonPackage rec {
name = "llvmlite-artiq";
version = "0.23.0.dev";
src = fetchFromGitHub {
rev = "158f9d3a898dbf055ca513d69505df288c681fea";
owner = "m-labs";
repo = "llvmlite";
sha256 = "1anniwya5jhhr2sxfdnwrsjy17yrk3x61i9hsm1rljsb8zvh68d5";
};
buildInputs = [ makeWrapper python3 ncurses zlib llvm-or1k python3Packages.setuptools ];
preBuild = "export LLVM_CONFIG=${llvm-or1k}/bin/llvm-config";
meta = with stdenv.lib; {
description = "A lightweight LLVM python binding for writing JIT compilers";
homepage = "http://llvmlite.pydata.org/";
maintainers = with maintainers; [ sb0 ];
license = licenses.bsd2;
platforms = platforms.unix;
};
}

View File

@ -0,0 +1,74 @@
{ stdenv, fetchFromGitHub, autoreconfHook, libftdi, libusb1, pkgconfig, hidapi }:
stdenv.mkDerivation rec {
name = "openocd-mlabs-${version}";
version = "0.10.0";
src = fetchFromGitHub {
owner = "m-labs";
repo = "openocd";
fetchSubmodules = true;
rev = "c383a57adcff332b2c5cf8d55a84626285b42c2c";
sha256 = "0xlj9cs72acx3zqagvr7f1c0v6lnqhl8fgrlhgmhmvk5n9knk492";
};
bscan_spi_bitstreams = fetchFromGitHub {
owner = "quartiq";
repo = "bscan_spi_bitstreams";
rev = "01d8f819f15baf9a8cc5d96945a51e4d267ff564";
sha256 = "1zqv47kzgvbn4c8cr019a6wcja7gn5h1z4kvw5bhpc72fyhagal9";
};
nativeBuildInputs = [ pkgconfig ];
buildInputs = [ autoreconfHook libftdi libusb1 hidapi ];
configureFlags = [
"--enable-jtag_vpi"
"--enable-usb_blaster_libftdi"
"--enable-amtjtagaccel"
"--enable-gw16012"
"--enable-presto_libftdi"
"--enable-openjtag_ftdi"
"--enable-oocd_trace"
"--enable-buspirate"
"--enable-sysfsgpio"
"--enable-remote-bitbang"
"--disable-werror"
];
NIX_CFLAGS_COMPILE = [
"-Wno-implicit-fallthrough"
"-Wno-format-truncation"
"-Wno-format-overflow"
"-Wno-error=tautological-compare"
];
postInstall = ''
mkdir -p "$out/etc/udev/rules.d"
rules="$out/share/openocd/contrib/60-openocd.rules"
if [ ! -f "$rules" ]; then
echo "$rules is missing, must update the Nix file."
exit 1
fi
ln -s "$rules" "$out/etc/udev/rules.d/"
mkdir -p "$out/share/bscan-spi-bitstreams"
cp ${bscan_spi_bitstreams}/*.bit "$out/share/bscan-spi-bitstreams"
'';
meta = with stdenv.lib; {
description = "Free and Open On-Chip Debugging, In-System Programming and Boundary-Scan Testing";
longDescription = ''
OpenOCD provides on-chip programming and debugging support with a layered
architecture of JTAG interface and TAP support, debug target support
(e.g. ARM, MIPS), and flash chip drivers (e.g. CFI, NAND, etc.). Several
network interfaces are available for interactiving with OpenOCD: HTTP,
telnet, TCL, and GDB. The GDB server enables OpenOCD to function as a
"remote target" for source-level debugging of embedded systems using the
GNU GDB program.
'';
homepage = http://openocd.sourceforge.net/;
license = licenses.gpl2Plus;
maintainers = with maintainers; [ sb0 ];
platforms = platforms.linux;
};
}

View File

@ -0,0 +1,263 @@
{ stdenv, fetchFromGitHub, python3Packages }:
rec {
# User dependencies
sipyco = python3Packages.buildPythonPackage rec {
name = "sipyco";
version = "1.1";
src = fetchFromGitHub {
owner = "m-labs";
repo = "sipyco";
rev = "v${version}";
sha256 = "09vyrzfhnbp65ybd7w2g96gvvnhzafpn72syls2kbg2paqjjf9gs";
};
propagatedBuildInputs = with python3Packages; [ numpy ];
};
asyncserial = python3Packages.buildPythonPackage rec {
name = "asyncserial";
version = "0.1";
src = fetchFromGitHub {
owner = "m-labs";
repo = "asyncserial";
rev = "d95bc1d6c791b0e9785935d2f62f628eb5cdf98d";
sha256 = "0yzkka9jk3612v8gx748x6ziwykq5lr7zmr9wzkcls0v2yilqx9k";
};
propagatedBuildInputs = with python3Packages; [ pyserial ];
};
pythonparser = python3Packages.buildPythonPackage rec {
name = "pythonparser";
version = "1.3";
src = fetchFromGitHub {
owner = "m-labs";
repo = "pythonparser";
rev = "5b391fe86f43bb9f4f96c5bc0532e2a112db2936";
sha256 = "1gw1fk4y2l6bwq0fg2a9dfc1rvq8cv492dyil96amjdhsxvnx35b";
};
patches = [ ./python37hack.patch ];
propagatedBuildInputs = with python3Packages; [ regex ];
};
pyqtgraph-qt5 = python3Packages.buildPythonPackage rec {
name = "pyqtgraph_qt5-${version}";
version = "0.10.0";
doCheck = false;
src = fetchFromGitHub {
owner = "pyqtgraph";
repo = "pyqtgraph";
rev = "1426e334e1d20542400d77c72c132b04c6d17ddb";
sha256 = "1079haxyr316jf0wpirxdj0ry6j8mr16cqr0dyyrd5cnxwl7zssh";
};
propagatedBuildInputs = with python3Packages; [ scipy numpy pyqt5 pyopengl ];
};
# Development/firmware dependencies
misoc = python3Packages.buildPythonPackage rec {
name = "misoc";
src = fetchFromGitHub {
owner = "m-labs";
repo = "misoc";
rev = "7e5fe8d38835175202dad2c51d37b20b76fd9e16";
sha256 = "0i8bppz7x2s45lx9n49c0r87pqps09z35yzc17amvx21qsplahxn";
fetchSubmodules = true;
};
# TODO: fix misoc bitrot and re-enable tests
doCheck = false;
propagatedBuildInputs = with python3Packages; [ pyserial jinja2 numpy asyncserial migen ];
meta = with stdenv.lib; {
description = "A high performance and small footprint system-on-chip based on Migen";
homepage = "https://m-labs.hk/migen";
license = licenses.bsd2;
platforms = platforms.unix;
};
};
migen = python3Packages.buildPythonPackage rec {
name = "migen";
src = fetchFromGitHub {
owner = "m-labs";
repo = "migen";
rev = "b1b2b298b85a795239daad84c75be073ddc4f8bd";
sha256 = "1qy2ydk8xqqv92i992j1g71fbi185zd6s3kigzsf3169874dyh81";
};
propagatedBuildInputs = with python3Packages; [ colorama ];
meta = with stdenv.lib; {
description = "A Python toolbox for building complex digital hardware";
homepage = "https://m-labs.hk/migen";
license = licenses.bsd2;
platforms = platforms.unix;
};
};
microscope = python3Packages.buildPythonPackage rec {
name = "microscope";
src = fetchFromGitHub {
owner = "m-labs";
repo = "microscope";
rev = "bcbc5346c71ad8f7a1a0b7771a9d126b18fdf558";
sha256 = "1hslm2nn2z1bl84ya4fsab3pvcdmbziwn7zkai0cm3bv525fjxxd";
};
propagatedBuildInputs = with python3Packages; [ pyserial prettytable msgpack migen ];
meta = with stdenv.lib; {
description = "Finding the bacteria in rotting FPGA designs";
homepage = "https://m-labs.hk/migen";
license = licenses.bsd2;
platforms = platforms.unix;
};
};
jesd204b = python3Packages.buildPythonPackage rec {
name = "jesd204b";
src = fetchFromGitHub {
owner = "m-labs";
repo = "jesd204b";
rev = "ac877ac5975411a438415f824e182338ed773529";
sha256 = "1lkb7cyj87bq4y0hp6379jq4q4lm2ijldccpyhawiizcfkawxa10";
};
propagatedBuildInputs = with python3Packages; [ migen misoc ];
meta = with stdenv.lib; {
description = "JESD204B core for Migen/MiSoC";
homepage = "https://m-labs.hk/migen";
license = licenses.bsd2;
platforms = platforms.unix;
};
};
fastnumbers = python3Packages.buildPythonPackage rec {
pname = "fastnumbers";
version = "2.2.1";
src = python3Packages.fetchPypi {
inherit pname version;
sha256 = "0j15i54p7nri6hkzn1wal9pxri4pgql01wgjccig6ar0v5jjbvsy";
};
meta = with stdenv.lib; {
description = "Super-fast and clean conversions to numbers";
homepage = "https://github.com/SethMMorton/fastnumbers";
license = licenses.mit;
platforms = platforms.unix;
};
};
ramda = python3Packages.buildPythonPackage {
name = "ramda";
src = fetchFromGitHub {
owner = "peteut";
repo = "ramda.py";
rev = "bd58f8e69d0e9a713d9c1f286a1ac5e5603956b1";
sha256 = "0qzd5yp9lbaham8p1wiymdjapzbqsli7lvngv24c3z4ybd9jlq9g";
};
nativeBuildInputs = [ python3Packages.pbr ];
propagatedBuildInputs = [ python3Packages.future fastnumbers ];
checkInputs = [ python3Packages.pytest python3Packages.pytest-flake8 ];
checkPhase = "pytest";
preBuild = ''
export PBR_VERSION=0.0.1
'';
meta = with stdenv.lib; {
description = "Ramda, ported to Python";
homepage = "https://github.com/peteut/ramda.py";
license = licenses.mit;
platforms = platforms.unix;
};
};
migen-axi = python3Packages.buildPythonPackage {
name = "migen-axi";
src = fetchFromGitHub {
owner = "peteut";
repo = "migen-axi";
rev = "c4002f7db62cb9c4599336a9413006ee1d138fbd";
sha256 = "0p2ndznch7z4sbp4m8hq49rkg7p4vcrlbbfk6l8644wyl1kk0fvg";
};
nativeBuildInputs = [ python3Packages.pbr ];
propagatedBuildInputs = [ python3Packages.click python3Packages.numpy python3Packages.toolz python3Packages.jinja2 ramda migen misoc ];
postPatch = ''
substituteInPlace requirements.txt \
--replace "jinja2==2.10.3" "jinja2"
substituteInPlace requirements.txt \
--replace "future==0.18.2" "future"
substituteInPlace requirements.txt \
--replace "ramda==0.5.5" "ramda"
substituteInPlace requirements.txt \
--replace "colorama==0.4.3" "colorama"
'';
checkInputs = [ python3Packages.pytest python3Packages.pytest-flake8 ];
checkPhase = "pytest";
preBuild = ''
export PBR_VERSION=0.0.1
'';
meta = with stdenv.lib; {
description = "AXI support for Migen/MiSoC";
homepage = "https://github.com/peteut/migen-axi";
license = licenses.mit;
platforms = platforms.unix;
};
};
# not using the nixpkgs version because it is Python 2 and an "application"
lit = python3Packages.buildPythonPackage rec {
pname = "lit";
version = "0.7.1";
src = python3Packages.fetchPypi {
inherit pname version;
sha256 = "ecef2833aef7f411cb923dac109c7c9dcc7dbe7cafce0650c1e8d19c243d955f";
};
# Non-standard test suite. Needs custom checkPhase.
doCheck = false;
meta = with stdenv.lib; {
description = "Portable tool for executing LLVM and Clang style test suites";
homepage = http://llvm.org/docs/CommandGuide/lit.html;
license = licenses.ncsa;
};
};
outputcheck = python3Packages.buildPythonApplication rec {
pname = "outputcheck";
version = "0.4.2";
src = fetchFromGitHub {
owner = "stp";
repo = "OutputCheck";
rev = "e0f533d3c5af2949349856c711bf4bca50022b48";
sha256 = "1y27vz6jq6sywas07kz3v01sqjd0sga9yv9w2cksqac3v7wmf2a0";
};
prePatch = "echo ${version} > RELEASE-VERSION";
meta = with stdenv.lib; {
description = "A tool for checking tool output inspired by LLVM's FileCheck";
homepage = "https://github.com/stp/OutputCheck";
license = licenses.bsd3;
};
};
}

View File

@ -0,0 +1,33 @@
diff --git a/pythonparser/lexer.py b/pythonparser/lexer.py
index a62eaf1..2c48d36 100644
--- a/pythonparser/lexer.py
+++ b/pythonparser/lexer.py
@@ -79,6 +79,7 @@ class Lexer:
(3, 4): _reserved_3_1,
(3, 5): _reserved_3_5,
(3, 6): _reserved_3_5,
+ (3, 7): _reserved_3_5,
}
"""
A map from a tuple (*major*, *minor*) corresponding to Python version to
@@ -102,6 +103,7 @@ class Lexer:
(3, 4): _string_prefixes_3_3,
(3, 5): _string_prefixes_3_3,
(3, 6): _string_prefixes_3_6,
+ (3, 7): _string_prefixes_3_6,
}
"""
A map from a tuple (*major*, *minor*) corresponding to Python version to
diff --git a/pythonparser/parser.py b/pythonparser/parser.py
index 10c741d..f748695 100644
--- a/pythonparser/parser.py
+++ b/pythonparser/parser.py
@@ -419,7 +419,7 @@ class Parser(object):
self.expr_stmt_1 = self.expr_stmt_1__26
self.yield_expr = self.yield_expr__26
return
- elif version in ((3, 0), (3, 1), (3, 2), (3, 3), (3, 4), (3, 5), (3, 6)):
+ elif version in ((3, 0), (3, 1), (3, 2), (3, 3), (3, 4), (3, 5), (3, 6), (3, 7)):
if version == (3, 0):
self.with_stmt = self.with_stmt__26 # lol
else:

View File

@ -0,0 +1,117 @@
{ stdenv, makeWrapper, bash, buildRustPackage, curl, darwin
, version
, src
, platform
, versionType
}:
let
inherit (stdenv.lib) optionalString;
inherit (darwin.apple_sdk.frameworks) Security;
bootstrapping = versionType == "bootstrap";
installComponents
= "rustc,rust-std-${platform}"
+ (optionalString bootstrapping ",cargo")
;
in
rec {
inherit buildRustPackage;
rustc = stdenv.mkDerivation rec {
name = "rustc-${versionType}-${version}";
inherit version;
inherit src;
meta = with stdenv.lib; {
homepage = http://www.rust-lang.org/;
description = "A safe, concurrent, practical language";
maintainers = with maintainers; [ sb0 ];
license = [ licenses.mit licenses.asl20 ];
};
buildInputs = [ bash ] ++ stdenv.lib.optional stdenv.isDarwin Security;
postPatch = ''
patchShebangs .
'';
installPhase = ''
./install.sh --prefix=$out \
--components=${installComponents}
${optionalString (stdenv.isLinux && bootstrapping) ''
patchelf \
--set-interpreter $(cat $NIX_CC/nix-support/dynamic-linker) \
"$out/bin/rustc"
patchelf \
--set-interpreter $(cat $NIX_CC/nix-support/dynamic-linker) \
"$out/bin/rustdoc"
patchelf \
--set-interpreter $(cat $NIX_CC/nix-support/dynamic-linker) \
"$out/bin/cargo"
''}
${optionalString (stdenv.isDarwin && bootstrapping) ''
install_name_tool -change /usr/lib/libresolv.9.dylib '${darwin.libresolv}/lib/libresolv.9.dylib' "$out/bin/rustc"
install_name_tool -change /usr/lib/libresolv.9.dylib '${darwin.libresolv}/lib/libresolv.9.dylib' "$out/bin/rustdoc"
install_name_tool -change /usr/lib/libiconv.2.dylib '${darwin.libiconv}/lib/libiconv.2.dylib' "$out/bin/cargo"
install_name_tool -change /usr/lib/libresolv.9.dylib '${darwin.libresolv}/lib/libresolv.9.dylib' "$out/bin/cargo"
install_name_tool -change /usr/lib/libcurl.4.dylib '${stdenv.lib.getLib curl}/lib/libcurl.4.dylib' "$out/bin/cargo"
for f in $out/lib/lib*.dylib; do
install_name_tool -change /usr/lib/libresolv.9.dylib '${darwin.libresolv}/lib/libresolv.9.dylib' "$f"
done
''}
# Do NOT, I repeat, DO NOT use `wrapProgram` on $out/bin/rustc
# (or similar) here. It causes strange effects where rustc loads
# the wrong libraries in a bootstrap-build causing failures that
# are very hard to track down. For details, see
# https://github.com/rust-lang/rust/issues/34722#issuecomment-232164943
'';
};
cargo = stdenv.mkDerivation rec {
name = "cargo-${versionType}-${version}";
inherit version;
inherit src;
meta = with stdenv.lib; {
homepage = http://www.rust-lang.org/;
description = "A safe, concurrent, practical language";
maintainers = with maintainers; [ sb0 ];
license = [ licenses.mit licenses.asl20 ];
};
buildInputs = [ makeWrapper bash ] ++ stdenv.lib.optional stdenv.isDarwin Security;
postPatch = ''
patchShebangs .
'';
installPhase = ''
patchShebangs ./install.sh
./install.sh --prefix=$out \
--components=cargo
${optionalString (stdenv.isLinux && bootstrapping) ''
patchelf \
--set-interpreter $(cat $NIX_CC/nix-support/dynamic-linker) \
"$out/bin/cargo"
''}
${optionalString (stdenv.isDarwin && bootstrapping) ''
install_name_tool -change /usr/lib/libiconv.2.dylib '${darwin.libiconv}/lib/libiconv.2.dylib' "$out/bin/cargo"
install_name_tool -change /usr/lib/libresolv.9.dylib '${darwin.libresolv}/lib/libresolv.9.dylib' "$out/bin/cargo"
install_name_tool -change /usr/lib/libcurl.4.dylib '${stdenv.lib.getLib curl}/lib/libcurl.4.dylib' "$out/bin/cargo"
''}
wrapProgram "$out/bin/cargo" \
--suffix PATH : "${rustc}/bin"
'';
};
}

View File

@ -0,0 +1,42 @@
{ stdenv, fetchurl, callPackage }:
let
# Note: the version MUST be one version prior to the version we're
# building
version = "1.28.0";
# fetch hashes by running `print-hashes.sh 1.24.1`
hashes = {
i686-unknown-linux-gnu = "de7cdb4e665e897ea9b10bf6fd545f900683296456d6a11d8510397bb330455f";
x86_64-unknown-linux-gnu = "2a1390340db1d24a9498036884e6b2748e9b4b057fc5219694e298bdaa37b810";
armv7-unknown-linux-gnueabihf = "346558d14050853b87049e5e1fbfae0bf0360a2f7c57433c6985b1a879c349a2";
aarch64-unknown-linux-gnu = "9b6fbcee73070332c811c0ddff399fa31965bec62ef258656c0c90354f6231c1";
i686-apple-darwin = "752e2c9182e057c4a54152d1e0b3949482c225d02bb69d9d9a4127dc2a65fb68";
x86_64-apple-darwin = "5d7a70ed4701fe9410041c1eea025c95cad97e5b3d8acc46426f9ac4f9f02393";
};
platform =
if stdenv.hostPlatform.system == "i686-linux"
then "i686-unknown-linux-gnu"
else if stdenv.hostPlatform.system == "x86_64-linux"
then "x86_64-unknown-linux-gnu"
else if stdenv.hostPlatform.system == "armv7l-linux"
then "armv7-unknown-linux-gnueabihf"
else if stdenv.hostPlatform.system == "aarch64-linux"
then "aarch64-unknown-linux-gnu"
else if stdenv.hostPlatform.system == "i686-darwin"
then "i686-apple-darwin"
else if stdenv.hostPlatform.system == "x86_64-darwin"
then "x86_64-apple-darwin"
else throw "missing bootstrap url for platform ${stdenv.hostPlatform.system}";
src = fetchurl {
url = "https://static.rust-lang.org/dist/rust-${version}-${platform}.tar.gz";
sha256 = hashes."${platform}";
};
in callPackage ./binaryBuild.nix
{ inherit version src platform;
buildRustPackage = null;
versionType = "bootstrap";
}

View File

@ -0,0 +1,693 @@
# Generated by carnix 0.10.0: carnix generate-nix --src .
{ lib, buildPlatform, buildRustCrate, buildRustCrateHelpers, cratesIO, fetchgit }:
with buildRustCrateHelpers;
let inherit (lib.lists) fold;
inherit (lib.attrsets) recursiveUpdate;
in
rec {
crates = cratesIO // rec {
# cargo-vendor-0.1.23
crates.cargo_vendor."0.1.23" = deps: { features?(features_.cargo_vendor."0.1.23" deps {}) }: buildRustCrate {
crateName = "cargo-vendor";
version = "0.1.23";
description = "A Cargo subcommand to vendor all crates.io dependencies onto the local\nfilesystem.\n";
authors = [ "Alex Crichton <alex@alexcrichton.com>" ];
edition = "2018";
src = exclude [ ".git" "target" ] ./.;
dependencies = mapFeatures features ([
(cratesIO.crates."cargo"."${deps."cargo_vendor"."0.1.23"."cargo"}" deps)
(cratesIO.crates."docopt"."${deps."cargo_vendor"."0.1.23"."docopt"}" deps)
(cratesIO.crates."env_logger"."${deps."cargo_vendor"."0.1.23"."env_logger"}" deps)
(cratesIO.crates."failure"."${deps."cargo_vendor"."0.1.23"."failure"}" deps)
(cratesIO.crates."serde"."${deps."cargo_vendor"."0.1.23"."serde"}" deps)
(cratesIO.crates."serde_json"."${deps."cargo_vendor"."0.1.23"."serde_json"}" deps)
(cratesIO.crates."toml"."${deps."cargo_vendor"."0.1.23"."toml"}" deps)
]
++ (if features.cargo_vendor."0.1.23".openssl or false then [ (cratesIO.crates.openssl."${deps."cargo_vendor"."0.1.23".openssl}" deps) ] else []));
features = mkFeatures (features."cargo_vendor"."0.1.23" or {});
};
features_.cargo_vendor."0.1.23" = deps: f: updateFeatures f (rec {
cargo."${deps.cargo_vendor."0.1.23".cargo}".default = true;
cargo_vendor."0.1.23".default = (f.cargo_vendor."0.1.23".default or true);
docopt."${deps.cargo_vendor."0.1.23".docopt}".default = true;
env_logger."${deps.cargo_vendor."0.1.23".env_logger}".default = true;
failure."${deps.cargo_vendor."0.1.23".failure}".default = true;
openssl = fold recursiveUpdate {} [
{ "${deps.cargo_vendor."0.1.23".openssl}"."vendored" =
(f.openssl."${deps.cargo_vendor."0.1.23".openssl}"."vendored" or false) ||
(cargo_vendor."0.1.23"."vendored-openssl" or false) ||
(f."cargo_vendor"."0.1.23"."vendored-openssl" or false); }
{ "${deps.cargo_vendor."0.1.23".openssl}".default = true; }
];
serde = fold recursiveUpdate {} [
{ "${deps.cargo_vendor."0.1.23".serde}"."derive" = true; }
{ "${deps.cargo_vendor."0.1.23".serde}".default = true; }
];
serde_json."${deps.cargo_vendor."0.1.23".serde_json}".default = true;
toml."${deps.cargo_vendor."0.1.23".toml}".default = true;
}) [
(cratesIO.features_.cargo."${deps."cargo_vendor"."0.1.23"."cargo"}" deps)
(cratesIO.features_.docopt."${deps."cargo_vendor"."0.1.23"."docopt"}" deps)
(cratesIO.features_.env_logger."${deps."cargo_vendor"."0.1.23"."env_logger"}" deps)
(cratesIO.features_.failure."${deps."cargo_vendor"."0.1.23"."failure"}" deps)
(cratesIO.features_.openssl."${deps."cargo_vendor"."0.1.23"."openssl"}" deps)
(cratesIO.features_.serde."${deps."cargo_vendor"."0.1.23"."serde"}" deps)
(cratesIO.features_.serde_json."${deps."cargo_vendor"."0.1.23"."serde_json"}" deps)
(cratesIO.features_.toml."${deps."cargo_vendor"."0.1.23"."toml"}" deps)
];
# end
};
cargo_vendor = crates.crates.cargo_vendor."0.1.23" deps;
__all = [ (cargo_vendor {}) ];
deps.adler32."1.0.3" = {};
deps.aho_corasick."0.7.3" = {
memchr = "2.2.0";
};
deps.ansi_term."0.11.0" = {
winapi = "0.3.7";
};
deps.atty."0.2.11" = {
termion = "1.5.1";
libc = "0.2.51";
winapi = "0.3.7";
};
deps.autocfg."0.1.2" = {};
deps.backtrace."0.3.15" = {
cfg_if = "0.1.7";
rustc_demangle = "0.1.14";
autocfg = "0.1.2";
backtrace_sys = "0.1.28";
libc = "0.2.51";
winapi = "0.3.7";
};
deps.backtrace_sys."0.1.28" = {
libc = "0.2.51";
cc = "1.0.35";
};
deps.bitflags."1.0.4" = {};
deps.bstr."0.1.2" = {
memchr = "2.2.0";
};
deps.build_const."0.2.1" = {};
deps.byteorder."1.3.1" = {};
deps.bytes."0.4.12" = {
byteorder = "1.3.1";
iovec = "0.1.2";
};
deps.bytesize."1.0.0" = {};
deps.cargo."0.35.0" = {
atty = "0.2.11";
byteorder = "1.3.1";
bytesize = "1.0.0";
clap = "2.33.0";
crates_io = "0.23.0";
crossbeam_utils = "0.6.5";
crypto_hash = "0.3.3";
curl = "0.4.21";
curl_sys = "0.4.18";
env_logger = "0.6.1";
failure = "0.1.5";
filetime = "0.2.4";
flate2 = "1.0.7";
fs2 = "0.4.3";
git2 = "0.8.0";
git2_curl = "0.9.0";
glob = "0.2.11";
hex = "0.3.2";
home = "0.3.4";
ignore = "0.4.7";
im_rc = "12.3.4";
jobserver = "0.1.13";
lazy_static = "1.3.0";
lazycell = "1.2.1";
libc = "0.2.51";
libgit2_sys = "0.7.11";
log = "0.4.6";
num_cpus = "1.10.0";
opener = "0.3.2";
rustc_workspace_hack = "1.0.0";
rustfix = "0.4.5";
same_file = "1.0.4";
semver = "0.9.0";
serde = "1.0.90";
serde_ignored = "0.0.4";
serde_json = "1.0.39";
shell_escape = "0.1.4";
tar = "0.4.22";
tempfile = "3.0.7";
termcolor = "1.0.4";
toml = "0.4.10";
unicode_width = "0.1.5";
url = "1.7.2";
url_serde = "0.2.0";
core_foundation = "0.6.4";
fwdansi = "1.0.1";
miow = "0.3.3";
winapi = "0.3.7";
};
deps.cargo_vendor."0.1.23" = {
cargo = "0.35.0";
docopt = "1.1.0";
env_logger = "0.6.1";
failure = "0.1.5";
openssl = "0.10.20";
serde = "1.0.90";
serde_json = "1.0.39";
toml = "0.5.0";
};
deps.cc."1.0.35" = {};
deps.cfg_if."0.1.7" = {};
deps.clap."2.33.0" = {
atty = "0.2.11";
bitflags = "1.0.4";
strsim = "0.8.0";
textwrap = "0.11.0";
unicode_width = "0.1.5";
vec_map = "0.8.1";
ansi_term = "0.11.0";
};
deps.cloudabi."0.0.3" = {
bitflags = "1.0.4";
};
deps.commoncrypto."0.2.0" = {
commoncrypto_sys = "0.2.0";
};
deps.commoncrypto_sys."0.2.0" = {
libc = "0.2.51";
};
deps.core_foundation."0.6.4" = {
core_foundation_sys = "0.6.2";
libc = "0.2.51";
};
deps.core_foundation_sys."0.6.2" = {};
deps.crates_io."0.23.0" = {
curl = "0.4.21";
failure = "0.1.5";
http = "0.1.17";
serde = "1.0.90";
serde_derive = "1.0.90";
serde_json = "1.0.39";
url = "1.7.2";
};
deps.crc."1.8.1" = {
build_const = "0.2.1";
};
deps.crc32fast."1.2.0" = {
cfg_if = "0.1.7";
};
deps.crossbeam_channel."0.3.8" = {
crossbeam_utils = "0.6.5";
smallvec = "0.6.9";
};
deps.crossbeam_utils."0.6.5" = {
cfg_if = "0.1.7";
lazy_static = "1.3.0";
};
deps.crypto_hash."0.3.3" = {
hex = "0.3.2";
commoncrypto = "0.2.0";
openssl = "0.10.20";
winapi = "0.3.7";
};
deps.curl."0.4.21" = {
curl_sys = "0.4.18";
libc = "0.2.51";
socket2 = "0.3.8";
openssl_probe = "0.1.2";
openssl_sys = "0.9.43";
kernel32_sys = "0.2.2";
schannel = "0.1.15";
winapi = "0.2.8";
};
deps.curl_sys."0.4.18" = {
libc = "0.2.51";
libnghttp2_sys = "0.1.1";
libz_sys = "1.0.25";
cc = "1.0.35";
pkg_config = "0.3.14";
openssl_sys = "0.9.43";
winapi = "0.3.7";
};
deps.docopt."1.1.0" = {
lazy_static = "1.3.0";
regex = "1.1.6";
serde = "1.0.90";
strsim = "0.9.1";
};
deps.either."1.5.2" = {};
deps.env_logger."0.6.1" = {
atty = "0.2.11";
humantime = "1.2.0";
log = "0.4.6";
regex = "1.1.6";
termcolor = "1.0.4";
};
deps.failure."0.1.5" = {
backtrace = "0.3.15";
failure_derive = "0.1.5";
};
deps.failure_derive."0.1.5" = {
proc_macro2 = "0.4.27";
quote = "0.6.12";
syn = "0.15.32";
synstructure = "0.10.1";
};
deps.filetime."0.2.4" = {
cfg_if = "0.1.7";
redox_syscall = "0.1.54";
libc = "0.2.51";
};
deps.flate2."1.0.7" = {
crc32fast = "1.2.0";
libc = "0.2.51";
libz_sys = "1.0.25";
miniz_sys = "0.1.11";
miniz_oxide_c_api = "0.2.1";
};
deps.fnv."1.0.6" = {};
deps.foreign_types."0.3.2" = {
foreign_types_shared = "0.1.1";
};
deps.foreign_types_shared."0.1.1" = {};
deps.fs2."0.4.3" = {
libc = "0.2.51";
winapi = "0.3.7";
};
deps.fuchsia_cprng."0.1.1" = {};
deps.fwdansi."1.0.1" = {
memchr = "2.2.0";
termcolor = "1.0.4";
};
deps.git2."0.8.0" = {
bitflags = "1.0.4";
libc = "0.2.51";
libgit2_sys = "0.7.11";
log = "0.4.6";
url = "1.7.2";
openssl_probe = "0.1.2";
openssl_sys = "0.9.43";
};
deps.git2_curl."0.9.0" = {
curl = "0.4.21";
git2 = "0.8.0";
log = "0.4.6";
url = "1.7.2";
};
deps.glob."0.2.11" = {};
deps.globset."0.4.3" = {
aho_corasick = "0.7.3";
bstr = "0.1.2";
fnv = "1.0.6";
log = "0.4.6";
regex = "1.1.6";
};
deps.hashbrown."0.1.8" = {
byteorder = "1.3.1";
scopeguard = "0.3.3";
};
deps.hex."0.3.2" = {};
deps.home."0.3.4" = {
scopeguard = "0.3.3";
winapi = "0.3.7";
};
deps.http."0.1.17" = {
bytes = "0.4.12";
fnv = "1.0.6";
itoa = "0.4.3";
};
deps.humantime."1.2.0" = {
quick_error = "1.2.2";
};
deps.idna."0.1.5" = {
matches = "0.1.8";
unicode_bidi = "0.3.4";
unicode_normalization = "0.1.8";
};
deps.ignore."0.4.7" = {
crossbeam_channel = "0.3.8";
globset = "0.4.3";
lazy_static = "1.3.0";
log = "0.4.6";
memchr = "2.2.0";
regex = "1.1.6";
same_file = "1.0.4";
thread_local = "0.3.6";
walkdir = "2.2.7";
winapi_util = "0.1.2";
};
deps.im_rc."12.3.4" = {
sized_chunks = "0.1.3";
typenum = "1.10.0";
rustc_version = "0.2.3";
};
deps.iovec."0.1.2" = {
libc = "0.2.51";
winapi = "0.2.8";
};
deps.itertools."0.7.11" = {
either = "1.5.2";
};
deps.itoa."0.4.3" = {};
deps.jobserver."0.1.13" = {
log = "0.4.6";
libc = "0.2.51";
rand = "0.6.5";
};
deps.kernel32_sys."0.2.2" = {
winapi = "0.2.8";
winapi_build = "0.1.1";
};
deps.lazy_static."1.3.0" = {};
deps.lazycell."1.2.1" = {};
deps.libc."0.2.51" = {};
deps.libgit2_sys."0.7.11" = {
curl_sys = "0.4.18";
libc = "0.2.51";
libssh2_sys = "0.2.11";
libz_sys = "1.0.25";
cc = "1.0.35";
pkg_config = "0.3.14";
openssl_sys = "0.9.43";
};
deps.libnghttp2_sys."0.1.1" = {
libc = "0.2.51";
cc = "1.0.35";
};
deps.libssh2_sys."0.2.11" = {
libc = "0.2.51";
libz_sys = "1.0.25";
cc = "1.0.35";
pkg_config = "0.3.14";
openssl_sys = "0.9.43";
};
deps.libz_sys."1.0.25" = {
libc = "0.2.51";
cc = "1.0.35";
pkg_config = "0.3.14";
};
deps.lock_api."0.1.5" = {
scopeguard = "0.3.3";
};
deps.log."0.4.6" = {
cfg_if = "0.1.7";
};
deps.matches."0.1.8" = {};
deps.matrixmultiply."0.1.15" = {
rawpointer = "0.1.0";
};
deps.memchr."2.2.0" = {};
deps.miniz_sys."0.1.11" = {
libc = "0.2.51";
cc = "1.0.35";
};
deps.miniz_oxide."0.2.1" = {
adler32 = "1.0.3";
};
deps.miniz_oxide_c_api."0.2.1" = {
crc = "1.8.1";
libc = "0.2.51";
miniz_oxide = "0.2.1";
cc = "1.0.35";
};
deps.miow."0.3.3" = {
socket2 = "0.3.8";
winapi = "0.3.7";
};
deps.ndarray."0.12.1" = {
itertools = "0.7.11";
matrixmultiply = "0.1.15";
num_complex = "0.2.1";
num_traits = "0.2.6";
};
deps.num_complex."0.2.1" = {
num_traits = "0.2.6";
};
deps.num_traits."0.2.6" = {};
deps.num_cpus."1.10.0" = {
libc = "0.2.51";
};
deps.once_cell."0.1.8" = {
parking_lot = "0.7.1";
};
deps.opener."0.3.2" = {
failure = "0.1.5";
failure_derive = "0.1.5";
winapi = "0.3.7";
};
deps.openssl."0.10.20" = {
bitflags = "1.0.4";
cfg_if = "0.1.7";
foreign_types = "0.3.2";
lazy_static = "1.3.0";
libc = "0.2.51";
openssl_sys = "0.9.43";
};
deps.openssl_probe."0.1.2" = {};
deps.openssl_src."111.2.1+1.1.1b" = {
cc = "1.0.35";
};
deps.openssl_sys."0.9.43" = {
libc = "0.2.51";
cc = "1.0.35";
openssl_src = "111.2.1+1.1.1b";
pkg_config = "0.3.14";
rustc_version = "0.2.3";
};
deps.parking_lot."0.7.1" = {
lock_api = "0.1.5";
parking_lot_core = "0.4.0";
};
deps.parking_lot_core."0.4.0" = {
rand = "0.6.5";
smallvec = "0.6.9";
rustc_version = "0.2.3";
libc = "0.2.51";
winapi = "0.3.7";
};
deps.percent_encoding."1.0.1" = {};
deps.pkg_config."0.3.14" = {};
deps.proc_macro2."0.4.27" = {
unicode_xid = "0.1.0";
};
deps.quick_error."1.2.2" = {};
deps.quote."0.6.12" = {
proc_macro2 = "0.4.27";
};
deps.rand."0.6.5" = {
rand_chacha = "0.1.1";
rand_core = "0.4.0";
rand_hc = "0.1.0";
rand_isaac = "0.1.1";
rand_jitter = "0.1.3";
rand_os = "0.1.3";
rand_pcg = "0.1.2";
rand_xorshift = "0.1.1";
autocfg = "0.1.2";
libc = "0.2.51";
winapi = "0.3.7";
};
deps.rand_chacha."0.1.1" = {
rand_core = "0.3.1";
autocfg = "0.1.2";
};
deps.rand_core."0.3.1" = {
rand_core = "0.4.0";
};
deps.rand_core."0.4.0" = {};
deps.rand_hc."0.1.0" = {
rand_core = "0.3.1";
};
deps.rand_isaac."0.1.1" = {
rand_core = "0.3.1";
};
deps.rand_jitter."0.1.3" = {
rand_core = "0.4.0";
libc = "0.2.51";
winapi = "0.3.7";
};
deps.rand_os."0.1.3" = {
rand_core = "0.4.0";
rdrand = "0.4.0";
cloudabi = "0.0.3";
fuchsia_cprng = "0.1.1";
libc = "0.2.51";
winapi = "0.3.7";
};
deps.rand_pcg."0.1.2" = {
rand_core = "0.4.0";
autocfg = "0.1.2";
};
deps.rand_xorshift."0.1.1" = {
rand_core = "0.3.1";
};
deps.rawpointer."0.1.0" = {};
deps.rdrand."0.4.0" = {
rand_core = "0.3.1";
};
deps.redox_syscall."0.1.54" = {};
deps.redox_termios."0.1.1" = {
redox_syscall = "0.1.54";
};
deps.regex."1.1.6" = {
aho_corasick = "0.7.3";
memchr = "2.2.0";
regex_syntax = "0.6.6";
thread_local = "0.3.6";
utf8_ranges = "1.0.2";
};
deps.regex_syntax."0.6.6" = {
ucd_util = "0.1.3";
};
deps.remove_dir_all."0.5.1" = {
winapi = "0.3.7";
};
deps.rustc_demangle."0.1.14" = {};
deps.rustc_workspace_hack."1.0.0" = {};
deps.rustc_version."0.2.3" = {
semver = "0.9.0";
};
deps.rustfix."0.4.5" = {
failure = "0.1.5";
log = "0.4.6";
serde = "1.0.90";
serde_derive = "1.0.90";
serde_json = "1.0.39";
};
deps.ryu."0.2.7" = {};
deps.same_file."1.0.4" = {
winapi_util = "0.1.2";
};
deps.schannel."0.1.15" = {
lazy_static = "1.3.0";
winapi = "0.3.7";
};
deps.scopeguard."0.3.3" = {};
deps.semver."0.9.0" = {
semver_parser = "0.7.0";
serde = "1.0.90";
};
deps.semver_parser."0.7.0" = {};
deps.serde."1.0.90" = {
serde_derive = "1.0.90";
};
deps.serde_derive."1.0.90" = {
proc_macro2 = "0.4.27";
quote = "0.6.12";
syn = "0.15.32";
};
deps.serde_ignored."0.0.4" = {
serde = "1.0.90";
};
deps.serde_json."1.0.39" = {
itoa = "0.4.3";
ryu = "0.2.7";
serde = "1.0.90";
};
deps.shell_escape."0.1.4" = {};
deps.sized_chunks."0.1.3" = {
typenum = "1.10.0";
};
deps.smallvec."0.6.9" = {};
deps.socket2."0.3.8" = {
cfg_if = "0.1.7";
libc = "0.2.51";
redox_syscall = "0.1.54";
winapi = "0.3.7";
};
deps.strsim."0.8.0" = {};
deps.strsim."0.9.1" = {
hashbrown = "0.1.8";
ndarray = "0.12.1";
};
deps.syn."0.15.32" = {
proc_macro2 = "0.4.27";
quote = "0.6.12";
unicode_xid = "0.1.0";
};
deps.synstructure."0.10.1" = {
proc_macro2 = "0.4.27";
quote = "0.6.12";
syn = "0.15.32";
unicode_xid = "0.1.0";
};
deps.tar."0.4.22" = {
filetime = "0.2.4";
redox_syscall = "0.1.54";
libc = "0.2.51";
};
deps.tempfile."3.0.7" = {
cfg_if = "0.1.7";
rand = "0.6.5";
remove_dir_all = "0.5.1";
redox_syscall = "0.1.54";
libc = "0.2.51";
winapi = "0.3.7";
};
deps.termcolor."1.0.4" = {
wincolor = "1.0.1";
};
deps.termion."1.5.1" = {
libc = "0.2.51";
redox_syscall = "0.1.54";
redox_termios = "0.1.1";
};
deps.textwrap."0.11.0" = {
unicode_width = "0.1.5";
};
deps.thread_local."0.3.6" = {
lazy_static = "1.3.0";
};
deps.toml."0.4.10" = {
serde = "1.0.90";
};
deps.toml."0.5.0" = {
serde = "1.0.90";
};
deps.typenum."1.10.0" = {};
deps.ucd_util."0.1.3" = {};
deps.unicode_bidi."0.3.4" = {
matches = "0.1.8";
};
deps.unicode_normalization."0.1.8" = {
smallvec = "0.6.9";
};
deps.unicode_width."0.1.5" = {};
deps.unicode_xid."0.1.0" = {};
deps.url."1.7.2" = {
idna = "0.1.5";
matches = "0.1.8";
percent_encoding = "1.0.1";
};
deps.url_serde."0.2.0" = {
serde = "1.0.90";
url = "1.7.2";
};
deps.utf8_ranges."1.0.2" = {};
deps.vcpkg."0.2.6" = {};
deps.vec_map."0.8.1" = {};
deps.walkdir."2.2.7" = {
same_file = "1.0.4";
winapi = "0.3.7";
winapi_util = "0.1.2";
};
deps.winapi."0.2.8" = {};
deps.winapi."0.3.7" = {
winapi_i686_pc_windows_gnu = "0.4.0";
winapi_x86_64_pc_windows_gnu = "0.4.0";
};
deps.winapi_build."0.1.1" = {};
deps.winapi_i686_pc_windows_gnu."0.4.0" = {};
deps.winapi_util."0.1.2" = {
winapi = "0.3.7";
};
deps.winapi_x86_64_pc_windows_gnu."0.4.0" = {};
deps.wincolor."1.0.1" = {
winapi = "0.3.7";
winapi_util = "0.1.2";
};
}

View File

@ -0,0 +1,10 @@
{ callPackage, fetchFromGitHub }:
((callPackage ./cargo-vendor-carnix.nix {}).cargo_vendor {}).overrideAttrs (attrs: {
src = fetchFromGitHub {
owner = "alexcrichton";
repo = "cargo-vendor";
rev = "9355661303ce2870d68a69d99953fce22581e31e";
sha256 = "0d4j3r09am3ynwhczimzv39264f5xz37jxa9js123y46w5by3wd2";
};
})

View File

@ -0,0 +1,61 @@
{ stdenv, file, curl, pkgconfig, python, openssl, cmake, zlib
, makeWrapper, libiconv, cacert, rustPlatform, rustc, libgit2
, fetchurl
}:
rustPlatform.buildRustPackage rec {
# Note: we can't build cargo 1.28.0 because rustc tightened the borrow checker rules and broke
# backward compatibility, which affects old cargo versions.
name = "cargo-${version}";
version = "1.37.0";
src = fetchurl {
url = "https://static.rust-lang.org/dist/rustc-1.37.0-src.tar.gz";
sha256 = "1hrqprybhkhs6d9b5pjskfnc5z9v2l2gync7nb39qjb5s0h703hj";
};
# the rust source tarball already has all the dependencies vendored, no need to fetch them again
cargoVendorDir = "vendor";
preBuild = "pushd src/tools/cargo";
postBuild = "popd";
passthru.rustc = rustc;
# changes hash of vendor directory otherwise
dontUpdateAutotoolsGnuConfigScripts = true;
nativeBuildInputs = [ pkgconfig cmake makeWrapper ];
buildInputs = [ cacert file curl python openssl zlib libgit2 ];
LIBGIT2_SYS_USE_PKG_CONFIG = 1;
# fixes: the cargo feature `edition` requires a nightly version of Cargo, but this is the `stable` channel
RUSTC_BOOTSTRAP = 1;
postInstall = ''
# NOTE: We override the `http.cainfo` option usually specified in
# `.cargo/config`. This is an issue when users want to specify
# their own certificate chain as environment variables take
# precedence
wrapProgram "$out/bin/cargo" \
--suffix PATH : "${rustc}/bin" \
--set CARGO_HTTP_CAINFO "${cacert}/etc/ssl/certs/ca-bundle.crt" \
--set SSL_CERT_FILE "${cacert}/etc/ssl/certs/ca-bundle.crt"
'';
checkPhase = ''
# Disable cross compilation tests
export CFG_DISABLE_CROSS_TESTS=1
cargo test
'';
# Disable check phase as there are failures (4 tests fail)
doCheck = false;
meta = with stdenv.lib; {
homepage = https://crates.io;
description = "Downloads your Rust project's dependencies and builds your project";
maintainers = with maintainers; [ wizeman retrry ];
license = [ licenses.mit licenses.asl20 ];
platforms = platforms.unix;
};
}

View File

@ -0,0 +1,10 @@
--- rustc-1.26.2-src.org/src/libstd/process.rs 2018-06-01 21:40:11.000000000 +0100
+++ rustc-1.26.2-src/src/libstd/process.rs 2018-06-08 07:50:23.023828658 +0100
@@ -1745,6 +1745,7 @@
}
#[test]
+ #[ignore]
fn test_inherit_env() {
use env;

View File

@ -0,0 +1,104 @@
diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs
index 0f60b5b3e..9b08415e7 100644
--- a/src/libstd/net/tcp.rs
+++ b/src/libstd/net/tcp.rs
@@ -962,6 +962,7 @@ mod tests {
}
}
+ #[cfg_attr(target_os = "macos", ignore)]
#[test]
fn listen_localhost() {
let socket_addr = next_test_ip4();
@@ -1020,6 +1021,7 @@ mod tests {
})
}
+ #[cfg_attr(target_os = "macos", ignore)]
#[test]
fn read_eof() {
each_ip(&mut |addr| {
@@ -1039,6 +1041,7 @@ mod tests {
})
}
+ #[cfg_attr(target_os = "macos", ignore)]
#[test]
fn write_close() {
each_ip(&mut |addr| {
@@ -1065,6 +1068,7 @@ mod tests {
})
}
+ #[cfg_attr(target_os = "macos", ignore)]
#[test]
fn multiple_connect_serial() {
each_ip(&mut |addr| {
@@ -1087,6 +1091,7 @@ mod tests {
})
}
+ #[cfg_attr(target_os = "macos", ignore)]
#[test]
fn multiple_connect_interleaved_greedy_schedule() {
const MAX: usize = 10;
@@ -1123,6 +1128,7 @@ mod tests {
}
#[test]
+ #[cfg_attr(target_os = "macos", ignore)]
fn multiple_connect_interleaved_lazy_schedule() {
const MAX: usize = 10;
each_ip(&mut |addr| {
@@ -1401,6 +1407,7 @@ mod tests {
}
#[test]
+ #[cfg_attr(target_os = "macos", ignore)]
fn clone_while_reading() {
each_ip(&mut |addr| {
let accept = t!(TcpListener::bind(&addr));
@@ -1421,7 +1422,10 @@ mod tests {
// FIXME: re-enabled bitrig/openbsd tests once their socket timeout code
// no longer has rounding errors.
- #[cfg_attr(any(target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"), ignore)]
+ #[cfg_attr(any(target_os = "bitrig",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "macos"), ignore)]
#[test]
fn timeouts() {
let addr = next_test_ip4();
@@ -1596,6 +1603,7 @@ mod tests {
drop(listener);
}
+ #[cfg_attr(target_os = "macos", ignore)]
#[test]
fn nodelay() {
let addr = next_test_ip4();
@@ -1610,6 +1618,7 @@ mod tests {
assert_eq!(false, t!(stream.nodelay()));
}
+ #[cfg_attr(target_os = "macos", ignore)]
#[test]
fn ttl() {
let ttl = 100;
@@ -1647,6 +1656,7 @@ mod tests {
}
}
+ #[cfg_attr(target_os = "macos", ignore)]
#[test]
fn peek() {
each_ip(&mut |addr| {
@@ -1679,6 +1689,7 @@ mod tests {
}
#[test]
+ #[cfg_attr(any(target_os = "linux", target_os = "macos"), ignore)]
fn connect_timeout_unroutable() {
// this IP is unroutable, so connections should always time out,
// provided the network is reachable to begin with.

View File

@ -0,0 +1,20 @@
diff --git a/src/stdsimd/coresimd/x86/mod.rs b/src/stdsimd/coresimd/x86/mod.rs
index 32915c332..7cb54f31e 100644
--- a/src/stdsimd/coresimd/x86/mod.rs
+++ b/src/stdsimd/coresimd/x86/mod.rs
@@ -279,7 +279,6 @@ types! {
///
/// # Examples
///
- /// ```
/// # #![feature(cfg_target_feature, target_feature, stdsimd)]
/// # #![cfg_attr(not(dox), no_std)]
/// # #[cfg(not(dox))]
@@ -301,7 +300,6 @@ types! {
/// # }
/// # if is_x86_feature_detected!("sse") { unsafe { foo() } }
/// # }
- /// ```
pub struct __m256(f32, f32, f32, f32, f32, f32, f32, f32);
/// 256-bit wide set of four `f64` types, x86-specific

View File

@ -0,0 +1,38 @@
#!/usr/bin/env bash
set -euo pipefail
# All rust-related downloads can be found at
# https://static.rust-lang.org/dist/index.html. To find the date on
# which a particular thing was last updated, look for the *-date.txt
# file, e.g.
# https://static.rust-lang.org/dist/channel-rust-beta-date.txt
PLATFORMS=(
i686-unknown-linux-gnu
x86_64-unknown-linux-gnu
armv7-unknown-linux-gnueabihf
aarch64-unknown-linux-gnu
i686-apple-darwin
x86_64-apple-darwin
)
BASEURL=https://static.rust-lang.org/dist
VERSION=${1:-}
DATE=${2:-}
if [[ -z $VERSION ]]
then
echo "No version supplied"
exit -1
fi
if [[ -n $DATE ]]
then
BASEURL=$BASEURL/$DATE
fi
for PLATFORM in "${PLATFORMS[@]}"
do
URL="$BASEURL/rust-$VERSION-$PLATFORM.tar.gz.sha256"
SHA256=$(curl -sSfL $URL | cut -d ' ' -f 1)
echo "$PLATFORM = \"$SHA256\";"
done

View File

@ -0,0 +1,95 @@
{ stdenv, callPackage, recurseIntoAttrs, makeRustPlatform, llvm-or1k, fetchurl
, targets ? []
, targetToolchains ? []
, targetPatches ? []
, fetchFromGitHub
, runCommand
}:
let
rustPlatform = recurseIntoAttrs (makeRustPlatform (callPackage ./bootstrap.nix {}));
version = "1.28.0";
src = fetchFromGitHub {
owner = "m-labs";
repo = "rust";
sha256 = "03lfps3xvvv7wv1nnwn3n1ji13z099vx8c3fpbzp9rnasrwzp5jy";
rev = "f305fb024318e96997fbe6e4a105b0cc1052aad4"; # artiq-1.28.0 branch
fetchSubmodules = true;
};
rustc_internal = callPackage ./rustc.nix {
inherit stdenv llvm-or1k targets targetPatches targetToolchains rustPlatform version src;
patches = [
./patches/net-tcp-disable-tests.patch
# Re-evaluate if this we need to disable this one
#./patches/stdsimd-disable-doctest.patch
# Fails on hydra - not locally; the exact reason is unknown.
# Comments in the test suggest that some non-reproducible environment
# variables such $RANDOM can make it fail.
./patches/disable-test-inherit-env.patch
];
#configureFlags = [ "--release-channel=stable" ];
# 1. Upstream is not running tests on aarch64:
# see https://github.com/rust-lang/rust/issues/49807#issuecomment-380860567
# So we do the same.
# 2. Tests run out of memory for i686
#doCheck = !stdenv.isAarch64 && !stdenv.isi686;
# Disabled for now; see https://github.com/NixOS/nixpkgs/pull/42348#issuecomment-402115598.
doCheck = false;
};
or1k-crates = stdenv.mkDerivation {
name = "or1k-crates";
inherit src;
phases = [ "unpackPhase" "buildPhase" ];
buildPhase = ''
destdir=$out
rustc="${rustc_internal}/bin/rustc --out-dir ''${destdir} -L ''${destdir} --target or1k-unknown-none -g -C target-feature=+mul,+div,+ffl1,+cmov,+addc -C opt-level=s --crate-type rlib"
mkdir -p ''${destdir}
''${rustc} --crate-name core src/libcore/lib.rs
''${rustc} --crate-name compiler_builtins src/libcompiler_builtins/src/lib.rs --cfg 'feature="compiler-builtins"' --cfg 'feature="mem"'
''${rustc} --crate-name std_unicode src/libstd_unicode/lib.rs
''${rustc} --crate-name alloc src/liballoc/lib.rs
''${rustc} --crate-name libc src/liblibc_mini/lib.rs
''${rustc} --crate-name unwind src/libunwind/lib.rs
''${rustc} -Cpanic=abort --crate-name panic_abort src/libpanic_abort/lib.rs
''${rustc} -Cpanic=unwind --crate-name panic_unwind src/libpanic_unwind/lib.rs --cfg llvm_libunwind
'';
};
arm-crates = stdenv.mkDerivation {
name = "arm-crates";
inherit src;
phases = [ "unpackPhase" "buildPhase" ];
buildPhase = ''
destdir=$out
rustc="${rustc_internal}/bin/rustc --out-dir ''${destdir} -L ''${destdir} --target armv7-unknown-linux-gnueabihf -g -C target-feature=+dsp,+fp16,+neon,+vfp3 -C opt-level=s --crate-type rlib"
mkdir -p ''${destdir}
''${rustc} --crate-name core src/libcore/lib.rs
''${rustc} --crate-name compiler_builtins src/libcompiler_builtins/src/lib.rs --cfg 'feature="compiler-builtins"' --cfg 'feature="mem"'
''${rustc} --crate-name std_unicode src/libstd_unicode/lib.rs
''${rustc} --crate-name alloc src/liballoc/lib.rs
''${rustc} --crate-name libc src/liblibc_mini/lib.rs
''${rustc} --crate-name unwind src/libunwind/lib.rs
''${rustc} -Cpanic=abort --crate-name panic_abort src/libpanic_abort/lib.rs
''${rustc} -Cpanic=unwind --crate-name panic_unwind src/libpanic_unwind/lib.rs --cfg llvm_libunwind
'';
};
in
stdenv.mkDerivation {
name = "rustc";
inherit src version;
buildCommand = ''
mkdir -p $out/lib/rustlib/or1k-unknown-none/lib/
cp -r ${or1k-crates}/* $out/lib/rustlib/or1k-unknown-none/lib/
mkdir -p $out/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/
cp -r ${arm-crates}/* $out/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/
cp -r ${rustc_internal}/* $out
'';
passAsFile = [ "buildCommand" ];
}

View File

@ -0,0 +1,182 @@
{ stdenv, targetPackages
, fetchurl, file, python2, tzdata, ps
, llvm-or1k, ncurses, zlib, darwin, rustPlatform, git, cmake, curl
, which, libffi, gdb
, version
, src
, configureFlags ? []
, patches
, targets
, targetPatches
, targetToolchains
, doCheck ? true
, broken ? false
}:
let
inherit (stdenv.lib) optional optionalString;
inherit (darwin.apple_sdk.frameworks) Security;
target = builtins.replaceStrings [" "] [","] (builtins.toString targets);
src_rustc = fetchurl {
url = "https://static.rust-lang.org/dist/rustc-1.28.0-src.tar.gz";
sha256 = "11k4rn77bca2rikykkk9fmprrgjswd4x4kaq7fia08vgkir82nhx";
};
in
stdenv.mkDerivation {
name = "rustc-${version}";
inherit version;
inherit src;
__darwinAllowLocalNetworking = true;
# rustc complains about modified source files otherwise
dontUpdateAutotoolsGnuConfigScripts = true;
# Running the default `strip -S` command on Darwin corrupts the
# .rlib files in "lib/".
#
# See https://github.com/NixOS/nixpkgs/pull/34227
stripDebugList = if stdenv.isDarwin then [ "bin" ] else null;
NIX_LDFLAGS = optionalString stdenv.isDarwin "-rpath ${llvm-or1k}/lib";
# Enable nightly features in stable compiles (used for
# bootstrapping, see https://github.com/rust-lang/rust/pull/37265).
# This loosens the hard restrictions on bootstrapping-compiler
# versions.
RUSTC_BOOTSTRAP = "1";
# Increase codegen units to introduce parallelism within the compiler.
RUSTFLAGS = "-Ccodegen-units=10";
# We need rust to build rust. If we don't provide it, configure will try to download it.
# Reference: https://github.com/rust-lang/rust/blob/master/src/bootstrap/configure.py
configureFlags = configureFlags
++ [ "--enable-local-rust" "--local-rust-root=${rustPlatform.rust.rustc}" "--enable-rpath" ]
++ [ "--enable-vendor" ]
++ [ "--default-linker=${targetPackages.stdenv.cc}/bin/cc" ]
++ [ "--enable-llvm-link-shared" ]
++ optional (targets != []) "--target=${target}"
++ [ "--llvm-root=${llvm-or1k}" ] ;
# The bootstrap.py will generated a Makefile that then executes the build.
# The BOOTSTRAP_ARGS used by this Makefile must include all flags to pass
# to the bootstrap builder.
postConfigure = ''
substituteInPlace Makefile --replace 'BOOTSTRAP_ARGS :=' 'BOOTSTRAP_ARGS := --jobs $(NIX_BUILD_CORES)'
'';
# FIXME: qknight, readd deleted vendor folder from 1.28 rustc
preConfigure = ''
export HOME=$out
# HACK: we add the vendor folder from rustc 1.28 to make the compiling work
tar xf ${src_rustc}
mv rustc-1.28.0-src/src/vendor/ src/vendor
'';
patches = patches ++ targetPatches;
# the rust build system complains that nix alters the checksums
dontFixLibtool = true;
passthru.target = target;
postPatch = ''
patchShebangs src/etc
# Fix the configure script to not require curl as we won't use it
sed -i configure \
-e '/probe_need CFG_CURL curl/d'
# Disable fragile tests.
rm -vr src/test/run-make/linker-output-non-utf8 || true
rm -vr src/test/run-make/issue-26092 || true
# Remove test targeted at LLVM 3.9 - https://github.com/rust-lang/rust/issues/36835
rm -vr src/test/run-pass/issue-36023.rs || true
# Disable test getting stuck on hydra - possible fix:
# https://reviews.llvm.org/rL281650
rm -vr src/test/run-pass/issue-36474.rs || true
# On Hydra: `TcpListener::bind(&addr)`: Address already in use (os error 98)'
sed '/^ *fn fast_rebind()/i#[ignore]' -i src/libstd/net/tcp.rs
# https://github.com/rust-lang/rust/issues/39522
echo removing gdb-version-sensitive tests...
find src/test/debuginfo -type f -execdir grep -q ignore-gdb-version '{}' \; -print -delete
rm src/test/debuginfo/{borrowed-c-style-enum.rs,c-style-enum-in-composite.rs,gdb-pretty-struct-and-enums-pre-gdb-7-7.rs,generic-enum-with-different-disr-sizes.rs}
# Useful debugging parameter
# export VERBOSE=1
'' + optionalString stdenv.isDarwin ''
# Disable all lldb tests.
# error: Can't run LLDB test because LLDB's python path is not set
rm -vr src/test/debuginfo/*
rm -v src/test/run-pass/backtrace-debuginfo.rs
# error: No such file or directory
rm -v src/test/run-pass/issue-45731.rs
# Disable tests that fail when sandboxing is enabled.
substituteInPlace src/libstd/sys/unix/ext/net.rs \
--replace '#[test]' '#[test] #[ignore]'
substituteInPlace src/test/run-pass/env-home-dir.rs \
--replace 'home_dir().is_some()' true
rm -v src/test/run-pass/fds-are-cloexec.rs # FIXME: pipes?
rm -v src/test/run-pass/sync-send-in-std.rs # FIXME: ???
'';
# rustc unfortunately need cmake for compiling llvm-rt but doesn't
# use it for the normal build. This disables cmake in Nix.
dontUseCmakeConfigure = true;
# ps is needed for one of the test cases
nativeBuildInputs =
[ file python2 ps rustPlatform.rust.rustc git cmake
which libffi
]
# Only needed for the debuginfo tests
++ optional (!stdenv.isDarwin) gdb;
buildInputs = [ ncurses zlib llvm-or1k ] ++ targetToolchains
++ optional stdenv.isDarwin Security;
outputs = [ "out" "man" "doc" ];
setOutputFlags = false;
# Disable codegen units and hardening for the tests.
preCheck = ''
export RUSTFLAGS=
export TZDIR=${tzdata}/share/zoneinfo
export hardeningDisable=all
'' +
# Ensure TMPDIR is set, and disable a test that removing the HOME
# variable from the environment falls back to another home
# directory.
optionalString stdenv.isDarwin ''
export TMPDIR=/tmp
sed -i '28s/home_dir().is_some()/true/' ./src/test/run-pass/env-home-dir.rs
'';
inherit doCheck;
configurePlatforms = [];
# https://github.com/NixOS/nixpkgs/pull/21742#issuecomment-272305764
# https://github.com/rust-lang/rust/issues/30181
# enableParallelBuilding = false;
meta = with stdenv.lib; {
homepage = https://www.rust-lang.org/;
description = "A safe, concurrent, practical language";
maintainers = with maintainers; [ sb0 ];
license = [ licenses.mit licenses.asl20 ];
platforms = platforms.linux ++ platforms.darwin;
broken = broken;
};
}

20
artiq-fast/shell-dev.nix Normal file
View File

@ -0,0 +1,20 @@
{ pkgs ? import <nixpkgs> {}}:
let
artiqpkgs = import ./default.nix { inherit pkgs; };
vivado = import ./vivado.nix { inherit pkgs; };
in
pkgs.mkShell {
buildInputs = [
vivado
pkgs.gnumake
(pkgs.python3.withPackages(ps: (with ps; [ jinja2 numpy paramiko ]) ++ (with artiqpkgs; [ migen microscope misoc jesd204b migen-axi artiq ])))
artiqpkgs.cargo
artiqpkgs.rustc
artiqpkgs.binutils-or1k
artiqpkgs.binutils-arm
artiqpkgs.llvm-or1k
artiqpkgs.openocd
];
TARGET_AR="or1k-linux-ar";
}

8
artiq-fast/shell.nix Normal file
View File

@ -0,0 +1,8 @@
{ pkgs ? import <nixpkgs> {}}:
let
artiqpkgs = import ./default.nix { inherit pkgs; };
in
pkgs.mkShell {
buildInputs = [ (pkgs.python3.withPackages(ps: [artiqpkgs.artiq])) ];
}

24
artiq-fast/vivado.nix Normal file
View File

@ -0,0 +1,24 @@
# Install Vivado in /opt and add to /etc/nixos/configuration.nix:
# nix.sandboxPaths = ["/opt"];
{ pkgs, vivadoPath ? "/opt/Xilinx/Vivado/2020.1" }:
pkgs.buildFHSUserEnv {
name = "vivado";
targetPkgs = pkgs: (
with pkgs; [
ncurses5
zlib
libuuid
xorg.libSM
xorg.libICE
xorg.libXrender
xorg.libX11
xorg.libXext
xorg.libXtst
xorg.libXi
]
);
profile = "source ${vivadoPath}/settings64.sh";
runScript = "vivado";
}

26
artiq-fast/wfvm/README.md Normal file
View File

@ -0,0 +1,26 @@
# Preparation steps
## Install a Windows image
1. Adjust demo-image.nix accordingly
2. Run:
If in impure mode
```shell
nix-build demo-image.nix
./result
```
Results in a file called c.img
If in pure mode
```shell
nix-build demo-image.nix
ls -la ./result
```
Results in a symlink to the image in the nix store
# Impure/pure mode
Sometimes it can be useful to build the image _outside_ of the Nix sandbox for debugging purposes.
For this purpose we have an attribute called `impureMode` which outputs the shell script used by Nix inside the sandbox to build the image.

View File

@ -0,0 +1,317 @@
{ pkgs
, fullName ? "John Doe"
, organization ? "KVM Authority"
, administratorPassword ? "123456"
, uiLanguage ? "en-US"
, inputLocale ? "en-US"
, userLocale ? "en-US"
, systemLocale ? "en-US"
, users ? {}
, productKey ? null
, defaultUser ? "wfvm"
, setupCommands ? []
, timeZone ? "UTC"
, services ? {}
, impureShellCommands ? []
, driveLetter ? "E:"
, ...
}:
let
lib = pkgs.lib;
serviceCommands = lib.mapAttrsToList (
serviceName: attrs: "powershell Set-Service -Name ${serviceName} " + (
lib.concatStringsSep " " (
(
lib.mapAttrsToList (
n: v: if builtins.typeOf v != "bool" then "-${n} ${v}" else "-${n}"
)
) (
# Always run without interaction
{ Force = true; } // attrs
)
)
)
) services;
sshSetupCommands =
# let
# makeDirs = lib.mapAttrsToList (n: v: ''mkdir C:\Users\${n}\.ssh'') users;
# writeKeys = lib.flatten (lib.mapAttrsToList (n: v: builtins.map (key: let
# commands = [
# ''powershell.exe Set-Content -Path C:\Users\${n}\.ssh\authorized_keys -Value '${key}' ''
# ];
# in lib.concatStringsSep "\n" commands) (v.sshKeys or [])) users);
# mkDirsDesc = builtins.map (c: {Path = c; Description = "Make SSH key dir";}) makeDirs;
# writeKeysDesc = builtins.map (c: {Path = c; Description = "Add SSH key";}) writeKeys;
# in
# mkDirsDesc ++ writeKeysDesc ++
[
{
Path = ''powershell.exe Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0 -Source ${driveLetter}\fod -LimitAccess'';
Description = "Add OpenSSH service.";
}
{
Path = ''powershell.exe Set-Service -Name sshd -StartupType Automatic'';
Description = "Enable SSH by default.";
}
];
assertCommand = c: builtins.typeOf c == "string" || builtins.typeOf c == "set" && builtins.hasAttr "Path" c && builtins.hasAttr "Description" c;
commands = builtins.map (x: assert assertCommand x; if builtins.typeOf x == "string" then { Path = x; Description = x; } else x) (
[
{
Path = "powershell.exe Set-ExecutionPolicy -Force Unrestricted";
Description = "Allow unsigned powershell scripts.";
}
]
++ [
{
Path = ''powershell.exe ${driveLetter}\win-bundle-installer.exe'';
Description = "Install any declared packages.";
}
]
++ setupCommands
++ [
{
Path = ''powershell.exe ${driveLetter}\ssh-setup.ps1'';
Description = "Setup SSH and keys";
}
]
++ serviceCommands
++ impureShellCommands
);
mkCommand = attrs: ''
<RunSynchronousCommand wcm:action="add">
${lib.concatStringsSep "\n" (lib.attrsets.mapAttrsToList (n: v: "<${n}>${v}</${n}>") attrs)}
</RunSynchronousCommand>
'';
mkCommands = commands: (
builtins.foldl' (
acc: v: rec {
i = acc.i + 1;
values = acc.values ++ [ (mkCommand (v // { Order = builtins.toString i; })) ];
}
) {
i = 0;
values = [];
} commands
).values;
mkUser =
{ name
, password
, description ? ""
, displayName ? ""
, groups ? []
# , sshKeys ? [] # Handled in scripts
}: ''
<LocalAccount wcm:action="add">
<Password>
<Value>${password}</Value>
<PlainText>true</PlainText>
</Password>
<Description>${description}</Description>
<DisplayName>${displayName}</DisplayName>
<Group>${builtins.concatStringsSep ";" (lib.unique ([ "Users" ] ++ groups))}</Group>
<Name>${name}</Name>
</LocalAccount>
'';
# Windows expects a flat list of users while we want to manage them as a set
flatUsers = builtins.attrValues (builtins.mapAttrs (name: s: s // { inherit name; }) users);
autounattendXML = pkgs.writeText "autounattend.xml" ''
<?xml version="1.0" encoding="utf-8"?>
<unattend xmlns="urn:schemas-microsoft-com:unattend">
<settings pass="windowsPE">
<component name="Microsoft-Windows-PnpCustomizationsWinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<DriverPaths>
<PathAndCredentials wcm:action="add" wcm:keyValue="1">
<Path>D:\</Path>
</PathAndCredentials>
<PathAndCredentials wcm:action="add" wcm:keyValue="2">
<Path>E:\</Path>
</PathAndCredentials>
</DriverPaths>
</component>
<component name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<DiskConfiguration>
<Disk wcm:action="add">
<CreatePartitions>
<CreatePartition wcm:action="add">
<Order>1</Order>
<Type>EFI</Type>
<Size>100</Size>
</CreatePartition>
<CreatePartition wcm:action="add">
<Order>2</Order>
<Type>MSR</Type>
<Size>16</Size>
</CreatePartition>
<CreatePartition wcm:action="add">
<Order>3</Order>
<Type>Primary</Type>
<Extend>true</Extend>
</CreatePartition>
</CreatePartitions>
<ModifyPartitions>
<ModifyPartition wcm:action="add">
<Order>1</Order>
<Format>FAT32</Format>
<Label>System</Label>
<PartitionID>1</PartitionID>
</ModifyPartition>
<ModifyPartition wcm:action="add">
<Order>2</Order>
<PartitionID>2</PartitionID>
</ModifyPartition>
<ModifyPartition wcm:action="add">
<Order>3</Order>
<Format>NTFS</Format>
<Label>Windows</Label>
<Letter>C</Letter>
<PartitionID>3</PartitionID>
</ModifyPartition>
</ModifyPartitions>
<DiskID>0</DiskID>
<WillWipeDisk>true</WillWipeDisk>
</Disk>
</DiskConfiguration>
<ImageInstall>
<OSImage>
<InstallTo>
<DiskID>0</DiskID>
<PartitionID>3</PartitionID>
</InstallTo>
<InstallFrom>
<MetaData wcm:action="add">
<Key>/IMAGE/INDEX</Key>
<Value>1</Value>
</MetaData>
</InstallFrom>
</OSImage>
</ImageInstall>
<UserData>
<ProductKey>
${if productKey != null then "<Key>${productKey}</Key>" else ""}
<WillShowUI>OnError</WillShowUI>
</ProductKey>
<AcceptEula>true</AcceptEula>
<FullName>${fullName}</FullName>
<Organization>${organization}</Organization>
</UserData>
</component>
<component name="Microsoft-Windows-International-Core-WinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SetupUILanguage>
<UILanguage>${uiLanguage}</UILanguage>
</SetupUILanguage>
<InputLocale>${inputLocale}</InputLocale>
<SystemLocale>${systemLocale}</SystemLocale>
<UILanguage>${uiLanguage}</UILanguage>
<UILanguageFallback>en-US</UILanguageFallback>
<UserLocale>${userLocale}</UserLocale>
</component>
</settings>
<settings pass="oobeSystem">
<component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<InputLocale>${inputLocale}</InputLocale>
<SystemLocale>${systemLocale}</SystemLocale>
<UILanguage>${uiLanguage}</UILanguage>
<UILanguageFallback>en-US</UILanguageFallback>
<UserLocale>${userLocale}</UserLocale>
</component>
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<OOBE>
<HideEULAPage>true</HideEULAPage>
<HideLocalAccountScreen>true</HideLocalAccountScreen>
<HideOEMRegistrationScreen>true</HideOEMRegistrationScreen>
<HideOnlineAccountScreens>true</HideOnlineAccountScreens>
<HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
<ProtectYourPC>1</ProtectYourPC>
</OOBE>
<TimeZone>${timeZone}</TimeZone>
<UserAccounts>
${if administratorPassword != null then ''
<AdministratorPassword>
<Value>${administratorPassword}</Value>
<PlainText>true</PlainText>
</AdministratorPassword>
'' else ""}
<LocalAccounts>
${builtins.concatStringsSep "\n" (builtins.map mkUser flatUsers)}
</LocalAccounts>
</UserAccounts>
${if defaultUser == null then "" else ''
<AutoLogon>
<Password>
<Value>${(builtins.getAttr defaultUser users).password}</Value>
<PlainText>true</PlainText>
</Password>
<Enabled>true</Enabled>
<Username>${defaultUser}</Username>
</AutoLogon>
''}
<FirstLogonCommands>
<SynchronousCommand wcm:action="add">
<Order>1</Order>
<CommandLine>cmd /C shutdown /s /f /t 00</CommandLine>
<Description>ChangeHideFiles</Description>
</SynchronousCommand>
</FirstLogonCommands>
</component>
</settings>
<settings pass="specialize">
<component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<RunSynchronous>
${lib.concatStringsSep "\n" (mkCommands commands)}
</RunSynchronous>
</component>
<component name="Microsoft-Windows-SQMApi" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="NonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<CEIPEnabled>0</CEIPEnabled>
</component>
</settings>
<!-- Disable Windows UAC -->
<settings pass="offlineServicing">
<component name="Microsoft-Windows-LUA-Settings" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<EnableLUA>false</EnableLUA>
</component>
</settings>
<cpi:offlineImage cpi:source="wim:c:/wim/windows-10/install.wim#Windows 10 Enterprise LTSC 2019 Evaluation" xmlns:cpi="urn:schemas-microsoft-com:cpi" />
</unattend>
'';
in {
# Lint and format as a sanity check
autounattendXML = pkgs.runCommandNoCC "autounattend.xml" {} ''
${pkgs.libxml2}/bin/xmllint --format ${autounattendXML} > $out
'';
# autounattend.xml is _super_ picky about quotes and other things
setupScript = pkgs.writeText "ssh-setup.ps1" (
''
# Setup SSH and keys
'' +
lib.concatStrings (
builtins.map (c: ''
# ${c.Description}
${c.Path}
'') sshSetupCommands
)
);
}

View File

@ -0,0 +1,7 @@
{ pkgs }:
pkgs.runCommandNoCC "win-bundle-installer.exe" {} ''
cp ${./main.go} main.go
env HOME=$(mktemp -d) GOOS=windows GOARCH=amd64 ${pkgs.go}/bin/go build
mv build.exe $out
''

View File

@ -0,0 +1,116 @@
package main
import (
"archive/tar"
"fmt"
"io"
"io/ioutil"
"log"
"os"
"os/exec"
"path/filepath"
)
func Untar(dst string, r io.Reader) error {
tr := tar.NewReader(r)
for {
header, err := tr.Next()
switch {
case err == io.EOF:
return nil
case err != nil:
return err
case header == nil:
continue
}
target := filepath.Join(dst, header.Name)
switch header.Typeflag {
case tar.TypeDir:
if _, err := os.Stat(target); err != nil {
if err := os.MkdirAll(target, 0755); err != nil {
return err
}
}
case tar.TypeReg:
f, err := os.OpenFile(target, os.O_CREATE|os.O_RDWR, os.FileMode(header.Mode))
if err != nil {
return err
}
if _, err := io.Copy(f, tr); err != nil {
return err
}
f.Close()
}
}
}
func InstallBundle(bundlePath string) error {
reader, err := os.Open(bundlePath)
if err != nil {
log.Fatal(err)
}
workDir, err := ioutil.TempDir("", "bundle_install")
if err != nil {
return err
}
defer os.RemoveAll(workDir)
err = Untar(workDir, reader)
if err != nil {
return err
}
installScript := filepath.Join(workDir, "install.ps1")
cmd := exec.Command("powershell", installScript)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Dir = workDir
err = cmd.Run()
return err
}
func main() {
// Get path relative to binary
baseDir, err := filepath.Abs(filepath.Dir(os.Args[0]))
if err != nil {
log.Fatal(err)
}
var dirs = [2]string{"bootstrap", "user"}
for _, pkgDir := range dirs {
dir := filepath.Join(baseDir, pkgDir)
files, err := ioutil.ReadDir(dir)
if err != nil {
log.Fatal(err)
}
for _, file := range files {
bundle := filepath.Join(dir, file.Name())
fmt.Println(fmt.Sprintf("Installing: %s", bundle))
err := InstallBundle(bundle)
if err != nil {
log.Fatal(err)
}
}
}
}

View File

@ -0,0 +1,13 @@
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
buildInputs = [
pkgs.go
];
shellHook = ''
unset GOPATH
'';
}

View File

@ -0,0 +1,7 @@
{ pkgs }:
{
makeWindowsImage = attrs: import ./win.nix ({ inherit pkgs; } // attrs);
layers = (import ./layers { inherit pkgs; });
utils = (import ./utils.nix { inherit pkgs; });
}

View File

@ -0,0 +1,59 @@
{ pkgs ? import <nixpkgs> {}, impureMode ? false }:
let
wfvm = (import ./default.nix { inherit pkgs; });
in
wfvm.makeWindowsImage {
# Build install script & skip building iso
inherit impureMode;
# Custom base iso
# windowsImage = pkgs.fetchurl {
# url = "https://software-download.microsoft.com/download/sg/17763.107.101029-1455.rs5_release_svc_refresh_CLIENT_LTSC_EVAL_x64FRE_en-us.iso";
# sha256 = "668fe1af70c2f7416328aee3a0bb066b12dc6bbd2576f40f812b95741e18bc3a";
# };
# impureShellCommands = [
# "powershell.exe echo Hello"
# ];
# User accounts
# users = {
# artiq = {
# password = "1234";
# # description = "Default user";
# # displayName = "Display name";
# groups = [
# "Administrators"
# ];
# };
# };
# Auto login
# defaultUser = "artiq";
# fullName = "M-Labs";
# organization = "m-labs";
# administratorPassword = "12345";
# Imperative installation commands, to be installed incrementally
installCommands = with wfvm.layers; [ anaconda3 msys2 msys2-packages ];
# services = {
# # Enable remote management
# WinRm = {
# Status = "Running";
# PassThru = true;
# };
# };
# License key
# productKey = "iboughtthisone";
# Locales
# uiLanguage = "en-US";
# inputLocale = "en-US";
# userLocale = "en-US";
# systemLocale = "en-US";
}

View File

@ -0,0 +1,13 @@
{ pkgs ? import <nixpkgs> {} }:
let
wfvm = (import ./default.nix { inherit pkgs; });
in
wfvm.utils.wfvm-run {
name = "demo-ssh";
image = import ./demo-image.nix { inherit pkgs; };
isolateNetwork = false;
script = ''
${pkgs.sshpass}/bin/sshpass -p1234 -- ${pkgs.openssh}/bin/ssh -p 2022 wfvm@localhost -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null
'';
}

View File

@ -0,0 +1,107 @@
{ pkgs }:
{
anaconda3 = {
name = "Anaconda3";
script = let
Anaconda3 = pkgs.fetchurl {
name = "Anaconda3.exe";
url = "https://repo.anaconda.com/archive/Anaconda3-2020.02-Windows-x86_64.exe";
sha256 = "0n31l8l89jrjrbzbifxbjnr3g320ly9i4zfyqbf3l9blf4ygbhl3";
};
in ''
ln -s ${Anaconda3} ./Anaconda3.exe
win-put Anaconda3.exe 'C:\Users\wfvm'
echo Running Anaconda installer...
win-exec 'start /wait "" .\Anaconda3.exe /S /D=%UserProfile%\Anaconda3'
echo Anaconda installer finished
'';
};
msys2 = {
name = "MSYS2";
buildInputs = [ pkgs.expect ];
script = let
msys2 = pkgs.fetchurl {
name = "msys2.exe";
url = "https://github.com/msys2/msys2-installer/releases/download/2020-06-02/msys2-x86_64-20200602.exe";
sha256 = "1mswlfybvk42vdr4r85dypgkwhrp5ff47gcbxgjqwq86ym44xzd4";
};
msys2-auto-install = pkgs.fetchurl {
url = "https://raw.githubusercontent.com/msys2/msys2-installer/master/auto-install.js";
sha256 = "0ww48xch2q427c58arg5llakfkfzh3kb32kahwplp0s7jc8224g7";
};
in ''
ln -s ${msys2} ./msys2.exe
ln -s ${msys2-auto-install} ./auto-install.js
win-put msys2.exe 'C:\Users\wfvm'
win-put auto-install.js 'C:\Users\wfvm'
echo Running MSYS2 installer...
# work around MSYS2 installer bug that prevents it from closing at the end of unattended install
expect -c 'set timeout 600; spawn win-exec ".\\msys2.exe --script auto-install.js -v InstallPrefix=C:\\msys64"; expect FinishedPageCallback { close }'
echo MSYS2 installer finished
'';
};
msys2-packages = {
name = "MSYS2-packages";
script = let
msys-packages = import ./msys_packages.nix { inherit pkgs; };
msys-packages-put = pkgs.lib.strings.concatStringsSep "\n"
(map (package: ''win-put ${package} 'C:\Users\wfvm\msyspackages' '') msys-packages);
in
# Windows command line is so shitty it can't even do glob expansion. Why do people use Windows?
''
win-exec 'mkdir msyspackages'
${msys-packages-put}
cat > installmsyspackages.bat << EOF
set MSYS=c:\msys64
set ARCH=64
set PATH=%MSYS%\usr\bin;%MSYS%\mingw%ARCH%\bin;%PATH%
bash -c "pacman -U --noconfirm C:/Users/wfvm/msyspackages/*"
EOF
win-put installmsyspackages.bat 'C:\Users\wfvm'
win-exec installmsyspackages
'';
};
cmake = {
name = "CMake";
script = let
cmake = pkgs.fetchurl {
name = "cmake.msi";
url = "https://github.com/Kitware/CMake/releases/download/v3.18.0-rc1/cmake-3.18.0-rc1-win64-x64.msi";
sha256 = "1n32jzbg9w3vfbvyi9jqijz97gn1zsk1w5226wlrxd2a9d4w1hrn";
};
in
''
ln -s ${cmake} cmake.msi
win-put cmake.msi
win-exec "msiexec.exe /q /i cmake.msi ADD_CMAKE_TO_PATH=System"
'';
};
msvc = {
name = "MSVC";
script = let
msvc-wine = pkgs.fetchFromGitHub {
owner = "mstorsjo";
repo = "msvc-wine";
rev = "b953f996401c19df3039c04e4ac7f962e435a4b2";
sha256 = "12rqx0r3d836x4k1ccda5xmzsd2938v5gmrp27awmzv1j3wplfsq";
};
vs = pkgs.stdenv.mkDerivation {
name = "vs";
outputHashAlgo = "sha256";
outputHashMode = "recursive";
outputHash = "1ngq7mg02kzfysh559j3fkjh2hngmay4jjar55p2db4d9rkvqh22";
src = msvc-wine;
phases = [ "buildPhase" ];
buildInputs = [ pkgs.cacert (pkgs.python3.withPackages(ps: [ ps.simplejson ps.six ])) pkgs.msitools ];
buildPhase = "python $src/vsdownload.py --accept-license --dest $out";
};
in
''
win-put ${vs}/VC/Tools/MSVC 'C:\'
win-exec 'setx PATH C:\MSVC\14.26.28801\bin\Hostx64\x64;%PATH% /m'
'';
};
}

View File

@ -0,0 +1,40 @@
#!/usr/bin/env bash
set -e
nix-build -E "
let
pkgs = import <nixpkgs> {};
wfvm = import ../default.nix { inherit pkgs; };
in
wfvm.utils.wfvm-run {
name = \"get-msys-packages\";
image = wfvm.makeWindowsImage { installCommands = [ wfvm.layers.msys2 ]; };
script = ''
cat > getmsyspackages.bat << EOF
set MSYS=C:\\MSYS64
set TOOLPREF=mingw-w64-x86_64-
set PATH=%MSYS%\usr\bin;%MSYS%\mingw64\bin;%PATH%
pacman -Sp %TOOLPREF%gcc %TOOLPREF%binutils make autoconf automake libtool texinfo %TOOLPREF%make %TOOLPREF%cmake > packages.txt
EOF
\${wfvm.utils.win-put}/bin/win-put getmsyspackages.bat
\${wfvm.utils.win-exec}/bin/win-exec getmsyspackages
\${wfvm.utils.win-get}/bin/win-get packages.txt
'';
}
"
./result/bin/wfvm-run-get-msys-packages
echo "{ pkgs } : [" > msys_packages.nix
while read package; do
hash=$(nix-prefetch-url $package)
echo "
(pkgs.fetchurl {
url = \"$package\";
sha256 = \"$hash\";
})" >> msys_packages.nix
done < packages.txt
echo "]" >> msys_packages.nix
rm result getmsyspackages.bat packages.txt

View File

@ -0,0 +1,332 @@
{ pkgs } : [
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-libiconv-1.16-1-any.pkg.tar.xz";
sha256 = "0w8jkjr5gwybw9469216vs6vpibkq36wx47bbl4r0smi4wvh2yxk";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-zlib-1.2.11-7-any.pkg.tar.xz";
sha256 = "1hnfagn5m0ys4f8349d8dpbqvh9p900jjn83r7fi1az6i9dz1v0x";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-binutils-2.34-3-any.pkg.tar.zst";
sha256 = "0ahlwbg5ir89nbra407yrzsplib4cia9m0dggcqjw1i4bxi7ypj1";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-headers-git-8.0.0.5905.066f1b3c-1-any.pkg.tar.zst";
sha256 = "0sskg0vvgggs932i09ipm5rrllv6vdf1ai3d3fvbi5pxis1xc9g0";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-crt-git-8.0.0.5905.066f1b3c-1-any.pkg.tar.zst";
sha256 = "1sjizkvknivbjs962fqxcmjkgnrvhd1frq96cfj2fyzk5cz7kfx0";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-isl-0.22.1-1-any.pkg.tar.xz";
sha256 = "1nj7sj3hgxhziqs1l7k42ginl10w7iy1b753mwvqiczfs322hb90";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-gmp-6.2.0-1-any.pkg.tar.xz";
sha256 = "1l4qdxr8xp6xyxabwcf9b876db3rhj4v54zsvb4v1kwm3jrs7caw";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-mpfr-4.0.2-2-any.pkg.tar.xz";
sha256 = "0hriryx58bkk3sihnhd4i6966civ3hq8i68rnc9kjivk47wi49rj";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-mpc-1.1.0-1-any.pkg.tar.xz";
sha256 = "0x1kg178l6mf9ivdy71bci36h2a37vypg4jk3k7y31ks6i79zifp";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-libwinpthread-git-8.0.0.5906.c9a21571-1-any.pkg.tar.zst";
sha256 = "16aqi04drn252cxdh1brpbi4syn4bfjb84qk4xqbnffnpxpvv5ph";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-gcc-libs-10.1.0-3-any.pkg.tar.zst";
sha256 = "0bmkrb9x7z0azzxl3z08r6chcl0pbnaijar7cdjxb2nh7fbbdzzp";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-windows-default-manifest-6.4-3-any.pkg.tar.xz";
sha256 = "1kwxb3q2slgsg17lkd0dc9fjks5f205dgm79fj0xq0zmrsns83kc";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-winpthreads-git-8.0.0.5906.c9a21571-1-any.pkg.tar.zst";
sha256 = "17nq8gs1nnxgligdrp5n6h4pnk46xw0yhjk2hn6y12vvpn7iv05v";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-zstd-1.4.5-1-any.pkg.tar.zst";
sha256 = "1jfxzajmbvlap1c0v17s8dzwdx0fi8kyrkmgr6gw1snisgllifyh";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-gcc-10.1.0-3-any.pkg.tar.zst";
sha256 = "1gkcc6hh20glx4b96ldsnd70r8dbp460bxfznm9z2rwgr0mxb374";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/msys/x86_64/make-4.3-1-x86_64.pkg.tar.xz";
sha256 = "0bmgggw56gkx7dcd8simpi2lhgz98limikx8wm0cb8cn7awi9w82";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/msys/x86_64/m4-1.4.18-2-x86_64.pkg.tar.xz";
sha256 = "05x7myqwwxk3vfqmliwk5pfn0w04fnjh1sqafsynpb9hx0c563ji";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/msys/x86_64/diffutils-3.7-1-x86_64.pkg.tar.xz";
sha256 = "11qdxn4mr8a96palhp5jkam904fh77bsw5v7mslhnzag4cg3kybx";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/msys/x86_64/autoconf-2.69-5-any.pkg.tar.xz";
sha256 = "1fxvgbjnmmb7dvmssfxkiw151dfd1wzj04hf45zklmzs4h2kkwda";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/msys/x86_64/automake1.6-1.6.3-2-any.pkg.tar.xz";
sha256 = "0if4wrr1vm2f1zjjh6dpln97xc1l1052bcawzmndwfh561cfxqb6";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/msys/x86_64/automake1.7-1.7.9-2-any.pkg.tar.xz";
sha256 = "1mjhp1k4c0xm8hfm3yckqvfb4ablzgg8a87l7wxaq1mmmskjmhpq";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/msys/x86_64/automake1.8-1.8.5-3-any.pkg.tar.xz";
sha256 = "046bzr44ss0lglx9lzccj9li74arz632hyvz6l9fcp98dndr3qjk";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/msys/x86_64/automake1.9-1.9.6-2-any.pkg.tar.xz";
sha256 = "0bh0dldmrd46xhix5358nj9sgf298n4ap0y8dsl6rvjsb5c0l5hd";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/msys/x86_64/automake1.10-1.10.3-3-any.pkg.tar.xz";
sha256 = "0p26lkx5n1mmmw1y98bgwzbxfxkfa18fqxvkgsm60fznjig4dq61";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/msys/x86_64/automake1.11-1.11.6-3-any.pkg.tar.xz";
sha256 = "1cjkav2bskf9rdm8g3hsl2l7wz1lx8dfigwqib0xhm7n8i8gc560";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/msys/x86_64/automake1.12-1.12.6-3-any.pkg.tar.xz";
sha256 = "1c0h2lngfjjfvw0jkrfah1fs25k0vdm80hlxfjs912almh2yg5gv";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/msys/x86_64/automake1.13-1.13.4-4-any.pkg.tar.xz";
sha256 = "0mczn8hanqn3hxr104klb832b4cnzn44bbn7lvqfsbvvjpklv9ld";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/msys/x86_64/automake1.14-1.14.1-3-any.pkg.tar.xz";
sha256 = "04gjyfszyphxy7qc1rr8378ms9hql0sy8a1gyj0mvpbmgb0phgkp";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/msys/x86_64/automake1.15-1.15.1-1-any.pkg.tar.xz";
sha256 = "00n1f3c6fwznpm1f6xmj30q41ixw5vdg52yg48yvr4jswb78qf8q";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/msys/x86_64/automake1.16-1.16.1-1-any.pkg.tar.xz";
sha256 = "1ds8rpagrlkzi28n5rh0jcibbic49xssl2hz6sy41my0vd8a3z9y";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/msys/x86_64/automake-wrapper-11-1-any.pkg.tar.xz";
sha256 = "1dzymv59wri7qqmgmy5xfkq6zvfcb0znwspc149a04d0bhxs75gw";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/msys/x86_64/libltdl-2.4.6-9-x86_64.pkg.tar.xz";
sha256 = "0j0xazjpj28dib9vjn3paibhry77k903rzvbkdn6gnl20smj18g2";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/msys/x86_64/tar-1.32-1-x86_64.pkg.tar.xz";
sha256 = "0ynz2qwzbcmixcxddp05q2wc7iqli6svzkrjss9izrpmbkv5ifa5";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/msys/x86_64/libtool-2.4.6-9-x86_64.pkg.tar.xz";
sha256 = "0mrnkayrhmrgq446nyysvj3kadqm1xhyl97qqv6hrq57lhkcry2p";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/msys/x86_64/texinfo-6.7-1-x86_64.pkg.tar.xz";
sha256 = "0c50809yg9g95m8yib867q8m28sjabqppz2qbzh3gr83z55kknnw";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-expat-2.2.9-1-any.pkg.tar.xz";
sha256 = "16fz2r902mmc0kka3pm7g54xjd8x3q07bi7y54vzpbmic31rrvh4";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-gettext-0.19.8.1-8-any.pkg.tar.xz";
sha256 = "1g28871qgc66k4csmc4rk4vcajzw5wavicc2x3iw4pnigh9vsj83";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-make-4.3-1-any.pkg.tar.xz";
sha256 = "0v133ip1r3djcki5znn946r1c81vvyc6xk5xf35ad8b30wmlfqvq";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-pkg-config-0.29.2-1-any.pkg.tar.xz";
sha256 = "1w6s9nb7kjwnlz2vgimzvyjmay47d6g008c82xab4k8nhd7nm77n";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-c-ares-1.16.1-1-any.pkg.tar.zst";
sha256 = "13sfv0cs4rj3vw4y9pibp02qvvcv5qnzs87282m7pxxnjzccv9an";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-brotli-1.0.7-4-any.pkg.tar.xz";
sha256 = "02i5jxmwbvraszy5rm31gm6wi21vclzsbqq9rx4qxjdgjwgn4rfl";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-libunistring-0.9.10-1-any.pkg.tar.xz";
sha256 = "1q03qjyndbv65j0w71x41gc7nhdcbmdsc5xb882gmzlgwrdi77hq";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-libidn2-2.3.0-1-any.pkg.tar.xz";
sha256 = "06523dq5q3dq07iz6f11pwk3b4v18z3b72ly3wvxl0kdy89khqjj";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-libmetalink-0.1.3-3-any.pkg.tar.xz";
sha256 = "1nvjvygcxmrb7xlqzxym3g6vhz31nr83qx2vfsqrc0haw4r08d5j";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-libpsl-0.21.0-2-any.pkg.tar.xz";
sha256 = "13456p4kl53i49hz6b9cpjbkb19k4443nksbii9c29x09lagbzwv";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-libtasn1-4.16.0-1-any.pkg.tar.xz";
sha256 = "0aziyg127l9742g7i8dl4ffp80v55272i8p3jqk3pvz8qaf8dfyh";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-libffi-3.3-1-any.pkg.tar.xz";
sha256 = "05sh8hwr171bbpjw9yf4z04sa3m4dg37kqbdz90y68glrj43i4xd";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-p11-kit-0.23.20-2-any.pkg.tar.xz";
sha256 = "02f3k46b09b4rd0fmadavjj04f4a2v1c56r9qlkr5lkjlmfm7a5a";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-ca-certificates-20190110-1-any.pkg.tar.xz";
sha256 = "1wjbm67rb07sp803dl51lfsrrih2xjnwbrif0hvsc6nq63q1i3dq";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-openssl-1.1.1.g-1-any.pkg.tar.xz";
sha256 = "047x6dxxqm8y8fj236cd3p9jk4cdnmzdp3pgh84gsqa2vgxdn64f";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-libssh2-1.9.0-1-any.pkg.tar.xz";
sha256 = "10pd4mmvsrvcs4sw0v786ry3w2xwrli6prnhpwcjfjvb25jn0y9a";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-jansson-2.12-1-any.pkg.tar.xz";
sha256 = "133al0y3fg38b303934ls7f7l5f76qy7v6wx2cnxmfq2k0fxj7cc";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-jemalloc-5.2.1-1-any.pkg.tar.xz";
sha256 = "1w0mm0wlsx37gbf5vcrbf7c4hvkcrhls8a1aiq3s4vbld8maccdl";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-nghttp2-1.40.0-2-any.pkg.tar.xz";
sha256 = "0m2xww09f5j8ii6nqk8wz6g8dy1qbgvv185ikrpabpbdaqgkaijj";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-curl-7.70.0-1-any.pkg.tar.zst";
sha256 = "013b04dxcfgcbx9ccknm8rkkxp5lxzi2473li678f0n1dagcxn0d";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-jsoncpp-1.9.2-1-any.pkg.tar.xz";
sha256 = "0wdxn26lv9j9fdixcvgbg299wix9xxl48jjdnqf1387aiprhsj4m";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-bzip2-1.0.8-1-any.pkg.tar.xz";
sha256 = "1ipndg1lg96hfznhcv8ifazv07944vk387i35rzaaamac2hm7nyf";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-lz4-1.9.2-1-any.pkg.tar.xz";
sha256 = "067rm6fjziid747b9lzng4hpzlddqq8d2xfrxd95nzvj4qrj1xli";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-libtre-git-r128.6fb7206-2-any.pkg.tar.xz";
sha256 = "0dp3ca83j8jlx32gml2qvqpwp5b42q8r98gf6hyiki45d910wb7x";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-libsystre-1.0.1-4-any.pkg.tar.xz";
sha256 = "037gkzaaj8kp5nspcbc8ll64s9b3mj8d6m663lk1za94bq2axff1";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-nettle-3.6-1-any.pkg.tar.zst";
sha256 = "1m5kakcfmwvmvajblscq541b40f5zhc01hqgvwlcgpdm4c1mjxhx";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-xz-5.2.5-1-any.pkg.tar.xz";
sha256 = "09h7qpy8nrrk3z9fh31k9jc17449qs9cf5v183rz6v6526x3v7jg";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-libarchive-3.4.3-1-any.pkg.tar.zst";
sha256 = "1c9wxa9i1hm1yvv82qdzc1pqgrw3gcfc0s9wjah7w1civ9a63flf";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-libuv-1.38.0-1-any.pkg.tar.zst";
sha256 = "1x9vz2ib8mgx0g2gxjmyshdcf1qgql0d6hycyh4xf7ns4zk70mh0";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-rhash-1.3.9-1-any.pkg.tar.xz";
sha256 = "1a5b1wvljbdn38jcw2w46mcw377aw8k7j93fxsjzghhf9msscl1a";
})
(pkgs.fetchurl {
url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-cmake-3.17.3-1-any.pkg.tar.zst";
sha256 = "0b9zaa11qazsgz88yfm6j93rddnw8mz9zzh8maz3vrmi9p4asldd";
})
]

View File

@ -0,0 +1 @@
This file is not publicaly acessible anywhere so had to be extracted from a connected instance

Binary file not shown.

98
artiq-fast/wfvm/utils.nix Normal file
View File

@ -0,0 +1,98 @@
{ pkgs, baseRtc ? "2020-04-20T14:21:42", cores ? "4", qemuMem ? "4G" }:
rec {
# qemu_test is a smaller closure only building for a single system arch
qemu = pkgs.qemu_test;
mkQemuFlags = extraFlags: [
"-enable-kvm"
"-cpu host"
"-smp ${cores}"
"-m ${qemuMem}"
"-bios ${pkgs.OVMF.fd}/FV/OVMF.fd"
"-vga virtio"
"-rtc base=${baseRtc}"
"-device piix3-usb-uhci"
"-device e1000,netdev=n1"
] ++ extraFlags;
# Pass empty config file to prevent ssh from failing to create ~/.ssh
sshOpts = "-F /dev/null -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=1";
win-exec = pkgs.writeShellScriptBin "win-exec" ''
${pkgs.sshpass}/bin/sshpass -p1234 -- \
${pkgs.openssh}/bin/ssh -np 2022 ${sshOpts} \
wfvm@localhost \
$1
'';
win-wait = pkgs.writeShellScriptBin "win-wait" ''
# If the machine is not up within 10 minutes it's likely never coming up
timeout=600
# Wait for VM to be accessible
sleep 20
echo "Waiting for SSH..."
while true; do
if test "$timeout" -eq 0; then
echo "SSH connection timed out"
exit 1
fi
output=$(${win-exec}/bin/win-exec 'echo|set /p="Ran command"' || echo "")
if test "$output" = "Ran command"; then
break
fi
echo "Retrying in 1 second, timing out in $timeout seconds"
((timeout=$timeout-1))
sleep 1
done
echo "SSH OK"
'';
win-put = pkgs.writeShellScriptBin "win-put" ''
echo win-put $1 -\> $2
${pkgs.sshpass}/bin/sshpass -p1234 -- \
${pkgs.openssh}/bin/scp -r -P 2022 ${sshOpts} \
$1 wfvm@localhost:$2
'';
win-get = pkgs.writeShellScriptBin "win-get" ''
echo win-get $1
${pkgs.sshpass}/bin/sshpass -p1234 -- \
${pkgs.openssh}/bin/scp -r -T -P 2022 ${sshOpts} \
wfvm@localhost:$1 .
'';
wfvm-run = { name, image, script, display ? false, isolateNetwork ? true, forwardedPorts ? [] }:
let
restrict =
if isolateNetwork
then "on"
else "off";
# use socat instead of `tcp:...` to allow multiple connections
guestfwds =
builtins.concatStringsSep ""
(map ({ listenAddr, targetAddr, port }:
",guestfwd=tcp:${listenAddr}:${toString port}-cmd:${pkgs.socat}/bin/socat\\ -\\ tcp:${targetAddr}:${toString port}"
) forwardedPorts);
qemuParams = mkQemuFlags (pkgs.lib.optional (!display) "-display none" ++ [
"-drive"
"file=${image},index=0,media=disk,cache=unsafe"
"-snapshot"
"-netdev user,id=n1,net=192.168.1.0/24,restrict=${restrict},hostfwd=tcp::2022-:22${guestfwds}"
]);
in pkgs.writeShellScriptBin "wfvm-run-${name}" ''
set -m
${qemu}/bin/qemu-system-x86_64 ${pkgs.lib.concatStringsSep " " qemuParams} &
${win-wait}/bin/win-wait
${script}
echo "Shutting down..."
${win-exec}/bin/win-exec 'shutdown /s'
echo "Waiting for VM to terminate..."
fg
echo "Done"
'';
}

163
artiq-fast/wfvm/win.nix Normal file
View File

@ -0,0 +1,163 @@
{ pkgs
, diskImageSize ? "22G"
, windowsImage ? null
, autoUnattendParams ? {}
, impureMode ? false
, installCommands ? []
, users ? {}
, ...
}@attrs:
let
lib = pkgs.lib;
utils = import ./utils.nix { inherit pkgs; };
libguestfs = pkgs.libguestfs-with-appliance;
# p7zip on >20.03 has known vulns but we have no better option
p7zip = pkgs.p7zip.overrideAttrs(old: {
meta = old.meta // {
knownVulnerabilities = [];
};
});
runQemuCommand = name: command: (
pkgs.runCommandNoCC name { buildInputs = [ p7zip utils.qemu libguestfs ]; }
(
''
if ! test -f; then
echo "KVM not available, bailing out" >> /dev/stderr
exit 1
fi
'' + command
)
);
windowsIso = if windowsImage != null then windowsImage else pkgs.fetchurl {
url = "https://software-download.microsoft.com/download/sg/17763.107.101029-1455.rs5_release_svc_refresh_CLIENT_LTSC_EVAL_x64FRE_en-us.iso";
sha256 = "668fe1af70c2f7416328aee3a0bb066b12dc6bbd2576f40f812b95741e18bc3a";
};
openSshServerPackage = ./openssh/server-package.cab;
autounattend = import ./autounattend.nix (
attrs // {
inherit pkgs;
users = users // {
wfvm = {
password = "1234";
description = "WFVM Administrator";
groups = [
"Administrators"
];
};
};
}
);
bundleInstaller = pkgs.callPackage ./bundle {};
# Packages required to drive installation of other packages
bootstrapPkgs =
runQemuCommand "bootstrap-win-pkgs.img" ''
mkdir -p pkgs/fod
cp ${bundleInstaller} pkgs/"$(stripHash "${bundleInstaller}")"
# Install optional windows features
cp ${openSshServerPackage} pkgs/fod/OpenSSH-Server-Package~31bf3856ad364e35~amd64~~.cab
# SSH setup script goes here because windows XML parser sucks
cp ${autounattend.setupScript} pkgs/ssh-setup.ps1
virt-make-fs --partition --type=fat pkgs/ $out
'';
installScript = pkgs.writeScript "windows-install-script" (
let
qemuParams = utils.mkQemuFlags (lib.optional (!impureMode) "-display none" ++ [
# "CD" drive with bootstrap pkgs
"-drive"
"id=virtio-win,file=${bootstrapPkgs},if=none,format=raw,readonly=on"
"-device"
"usb-storage,drive=virtio-win"
# USB boot
"-drive"
"id=win-install,file=usbimage.img,if=none,format=raw,readonly=on"
"-device"
"usb-storage,drive=win-install"
# Output image
"-drive"
"file=c.img,index=0,media=disk,cache=unsafe"
# Network
"-netdev user,id=n1,net=192.168.1.0/24,restrict=on"
]);
in
''
#!${pkgs.runtimeShell}
set -euxo pipefail
export PATH=${lib.makeBinPath [ p7zip utils.qemu libguestfs ]}:$PATH
# Create a bootable "USB" image
# Booting in USB mode circumvents the "press any key to boot from cdrom" prompt
#
# Also embed the autounattend answer file in this image
mkdir -p win
mkdir -p win/nix-win
7z x -y ${windowsIso} -owin
cp ${autounattend.autounattendXML} win/autounattend.xml
virt-make-fs --partition --type=fat win/ usbimage.img
rm -rf win
# Qemu requires files to be rw
qemu-img create -f qcow2 c.img ${diskImageSize}
qemu-system-x86_64 ${lib.concatStringsSep " " qemuParams}
''
);
baseImage = pkgs.runCommandNoCC "windows.img" {} ''
${installScript}
mv c.img $out
'';
finalImage = builtins.foldl' (acc: v: pkgs.runCommandNoCC "${v.name}.img" {
buildInputs = with utils; [
qemu win-wait win-exec win-put
] ++ (v.buildInputs or []);
} (let
script = pkgs.writeScript "${v.name}-script" v.script;
qemuParams = utils.mkQemuFlags (lib.optional (!impureMode) "-display none" ++ [
# Output image
"-drive"
"file=c.img,index=0,media=disk,cache=unsafe"
# Network - enable SSH forwarding
"-netdev user,id=n1,net=192.168.1.0/24,restrict=on,hostfwd=tcp::2022-:22"
]);
in ''
# Create an image referencing the previous image in the chain
qemu-img create -f qcow2 -b ${acc} c.img
set -m
qemu-system-x86_64 ${lib.concatStringsSep " " qemuParams} &
win-wait
echo "Executing script to build layer..."
${script}
echo "Layer script done"
echo "Shutting down..."
win-exec 'shutdown /s'
echo "Waiting for VM to terminate..."
fg
echo "Done"
mv c.img $out
'')) baseImage installCommands;
in
# impureMode is meant for debugging the base image, not the full incremental build process
if !(impureMode) then finalImage else assert installCommands == []; installScript

View File

@ -0,0 +1,26 @@
# Preparation steps
## Install a Windows image
1. Adjust build.nix accordingly
2. Run:
If in impure mode
```shell
nix-build build.nix
./result
```
Results in a file called c.img
If in pure mode
```shell
nix-build build.nix
ls -la ./result
```
Results in a symlink to the image in the nix store
# Impure/pure mode
Sometimes it can be useful to build the image _outside_ of the Nix sandbox for debugging purposes.
For this purpose we have an attribute called `impureMode` which outputs the shell script used by Nix inside the sandbox to build the image.

View File

@ -0,0 +1,318 @@
{ pkgs
, lib ? pkgs.lib
, fullName
, organization
, administratorPassword
, uiLanguage ? "en-US"
, inputLocale ? "en-US"
, userLocale ? "en-US"
, systemLocale ? "en-US"
, users ? {}
, productKey ? null
, defaultUser ? null
, setupCommands ? []
, timeZone ? "UTC"
, services ? {}
, impureShellCommands ? []
, driveLetter ? "E:"
, ...
}:
let
serviceCommands = lib.mapAttrsToList (
serviceName: attrs: "powershell Set-Service -Name ${serviceName} " + (
lib.concatStringsSep " " (
(
lib.mapAttrsToList (
n: v: if builtins.typeOf v != "bool" then "-${n} ${v}" else "-${n}"
)
) (
# Always run without interaction
{ Force = true; } // attrs
)
)
)
) services;
sshSetupCommands =
# let
# makeDirs = lib.mapAttrsToList (n: v: ''mkdir C:\Users\${n}\.ssh'') users;
# writeKeys = lib.flatten (lib.mapAttrsToList (n: v: builtins.map (key: let
# commands = [
# ''powershell.exe Set-Content -Path C:\Users\${n}\.ssh\authorized_keys -Value '${key}' ''
# ];
# in lib.concatStringsSep "\n" commands) (v.sshKeys or [])) users);
# mkDirsDesc = builtins.map (c: {Path = c; Description = "Make SSH key dir";}) makeDirs;
# writeKeysDesc = builtins.map (c: {Path = c; Description = "Add SSH key";}) writeKeys;
# in
# mkDirsDesc ++ writeKeysDesc ++
[
{
Path = ''powershell.exe Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0 -Source ${driveLetter}\fod -LimitAccess'';
Description = "Add OpenSSH service.";
}
{
Path = ''powershell.exe Set-Service -Name sshd -StartupType Automatic'';
Description = "Enable SSH by default.";
}
];
assertCommand = c: builtins.typeOf c == "string" || builtins.typeOf c == "set" && builtins.hasAttr "Path" c && builtins.hasAttr "Description" c;
commands = builtins.map (x: assert assertCommand x; if builtins.typeOf x == "string" then { Path = x; Description = x; } else x) (
[
{
Path = "powershell.exe Set-ExecutionPolicy -Force Unrestricted";
Description = "Allow unsigned powershell scripts.";
}
]
++ [
{
Path = ''powershell.exe ${driveLetter}\win-bundle-installer.exe'';
Description = "Install any declared packages.";
}
]
++ setupCommands
++ [
{
Path = ''powershell.exe ${driveLetter}\ssh-setup.ps1'';
Description = "Setup SSH and keys";
}
]
++ serviceCommands
++ impureShellCommands
);
mkCommand = attrs: ''
<RunSynchronousCommand wcm:action="add">
${lib.concatStringsSep "\n" (lib.attrsets.mapAttrsToList (n: v: "<${n}>${v}</${n}>") attrs)}
</RunSynchronousCommand>
'';
mkCommands = commands: (
builtins.foldl' (
acc: v: rec {
i = acc.i + 1;
values = acc.values ++ [ (mkCommand (v // { Order = builtins.toString i; })) ];
}
) {
i = 0;
values = [];
} commands
).values;
mkUser =
{ name
, password
, description ? ""
, displayName ? ""
, groups ? []
# , sshKeys ? [] # Handled in scripts
}: ''
<LocalAccount wcm:action="add">
<Password>
<Value>${password}</Value>
<PlainText>true</PlainText>
</Password>
<Description>${description}</Description>
<DisplayName>${displayName}</DisplayName>
<Group>${builtins.concatStringsSep ";" (lib.unique ([ "Users" ] ++ groups))}</Group>
<Name>${name}</Name>
</LocalAccount>
'';
# Windows expects a flat list of users while we want to manage them as a set
flatUsers = builtins.attrValues (builtins.mapAttrs (name: s: s // { inherit name; }) users);
autounattendXML = pkgs.writeText "autounattend.xml" ''
<?xml version="1.0" encoding="utf-8"?>
<unattend xmlns="urn:schemas-microsoft-com:unattend">
<settings pass="windowsPE">
<component name="Microsoft-Windows-PnpCustomizationsWinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<DriverPaths>
<PathAndCredentials wcm:action="add" wcm:keyValue="1">
<Path>D:\</Path>
</PathAndCredentials>
<PathAndCredentials wcm:action="add" wcm:keyValue="2">
<Path>E:\</Path>
</PathAndCredentials>
</DriverPaths>
</component>
<component name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<DiskConfiguration>
<Disk wcm:action="add">
<CreatePartitions>
<CreatePartition wcm:action="add">
<Order>1</Order>
<Type>EFI</Type>
<Size>100</Size>
</CreatePartition>
<CreatePartition wcm:action="add">
<Order>2</Order>
<Type>MSR</Type>
<Size>16</Size>
</CreatePartition>
<CreatePartition wcm:action="add">
<Order>3</Order>
<Type>Primary</Type>
<Extend>true</Extend>
</CreatePartition>
</CreatePartitions>
<ModifyPartitions>
<ModifyPartition wcm:action="add">
<Order>1</Order>
<Format>FAT32</Format>
<Label>System</Label>
<PartitionID>1</PartitionID>
</ModifyPartition>
<ModifyPartition wcm:action="add">
<Order>2</Order>
<PartitionID>2</PartitionID>
</ModifyPartition>
<ModifyPartition wcm:action="add">
<Order>3</Order>
<Format>NTFS</Format>
<Label>Windows</Label>
<Letter>C</Letter>
<PartitionID>3</PartitionID>
</ModifyPartition>
</ModifyPartitions>
<DiskID>0</DiskID>
<WillWipeDisk>true</WillWipeDisk>
</Disk>
</DiskConfiguration>
<ImageInstall>
<OSImage>
<InstallTo>
<DiskID>0</DiskID>
<PartitionID>3</PartitionID>
</InstallTo>
<InstallFrom>
<MetaData wcm:action="add">
<Key>/IMAGE/INDEX</Key>
<Value>1</Value>
</MetaData>
</InstallFrom>
</OSImage>
</ImageInstall>
<UserData>
<ProductKey>
${if productKey != null then "<Key>${productKey}</Key>" else ""}
<WillShowUI>OnError</WillShowUI>
</ProductKey>
<AcceptEula>true</AcceptEula>
<FullName>${fullName}</FullName>
<Organization>${organization}</Organization>
</UserData>
</component>
<component name="Microsoft-Windows-International-Core-WinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SetupUILanguage>
<UILanguage>${uiLanguage}</UILanguage>
</SetupUILanguage>
<InputLocale>${inputLocale}</InputLocale>
<SystemLocale>${systemLocale}</SystemLocale>
<UILanguage>${uiLanguage}</UILanguage>
<UILanguageFallback>en-US</UILanguageFallback>
<UserLocale>${userLocale}</UserLocale>
</component>
</settings>
<settings pass="oobeSystem">
<component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<InputLocale>${inputLocale}</InputLocale>
<SystemLocale>${systemLocale}</SystemLocale>
<UILanguage>${uiLanguage}</UILanguage>
<UILanguageFallback>en-US</UILanguageFallback>
<UserLocale>${userLocale}</UserLocale>
</component>
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<OOBE>
<HideEULAPage>true</HideEULAPage>
<HideLocalAccountScreen>true</HideLocalAccountScreen>
<HideOEMRegistrationScreen>true</HideOEMRegistrationScreen>
<HideOnlineAccountScreens>true</HideOnlineAccountScreens>
<HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
<ProtectYourPC>1</ProtectYourPC>
</OOBE>
<TimeZone>${timeZone}</TimeZone>
<UserAccounts>
${if administratorPassword != null then ''
<AdministratorPassword>
<Value>${administratorPassword}</Value>
<PlainText>true</PlainText>
</AdministratorPassword>
'' else ""}
<LocalAccounts>
${builtins.concatStringsSep "\n" (builtins.map mkUser flatUsers)}
</LocalAccounts>
</UserAccounts>
${if defaultUser == null then "" else ''
<AutoLogon>
<Password>
<Value>${(builtins.getAttr defaultUser users).password}</Value>
<PlainText>true</PlainText>
</Password>
<Enabled>true</Enabled>
<Username>${defaultUser}</Username>
</AutoLogon>
''}
<FirstLogonCommands>
<SynchronousCommand wcm:action="add">
<Order>1</Order>
<CommandLine>cmd /C shutdown /s /f /t 00</CommandLine>
<Description>ChangeHideFiles</Description>
</SynchronousCommand>
</FirstLogonCommands>
</component>
</settings>
<settings pass="specialize">
<component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<RunSynchronous>
${lib.concatStringsSep "\n" (mkCommands commands)}
</RunSynchronous>
</component>
<component name="Microsoft-Windows-SQMApi" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="NonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<CEIPEnabled>0</CEIPEnabled>
</component>
</settings>
<!-- Disable Windows UAC -->
<settings pass="offlineServicing">
<component name="Microsoft-Windows-LUA-Settings" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<EnableLUA>false</EnableLUA>
</component>
</settings>
<cpi:offlineImage cpi:source="wim:c:/wim/windows-10/install.wim#Windows 10 Enterprise LTSC 2019 Evaluation" xmlns:cpi="urn:schemas-microsoft-com:cpi" />
</unattend>
'';
in {
# Lint and format as a sanity check
autounattendXML = pkgs.runCommandNoCC "autounattend.xml" {} ''
${pkgs.libxml2}/bin/xmllint --format ${autounattendXML} > $out
'';
# autounattend.xml is _super_ picky about quotes and other things
setupScript = pkgs.writeText "ssh-setup.ps1" (
''
# Setup SSH and keys
'' +
lib.concatStrings (
builtins.map (c: ''
# ${c.Description}
${c.Path}
'') sshSetupCommands
)
);
}

View File

@ -0,0 +1,100 @@
{
pkgs ? import <nixpkgs> {}
, impureMode ? false
}:
let
win = (import ./default.nix { inherit pkgs; });
in
win.makeWindowsImage {
# Custom base iso
# windowsImage = pkgs.fetchurl {
# url = "https://software-download.microsoft.com/download/sg/17763.107.101029-1455.rs5_release_svc_refresh_CLIENT_LTSC_EVAL_x64FRE_en-us.iso";
# sha256 = "668fe1af70c2f7416328aee3a0bb066b12dc6bbd2576f40f812b95741e18bc3a";
# };
# User accounts
users = {
artiq = {
password = "1234";
# description = "Default user";
# displayName = "Display name";
groups = [
"Administrators"
];
};
};
# Build install script & skip building iso
inherit impureMode;
# impureShellCommands = [
# "powershell.exe echo Hello"
# ];
fullName = "M-Labs";
organization = "m-labs";
administratorPassword = "12345";
# Auto login
defaultUser = "artiq";
# Imperative installation commands, to be installed incrementally
installCommands = [
{
name = "Anaconda3";
script = let
Anaconda3 = pkgs.fetchurl {
name = "Anaconda3.exe";
url = "https://repo.anaconda.com/archive/Anaconda3-2019.03-Windows-x86_64.exe";
sha256 = "1f9icm5rwab6l1f23a70dw0qixzrl62wbglimip82h4zhxlh3jfj";
};
in ''
cp ${Anaconda3} ./Anaconda3.exe
win put Anaconda3.exe 'C:\Users\artiq'
win exec 'start /wait "" .\Anaconda3.exe /S /D=%UserProfile%\Anaconda3'
'';
}
];
# services = {
# # Enable remote management
# WinRm = {
# Status = "Running";
# PassThru = true;
# };
# };
# License key
# productKey = "iboughtthisone";
# Locales
# uiLanguage = "en-US";
# inputLocale = "en-US";
# userLocale = "en-US";
# systemLocale = "en-US";
# packages = [
# (
# win.pkgs.makeMSIPkg {
# # Note: File not in repository, it's meant as an example to subsitute
# name = "notepadplusplus";
# msi = ./Notepad++7.7.msi;
# # Custom cert
# # cert = ./notepad++-cert.cer
# }
# )
# (
# win.pkgs.makeCrossPkg {
# name = "hello";
# pkg = pkgs.pkgsCross.mingwW64.hello;
# }
# )
# ];
}

View File

@ -0,0 +1 @@
use nix

View File

@ -0,0 +1,9 @@
{ pkgs ? import <nixpkgs> {}
, lib ? pkgs.lib
}:
pkgs.runCommandNoCC "win-bundle-installer.exe" {} ''
cp ${./main.go} main.go
env HOME=$(mktemp -d) GOOS=windows GOARCH=amd64 ${pkgs.go}/bin/go build
mv build.exe $out
''

View File

@ -0,0 +1,116 @@
package main
import (
"archive/tar"
"fmt"
"io"
"io/ioutil"
"log"
"os"
"os/exec"
"path/filepath"
)
func Untar(dst string, r io.Reader) error {
tr := tar.NewReader(r)
for {
header, err := tr.Next()
switch {
case err == io.EOF:
return nil
case err != nil:
return err
case header == nil:
continue
}
target := filepath.Join(dst, header.Name)
switch header.Typeflag {
case tar.TypeDir:
if _, err := os.Stat(target); err != nil {
if err := os.MkdirAll(target, 0755); err != nil {
return err
}
}
case tar.TypeReg:
f, err := os.OpenFile(target, os.O_CREATE|os.O_RDWR, os.FileMode(header.Mode))
if err != nil {
return err
}
if _, err := io.Copy(f, tr); err != nil {
return err
}
f.Close()
}
}
}
func InstallBundle(bundlePath string) error {
reader, err := os.Open(bundlePath)
if err != nil {
log.Fatal(err)
}
workDir, err := ioutil.TempDir("", "bundle_install")
if err != nil {
return err
}
defer os.RemoveAll(workDir)
err = Untar(workDir, reader)
if err != nil {
return err
}
installScript := filepath.Join(workDir, "install.ps1")
cmd := exec.Command("powershell", installScript)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Dir = workDir
err = cmd.Run()
return err
}
func main() {
// Get path relative to binary
baseDir, err := filepath.Abs(filepath.Dir(os.Args[0]))
if err != nil {
log.Fatal(err)
}
var dirs = [2]string{"bootstrap", "user"}
for _, pkgDir := range dirs {
dir := filepath.Join(baseDir, pkgDir)
files, err := ioutil.ReadDir(dir)
if err != nil {
log.Fatal(err)
}
for _, file := range files {
bundle := filepath.Join(dir, file.Name())
fmt.Println(fmt.Sprintf("Installing: %s", bundle))
err := InstallBundle(bundle)
if err != nil {
log.Fatal(err)
}
}
}
}

View File

@ -0,0 +1,13 @@
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
buildInputs = [
pkgs.go
];
shellHook = ''
unset GOPATH
'';
}

View File

@ -0,0 +1,7 @@
{ pkgs ? import <nixpkgs> {}
}:
{
makeWindowsImage = attrs: import ./win.nix ({ inherit pkgs; } // attrs);
pkgs = import ./pkgs.nix { inherit pkgs; };
}

View File

@ -0,0 +1,97 @@
{ pkgs ? import <nixpkgs> {}
, diskImageSize ? "22G"
, qemuMem ? "4G"
,
}:
with pkgs;
let
windowsIso = fetchurl {
url = "https://software-download.microsoft.com/download/sg/17763.107.101029-1455.rs5_release_svc_refresh_CLIENT_LTSC_EVAL_x64FRE_en-us.iso";
sha256 = "668fe1af70c2f7416328aee3a0bb066b12dc6bbd2576f40f812b95741e18bc3a";
};
anaconda = fetchurl {
url = "https://repo.anaconda.com/archive/Anaconda3-2019.03-Windows-x86_64.exe";
sha256 = "1f9icm5rwab6l1f23a70dw0qixzrl62wbglimip82h4zhxlh3jfj";
};
escape = builtins.replaceStrings [ "\\" ] [ "\\\\" ];
qemu = import ./qemu.nix {
inherit pkgs qemuMem;
diskImage = "c.img";
};
# Double-escape because we produce a script from a shell heredoc
ssh = cmd: qemu.ssh (escape cmd);
scp = qemu.scp;
sshCondaEnv = cmd: ssh "anaconda\\scripts\\activate && ${cmd}";
condaEnv = "artiq-env";
condaDepSpecs =
builtins.concatStringsSep " "
(map (s: "\"${s}\"")
(import ../conda/artiq-deps.nix));
instructions =
builtins.toFile "install.txt"
(builtins.readFile ./install.txt);
in
stdenv.mkDerivation {
name = "windows-installer";
src = windowsIso;
setSourceRoot = "sourceRoot=`pwd`";
unpackCmd = ''
ln -s $curSrc windows.iso
'';
propagatedBuildInputs = qemu.inputs;
dontBuild = true;
installPhase = ''
mkdir -p $out/bin $out/data
ln -s $(readlink windows.iso) $out/data/windows.iso
cat > $out/bin/windows-installer.sh << EOF
#!/usr/bin/env bash
set -e -m
${qemu.qemu-img} create -f qcow2 c.img ${diskImageSize}
${qemu.runQemu false [] [
"-boot"
"order=d"
"-drive"
"file=c.img,index=0,media=disk,cache=unsafe"
"-drive"
"file=$out/data/windows.iso,index=1,media=cdrom,cache=unsafe"
]} &
cat ${instructions}
wait
EOF
cat > $out/bin/anaconda-installer.sh << EOF
#!/usr/bin/env bash
set -e -m
${qemu.runQemu false [] [
"-boot"
"order=c"
"-drive"
"file=c.img,index=0,media=disk"
]} &
sleep 10
${ssh "ver"}
${scp anaconda "Anaconda.exe"}
${ssh "start /wait \"\" Anaconda.exe /S /D=%cd%\\anaconda"}
${sshCondaEnv "conda config --add channels conda-forge"}
${sshCondaEnv "conda config --add channels m-labs"}
( ${sshCondaEnv "conda update -y conda"} ) || true
${sshCondaEnv "conda update -y --all"}
${sshCondaEnv "conda create -y -n ${condaEnv}"}
${sshCondaEnv "conda install -y -n ${condaEnv} ${condaDepSpecs}"}
${ssh "shutdown /p /f"}
echo "Waiting for qemu exit"
wait
EOF
chmod a+x $out/bin/*.sh
'';
}

View File

@ -0,0 +1,32 @@
# This runs `run-test.nix` with `nix-build`
{ pkgs ? import <nixpkgs> {}
, artiqpkgs ? import ../. { inherit pkgs; }
, diskImage ? (import ./build.nix { inherit pkgs; })
, qemuMem ? "2G"
, testTimeout ? 180
}:
with pkgs;
let
windowsRunner = overrides:
import ./run-test.nix (
{
inherit pkgs diskImage qemuMem testTimeout;
sipycoPkg = artiqpkgs.conda-sipyco;
artiqPkg = artiqpkgs.conda-artiq;
} // overrides
);
in
stdenv.mkDerivation {
name = "windows-test";
phases = [ "installPhase" "checkPhase" ];
installPhase = "touch $out";
doCheck = true;
checkPhase = ''
${windowsRunner { testCommand = "set ARTIQ_ROOT=%cd%\\anaconda\\envs\\artiq-env\\Lib\\site-packages\\artiq\\examples\\kc705_nist_clock&&python -m unittest discover -v artiq.test"; }}/bin/run.sh
'';
}

View File

@ -0,0 +1 @@
This file is not publicaly acessible anywhere so had to be extracted from a connected instance

Binary file not shown.

110
artiq-fast/windows/pkgs.nix Normal file
View File

@ -0,0 +1,110 @@
{ pkgs ? import <nixpkgs> {}
, lib ? pkgs.lib
}:
/*
This file creates a simple custom simple bundle format containing
a powershell script plus any required executables and assets.
These are assets that are only handled in the pure build steps.
Impure packages are installed in _another_ step that runs impurely outside of
the Nix sandbox.
*/
let
makeBundle =
{ name
, bundle
}: pkgs.runCommandNoCC "${name}-archive.tar" {} ''
cp -r -L ${bundle} build
tar -cpf $out -C build .
'';
in
rec {
/*
Make a custom install bundle
*/
makePkg =
{ name
, src
, installScript
}: let
installScript_ = pkgs.writeText "${name}-install-script" installScript;
bundle = pkgs.runCommandNoCC "${name}-bundle" {} ''
mkdir build
ln -s ${src} build/"$(stripHash "${src}")"
ln -s ${installScript_} build/install.ps1
mv build $out
'';
in
makeBundle {
inherit name bundle;
};
/*
Make an install bundle from a .msi
*/
makeMSIPkg =
{ name
, msi
, cert ? null
, ADDLOCAL ? []
, preInstall ? ""
, postInstall ? ""
}: let
installScript = pkgs.writeText "${name}-install-script" ''
${preInstall}
${if cert != null then "certutil.exe -f -addstore TrustedPublisher cert.cer" else ""}
msiexec.exe /i .\${name}.msi ${if ADDLOCAL != [] then "ADDLOCAL=" else ""}${lib.concatStringsSep "," ADDLOCAL}
${postInstall}
'';
bundle = pkgs.runCommandNoCC "${name}-bundle" {} ''
mkdir build
ln -s ${msi} build/${name}.msi
${if cert != null then "ln -s ${cert} build/cert.cer" else ""}
ln -s ${installScript} build/install.ps1
mv build $out
'';
in
makeBundle {
inherit name bundle;
};
/*
Nix cross-built packages
*/
makeCrossPkg =
{ name
, pkg
, destination ? ''C:\Program Files\${name}\''
, preInstall ? ""
, postInstall ? ""
}: let
installScript = pkgs.writeText "${name}-install-script" ''
${preInstall}
Copy-Item pkg -Destination "${destination}"
${postInstall}
'';
bundle = pkgs.runCommandNoCC "${name}-bundle" {} ''
mkdir -p build/pkg
ln -s ${pkg} build/pkg
ln -s ${installScript} build/install.ps1
mv build $out
'';
in
makeBundle {
inherit name bundle;
};
}

View File

@ -0,0 +1,63 @@
{ pkgs
, qemuMem
, sshUser ? "user"
, sshPassword ? "user"
,
}:
with pkgs;
let
qemu-img = "${qemu_kvm}/bin/qemu-img";
runQemu = isolateNetwork: forwardedPorts: extraArgs:
let
restrict =
if isolateNetwork
then "on"
else "off";
# use socat instead of `tcp:…` to allow multiple connections
guestfwds =
builtins.concatStringsSep ""
(
map (
{ listenAddr, targetAddr, port }:
",guestfwd=tcp:${listenAddr}:${toString port}-cmd:${socat}/bin/socat\\ -\\ tcp:${targetAddr}:${toString port}"
) forwardedPorts
);
args = [
#"-enable-kvm"
"-m"
qemuMem
"-bios"
"${OVMF.fd}/FV/OVMF.fd"
"-netdev"
"user,id=n1,net=192.168.1.0/24,restrict=${restrict},hostfwd=tcp::2022-:22${guestfwds}"
"-device"
"e1000,netdev=n1"
];
argStr = builtins.concatStringsSep " " (args ++ extraArgs);
in
"${qemu_kvm}/bin/qemu-system-x86_64 ${argStr}";
# Pass empty config file to prevent ssh from failing to create ~/.ssh
sshOpts = "-F /dev/null -o StrictHostKeyChecking=accept-new -o UserKnownHostsFile=\$TMP/known_hosts";
sshWithQuotes = quotes: cmd: ''
echo ssh windows ${quotes}${cmd}${quotes}
${sshpass}/bin/sshpass -p${sshPassword} -- \
${openssh}/bin/ssh -np 2022 ${sshOpts} \
${sshUser}@localhost \
${quotes}${cmd}${quotes}
'';
ssh = sshWithQuotes "'";
scp = src: target: ''
echo "Copy ${src} to ${target}"
${sshpass}/bin/sshpass -p${sshPassword} -- \
${openssh}/bin/scp -P 2022 ${sshOpts} \
"${src}" "${sshUser}@localhost:${target}"
'';
in
{
inherit qemu-img runQemu ssh sshWithQuotes scp;
inputs = [ qemu_kvm openssh sshpass ];
}

View File

@ -0,0 +1,91 @@
{ pkgs
, sipycoPkg
, artiqPkg
, diskImage ? (import ./build.nix { inherit pkgs; })
, qemuMem ? "2G"
, testTimeout ? 600
, testCommand ? "python -m unittest discover -v sipyco.test && python -m unittest discover -v artiq.test"
,
}:
with pkgs;
let
escape = builtins.replaceStrings [ "\\" ] [ "\\\\" ];
qemu = import ./qemu.nix {
inherit pkgs qemuMem;
};
# Double-escape because we produce a script from a shell heredoc
ssh = cmd: qemu.ssh (escape cmd);
sshUnquoted = qemu.sshWithQuotes "\"";
scp = qemu.scp;
condaEnv = "artiq-env";
tcpPorts = [ 1380 1381 1382 1383 ];
forwardedPorts =
map (
port: {
listenAddr = "192.168.1.50";
targetAddr = "192.168.1.50";
inherit port;
}
) tcpPorts;
in
stdenv.mkDerivation {
name = "windows-test-runner";
# Dummy sources
src = pkgs.runCommandNoCC "dummy" {} "touch $out";
dontUnpack = true;
propagatedBuildInputs = qemu.inputs;
dontBuild = true;
installPhase = ''
mkdir -p $out/bin
cat > $out/bin/run.sh << EOF
#!/usr/bin/env bash
set -e -m
cp ${diskImage} c.img
${qemu.runQemu true forwardedPorts [
"-boot"
"order=c"
"-snapshot"
"-drive"
"file=c.img,index=0,media=disk,cache=unsafe"
"-display"
"none"
]} &
echo "Wait for Windows to boot"
sleep 30
${ssh "ver"}
i=0
for pkg in ${sipycoPkg}/noarch/sipyco*.tar.bz2 ${artiqPkg}/noarch/artiq*.tar.bz2 ; do
${scp "\\$pkg" "to_install\\$i.tar.bz2"}
${sshUnquoted "anaconda\\scripts\\activate ${condaEnv} && conda install to_install\\$i.tar.bz2"}
((i=i+1))
done
# Schedule a timed shutdown against hanging test runs
${ssh "shutdown -s -t ${toString testTimeout}"}
FAIL=n
( ${ssh "anaconda\\scripts\\activate ${condaEnv} && ${testCommand}"} ) || FAIL=y
# Abort timeouted shutdown
${ssh "shutdown -a"}
# Power off immediately
${ssh "shutdown -p -f"}
wait
if [ "\$FAIL" = "y" ]; then
exit 1
else
exit 0
fi
EOF
chmod a+x $out/bin/run.sh
'';
}

264
artiq-fast/windows/win.nix Normal file
View File

@ -0,0 +1,264 @@
{ pkgs ? import <nixpkgs> {}
, lib ? pkgs.lib
, diskImageSize ? "22G"
, qemuMem ? "4G"
, windowsImage ? null
, autoUnattendParams ? {}
, packages ? []
, impureMode ? false
, baseRtc ? "2020-04-20T14:21:42"
, installCommands ? []
, users ? {}
, ...
}@attrs:
let
# qemu_test is a smaller closure only building for a single system arch
qemu = pkgs.qemu_test;
libguestfs = pkgs.libguestfs-with-appliance;
# p7zip on >20.03 has known vulns but we have no better option
p7zip = pkgs.p7zip.overrideAttrs(old: {
meta = old.meta // {
knownVulnerabilities = [];
};
});
runQemuCommand = name: command: (
pkgs.runCommandNoCC name { buildInputs = [ p7zip qemu libguestfs ]; }
(
''
if ! test -f; then
echo "KVM not available, bailing out" >> /dev/stderr
exit 1
fi
'' + command
)
);
windowsIso = if windowsImage != null then windowsImage else pkgs.fetchurl {
url = "https://software-download.microsoft.com/download/sg/17763.107.101029-1455.rs5_release_svc_refresh_CLIENT_LTSC_EVAL_x64FRE_en-us.iso";
sha256 = "668fe1af70c2f7416328aee3a0bb066b12dc6bbd2576f40f812b95741e18bc3a";
};
openSshServerPackage = ./openssh/server-package.cab;
autounattend = import ./autounattend.nix (
attrs // {
inherit pkgs;
}
);
bundleInstaller = pkgs.callPackage ./bundle {};
# Packages required to drive installation of other packages
bootstrapPkgs = let
winPkgs = import ./pkgs.nix { inherit pkgs; };
in
runQemuCommand "bootstrap-win-pkgs.img" ''
mkdir pkgs
mkdir pkgs/bootstrap
mkdir pkgs/user
mkdir pkgs/fod
cp ${bundleInstaller} pkgs/"$(stripHash "${bundleInstaller}")"
# Install optional windows features
cp ${openSshServerPackage} pkgs/fod/OpenSSH-Server-Package~31bf3856ad364e35~amd64~~.cab
# SSH setup script goes here because windows XML parser sucks
cp ${autounattend.setupScript} pkgs/ssh-setup.ps1
${lib.concatStringsSep "\n" (builtins.map (x: ''cp ${x} pkgs/bootstrap/"$(stripHash "${x}")"'') packages)}
virt-make-fs --partition --type=fat pkgs/ $out
'';
mkQemuFlags = extraFlags: [
#"-enable-kvm"
"-cpu"
"host"
"-smp"
"$NIX_BUILD_CORES"
"-m"
"${qemuMem}"
"-bios"
"${pkgs.OVMF.fd}/FV/OVMF.fd"
"-vga"
"virtio"
"-device"
"piix3-usb-uhci" # USB root hub
# "CD" drive with windows features-on-demand
# "-cdrom" "${fodIso}"
# Set the base clock inside the VM
"-rtc base=${baseRtc}"
# Always enable SSH port forward
# It's not really required for the initial setup but we do it here anyway
"-netdev user,id=n1,net=192.168.1.0/24,restrict=off,hostfwd=tcp::2022-:22"
"-device e1000,netdev=n1"
] ++ lib.optional (!impureMode) "-nographic" ++ extraFlags;
installScript = pkgs.writeScript "windows-install-script" (
let
qemuParams = mkQemuFlags [
# "CD" drive with bootstrap pkgs
"-drive"
"id=virtio-win,file=${bootstrapPkgs},if=none,format=raw,readonly=on"
"-device"
"usb-storage,drive=virtio-win"
# USB boot
"-drive"
"id=win-install,file=usbimage.img,if=none,format=raw,readonly=on"
"-device"
"usb-storage,drive=win-install"
# Output image
"-drive"
"file=c.img,index=0,media=disk,cache=unsafe"
];
in
''
#!${pkgs.runtimeShell}
set -euxo pipefail
export PATH=${lib.makeBinPath [ p7zip qemu libguestfs ]}:$PATH
if test -z "''${NIX_BUILD_CORES+x}"; then
export NIX_BUILD_CORES=$(nproc)
fi
# Create a bootable "USB" image
# Booting in USB mode circumvents the "press any key to boot from cdrom" prompt
#
# Also embed the autounattend answer file in this image
mkdir -p win
mkdir -p win/nix-win
7z x -y ${windowsIso} -owin
cp ${autounattend.autounattendXML} win/autounattend.xml
virt-make-fs --partition --type=fat win/ usbimage.img
rm -rf win
# Qemu requires files to be rw
qemu-img create -f qcow2 c.img ${diskImageSize}
env NIX_BUILD_CORES="''${NIX_BUILD_CORES:4}" qemu-system-x86_64 ${lib.concatStringsSep " " qemuParams}
''
);
baseImage = pkgs.runCommandNoCC "windows.img" {} ''
${installScript}
mv c.img $out
'';
# Use Paramiko instead of OpenSSH
#
# OpenSSH goes out of it's way to make password logins hard
# and Windows goes out of it's way to make key authentication hard
# so we're in a pretty tough spot
#
# Luckily the usage patterns are quite simple and easy to reimplement with paramiko
paramikoClient = pkgs.writeScriptBin "win" ''
#!${pkgs.python3.withPackages(ps: [ ps.paramiko ])}/bin/python
import paramiko
import os.path
import sys
def w_join(*args):
# Like os.path.join but for windows paths
return "\\".join(args)
if __name__ == '__main__':
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.client.AutoAddPolicy)
cmd = sys.argv[1]
try:
client.connect(hostname="127.0.0.1", port=2022, username="artiq", password="${users.artiq.password}", timeout=1)
if cmd == "put":
sftp = client.open_sftp()
src = sys.argv[2]
dst = sys.argv[3]
sftp.put(src, w_join(dst, os.path.basename(src)))
elif cmd == "exec":
_, stdout, stderr = client.exec_command(sys.argv[2])
sys.stdout.write(stdout.read().strip().decode())
sys.stdout.flush()
sys.stderr.write(stderr.read().strip().decode())
sys.stderr.flush()
else:
raise ValueError(f"Unhandled command: {cmd}")
except (EOFError, paramiko.ssh_exception.SSHException):
exit(1)
'';
finalImage = builtins.foldl' (acc: v: pkgs.runCommandNoCC "${v.name}.img" {
buildInputs = [
paramikoClient
qemu
];
} (let
script = pkgs.writeScript "${v.name}-script" v.script;
qemuParams = mkQemuFlags [
# Output image
"-drive"
"file=c.img,index=0,media=disk,cache=unsafe"
];
in ''
export HOME=$(mktemp -d)
# Create an image referencing the previous image in the chain
qemu-img create -f qcow2 -b ${acc} c.img
qemu-system-x86_64 ${lib.concatStringsSep " " qemuParams} &
# If the machine is not up within 10 minutes it's likely never coming up
timeout=600
# Wait for VM to be accessible
sleep 20
echo "Waiting for SSH"
while true; do
if test "$timeout" -eq 0; then
echo "SSH connection timed out"
exit 1
fi
output=$(win exec 'echo Ran command' || echo "")
if test "$output" = "Ran command"; then
break
fi
echo "Retrying in 1 second, timing out in $timeout seconds"
((timeout=$timeout-1))
sleep 1
done
echo "Executing user script to build layer"
${script}
# Allow install to "settle"
sleep 20
win exec 'shutdown /s'
mv c.img $out
'')) baseImage installCommands;
in
# impureMode is meant for debugging the base image, not the full incremental build process
if !(impureMode) then finalImage else assert installCommands == []; installScript

270
artiq-full.nix Normal file
View File

@ -0,0 +1,270 @@
{ pkgs ? import <nixpkgs> {}}:
let
sinaraSystemsSrc = <sinaraSystemsSrc>;
generatedNix = builtins.trace "full generatedNix" (pkgs.runCommand "generated-nix" { buildInputs = [ pkgs.nix pkgs.git ]; }
''
mkdir $out
cp -a ${<artiq-fast>} $out/fast
cp ${./artiq-full/conda-artiq-board.nix} $out/conda-artiq-board.nix
cp ${./artiq-full/extras.nix} $out/extras.nix
REV=`git --git-dir ${sinaraSystemsSrc}/.git rev-parse HEAD`
SINARA_SRC_CLEAN=`mktemp -d`
cp -a ${sinaraSystemsSrc}/. $SINARA_SRC_CLEAN
chmod -R 755 $SINARA_SRC_CLEAN/.git
chmod 755 $SINARA_SRC_CLEAN
rm -rf $SINARA_SRC_CLEAN/.git
HASH=`nix-hash --type sha256 --base32 $SINARA_SRC_CLEAN`
cat > $out/default.nix << EOF
{ pkgs ? import <nixpkgs> {}}:
let
artiq-fast = import ./fast { inherit pkgs; };
target = "kasli";
variants = [
"afmaster"
"afsatellite"
"berkeley2"
"berkeley3"
"csu"
"duke"
"duke2"
"duke3"
"femto1"
"femto2"
"femto3"
"freiburg1"
"griffith"
"hub"
"hw"
"indiana"
"innsbruck2"
"ist"
"liaf"
"luh"
"luh2"
"luh3"
"mikes"
"mit"
"mitll3"
"mitll4master"
"mitll4satellite"
"mpik"
"mpq"
"nict"
"nist"
"no"
"npl1"
"npl2"
"oklahoma"
"olomouc"
"opticlock"
"oregon"
"osaka"
"ptb"
"ptb2"
"ptb3"
"ptb4"
"ptb5"
"ptb6"
"ptbal"
"ptbin"
"purdue"
"qe"
"rice"
"saymamaster"
"siegen"
"su"
"sydney"
"uaarhus"
"ubirmingham"
"ugranada"
"unlv"
"unsw2"
"ustc2"
"vlbaimaster"
"vlbaisatellite"
"wipm"
"wipm4"
"wipm5master"
"wipm5satellite"
] ++ (pkgs.lib.lists.optionals (pkgs.lib.strings.versionAtLeast artiq-fast.artiq.version "6.0") [
"bonn1master"
"bonn1satellite"
"hw2master"
"hw2satellite"
"uamsterdam"
]);
vivado = builtins.trace "vivado (full)" (import ./fast/vivado.nix { inherit pkgs; });
artiq-board = builtins.trace "artiq-board" (import ./fast/artiq-board.nix { inherit pkgs vivado; });
conda-artiq-board = import ./conda-artiq-board.nix { inherit pkgs; };
src = pkgs.fetchgit {
url = "https://git.m-labs.hk/M-Labs/sinara-systems.git";
rev = "$REV";
sha256 = "$HASH";
};
generic-kasli = pkgs.lib.lists.foldr (variant: start:
let
json = builtins.toPath (src + "/\''${variant}.json");
boardBinaries = artiq-board {
inherit target variant;
buildCommand = "python -m artiq.gateware.targets.kasli_generic \''${json}";
};
in
start // {
"artiq-board-\''${target}-\''${variant}" = boardBinaries;
"conda-artiq-board-\''${target}-\''${variant}" = conda-artiq-board {
boardBinaries = boardBinaries;
inherit target variant;
};
} // (pkgs.lib.optionalAttrs ((builtins.fromJSON (builtins.readFile json)).base == "standalone") {
"device-db-\''${target}-\''${variant}" = pkgs.stdenv.mkDerivation {
name = "device-db-\''${target}-\''${variant}";
buildInputs = [ artiq-fast.artiq ];
phases = [ "buildPhase" ];
buildPhase = "
mkdir \$out
artiq_ddb_template \''${json} -o \$out/device_db.py
mkdir \$out/nix-support
echo file device_db_template \$out/device_db.py >> \$out/nix-support/hydra-build-products
";
};
})) {} variants;
drtio-systems = {
af = {
master = "afmaster";
satellites = {
"1" = "afsatellite";
};
};
mitll4 = {
master = "mitll4master";
satellites = {
"1" = "mitll4satellite";
};
};
vlbai = {
master = "vlbaimaster";
satellites = {
"1" = "vlbaisatellite";
};
};
wipm5 = {
master = "wipm5master";
satellites = {
"1" = "wipm5satellite";
};
};
} // (pkgs.lib.optionalAttrs (pkgs.lib.strings.versionAtLeast artiq-fast.artiq.version "6.0") {
bonn1 = {
master = "bonn1master";
satellites = {
"1" = "bonn1satellite";
};
};
hw2 = {
master = "hw2master";
satellites = {
"1" = "hw2satellite";
};
};
});
drtio-ddbs = pkgs.lib.attrsets.mapAttrs'
(system: crates: pkgs.lib.attrsets.nameValuePair ("device-db-" + system)
(pkgs.stdenv.mkDerivation {
name = "device-db-\''${system}";
buildInputs = [ artiq-fast.artiq ];
phases = [ "buildPhase" ];
buildPhase = "
mkdir \$out
artiq_ddb_template \
\''${pkgs.lib.strings.concatStringsSep " " (pkgs.lib.attrsets.mapAttrsToList (dest: desc: "-s " + dest + " " + src + "/" + desc + ".json") crates.satellites) } \
\''${src}/\''${crates.master}.json -o \$out/device_db.py
mkdir \$out/nix-support
echo file device_db_template \$out/device_db.py >> \$out/nix-support/hydra-build-products
";
})) drtio-systems;
extras = import ./extras.nix { inherit pkgs; inherit (artiq-fast) sipyco asyncserial artiq; };
in
artiq-fast // generic-kasli // drtio-ddbs // extras // rec {
artiq-board-sayma-rtm = artiq-board {
target = "sayma";
variant = "rtm";
buildCommand = "python -m artiq.gateware.targets.sayma_rtm";
};
artiq-board-sayma-satellite = artiq-board {
target = "sayma";
variant = "satellite";
buildCommand = "python -m artiq.gateware.targets.sayma_amc";
};
artiq-board-metlino-master = artiq-board {
target = "metlino";
variant = "master";
buildCommand = "python -m artiq.gateware.targets.metlino";
};
artiq-board-kc705-nist_qc2 = artiq-board {
target = "kc705";
variant = "nist_qc2";
};
conda-artiq-board-sayma-rtm = conda-artiq-board {
target = "sayma";
variant = "rtm";
boardBinaries = artiq-board-sayma-rtm;
};
conda-artiq-board-sayma-satellite = conda-artiq-board {
target = "sayma";
variant = "satellite";
boardBinaries = artiq-board-sayma-satellite;
};
conda-artiq-board-metlino-master = conda-artiq-board {
target = "metlino";
variant = "master";
boardBinaries = artiq-board-metlino-master;
};
conda-artiq-board-kasli-tester = conda-artiq-board {
target = "kasli";
variant = "tester";
boardBinaries = artiq-fast.artiq-board-kasli-tester;
};
conda-artiq-board-kc705-nist_clock = conda-artiq-board {
target = "kc705";
variant = "nist_clock";
boardBinaries = artiq-fast.artiq-board-kc705-nist_clock;
};
conda-artiq-board-kc705-nist_qc2 = conda-artiq-board {
target = "kc705";
variant = "nist_qc2";
boardBinaries = artiq-board-kc705-nist_qc2;
};
}
EOF
'');
pythonDeps = import ./artiq-full/python-deps.nix { inherit pkgs; };
sipycoManualPackages = import ./artiq-full/sipyco-manual.nix {
inherit (pkgs) stdenv lib python3Packages texlive texinfo;
inherit (import <artiq-fast> { inherit pkgs; }) sipyco;
};
artiqManualPackages = import ./artiq-full/artiq-manual.nix {
inherit (pkgs) stdenv lib fetchgit git python3Packages texlive texinfo;
inherit (pythonDeps) sphinxcontrib-wavedrom;
};
jobs = (import generatedNix { inherit pkgs; }) // sipycoManualPackages // artiqManualPackages // {
# This is in the example in the ARTIQ manual - precompile it to speed up
# installation for users.
matplotlib-qt = pkgs.lib.hydraJob (pkgs.python3Packages.matplotlib.override { enableQt = true; });
};
in
builtins.mapAttrs (key: value: builtins.trace "full-${key}" pkgs.lib.hydraJob value) jobs // {
artiq-full = builtins.trace "channel" (pkgs.releaseTools.channel {
name = "artiq-full";
src = generatedNix;
constituents = builtins.attrValues jobs;
});
conda-channel = builtins.trace "conda-channel" (import ./artiq-full/conda-channel.nix { inherit pkgs; }) { inherit jobs; };
}

View File

@ -0,0 +1,57 @@
{ stdenv, lib, fetchgit, git, python3Packages, texlive, texinfo, sphinxcontrib-wavedrom }:
let
artiqVersion = import <artiq-fast/pkgs/artiq-version.nix> { inherit stdenv fetchgit git; };
isLatexPdfTarget = target: builtins.match "latexpdf.*" target != null;
latex = texlive.combine {
inherit (texlive)
scheme-basic latexmk cmap collection-fontsrecommended fncychap
titlesec tabulary varwidth framed fancyvrb float wrapfig parskip
upquote capt-of needspace etoolbox;
};
artiq-manual = target: stdenv.mkDerivation rec {
name = "artiq-manual-${target}-${version}";
version = artiqVersion;
src = import <artiq-fast/pkgs/artiq-src.nix> { inherit fetchgit; };
buildInputs = [
python3Packages.sphinx python3Packages.sphinx_rtd_theme
python3Packages.sphinx-argparse sphinxcontrib-wavedrom
] ++
lib.optional (isLatexPdfTarget target) latex ++
lib.optional (target == "texinfo") texinfo;
preBuild = ''
export VERSIONEER_OVERRIDE=${artiqVersion}
export SOURCE_DATE_EPOCH=${import <artiq-fast/pkgs/artiq-timestamp.nix> { inherit stdenv fetchgit git; }}
cd doc/manual
'';
makeFlags = [ target ];
installPhase =
let
dest = "$out/share/doc/artiq-manual";
in
if isLatexPdfTarget target
then ''
mkdir -p ${dest}
cp _build/latex/ARTIQ.pdf ${dest}/
mkdir -p $out/nix-support/
echo doc-pdf manual ${dest} ARTIQ.pdf >> $out/nix-support/hydra-build-products
''
else ''
mkdir -p ${dest}
cp -r _build/${target} ${dest}/
mkdir -p $out/nix-support/
echo doc manual ${dest}/${target} index.html >> $out/nix-support/hydra-build-products
'';
};
targets = [ "html" "latexpdf" ];
in
builtins.listToAttrs (map (target: { name = "artiq-manual-${target}"; value = artiq-manual target; }) targets)

View File

@ -0,0 +1,48 @@
{ pkgs }:
{ target, variant, boardBinaries }:
with pkgs;
let
version = import ./fast/pkgs/artiq-version.nix (with pkgs; { inherit stdenv fetchgit git; });
fakeCondaSource = runCommand "fake-condasrc-artiq-board-${target}-${variant}" { }
''
mkdir -p $out/fake-conda;
cat << EOF > $out/fake-conda/meta.yaml
package:
name: artiq-board-${target}-${variant}
version: ${version}
build:
noarch: python
ignore_prefix_files: True
outputs:
- name: artiq-board-${target}-${variant}
noarch: python
files:
- site-packages
ignore_prefix_files: True
about:
home: https://m-labs.hk/artiq
license: LGPL
summary: 'Bitstream, bootloader and firmware for the ${target}-${variant} board variant'
EOF
cat << EOF > $out/fake-conda/build.sh
#!/bin/bash
set -e
SOC_PREFIX=\$PREFIX/site-packages/artiq/board-support/${target}-${variant}
mkdir -p \$SOC_PREFIX
cp ${boardBinaries}/${pkgs.python3Packages.python.sitePackages}/artiq/board-support/${target}-${variant}/* \$SOC_PREFIX
EOF
chmod 755 $out/fake-conda/build.sh
'';
conda-artiq-board = import ./fast/conda/build.nix { inherit pkgs; } {
name = "conda-artiq-board-${target}-${variant}";
src = fakeCondaSource;
};
in
conda-artiq-board

View File

@ -0,0 +1,25 @@
{ pkgs }:
{ jobs }:
let
condaBuilderEnv = import <artiq-fast/conda/builder-env.nix> { inherit pkgs; };
in
pkgs.runCommand "conda-channel" { }
''
mkdir -p $out/noarch $out/linux-64 $out/win-64
for storepath in ${pkgs.lib.concatMapStringsSep " " builtins.toString (builtins.attrValues jobs)}; do
hydra_build_products=$storepath/nix-support/hydra-build-products
if [ -f $hydra_build_products ]; then
while IFS= read -r line; do
type=`echo $line | cut -f2 -d " "`
if [ $type == "conda" ]; then
path=`echo $line | cut -f3 -d " "`
arch=`echo $path | cut -f5 -d "/"`
ln -s $path $out/$arch
fi
done < $hydra_build_products
fi
done
cd $out
${condaBuilderEnv}/bin/conda-builder-env -c "conda index"
''

206
artiq-full/extras.nix Normal file
View File

@ -0,0 +1,206 @@
{ pkgs, sipyco, asyncserial, artiq }:
let
condaBuild = import ./fast/conda/build.nix { inherit pkgs; };
condaFakeSource = import ./fast/conda/fake-source.nix { inherit pkgs; };
dualPackage = (
{ name, version, src, pythonOptions ? {}, condaOptions ? {}}:
{
"${name}" = pkgs.python3Packages.buildPythonPackage ({
inherit version;
name = "${name}-${version}";
inherit src;
} // pythonOptions);
"${name}-manual-html" = pkgs.stdenv.mkDerivation {
name = "${name}-manual-html-${version}";
inherit version src;
buildInputs = (with pkgs.python3Packages; [ sphinx sphinx_rtd_theme sphinx-argparse ]) ++ [ artiq ];
preBuild = ''
export SOURCE_DATE_EPOCH=${import ./fast/pkgs/artiq-timestamp.nix { inherit (pkgs) stdenv fetchgit git; }}
cd doc
'';
makeFlags = [ "html" ];
installPhase =
let
dest = "$out/share/doc/${name}-manual";
in
''
mkdir -p ${dest}
cp -r _build/html ${dest}/
mkdir -p $out/nix-support/
echo doc manual ${dest}/html index.html >> $out/nix-support/hydra-build-products
'';
};
"conda-${name}" = condaBuild {
name = "conda-${name}";
src = condaFakeSource ({
inherit name version src;
} // condaOptions);
};
}
);
# https://github.com/m-labs/artiq/issues/23
hidapi = pkgs.hidapi.overrideAttrs (oa: {
src = pkgs.fetchFromGitHub {
owner = "signal11";
repo = "hidapi";
rev = "a6a622ffb680c55da0de787ff93b80280498330f";
sha256 = "17n7c4v3jjrnzqwxpflggxjn6vkzscb32k4kmxqjbfvjqnx7qp7j";
};
});
in
(dualPackage {
name = "korad_ka3005p";
version = "1.1";
src = pkgs.fetchFromGitHub {
owner = "m-labs";
repo = "korad_ka3005p";
rev = "a0cfaa5792a211e166d224314c4d0be4881b9b8d";
sha256 = "1bxzyjyvdhsbm9hj7ypf0vgkd1lvc340bb6lx3wchvh30n7bv9gv";
};
pythonOptions = { propagatedBuildInputs = [ sipyco asyncserial ]; };
condaOptions = { dependencies = [ "sipyco" "asyncserial" ]; };
}) // (dualPackage {
name = "novatech409b";
version = "1.1";
src = pkgs.fetchFromGitHub {
owner = "m-labs";
repo = "novatech409b";
rev = "8740b3e7b254e03395135e6bc128bbaca70d4fbb";
sha256 = "0mwm434y83y8jb30fpz69z6z3b6sxbc8dv3nw0hq4wc7iginx89d";
};
pythonOptions = { propagatedBuildInputs = [ sipyco asyncserial ]; };
condaOptions = { dependencies = [ "sipyco" "asyncserial" ]; };
}) // (dualPackage {
name = "lda";
version = "1.1";
src = pkgs.fetchFromGitHub {
owner = "m-labs";
repo = "lda";
rev = "6138a94a1116c8f7b40b8bd8bb161f847065aab6";
sha256 = "1009k9pq8wx5zxrljkxr1g95g8q979i7mq3csksdkd3d0v2jvqif";
};
pythonOptions = {
propagatedBuildInputs = [ sipyco ];
postPatch = ''
substituteInPlace lda/hidapi.py \
--replace "hidapi_lib_path = None"\
"hidapi_lib_path = '${hidapi}/lib/libhidapi-libusb.so.0'"
'';
};
condaOptions = { dependencies = [ "sipyco" ]; };
}) // (dualPackage {
name = "thorlabs_tcube";
version = "1.1";
src = pkgs.fetchFromGitHub {
owner = "m-labs";
repo = "thorlabs_tcube";
rev = "8b85292d76a69ae72ba8da32b894c87c794574ba";
sha256 = "09cy9nhydcwdib21wb0qg1cinvibfbszwgphrmf2ajw5kqpr1d6a";
};
pythonOptions = { propagatedBuildInputs = [ sipyco asyncserial ]; };
condaOptions = { dependencies = [ "sipyco" "asyncserial" ]; };
}) // (dualPackage {
name = "newfocus8742";
version = "0.2";
src = pkgs.fetchFromGitHub {
owner = "quartiq";
repo = "newfocus8742";
rev = "9f6092b724b33b934aa4d3a1d6a20c295cd1d02d";
sha256 = "0qf05ghylnqf3l5vjx5dc748wi84xn6p6lb6f9r8p6f1z7z67fb8";
};
pythonOptions = {
propagatedBuildInputs = [ sipyco pkgs.python3Packages.pyusb ];
# no unit tests so do a simple smoke test
checkPhase = "python -m newfocus8742.aqctl_newfocus8742 -h";
};
condaOptions = { dependencies = [ "sipyco" ]; };
}) // (dualPackage {
name = "hut2";
version = "0.2";
src = pkgs.fetchFromGitHub {
owner = "quartiq";
repo = "hut2";
rev = "68369d5d63d233827840a9a752d90454a4e03baa";
sha256 = "0r832c0icz8v3w27ci13024bqfslj1gx6dwhjv11ksw229xdcghd";
};
pythonOptions = {
propagatedBuildInputs = [ sipyco ];
# no unit tests without hardware so do a simple smoke test
checkPhase = "python -m hut2.aqctl_hut2 -h";
};
condaOptions = { dependencies = [ "sipyco" ]; };
}) // rec {
toptica-lasersdk = pkgs.python3Packages.buildPythonPackage rec {
version = "2.0.0";
name = "toptica-lasersdk-${version}";
format = "wheel";
src = pkgs.fetchurl {
url = "https://files.pythonhosted.org/packages/6b/e2/5c98407215884c2570453a78bc0d6f0bbe619f06593847ccd6a2f1d3fe59/toptica_lasersdk-2.0.0-py3-none-any.whl";
sha256 = "1k5d9ah8qzp75hh63nh9l5dk808v9ybpmzlhrdc3sxmas3ajv8s7";
};
propagatedBuildInputs = [ pkgs.python3Packages.pyserial ];
};
toptica-lasersdk-artiq = pkgs.python3Packages.buildPythonPackage rec {
version = "0.2";
name = "toptica-lasersdk-artiq-${version}";
src = pkgs.fetchFromGitHub {
owner = "quartiq";
repo = "lasersdk-artiq";
rev = "901dec13a1bf9429ce7ab49be34b03d1c49b8a9f";
sha256 = "0lqxvgvpgrpw1kzhg5axnfb40ils2vdk75r43hqmk2lfz4sydwb2";
};
postPatch = ''
substituteInPlace lasersdk_artiq/aqctl_laser.py \
--replace "toptica.lasersdk.async.client" \
"toptica.lasersdk.asyncio.client"
substituteInPlace lasersdk_artiq/test.py \
--replace "toptica.lasersdk.async.client" \
"toptica.lasersdk.asyncio.client"
'';
propagatedBuildInputs = [ sipyco toptica-lasersdk ];
};
conda-toptica-lasersdk-artiq = condaBuild {
name = "conda-toptica-lasersdk-artiq";
src = condaFakeSource {
name = "toptica-lasersdk-artiq";
inherit (toptica-lasersdk-artiq) version src;
dependencies = [ "sipyco" "lasersdk =1.3.1" ];
};
};
} // (dualPackage {
name = "highfinesse-net";
version = "0.2";
src = pkgs.fetchFromGitHub {
owner = "quartiq";
repo = "highfinesse-net";
rev = "a9cc049c9846845d2b2d8662266ec11fe770abee";
sha256 = "01mk4gf6rk3jqpz4y7m35vawjybvyp26bizz5a4ygkb8dq5l51g4";
};
pythonOptions = {
propagatedBuildInputs = [ sipyco ];
# no unit tests without hardware so do a simple smoke test
checkPhase = "python -m highfinesse_net.aqctl_highfinesse_net -h";
};
condaOptions = { dependencies = [ "sipyco" ]; };
}) // rec {
artiq-comtools = pkgs.python3Packages.buildPythonPackage rec {
name = "artiq-comtools-${version}";
version = "1.1";
src = pkgs.fetchFromGitHub {
owner = "m-labs";
repo = "artiq-comtools";
rev = "v${version}";
sha256 = "165j12k9nnrkf2pv0idcv6xhnp1hnsllna4rps2dssnqgjfaw1ss";
};
propagatedBuildInputs = [ sipyco pkgs.python3Packages.numpy pkgs.python3Packages.aiohttp ];
};
conda-artiq-comtools = condaBuild {
name = "conda-artiq-comtools";
src = condaFakeSource {
name = "artiq-comtools";
inherit (artiq-comtools) version src;
dependencies = [ "sipyco" "numpy" "aiohttp >=3" ];
};
};
}

View File

@ -0,0 +1,43 @@
{ pkgs }:
rec {
wavedrom = pkgs.python3Packages.buildPythonPackage rec {
pname = "wavedrom";
version = "0.1";
src = pkgs.python3Packages.fetchPypi {
inherit pname version;
sha256 = "006w683zlmmwcw5xz1n5dwg34ims5jg3gl2700ql4wr0myjz6710";
};
buildInputs = [ pkgs.python3Packages.setuptools_scm ];
propagatedBuildInputs = with pkgs.python3Packages; [ svgwrite attrdict ];
doCheck = false;
meta = with pkgs.stdenv.lib; {
description = "WaveDrom compatible Python module and command line";
homepage = "https://pypi.org/project/wavedrom/";
license = licenses.mit;
};
};
sphinxcontrib-wavedrom = pkgs.python3Packages.buildPythonPackage rec {
pname = "sphinxcontrib-wavedrom";
version = "2.0.0";
src = pkgs.python3Packages.fetchPypi {
inherit pname version;
sha256 = "0nk36zqq5ipxqx9izz2iazb3iraasanv3nm05bjr21gw42zgkz22";
};
buildInputs = [ pkgs.python3Packages.setuptools_scm ];
propagatedBuildInputs = [ wavedrom ] ++ (with pkgs.python3Packages; [ sphinx xcffib cairosvg ]);
doCheck = false;
meta = with pkgs.stdenv.lib; {
description = "A Sphinx extension that allows including WaveDrom diagrams";
homepage = "https://pypi.org/project/sphinxcontrib-wavedrom/";
license = licenses.mit;
};
};
}

View File

@ -0,0 +1,56 @@
{ stdenv, lib, python3Packages, texlive, texinfo, sipyco }:
let
version = sipyco.version;
isLatexPdfTarget = target: builtins.match "latexpdf.*" target != null;
latex = texlive.combine {
inherit (texlive)
scheme-basic latexmk cmap collection-fontsrecommended fncychap
titlesec tabulary varwidth framed fancyvrb float wrapfig parskip
upquote capt-of needspace etoolbox;
};
sipyco-manual = target: stdenv.mkDerivation rec {
name = "sipyco-manual-${target}-${version}";
inherit version;
src = sipyco.src;
buildInputs = [
python3Packages.sphinx python3Packages.sphinx_rtd_theme
python3Packages.sphinx-argparse sipyco
] ++
lib.optional (isLatexPdfTarget target) latex ++
lib.optional (target == "texinfo") texinfo;
preBuild = ''
export SOURCE_DATE_EPOCH=`cat TIMESTAMP`
cd doc
'';
makeFlags = [ target ];
installPhase =
let
dest = "$out/share/doc/sipyco-manual";
in
if isLatexPdfTarget target
then ''
mkdir -p ${dest}
cp _build/latex/SiPyCo.pdf ${dest}/
mkdir -p $out/nix-support/
echo doc-pdf manual ${dest} SiPyCo.pdf >> $out/nix-support/hydra-build-products
''
else ''
mkdir -p ${dest}
cp -r _build/${target} ${dest}/
mkdir -p $out/nix-support/
echo doc manual ${dest}/${target} index.html >> $out/nix-support/hydra-build-products
'';
};
targets = [ "html" "latexpdf" ];
in
builtins.listToAttrs (map (target: { name = "sipyco-manual-${target}"; value = sipyco-manual target; }) targets)

View File

@ -1,28 +1,27 @@
{ pkgs ? import <nixpkgs> {} }:
let
artiqpkgs = import ../artiq-fast/pkgs/python-deps.nix { inherit (pkgs) stdenv fetchFromGitHub python3Packages; };
ise = import ./ise.nix { inherit pkgs; };
vivado = import ./vivado.nix { inherit pkgs; };
fpgatools = import ./fpgatools.nix { inherit pkgs; };
buildUrukulCpld = {version, src}: pkgs.stdenv.mkDerivation {
pname = "urukul-cpld";
inherit src version;
buildInputs = [(pkgs.python3.withPackages(ps: [fpgatools.migen]))] ++ (builtins.attrValues fpgatools.ise);
name = "urukul-cpld-${version}";
inherit src;
buildInputs = [(pkgs.python3.withPackages(ps: [artiqpkgs.migen]))] ++ (builtins.attrValues ise);
phases = ["buildPhase" "installPhase"];
buildPhase = "python $src/urukul_impl.py";
installPhase =
installPhase =
''
mkdir -p $out $out/nix-support
cp build/urukul.jed $out
echo file binary-dist $out/urukul.jed >> $out/nix-support/hydra-build-products
'';
};
buildMirnyCpld = {version, patchPhase ? "", src}: pkgs.stdenv.mkDerivation {
pname = "mirny-cpld";
inherit src version patchPhase;
buildInputs = [(pkgs.python3.withPackages(ps: [fpgatools.migen]))] ++ (builtins.attrValues fpgatools.ise);
phases = ["unpackPhase" "patchPhase" "buildPhase" "installPhase"];
buildMirnyCpld = {version, src}: pkgs.stdenv.mkDerivation {
name = "mirny-cpld-${version}";
inherit src;
buildInputs = [(pkgs.python3.withPackages(ps: [artiqpkgs.migen]))] ++ (builtins.attrValues ise);
phases = ["buildPhase" "installPhase"];
buildPhase = "python $src/mirny_impl.py";
installPhase =
installPhase =
''
mkdir -p $out $out/nix-support
cp build/mirny.jed $out
@ -44,42 +43,23 @@ in
sha256 = "1962jpzqzn22cwkcmfnvwqlj5i89pljhgfk64n6pk73clir9mp0w";
};
};
urukul-cpld-legacy = buildUrukulCpld rec {
version = "1.3.1";
src = pkgs.fetchFromGitHub {
owner = "quartiq";
repo = "urukul";
rev = "v${version}";
sha256 = "1nvarspqbf9f7b27j34jkkh4mj6rwrlmccmfpz5nnzk3h2j6zbqc";
};
};
mirny-cpld-master = buildMirnyCpld {
version = "master";
src = <mirnySrc>;
};
mirny-cpld-release = buildMirnyCpld rec {
version = "0.3.1";
src = pkgs.fetchFromGitHub {
owner = "quartiq";
repo = "mirny";
rev = "v${version}";
sha256 = "sha256-FbPUgXcUByEnczbnDCh8wYPO+rpSZSAabG1rtvA7mIs=";
};
};
mirny-cpld-legacy-almazny = buildMirnyCpld rec {
version = "0.2.4";
src = pkgs.fetchFromGitHub {
owner = "quartiq";
repo = "mirny";
rev = "v${version}";
sha256 = "sha256-/O1AE0JOXALC8I7NPhOd8h18oX8Qu7lj+6ToAMMD3zs=";
sha256 = "0fyz0g1h1s54zdivkfqhgyhpq7gjkl9kxkcfy3104p2f889l1vgw";
};
patchPhase = "patch -p1 < ${./mirny-legacy-almazny.diff}";
};
fastino-fpga = pkgs.stdenv.mkDerivation {
name = "fastino-fpga";
src = <fastinoSrc>;
buildInputs = [(pkgs.python3.withPackages(ps: [fpgatools.migen fpgatools.misoc]))] ++ [pkgs.yosys pkgs.nextpnr pkgs.icestorm];
buildInputs = [(pkgs.python3.withPackages(ps: [artiqpkgs.migen artiqpkgs.misoc]))] ++ [pkgs.yosys pkgs.nextpnr pkgs.icestorm];
phases = ["buildPhase" "installPhase"];
buildPhase = "python $src/fastino_phy.py";
installPhase =
@ -89,27 +69,4 @@ in
echo file binary-dist $out/fastino.bin >> $out/nix-support/hydra-build-products
'';
};
phaser-fpga = pkgs.stdenv.mkDerivation {
name = "phaser-fpga";
src = <phaserSrc>;
patchPhase = ''
substituteInPlace phaser.py \
--replace "source ../load.tcl" \
""
'';
buildInputs = [ (pkgs.python3.withPackages(ps: [ fpgatools.migen fpgatools.misoc ])) ] ++ [ fpgatools.vivado ];
buildPhase = "python phaser.py";
installPhase =
''
mkdir -p $out $out/nix-support
cp build/phaser.bit $out
echo file binary-dist $out/phaser.bit >> $out/nix-support/hydra-build-products
'';
dontFixup = true;
doCheck = true;
checkInputs = [ pkgs.python3Packages.pytest ];
checkPhase = "pytest";
};
}

View File

@ -1,94 +0,0 @@
{ pkgs, isePath ? "/opt/Xilinx/14.7/ISE_DS", vivadoPath ? "/opt/Xilinx/Vivado/2022.2" }:
rec {
ise = let
makeXilinxEnv = name: pkgs.buildFHSUserEnv {
inherit name;
targetPkgs = pkgs: (
with pkgs; [
ncurses5
zlib
libuuid
xorg.libSM
xorg.libICE
xorg.libXrender
xorg.libX11
xorg.libXext
xorg.libXtst
xorg.libXi
]
);
profile =
''
source ${isePath}/common/.settings64.sh ${isePath}/common
source ${isePath}/ISE/.settings64.sh ${isePath}/ISE
'';
runScript = name;
};
in
pkgs.lib.attrsets.genAttrs ["xst" "ngdbuild" "cpldfit" "taengine" "hprep6"] makeXilinxEnv;
vivado = pkgs.buildFHSUserEnv {
name = "vivado";
targetPkgs = pkgs: (
with pkgs; let
# Apply patch from https://github.com/nix-community/nix-environments/pull/54
# to fix ncurses libtinfo.so's soname issue
ncurses' = ncurses5.overrideAttrs (old: {
configureFlags = old.configureFlags ++ [ "--with-termlib" ];
postFixup = "";
});
in [
libxcrypt-legacy
(ncurses'.override { unicodeSupport = false; })
zlib
libuuid
xorg.libSM
xorg.libICE
xorg.libXrender
xorg.libX11
xorg.libXext
xorg.libXtst
xorg.libXi
]
);
profile = "source ${vivadoPath}/settings64.sh";
runScript = "vivado";
};
migen = pkgs.python3Packages.buildPythonPackage {
pname = "migen";
version = "unstable-2024-05-02";
src = pkgs.fetchFromGitHub {
owner = "m-labs";
repo = "migen";
rev = "4790bb577681a8c3a8d226bc196a4e5deb39e4df";
sha256 = "sha256-4DCHBUBfc/VA+7NW2Hr0+JP4NnKPru2uVJyZjCCk0Ws=";
};
format = "pyproject";
nativeBuildInputs = [ pkgs.python3Packages.setuptools ];
propagatedBuildInputs = with pkgs.python3Packages; [ colorama ];
};
asyncserial = pkgs.python3Packages.buildPythonPackage {
pname = "asyncserial";
version = "0.1";
src = pkgs.fetchFromGitHub {
owner = "m-labs";
repo = "asyncserial";
rev = "d95bc1d6c791b0e9785935d2f62f628eb5cdf98d";
sha256 = "0yzkka9jk3612v8gx748x6ziwykq5lr7zmr9wzkcls0v2yilqx9k";
};
propagatedBuildInputs = with pkgs.python3Packages; [ pyserial ];
};
misoc = pkgs.python3Packages.buildPythonPackage {
pname = "misoc";
version = "unstable-2021-10-10";
src = pkgs.fetchFromGitHub {
owner = "m-labs";
repo = "misoc";
rev = "f5203e406520874e15ab5d070058ef642fc57fd9";
sha256 = "sha256-/2XTejqj0Bo81HaTrlTSWwInnWwsuqnq+CURXbpIrkA=";
fetchSubmodules = true;
};
# TODO: fix misoc bitrot and re-enable tests
doCheck = false;
propagatedBuildInputs = with pkgs.python3Packages; [ pyserial jinja2 numpy asyncserial migen ];
};
}

31
gluelogic/ise.nix Normal file
View File

@ -0,0 +1,31 @@
# Install ISE in /opt and add to /etc/nixos/configuration.nix:
# nix.sandboxPaths = ["/opt"];
{ pkgs, isePath ? "/opt/Xilinx/14.7/ISE_DS" }:
let
makeXilinxEnv = name: pkgs.buildFHSUserEnv {
inherit name;
targetPkgs = pkgs: (
with pkgs; [
ncurses5
zlib
libuuid
xorg.libSM
xorg.libICE
xorg.libXrender
xorg.libX11
xorg.libXext
xorg.libXtst
xorg.libXi
]
);
profile =
''
source ${isePath}/common/.settings64.sh ${isePath}/common
source ${isePath}/ISE/.settings64.sh ${isePath}/ISE
'';
runScript = name;
};
in
pkgs.lib.attrsets.genAttrs ["xst" "ngdbuild" "cpldfit" "taengine" "hprep6"] makeXilinxEnv

View File

@ -1,313 +0,0 @@
diff --git a/Makefile b/Makefile
index 667b8e7..ed97303 100644
--- a/Makefile
+++ b/Makefile
@@ -8,9 +8,15 @@ test:
.PHONY: build
build: build/mirny.vm6
+.PHONY: legacy_almazny
+legacy_almazny: build/mirny_legacy_almazny.vm6
+
build/mirny.vm6: mirny.py mirny_cpld.py
python mirny_impl.py
+build/mirny_legacy_almazny.vm6: mirny.py mirny_cpld.py
+ python mirny_impl.py --legacy-almazny
+
REV:=$(shell git describe --always --abbrev=8 --dirty)
.PHONY: release
diff --git a/README.md b/README.md
index 1bea35a..5e93809 100644
--- a/README.md
+++ b/README.md
@@ -1,23 +1,39 @@
-# Mirny CPLD code
+# Mirny CPLD gateware
-[Mirny overview](https://github.com/sinara-hw/mirny/wiki)
+## Hardware
+
+[![Hardware](https://github.com/sinara-hw/mirny/wiki/Mirny_v1.0_top_small.jpg)](https://github.com/sinara-hw/mirny/wiki)
[Mirny Schematics](https://github.com/sinara-hw/mirny/releases)
## Building
-Needs migen and ISE.
+Needs [migen](https://github.com/m-labs/migen) and [Xilinx ISE](https://www.xilinx.com/products/design-tools/ise-design-suite.html). Assumes ISE is installed in ``/opt/Xilinx``.
```
make
-# and then look at/use flash.sh or make flash
-
-# or use fxload and xc3sprog:
-/sbin/fxload -t fx2 -I /opt/Xilinx/14.7/ISE_DS/ISE/bin/lin64/xusb_xp2.hex -D /dev/bus/usb/001/*`cat /sys/bus/usb/devices/1-3/devnum` && sleep 10 && \
-xc3sprog -c xpc -m /opt/Xilinx/14.7/ISE_DS/ISE/xbr/data -v build/mirny.jed:w
-# look for "Verify: Success"
```
+## Flashing
+
+With Digilent [JTAG HS2](https://store.digilentinc.com/jtag-hs2-programming-cable/) cable:
+
+ - download firmware to dongle. Manually (adjust USB bus as needed):
+ ```
+ /sbin/fxload -t fx2 -I /opt/Xilinx/14.7/ISE_DS/ISE/bin/lin64/xusb_xp2.hex -D /dev/bus/usb/001/*`cat /sys/bus/usb/devices/1-3/devnum`
+ ```
+ or automatically via the ``udev`` rule:
+ ```
+ SUBSYSTEM=="usb", ACTION="add", ATTR{idVendor}=="0403", ATTR{idProduct}=="6014", ATTR{manufacturer}=="Digilent", RUN+="/usr/bin/fxload -v -t fx2 -I /opt/Xilinx/14.7/ISE_DS/ISE/bin/lin64/xusb_xp2.hex -D $tempnode"
+ ```
+
+ - install [xc3sprog](http://xc3sprog.sourceforge.net/)
+
+ - ``flash_xc3.sh jtaghs2``
+
+ - look for ``Verify: Success``
+
+
# License
GPLv3+
diff --git a/flash_xc3.sh b/flash_xc3.sh
index 4c8a94c..c84b4d6 100755
--- a/flash_xc3.sh
+++ b/flash_xc3.sh
@@ -1,8 +1,9 @@
#!/bin/bash
set -e
-set -x
-/sbin/fxload -t fx2 -I /opt/Xilinx/14.7/ISE_DS/ISE/bin/lin64/xusb_xp2.hex -D /dev/bus/usb/001/*`cat /sys/bus/usb/devices/1-7/devnum`
-sleep 7
-../xc3sprog/build/xc3sprog -c xpc -m /opt/Xilinx/14.7/ISE_DS/ISE/xbr/data -v build/mirny.jed:w
+XC3SPROG=xc3sprog
+CABLE=${1-xpc}
+
+set -x
+$XC3SPROG -c $CABLE -m /opt/Xilinx/14.7/ISE_DS/ISE/xbr/data -v build/mirny.jed:w
diff --git a/mirny.py b/mirny.py
index 82edca2..6dc2612 100644
--- a/mirny.py
+++ b/mirny.py
@@ -153,7 +153,6 @@ class SR(Module):
),
]
-
def intersection(a, b):
(aa, am), (ba, bm) = a, b
# TODO
@@ -182,26 +181,26 @@ class Mirny(Module):
SPI
---
- SPI xfer is ADR(7), WE(1), DAT(REG: 16, ATT: 8, PLL: 32)
-
- | ADR | TARGET |
- |--------+--------|
- | 0 | REG0 |
- | 1 | REG1 |
- | 2 | REG2 |
- | 3 | REG3 |
- | 4 | PLL0 |
- | 5 | PLL1 |
- | 6 | PLL2 |
- | 7 | PLL3 |
- | 8 | ATT0 |
- | 9 | ATT1 |
- | a | ATT2 |
- | b | ATT3 |
- | c | reserved |
- | d | reserved |
- | e | reserved |
- | f | reserved |
+ SPI xfer is ADR(7), WE(1), DAT(REG: 16, ATT: 8, PLL: 32, SR: 8)
+
+ | ADR | TARGET |
+ |-----+----------------------|
+ | 0 | REG0 |
+ | 1 | REG1 |
+ | 2 | REG2 |
+ | 3 | REG3 |
+ | 4 | PLL0 |
+ | 5 | PLL1 |
+ | 6 | PLL2 |
+ | 7 | PLL3 |
+ | 8 | ATT0 |
+ | 9 | ATT1 |
+ | a | ATT2 |
+ | b | ATT3 |
+ | c | (Legacy Almazny) SR1 |
+ | d | (Legacy Almazny) SR2 |
+ | e | (Legacy Almazny) SR3 |
+ | f | (Legacy Almazny) SR4 |
The SPI interface is CPOL=0, CPHA=0, SPI mode 0, 4-wire, full fuplex.
@@ -223,8 +222,8 @@ class Mirny(Module):
| Name | Width | Function |
|-----------+-------+------------------------------------|
| CE_N | 4 | PLL chip enable (bar) |
- | CLK_SEL | 2 | Selects CLK source: 0 OSC, 1 MMCX, |
- | | | 2 reserved, 3 SMA |
+ | CLK_SEL | 2 | Selects CLK source: |
+ | | | 0 OSC, 1 reserved, 2 MMCX, 3 SMA |
| DIV | 2 | Clock divider configuration: |
| | | 0: divide-by-one, |
| | | 1: reserved, |
@@ -234,6 +233,7 @@ class Mirny(Module):
| FSEN_N | 1 | LVDS fail safe, Type 2 (bar) |
| MUXOUT_EEM| 1 | route MUXOUT to EEM[4:8] |
| EEM_MEZZIO| 1 | route EEM[4:8] to MEZZ_IO[0:4] |
+ | ALMAZNY_OE| 1 | Almazny OE in legacy Almazny mode |
| Name | Width | Function |
|-----------+-------+------------------------------------|
@@ -250,7 +250,7 @@ class Mirny(Module):
The test points expose miscellaneous signals for debugging and are not part
of the protocol revision.
"""
- def __init__(self, platform):
+ def __init__(self, platform, legacy_almazny=False):
self.eem = eem = []
for i in range(8):
tsi = TSTriple()
@@ -292,7 +292,7 @@ class Mirny(Module):
self.sr.ext.cs.eq(eem[3].i),
]
- regs = [REG(), REG(width=12), REG(width=4), REG()]
+ regs = [REG(), REG(width=13), REG(width=4), REG()]
self.submodules += regs
for i, reg in enumerate(regs):
self.sr.connect(reg.bus, adr=i, mask=mask)
@@ -310,23 +310,47 @@ class Mirny(Module):
clk = platform.request("clk")
clk_div = TSTriple()
self.specials += clk_div.get_tristate(clk.div)
- # in_sel: 00: XO, 01: MMCX, 10: n/a (SMA+XO), 11: SMA
+ # in_sel: 00: XO, 01: n/a (SMA+XO), 10: MMCX, 11: SMA
# dividers: 00(z): 1, 01(z): 1, 10(low): 2, 11(high) 4
self.comb += [
Cat(clk.in_sel, clk_div.o, clk_div.oe).eq(regs[1].write[4:8]),
platform.request("fsen").eq(~regs[1].write[9]),
]
- for i, m in enumerate(platform.request("mezz_io")):
- tsi = TSTriple()
- self.specials += tsi.get_tristate(m)
+ if legacy_almazny:
+ almazny_io = platform.request("legacy_almazny_common")
+ almazny_adr = 0b1100 # 1100 - and then 1101, 1110, 1111 for sr 1-4
+ ext = Record(ext_layout)
+ self.sr.connect_ext(ext, almazny_adr, almazny_adr)
+ latches = AsyncRst(width=4, reset=0xF)
+ self.submodules += latches
+
self.comb += [
- tsi.o.eq(regs[3].write[i] | (0 if i >= 4 else
- (regs[1].write[11] & eem[i + 4].i))),
- regs[3].read[i].eq(tsi.i),
- tsi.oe.eq(regs[3].write[i + 8]),
- regs[3].read[i + 8].eq(tsi.oe),
+ latches.ce.eq(ext.cs),
+ almazny_io.clk.eq(ext.sck),
+ almazny_io.mosi.eq(ext.sdi),
+ almazny_io.srclr.eq(1)
]
+
+ for i in range(4):
+ almazny = platform.request("legacy_almazny", i)
+ self.sync += latches.i[i].eq(self.sr.bus.adr[:2] != i)
+ self.comb += [
+ almazny.latch.eq(latches.o[i]),
+ almazny.noe.eq(~regs[1].write[12])
+ ]
+
+ else:
+ for i, m in enumerate(platform.request("mezz_io")):
+ tsi = TSTriple()
+ self.specials += tsi.get_tristate(m)
+ self.comb += [
+ tsi.o.eq(regs[3].write[i] | (0 if i >= 4 else
+ (regs[1].write[11] & eem[i + 4].i))),
+ regs[3].read[i].eq(tsi.i),
+ tsi.oe.eq(regs[3].write[i + 8]),
+ regs[3].read[i + 8].eq(tsi.oe),
+ ]
for i in range(4):
rf_sw = platform.request("rf_sw", i)
diff --git a/mirny_cpld.py b/mirny_cpld.py
index 70fc164..a688d89 100644
--- a/mirny_cpld.py
+++ b/mirny_cpld.py
@@ -16,9 +16,33 @@ _io = [
# fail save LVDS enable, LVDS mode selection
# high: type 2 receiver, failsafe low
("fsen", 0, Pins("P80")),
-
+
+ # IO from 0 to 7
("mezz_io", 0, Pins("P57 P58 P59 P60 P61 P64 P68 P69")),
+ # legacy (v1.0-1.1) Almazny pins
+ ("legacy_almazny_common", 0,
+ Subsignal("mosi", Pins("P94")),
+ Subsignal("clk", Pins("P97")),
+ Subsignal("srclr", Pins("P60")),
+ ),
+ ("legacy_almazny", 0,
+ Subsignal("latch", Pins("P96")),
+ Subsignal("noe", Pins("P95")),
+ ),
+ ("legacy_almazny", 1,
+ Subsignal("latch", Pins("P100")),
+ Subsignal("noe", Pins("P98")),
+ ),
+ ("legacy_almazny", 2,
+ Subsignal("latch", Pins("P92")),
+ Subsignal("noe", Pins("P101")),
+ ),
+ ("legacy_almazny", 3,
+ Subsignal("latch", Pins("P57")),
+ Subsignal("noe", Pins("P58")),
+ ),
+
("clk", 0,
Subsignal("div", Pins("P53")),
Subsignal("in_sel", Pins("P54 P56")),
diff --git a/mirny_impl.py b/mirny_impl.py
index 0c42b0b..d7022dc 100644
--- a/mirny_impl.py
+++ b/mirny_impl.py
@@ -1,10 +1,23 @@
+import argparse
+
+def get_argparser():
+ parser = argparse.ArgumentParser(
+ description="Mirny CPLD firmware"
+ )
+ parser.add_argument("--legacy-almazny", action="store_true", default=False)
+
+ return parser
+
def main():
from mirny_cpld import Platform
from mirny import Mirny
+ args = get_argparser().parse_args()
+
p = Platform()
- mirny = Mirny(p)
- p.build(mirny, build_name="mirny", mode="cpld")
+ mirny = Mirny(p, args.legacy_almazny)
+ build_name = "mirny" if not args.legacy_almazny else "mirny_legacy_almazny"
+ p.build(mirny, build_name=build_name, mode="cpld")
if __name__ == "__main__":

View File

@ -1,183 +1,16 @@
{
"main-nac3": {
"enabled": 1,
"type": 1,
"hidden": false,
"description": "Main ARTIQ packages (with NAC3)",
"flake": "git+https://github.com/m-labs/artiq.git?ref=nac3",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 50
},
"nac3": {
"enabled": 1,
"type": 1,
"hidden": false,
"description": "Third generation ARTIQ compiler",
"flake": "git+https://git.m-labs.hk/M-Labs/nac3.git",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 50
},
"main-beta": {
"enabled": 1,
"type": 1,
"hidden": false,
"description": "Main ARTIQ packages (beta version)",
"flake": "git+https://github.com/m-labs/artiq.git",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 50
},
"extra-beta": {
"enabled": 1,
"type": 1,
"hidden": false,
"description": "Additional ARTIQ packages (beta version)",
"flake": "git+https://git.m-labs.hk/m-labs/artiq-extrapkg.git",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 50
},
"zynq-beta": {
"enabled": 1,
"type": 1,
"hidden": false,
"description": "ARTIQ on Zynq-7000 (beta version)",
"flake": "git+https://git.m-labs.hk/m-labs/artiq-zynq.git",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 50
},
"main": {
"enabled": 1,
"type": 1,
"hidden": false,
"description": "Main ARTIQ packages (stable version)",
"flake": "git+https://github.com/m-labs/artiq.git?ref=release-8",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 50
},
"extra": {
"enabled": 1,
"type": 1,
"hidden": false,
"description": "Additional ARTIQ packages (stable version)",
"flake": "git+https://git.m-labs.hk/m-labs/artiq-extrapkg.git?ref=release-8",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 50
},
"zynq": {
"enabled": 1,
"type": 1,
"hidden": false,
"description": "ARTIQ on Zynq-7000 (stable version)",
"flake": "git+https://git.m-labs.hk/m-labs/artiq-zynq.git?ref=release-8",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 50
},
"main-legacy": {
"enabled": 1,
"type": 1,
"hidden": false,
"description": "Main ARTIQ packages (legacy version)",
"flake": "git+https://github.com/m-labs/artiq.git?ref=release-7",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 50
},
"extra-legacy": {
"enabled": 1,
"type": 1,
"hidden": false,
"description": "Additional ARTIQ packages (legacy version)",
"flake": "git+https://git.m-labs.hk/m-labs/artiq-extrapkg.git?ref=release-7",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 50
},
"zynq-legacy": {
"enabled": 1,
"type": 1,
"hidden": false,
"description": "ARTIQ on Zynq-7000 (legacy version)",
"flake": "git+https://git.m-labs.hk/m-labs/artiq-zynq.git?ref=release-7",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 50
},
"gluelogic": {
"enabled": 1,
"hidden": false,
"description": "Glue logic gateware for Sinara devices",
"nixexprinput": "nixScripts",
"nixexprpath": "gluelogic.nix",
"checkinterval": 172800,
"schedulingshares": 1,
"enableemail": false,
"emailoverride": "",
"keepnr": 50,
"inputs": {
"nixpkgs": { "type": "git", "value": "https://github.com/NixOS/nixpkgs.git nixos-24.11", "emailresponsible": false },
"nixScripts": { "type": "git", "value": "https://git.m-labs.hk/M-Labs/nix-scripts.git", "emailresponsible": false },
"urukulSrc": { "type": "git", "value": "https://github.com/quartiq/urukul.git", "emailresponsible": false },
"mirnySrc": { "type": "git", "value": "https://github.com/quartiq/mirny.git", "emailresponsible": false },
"fastinoSrc": { "type": "git", "value": "https://github.com/quartiq/fastino.git", "emailresponsible": false },
"phaserSrc": { "type": "git", "value": "https://github.com/quartiq/phaser.git", "emailresponsible": false }
}
},
"sipyco": {
"enabled": 1,
"type": 1,
"hidden": false,
"description": "Simple Python Communications",
"flake": "git+https://github.com/m-labs/sipyco.git",
"checkinterval": 600,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 50
},
"zynq-rs": {
"enabled": 1,
"type": 1,
"hidden": false,
"description": "Bare-metal Rust on Zynq-7000",
"flake": "git+https://git.m-labs.hk/m-labs/zynq-rs.git",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 50
"enabled": 1,
"hidden": true,
"description": "js",
"nixexprinput": "nixScripts",
"nixexprpath": "hydra/artiq.nix",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 10,
"inputs": {
"nixpkgs": { "type": "git", "value": "git://github.com/NixOS/nixpkgs-channels nixos-20.03", "emailresponsible": false },
"nixScripts": { "type": "git", "value": "https://git.m-labs.hk/astro/nix-scripts.git wfvm", "emailresponsible": false }
}
}

119
hydra/artiq.nix Normal file
View File

@ -0,0 +1,119 @@
{ pkgs ? import <nixpkgs> {}}:
{
jobsets = pkgs.runCommand "spec.json" {}
''
cat > $out << EOF
{
"fast-beta": {
"enabled": 1,
"hidden": false,
"description": "Core ARTIQ packages to build fast for CI purposes (beta version)",
"nixexprinput": "nixScripts",
"nixexprpath": "artiq-fast.nix",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 10,
"inputs": {
"nixpkgs": { "type": "git", "value": "git://github.com/NixOS/nixpkgs-channels nixos-20.03", "emailresponsible": false },
"nixScripts": { "type": "git", "value": "https://git.m-labs.hk/astro/nix-scripts.git wfvm", "emailresponsible": false },
"artiqSrc": { "type": "git", "value": "git://github.com/m-labs/artiq.git master 1", "emailresponsible": false }
}
},
"full-beta": {
"enabled": 1,
"hidden": false,
"description": "Full set of ARTIQ packages (beta version)",
"nixexprinput": "nixScripts",
"nixexprpath": "artiq-full.nix",
"checkinterval": 86400,
"schedulingshares": 1,
"enableemail": false,
"emailoverride": "",
"keepnr": 10,
"inputs": {
"nixpkgs": { "type": "git", "value": "git://github.com/NixOS/nixpkgs-channels nixos-20.03", "emailresponsible": false },
"nixScripts": { "type": "git", "value": "https://git.m-labs.hk/astro/nix-scripts.git wfvm", "emailresponsible": false },
"sinaraSystemsSrc": { "type": "git", "value": "https://git.m-labs.hk/M-Labs/sinara-systems.git master 1", "emailresponsible": false },
"artiq-fast": { "type": "sysbuild", "value": "artiq:fast-beta:generated-nix", "emailresponsible": false }
}
},
"fast": {
"enabled": 1,
"hidden": false,
"description": "Core ARTIQ packages to build fast for CI purposes",
"nixexprinput": "nixScripts",
"nixexprpath": "artiq-fast.nix",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 10,
"inputs": {
"nixpkgs": { "type": "git", "value": "git://github.com/NixOS/nixpkgs-channels nixos-20.03", "emailresponsible": false },
"nixScripts": { "type": "git", "value": "https://git.m-labs.hk/astro/nix-scripts.git wfvm", "emailresponsible": false },
"artiqSrc": { "type": "git", "value": "git://github.com/m-labs/artiq.git release-5 1", "emailresponsible": false }
}
},
"full": {
"enabled": 1,
"hidden": false,
"description": "Full set of ARTIQ packages",
"nixexprinput": "nixScripts",
"nixexprpath": "artiq-full.nix",
"checkinterval": 86400,
"schedulingshares": 1,
"enableemail": false,
"emailoverride": "",
"keepnr": 10,
"inputs": {
"nixpkgs": { "type": "git", "value": "git://github.com/NixOS/nixpkgs-channels nixos-20.03", "emailresponsible": false },
"nixScripts": { "type": "git", "value": "https://git.m-labs.hk/astro/nix-scripts.git wfvm", "emailresponsible": false },
"sinaraSystemsSrc": { "type": "git", "value": "https://git.m-labs.hk/M-Labs/sinara-systems.git master 1", "emailresponsible": false },
"artiq-fast": { "type": "sysbuild", "value": "artiq:fast:generated-nix", "emailresponsible": false }
}
},
"gluelogic": {
"enabled": 1,
"hidden": false,
"description": "Glue logic gateware for Sinara devices",
"nixexprinput": "nixScripts",
"nixexprpath": "gluelogic.nix",
"checkinterval": 172800,
"schedulingshares": 1,
"enableemail": false,
"emailoverride": "",
"keepnr": 10,
"inputs": {
"nixpkgs": { "type": "git", "value": "git://github.com/NixOS/nixpkgs-channels nixos-20.03", "emailresponsible": false },
"nixScripts": { "type": "git", "value": "https://git.m-labs.hk/astro/nix-scripts.git wfvm", "emailresponsible": false },
"urukulSrc": { "type": "git", "value": "git://github.com/quartiq/urukul", "emailresponsible": false },
"mirnySrc": { "type": "git", "value": "git://github.com/quartiq/mirny", "emailresponsible": false },
"fastinoSrc": { "type": "git", "value": "git://github.com/quartiq/fastino", "emailresponsible": false }
}
},
"zynq": {
"enabled": 1,
"hidden": false,
"description": "ARTIQ on the Zynq-based ZC706 board",
"nixexprinput": "nixScripts",
"nixexprpath": "zynq.nix",
"checkinterval": 300,
"schedulingshares": 1,
"enableemail": false,
"emailoverride": "",
"keepnr": 10,
"inputs": {
"nixpkgs": { "type": "git", "value": "git://github.com/NixOS/nixpkgs-channels nixos-20.03", "emailresponsible": false },
"nixScripts": { "type": "git", "value": "https://git.m-labs.hk/astro/nix-scripts.git wfvm", "emailresponsible": false },
"mozillaOverlay": { "type": "git", "value": "git://github.com/mozilla/nixpkgs-mozilla", "emailresponsible": false },
"artiq-fast": { "type": "sysbuild", "value": "artiq:fast-beta:generated-nix", "emailresponsible": false },
"zc706": { "type": "git", "value": "https://git.m-labs.hk/M-Labs/zc706.git", "emailresponsible": false },
"artiq-zynq": { "type": "git", "value": "https://git.m-labs.hk/M-Labs/artiq-zynq.git", "emailresponsible": false }
}
}
}
EOF
'';
}

16
hydra/fpga.json Normal file
View File

@ -0,0 +1,16 @@
{
"enabled": 1,
"hidden": true,
"description": "js",
"nixexprinput": "nixScripts",
"nixexprpath": "hydra/fpga.nix",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 10,
"inputs": {
"nixpkgs": { "type": "git", "value": "git://github.com/NixOS/nixpkgs-channels nixos-19.03", "emailresponsible": false },
"nixScripts": { "type": "git", "value": "https://git.m-labs.hk/astro/nix-scripts.git wfvm", "emailresponsible": false }
}
}

26
hydra/fpga.nix Normal file
View File

@ -0,0 +1,26 @@
{ pkgs ? import <nixpkgs> {}}:
{
jobsets = pkgs.runCommand "spec.json" {}
''
cat > $out << EOF
{
"heavyx": {
"enabled": 1,
"hidden": false,
"description": "HeavyX SoC toolkit experiment",
"nixexprinput": "heavyx",
"nixexprpath": "release.nix",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 10,
"inputs": {
"nixpkgs": { "type": "git", "value": "git://github.com/NixOS/nixpkgs-channels nixos-19.03", "emailresponsible": false },
"heavyx": { "type": "git", "value": "https://git.m-labs.hk/M-Labs/HeavyX.git", "emailresponsible": false }
}
}
}
EOF
'';
}

View File

@ -1,56 +0,0 @@
{
"mcu-contrib": {
"enabled": 1,
"hidden": false,
"description": "Third-party MCU firmware",
"nixexprinput": "nixScripts",
"nixexprpath": "mcu-contrib.nix",
"checkinterval": 7200,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 10,
"inputs": {
"nixpkgs": { "type": "git", "value": "https://github.com/NixOS/nixpkgs.git nixos-24.11", "emailresponsible": false },
"mozillaOverlay": { "type": "git", "value": "https://github.com/mozilla/nixpkgs-mozilla.git", "emailresponsible": false },
"nixScripts": { "type": "git", "value": "https://git.m-labs.hk/M-Labs/nix-scripts.git", "emailresponsible": false },
"stabilizerSrc": { "type": "git", "value": "https://github.com/quartiq/stabilizer.git main", "emailresponsible": false }
}
},
"thermostat": {
"enabled": 1,
"type": 1,
"hidden": false,
"description": "Firmware for the Sinara 8451 Thermostat",
"flake": "git+https://git.m-labs.hk/M-Labs/thermostat.git",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 10
},
"humpback-dds": {
"enabled": 1,
"type": 1,
"hidden": false,
"description": "Firmware for Humpback-DDS",
"flake": "git+https://git.m-labs.hk/M-Labs/humpback-dds.git",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 10
},
"kirdy": {
"enabled": 1,
"type": 1,
"hidden": false,
"description": "Firmware for the Sinara 1550 Kirdy laser diode driver",
"flake": "git+https://git.m-labs.hk/M-Labs/kirdy.git",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 10
}
}

16
hydra/stm32.json Normal file
View File

@ -0,0 +1,16 @@
{
"enabled": 1,
"hidden": true,
"description": "js",
"nixexprinput": "nixScripts",
"nixexprpath": "hydra/stm32.nix",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 10,
"inputs": {
"nixpkgs": { "type": "git", "value": "git://github.com/NixOS/nixpkgs-channels nixos-20.03", "emailresponsible": false },
"nixScripts": { "type": "git", "value": "https://git.m-labs.hk/astro/nix-scripts.git wfvm", "emailresponsible": false }
}
}

29
hydra/stm32.nix Normal file
View File

@ -0,0 +1,29 @@
{ pkgs ? import <nixpkgs> {}}:
{
jobsets = pkgs.runCommand "spec.json" {}
''
cat > $out << EOF
{
"stm32": {
"enabled": 1,
"hidden": false,
"description": "STM32 firmware",
"nixexprinput": "nixScripts",
"nixexprpath": "stm32.nix",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 10,
"inputs": {
"nixpkgs": { "type": "git", "value": "git://github.com/NixOS/nixpkgs-channels nixos-20.03", "emailresponsible": false },
"mozillaOverlay": { "type": "git", "value": "git://github.com/mozilla/nixpkgs-mozilla.git", "emailresponsible": false },
"nixScripts": { "type": "git", "value": "https://git.m-labs.hk/astro/nix-scripts.git wfvm", "emailresponsible": false },
"stabilizerSrc": { "type": "git", "value": "git://github.com/quartiq/stabilizer.git", "emailresponsible": false },
"thermostatSrc": { "type": "git", "value": "https://git.m-labs.hk/M-Labs/thermostat.git", "emailresponsible": false }
}
}
}
EOF
'';
}

View File

@ -1,20 +1,16 @@
{
"web": {
"enabled": 1,
"hidden": false,
"description": "Websites",
"nixexprinput": "nixScripts",
"nixexprpath": "web.nix",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 10,
"inputs": {
"nixpkgs": { "type": "git", "value": "https://github.com/NixOS/nixpkgs.git nixos-24.11", "emailresponsible": false },
"nixScripts": { "type": "git", "value": "https://git.m-labs.hk/M-Labs/nix-scripts.git", "emailresponsible": false },
"webSrc": { "type": "git", "value": "https://git.m-labs.hk/M-Labs/web2019.git", "emailresponsible": false },
"nmigenSrc": { "type": "git", "value": "https://gitlab.com/nmigen/nmigen.git", "emailresponsible": false }
}
"enabled": 1,
"hidden": true,
"description": "js",
"nixexprinput": "nixScripts",
"nixexprpath": "hydra/web.nix",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 10,
"inputs": {
"nixpkgs": { "type": "git", "value": "git://github.com/NixOS/nixpkgs-channels nixos-20.03", "emailresponsible": false },
"nixScripts": { "type": "git", "value": "https://git.m-labs.hk/astro/nix-scripts.git wfvm", "emailresponsible": false }
}
}

27
hydra/web.nix Normal file
View File

@ -0,0 +1,27 @@
{ pkgs ? import <nixpkgs> {}}:
{
jobsets = pkgs.runCommand "spec.json" {}
''
cat > $out << EOF
{
"web": {
"enabled": 1,
"hidden": false,
"description": "M-Labs website",
"nixexprinput": "nixScripts",
"nixexprpath": "web.nix",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 10,
"inputs": {
"nixpkgs": { "type": "git", "value": "git://github.com/NixOS/nixpkgs-channels nixos-20.03", "emailresponsible": false },
"nixScripts": { "type": "git", "value": "https://git.m-labs.hk/astro/nix-scripts.git wfvm", "emailresponsible": false },
"webSrc": { "type": "git", "value": "https://git.m-labs.hk/M-Labs/web2019.git", "emailresponsible": false }
}
}
}
EOF
'';
}

View File

@ -1,8 +0,0 @@
{ pkgs ? import <nixpkgs> {} }:
let
jobs = import ./mcu-contrib/default.nix {
mozillaOverlay = import <mozillaOverlay>;
};
in
builtins.mapAttrs (key: value: pkgs.lib.hydraJob value) jobs

View File

@ -1,82 +0,0 @@
{ # Use master branch of the overlay by default
mozillaOverlay ? import (builtins.fetchTarball https://github.com/mozilla/nixpkgs-mozilla/archive/master.tar.gz),
}:
let
pkgs = import <nixpkgs> { overlays = [ mozillaOverlay ]; };
targets = [
"thumbv7em-none-eabihf"
];
rustManifest = pkgs.fetchurl {
url = "https://static.rust-lang.org/dist/2024-11-28/channel-rust-stable.toml";
sha256 = "b3544fb72bc3189697fc18ac2d3fa27d57ee8434f59d9919d4d70af2c6f010b3";
};
rustChannelOfTargets = _channel: _date: targets:
(pkgs.lib.rustLib.fromManifestFile rustManifest {
inherit (pkgs) stdenv lib fetchurl patchelf;
}).rust.override {
inherit targets;
extensions = ["rust-src"];
};
rust = rustChannelOfTargets "nightly" null targets;
rustPlatform = pkgs.recurseIntoAttrs (pkgs.makeRustPlatform {
rustc = rust // {
# https://github.com/oxalica/rust-overlay/commit/c48c2d76b68dd9ede0815fec53479375c61af857
targetPlatforms = pkgs.lib.platforms.all;
tier1TargetPlatforms = pkgs.lib.platforms.all;
badTargetPlatforms = [ ];
};
cargo = rust;
});
buildStm32Firmware = { name, src, cargoDepsName ? name, patchPhase ? "", extraNativeBuildInputs ? [], checkPhase ? "", doCheck ? true, binaryName ? name, extraCargoBuildArgs ? "", outputHashes ? {} }:
rustPlatform.buildRustPackage rec {
inherit name cargoDepsName;
version = "0.0.0";
inherit src;
cargoLock = { lockFile = "${src}/Cargo.lock"; inherit outputHashes; };
inherit patchPhase;
nativeBuildInputs = [ pkgs.llvm ] ++ extraNativeBuildInputs;
buildPhase = ''
export CARGO_HOME=$(mktemp -d cargo-home.XXX)
cargo build --release --bin ${binaryName} ${extraCargoBuildArgs}
'';
inherit checkPhase doCheck;
# binaryName defaults to the `name` arg (i.e. the Rust package name);
# it is used as the Cargo binary filename
installPhase = ''
mkdir -p $out $out/nix-support
cp target/thumbv7em-none-eabihf/release/${binaryName} $out/${name}.elf
echo file binary-dist $out/${name}.elf >> $out/nix-support/hydra-build-products
llvm-objcopy -O binary target/thumbv7em-none-eabihf/release/${binaryName} $out/${name}.bin
echo file binary-dist $out/${name}.bin >> $out/nix-support/hydra-build-products
'';
dontFixup = true;
auditable = false;
};
in
pkgs.lib.attrsets.mapAttrs'
(name: value: pkgs.lib.attrsets.nameValuePair ("stabilizer-" + name)
(buildStm32Firmware ({
name = "stabilizer-" + name;
# If binaryName is not specified, use the attribute name as binaryName by default.
binaryName = name;
cargoDepsName = "stabilizer";
src = <stabilizerSrc>;
patchPhase = ''
patch -p1 < ${./pounder-725.diff}
'';
doCheck = false;
} // value))) {
dual-iir = {};
dual-iir-pounder_v1_0 = {
binaryName = "dual-iir";
extraCargoBuildArgs = "--features pounder_v1_0";
};
lockin = {};
}

View File

@ -1,883 +0,0 @@
diff --git a/ad9959/src/lib.rs b/ad9959/src/lib.rs
index 025f7d4f..59578cce 100644
--- a/ad9959/src/lib.rs
+++ b/ad9959/src/lib.rs
@@ -2,8 +2,24 @@
use bit_field::BitField;
use bitflags::bitflags;
+use core::ops::Range;
use embedded_hal::{blocking::delay::DelayUs, digital::v2::OutputPin};
+/// The minimum reference clock input frequency with REFCLK multiplier disabled.
+const MIN_REFCLK_FREQUENCY: f32 = 1e6;
+/// The minimum reference clock input frequency with REFCLK multiplier enabled.
+const MIN_MULTIPLIED_REFCLK_FREQUENCY: f32 = 10e6;
+/// The system clock frequency range with high gain configured for the internal VCO.
+const HIGH_GAIN_VCO_RANGE: Range<f32> = Range {
+ start: 255e6,
+ end: 500e6,
+};
+/// The system clock frequency range with low gain configured for the internal VCO.
+const LOW_GAIN_VCO_RANGE: Range<f32> = Range {
+ start: 100e6,
+ end: 160e6,
+};
+
/// A device driver for the AD9959 direct digital synthesis (DDS) chip.
///
/// This chip provides four independently controllable digital-to-analog output sinusoids with
@@ -218,23 +234,17 @@ impl<I: Interface> Ad9959<I> {
reference_clock_frequency: f32,
multiplier: u8,
) -> Result<f32, Error> {
+ let frequency =
+ validate_clocking(reference_clock_frequency, multiplier)?;
self.reference_clock_frequency = reference_clock_frequency;
- if multiplier != 1 && !(4..=20).contains(&multiplier) {
- return Err(Error::Bounds);
- }
-
- let frequency = multiplier as f32 * self.reference_clock_frequency;
- if frequency > 500_000_000.0f32 {
- return Err(Error::Frequency);
- }
-
// TODO: Update / disable any enabled channels?
let mut fr1: [u8; 3] = [0, 0, 0];
self.read(Register::FR1, &mut fr1)?;
fr1[0].set_bits(2..=6, multiplier);
- let vco_range = frequency > 255e6;
+ let vco_range = HIGH_GAIN_VCO_RANGE.contains(&frequency)
+ || frequency == HIGH_GAIN_VCO_RANGE.end;
fr1[0].set_bit(7, vco_range);
self.write(Register::FR1, &fr1)?;
@@ -365,9 +375,7 @@ impl<I: Interface> Ad9959<I> {
channel: Channel,
phase_turns: f32,
) -> Result<f32, Error> {
- let phase_offset: u16 =
- (phase_turns * (1 << 14) as f32) as u16 & 0x3FFFu16;
-
+ let phase_offset = phase_to_pow(phase_turns)?;
self.modify_channel(
channel,
Register::CPOW0,
@@ -513,6 +521,108 @@ impl<I: Interface> Ad9959<I> {
}
}
+/// Validate the internal system clock configuration of the chip.
+///
+/// Arguments:
+/// * `reference_clock_frequency` - The reference clock frequency provided to the AD9959 core.
+/// * `multiplier` - The frequency multiplier of the system clock. Must be 1 or 4-20.
+///
+/// Returns:
+/// The system clock frequency to be configured.
+pub fn validate_clocking(
+ reference_clock_frequency: f32,
+ multiplier: u8,
+) -> Result<f32, Error> {
+ // The REFCLK frequency must be at least 1 MHz with REFCLK multiplier disabled.
+ if reference_clock_frequency < MIN_REFCLK_FREQUENCY {
+ return Err(Error::Bounds);
+ }
+ // If the REFCLK multiplier is enabled, the multiplier (FR1[22:18]) must be between 4 to 20.
+ // Alternatively, the clock multiplier can be disabled. The multiplication factor is 1.
+ if multiplier != 1 && !(4..=20).contains(&multiplier) {
+ return Err(Error::Bounds);
+ }
+ // If the REFCLK multiplier is enabled, the REFCLK frequency must be at least 10 MHz.
+ if multiplier != 1
+ && reference_clock_frequency < MIN_MULTIPLIED_REFCLK_FREQUENCY
+ {
+ return Err(Error::Bounds);
+ }
+ let frequency = multiplier as f32 * reference_clock_frequency;
+ // SYSCLK frequency between 255 MHz and 500 MHz (inclusive) is valid with high range VCO
+ if HIGH_GAIN_VCO_RANGE.contains(&frequency)
+ || frequency == HIGH_GAIN_VCO_RANGE.end
+ {
+ return Ok(frequency);
+ }
+
+ // SYSCLK frequency between 100 MHz and 160 MHz (inclusive) is valid with low range VCO
+ if LOW_GAIN_VCO_RANGE.contains(&frequency)
+ || frequency == LOW_GAIN_VCO_RANGE.end
+ {
+ return Ok(frequency);
+ }
+
+ // When the REFCLK multiplier is disabled, SYSCLK frequency can go below 100 MHz
+ if multiplier == 1 && (0.0..=LOW_GAIN_VCO_RANGE.start).contains(&frequency)
+ {
+ return Ok(frequency);
+ }
+
+ Err(Error::Frequency)
+}
+
+/// Convert and validate frequency into frequency tuning word.
+///
+/// Arguments:
+/// * `dds_frequency` - The DDS frequency to be converted and validated.
+/// * `system_clock_frequency` - The system clock frequency of the AD9959 core.
+///
+/// Returns:
+/// The corresponding frequency tuning word.
+pub fn frequency_to_ftw(
+ dds_frequency: f32,
+ system_clock_frequency: f32,
+) -> Result<u32, Error> {
+ // Output frequency should not exceed the Nyquist's frequency.
+ if !(0.0..=(system_clock_frequency / 2.0)).contains(&dds_frequency) {
+ return Err(Error::Bounds);
+ }
+ // The function for channel frequency is `f_out = FTW * f_s / 2^32`, where FTW is the
+ // frequency tuning word and f_s is the system clock rate.
+ Ok(((dds_frequency / system_clock_frequency) * (1u64 << 32) as f32) as u32)
+}
+
+/// Convert phase into phase offset word.
+///
+/// Arguments:
+/// * `phase_turns` - The normalized number of phase turns of a DDS channel.
+///
+/// Returns:
+/// The corresponding phase offset word.
+pub fn phase_to_pow(phase_turns: f32) -> Result<u16, Error> {
+ Ok((phase_turns * (1 << 14) as f32) as u16 & 0x3FFFu16)
+}
+
+/// Convert amplitude into amplitude control register values.
+///
+/// Arguments:
+/// * `amplitude` - The normalized amplitude of a DDS channel.
+///
+/// Returns:
+/// The corresponding value in the amplitude control register.
+pub fn amplitude_to_acr(amplitude: f32) -> Result<u32, Error> {
+ if !(0.0..=1.0).contains(&amplitude) {
+ return Err(Error::Bounds);
+ }
+
+ let acr: u32 = *0u32
+ .set_bits(0..=9, ((amplitude * (1 << 10) as f32) as u32) & 0x3FF)
+ .set_bit(12, amplitude != 1.0);
+
+ Ok(acr as u32)
+}
+
/// Represents a means of serializing a DDS profile for writing to a stream.
pub struct ProfileSerializer {
// heapless::Vec<u8, 32>, especially its extend_from_slice() is slow
@@ -568,6 +678,39 @@ impl ProfileSerializer {
}
}
+ /// Update the system clock configuration.
+ ///
+ /// # Args
+ /// * `reference_clock_frequency` - The reference clock frequency provided to the AD9959 core.
+ /// * `multiplier` - The frequency multiplier of the system clock. Must be 1 or 4-20.
+ ///
+ /// # Limitations
+ /// The correctness of the FR1 register setting code rely on FR1\[0:17\] staying 0.
+ pub fn set_system_clock(
+ &mut self,
+ reference_clock_frequency: f32,
+ multiplier: u8,
+ ) -> Result<f32, Error> {
+ let frequency = reference_clock_frequency * multiplier as f32;
+
+ // The enabled channel will be updated after clock reconfig
+ let mut fr1 = [0u8; 3];
+
+ // The ad9959 crate does not modify FR1[0:17]. These bits keep their default value.
+ // These bits by default are 0.
+ // Reading the register then update is not possible to implement in a serializer, where
+ // many QSPI writes are performed in burst. Switching between read and write requires
+ // breaking the QSPI indirect write mode and switch into the QSPI indirect read mode.
+ fr1[0].set_bits(2..=6, multiplier);
+
+ // Frequencies within the VCO forbidden range (160e6, 255e6) are already rejected.
+ let vco_range = HIGH_GAIN_VCO_RANGE.contains(&frequency);
+ fr1[0].set_bit(7, vco_range);
+
+ self.add_write(Register::FR1, &fr1);
+ Ok(frequency)
+ }
+
/// Add a register write to the serialization data.
fn add_write(&mut self, register: Register, value: &[u8]) {
let data = &mut self.data[self.index..];
diff --git a/src/bin/dual-iir.rs b/src/bin/dual-iir.rs
index d4146cc2..b9bc99d9 100644
--- a/src/bin/dual-iir.rs
+++ b/src/bin/dual-iir.rs
@@ -28,7 +28,7 @@
#![no_std]
#![no_main]
-use core::mem::MaybeUninit;
+use core::mem::{MaybeUninit, size_of};
use core::sync::atomic::{fence, Ordering};
use miniconf::{Leaf, Tree};
use serde::{Deserialize, Serialize};
@@ -48,6 +48,8 @@ use stabilizer::{
dac::{Dac0Output, Dac1Output, DacCode},
hal,
signal_generator::{self, SignalGenerator},
+ pounder::{ClockConfig, PounderConfig},
+ setup::PounderDevices as Pounder,
timers::SamplingTimer,
DigitalInput0, DigitalInput1, SerialTerminal, SystemTimer, Systick,
UsbDevice, AFE0, AFE1,
@@ -173,6 +175,16 @@ pub struct DualIir {
/// # Value
/// See [signal_generator::BasicConfig#miniconf]
source: [signal_generator::BasicConfig; 2],
+
+ /// Specifies the config for pounder DDS clock configuration, DDS channels & attenuations
+ ///
+ /// # Path
+ /// `pounder`
+ ///
+ /// # Value
+ /// See [PounderConfig#miniconf]
+ #[tree]
+ pounder: Option<PounderConfig>,
}
impl Default for DualIir {
@@ -200,6 +212,8 @@ impl Default for DualIir {
source: Default::default(),
stream: Default::default(),
+
+ pounder: None.into(),
}
}
}
@@ -211,22 +225,24 @@ mod app {
#[shared]
struct Shared {
usb: UsbDevice,
- network: NetworkUsers<DualIir, 3>,
+ network: NetworkUsers<DualIir, 6>,
settings: Settings,
active_settings: DualIir,
telemetry: TelemetryBuffer,
source: [SignalGenerator; 2],
+ pounder: Option<Pounder>,
}
#[local]
struct Local {
- usb_terminal: SerialTerminal<Settings, 4>,
+ usb_terminal: SerialTerminal<Settings, 6>,
sampling_timer: SamplingTimer,
digital_inputs: (DigitalInput0, DigitalInput1),
afes: (AFE0, AFE1),
adcs: (Adc0Input, Adc1Input),
dacs: (Dac0Output, Dac1Output),
iir_state: [[[f32; 4]; IIR_CASCADE_LENGTH]; 2],
+ dds_clock_state: Option<ClockConfig>,
generator: FrameGenerator,
cpu_temp_sensor: stabilizer::hardware::cpu_temp_sensor::CpuTempSensor,
}
@@ -236,7 +252,7 @@ mod app {
let clock = SystemTimer::new(|| Systick::now().ticks());
// Configure the microcontroller
- let (stabilizer, _pounder) = hardware::setup::setup::<Settings, 4>(
+ let (mut stabilizer, pounder) = hardware::setup::setup::<Settings, 6>(
c.core,
c.device,
clock,
@@ -255,6 +271,13 @@ mod app {
let generator = network.configure_streaming(StreamFormat::AdcDacData);
+ let dds_clock_state = pounder.as_ref().map(|_| ClockConfig::default());
+ if pounder.is_some() {
+ stabilizer.settings.dual_iir
+ .pounder
+ .replace(PounderConfig::default());
+ }
+
let shared = Shared {
usb: stabilizer.usb,
network,
@@ -273,6 +296,7 @@ mod app {
),
],
settings: stabilizer.settings,
+ pounder
};
let mut local = Local {
@@ -283,6 +307,7 @@ mod app {
adcs: stabilizer.adcs,
dacs: stabilizer.dacs,
iir_state: [[[0.; 4]; IIR_CASCADE_LENGTH]; 2],
+ dds_clock_state,
generator,
cpu_temp_sensor: stabilizer.temperature_sensor,
};
@@ -452,7 +477,7 @@ mod app {
}
}
- #[task(priority = 1, local=[afes], shared=[network, settings, active_settings, source])]
+ #[task(priority = 1, local=[afes, dds_clock_state], shared=[network, settings, active_settings, source, pounder])]
async fn settings_update(mut c: settings_update::Context) {
c.shared.settings.lock(|settings| {
c.local.afes.0.set_gain(*settings.dual_iir.afe[0]);
@@ -474,6 +499,17 @@ mod app {
),
}
}
+ // Update Pounder configurations
+ c.shared.pounder.lock(|pounder| {
+ if let Some(pounder) = pounder {
+ let pounder_settings = settings.dual_iir.pounder.as_ref().unwrap();
+ // let mut clocking = c.local.dds_clock_state;
+ pounder.update_dds(
+ *pounder_settings,
+ c.local.dds_clock_state.as_mut().unwrap(),
+ );
+ }
+ });
c.shared
.network
@@ -485,22 +521,31 @@ mod app {
});
}
- #[task(priority = 1, shared=[network, settings, telemetry], local=[cpu_temp_sensor])]
+ #[task(priority = 1, shared=[network, settings, telemetry, pounder], local=[cpu_temp_sensor])]
async fn telemetry(mut c: telemetry::Context) {
loop {
let telemetry =
c.shared.telemetry.lock(|telemetry| telemetry.clone());
- let (gains, telemetry_period) =
+ let (gains, telemetry_period, pounder_config) =
c.shared.settings.lock(|settings| {
- (settings.dual_iir.afe, *settings.dual_iir.telemetry_period)
+ (
+ settings.dual_iir.afe,
+ *settings.dual_iir.telemetry_period,
+ settings.dual_iir.pounder
+ )
});
+ let pounder_telemetry = c.shared.pounder.lock(|pounder| {
+ pounder.as_mut().map(|pdr| pdr.get_telemetry(pounder_config.unwrap()))
+ });
+
c.shared.network.lock(|net| {
net.telemetry.publish(&telemetry.finalize(
*gains[0],
*gains[1],
c.local.cpu_temp_sensor.get_temperature().unwrap(),
+ pounder_telemetry,
))
});
diff --git a/src/bin/lockin.rs b/src/bin/lockin.rs
index d8d193dd..4e5abb28 100644
--- a/src/bin/lockin.rs
+++ b/src/bin/lockin.rs
@@ -29,7 +29,7 @@
use core::{
convert::TryFrom,
- mem::MaybeUninit,
+ mem::{MaybeUninit, size_of},
sync::atomic::{fence, Ordering},
};
@@ -248,7 +248,7 @@ mod app {
#[shared]
struct Shared {
usb: UsbDevice,
- network: NetworkUsers<Lockin, 2>,
+ network: NetworkUsers<Lockin, 6>,
settings: Settings,
active_settings: Lockin,
telemetry: TelemetryBuffer,
@@ -256,7 +256,7 @@ mod app {
#[local]
struct Local {
- usb_terminal: SerialTerminal<Settings, 3>,
+ usb_terminal: SerialTerminal<Settings, 6>,
sampling_timer: SamplingTimer,
digital_inputs: (DigitalInput0, DigitalInput1),
timestamper: InputStamper,
@@ -275,7 +275,7 @@ mod app {
let clock = SystemTimer::new(|| Systick::now().ticks());
// Configure the microcontroller
- let (mut stabilizer, _pounder) = hardware::setup::setup::<Settings, 3>(
+ let (mut stabilizer, _pounder) = hardware::setup::setup::<Settings, 6>(
c.core,
c.device,
clock,
@@ -543,6 +543,7 @@ mod app {
*gains[0],
*gains[1],
c.local.cpu_temp_sensor.get_temperature().unwrap(),
+ None,
))
});
diff --git a/src/bin/urukul.rs b/src/bin/urukul.rs
index fc7faf40..10ff9016 100644
--- a/src/bin/urukul.rs
+++ b/src/bin/urukul.rs
@@ -104,21 +104,21 @@ mod app {
#[shared]
struct Shared {
usb: UsbDevice,
- network: NetworkUsers<App, 3>,
+ network: NetworkUsers<App, 6>,
settings: Settings,
}
#[local]
struct Local {
urukul: Urukul,
- usb_terminal: SerialTerminal<Settings, 4>,
+ usb_terminal: SerialTerminal<Settings, 6>,
}
#[init]
fn init(c: init::Context) -> (Shared, Local) {
let clock = SystemTimer::new(|| Systick::now().ticks());
- let (stabilizer, _pounder) = hardware::setup::setup::<Settings, 4>(
+ let (stabilizer, _pounder) = hardware::setup::setup::<Settings, 6>(
c.core,
c.device,
clock,
diff --git a/src/hardware/pounder/attenuators.rs b/src/hardware/pounder/attenuators.rs
index cfd08b7f..2570f506 100644
--- a/src/hardware/pounder/attenuators.rs
+++ b/src/hardware/pounder/attenuators.rs
@@ -52,10 +52,9 @@ pub trait AttenuatorInterface {
fn get_attenuation(&mut self, channel: Channel) -> Result<f32, Error> {
let mut channels = [0_u8; 4];
- // Reading the data always shifts data out of the staging registers, so we perform a
- // duplicate write-back to ensure the staging register is always equal to the output
- // register.
- self.transfer_attenuators(&mut channels)?;
+ // Reading the data always shifts data out of the staging registers, so a duplicate
+ // write-back will be performed to ensure the staging register is always equal to the
+ // output register.
self.transfer_attenuators(&mut channels)?;
// The attenuation code is stored in the upper 6 bits of the register, where each LSB
@@ -66,6 +65,9 @@ pub trait AttenuatorInterface {
// care) would contain erroneous data.
let attenuation_code = (!channels[channel as usize]) >> 2;
+ // The write-back transfer is performed. Staging register is now restored.
+ self.transfer_attenuators(&mut channels)?;
+
// Convert the desired channel code into dB of attenuation.
Ok(attenuation_code as f32 / 2.0)
}
diff --git a/src/hardware/pounder/dds_output.rs b/src/hardware/pounder/dds_output.rs
index 5527a8e1..23435e2e 100644
--- a/src/hardware/pounder/dds_output.rs
+++ b/src/hardware/pounder/dds_output.rs
@@ -55,7 +55,7 @@
use log::warn;
use stm32h7xx_hal as hal;
-use super::{hrtimer::HighResTimerE, QspiInterface};
+use super::{hrtimer::HighResTimerE, Profile, QspiInterface};
use ad9959::{Channel, Mode, ProfileSerializer};
/// The DDS profile update stream.
@@ -157,6 +157,46 @@ impl ProfileBuilder<'_> {
self
}
+ /// Update a number of channels with fully defined profile settings.
+ ///
+ /// # Args
+ /// * `channels` - A set of channels to apply the configuration to.
+ /// * `profile` - The complete DDS profile, which defines the frequency tuning word,
+ /// amplitude control register & the phase offset word of the channels.
+ /// # Note
+ /// The ACR should be stored in the 3 LSB of the word.
+ /// If amplitude scaling is to be used, the "Amplitude multiplier enable" bit must be set.
+ #[inline]
+ pub fn update_channels_with_profile(
+ &mut self,
+ channels: Channel,
+ profile: Profile,
+ ) -> &mut Self {
+ self.serializer.update_channels(
+ channels,
+ Some(profile.frequency_tuning_word),
+ Some(profile.phase_offset),
+ Some(profile.amplitude_control),
+ );
+ self
+ }
+
+ /// Update the system clock configuration.
+ ///
+ /// # Args
+ /// * `reference_clock_frequency` - The reference clock frequency provided to the AD9959 core.
+ /// * `multiplier` - The frequency multiplier of the system clock. Must be 1 or 4-20.
+ #[inline]
+ pub fn set_system_clock(
+ &mut self,
+ reference_clock_frequency: f32,
+ multiplier: u8,
+ ) -> Result<&mut Self, ad9959::Error> {
+ self.serializer
+ .set_system_clock(reference_clock_frequency, multiplier)?;
+ Ok(self)
+ }
+
/// Write the profile to the DDS asynchronously.
#[allow(dead_code)]
#[inline]
diff --git a/src/hardware/pounder/mod.rs b/src/hardware/pounder/mod.rs
index c144db0c..a6831605 100644
--- a/src/hardware/pounder/mod.rs
+++ b/src/hardware/pounder/mod.rs
@@ -1,10 +1,17 @@
use self::attenuators::AttenuatorInterface;
use super::hal;
-use crate::hardware::{shared_adc::AdcChannel, I2c1Proxy};
+use crate::hardware::{setup, shared_adc::AdcChannel, I2c1Proxy};
+use crate::net::telemetry::PounderTelemetry;
+use ad9959::{
+ amplitude_to_acr, frequency_to_ftw, phase_to_pow, validate_clocking,
+};
use embedded_hal_02::blocking::spi::Transfer;
use enum_iterator::Sequence;
+use miniconf::{Leaf, Tree};
+use rf_power::PowerMeasurementInterface;
use serde::{Deserialize, Serialize};
+use stm32h7xx_hal::time::MegaHertz;
pub mod attenuators;
pub mod dds_output;
@@ -120,38 +127,97 @@ impl From<Channel> for GpioPin {
}
}
-#[derive(Serialize, Deserialize, Copy, Clone, Debug)]
-pub struct DdsChannelState {
- pub phase_offset: f32,
- pub frequency: f32,
- pub amplitude: f32,
- pub enabled: bool,
+#[derive(Serialize, Deserialize, Copy, Clone, Debug, Tree)]
+pub struct DdsChannelConfig {
+ pub frequency: Leaf<f32>,
+ pub phase_offset: Leaf<f32>,
+ pub amplitude: Leaf<f32>,
}
-#[derive(Serialize, Deserialize, Copy, Clone, Debug)]
-pub struct ChannelState {
- pub parameters: DdsChannelState,
- pub attenuation: f32,
+impl Default for DdsChannelConfig {
+ fn default() -> Self {
+ Self {
+ frequency: 0.0.into(),
+ phase_offset: 0.0.into(),
+ amplitude: 0.0.into(),
+ }
+ }
}
-#[derive(Serialize, Deserialize, Copy, Clone, Debug)]
-pub struct InputChannelState {
- pub attenuation: f32,
- pub power: f32,
- pub mixer: DdsChannelState,
+/// Represents a fully defined DDS profile, with parameters expressed in machine units
+pub struct Profile {
+ /// A 32-bits representation of DDS frequency in relation to the system clock frequency.
+ /// This value corresponds to the AD9959 CFTW0 register, which specifies the frequency
+ /// of DDS channels.
+ pub frequency_tuning_word: u32,
+ /// The DDS phase offset. It corresponds to the AD9959 CPOW0 register, which specifies
+ /// the phase offset of DDS channels.
+ pub phase_offset: u16,
+ /// Control amplitudes of DDS channels. It corresponds to the AD9959 ACR register, which
+ /// controls the amplitude scaling factor of DDS channels.
+ pub amplitude_control: u32,
}
-#[derive(Serialize, Deserialize, Copy, Clone, Debug)]
-pub struct OutputChannelState {
- pub attenuation: f32,
- pub channel: DdsChannelState,
+impl TryFrom<(ClockConfig, ChannelConfig)> for Profile {
+ type Error = ad9959::Error;
+
+ fn try_from(
+ (clocking, channel): (ClockConfig, ChannelConfig),
+ ) -> Result<Self, Self::Error> {
+ let system_clock_frequency =
+ *clocking.reference_clock * *clocking.multiplier as f32;
+ Ok(Profile {
+ frequency_tuning_word: frequency_to_ftw(
+ *channel.dds.frequency,
+ system_clock_frequency,
+ )?,
+ phase_offset: phase_to_pow(*channel.dds.phase_offset)?,
+ amplitude_control: amplitude_to_acr(*channel.dds.amplitude)?,
+ })
+ }
}
-#[derive(Serialize, Deserialize, Copy, Clone, Debug)]
-pub struct DdsClockConfig {
- pub multiplier: u8,
- pub reference_clock: f32,
- pub external_clock: bool,
+#[derive(Serialize, Deserialize, Copy, Clone, Debug, Tree)]
+pub struct ChannelConfig {
+ #[tree]
+ pub dds: DdsChannelConfig,
+ pub attenuation: Leaf<f32>,
+}
+
+impl Default for ChannelConfig {
+ fn default() -> Self {
+ ChannelConfig {
+ dds: DdsChannelConfig::default(),
+ attenuation: 31.5.into(),
+ }
+ }
+}
+
+#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Tree)]
+pub struct ClockConfig {
+ pub multiplier: Leaf<u8>,
+ pub reference_clock: Leaf<f32>,
+ pub external_clock: Leaf<bool>,
+}
+
+impl Default for ClockConfig {
+ fn default() -> Self {
+ Self {
+ multiplier: 5.into(),
+ reference_clock: (MegaHertz::MHz(100).to_Hz() as f32).into(),
+ external_clock: false.into(),
+ }
+ }
+}
+
+#[derive(Copy, Clone, Debug, Default, Deserialize, Serialize, Tree)]
+pub struct PounderConfig {
+ #[tree]
+ pub clock: ClockConfig,
+ #[tree]
+ pub in_channel: [ChannelConfig; 2],
+ #[tree]
+ pub out_channel: [ChannelConfig; 2],
}
impl From<Channel> for ad9959::Channel {
@@ -585,3 +651,78 @@ impl rf_power::PowerMeasurementInterface for PounderDevices {
Ok(adc_scale * 2.048)
}
}
+
+impl setup::PounderDevices {
+ pub fn update_dds(
+ &mut self,
+ settings: PounderConfig,
+ clocking: &mut ClockConfig,
+ ) {
+ if *clocking != settings.clock {
+ match validate_clocking(
+ *settings.clock.reference_clock,
+ *settings.clock.multiplier,
+ ) {
+ Ok(_frequency) => {
+ self.pounder
+ .set_ext_clk(*settings.clock.external_clock)
+ .unwrap();
+
+ self.dds_output
+ .builder()
+ .set_system_clock(
+ *settings.clock.reference_clock,
+ *settings.clock.multiplier,
+ )
+ .unwrap()
+ .write();
+
+ *clocking = settings.clock;
+ }
+ Err(err) => {
+ log::error!("Invalid AD9959 clocking parameters: {:?}", err)
+ }
+ }
+ }
+
+ for (channel_config, pounder_channel) in settings
+ .in_channel
+ .iter()
+ .chain(settings.out_channel.iter())
+ .zip([Channel::In0, Channel::In1, Channel::Out0, Channel::Out1])
+ {
+ match Profile::try_from((*clocking, *channel_config)) {
+ Ok(dds_profile) => {
+ self.dds_output
+ .builder()
+ .update_channels_with_profile(
+ pounder_channel.into(),
+ dds_profile,
+ )
+ .write();
+
+ if let Err(err) = self.pounder.set_attenuation(
+ pounder_channel,
+ *channel_config.attenuation,
+ ) {
+ log::error!("Invalid attenuation settings: {:?}", err)
+ }
+ }
+ Err(err) => {
+ log::error!("Invalid AD9959 profile settings: {:?}", err)
+ }
+ }
+ }
+ }
+
+ pub fn get_telemetry(&mut self, config: PounderConfig) -> PounderTelemetry {
+ PounderTelemetry {
+ temperature: self.pounder.lm75.read_temperature().unwrap(),
+ input_power: [
+ self.pounder.measure_power(Channel::In0).unwrap(),
+ self.pounder.measure_power(Channel::In1).unwrap(),
+ ],
+ config,
+ }
+ }
+}
diff --git a/src/net/data_stream.rs b/src/net/data_stream.rs
index 714ec57f..d442f197 100644
--- a/src/net/data_stream.rs
+++ b/src/net/data_stream.rs
@@ -25,7 +25,7 @@
#![allow(non_camel_case_types)] // https://github.com/rust-embedded/heapless/issues/411
-use core::{fmt::Write, mem::MaybeUninit};
+use core::{fmt::Write, mem::{MaybeUninit, size_of_val}};
use heapless::{
box_pool,
pool::boxed::{Box, BoxBlock},
diff --git a/src/net/mod.rs b/src/net/mod.rs
index 8d815e51..5541f8ba 100644
--- a/src/net/mod.rs
+++ b/src/net/mod.rs
@@ -32,14 +32,14 @@ pub type NetworkReference =
pub struct MqttStorage {
telemetry: [u8; 2048],
- settings: [u8; 1024],
+ settings: [u8; 1536],
}
impl Default for MqttStorage {
fn default() -> Self {
Self {
telemetry: [0u8; 2048],
- settings: [0u8; 1024],
+ settings: [0u8; 1536],
}
}
}
diff --git a/src/net/telemetry.rs b/src/net/telemetry.rs
index 6b42b97c..48f9828e 100644
--- a/src/net/telemetry.rs
+++ b/src/net/telemetry.rs
@@ -16,7 +16,7 @@ use minimq::{DeferredPublication, Publication};
use serde::Serialize;
use super::NetworkReference;
-use crate::hardware::{adc::AdcCode, afe::Gain, dac::DacCode, SystemTimer};
+use crate::hardware::{adc::AdcCode, afe::Gain, dac::DacCode, SystemTimer, pounder::PounderConfig};
/// Default metadata message if formatting errors occur.
const DEFAULT_METADATA: &str = "{\"message\":\"Truncated: See USB terminal\"}";
@@ -68,6 +68,26 @@ pub struct Telemetry {
/// The CPU temperature in degrees Celsius.
pub cpu_temp: f32,
+
+ /// Measurements related to Pounder
+ pub pounder: Option<PounderTelemetry>,
+}
+
+/// The structure that holds the telemetry related to Pounder.
+///
+/// # Note
+/// This structure should be generated on-demand by the buffer when required to minimize conversion
+/// overhead.
+#[derive(Copy, Clone, Serialize)]
+pub struct PounderTelemetry {
+ /// The Pounder temperature in degrees Celsius
+ pub temperature: f32,
+
+ /// The detected RF power into IN channels
+ pub input_power: [f32; 2],
+
+ /// The configuration of the clock and DDS channels
+ pub config: PounderConfig,
}
impl TelemetryBuffer {
@@ -77,10 +97,17 @@ impl TelemetryBuffer {
/// * `afe0` - The current AFE configuration for channel 0.
/// * `afe1` - The current AFE configuration for channel 1.
/// * `cpu_temp` - The current CPU temperature.
+ /// * `pounder` - The current Pounder telemetry.
///
/// # Returns
/// The finalized telemetry structure that can be serialized and reported.
- pub fn finalize(self, afe0: Gain, afe1: Gain, cpu_temp: f32) -> Telemetry {
+ pub fn finalize(
+ self,
+ afe0: Gain,
+ afe1: Gain,
+ cpu_temp: f32,
+ pounder: Option<PounderTelemetry>,
+ ) -> Telemetry {
let in0_volts = Into::<f32>::into(self.adcs[0]) / afe0.as_multiplier();
let in1_volts = Into::<f32>::into(self.adcs[1]) / afe1.as_multiplier();
@@ -89,6 +116,7 @@ impl TelemetryBuffer {
adcs: [in0_volts, in1_volts],
dacs: [self.dacs[0].into(), self.dacs[1].into()],
digital_inputs: self.digital_inputs,
+ pounder,
}
}
}

View File

@ -0,0 +1,54 @@
{ config, pkgs, lib, ... }:
with lib;
let
makeBackup = pkgs.writeScript "make-backup" ''
#!${pkgs.bash}/bin/bash
set -e
umask 0077
DBDUMPDIR=`mktemp -d`
pushd $DBDUMPDIR
${config.services.mysql.package}/bin/mysqldump --single-transaction flarum > flarum.sql
${pkgs.sudo}/bin/sudo -u mattermost ${config.services.postgresql.package}/bin/pg_dump mattermost > mattermost.sql
${pkgs.gnutar}/bin/tar cf - --exclude "/var/lib/gitea/repositories/*/*.git/archives" /etc/nixos /var/lib/gitea flarum.sql mattermost.sql | \
${pkgs.bzip2}/bin/bzip2 | \
${pkgs.gnupg}/bin/gpg --symmetric --batch --passphrase-file /etc/nixos/secret/backup-passphrase | \
${pkgs.rclone}/bin/rclone rcat --config /etc/nixos/secret/rclone.conf dropbox:backup-`date +%F`.tar.bz2.gpg
popd
rm -rf $DBDUMPDIR
echo Backup done
'';
cfg = config.services.mlabs-backup;
in
{
options.services.mlabs-backup = {
enable = mkOption {
type = types.bool;
default = false;
description = "Enable backups";
};
};
config = mkIf cfg.enable {
systemd.services.mlabs-backup = {
description = "M-Labs backup";
serviceConfig = {
Type = "oneshot";
User = "root";
Group = "root";
ExecStart = "${makeBackup}";
};
};
systemd.timers.mlabs-backup = {
description = "M-Labs backup";
wantedBy = [ "timers.target" ];
timerConfig.OnCalendar = "weekly";
};
};
}

View File

@ -0,0 +1,666 @@
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running nixos-help).
{ config, pkgs, ... }:
let
netifWan = "enp0s31f6";
netifLan = "enp3s0";
netifWifi = "wlp1s0";
netifSit = "henet0";
hydraWwwOutputs = "/var/www/hydra-outputs";
in
{
imports =
[
./hardware-configuration.nix
./homu/nixos-module.nix
./backup-module.nix
(builtins.fetchTarball {
url = "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/v2.3.0/nixos-mailserver-v2.3.0.tar.gz";
sha256 = "0lpz08qviccvpfws2nm83n7m2r8add2wvfg9bljx9yxx8107r919";
})
];
# Use the systemd-boot EFI boot loader.
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
boot.blacklistedKernelModules = ["iwlwifi"];
security.apparmor.enable = true;
networking = {
hostName = "nixbld";
firewall = {
allowedTCPPorts = [ 80 443 ];
allowedUDPPorts = [ 53 67 ];
trustedInterfaces = [ netifLan ];
};
interfaces."${netifLan}" = {
ipv4.addresses = [{
address = "192.168.1.1";
prefixLength = 24;
}];
ipv6.addresses = [{
address = "2001:470:f821:1::";
prefixLength = 64;
}];
};
interfaces."${netifWifi}" = {
ipv4.addresses = [{
address = "192.168.12.1";
prefixLength = 24;
}];
ipv6.addresses = [{
address = "2001:470:f821:2::";
prefixLength = 64;
}];
};
nat = {
enable = true;
externalInterface = netifWan;
internalInterfaces = [ netifLan netifWifi ];
forwardPorts = [
{ sourcePort = 2201; destination = "192.168.1.201:22"; proto = "tcp"; }
{ sourcePort = 2202; destination = "192.168.1.202:22"; proto = "tcp"; }
{ sourcePort = 2203; destination = "192.168.1.203:22"; proto = "tcp"; }
{ sourcePort = 2204; destination = "192.168.1.204:22"; proto = "tcp"; }
{ sourcePort = 2205; destination = "192.168.1.205:22"; proto = "tcp"; }
];
extraCommands = ''
iptables -w -N block-lan-from-wifi
iptables -w -A block-lan-from-wifi -i ${netifLan} -o ${netifWifi} -j DROP
iptables -w -A block-lan-from-wifi -i ${netifWifi} -o ${netifLan} -j DROP
iptables -w -A FORWARD -j block-lan-from-wifi
'';
extraStopCommands = ''
iptables -w -D FORWARD -j block-lan-from-wifi 2>/dev/null|| true
iptables -w -F block-lan-from-wifi 2>/dev/null|| true
iptables -w -X block-lan-from-wifi 2>/dev/null|| true
'';
};
sits."${netifSit}" = {
dev = netifWan;
remote = "216.218.221.6";
local = "42.200.147.171";
ttl = 255;
};
interfaces."${netifSit}".ipv6 = {
addresses = [{ address = "2001:470:18:629::2"; prefixLength = 64; }];
routes = [{ address = "::"; prefixLength = 0; }];
};
};
boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = "1";
boot.kernel.sysctl."net.ipv6.conf.default.forwarding" = "1";
services.unbound = {
enable = true;
extraConfig =
''
server:
port: 5353
'';
};
services.hostapd = {
enable = true;
interface = netifWifi;
hwMode = "g";
ssid = "M-Labs";
wpaPassphrase = (import /etc/nixos/secret/wifi_password.nix);
extraConfig = ''
ieee80211d=1
country_code=HK
ieee80211n=1
wmm_enabled=1
auth_algs=1
wpa_key_mgmt=WPA-PSK
rsn_pairwise=CCMP
'';
};
services.dnsmasq = {
enable = true;
servers = ["::1#5353"];
extraConfig = ''
interface=${netifLan}
interface=${netifWifi}
bind-interfaces
dhcp-range=interface:${netifLan},192.168.1.81,192.168.1.254,24h
dhcp-range=interface:${netifWifi},192.168.12.10,192.168.12.254,24h
enable-ra
dhcp-range=interface:${netifLan},::,constructor:${netifLan},ra-names
dhcp-range=interface:${netifWifi},::,constructor:${netifWifi},ra-only
no-resolv
# Static IPv4s to make Red Pitayas less annoying
dhcp-host=rp-f05cc9,192.168.1.190
dhcp-host=rp-f0612e,192.168.1.191
# Static IPv4s to make port redirections work
dhcp-host=rpi-1,192.168.1.201
dhcp-host=rpi-2,192.168.1.202
dhcp-host=rpi-3,192.168.1.203
dhcp-host=rpi-4,192.168.1.204
dhcp-host=rpi-5,192.168.1.205
# Default IP addresses for ARTIQ boards
address=/thermostat/192.168.1.26
address=/kc705/192.168.1.50
address=/zc706/192.168.1.51
address=/zc706-2/192.168.1.52
address=/sayma/192.168.1.60
address=/metlino/192.168.1.65
address=/kasli/192.168.1.70
address=/kasli-customer/192.168.1.75
address=/stabilizer-customer/192.168.1.76
# uTCA MCH from NAT
address=/tschernobyl/192.168.1.80
'';
};
# Select internationalisation properties.
i18n.defaultLocale = "en_US.UTF-8";
console = {
font = "Lat2-Terminus16";
keyMap = "de";
};
# Set your time zone.
time.timeZone = "Asia/Hong_Kong";
# List packages installed in system profile. To search, run:
# $ nix search wget
environment.systemPackages = with pkgs; [
wget vim git file lm_sensors acpi pciutils psmisc telnet nixops
irssi tmux usbutils imagemagick jq zip unzip
];
# Some programs need SUID wrappers, can be configured further or are
# started in user sessions.
# programs.mtr.enable = true;
# programs.gnupg.agent = { enable = true; enableSSHSupport = true; };
# List services that you want to enable:
services.apcupsd.enable = true;
services.apcupsd.configText = ''
UPSTYPE usb
NISIP 127.0.0.1
BATTERYLEVEL 10
MINUTES 5
'';
# Enable the OpenSSH daemon.
services.openssh.enable = true;
services.openssh.forwardX11 = true;
services.openssh.passwordAuthentication = false;
programs.mosh.enable = true;
programs.fish.enable = true;
# Enable CUPS to print documents.
services.avahi.enable = true;
services.avahi.interfaces = [ netifLan ];
services.avahi.publish.enable = true;
services.avahi.publish.userServices = true;
nixpkgs.config.allowUnfree = true;
services.printing.enable = true;
services.printing.drivers = [ pkgs.hplipWithPlugin ];
services.printing.browsing = true;
services.printing.listenAddresses = [ "*:631" ];
services.printing.defaultShared = true;
hardware.sane.enable = true;
hardware.sane.extraBackends = [ pkgs.hplipWithPlugin ];
users.extraGroups.plugdev = { };
users.extraUsers.sb = {
isNormalUser = true;
extraGroups = ["wheel" "plugdev" "dialout" "lp" "scanner"];
shell = pkgs.fish;
openssh.authorizedKeys.keys = [
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCyPk5WyFoWSvF4ozehxcVBoZ+UHgrI7VW/OoQfFFwIQe0qvetUZBMZwR2FwkLPAMZV8zz1v4EfncudEkVghy4P+/YVLlDjqDq9zwZnh8Nd/ifu84wmcNWHT2UcqnhjniCdshL8a44memzABnxfLLv+sXhP2x32cJAamo5y6fukr2qLp2jbXzR+3sv3klE0ruUXis/BR1lLqNJEYP8jB6fLn2sLKinnZPfn6DwVOk10mGeQsdME/eGl3phpjhODH9JW5V2V5nJBbC0rBnq+78dyArKVqjPSmIcSy72DEIpTctnMEN1W34BGrnsDd5Xd/DKxKxHKTMCHtZRwLC2X0NWN"
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCMALVC8RDTHec+PC8y1s3tcpUAODgq6DEzQdHDf/cyvDMfmCaPiMxfIdmkns5lMa03hymIfSmLUF0jFFDc7biRp7uf9AAXNsrTmplHii0l0McuOOZGlSdZM4eL817P7UwJqFMxJyFXDjkubhQiX6kp25Kfuj/zLnupRCaiDvE7ho/xay6Jrv0XLz935TPDwkc7W1asLIvsZLheB+sRz9SMOb9gtrvk5WXZl5JTOFOLu+JaRwQLHL/xdcHJTOod7tqHYfpoC5JHrEwKzbhTOwxZBQBfTQjQktKENQtBxXHTe71rUEWfEZQGg60/BC4BrRmh4qJjlJu3v4VIhC7SSHn1"
];
};
users.extraUsers.rj = {
isNormalUser = true;
extraGroups = ["wheel" "plugdev" "dialout"];
};
users.extraUsers.astro = {
isNormalUser = true;
extraGroups = ["plugdev" "dialout"];
};
users.extraUsers.nix = {
isNormalUser = true;
};
security.sudo.wheelNeedsPassword = false;
security.hideProcessInformation = true;
boot.kernel.sysctl."kernel.dmesg_restrict" = true;
services.udev.packages = [ pkgs.sane-backends ];
nix.distributedBuilds = true;
nix.buildMachines = [
{
hostName = "localhost";
maxJobs = 4;
system = "x86_64-linux";
supportedFeatures = ["big-parallel"];
}
{
hostName = "rpi-3";
sshUser = "nix";
sshKey = "/etc/nixos/secret/nix_id_rsa";
maxJobs = 1;
system = "aarch64-linux";
}
];
services.hydra = {
enable = true;
package = pkgs.hydra-unstable;
useSubstitutes = true;
hydraURL = "https://nixbld.m-labs.hk";
notificationSender = "hydra@m-labs.hk";
minimumDiskFree = 15; # in GB
minimumDiskFreeEvaluator = 1;
extraConfig =
''
binary_cache_secret_key_file = /etc/nixos/secret/nixbld.m-labs.hk-1
max_output_size = 10000000000
<runcommand>
job = web:web:web
command = [ $(jq '.buildStatus' < $HYDRA_JSON) = 0 ] && ln -sfn $(jq -r '.outputs[0].path' < $HYDRA_JSON) ${hydraWwwOutputs}/web
</runcommand>
<runcommand>
job = artiq:full:sipyco-manual-html
command = [ $(jq '.buildStatus' < $HYDRA_JSON) = 0 ] && ln -sfn $(jq -r '.outputs[0].path' < $HYDRA_JSON) ${hydraWwwOutputs}/sipyco-manual-html
</runcommand>
<runcommand>
job = artiq:full:sipyco-manual-latexpdf
command = [ $(jq '.buildStatus' < $HYDRA_JSON) = 0 ] && ln -sfn $(jq -r '.outputs[0].path' < $HYDRA_JSON) ${hydraWwwOutputs}/sipyco-manual-latexpdf
</runcommand>
<runcommand>
job = artiq:full-beta:artiq-manual-html
command = [ $(jq '.buildStatus' < $HYDRA_JSON) = 0 ] && ln -sfn $(jq -r '.outputs[0].path' < $HYDRA_JSON) ${hydraWwwOutputs}/artiq-manual-html-beta
</runcommand>
<runcommand>
job = artiq:full-beta:artiq-manual-latexpdf
command = [ $(jq '.buildStatus' < $HYDRA_JSON) = 0 ] && ln -sfn $(jq -r '.outputs[0].path' < $HYDRA_JSON) ${hydraWwwOutputs}/artiq-manual-latexpdf-beta
</runcommand>
<runcommand>
job = artiq:full-beta:conda-channel
command = [ $(jq '.buildStatus' < $HYDRA_JSON) = 0 ] && ln -sfn $(jq -r '.outputs[0].path' < $HYDRA_JSON) ${hydraWwwOutputs}/artiq-conda-channel-beta
</runcommand>
<runcommand>
job = artiq:full:artiq-manual-html
command = [ $(jq '.buildStatus' < $HYDRA_JSON) = 0 ] && ln -sfn $(jq -r '.outputs[0].path' < $HYDRA_JSON) ${hydraWwwOutputs}/artiq-manual-html
</runcommand>
<runcommand>
job = artiq:full:artiq-manual-latexpdf
command = [ $(jq '.buildStatus' < $HYDRA_JSON) = 0 ] && ln -sfn $(jq -r '.outputs[0].path' < $HYDRA_JSON) ${hydraWwwOutputs}/artiq-manual-latexpdf
</runcommand>
<runcommand>
job = artiq:full:conda-channel
command = [ $(jq '.buildStatus' < $HYDRA_JSON) = 0 ] && ln -sfn $(jq -r '.outputs[0].path' < $HYDRA_JSON) ${hydraWwwOutputs}/artiq-conda-channel
</runcommand>
'';
};
systemd.services.hydra-www-outputs-init = {
description = "Set up a hydra-owned directory for build outputs";
wantedBy = [ "multi-user.target" ];
requiredBy = [ "hydra-queue-runner.service" ];
before = [ "hydra-queue-runner.service" ];
serviceConfig = {
Type = "oneshot";
ExecStart = [ "${pkgs.coreutils}/bin/mkdir -p ${hydraWwwOutputs}" "${pkgs.coreutils}/bin/chown hydra-queue-runner:hydra ${hydraWwwOutputs}" ];
};
};
nix.extraOptions = ''
secret-key-files = /etc/nixos/secret/nixbld.m-labs.hk-1
'';
nix.sandboxPaths = ["/opt"];
services.munin-node.enable = true;
services.munin-cron = {
enable = true;
hosts = ''
[${config.networking.hostName}]
address localhost
'';
};
services.mlabs-backup.enable = true;
services.gitea = {
enable = true;
httpPort = 3001;
rootUrl = "https://git.m-labs.hk/";
appName = "M-Labs Git";
cookieSecure = true;
disableRegistration = true;
mailerPasswordFile = "/etc/nixos/secret/mailerpassword";
extraConfig =
''
[mailer]
ENABLED = true
HOST = ssl.serverraum.org:587
FROM = sysop@m-labs.hk
USER = sysop@m-labs.hk
[service]
ENABLE_NOTIFY_MAIL = true
[attachment]
ALLOWED_TYPES = */*
'';
};
systemd.tmpfiles.rules = [
"L+ '${config.services.gitea.stateDir}/custom/templates/home.tmpl' - - - - ${./gitea-home.tmpl}"
];
services.mattermost = {
enable = true;
siteUrl = "https://chat.m-labs.hk/";
mutableConfig = true;
};
services.matterbridge = {
enable = true;
configPath = "/etc/nixos/secret/matterbridge.toml";
};
nixpkgs.config.packageOverrides = super: let self = super.pkgs; in {
hydra-unstable = super.hydra-unstable.overrideAttrs(oa: {
patches = oa.patches or [] ++ [ ./hydra-conda.patch ./hydra-retry.patch ./hydra-unbreak-sysbuild.patch ];
hydraPath = oa.hydraPath + ":" + super.lib.makeBinPath [ super.jq ];
});
matterbridge = super.matterbridge.overrideAttrs(oa: {
patches = oa.patches or [] ++ [ ./matterbridge-disable-github.patch ];
});
};
security.acme.acceptTerms = true;
security.acme.email = "sb" + "@m-labs.hk";
security.acme.certs = {
"nixbld.m-labs.hk" = {
group = "nginx";
user = "nginx";
webroot = "/var/lib/acme/acme-challenge";
extraDomains = {
"m-labs.hk" = null;
"www.m-labs.hk" = null;
"conda.m-labs.hk" = null;
"lab.m-labs.hk" = null;
"git.m-labs.hk" = null;
"chat.m-labs.hk" = null;
"hooks.m-labs.hk" = null;
"forum.m-labs.hk" = null;
"perso.m-labs.hk" = null;
"nmigen.org" = null;
"www.nmigen.org" = null;
"openhardware.hk" = null;
"git.openhardware.hk" = null;
};
};
};
services.nginx = {
enable = true;
recommendedProxySettings = true;
recommendedGzipSettings = true;
virtualHosts = let
mainWebsite = {
addSSL = true;
useACMEHost = "nixbld.m-labs.hk";
root = "${hydraWwwOutputs}/web";
extraConfig = ''
error_page 404 /404.html;
'';
locations."^~ /fonts/".extraConfig = ''
expires 60d;
'';
locations."^~ /js/".extraConfig = ''
expires 60d;
'';
locations."/MathJax/" = {
alias = "/var/www/MathJax/";
extraConfig = ''
expires 60d;
'';
};
# legacy URLs, redirect to avoid breaking people's bookmarks
locations."/gateware.html".extraConfig = ''
return 301 /gateware/migen/;
'';
locations."/migen".extraConfig = ''
return 301 /gateware/migen/;
'';
locations."/artiq".extraConfig = ''
return 301 /experiment-control/artiq/;
'';
locations."/artiq/resources.html".extraConfig = ''
return 301 /experiment-control/resources/;
'';
# autogenerated manuals
locations."/artiq/sipyco-manual/" = {
alias = "${hydraWwwOutputs}/sipyco-manual-html/share/doc/sipyco-manual/html/";
};
locations."=/artiq/sipyco-manual.pdf" = {
alias = "${hydraWwwOutputs}/sipyco-manual-latexpdf/share/doc/sipyco-manual/SiPyCo.pdf";
};
locations."/artiq/manual-beta/" = {
alias = "${hydraWwwOutputs}/artiq-manual-html-beta/share/doc/artiq-manual/html/";
};
locations."=/artiq/manual-beta.pdf" = {
alias = "${hydraWwwOutputs}/artiq-manual-latexpdf-beta/share/doc/artiq-manual/ARTIQ.pdf";
};
locations."/artiq/manual/" = {
alias = "${hydraWwwOutputs}/artiq-manual-html/share/doc/artiq-manual/html/";
};
locations."=/artiq/manual.pdf" = {
alias = "${hydraWwwOutputs}/artiq-manual-latexpdf/share/doc/artiq-manual/ARTIQ.pdf";
};
# legacy content
locations."/migen/manual/" = {
alias = "/var/www/m-labs.hk.old/migen/manual/";
};
locations."/artiq/manual-release-4/" = {
alias = "/var/www/m-labs.hk.old/artiq/manual-release-4/";
};
locations."/artiq/manual-release-3/" = {
alias = "/var/www/m-labs.hk.old/artiq/manual-release-3/";
};
locations."/artiq/manual-release-2/" = {
alias = "/var/www/m-labs.hk.old/artiq/manual-release-2/";
};
};
in {
"m-labs.hk" = mainWebsite;
"www.m-labs.hk" = mainWebsite;
"lab.m-labs.hk" = {
addSSL = true;
useACMEHost = "nixbld.m-labs.hk";
locations."/munin/".alias = "/var/www/munin/";
locations."/munin".extraConfig = ''
auth_basic "Munin";
auth_basic_user_file /etc/nixos/secret/muninpasswd;
'';
locations."/homu/".proxyPass = "http://127.0.0.1:54856/";
};
"nixbld.m-labs.hk" = {
forceSSL = true;
useACMEHost = "nixbld.m-labs.hk";
locations."/".proxyPass = "http://127.0.0.1:3000";
};
"conda.m-labs.hk" = {
forceSSL = true;
useACMEHost = "nixbld.m-labs.hk";
locations."/artiq-beta/" = {
alias = "${hydraWwwOutputs}/artiq-conda-channel-beta/";
extraConfig = ''
autoindex on;
index bogus_index_file;
'';
};
locations."/artiq/" = {
alias = "${hydraWwwOutputs}/artiq-conda-channel/";
extraConfig = ''
autoindex on;
index bogus_index_file;
'';
};
};
"git.m-labs.hk" = {
forceSSL = true;
useACMEHost = "nixbld.m-labs.hk";
locations."/".proxyPass = "http://127.0.0.1:3001";
extraConfig = ''
client_max_body_size 300M;
'';
};
"chat.m-labs.hk" = {
forceSSL = true;
useACMEHost = "nixbld.m-labs.hk";
locations."/".proxyPass = "http://127.0.0.1:8065";
locations."~ /api/v[0-9]+/(users/)?websocket$".proxyPass = "http://127.0.0.1:8065";
locations."~ /api/v[0-9]+/(users/)?websocket$".proxyWebsockets = true;
};
"hooks.m-labs.hk" = {
forceSSL = true;
useACMEHost = "nixbld.m-labs.hk";
locations."/mattermost-github".extraConfig = ''
include ${pkgs.nginx}/conf/uwsgi_params;
uwsgi_pass unix:${config.services.uwsgi.runDir}/uwsgi-mgi.sock;
'';
locations."/rfq".extraConfig = ''
include ${pkgs.nginx}/conf/uwsgi_params;
uwsgi_pass unix:${config.services.uwsgi.runDir}/uwsgi-rfq.sock;
'';
};
"forum.m-labs.hk" = {
forceSSL = true;
useACMEHost = "nixbld.m-labs.hk";
root = "/var/www/flarum/public";
locations."~ \.php$".extraConfig = ''
fastcgi_pass unix:${config.services.phpfpm.pools.flarum.socket};
fastcgi_index index.php;
'';
extraConfig = ''
index index.php;
include /var/www/flarum/.nginx.conf;
'';
};
"perso.m-labs.hk" = {
addSSL = true;
useACMEHost = "nixbld.m-labs.hk";
root = "/var/www/perso";
};
"nmigen.org" = {
addSSL = true;
useACMEHost = "nixbld.m-labs.hk";
locations."/".extraConfig = ''
return 307 https://m-labs.hk/gateware/nmigen/;
'';
};
"www.nmigen.org" = {
addSSL = true;
useACMEHost = "nixbld.m-labs.hk";
locations."/".extraConfig = ''
return 307 https://m-labs.hk/gateware/nmigen/;
'';
};
"git.openhardware.hk" = {
forceSSL = true;
useACMEHost = "nixbld.m-labs.hk";
locations."/".proxyPass = "http://127.0.0.1:3002";
extraConfig = ''
client_max_body_size 300M;
'';
};
};
};
services.uwsgi = {
enable = true;
plugins = [ "python3" ];
instance = {
type = "emperor";
vassals = {
mattermostgithub = import ./mattermost-github-integration/uwsgi-config.nix { inherit config pkgs; };
rfq = import ./rfq/uwsgi-config.nix { inherit config pkgs; };
};
};
};
services.mysql = {
enable = true;
package = pkgs.mariadb;
};
services.phpfpm.pools.flarum = {
user = "nobody";
settings = {
"listen.owner" = "nginx";
"listen.group" = "nginx";
"listen.mode" = "0600";
"pm" = "dynamic";
"pm.max_children" = 5;
"pm.start_servers" = 2;
"pm.min_spare_servers" = 1;
"pm.max_spare_servers" = 3;
"pm.max_requests" = 500;
};
};
services.homu = {
enable = true;
config = "/etc/nixos/secret/homu.toml";
};
mailserver = {
enable = true;
localDnsResolver = false; # conflicts with dnsmasq
# Some mail servers do reverse DNS lookups to filter spam.
# Getting a proper reverse DNS record from ISP is difficult, so use whatever already exists.
fqdn = "42-200-147-171.static.imsbiz.com";
domains = [ "nmigen.org" ];
loginAccounts = (import /etc/nixos/secret/email_accounts.nix);
certificateScheme = 3;
};
security.acme.certs."${config.mailserver.fqdn}".extraDomains = {
"mail.nmigen.org" = null;
};
containers.openhardwarehk = {
autoStart = true;
config =
{ config, pkgs, ... }:
{
services.gitea = {
enable = true;
httpPort = 3002;
rootUrl = "https://git.openhardware.hk/";
appName = "Open Hardware HK";
cookieSecure = true;
disableRegistration = true;
extraConfig =
''
[attachment]
ALLOWED_TYPES = */*
'';
};
};
};
# This value determines the NixOS release with which your system is to be
# compatible, in order to avoid breaking some software such as database
# servers. You should change this only after NixOS release notes say you
# should.
system.stateVersion = "18.09"; # Did you read the comment?
}

View File

@ -0,0 +1,23 @@
{{template "base/head" .}}
<div class="home">
<div class="ui stackable middle very relaxed page grid">
<div class="sixteen wide center aligned centered column">
<div>
<img class="logo" src="{{AppSubUrl}}/img/gitea-lg.png" />
</div>
<div class="hero">
<h1 class="ui icon header title">
{{AppName}}
</h1>
</div>
</div>
</div>
<div class="ui stackable middle very relaxed page grid">
<div class="sixteen wide center column">
<p class="large">
Welcome! This Gitea instance is here to support projects related to <a href="https://m-labs.hk">M-Labs</a>. You may want to browse the <a href="https://git.m-labs.hk/M-Labs/">M-Labs organization</a> where many projects are located. If you would like an account (we give them to anyone who wants to contribute on projects related to Sinara, ARTIQ, nMigen, etc.), simply write a short email to sb@m-***.hk stating the username you would like to have.
</p>
</div>
</div>
</div>
{{template "base/footer" .}}

View File

@ -0,0 +1,13 @@
diff --git a/homu/git_helper.py b/homu/git_helper.py
index 0f70c69..f53fb57 100755
--- a/homu/git_helper.py
+++ b/homu/git_helper.py
@@ -7,7 +7,7 @@ SSH_KEY_FILE = os.path.join(os.path.dirname(__file__), '../cache/key')
def main():
- args = ['ssh', '-i', SSH_KEY_FILE, '-S', 'none'] + sys.argv[1:]
+ args = ['ssh', '-o', 'StrictHostKeyChecking=no', '-i', SSH_KEY_FILE, '-S', 'none'] + sys.argv[1:]
os.execvp('ssh', args)

Some files were not shown because too many files have changed in this diff Show More