1import * as rust from './rust'; 2import path from 'path'; 3import Crate from './crate'; 4import BuildSettings from './build-settings'; 5import { rimraf } from './async/rimraf'; 6 7const LIB_PREFIX: Record<string, string> = { 8 'darwin': "lib", 9 'freebsd': "lib", 10 'linux': "lib", 11 'sunos': "lib", 12 'win32': "" 13}; 14 15const LIB_SUFFIX: Record<string, string> = { 16 'darwin': ".dylib", 17 'freebsd': ".so", 18 'linux': ".so", 19 'sunos': ".so", 20 'win32': ".dll" 21}; 22 23export type TargetOptions = { 24 release?: boolean, 25 arch?: string 26}; 27 28/** The Rust build artifacts for a single build target of a Neon crate. */ 29export default class Target { 30 readonly crate: Crate; 31 readonly release: boolean; 32 readonly arch: string; 33 readonly triple: string; 34 readonly subdirectory: string; 35 readonly root: string; 36 readonly dylib: string; 37 38 constructor(crate: Crate, options: TargetOptions = {}) { 39 let { release = true, arch = process.env.npm_config_arch || process.arch } = options; 40 this.crate = crate; 41 this.release = release; 42 this.arch = arch; 43 44 if (process.platform === 'win32') { 45 this.triple = (arch === 'ia32') ? 'i686-pc-windows-msvc' : 'x86_64-pc-windows-msvc'; 46 } else { 47 this.triple = ''; 48 } 49 50 if (process.env.CARGO_BUILD_TARGET) { 51 this.triple = process.env.CARGO_BUILD_TARGET; 52 } 53 54 this.subdirectory = path.join(this.triple, release ? 'release' : 'debug'); 55 this.root = path.resolve(crate.project.targetDirectory, this.subdirectory); 56 57 let prefix = LIB_PREFIX[process.platform]; 58 let suffix = LIB_SUFFIX[process.platform]; 59 this.dylib = path.resolve(this.root, prefix + crate.name + suffix); 60 } 61 62 async clean() { 63 // Remove the directory associated with this target. 64 const absolutePathSubdir = path.resolve(this.crate.root, 'target', this.subdirectory); 65 await rimraf(absolutePathSubdir); 66 67 // If this target was the active target, remove the addon. 68 if (this.crate.artifacts.haveActivated(this.subdirectory)) { 69 await this.crate.removeAddon(); 70 } 71 72 // Update the build state. 73 this.crate.artifacts.delete(this.subdirectory); 74 this.crate.saveArtifacts(); 75 } 76 77 async build(toolchain: rust.Toolchain, 78 settings: BuildSettings, 79 additionalArgs: string[]) 80 { 81 let releaseFlags = this.release ? ["--release"] : []; 82 let targetFlags = this.triple ? ["--target=" + this.triple] : []; 83 84 let args = ['build'].concat(releaseFlags, targetFlags, additionalArgs); 85 86 try { 87 let result = await rust.spawn("cargo", args, toolchain, { 88 cwd: this.crate.root, 89 stdio: 'inherit' 90 }); 91 92 if (result !== 0) { 93 throw new Error("cargo build failed"); 94 } 95 96 this.crate.artifacts.activate(this.subdirectory, settings); 97 98 return result; 99 } finally { 100 this.crate.saveArtifacts(); 101 } 102 } 103 104 inState(settings: BuildSettings) { 105 let savedSettings = this.crate.artifacts.lookup(this.subdirectory); 106 return savedSettings && savedSettings.match(settings); 107 } 108 109}; 110