This guide builds RetopoFlow 4 from its GitHub source and prepares a GitHub-style release ZIP using the repository's build scripts. The installation script supports Windows through MSYS2 and Linux, including Blender installations managed through Steam.
Prerequisites
- Bash on Linux or MSYS2 Bash on Windows
- Blender 4.3 or newer installed locally
- Internet access for cloning the CGCookie repositories
The script checks for all required command-line tools before cloning or building anything. If something is missing, it displays an appropriate installation command.
Install script
#!/usr/bin/env bash
set -Eeuo pipefail
PROJECTS_DIR="${PROJECTS_DIR:-$HOME/projects}"
REPO_DIR="$PROJECTS_DIR/retopoflow"
BUILD_DIR="$PROJECTS_DIR/retopoflow_release"
RETOPOFLOW_BRANCH="${RETOPOFLOW_BRANCH:-v4.1.9}"
# ------------------------------------------------------------
# Detect platform
# ------------------------------------------------------------
case "$(uname -s)" in
Linux*)
PLATFORM="linux"
;;
MINGW*|MSYS*|CYGWIN*)
PLATFORM="msys2"
;;
*)
echo "ERROR: This script currently supports Linux and MSYS2." >&2
echo "Detected: $(uname -s)" >&2
exit 1
;;
esac
echo "=== Platform: $PLATFORM ==="
echo "=== RetopoFlow branch: $RETOPOFLOW_BRANCH ==="
# ------------------------------------------------------------
# Check dependencies
# ------------------------------------------------------------
REQUIRED_TOOLS=(
git
make
rsync
zip
python3
find
sort
tail
mktemp
realpath
cat
chmod
rm
mkdir
ls
)
if [[ "$PLATFORM" == "msys2" ]]; then
REQUIRED_TOOLS+=(cygpath)
fi
MISSING_TOOLS=()
for tool in "${REQUIRED_TOOLS[@]}"; do
if ! command -v "$tool" >/dev/null 2>&1; then
MISSING_TOOLS+=("$tool")
fi
done
if ((${#MISSING_TOOLS[@]})); then
echo
echo "ERROR: Missing required commands:"
printf ' - %s\n' "${MISSING_TOOLS[@]}"
echo
echo "Install the missing dependencies, then run this script again."
echo
if [[ "$PLATFORM" == "msys2" ]]; then
echo "Suggested MSYS2 command:"
echo " pacman -S --needed git make rsync zip python coreutils findutils"
elif command -v apt-get >/dev/null 2>&1; then
echo "Suggested Debian/Ubuntu command:"
echo " sudo apt-get install git make rsync zip python3 coreutils findutils"
elif command -v dnf >/dev/null 2>&1; then
echo "Suggested Fedora command:"
echo " sudo dnf install git make rsync zip python3 coreutils findutils"
elif command -v pacman >/dev/null 2>&1; then
echo "Suggested Arch Linux command:"
echo " sudo pacman -S --needed git make rsync zip python coreutils findutils"
elif command -v zypper >/dev/null 2>&1; then
echo "Suggested openSUSE command:"
echo " sudo zypper install git make rsync zip python3 coreutils findutils"
else
echo "Use your Linux distribution's package manager."
fi
exit 1
fi
echo "All required command-line tools were found."
# ------------------------------------------------------------
# Find Blender
# ------------------------------------------------------------
echo
echo "=== Looking for Blender ==="
BLENDER_MODE="binary"
BLENDER_BIN="${BLENDER_BIN:-}"
# Accept a Windows-style path under MSYS2.
if [[ "$PLATFORM" == "msys2" &&
"$BLENDER_BIN" =~ ^[A-Za-z]:[\\/].* ]]; then
BLENDER_BIN="$(cygpath -u "$BLENDER_BIN")"
fi
if [[ -z "$BLENDER_BIN" ]]; then
if [[ "$PLATFORM" == "msys2" ]]; then
# Check PATH first.
BLENDER_BIN="$(command -v blender.exe 2>/dev/null || true)"
# Search standard Windows Blender installations.
if [[ -z "$BLENDER_BIN" ]]; then
BLENDER_BIN="$(
find "/c/Program Files/Blender Foundation" \
-maxdepth 3 \
-type f \
-iname 'blender.exe' \
2>/dev/null |
sort -V |
tail -n 1
)"
fi
else
# Check distribution packages, Snap, and other installations
# that expose Blender on PATH.
BLENDER_BIN="$(command -v blender 2>/dev/null || true)"
# Check common Steam installation locations.
if [[ -z "$BLENDER_BIN" ]]; then
STEAM_ROOTS=(
"$HOME/.local/share/Steam"
"$HOME/.steam/steam"
"$HOME/.var/app/com.valvesoftware.Steam/data/Steam"
)
for STEAM_ROOT in "${STEAM_ROOTS[@]}"; do
STEAM_BLENDER="$STEAM_ROOT/steamapps/common/Blender/blender"
if [[ -x "$STEAM_BLENDER" ]]; then
BLENDER_BIN="$STEAM_BLENDER"
break
fi
done
fi
# Check RetopoFlow's default Blender location.
if [[ -z "$BLENDER_BIN" &&
-x "$HOME/software/blender/blender" ]]; then
BLENDER_BIN="$HOME/software/blender/blender"
fi
# Check Blender installed directly through Flatpak.
if [[ -z "$BLENDER_BIN" ]] &&
command -v flatpak >/dev/null 2>&1 &&
flatpak info org.blender.Blender >/dev/null 2>&1; then
BLENDER_MODE="flatpak"
fi
fi
fi
if [[ "$BLENDER_MODE" == "binary" ]]; then
# Resolve a command name supplied through BLENDER_BIN.
if [[ -n "$BLENDER_BIN" && "$BLENDER_BIN" != */* ]]; then
BLENDER_BIN="$(command -v "$BLENDER_BIN" 2>/dev/null || true)"
fi
if [[ -z "$BLENDER_BIN" || ! -x "$BLENDER_BIN" ]]; then
echo
echo "ERROR: Could not find an executable Blender binary." >&2
if [[ "$PLATFORM" == "msys2" ]]; then
echo "Expected Blender beneath:" >&2
echo ' C:\Program Files\Blender Foundation' >&2
else
echo "Checked PATH, common Steam locations, and Flatpak." >&2
fi
echo >&2
echo "You can specify Blender explicitly:" >&2
echo " BLENDER_BIN=/path/to/blender $0" >&2
exit 1
fi
BLENDER_BIN="$(realpath "$BLENDER_BIN")"
echo "Found Blender: $BLENDER_BIN"
else
echo "Found Blender Flatpak: org.blender.Blender"
fi
# ------------------------------------------------------------
# Create a no-space Blender launcher for the Makefile
# ------------------------------------------------------------
echo
echo "=== Creating Blender launcher ==="
BLENDER_LAUNCHER="$(
mktemp "${TMPDIR:-/tmp}/retopoflow-blender.XXXXXX"
)"
cleanup() {
rm -f -- "$BLENDER_LAUNCHER"
}
trap cleanup EXIT
if [[ "$BLENDER_MODE" == "flatpak" ]]; then
cat >"$BLENDER_LAUNCHER" <<'EOF'
#!/usr/bin/env bash
exec flatpak run org.blender.Blender "$@"
EOF
else
export BLENDER_BIN
cat >"$BLENDER_LAUNCHER" <<'EOF'
#!/usr/bin/env bash
exec "$BLENDER_BIN" "$@"
EOF
fi
chmod 700 "$BLENDER_LAUNCHER"
echo
echo "=== Blender version ==="
"$BLENDER_LAUNCHER" --version
# ------------------------------------------------------------
# Clone, switch, or update RetopoFlow
# ------------------------------------------------------------
echo
echo "=== Creating projects directory ==="
mkdir -p "$PROJECTS_DIR"
echo
echo "=== Cloning/updating RetopoFlow ==="
if [[ -d "$REPO_DIR/.git" ]]; then
git -C "$REPO_DIR" fetch origin --prune
if git -C "$REPO_DIR" show-ref \
--verify \
--quiet "refs/heads/$RETOPOFLOW_BRANCH"; then
git -C "$REPO_DIR" checkout "$RETOPOFLOW_BRANCH"
else
git -C "$REPO_DIR" checkout \
--track \
-b "$RETOPOFLOW_BRANCH" \
"origin/$RETOPOFLOW_BRANCH"
fi
git -C "$REPO_DIR" pull \
--ff-only \
origin \
"$RETOPOFLOW_BRANCH"
elif [[ -e "$REPO_DIR" ]]; then
echo "ERROR: $REPO_DIR exists but is not a Git repository." >&2
exit 1
else
git clone \
--branch "$RETOPOFLOW_BRANCH" \
https://github.com/CGCookie/retopoflow.git \
"$REPO_DIR"
fi
cd "$REPO_DIR"
# Initialize submodules if the selected branch declares any.
if git config \
-f .gitmodules \
--get-regexp '^submodule\..*\.path$' \
>/dev/null 2>&1; then
git submodule sync --recursive
# Use HTTPS for addon_common if it is configured as a submodule.
git config \
submodule.addon_common.url \
https://github.com/CGCookie/addon_common.git
git submodule update --init --recursive
fi
echo
echo "=== Current RetopoFlow source ==="
git log -1 --oneline
echo
echo "=== RetopoFlow branch ==="
git branch --show-current
echo
echo "=== RetopoFlow version ==="
python3 scripts/get_blinfo_value.py version
# ------------------------------------------------------------
# Build the package
# ------------------------------------------------------------
echo
echo "=== Cleaning previous RetopoFlow build ==="
make clean
echo
echo "=== Building RetopoFlow GitHub package ==="
make build-github BLENDER="$BLENDER_LAUNCHER"
ZIP_PATH="$(
find "$BUILD_DIR" \
-maxdepth 1 \
-type f \
-name '*GitHub.zip' \
-print \
-quit
)"
if [[ -z "$ZIP_PATH" ]]; then
echo
echo "ERROR: Build completed, but no GitHub ZIP was found." >&2
echo "Expected output directory: $BUILD_DIR" >&2
echo
echo "Contents of the release directory:"
ls -lah "$BUILD_DIR" 2>/dev/null || true
exit 1
fi
ZIP_PATH="$(realpath "$ZIP_PATH")"
echo
echo "=============================================="
echo "BUILD COMPLETE"
echo "=============================================="
echo
echo "Your RetopoFlow ZIP is:"
echo
if [[ "$PLATFORM" == "msys2" ]]; then
echo "$(cygpath -w "$ZIP_PATH")"
if command -v explorer.exe >/dev/null 2>&1; then
echo
echo "Opening the output directory in Windows Explorer..."
explorer.exe "$(cygpath -w "$BUILD_DIR")" || true
fi
else
echo "$ZIP_PATH"
if command -v xdg-open >/dev/null 2>&1 &&
[[ -n "${DISPLAY:-}${WAYLAND_DISPLAY:-}" ]]; then
echo
echo "Opening the output directory..."
xdg-open "$BUILD_DIR" >/dev/null 2>&1 || true
fi
fi
echo
echo "Install this ZIP from Blender's Add-ons or Extensions preferences."
How to use
- Save the script as
install-retopoflow.sh. - Open Linux Bash or MSYS2 Bash in the directory containing the script.
- Run
chmod +x install-retopoflow.sh. - Run
./install-retopoflow.sh. - If dependencies are missing, install them using the command displayed by the script and run it again.
- Install the generated
*GitHub.zipfrom Blender's Add-ons or Extensions preferences.
Custom Blender location
If Blender is not available on PATH or in a recognized installation location, provide its executable through BLENDER_BIN.
Linux example:
BLENDER_BIN=/opt/blender/blender ./install-retopoflow.sh
Steam on Linux example:
BLENDER_BIN="$HOME/.local/share/Steam/steamapps/common/Blender/blender" \
./install-retopoflow.sh
MSYS2 example:
BLENDER_BIN='/c/Program Files/Blender Foundation/Blender 4.5/blender.exe' \
./install-retopoflow.sh
Selecting another branch
The script defaults to RetopoFlow's v4 branch. A different branch can be selected through RETOPOFLOW_BRANCH.
RETOPOFLOW_BRANCH=v4 ./install-retopoflow.sh
Notes
- The script explicitly checks out the
v4branch instead of the repository's defaultmasterbranch. - The default
masterbranch currently contains RetopoFlow 3. - The script supports Linux and Windows through MSYS2.
- Native, Steam, Snap, and Flatpak Blender installations are supported.
- Common Steam installation locations are checked automatically on Linux.
- Dependencies are checked before cloning, updating, cleaning, or building anything.
- Dependencies are not installed automatically.
- An existing clone is switched to the selected branch and updated with a fast-forward-only pull.
- Otherwise, the selected branch is cloned into
~/projects/retopoflow. - The previous release directory is removed by RetopoFlow's
make cleantarget before rebuilding.