55#![ cfg_attr( doc_cfg, feature( doc_cfg) ) ]
66
77pub use anyhow:: Result ;
8+ use cargo_toml:: { Dependency , Manifest } ;
89use heck:: AsShoutySnakeCase ;
910
10- use tauri_utils:: resources:: { external_binaries, resource_relpath, ResourcePaths } ;
11+ use tauri_utils:: {
12+ config:: Config ,
13+ resources:: { external_binaries, resource_relpath, ResourcePaths } ,
14+ } ;
1115
1216use std:: path:: { Path , PathBuf } ;
1317
@@ -242,8 +246,6 @@ pub fn build() {
242246#[ allow( unused_variables) ]
243247pub fn try_build ( attributes : Attributes ) -> Result < ( ) > {
244248 use anyhow:: anyhow;
245- use cargo_toml:: { Dependency , Manifest } ;
246- use tauri_utils:: config:: { Config , TauriConfig } ;
247249
248250 println ! ( "cargo:rerun-if-env-changed=TAURI_CONFIG" ) ;
249251 println ! ( "cargo:rerun-if-changed=tauri.conf.json" ) ;
@@ -268,50 +270,33 @@ pub fn try_build(attributes: Attributes) -> Result<()> {
268270
269271 cfg_alias ( "dev" , !has_feature ( "custom-protocol" ) ) ;
270272
271- let mut manifest = Manifest :: from_path ( "Cargo.toml" ) ?;
272- if let Some ( tauri) = manifest. dependencies . remove ( "tauri" ) {
273- let features = match tauri {
274- Dependency :: Simple ( _) => Vec :: new ( ) ,
275- Dependency :: Detailed ( dep) => dep. features ,
276- Dependency :: Inherited ( dep) => dep. features ,
277- } ;
278-
279- let all_cli_managed_features = TauriConfig :: all_features ( ) ;
280- let diff = features_diff (
281- & features
282- . into_iter ( )
283- . filter ( |f| all_cli_managed_features. contains ( & f. as_str ( ) ) )
284- . collect :: < Vec < String > > ( ) ,
285- & config
286- . tauri
287- . features ( )
288- . into_iter ( )
289- . map ( |f| f. to_string ( ) )
290- . collect :: < Vec < String > > ( ) ,
291- ) ;
292-
293- let mut error_message = String :: new ( ) ;
294- if !diff. remove . is_empty ( ) {
295- error_message. push_str ( "remove the `" ) ;
296- error_message. push_str ( & diff. remove . join ( ", " ) ) ;
297- error_message. push_str ( if diff. remove . len ( ) == 1 {
298- "` feature"
299- } else {
300- "` features"
301- } ) ;
302- if !diff. add . is_empty ( ) {
303- error_message. push_str ( " and " ) ;
304- }
305- }
306- if !diff. add . is_empty ( ) {
307- error_message. push_str ( "add the `" ) ;
308- error_message. push_str ( & diff. add . join ( ", " ) ) ;
309- error_message. push_str ( if diff. add . len ( ) == 1 {
310- "` feature"
311- } else {
312- "` features"
313- } ) ;
273+ let ws_path = get_workspace_dir ( ) ?;
274+ let mut manifest =
275+ Manifest :: < cargo_toml:: Value > :: from_slice_with_metadata ( & std:: fs:: read ( "Cargo.toml" ) ?) ?;
276+
277+ if let Ok ( ws_manifest) = Manifest :: from_path ( ws_path. join ( "Cargo.toml" ) ) {
278+ Manifest :: complete_from_path_and_workspace (
279+ & mut manifest,
280+ Path :: new ( "Cargo.toml" ) ,
281+ Some ( ( & ws_manifest, ws_path. as_path ( ) ) ) ,
282+ ) ?;
283+ } else {
284+ Manifest :: complete_from_path ( & mut manifest, Path :: new ( "Cargo.toml" ) ) ?;
285+ }
286+
287+ if let Some ( tauri_build) = manifest. build_dependencies . remove ( "tauri-build" ) {
288+ let error_message = check_features ( & config, tauri_build, true ) ;
289+
290+ if !error_message. is_empty ( ) {
291+ return Err ( anyhow ! ( "
292+ The `tauri-build` dependency features on the `Cargo.toml` file does not match the allowlist defined under `tauri.conf.json`.
293+ Please run `tauri dev` or `tauri build` or {}.
294+ " , error_message) ) ;
314295 }
296+ }
297+
298+ if let Some ( tauri) = manifest. dependencies . remove ( "tauri" ) {
299+ let error_message = check_features ( & config, tauri, false ) ;
315300
316301 if !error_message. is_empty ( ) {
317302 return Err ( anyhow ! ( "
@@ -485,6 +470,89 @@ fn features_diff(current: &[String], expected: &[String]) -> Diff {
485470 Diff { remove, add }
486471}
487472
473+ fn check_features ( config : & Config , dependency : Dependency , is_tauri_build : bool ) -> String {
474+ use tauri_utils:: config:: { PatternKind , TauriConfig } ;
475+
476+ let features = match dependency {
477+ Dependency :: Simple ( _) => Vec :: new ( ) ,
478+ Dependency :: Detailed ( dep) => dep. features ,
479+ Dependency :: Inherited ( dep) => dep. features ,
480+ } ;
481+
482+ let all_cli_managed_features = if is_tauri_build {
483+ vec ! [ "isolation" ]
484+ } else {
485+ TauriConfig :: all_features ( )
486+ } ;
487+
488+ let expected = if is_tauri_build {
489+ match config. tauri . pattern {
490+ PatternKind :: Isolation { .. } => vec ! [ "isolation" . to_string( ) ] ,
491+ _ => vec ! [ ] ,
492+ }
493+ } else {
494+ config
495+ . tauri
496+ . features ( )
497+ . into_iter ( )
498+ . map ( |f| f. to_string ( ) )
499+ . collect :: < Vec < String > > ( )
500+ } ;
501+
502+ let diff = features_diff (
503+ & features
504+ . into_iter ( )
505+ . filter ( |f| all_cli_managed_features. contains ( & f. as_str ( ) ) )
506+ . collect :: < Vec < String > > ( ) ,
507+ & expected,
508+ ) ;
509+
510+ let mut error_message = String :: new ( ) ;
511+ if !diff. remove . is_empty ( ) {
512+ error_message. push_str ( "remove the `" ) ;
513+ error_message. push_str ( & diff. remove . join ( ", " ) ) ;
514+ error_message. push_str ( if diff. remove . len ( ) == 1 {
515+ "` feature"
516+ } else {
517+ "` features"
518+ } ) ;
519+ if !diff. add . is_empty ( ) {
520+ error_message. push_str ( " and " ) ;
521+ }
522+ }
523+ if !diff. add . is_empty ( ) {
524+ error_message. push_str ( "add the `" ) ;
525+ error_message. push_str ( & diff. add . join ( ", " ) ) ;
526+ error_message. push_str ( if diff. add . len ( ) == 1 {
527+ "` feature"
528+ } else {
529+ "` features"
530+ } ) ;
531+ }
532+
533+ error_message
534+ }
535+
536+ #[ derive( serde:: Deserialize ) ]
537+ struct CargoMetadata {
538+ workspace_root : PathBuf ,
539+ }
540+
541+ fn get_workspace_dir ( ) -> Result < PathBuf > {
542+ let output = std:: process:: Command :: new ( "cargo" )
543+ . args ( [ "metadata" , "--no-deps" , "--format-version" , "1" ] )
544+ . output ( ) ?;
545+
546+ if !output. status . success ( ) {
547+ return Err ( anyhow:: anyhow!(
548+ "cargo metadata command exited with a non zero exit code: {}" ,
549+ String :: from_utf8( output. stderr) ?
550+ ) ) ;
551+ }
552+
553+ Ok ( serde_json:: from_slice :: < CargoMetadata > ( & output. stdout ) ?. workspace_root )
554+ }
555+
488556#[ cfg( test) ]
489557mod tests {
490558 use super :: Diff ;
0 commit comments