Created
September 14, 2023 15:28
-
-
Save thejustinwalsh/cf352e6186f5781dd6b9f2503ffaef60 to your computer and use it in GitHub Desktop.
nodejs unreal plugin build script (macOS)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { readFile, readdir } from 'fs/promises' | |
import { existsSync } from 'fs'; | |
import { resolve, join, sep } from 'path' | |
import { argv } from 'process'; | |
import { spawn } from 'child_process'; | |
const exec = ( | |
cmd, | |
args, | |
) => new Promise((resolve, reject) => { | |
const cp = spawn(cmd, args, { stdio: ['ignore', 'inherit', 'inherit'] }); | |
cp.on('exit', (code) => (code && code !== 0) ? reject(code) : resolve(0)); | |
}); | |
const getEngineVersion = async (uprojectPath) => { | |
const uproject = await readFile(uprojectPath, 'utf-8'); | |
const project = JSON.parse(uproject); | |
const engineVersion = project.EngineAssociation; | |
if (!engineVersion) throw new Error(`Could not find engine version in ${uprojectPath}`); | |
return engineVersion; | |
} | |
const getInstallLocation = async (engineVersion) => { | |
const installIniPath = join(process.env.HOME, 'Library/Application Support/Epic/UnrealEngine/Install.ini'); | |
const installIni = await readFile(installIniPath, 'utf-8'); | |
const matches = installIni.match(new RegExp(`^{${engineVersion}}=(.*)`, 'gm')); | |
let installLocation = matches ? matches[1] : ""; | |
if (!installLocation) { | |
const dirListing = await readdir(join(process.env.HOME, 'Library/Application Support/Epic/UnrealEngine')); | |
const configCacheFiles = dirListing.filter(file => file.startsWith('XmlConfigCache')); | |
const configCache = configCacheFiles.find(file => file.includes(`UE_${engineVersion}`)); | |
if (!configCache) throw new Error(`Could not find Unreal Engine ${engineVersion} installation location`); | |
const encodedPath = configCache.match(/XmlConfigCache-(.*)\.bin/)[1] ?? ""; | |
if (encodedPath) installLocation = encodedPath.replace(/\+/g, sep); | |
} | |
if (!installLocation) throw new Error(`Could not find Unreal Engine ${engineVersion} installation location`); | |
return installLocation; | |
} | |
const getRunUATPath = async (engineVersion) => { | |
const installLocation = await getInstallLocation(engineVersion); | |
const runUATPath = join(installLocation, `Engine/Build/BatchFiles/RunUAT.${process.platform === 'win32' ? 'bat' : 'sh'}`); | |
if (!existsSync(runUATPath)) throw new Error(`Could not find RunUAT script in ${installLocation}`); | |
return runUATPath; | |
} | |
const getPluginPath = async (uprojectPath, pluginName) => { | |
const uprojectDir = resolve(uprojectPath, '..'); | |
const pluginDir = join(uprojectDir, 'Plugins', pluginName); | |
const pluginFile = join(pluginDir, `${pluginName}.uplugin`); | |
if (!existsSync(pluginFile)) throw new Error(`Could not find plugin ${pluginName} in ${pluginDir}`); | |
return pluginFile; | |
} | |
const buildPlugin = async (engineVersion, pluginPath) => { | |
const runUATPath = await getRunUATPath(engineVersion); | |
const exitCode = await exec(runUATPath, ["BuildPlugin", `-Plugin=${pluginPath}`, `-Package=${process.cwd()}/Packages/Mac`, "-Rocket", "-TargetPlatforms=Mac"]); | |
if (exitCode !== 0) throw new Error(`Failed to build plugin ${pluginPath}`); | |
} | |
const main = async () => { | |
if (argv.length < 4) throw new Error('Usage: build.mjs <uproject path> <plugin name>'); | |
if (process.platform !== 'darwin') throw new Error('TODO: Need to modify this script to work on windows and linux'); | |
const uprojectPath = resolve(argv[2]); | |
const plugin = await getPluginPath(uprojectPath, argv[3]); | |
const engineVersion = await getEngineVersion(uprojectPath); | |
await buildPlugin(engineVersion, plugin); | |
} | |
await main(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment