From 9de9bec3fa0415bd68610f263b0db3fefbaaed39 Mon Sep 17 00:00:00 2001 From: ehutchllew Date: Fri, 10 May 2024 00:52:28 -0400 Subject: [PATCH] Core/multiplatform binaries (#19) * Saving progress: making a Makefile to handle building and publishing * Adding some platform specific builds and publishing commands to the Makefile; Adding directories for platform binary output * Changing package json bin location and adding a default bin created by makefile * Typo in Makefile * Adding a postinstall script to swap default bin with os viable bin * Fixing a couple typos * Got Makefile mostly working * Finished with Makefile * Adding a clean action to Makefile * Tweaking publish checks in Makefile * Adjusting optionalDeps versions --- .github/workflows/deploy.yml | 2 +- Makefile | 90 +++++++++++++++++++++++++++ npm/@tmplts/darwin-arm64/package.json | 20 ++++++ npm/@tmplts/darwin-x64/package.json | 20 ++++++ npm/@tmplts/linux-x64/package.json | 20 ++++++ npm/install.js | 50 +++++++++++++++ npm/package.json | 18 +++++- 7 files changed, 217 insertions(+), 3 deletions(-) create mode 100644 Makefile create mode 100644 npm/@tmplts/darwin-arm64/package.json create mode 100644 npm/@tmplts/darwin-x64/package.json create mode 100644 npm/@tmplts/linux-x64/package.json create mode 100644 npm/install.js diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 88ce65b..f6c1723 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -63,7 +63,7 @@ jobs: uses: actions/download-artifact@v4 with: name: go_binary - path: npm + path: npm/bin - name: Copy Files run: cp ../README.md ../LICENSE ./ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..7058e06 --- /dev/null +++ b/Makefile @@ -0,0 +1,90 @@ +VERSION := $(shell go run scripts/version.go) +# Strip debug info (symbol table and DWARF) +# Also add version info to binary +GO_FLAGS += "-ldflags=-s -w -X 'github.com/ev-the-dev/tmplts/cmd.version=$(VERSION)'" + +# Avoid embedding build path in executable +GO_FLAGS += -trimpath + +.PHONY version: +version: + @echo "Version: $(VERSION)" + +.PHONY clean: +clean: + rm -f npm/README.md npm/LICENSE &&\ + rm -rf npm/bin + + cd npm/@tmplts && \ + rm -rf \ + darwin-arm64/bin \ + darwin-x64/bin \ + linux-x64/bin + + cd npm/@tmplts && \ + rm -f\ + darwin-arm64/README.md darwin-arm64/LICENSE \ + darwin-x64/README.md darwin-x64/LICENSE \ + linux-x64/README.md linux-x64/LICENSE + +.PHONY copy-files: +copy-files: + cp README.md LICENSE npm/ + cp README.md LICENSE npm/@tmplts/darwin-arm64/ + cp README.md LICENSE npm/@tmplts/darwin-x64/ + cp README.md LICENSE npm/@tmplts/linux-x64/ + + ############## + # Publishing # +############## +.PHONY: publish-all +publish-all: copy-files + @echo "Attempting to publish all supported binaries..." + @npm --version > /dev/null || (echo "The 'npm' command must be in your path to publish" && false) + @echo "Checking for uncommitted & untracked changes..." && test -z "`git status --porcelain | grep -vE '(README\.md|LICENSE)'`" || \ + (echo "Cannot publish with uncommited/untracked changes:" && \ + git status --porcelain | grep -vE '(README\.md|LICENSE)' && false) + @echo "Checking for main branch..." && test main = "`git rev-parse --abbrev-ref HEAD`" || \ + (echo "Cannot publish from non-main branch `git rev-parse --abbrev-ref HEAD`" && false) + @echo "Checking for unpushed commits..." && git fetch + @test "" = "`git cherry`" || (echo "Cannot publish with unpushed commits" && false) + + @$(MAKE) --no-print-directory -j4 \ + publish-default \ + publish-darwin-arm64 \ + publish-darwin-x64 \ + publish-linux-x64 + +publish-default: platform-default + cd npm && npm publish + +publish-darwin-arm64: platform-darwin-arm64 + cd npm/@tmplts/darwin-arm64 && npm publish + +publish-darwin-x64: platform-darwin-x64 + cd npm/@tmplts/darwin-x64 && npm publish + +publish-linux-x64: platform-linux-x64 + cd npm/@tmplts/linux-x64 && npm publish + + + ################## + # Platform Build # +################## +platform-unixlike: + @test -n "$(GOOS)" || (echo "The environment variable GOOS must be provided" && false) + @test -n "$(GOARCH)" || (echo "The environment variable GOARCH must be provided" && false) + @test -n "$(NPMDIR)" || (echo "The environment variable NPMDIR must be provided" && false) + CGO_ENABLED=0 GOOS="$(GOOS)" GOARCH="$(GOARCH)" go build $(GO_FLAGS) -o "$(NPMDIR)/bin/tmplts" + +platform-default: + @$(MAKE) --no-print-directory GOOS=darwin GOARCH=arm64 NPMDIR=npm platform-unixlike + +platform-darwin-arm64: + @$(MAKE) --no-print-directory GOOS=darwin GOARCH=arm64 NPMDIR=npm/@tmplts/darwin-arm64 platform-unixlike + +platform-darwin-x64: + @$(MAKE) --no-print-directory GOOS=darwin GOARCH=amd64 NPMDIR=npm/@tmplts/darwin-x64 platform-unixlike + +platform-linux-x64: + @$(MAKE) --no-print-directory GOOS=linux GOARCH=amd64 NPMDIR=npm/@tmplts/linux-x64 platform-unixlike diff --git a/npm/@tmplts/darwin-arm64/package.json b/npm/@tmplts/darwin-arm64/package.json new file mode 100644 index 0000000..1e9812b --- /dev/null +++ b/npm/@tmplts/darwin-arm64/package.json @@ -0,0 +1,20 @@ +{ + "name": "@tmplts/darwin-arm64", + "author": "ev-the-dev", + "version": "0.1.1", + "description": "MacOS ARM 64-bit (Mac Silicon) binary for TmplTS", + "license": "Apache-2.0", + "repository": { + "type": "git", + "url": "git+https://github.com/ev-the-dev/tmplts.git" + }, + "publishConfig": { + "access": "public" + }, + "os": [ + "darwin" + ], + "cpu": [ + "arm64" + ] +} diff --git a/npm/@tmplts/darwin-x64/package.json b/npm/@tmplts/darwin-x64/package.json new file mode 100644 index 0000000..0c1eeb2 --- /dev/null +++ b/npm/@tmplts/darwin-x64/package.json @@ -0,0 +1,20 @@ +{ + "name": "@tmplts/darwin-x64", + "author": "ev-the-dev", + "version": "0.1.1", + "description": "MacOS AMD 64-bit (Intel) binary for TmplTS", + "license": "Apache-2.0", + "repository": { + "type": "git", + "url": "git+https://github.com/ev-the-dev/tmplts.git" + }, + "publishConfig": { + "access": "public" + }, + "os": [ + "darwin" + ], + "cpu": [ + "x64" + ] +} diff --git a/npm/@tmplts/linux-x64/package.json b/npm/@tmplts/linux-x64/package.json new file mode 100644 index 0000000..1eadfcb --- /dev/null +++ b/npm/@tmplts/linux-x64/package.json @@ -0,0 +1,20 @@ +{ + "name": "@tmplts/linux-x64", + "author": "ev-the-dev", + "version": "0.1.1", + "description": "Linux 64-bit (Intel) binary for TmplTS", + "license": "Apache-2.0", + "repository": { + "type": "git", + "url": "git+https://github.com/ev-the-dev/tmplts.git" + }, + "publishConfig": { + "access": "public" + }, + "os": [ + "linux" + ], + "cpu": [ + "x64" + ] +} diff --git a/npm/install.js b/npm/install.js new file mode 100644 index 0000000..be57ffd --- /dev/null +++ b/npm/install.js @@ -0,0 +1,50 @@ +const fs = require("fs") +const os = require("os") +const path = require("path") + +const supportedUnixLikePackages = { + "darwin arm64 LE": "@tmplts/darwin-arm64", + "darwin x64 LE": "@tmplts/darwin-x64", + "linux x64 LE": "@tmplts/linux-x64" +} + +function getPkgAndPathForPlatform() { + const platformKey = `${process.platform} ${os.arch()} ${os.endianness()}` + const pkgPath = supportedUnixLikePackages[platformKey] + + if(!pkgPath) { + throw new Error(`Unsupported OS: ${platformKey}`) + } + + return pkgPath +} + +function main() { + const pkgPath = getPkgAndPathForPlatform() + const binSubPath = "bin/tmplts" + + const binFullPath = require.resolve(`${pkgPath}/${binSubPath}`) + const tempPath = path.join(__dirname, "bin-tmplts") + try { + /* + * First: linking binary with temp file. + */ + fs.linkSync(binFullPath, tempPath) + + /* + * Second: rename to atomically replace target file with temp file + */ + fs.renameSync(tempPath, path.join(__dirname, "bin", "tmplts")) + + /* + * Third: Remove temp file if it still exists + */ + if(fs.existsSync(tempPath)){ + fs.unlinkSync(tempPath) + } + } catch (e) { + console.error("Failed to swap out default binary with platform compatible one:\nERROR:", e) + } +} + +main() diff --git a/npm/package.json b/npm/package.json index f9490b6..f098592 100644 --- a/npm/package.json +++ b/npm/package.json @@ -1,11 +1,20 @@ { "name": "@ev-the-dev/tmplts", "author": "ev-the-dev", - "version": "0.1.0", + "version": "0.1.1", "description": "TypeScript Project Configuration Bootstrapper", "license": "Apache-2.0", "bin": { - "tmplts": "tmplts" + "tmplts": "bin/tmplts" + }, + "files": [ + "package.json", + "LICENSE", + "README.md", + "bin/tmplts" + ], + "scripts": { + "postinstall": "node install.js" }, "repository": { "type": "git", @@ -18,6 +27,11 @@ "bugs": { "url": "https://github.com/ev-the-dev/tmplts/issues" }, + "optionalDependencies": { + "@tmplts/darwin-arm64": "0.1.1", + "@tmplts/darwin-x64": "0.1.1", + "@tmplts/linux-x64": "0.1.1" + }, "keywords": [ "typescript", "eslint",