From 4545b437755a91d8fafbd9a7041d3332aab7502f Mon Sep 17 00:00:00 2001 From: OPNA2608 Date: Mon, 4 Dec 2023 15:11:42 +0100 Subject: [PATCH] famistudio: init at 4.1.3 --- .../audio/famistudio/build-native-wrapper.nix | 69 ++++++++++ .../applications/audio/famistudio/default.nix | 118 ++++++++++++++++++ pkgs/applications/audio/famistudio/deps.nix | 5 + pkgs/applications/audio/famistudio/update.sh | 23 ++++ pkgs/top-level/all-packages.nix | 2 + 5 files changed, 217 insertions(+) create mode 100644 pkgs/applications/audio/famistudio/build-native-wrapper.nix create mode 100644 pkgs/applications/audio/famistudio/default.nix create mode 100644 pkgs/applications/audio/famistudio/deps.nix create mode 100755 pkgs/applications/audio/famistudio/update.sh diff --git a/pkgs/applications/audio/famistudio/build-native-wrapper.nix b/pkgs/applications/audio/famistudio/build-native-wrapper.nix new file mode 100644 index 000000000000..ddee5bf5712d --- /dev/null +++ b/pkgs/applications/audio/famistudio/build-native-wrapper.nix @@ -0,0 +1,69 @@ +{ depname +, version +, src +, sourceRoot +, stdenv +, lib +, patches ? [] +, extraPostPatch ? "" +, buildInputs ? [] +}: + +let + rebuildscriptName = if stdenv.hostPlatform.isLinux then + "build_linux" + else if stdenv.hostPlatform.isDarwin then + "build_macos" + else throw "Don't know how to rebuild FamiStudio's vendored ${depname} for ${stdenv.hostPlatform.system}"; +in +stdenv.mkDerivation { + pname = "famistudio-nativedep-${depname}"; + inherit version src sourceRoot patches buildInputs; + + postPatch = let + libnameBase = lib.optionalString stdenv.hostPlatform.isLinux "lib" + depname; + in '' + # Use one name for build script, eases with patching + mv ${rebuildscriptName}.sh build.sh + + # Scripts use hardcoded compilers and try to copy built libraries into FamiStudio's build tree + # Not all scripts use the same compiler, so don't fail on replacing that + substituteInPlace build.sh \ + --replace-fail '../../FamiStudio/' "$out/lib/" \ + --replace-quiet 'g++' "$CXX" + + # Replacing gcc via sed, would break -static-libgcc otherwise + sed -i -e "s/^gcc/$CC/g" build.sh + '' + lib.optionalString stdenv.hostPlatform.isDarwin '' + # Darwin rebuild scripts try to make a universal2 dylib + # - build dylib for non-hostPlatform + # - copy built library into special directory for later packaging script + # - join two dylibs together into a universal2 dylib + # Remove everything we don't need + sed -ri \ + -e '/-target ${if stdenv.hostPlatform.isx86_64 then "arm64" else "x86_64"}/d' \ + -e '/..\/..\/Setup/d' \ + build.sh + + # Replace joining multi-arch dylibs with copying dylib for target arch + substituteInPlace build.sh \ + --replace-fail 'lipo -create -output ${libnameBase}.dylib' 'cp ${libnameBase}_${if stdenv.hostPlatform.isx86_64 then "x86_64" else "arm64"}.dylib ${libnameBase}.dylib #' + '' + extraPostPatch; + + dontConfigure = true; + dontInstall = true; # rebuild script automatically installs + + buildPhase = '' + runHook preBuild + + mkdir -p $out/lib + + # Delete all prebuilt libraries, make sure everything is rebuilt + find . -name '*.so' -or -name '*.dylib' -or -name '*.a' -delete + + # When calling normally, an error won't cause derivation to fail + source ./build.sh + + runHook postBuild + ''; +} diff --git a/pkgs/applications/audio/famistudio/default.nix b/pkgs/applications/audio/famistudio/default.nix new file mode 100644 index 000000000000..7d738065ce3a --- /dev/null +++ b/pkgs/applications/audio/famistudio/default.nix @@ -0,0 +1,118 @@ +{ stdenv +, lib +, buildDotnetModule +, callPackage +, fetchFromGitHub +, ffmpeg +, glfw +, libogg +, libvorbis +, makeWrapper +, openal +, portaudio +, rtmidi +}: + +let + csprojName = if stdenv.hostPlatform.isLinux then + "FamiStudio.Linux" + else if stdenv.hostPlatform.isDarwin then + "FamiStudio.Mac" + else throw "Don't know how to build FamiStudio for ${stdenv.hostPlatform.system}"; +in +buildDotnetModule rec { + pname = "famistudio"; + version = "4.1.3"; + + src = fetchFromGitHub { + owner = "BleuBleu"; + repo = "FamiStudio"; + rev = "refs/tags/${version}"; + hash = "sha256-bryxhminkrTVe5qhGeMStZp3NTHBREXrsUlyQkfPkao="; + }; + + postPatch = let + libname = library: "${library}${stdenv.hostPlatform.extensions.sharedLibrary}"; + buildNativeWrapper = args: callPackage ./build-native-wrapper.nix (args // { + inherit version src; + sourceRoot = "${src.name}/ThirdParty/${args.depname}"; + }); + nativeWrapperToReplaceFormat = args: let + libPrefix = lib.optionalString stdenv.hostPlatform.isLinux "lib"; + in { + package = buildNativeWrapper args; + expectedName = "${libPrefix}${args.depname}"; + ourName = "${libPrefix}${args.depname}"; + }; + librariesToReplace = [ + # Unmodified native libraries that we can fully substitute + { package = glfw; expectedName = "libglfw"; ourName = "libglfw"; } + { package = rtmidi; expectedName = "librtmidi"; ourName = "librtmidi"; } + ] ++ lib.optionals stdenv.hostPlatform.isLinux [ + { package = openal; expectedName = "libopenal32"; ourName = "libopenal"; } + ] ++ lib.optionals stdenv.hostPlatform.isDarwin [ + { package = portaudio; expectedName = "libportaudio.2"; ourName = "libportaudio.2"; } + ] ++ [ + # Native libraries, with extra code for the C# wrapping + (nativeWrapperToReplaceFormat { depname = "GifDec"; }) + (nativeWrapperToReplaceFormat { depname = "NesSndEmu"; }) + (nativeWrapperToReplaceFormat { depname = "NotSoFatso"; extraPostPatch = '' + # C++17 does not allow register storage class specifier + substituteInPlace build.sh \ + --replace-fail "$CXX" "$CXX -std=c++14" + ''; }) + (nativeWrapperToReplaceFormat { depname = "ShineMp3"; }) + (nativeWrapperToReplaceFormat { depname = "Stb"; }) + (nativeWrapperToReplaceFormat { depname = "Vorbis"; buildInputs = [ libogg libvorbis ]; }) + ]; + libraryReplaceArgs = lib.strings.concatMapStringsSep " " + (library: "--replace-fail '${libname library.expectedName}' '${lib.getLib library.package}/lib/${libname library.ourName}'") + librariesToReplace; + in '' + # Don't use any prebuilt libraries + rm FamiStudio/*.{dll,dylib,so*} + + # Replace copying of vendored prebuilt native libraries with copying of our native libraries + substituteInPlace ${projectFile} ${libraryReplaceArgs} + + # Un-hardcode target platform if set + sed -i -e '/PlatformTarget/d' ${projectFile} + + # Don't require a special name to be preserved, our OpenAL isn't 32-bit + substituteInPlace FamiStudio/Source/AudioStreams/OpenALStream.cs \ + --replace-fail 'libopenal32' 'libopenal' + ''; + + projectFile = "FamiStudio/${csprojName}.csproj"; + nugetDeps = ./deps.nix; + + executables = [ "FamiStudio" ]; + + postInstall = '' + mkdir -p $out/share/famistudio + for datdir in Setup/Demo\ {Instruments,Songs}; do + cp -R "$datdir" $out/share/famistudio/ + done + ''; + + postFixup = '' + # FFMpeg looked up from PATH + wrapProgram $out/bin/FamiStudio \ + --prefix PATH : ${lib.makeBinPath [ ffmpeg ]} + ''; + + passthru.updateScript = ./update.sh; + + meta = with lib; { + homepage = "https://famistudio.org/"; + description = "NES Music Editor"; + longDescription = '' + FamiStudio is very simple music editor for the Nintendo Entertainment System + or Famicom. It is targeted at both chiptune artists and NES homebrewers. + ''; + license = licenses.mit; + maintainers = with maintainers; [ OPNA2608 ]; + platforms = platforms.unix; + mainProgram = "FamiStudio"; + }; +} diff --git a/pkgs/applications/audio/famistudio/deps.nix b/pkgs/applications/audio/famistudio/deps.nix new file mode 100644 index 000000000000..f3a17967e25c --- /dev/null +++ b/pkgs/applications/audio/famistudio/deps.nix @@ -0,0 +1,5 @@ +# This file was automatically generated by passthru.fetch-deps. +# Please dont edit it manually, your changes might get overwritten! + +{ fetchNuGet }: [ +] diff --git a/pkgs/applications/audio/famistudio/update.sh b/pkgs/applications/audio/famistudio/update.sh new file mode 100755 index 000000000000..15657955c025 --- /dev/null +++ b/pkgs/applications/audio/famistudio/update.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env nix-shell +#!nix-shell -i bash -p curl jq common-updater-scripts +set -eo pipefail + +cd "$(dirname "${BASH_SOURCE[0]}")" + +deps_file="$(realpath "./deps.nix")" + +new_version="$(curl ${GITHUB_TOKEN:+-u ":$GITHUB_TOKEN"} \ + -s "https://api.github.com/repos/BleuBleu/FamiStudio/releases?per_page=1" | jq -r '.[0].tag_name')" +old_version="$(sed -nE 's/\s*version = "(.*)".*/\1/p' ./default.nix)" +if [[ "$new_version" == "$old_version" ]]; then + echo "Up to date" + exit 0 +fi + +cd ../../../.. + +if [[ "$1" != "--deps-only" ]]; then + update-source-version famistudio "$new_version" +fi + +$(nix-build . -A famistudio.fetch-deps --no-out-link) "$deps_file" diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index aec6ee2ada01..f23d0e0319bc 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -30984,6 +30984,8 @@ with pkgs; faircamp = callPackage ../applications/misc/faircamp { }; + famistudio = darwin.apple_sdk_11_0.callPackage ../applications/audio/famistudio { }; + fasttext = callPackage ../applications/science/machine-learning/fasttext { }; fbmenugen = callPackage ../applications/misc/fbmenugen { };