Unverified Commit 3ea38d98 authored by Sandro Jäckel's avatar Sandro Jäckel Committed by GitHub
Browse files

Merge pull request #243238 from OPNA2608/init/famistudio-source

famistudio: init source-built version
parents e68863fa ee6c9119
Loading
Loading
Loading
Loading
+69 −0
Original line number Diff line number Diff line
{ 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
  '';
}
+88 −41
Original line number Diff line number Diff line
{ lib
, stdenv
, fetchzip
, autoPatchelfHook
, dotnet-runtime
{ stdenv
, lib
, buildDotnetModule
, callPackage
, fetchFromGitHub
, ffmpeg
, libglvnd
, glfw
, libogg
, libvorbis
, makeWrapper
, openal
, portaudio
, rtmidi
}:

stdenv.mkDerivation rec {
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 = fetchzip {
    url = "https://github.com/BleuBleu/FamiStudio/releases/download/${version}/FamiStudio${lib.strings.concatStrings (lib.splitVersion version)}-LinuxAMD64.zip";
    stripRoot = false;
    hash = "sha256-eAdv0oObczbs8QLGYbxCrdFk/gN5DOCJ1dp/tg8JWIc=";
  src = fetchFromGitHub {
    owner = "BleuBleu";
    repo = "FamiStudio";
    rev = "refs/tags/${version}";
    hash = "sha256-bryxhminkrTVe5qhGeMStZp3NTHBREXrsUlyQkfPkao=";
  };

  strictDeps = true;

  nativeBuildInputs = [
    autoPatchelfHook
    makeWrapper
  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*}

  buildInputs = [
    dotnet-runtime
    ffmpeg
    libglvnd
    openal
  ];
    # Replace copying of vendored prebuilt native libraries with copying of our native libraries
    substituteInPlace ${projectFile} ${libraryReplaceArgs}

  dontConfigure = true;
  dontBuild = true;
    # Un-hardcode target platform if set
    sed -i -e '/PlatformTarget/d' ${projectFile}

  installPhase = ''
    runHook preInstall
    # 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'
  '';

    mkdir -p $out/{bin,lib/famistudio}
    mv * $out/lib/famistudio
  projectFile = "FamiStudio/${csprojName}.csproj";
  nugetDeps = ./deps.nix;

    makeWrapper ${lib.getExe dotnet-runtime} $out/bin/famistudio \
      --add-flags $out/lib/famistudio/FamiStudio.dll \
      --prefix LD_LIBRARY_PATH : ${lib.makeLibraryPath [ libglvnd ]} \
      --prefix PATH : ${lib.makeBinPath [ ffmpeg ]}
  executables = [ "FamiStudio" ];

    # Bundled openal lib freezes the application
    rm $out/lib/famistudio/libopenal32.so
    ln -s ${openal}/lib/libopenal.so $out/lib/famistudio/libopenal32.so
  postInstall = ''
    mkdir -p $out/share/famistudio
    for datdir in Setup/Demo\ {Instruments,Songs}; do
      cp -R "$datdir" $out/share/famistudio/
    done
  '';

    runHook postInstall
  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";
@@ -62,10 +111,8 @@ stdenv.mkDerivation rec {
      or Famicom. It is targeted at both chiptune artists and NES homebrewers.
    '';
    license = licenses.mit;
    # Maybe possible to build from source but I'm not too familiar with C# packaging
    sourceProvenance = with lib.sourceTypes; [ binaryNativeCode ];
    maintainers = with maintainers; [ OPNA2608 ];
    platforms = [ "x86_64-linux" ];
    mainProgram = "famistudio";
    platforms = platforms.unix;
    mainProgram = "FamiStudio";
  };
}
+5 −0
Original line number Diff line number Diff line
# This file was automatically generated by passthru.fetch-deps.
# Please dont edit it manually, your changes might get overwritten!

{ fetchNuGet }: [
]
+23 −0
Original line number Diff line number Diff line
#!/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"
+1 −1
Original line number Diff line number Diff line
@@ -30979,7 +30979,7 @@ with pkgs;
  faircamp = callPackage ../applications/misc/faircamp { };
  famistudio = callPackage ../applications/audio/famistudio { };
  famistudio = darwin.apple_sdk_11_0.callPackage ../applications/audio/famistudio { };
  fasttext = callPackage ../applications/science/machine-learning/fasttext { };