diff --git a/scripts/build.ps1 b/scripts/build.ps1 index e01688e8..7e171ae8 100644 --- a/scripts/build.ps1 +++ b/scripts/build.ps1 @@ -1,36 +1,146 @@ -# Usage: ./scripts/build.ps1 -# This is only for local builds. +# This script builds memos for all listed platforms. +# It's only for local builds. -# For development, setup a proper environment as described here: -# https://github.com/usememos/memos/blob/main/docs/development.md +# Before using, setup a proper development environment as described here: +# * https://usememos.com/docs/contribution/development +# * https://github.com/usememos/memos/blob/main/docs/development.md -$projectRoot = (Resolve-Path "$MyInvocation.MyCommand.Path/..").Path -Write-Host "Project root: $projectRoot" +# Requirements: +# * go +# * node.js +# * npm -Write-Host "Building frontend..." -f Magenta -Set-Location "$projectRoot/web" -npm install -g pnpm +# Usage: +# ./scripts/build.ps1 +# +# Output: ./build/memos--[.exe] + +$goBuilds = @( + # "darwin/amd64" + # "darwin/arm64" + # "linux/amd64" + # "linux/arm64" + "windows/amd64" +) +$ldFlags = @( + "-s" # Omit symbol table and debug information + "-w" # Omit DWARF symbol table +) + +## + +foreach ($dir in @(".", "../")) { + if (Test-Path (Join-Path $dir ".gitignore")) { + $repoRoot = (Resolve-Path $dir).Path + break + } +} +if ([string]::IsNullOrWhiteSpace($repoRoot)) { + Write-Host -BackgroundColor red -ForegroundColor white "Could not find repository root." + Exit 1 +} + +Write-Host "Repository root: " -NoNewline +Write-Host $repoRoot -f Blue + +Set-Location "$repoRoot/web" + +if (-not (Get-Command pnpm -ErrorAction SilentlyContinue)) { + Write-Host "Installing pnpm..." -f DarkYellow + npm install -g pnpm + if (!$?) { + Write-Host -BackgroundColor red -ForegroundColor white "Could not install pnpm. See above." + Exit 1 + } +} + +Write-Host "`nInstalling frontend dependencies..." -f DarkYellow pnpm i --frozen-lockfile -pnpm build +if (!$?) { + Write-Host -BackgroundColor red -ForegroundColor white "Could not install frontend dependencies. See above." + Exit 1 +} +Write-Host "Frontend dependencies installed!" -f green -Write-Host "Backing up frontend placeholder..." -f Magenta -Move-Item "$projectRoot/server/dist" "$projectRoot/server/dist.bak" -Force -ErrorAction Stop +Write-Host "`nBuilding frontend..." -f DarkYellow +$frontendTime = Measure-Command { + &pnpm build | Out-Host +} +if (!$?) { + Write-Host -BackgroundColor red -ForegroundColor white "Could not build frontend. See above." + Exit 1 +} else { + Write-Host "Frontend built!" -f green +} -Write-Host "Moving frontend build to /server/dist ..." -f Magenta -Move-Item "$projectRoot/web/dist" "$projectRoot/server/" -Force -ErrorAction Stop +Write-Host "`nBacking up frontend placeholder..." -f Magenta +Move-Item "$repoRoot/server/dist" "$repoRoot/server/dist.bak" -Force -ErrorAction Stop +if (!$?) { + Write-Host -BackgroundColor red -ForegroundColor white "Could not backup frontend placeholder. See above." + Exit 1 +} -Set-Location $projectRoot +Write-Host "Moving frontend build to ./server/dist..." -f Magenta +Move-Item "$repoRoot/web/dist" "$repoRoot/server/" -Force -ErrorAction Stop +if (!$?) { + Write-Host -BackgroundColor red -ForegroundColor white "Could not move frontend build to /server/dist. See above." + Exit 1 +} -Write-Host "Building backend..." -f Magenta -go build -o ./build/memos.exe ./main.go +Set-Location $repoRoot +Write-Host "`nBuilding backend..." -f DarkYellow + +$backendTime = Measure-Command { + foreach ($build in $goBuilds) { + $os, $arch = $build.Split("/") + $Env:CGO_ENABLED = 0 + $Env:GOOS = $os + $Env:GOARCH = $arch + + $output = [IO.Path]::Combine($repoRoot, "build", "memos-$os-$arch") + if ($os -eq "windows") { + $output += ".exe" + } + + Write-Host "Building $os/$arch to $output..." -f Blue + &go build -trimpath -o $output -ldflags="$($ldFlags -join " ")" ./main.go | Out-Host + if (!$?) { + Write-Host -BackgroundColor red -ForegroundColor white "'go build' failed for $build ($outputBinary)!. See above." + continue + } + } +} Write-Host "Backend built!" -f green -Write-Host "Removing frontend from /server/dist ..." -f Magenta -Remove-Item "$projectRoot/server/dist" -Recurse -Force -ErrorAction SilentlyContinue +Write-Host "`nFrontend build took $($frontendTime.TotalSeconds) seconds." -f Cyan +Write-Host "Backend builds took $($backendTime.TotalSeconds) seconds." -f Cyan + +Write-Host "`nRemoving frontend from ./server/dist ..." -f Magenta +Remove-Item "$repoRoot/server/dist" -Recurse -Force -ErrorAction SilentlyContinue +if (!$?) { + Write-Host -BackgroundColor red -ForegroundColor white "Could not remove frontend from /server/dist. See above." + Exit 1 +} Write-Host "Restoring frontend placeholder..." -f Magenta -Move-Item "$projectRoot/server/dist.bak" "$projectRoot/server/dist" -Force -ErrorAction Stop +Move-Item "$repoRoot/server/dist.bak" "$repoRoot/server/dist" -Force -ErrorAction Stop +if (!$?) { + Write-Host -BackgroundColor red -ForegroundColor white "Could not restore frontend placeholder. See above." + Exit 1 +} -Write-Host "You can test the build with ./build/memos.exe --mode demo" -f Green +Write-Host "`nBuilds:" -f White +foreach ($build in $goBuilds) { + $output = [IO.Path]::Combine($repoRoot, "build", "memos-$os-$arch") + if ($os -eq "windows") { + $output = "$output.exe" + } + Write-Host $output -f White +} -Set-Location -Path $projectRoot \ No newline at end of file +Write-Host -f Green "`nYou can test the build with" -NoNewline +Write-Host -f White "` ./build/memos--" -NoNewline +Write-Host -f DarkGray "`.exe" -NoNewline +Write-Host -f White " --mode demo" + +Set-Location -Path $repoRoot diff --git a/scripts/build.sh b/scripts/build.sh index b1b855a8..eeb1434c 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -1,13 +1,152 @@ #!/bin/bash +# This script builds memos for all listed platforms. +# It's only for local builds. -# Usage: ./scripts/build.sh +# Before using, setup a proper development environment as described here: +# * https://usememos.com/docs/contribution/development +# * https://github.com/usememos/memos/blob/main/docs/development.md -set -e +# Requirements: +# * go +# * node.js +# * npm -cd "$(dirname "$0")/../" +# Usage: +# chmod +x ./scripts/build.sh +# ./scripts/build.sh +# +# Output: ./build/memos--[.exe] -echo "Start building backend..." +goBuilds=( + # "darwin/amd64" + # "darwin/arm64" + "linux/amd64" + # "linux/arm64" + # "windows/amd64" +) +ldFlags=( + "-s" # Omit symbol table and debug information + "-w" # Omit DWARF symbol table +) -go build -o ./build/memos ./main.go +## -echo "Backend built!" +find_repo_root() { + # Usage: find_repo_root ... + local looking_for="${1:-".gitignore"}" + shift + local default_dirs=("." "../") + local dirs=("${@:-${default_dirs[@]}}") + for dir in "${dirs[@]}"; do + if [ -f "$dir/$looking_for" ]; then + echo $(realpath "$dir") + return + fi + done +} + +repo_root=$(find_repo_root) +if [ -z "$repo_root" ]; then + echo -e "\033[0;31mRepository root not found! Exiting.\033[0m" + exit 1 +else + echo -e "Repository root: \033[0;34m$repo_root\033[0m" +fi + + +cd "$repo_root/web" + +if ! command -v pnpm &> /dev/null +then + echo -e "\n\033[35mInstalling pnpm...\033[0m" + npm install -g pnpm + if [ $? -ne 0 ]; then + echo -e "\033[0;31mFailed to install pnpm! Exiting.\033[0m" + exit 1 + fi +fi + +echo -e "\n\033[33mInstalling frontend dependencies...\033[0m" +pnpm i --frozen-lockfile +if [ $? -ne 0 ]; then + echo -e "\033[0;31mFrontend dependencies failed to install! Exiting.\033[0m" + exit 1 +fi +echo -e "\033[32mFrontend dependencies installed!\033[0m" + +echo -e "\n\033[33mBuilding frontend...\033[0m" +pnpm build +if [ $? -ne 0 ]; then + echo -e "\033[0;31mFrontend build failed! Exiting.\033[0m" + exit 1 +fi +echo -e "\033[32mFrontend built!\033[0m" + +cd $repo_root + +echo -e "\n\033[35mBacking up frontend placeholder...\033[0m" +mv -f "$repo_root/server/dist" "$repo_root/server/dist.bak" +if [ $? -ne 0 ]; then + echo -e "\033[0;31mFailed to backup frontend placeholder! Exiting.\033[0m" + exit 1 +fi + +echo -e "\033[35mMoving frontend build to ./server/dist...\033[0m" +mv -f "$repo_root/web/dist" "$repo_root/server/" +if [ $? -ne 0 ]; then + echo -e "\033[0;31mFailed to move frontend build! Exiting.\033[0m" + exit 1 +fi + +cd "$repo_root" +echo -e "\n\033[33mBuilding backend...\033[0m" + +for build in "${goBuilds[@]}"; do + os=$(echo $build | cut -d'/' -f1) + arch=$(echo $build | cut -d'/' -f2) + + output="$repo_root/build/memos-$os-$arch" + if [ "$os" = "windows" ]; then + output="$output.exe" + fi + + CGO_ENABLED=0 GOOS=$os GOARCH=$arch go build -trimpath -ldflags="${ldFlags[*]}" -o "$output" ./main.go + + echo -e "\033[34mBuilding $os/$arch to $output...\033[0m" + GOOS=$os GOARCH=$arch go build -ldflags="${ldFlags[*]}" -o "./build/memos-$os-$arch" ./main.go + if [ $? -ne 0 ]; then + echo -e "\033[0;31mgo build failed for $os/$arch($output)! See above.\033[0m" + fi +done + +echo -e "\033[32mBackend built!\033[0m" + +echo -e "\n\033[35mRemoving frontend from ./server/dist...\033[0m" +rm -rf $repo_root/server/dist +if [ $? -ne 0 ] +then + echo -e "\033[93mCould not remove frontend from /server/dist.\033[0m" + exit 1 +fi + +echo -e "\033[35mRestoring frontend placeholder...\033[0m" +mv $repo_root/server/dist.bak $repo_root/server/dist +if [ $? -ne 0 ] +then + echo -e "\033[93mCould not restore frontend placeholder.\033e[0m" + exit 1 +fi + +echo -e "\n\033[37mBuilds:\033[0m" +for build in "${goBuilds[@]}"; do + os=$(echo $build | cut -d'/' -f1) + arch=$(echo $build | cut -d'/' -f2) + output="$repo_root/build/memos-$os-$arch" + if [ "$os" = "windows" ]; then + output="$output.exe" + fi + echo -e "\033[37m$output\033[0m" +done +echo -e "\n\033[32mYou can test the build with \033[37m./build/memos--\033[0m\033[90m.exe\033[0m \033[37m--mode demo\033[0m" + +cd $repo_root