fix(cli): always generate typedef file even native code never changes (#1489)

This commit is contained in:
liuyi 2023-02-16 22:24:40 +08:00 committed by GitHub
parent 853f52ed1f
commit 7281f533bd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 64 additions and 28 deletions

View file

@ -1,4 +1,5 @@
import { execSync } from 'child_process' import { execSync } from 'child_process'
import { createHash } from 'crypto'
import { existsSync, mkdirSync } from 'fs' import { existsSync, mkdirSync } from 'fs'
import { tmpdir } from 'os' import { tmpdir } from 'os'
import { join, parse, sep } from 'path' import { join, parse, sep } from 'path'
@ -289,7 +290,6 @@ export class BuildCommand extends Command {
additionalEnv['XWIN_ARCH'] = 'x86' additionalEnv['XWIN_ARCH'] = 'x86'
} }
const cargoCommand = `${cargo} build ${externalFlags}` const cargoCommand = `${cargo} build ${externalFlags}`
const intermediateTypeFile = join(tmpdir(), `type_def.${Date.now()}.tmp`)
debug(`Run ${chalk.green(cargoCommand)}`) debug(`Run ${chalk.green(cargoCommand)}`)
const rustflags = process.env.RUSTFLAGS const rustflags = process.env.RUSTFLAGS
@ -439,32 +439,7 @@ export class BuildCommand extends Command {
PATH: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin:${process.env.PATH}`, PATH: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin:${process.env.PATH}`,
}) })
} }
try {
execSync(cargoCommand, {
env: {
...process.env,
...additionalEnv,
TYPE_DEF_TMP_PATH: intermediateTypeFile,
},
stdio: 'inherit',
cwd,
})
} catch (e) {
if (cargo === 'cargo-xwin') {
console.warn(
`You are cross compiling ${chalk.underline(
triple.raw,
)} target on ${chalk.green(process.platform)} host`,
)
} else if (isCrossForLinux || isCrossForMacOS) {
console.warn(
`You are cross compiling ${chalk.underline(
triple.raw,
)} on ${chalk.green(process.platform)} host`,
)
}
throw e
}
const { binaryName, packageName } = getNapiConfig(this.configFileName) const { binaryName, packageName } = getNapiConfig(this.configFileName)
let cargoArtifactName = this.cargoName let cargoArtifactName = this.cargoName
if (!cargoArtifactName) { if (!cargoArtifactName) {
@ -494,6 +469,42 @@ export class BuildCommand extends Command {
debug(`Dylib name: ${chalk.greenBright(cargoArtifactName)}`) debug(`Dylib name: ${chalk.greenBright(cargoArtifactName)}`)
} }
const intermediateTypeFile = join(
tmpdir(),
`${cargoArtifactName}-${createHash('sha256')
.update(process.cwd())
.digest('hex')
.substring(0, 8)}.napi_type_def.tmp`,
)
debug(`intermediate type def file: ${intermediateTypeFile}`)
try {
execSync(cargoCommand, {
env: {
...process.env,
...additionalEnv,
TYPE_DEF_TMP_PATH: intermediateTypeFile,
},
stdio: 'inherit',
cwd,
})
} catch (e) {
if (cargo === 'cargo-xwin') {
console.warn(
`You are cross compiling ${chalk.underline(
triple.raw,
)} target on ${chalk.green(process.platform)} host`,
)
} else if (isCrossForLinux || isCrossForMacOS) {
console.warn(
`You are cross compiling ${chalk.underline(
triple.raw,
)} on ${chalk.green(process.platform)} host`,
)
}
throw e
}
const platform = triple.platform const platform = triple.platform
let libExt = '' let libExt = ''
@ -787,7 +798,6 @@ async function processIntermediateTypeFile(
}\n` }\n`
: '' : ''
await unlinkAsync(source)
await writeFileAsync( await writeFileAsync(
target, target,
dtsHeader + externalDef + topLevelDef + namespaceDefs, dtsHeader + externalDef + topLevelDef + namespaceDefs,

View file

@ -11,6 +11,7 @@ extern crate quote;
#[cfg(not(feature = "noop"))] #[cfg(not(feature = "noop"))]
use std::env; use std::env;
use std::sync::atomic::{AtomicBool, Ordering};
#[cfg(all(feature = "type-def", not(feature = "noop")))] #[cfg(all(feature = "type-def", not(feature = "noop")))]
use std::{ use std::{
fs, fs,
@ -35,6 +36,17 @@ use syn::Item;
#[cfg(feature = "compat-mode")] #[cfg(feature = "compat-mode")]
use syn::{fold::Fold, parse_macro_input, ItemFn}; use syn::{fold::Fold, parse_macro_input, ItemFn};
/// a flag indicate whether or never at least one `napi` macro has been expanded.
/// ```ignore
/// if BUILT_FLAG
/// .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
/// .is_ok() {
/// // logic on first macro expansion
/// }
///
/// ```
static BUILT_FLAG: AtomicBool = AtomicBool::new(false);
/// ```ignore /// ```ignore
/// #[napi] /// #[napi]
/// fn test(ctx: CallContext, name: String) { /// fn test(ctx: CallContext, name: String) {
@ -44,6 +56,20 @@ use syn::{fold::Fold, parse_macro_input, ItemFn};
#[cfg(not(feature = "noop"))] #[cfg(not(feature = "noop"))]
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn napi(attr: RawStream, input: RawStream) -> RawStream { pub fn napi(attr: RawStream, input: RawStream) -> RawStream {
if BUILT_FLAG
.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
.is_ok()
{
// logic on first macro expansion
#[cfg(feature = "type-def")]
if let Ok(type_def_file) = env::var("TYPE_DEF_TMP_PATH") {
if let Err(_e) = fs::remove_file(type_def_file) {
// should only input in debug mode
// println!("Failed to manipulate type def file: {:?}", e);
}
}
}
match expand(attr.into(), input.into()) { match expand(attr.into(), input.into()) {
Ok(tokens) => { Ok(tokens) => {
if env::var("DEBUG_GENERATED_CODE").is_ok() { if env::var("DEBUG_GENERATED_CODE").is_ok() {