commit 494378e890ae9cebc5c11534ea7c04b734372f6f Author: Patrick Northon Date: Mon Jul 8 00:57:15 2024 -0400 Initial commit. diff --git a/.SRCINFO b/.SRCINFO new file mode 100644 index 0000000000000..64905ac6eab46 --- /dev/null +++ b/.SRCINFO @@ -0,0 +1,33 @@ +pkgbase = fvm-sourcebuild + pkgdesc = Flutter Version Management: A simple CLI to manage Flutter SDK versions. (Build engine from sources) + pkgver = 3.1.7 + pkgrel = 1 + url = https://fvm.app + arch = x86_64 + license = MIT + makedepends = dart + depends = git + provides = fvm + conflicts = fvm + options = !strip + source = fvm-3.1.7.tar.gz::https://github.com/leoafarias/fvm/archive/refs/tags/3.1.7.tar.gz + source = fvm-sourcebuild-wrapper + sha256sums = a479b54c4ade1df99dee975adbf61b56c6dff224915e44d4914925e4dfce8b4c + sha256sums = c422a806ed809c4b95e539b26860e2df93a744a81447cc524cec22c43e797905 + +pkgname = fvm-sourcebuild + depends = git + depends = cmake + depends = ninja + depends = git + depends = clang + depends = python + depends = unzip + depends = gtk3 + depends = lld + depends = yq + depends = gn + depends = llvm + depends = python-httplib2 + depends = python-six + depends = python311 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000..72e8ffc0db8aa --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +* diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 0000000000000..ae84552515eb4 --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,60 @@ +# Maintainer: Patrick Northon +# Contributor: Mark Wagie + +_pkgname=fvm +pkgname=${_pkgname}-sourcebuild +pkgver=3.1.7 +pkgrel=1 +provides=(${_pkgname}) +conflicts=(${_pkgname}) +pkgdesc="Flutter Version Management: A simple CLI to manage Flutter SDK versions. (Build engine from sources)" +arch=('x86_64') +url="https://fvm.app" +license=('MIT') +depends=('git') +makedepends=('dart') +options=('!strip') +source=( + "$_pkgname-$pkgver.tar.gz::https://github.com/leoafarias/fvm/archive/refs/tags/$pkgver.tar.gz" + "${pkgname}-wrapper") +sha256sums=('a479b54c4ade1df99dee975adbf61b56c6dff224915e44d4914925e4dfce8b4c' + 'c422a806ed809c4b95e539b26860e2df93a744a81447cc524cec22c43e797905') + +prepare() { + cd "$_pkgname-$pkgver" + + # disable analytics + dart --disable-analytics + + # download dependencies + dart pub get +} + +build() { + cd "$_pkgname-$pkgver" + dart compile exe -o bin/fvm bin/main.dart +} + +package() { + depends+=( + 'cmake' + 'ninja' + 'git' + 'clang' + 'python' + 'unzip' + 'gtk3' + 'lld' + 'yq' + 'gn' + 'llvm' + 'python-httplib2' + 'python-six' + 'python311' + ) + + cd "$_pkgname-$pkgver" + install -Dm755 "bin/$_pkgname" "$pkgdir/usr/bin/fvm.real" + install -Dm755 "${srcdir}/${pkgname}-wrapper" "$pkgdir/usr/bin/fvm" + install -Dm644 LICENSE -t "$pkgdir/usr/share/licenses/$_pkgname/" +} diff --git a/fvm-sourcebuild-wrapper b/fvm-sourcebuild-wrapper new file mode 100755 index 0000000000000..3374c9a2c5acc --- /dev/null +++ b/fvm-sourcebuild-wrapper @@ -0,0 +1,301 @@ +#!/usr/bin/env bash + +set -euo pipefail +shopt -s inherit_errexit +#set -x + +_git() { + git -c safe.bareRepository=all "$@" +} + +_ln() { + rm -rf "$2" && ln -sf "$1" "$2" +} + +if [[ ! -v ARCH_FLUTTER_TARGET_CPU || -z "$ARCH_FLUTTER_TARGET_CPU" ]]; then + CARCH="${CARCH:-}" + + if [[ $CARCH == 'aarch64' ]]; then + ARCH_FLUTTER_TARGET_CPU=arm64 + else + ARCH_FLUTTER_TARGET_CPU=x64 + fi +fi + +ARCH_FLUTTER_ENGINE_URL="${ARCH_FLUTTER_ENGINE_URL:-https://github.com/flutter/engine.git}" +ARCH_FLUTTER_DEPOT_TOOL_URL="${ARCH_FLUTTER_DEPOT_TOOL_URL:-https://chromium.googlesource.com/chromium/tools/depot_tools.git}" +readonly flutter_outdir="linux_release_$ARCH_FLUTTER_TARGET_CPU" + +_setup_build_env() +{ + export \ + PATH="$(pwd)/.engine-src/depot_tools:$PATH" \ + DEPOT_TOOLS_UPDATE=0 \ + VPYTHON_BYPASS='manually managed python not supported by chrome operations' +} + +setup_flutter_env() +{ + export FLUTTER_ENGINE="$(pwd)/.engine-src/engine" + + local -r engine_version="$(git -C "${FLUTTER_ENGINE}" describe --tags)" + + if [[ -n "$engine_version" && "$(vercmp "$engine_version" '3.16.0')" == -1 ]]; then + export ARCH_FLUTTER_OPTS='--local-engine=arch_release --no-version-check --suppress-analytics' + else + export ARCH_FLUTTER_OPTS='--local-engine=arch_release --local-engine-host=arch_release --no-version-check --suppress-analytics' + fi +} + +_patch_flutter() +{ + sed -i 's|--no-enable-mirrors "$SCRIPT_PATH"|--no-enable-mirrors "$SCRIPT_PATH" $ARCH_FLUTTER_OPTS|' \ + "$1/bin/internal/shared.sh" + sed -i 's|exec "$DART" --disable-dart-dev --packages="$FLUTTER_TOOLS_DIR/.dart_tool/package_config.json" $FLUTTER_TOOL_ARGS "$SNAPSHOT_PATH" "$@"|exec "$DART" --disable-dart-dev --packages="$FLUTTER_TOOLS_DIR/.dart_tool/package_config.json" $FLUTTER_TOOL_ARGS "$SNAPSHOT_PATH" $ARCH_FLUTTER_OPTS "$@"|' \ + "$1/bin/internal/shared.sh" +} + +_clone_src() +{ + local -r url="$1" + local -r dest="$2" + local -r ref="${3:-origin/HEAD}" + local -r filename="$(basename "$dest")" + + # Clone repo. + if [[ -e "$dest" ]]; then + local remote_url="$(_git -C "$dest" config --get remote.origin.url)" + if [[ "${url%%.git}" != "${remote_url%%.git}" ]] ; then + >&2 echo "$dest is not a clone of $url." + return 1 + fi + + _git -C "$dest" fetch --all -p + else + _git clone --mirror "$url" "$dest" + fi + + local _abs_git_dir="$(_git -C "$dest" rev-parse --absolute-git-dir)" + mkdir -p "$_abs_git_dir/info" + echo '* -export-subst -export-ignore' > "$_abs_git_dir/info/attributes" + + # Create working copy in current dir. + mkdir -p '.engine-src' + if [[ -e ".engine-src/$filename" ]]; then + _git -C ".engine-src/$filename" fetch + else + _git clone --origin=origin -s "$dest" ".engine-src/$filename" + fi + + if [[ -n "$ref" ]]; then + _git -C ".engine-src/$filename" checkout --force --no-track -B makepkg "$ref" + fi +} + +_prepare_build() +{ + local -r outdir="$1" + local -r version="$2" + + if [[ $(vercmp "$version" '3.14.0') == -1 ]]; then + local -r python_exec="python3.11" + else + local -r python_exec='python3' + fi + + if ! "$python_exec" --version &>/dev/null; then + >&2 echo "Engine version $version requires $python_exec." + return 1 + fi + + sed -i "s/exec \"python3\"/exec \"$python_exec\"/" '.engine-src/depot_tools/vpython3' + + _setup_build_env + + local -r engine_src_dir="$(pwd)/.engine-src/engine" + + mkdir -p "$outdir" && pushd "$outdir" + + cat >.gclient <&2 echo '`gclient.py sync` command failed.'; return 1; } + + sed -i "s/'python3'/'$python_exec'/" 'src/flutter/DEPS' + + gclient.py runhooks \ + || { >&2 echo '`gclient.py runhooks` command failed.'; return 1; } + + cd 'src' + + sed -i 's|prefix = rebased_clang_dir|prefix= ""|g' 'build/toolchain/linux/BUILD.gn' # use system clang + sed -i 's|}/|}|g' 'build/toolchain/linux/BUILD.gn' # use system clang + sed -i 's|rebase|#|g' 'build/toolchain/linux/BUILD.gn' + + if [[ -e 'third_party/angle/BUILD.gn' ]]; then + sed -i 's|$wayland_dir|//third_party/angle/third_party/wayland|' \ + 'third_party/angle/BUILD.gn' \ + 'third_party/angle/src/common/vulkan/BUILD.gn' \ + 'third_party/angle/src/third_party/volk/BUILD.gn' + sed -i 's|import("//build/config/chromecast_build.gni")||' 'third_party/angle/src/tests/BUILD.gn' + fi + + sed -i '/-Wno-deprecated-literal-operator/d' 'build/config/compiler/BUILD.gn' + sed -i '/G_DEFINE_AUTOPTR_CLEANUP_FUNC(PangoLayout, g_object_unref)/d' 'flutter/shell/platform/linux/fl_accessible_text_field.cc' + + # Not our problem. + sed -i 's/"-Werror",//' 'build/config/compiler/BUILD.gn' + + cat > 'third_party/dart/build/dart/prebuilt_dart_sdk.gni' <<-EOF + import("../executable_suffix.gni") + _dart_root = rebase_path("../..") + #_prebuilt_dart_exe = "" + #_prebuilt_dart_exe_trial = "" + prebuilt_dart_exe_works = true +EOF + + #_ln "${srcdir}/emsdk" 'buildtools/emsdk' + popd +} + +_build() +{ + local -r outdir="$1" + + _setup_build_env + + pushd "$outdir" + cd 'src' + + "./flutter/tools/gn" --no-prebuilt-dart-sdk --verbose --out-dir="$outdir" \ + --linux \ + --linux-cpu="$ARCH_FLUTTER_TARGET_CPU" \ + --no-goma \ + --lto \ + --enable-vulkan \ + --target-sysroot='/' \ + --runtime-mode='release' \ + --no-enable-unittests \ + || { >&2 echo '`gn gen` command failed.'; return 1; } + + sed -i 's|ldflags}|ldflags} -fuse-ld=lld|g' "$outdir/out/$flutter_outdir/toolchain.ninja" # use system linker + ninja -v -C "$outdir/out/$flutter_outdir" \ + || { >&2 echo 'Flutter engine build failed.'; return 1; } + + #export PATH+=":${srcdir}/src/flutter/lib/web_ui/dev" + #felt build + + popd +} + +_install() +{ + local -r outdir="$1" + + pushd "$outdir" + + find . -mindepth 1 -maxdepth 1 ! -name 'out' -exec rm -rf {} \; + rm -rf "out/$flutter_outdir/"{gen,obj,lib.unstripped,exe.unstripped} + ln -sf "$flutter_outdir" 'out/arch_release' + ln -sf "$flutter_outdir" 'out/host_release' + + popd +} + +_get_engine_version() +{ + local -r fvm_cache_dir="$1" + + local engine_version="$(fvm.real api project | yq -er '.project.pinnedVersion.name')" + + if [[ -z "$engine_version" || "$engine_version" == 'null' ]]; then + engine_version="$(basename $(realpath "$fvm_cache_dir/default"))" + if [[ -z "$engine_version" ]]; then + >&2 echo "No version of flutter detected." + return 1 + fi + fi + + echo "$engine_version" +} + +build_engine() +{ + local -r fvm_cache_dir="$(fvm.real api context | yq -er '.context.fvmDir')" + local -r engine_version="$(_get_engine_version "$fvm_cache_dir")" + + if [[ -z "$engine_version" ]]; then + >&2 echo "No version of flutter detected." + return 1 + fi + + local -r cache_home="${XDG_CACHE_HOME:-"$HOME/.cache"}" + local -r cached_flutter_dir="$cache_home/flutter-engine/$ARCH_FLUTTER_TARGET_CPU/$engine_version" + + mkdir -p "$cached_flutter_dir" + + #fvm.real api project + + { + flock -s 3 + + if [[ ! -L "$cached_flutter_dir/out/arch_release" ]]; then + _prepare_build "${cached_flutter_dir}" "$engine_version" && \ + _build "${cached_flutter_dir}" && \ + _install "${cached_flutter_dir}" || \ + { return 1; } + fi + + } 3> "$cached_flutter_dir/.lock" + + _ln "$cached_flutter_dir/out" '.engine-src/engine/out' +} + +download_and_patch() +{ + local -r fvm_cache_dir="$(fvm.real api context | yq -er '.context.fvmDir')" + local -r fvm_version_cache="$(fvm.real api context | yq -er '.context.versionsCachePath')" + local -r engine_version="$(_get_engine_version "$fvm_cache_dir")" + local -r flutter_dir="$fvm_version_cache/$engine_version" + + _clone_src "$ARCH_FLUTTER_ENGINE_URL" "$fvm_cache_dir/engine" "$engine_version" + _clone_src "$ARCH_FLUTTER_DEPOT_TOOL_URL" "$fvm_cache_dir/depot_tools" + _patch_flutter "$flutter_dir" +} + + +cmd= +for (( i=1; i<=${#@}; i++ )); do + if [[ ! "${!i}" =~ ^-.* ]]; then + cmd="${!i}" + break + fi +done + +case "$cmd" in + dart|flutter) + download_and_patch + build_engine + setup_flutter_env + fvm.real "$@" + ;; + *) + fvm.real "$@" + ;; +esac +