diff --git a/buildgraph/CoreBuildGraph.xml b/buildgraph/CoreBuildGraph.xml
new file mode 100644
index 0000000..a7cbc1e
--- /dev/null
+++ b/buildgraph/CoreBuildGraph.xml
@@ -0,0 +1,345 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/commands/buildgraph/run.ts b/src/commands/buildgraph/run.ts
index 175d91c..d9ed87e 100644
--- a/src/commands/buildgraph/run.ts
+++ b/src/commands/buildgraph/run.ts
@@ -24,7 +24,7 @@ export const run = new Command()
})
const project = await createProject(enginePath, projectPath)
- const { success, code } = await project.runBuildGraph(buildGraphScript, buildGraphArgs)
+ const { success, code } = await project.runCustomBuildGraph(buildGraphScript, buildGraphArgs)
if (!success) {
const logs = await project.engine.getAutomationToolLogs(enginePath)
@@ -36,6 +36,7 @@ export const run = new Command()
await writeMarkdownReport(logs, options.buildgraphReportErrors)
}
- Deno.exit(code)
+ //Deno.exit(code)
+ Deno.exit(1)
}
})
diff --git a/src/commands/project/compile.ts b/src/commands/project/compile.ts
index 2643c57..f31acac 100644
--- a/src/commands/project/compile.ts
+++ b/src/commands/project/compile.ts
@@ -17,6 +17,7 @@ export const compile = new Command()
.option('-c, --configuration ', 'Configuration', {
default: EngineConfiguration.Development,
})
+ .option('--buildgraph', 'Build Graph', { default: false })
.option('--dry-run', 'Dry run', { default: false })
.arguments('')
.action(async (options, target = EngineTarget.Editor) => {
@@ -25,7 +26,7 @@ export const compile = new Command()
const { engine: { path: enginePath }, project: { path: projectPath } } = config.mergeConfigCLIConfig({
cliOptions: options,
})
- const project = await createProject(enginePath, projectPath)
+ const project = await createProject(enginePath, projectPath, options.buildgraph)
await project.compile({
target: target as EngineTarget,
configuration: configuration as EngineConfiguration,
diff --git a/src/commands/project/editor.ts b/src/commands/project/editor.ts
index dc57116..8ac674b 100644
--- a/src/commands/project/editor.ts
+++ b/src/commands/project/editor.ts
@@ -3,6 +3,7 @@ import { Command } from '@cliffy/command'
import { createProject } from '../../lib/project.ts'
import type { GlobalOptions } from '../../lib/types.ts'
import { Config } from '../../lib/config.ts'
+import { EngineConfiguration, EnginePlatform, EngineTarget } from '../../lib/engine.ts'
export const editor = new Command()
.description('Run the editor')
@@ -25,8 +26,12 @@ export const editor = new Command()
console.log(`Running editor with ${editorArguments}`)
if (options.compile) {
- await project.compileAndRunEditor({ extraRunArgs: editorArguments })
- } else {
- await project.runEditor({ extraArgs: editorArguments })
+ await project.compile({
+ target: EngineTarget.Editor,
+ configuration: EngineConfiguration.Development,
+ dryRun: options.dryRun,
+ platform: EnginePlatform.Windows,
+ })
}
+ await project.runEditor({ extraArgs: editorArguments })
})
diff --git a/src/commands/project/pkg.ts b/src/commands/project/pkg.ts
index 46c0e6e..c1ad653 100644
--- a/src/commands/project/pkg.ts
+++ b/src/commands/project/pkg.ts
@@ -3,6 +3,7 @@ import { Engine, EngineConfiguration, EnginePlatform } from '../../lib/engine.ts
import { Config } from '../../lib/config.ts'
import type { GlobalOptions } from '../../lib/types.ts'
import { createProject } from '../../lib/project.ts'
+import { formatIsoTimestamp } from '../../lib/utils.ts'
export type PkgOptions = typeof pkg extends Command ? Options
: never
@@ -18,8 +19,9 @@ export const pkg = new Command()
})
.option('-a, --archive-directory ', 'Path to archive directory')
.option('-z, --zip', 'Should we zip the archive')
- .option('-d, --dry-run', 'Dry run')
- .option('--compile', 'Use the precompiled binaries', { default: false })
+ .option('--buildgraph', 'Build Graph', { default: false })
+ .option('-d, --dry-run', 'Dry run', { default: false })
+ .option('--compile', 'Compile the editor', { default: false })
.option('--profile ', 'Build profile', { default: 'client', required: true })
.stopEarly()
.action(async (options, ...pkgArguments: Array) => {
@@ -29,8 +31,16 @@ export const pkg = new Command()
cliOptions: options,
})
- const args = pkg.getLiteralArgs().concat(pkgArguments)
+ const buildId = `${
+ formatIsoTimestamp(cfg.getConfig().metadata?.ts)
+ }-${cfg.getBuildId()}-${cfg.getConfig().buildkite?.buildNumber}`
- const project = await createProject(enginePath, projectPath)
- project.package({ archiveDirectory: archiveDirectory, profile: profile, extraArgs: args })
+ const project = await createProject(enginePath, projectPath, options.buildgraph)
+ project.package({
+ archiveDirectory: archiveDirectory,
+ profile: profile,
+ buildId: buildId,
+ extraArgs: pkgArguments,
+ dryRun: options.dryRun,
+ })
})
diff --git a/src/commands/project/run.ts b/src/commands/project/run.ts
index 9ebdf95..38fbcb7 100644
--- a/src/commands/project/run.ts
+++ b/src/commands/project/run.ts
@@ -3,6 +3,7 @@ import { Command } from '@cliffy/command'
import { createProject } from '../../lib/project.ts'
import type { GlobalOptions } from '../../lib/types.ts'
import { Config } from '../../lib/config.ts'
+import { EngineConfiguration, EnginePlatform, EngineTarget } from '../../lib/engine.ts'
export const run = new Command()
.description('Run the game')
@@ -19,8 +20,12 @@ export const run = new Command()
const project = await createProject(enginePath, projectPath)
if (options.compile) {
- await project.runEditor({ extraArgs: ['-game', ...runArguments] })
- } else {
- await project.compileAndRunEditor({ extraRunArgs: ['-game', ...runArguments] })
+ await project.compile({
+ target: EngineTarget.Editor,
+ configuration: EngineConfiguration.Development,
+ dryRun: options.dryRun,
+ platform: EnginePlatform.Windows,
+ })
}
+ await project.runEditor({ extraArgs: ['-game', ...runArguments] })
})
diff --git a/src/lib/buildgraph.ts b/src/lib/buildgraph.ts
new file mode 100644
index 0000000..3d347c0
--- /dev/null
+++ b/src/lib/buildgraph.ts
@@ -0,0 +1,122 @@
+export interface BuildGraphArgs {
+ buildId?: string
+ editorTarget?: string
+ gameTargets?: string[] | string
+ licensee?: string
+ versioned?: string
+ promoted?: string
+ archiveStream?: string
+ forceSubmit?: string
+ preferredAgent?: string
+ archiveName?: string
+ symbolStorePath?: string
+ clientPlatforms?: string[] | string
+ serverPlatforms?: string[] | string
+ clientConfigurations?: string[] | string
+ serverConfigurations?: string[] | string
+ clientTargetType?: string
+ outputDir?: string
+ extraCompileArguments?: string[] | string
+ extraCookArguments?: string[] | string
+ extraPackageArguments?: string[] | string
+ additionalTools?: string[] | string
+ dryRun?: boolean
+}
+
+function buildGraphArgToString(arg: string[] | string, separator: string = ';') {
+ if (Array.isArray(arg)) {
+ return `${(arg as string[]).join(separator).replaceAll(' ', '')}`
+ } else {
+ return `${(arg as string)}`
+ }
+}
+
+export function buildCommandLine(buildGraphArgs: BuildGraphArgs): string[] {
+ const outArgs: string[] = []
+
+ if (buildGraphArgs.buildId) {
+ outArgs.push(`-Set:buildId=${buildGraphArgToString(buildGraphArgs.buildId)}`)
+ }
+
+ if (buildGraphArgs.editorTarget) {
+ outArgs.push(`-Set:editorTarget=${buildGraphArgToString(buildGraphArgs.editorTarget)}`)
+ }
+
+ if (buildGraphArgs.gameTargets) {
+ outArgs.push(`-Set:gameTargets=${buildGraphArgToString(buildGraphArgs.gameTargets, ';')}`)
+ }
+
+ if (buildGraphArgs.versioned) {
+ outArgs.push(`-Set:versioned=${buildGraphArgToString(buildGraphArgs.versioned)}`)
+ }
+
+ if (buildGraphArgs.promoted) {
+ outArgs.push(`-Set:promoted=${buildGraphArgToString(buildGraphArgs.promoted)}`)
+ }
+
+ if (buildGraphArgs.archiveStream) {
+ outArgs.push(`-Set:archiveStream=${buildGraphArgToString(buildGraphArgs.archiveStream)}`)
+ }
+
+ if (buildGraphArgs.forceSubmit) {
+ outArgs.push(`-Set:forceSubmit=${buildGraphArgToString(buildGraphArgs.forceSubmit)}`)
+ }
+
+ if (buildGraphArgs.preferredAgent) {
+ outArgs.push(`-Set:preferredAgent=${buildGraphArgToString(buildGraphArgs.preferredAgent)}`)
+ }
+
+ if (buildGraphArgs.archiveName) {
+ outArgs.push(`-Set:archiveName=${buildGraphArgToString(buildGraphArgs.archiveName)}`)
+ }
+
+ if (buildGraphArgs.symbolStorePath) {
+ outArgs.push(`-Set:symbolStorePath=${buildGraphArgToString(buildGraphArgs.symbolStorePath)}`)
+ }
+
+ if (buildGraphArgs.clientPlatforms) {
+ outArgs.push(`-Set:clientPlatforms=${buildGraphArgToString(buildGraphArgs.clientPlatforms)}`)
+ }
+
+ if (buildGraphArgs.serverPlatforms) {
+ outArgs.push(`-Set:serverPlatforms=${buildGraphArgToString(buildGraphArgs.serverPlatforms)}`)
+ }
+
+ if (buildGraphArgs.clientConfigurations) {
+ outArgs.push(`-Set:clientConfigurations=${buildGraphArgToString(buildGraphArgs.clientConfigurations)}`)
+ }
+
+ if (buildGraphArgs.serverConfigurations) {
+ outArgs.push(`-Set:serverConfigurations=${buildGraphArgToString(buildGraphArgs.serverConfigurations)}`)
+ }
+
+ if (buildGraphArgs.clientTargetType) {
+ outArgs.push(`-Set:clientTargetType=${buildGraphArgToString(buildGraphArgs.clientTargetType)}`)
+ }
+
+ if (buildGraphArgs.outputDir) {
+ outArgs.push(`-Set:outputDir=${buildGraphArgToString(buildGraphArgs.outputDir)}`)
+ }
+
+ if (buildGraphArgs.extraCompileArguments) {
+ outArgs.push(`-Set:extraCompileArguments=${buildGraphArgToString(buildGraphArgs.extraCompileArguments)}`)
+ }
+
+ if (buildGraphArgs.extraCookArguments) {
+ outArgs.push(`-Set:extraCookArguments=${buildGraphArgToString(buildGraphArgs.extraCookArguments)}`)
+ }
+
+ if (buildGraphArgs.extraPackageArguments) {
+ outArgs.push(`-Set:extraPackageArguments=${buildGraphArgToString(buildGraphArgs.extraPackageArguments)}`)
+ }
+
+ if (buildGraphArgs.additionalTools) {
+ outArgs.push(`-Set:additionalTools=${buildGraphArgToString(buildGraphArgs.additionalTools)}`)
+ }
+
+ if (buildGraphArgs.dryRun) {
+ outArgs.push('-ListOnly')
+ }
+
+ return outArgs
+}
diff --git a/src/lib/engine.ts b/src/lib/engine.ts
index 1741b1a..f0604d8 100644
--- a/src/lib/engine.ts
+++ b/src/lib/engine.ts
@@ -163,7 +163,7 @@ export abstract class Engine {
const buildScript = this.getBuildScript()
const args = [target, configuration, platform, ...extraArgs]
console.log('[runUBT]', args)
- if (dryRun) return
+ if (dryRun) return { success: true, code: 0, signal: null, output: '' }
return await exec(buildScript, args)
}
diff --git a/src/lib/project.ts b/src/lib/project.ts
index 5c28ff1..95ccc10 100644
--- a/src/lib/project.ts
+++ b/src/lib/project.ts
@@ -4,6 +4,8 @@ import { globber } from 'globber'
import { ValidationError } from '@cliffy/command'
import { logger } from '../lib/logger.ts'
+import { buildCommandLine, BuildGraphArgs } from '../lib/buildgraph.ts'
+
import {
createEngine,
Engine,
@@ -77,15 +79,121 @@ interface ProjectFileVars {
projectDir: string
}
-export class Project {
+export abstract class Project {
public readonly engine: Engine
public readonly projectFileVars: ProjectFileVars
+ abstract compile({
+ target,
+ configuration,
+ extraArgs,
+ dryRun,
+ platform,
+ }: {
+ target?: EngineTarget
+ configuration?: EngineConfiguration
+ platform?: EnginePlatform
+ extraArgs?: string[]
+ dryRun?: boolean
+ }): Promise<{ success: boolean; code: number; signal: Deno.Signal | null; output: string }>
+
+ abstract package({
+ buildId,
+ configuration,
+ extraArgs,
+ dryRun,
+ platform,
+ zip,
+ profile,
+ archiveDirectory,
+ }: {
+ buildId: string
+ archiveDirectory: string
+ profile: string
+ zip?: boolean
+ configuration?: EngineConfiguration
+ platform?: EnginePlatform
+ extraArgs?: string[]
+ dryRun?: boolean
+ }): Promise<{ success: boolean; code: number; signal: Deno.Signal | null; output: string }>
+
+ abstract runEditor({
+ extraArgs,
+ }: {
+ extraArgs?: string[]
+ }): Promise<{ success: boolean; code: number; signal: Deno.Signal | null; output: string }>
+
+ abstract cookContent({
+ extraArgs,
+ }: {
+ extraArgs?: string[]
+ }): Promise<{ success: boolean; code: number; signal: Deno.Signal | null; output: string }>
+
+ abstract runClean(dryRun?: boolean): Promise
+
constructor(enginePath: Engine, projectFileVars: ProjectFileVars) {
this.engine = enginePath
this.projectFileVars = projectFileVars
}
+ async parseProjectTargets(): Promise {
+ const args = ['-Mode=QueryTargets', this.projectFileVars.projectArgument]
+ await this.engine.ubt(args, { quiet: true })
+ try {
+ const targetInfoJson = path.resolve(path.join(this.projectFileVars.projectDir, 'Intermediate', 'TargetInfo.json'))
+ const { Targets } = JSON.parse(Deno.readTextFileSync(targetInfoJson))
+ const targets = Targets.map((target: TargetInfo) => target.Name)
+ return targets
+ } catch (e) {
+ return []
+ }
+ }
+
+ async checkTarget(target: string) {
+ const validTargets = await this.parseProjectTargets()
+ if (!validTargets.includes(target)) {
+ throw TargetError(target, validTargets)
+ }
+ }
+
+ async genProjectFiles(args: string[]) {
+ // Generate project
+ // GenerateProjectFiles.bat -project=E:\Project\TestProject.uproject -game -engine
+ return await exec(this.engine.getGenerateScript(), [
+ this.projectFileVars.projectArgument,
+ ...args,
+ ])
+ }
+
+ async runPython(scriptPath: string, extraArgs: Array) {
+ const args = [
+ '-run=pythonscript',
+ `-script=${scriptPath}`,
+ ...extraArgs,
+ ]
+ logger.info(`Running Python script: ${scriptPath}`)
+ return await this.runEditor({ extraArgs: args })
+ }
+
+ async runCustomBuildGraph(buildGraphScript: string, args: string[] = []) {
+ let bgScriptPath = path.resolve(buildGraphScript)
+ if (!bgScriptPath.endsWith('.xml')) {
+ throw new Error('Invalid buildgraph script')
+ }
+ if (path.relative(this.engine.enginePath, bgScriptPath).startsWith('..')) {
+ console.log('Buildgraph script is outside of engine folder, copying...')
+ bgScriptPath = await copyBuildGraphScripts(this.engine.enginePath, bgScriptPath)
+ }
+ const uatArgs = [
+ 'BuildGraph',
+ `-Script=${bgScriptPath}`,
+ ...args,
+ ]
+ return this.engine.runUAT(uatArgs)
+ }
+}
+
+export class ManualProject extends Project {
async compile({
target = EngineTarget.Editor,
configuration = EngineConfiguration.Development,
@@ -112,7 +220,7 @@ export class Project {
const projectTarget = `${this.projectFileVars.projectName}${target}`
await this.checkTarget(projectTarget)
- await this.engine.runUBT({
+ return await this.engine.runUBT({
target: projectTarget,
configuration: configuration,
platform: platform,
@@ -127,9 +235,11 @@ export class Project {
dryRun = false,
platform = this.engine.getPlatformName(),
zip = false,
+ buildId,
profile,
archiveDirectory,
}: {
+ buildId: string
archiveDirectory: string
profile: string
zip?: boolean
@@ -161,10 +271,14 @@ export class Project {
console.log(`[package] package ${profile} ${configuration} ${platform}`)
console.log('[package] BCR args:')
console.log(bcrArgs)
- return
+ return { success: true, code: 0, signal: null, output: '' }
}
- await this.engine.runUAT(['BuildCookRun', ...bcrArgs])
+ const result = await this.engine.runUAT(['BuildCookRun', ...bcrArgs])
+
+ if (!result.success) {
+ return result
+ }
if (zip) {
// Reverse the EnginePlatform enum to get the build output platform name, ie Win64 => Windows
@@ -180,21 +294,12 @@ export class Project {
`-archive=${archivePath}.zip`,
'-compression=5',
]
- await this.engine.runUAT(['ZipUtils', ...zipArgs])
+ return await this.engine.runUAT(['ZipUtils', ...zipArgs])
+ } else {
+ return result
}
}
- async compileAndRunEditor({
- extraCompileArgs = [],
- extraRunArgs = [],
- }: {
- extraCompileArgs?: string[]
- extraRunArgs?: string[]
- }) {
- await this.compile({ extraArgs: extraCompileArgs })
- await this.runEditor({ extraArgs: extraRunArgs })
- }
-
async runEditor({
extraArgs = [],
}: {
@@ -207,8 +312,7 @@ export class Project {
console.log(`Running editor with: ${this.engine.getEditorBin} ${args.join(' ')}`)
try {
- const result = await exec(this.engine.getEditorBin(), args)
- return result
+ return await exec(this.engine.getEditorBin(), args)
} catch (error: unknown) {
console.log(`Error running Editor: ${error instanceof Error ? error.message : String(error)}`)
Deno.exit(1)
@@ -231,43 +335,13 @@ export class Project {
console.log(`Running editor with: ${this.engine.getEditorCmdBin} ${args.join(' ')}`)
try {
- const result = await exec(this.engine.getEditorCmdBin(), args)
- return result
+ return await exec(this.engine.getEditorCmdBin(), args)
} catch (error: unknown) {
console.log(`Error running Editor: ${error instanceof Error ? error.message : String(error)}`)
Deno.exit(1)
}
}
- async parseProjectTargets(): Promise {
- const args = ['-Mode=QueryTargets', this.projectFileVars.projectArgument]
- await this.engine.ubt(args, { quiet: true })
- try {
- const targetInfoJson = path.resolve(path.join(this.projectFileVars.projectDir, 'Intermediate', 'TargetInfo.json'))
- const { Targets } = JSON.parse(Deno.readTextFileSync(targetInfoJson))
- const targets = Targets.map((target: TargetInfo) => target.Name)
- return targets
- } catch (e) {
- return []
- }
- }
-
- async checkTarget(target: string) {
- const validTargets = await this.parseProjectTargets()
- if (!validTargets.includes(target)) {
- throw TargetError(target, validTargets)
- }
- }
-
- async genProjectFiles(args: string[]) {
- // Generate project
- // GenerateProjectFiles.bat -project=E:\Project\TestProject.uproject -game -engine
- await exec(this.engine.getGenerateScript(), [
- this.projectFileVars.projectArgument,
- ...args,
- ])
- }
-
async runClean(dryRun?: boolean) {
const cwd = this.projectFileVars.projectDir
@@ -286,18 +360,10 @@ export class Project {
}
}
}
+}
- async runPython(scriptPath: string, extraArgs: Array) {
- const args = [
- '-run=pythonscript',
- `-script=${scriptPath}`,
- ...extraArgs,
- ]
- logger.info(`Running Python script: ${scriptPath}`)
- await this.runEditor({ extraArgs: args })
- }
-
- async runBuildGraph(buildGraphScript: string, args: string[] = []) {
+export class BuildGraphProject extends Project {
+ async runBuildGraph(buildGraphScript: string, buildGraphNode: string, buildGraphArgs: BuildGraphArgs) {
let bgScriptPath = path.resolve(buildGraphScript)
if (!bgScriptPath.endsWith('.xml')) {
throw new Error('Invalid buildgraph script')
@@ -306,16 +372,195 @@ export class Project {
console.log('Buildgraph script is outside of engine folder, copying...')
bgScriptPath = await copyBuildGraphScripts(this.engine.enginePath, bgScriptPath)
}
+
+ const args = buildCommandLine(buildGraphArgs)
+
+ console.log(args)
+
const uatArgs = [
- 'BuildGraph',
- `-Script=${bgScriptPath}`,
+ `-Target=${buildGraphNode}`,
+ this.projectFileVars.projectArgument,
...args,
]
- return await this.engine.runUAT(uatArgs)
+ return await this.runCustomBuildGraph(bgScriptPath, uatArgs)
+ }
+
+ async compile({
+ target = EngineTarget.Editor,
+ configuration = EngineConfiguration.Development,
+ extraArgs = [],
+ dryRun = false,
+ platform = this.engine.getPlatformName(),
+ }: {
+ target?: EngineTarget
+ configuration?: EngineConfiguration
+ platform?: EnginePlatform
+ extraArgs?: string[]
+ dryRun?: boolean
+ }) {
+ console.log('using build graph')
+
+ const args = [
+ '-NoUBTMakefiles',
+ '-NoXGE',
+ '-NoHotReload',
+ '-NoCodeSign',
+ '-NoP4',
+ '-TraceWrites',
+ ].concat(extraArgs)
+
+ const projectTarget = `${this.projectFileVars.projectName}${target}`
+
+ await this.checkTarget(projectTarget)
+
+ const targetName = `${this.projectFileVars.projectName}${target}`
+
+ const bgArgs: BuildGraphArgs = {
+ clientPlatforms: `${platform}`,
+ clientConfigurations: `${configuration}`,
+ dryRun: dryRun,
+ }
+
+ if (extraArgs.length > 0) {
+ bgArgs.extraCompileArguments = extraArgs
+ }
+
+ return await this.runBuildGraph(
+ path.join(this.projectFileVars.projectDir, '..', 'buildgraph', 'CoreBuildGraph.xml'),
+ `Compile ${targetName} ${platform} ${configuration}`,
+ bgArgs,
+ )
+ }
+
+ async package({
+ configuration = EngineConfiguration.Development,
+ extraArgs = [],
+ dryRun = false,
+ platform = this.engine.getPlatformName(),
+ zip = false,
+ buildId,
+ profile,
+ archiveDirectory,
+ }: {
+ buildId: string
+ archiveDirectory: string
+ profile: string
+ zip?: boolean
+ configuration?: EngineConfiguration
+ platform?: EnginePlatform
+ extraArgs?: string[]
+ dryRun?: boolean
+ }) {
+ const args = [
+ '-NoP4',
+ '-NoCodeSign',
+ '-stdout',
+ '-utf8output',
+ '-unattended',
+ '-nosplash',
+ ].concat(extraArgs)
+
+ const bgArgs: BuildGraphArgs = {
+ outputDir: archiveDirectory,
+ buildId: buildId,
+ extraPackageArguments: args,
+ dryRun: dryRun,
+ }
+
+ let target = ''
+ if (profile == 'client' || profile == 'game') {
+ target = 'Package Clients'
+ bgArgs.clientPlatforms = platform
+ bgArgs.clientConfigurations = configuration
+
+ if (profile == 'client') {
+ bgArgs.clientTargetType = 'Client'
+ } else {
+ bgArgs.clientTargetType = 'Game'
+ }
+ } else if (profile == 'server') {
+ target = 'Package Servers'
+ bgArgs.serverPlatforms = platform
+ bgArgs.serverConfigurations = configuration
+ }
+
+ if (extraArgs) {
+ bgArgs.extraPackageArguments = ''
+ }
+ return await this.runBuildGraph(
+ path.join(this.projectFileVars.projectDir, '..', 'buildgraph', 'CoreBuildGraph.xml'),
+ `${target}`,
+ bgArgs,
+ )
+ }
+
+ async runEditor({
+ extraArgs = [],
+ }: {
+ extraArgs?: string[]
+ }) {
+ const args = [
+ this.projectFileVars.projectFullPath,
+ ].concat(extraArgs)
+
+ console.log(`Running editor with: ${this.engine.getEditorBin} ${args.join(' ')}`)
+
+ try {
+ return await exec(this.engine.getEditorBin(), args)
+ } catch (error: unknown) {
+ console.log(`Error running Editor: ${error instanceof Error ? error.message : String(error)}`)
+ Deno.exit(1)
+ }
+ }
+
+ async cookContent({
+ extraArgs = [],
+ }: {
+ extraArgs?: string[]
+ }) {
+ const platformTarget = getPlatformCookTarget(this.engine.getPlatformName())
+ const args = [
+ this.projectFileVars.projectFullPath,
+ '-run=Cook',
+ `-targetplatform=${platformTarget}`,
+ '-fileopenlog',
+ ].concat(extraArgs)
+
+ console.log(`Running editor with: ${this.engine.getEditorCmdBin} ${args.join(' ')}`)
+
+ try {
+ return await exec(this.engine.getEditorCmdBin(), args)
+ } catch (error: unknown) {
+ console.log(`Error running Editor: ${error instanceof Error ? error.message : String(error)}`)
+ Deno.exit(1)
+ }
+ }
+
+ async runClean(dryRun?: boolean) {
+ const cwd = this.projectFileVars.projectDir
+
+ const iterator = globber({
+ cwd,
+ include: ['**/Binaries/**', '**/Intermediate/**'],
+ })
+ for await (const file of iterator) {
+ if (dryRun) {
+ console.log('Would delete:', file.absolute)
+ continue
+ }
+ if (file.isFile) {
+ console.log('Deleting:', file.absolute)
+ await Deno.remove(file.absolute)
+ }
+ }
}
}
-export async function createProject(enginePath: string, projectPath: string): Promise {
+export async function createProject(
+ enginePath: string,
+ projectPath: string,
+ useBuildGraph: boolean = false,
+): Promise {
const projectFile = await findProjectFile(projectPath).catch(() => null)
if (projectFile == null) {
@@ -332,7 +577,14 @@ export async function createProject(enginePath: string, projectPath: string): Pr
console.log(
`projectFullPath=${projectFileVars.projectFullPath} projectName=${projectFileVars.projectName} projectArgument=${projectFileVars.projectArgument} projectDir=${projectFileVars.projectDir}`,
)
- const project = new Project(createEngine(enginePath), projectFileVars)
+
+ let project = null
+
+ if (useBuildGraph) {
+ project = new BuildGraphProject(createEngine(enginePath), projectFileVars)
+ } else {
+ project = new ManualProject(createEngine(enginePath), projectFileVars)
+ }
return Promise.resolve(project)
}