mirror of
https://github.com/napi-rs/napi-rs.git
synced 2025-12-08 19:56:07 +00:00
fix: revalidate shared libs if type def not found (#2689)
This commit is contained in:
parent
a6f133cf7f
commit
5a17b88636
@ -32,6 +32,7 @@ import {
|
||||
writeFileAsync,
|
||||
dirExistsAsync,
|
||||
readdirAsync,
|
||||
CargoWorkspaceMetadata,
|
||||
} from '../utils/index.js'
|
||||
|
||||
import { createCjsBinding, createEsmBinding } from './templates/index.js'
|
||||
@ -51,20 +52,23 @@ type OutputKind = 'js' | 'dts' | 'node' | 'exe' | 'wasm'
|
||||
type Output = { kind: OutputKind; path: string }
|
||||
|
||||
type BuildOptions = RawBuildOptions & { cargoOptions?: string[] }
|
||||
type ParsedBuildOptions = Omit<BuildOptions, 'cwd'> & { cwd: string }
|
||||
|
||||
export async function buildProject(options: BuildOptions) {
|
||||
debug('napi build command receive options: %O', options)
|
||||
export async function buildProject(rawOptions: BuildOptions) {
|
||||
debug('napi build command receive options: %O', rawOptions)
|
||||
|
||||
options = { dtsCache: true, ...options }
|
||||
const options: ParsedBuildOptions = {
|
||||
dtsCache: true,
|
||||
...rawOptions,
|
||||
cwd: rawOptions.cwd ?? process.cwd(),
|
||||
}
|
||||
|
||||
const cwd = options.cwd ?? process.cwd()
|
||||
|
||||
const resolvePath = (...paths: string[]) => resolve(cwd, ...paths)
|
||||
const resolvePath = (...paths: string[]) => resolve(options.cwd, ...paths)
|
||||
|
||||
const manifestPath = resolvePath(options.manifestPath ?? 'Cargo.toml')
|
||||
const metadata = await parseMetadata(manifestPath)
|
||||
|
||||
const pkg = metadata.packages.find((p) => {
|
||||
const crate = metadata.packages.find((p) => {
|
||||
// package with given name
|
||||
if (options.package) {
|
||||
return p.name === options.package
|
||||
@ -73,36 +77,20 @@ export async function buildProject(options: BuildOptions) {
|
||||
}
|
||||
})
|
||||
|
||||
if (!pkg) {
|
||||
if (!crate) {
|
||||
throw new Error(
|
||||
'Unable to find crate to build. It seems you are trying to build a crate in a workspace, try using `--package` option to specify the package to build.',
|
||||
)
|
||||
}
|
||||
|
||||
const crateDir = parse(pkg.manifest_path).dir
|
||||
|
||||
const builder = new Builder(
|
||||
options,
|
||||
pkg,
|
||||
cwd,
|
||||
options.target
|
||||
? parseTriple(options.target)
|
||||
: process.env.CARGO_BUILD_TARGET
|
||||
? parseTriple(process.env.CARGO_BUILD_TARGET)
|
||||
: getSystemDefaultTarget(),
|
||||
crateDir,
|
||||
resolvePath(options.outputDir ?? crateDir),
|
||||
options.targetDir ??
|
||||
process.env.CARGO_BUILD_TARGET_DIR ??
|
||||
metadata.target_directory,
|
||||
await readNapiConfig(
|
||||
resolvePath(
|
||||
options.configPath ?? options.packageJsonPath ?? 'package.json',
|
||||
),
|
||||
options.configPath ? resolvePath(options.configPath) : undefined,
|
||||
const config = await readNapiConfig(
|
||||
resolvePath(
|
||||
options.configPath ?? options.packageJsonPath ?? 'package.json',
|
||||
),
|
||||
options.configPath ? resolvePath(options.configPath) : undefined,
|
||||
)
|
||||
|
||||
const builder = new Builder(metadata, crate, config, options)
|
||||
|
||||
return builder.build()
|
||||
}
|
||||
|
||||
@ -111,16 +99,32 @@ class Builder {
|
||||
private readonly envs: Record<string, string> = {}
|
||||
private readonly outputs: Output[] = []
|
||||
|
||||
private readonly target: Target
|
||||
private readonly crateDir: string
|
||||
private readonly outputDir: string
|
||||
private readonly targetDir: string
|
||||
|
||||
constructor(
|
||||
private readonly options: BuildOptions,
|
||||
private readonly metadata: CargoWorkspaceMetadata,
|
||||
private readonly crate: Crate,
|
||||
private readonly cwd: string,
|
||||
private readonly target: Target,
|
||||
private readonly crateDir: string,
|
||||
private readonly outputDir: string,
|
||||
private readonly targetDir: string,
|
||||
private readonly config: NapiConfig,
|
||||
) {}
|
||||
private readonly options: ParsedBuildOptions,
|
||||
) {
|
||||
this.target = options.target
|
||||
? parseTriple(options.target)
|
||||
: process.env.CARGO_BUILD_TARGET
|
||||
? parseTriple(process.env.CARGO_BUILD_TARGET)
|
||||
: getSystemDefaultTarget()
|
||||
this.crateDir = parse(crate.manifest_path).dir
|
||||
this.outputDir = resolve(
|
||||
this.options.cwd,
|
||||
options.outputDir ?? this.crateDir,
|
||||
)
|
||||
this.targetDir =
|
||||
options.targetDir ??
|
||||
process.env.CARGO_BUILD_TARGET_DIR ??
|
||||
metadata.target_directory
|
||||
}
|
||||
|
||||
get cdyLibName() {
|
||||
return this.crate.targets.find((t) => t.crate_types.includes('cdylib'))
|
||||
@ -303,7 +307,7 @@ class Builder {
|
||||
const buildProcess = spawn(command, this.args, {
|
||||
env: { ...process.env, ...this.envs },
|
||||
stdio: watch ? ['inherit', 'inherit', 'pipe'] : 'inherit',
|
||||
cwd: this.cwd,
|
||||
cwd: this.options.cwd,
|
||||
signal: controller.signal,
|
||||
})
|
||||
|
||||
@ -449,7 +453,9 @@ class Builder {
|
||||
|
||||
private setEnvs() {
|
||||
// folder for intermediate type definition files
|
||||
this.envs.TYPE_DEF_TMP_FOLDER = this.generateIntermediateTypeDefFolder()
|
||||
this.envs.NAPI_TYPE_DEF_TMP_FOLDER =
|
||||
this.generateIntermediateTypeDefFolder()
|
||||
this.setForceBuildEnvs(this.envs.NAPI_TYPE_DEF_TMP_FOLDER)
|
||||
|
||||
// RUSTFLAGS
|
||||
let rustflags =
|
||||
@ -577,6 +583,20 @@ class Builder {
|
||||
return this
|
||||
}
|
||||
|
||||
private setForceBuildEnvs(typeDefTmpFolder: string) {
|
||||
// dynamically check all napi-rs deps and set `NAPI_FORCE_BUILD_{uppercase(snake_case(name))} = timestamp`
|
||||
this.metadata.packages.forEach((crate) => {
|
||||
if (
|
||||
crate.dependencies.some((d) => d.name === 'napi-derive') &&
|
||||
!existsSync(join(typeDefTmpFolder, crate.name))
|
||||
) {
|
||||
this.envs[
|
||||
`NAPI_FORCE_BUILD_${crate.name.replace(/-/g, '_').toUpperCase()}`
|
||||
] = Date.now().toString()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private setFeatures() {
|
||||
const args = []
|
||||
if (this.options.allFeatures && this.options.noDefaultFeatures) {
|
||||
@ -793,7 +813,7 @@ class Builder {
|
||||
}
|
||||
|
||||
private async generateTypeDef() {
|
||||
const typeDefDir = this.envs.TYPE_DEF_TMP_FOLDER
|
||||
const typeDefDir = this.envs.NAPI_TYPE_DEF_TMP_FOLDER
|
||||
if (!(await dirExistsAsync(typeDefDir))) {
|
||||
return []
|
||||
}
|
||||
@ -810,7 +830,7 @@ class Builder {
|
||||
if (this.config.dtsHeaderFile) {
|
||||
try {
|
||||
header = await readFileAsync(
|
||||
join(this.cwd, this.config.dtsHeaderFile),
|
||||
join(this.options.cwd, this.config.dtsHeaderFile),
|
||||
'utf-8',
|
||||
)
|
||||
} catch (e) {
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
collections::HashMap,
|
||||
env,
|
||||
fmt::{self, Display, Formatter},
|
||||
sync::LazyLock,
|
||||
};
|
||||
@ -14,11 +13,6 @@ mod r#type;
|
||||
|
||||
use syn::{PathSegment, Type, TypePath, TypeSlice};
|
||||
|
||||
pub static NAPI_RS_CLI_VERSION: LazyLock<semver::Version> = LazyLock::new(|| {
|
||||
let version = env::var("CARGO_CFG_NAPI_RS_CLI_VERSION").unwrap_or_else(|_| "0.0.0".to_string());
|
||||
semver::Version::parse(&version).unwrap_or_else(|_| semver::Version::new(0, 0, 0))
|
||||
});
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct TypeDef {
|
||||
pub kind: String,
|
||||
|
||||
@ -6,14 +6,14 @@ mod wasi;
|
||||
mod windows;
|
||||
|
||||
pub fn setup() {
|
||||
let package_name = env::var("CARGO_PKG_NAME").expect("CARGO_PKG_NAME is not set");
|
||||
|
||||
println!("cargo:rerun-if-env-changed=DEBUG_GENERATED_CODE");
|
||||
println!("cargo:rerun-if-env-changed=TYPE_DEF_TMP_PATH");
|
||||
println!("cargo:rerun-if-env-changed=CARGO_CFG_NAPI_RS_CLI_VERSION");
|
||||
println!("cargo::rerun-if-env-changed=NAPI_DEBUG_GENERATED_CODE");
|
||||
println!("cargo::rerun-if-env-changed=NAPI_TYPE_DEF_TMP_FOLDER");
|
||||
println!(
|
||||
"cargo:rerun-if-env-changed=NAPI_PACKAGE_{}_INVALID",
|
||||
package_name.to_uppercase().replace("-", "_")
|
||||
"cargo::rerun-if-env-changed=NAPI_FORCE_BUILD_{}",
|
||||
env::var("CARGO_PKG_NAME")
|
||||
.expect("CARGO_PKG_NAME is not set")
|
||||
.to_uppercase()
|
||||
.replace("-", "_")
|
||||
);
|
||||
|
||||
match env::var("CARGO_CFG_TARGET_OS").as_deref() {
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
use std::env;
|
||||
use std::env::VarError;
|
||||
use std::fs;
|
||||
use std::io::{BufWriter, Write};
|
||||
use std::path::PathBuf;
|
||||
@ -9,16 +8,17 @@ use napi_derive_backend::{Napi, ToTypeDef};
|
||||
|
||||
static PKG_NAME: LazyLock<String> =
|
||||
LazyLock::new(|| env::var("CARGO_PKG_NAME").expect("Expected `CARGO_PKG_NAME` to be set"));
|
||||
static TYPE_DEF_FOLDER: LazyLock<Result<String, VarError>> =
|
||||
LazyLock::new(|| env::var("TYPE_DEF_TMP_FOLDER"));
|
||||
static TYPE_DEF_FOLDER: LazyLock<Option<String>> =
|
||||
LazyLock::new(|| env::var("NAPI_TYPE_DEF_TMP_FOLDER").ok());
|
||||
|
||||
fn get_type_def_file() -> Option<PathBuf> {
|
||||
if let Ok(folder) = TYPE_DEF_FOLDER.as_ref() {
|
||||
if let Some(folder) = TYPE_DEF_FOLDER.as_ref() {
|
||||
let file = PathBuf::from(folder).join(&*PKG_NAME);
|
||||
Some(file)
|
||||
} else {
|
||||
// the environment variable set by old `@napi-rs/cli`
|
||||
if env::var("TYPE_DEF_TMP_PATH").is_ok() {
|
||||
panic!("Expected `TYPE_DEF_TMP_FOLDER` to be set. It may caused by an older version of '@napi-rs/cli' used. Please upgrade to the latest version.");
|
||||
panic!("[napi-rs] missing environment variables. please upgrade `@napi-rs/cli` to the latest version.");
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@ use syn::{fold::Fold, parse_macro_input};
|
||||
pub fn napi(attr: TokenStream, input: TokenStream) -> TokenStream {
|
||||
match expand::expand(attr.into(), input.into()) {
|
||||
Ok(tokens) => {
|
||||
if env::var("DEBUG_GENERATED_CODE").is_ok() {
|
||||
if env::var("NAPI_DEBUG_GENERATED_CODE").is_ok() {
|
||||
println!("{}", tokens);
|
||||
}
|
||||
tokens.into()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user