Struct apple_sdk::SdkSearch

source ·
pub struct SdkSearch { /* private fields */ }
Expand description

Search parameters for locating an Apple SDK.

This type can be used to construct a search for an Apple SDK given user chosen search parameters.

The search algorithm is essentially:

  1. Iterate through each registered search location.
  2. Discover candidate SDKs and filter.
  3. Globally sort (if enabled).

Search Locations

Search mechanisms / locations are represented via SdkSearchLocation and internally the searcher maintains a vector of locations. The default search locations are:

  1. Use path specified by SDKROOT environment variable, if defined.
  2. Find SDKs within the Developer Directory defined by the DEVELOPER_DIR environment variable.
  3. Find SDKs within the system installed Xcode application.
  4. Find SDKs within the system installed Xcode Command Line Tools.

Simply call Self::location() to register a new location. If the default locations are not desirable, construct an empty instance via Self::empty() and register your explicit list of locations.

An attempt is made to only search a given location at most once. This is done in order to avoid redundant work. If a location is specified multiple times - even via different SdkSearchLocation variants - subsequent searches of that location will yield no distinct results. Duplicate SDKs can occur in the returned list.

Filtering

Filters can be registered to control which SDKs are emitted from the search.

By default, no filtering is performed. This means all SDKs in all search locations are returned. This can return SDKs belonging to multiple platforms (e.g. macOS and iOS).

The following functions control filtering:

If you are looking for an SDK to use (e.g. for compilation), you should at least use a platform filter. Otherwise you may see SDKs for platforms you aren’t targeting! It is also an encouraged practice to specify a minimum or maximum SDK version to use.

If you know you are targeting a specific OS version, applying a targeting filter via Self::deployment_target() is recommended. However, this filter is not always reliable. See the caveats in its documentation.

Sorting

By default, the returned list of SDKs is the chained result of SDKs discovered in all registered search locations. The order of the SDK within each search location is likely the sorted order of directory names as they appear on the filesystem.

If using an SDK for compilation, sorting by the SDK version is likely desired. Using the latest/newest SDK that supports a given deployment target is generally a best practice.

Implementations§

Obtain an instance with an empty set of search locations.

The search will not resolve any SDKs unless a search location is registered with the instance.

Define a function that will be called to provide updates on SDK search status.

Add a location to search.

The location will be appended to the current search location list.

Set the SDK platform to search for.

If you do not call this, SDKs for all platforms are returned.

If you are looking for a specific SDK to use, you probably want to call this. If you are searching for all available SDKs, you probably don’t want to call this.

Minimum SDK version to require.

Effectively imposes a >= filter on found SDKs.

If using SimpleSdk and the SDK version could not be determined from the filesystem path, the version is assumed to be 0.0 and this filter will likely exclude the SDK.

Maximum SDK version to return.

Effectively imposes a <= filter on found SDKs.

Deployment target that the SDK must support.

When set, only SDKs that support targeting the given target-version pair will be returned. Example values are (macosx, 10.15).

Only modern SDKs with SDKSettings.json files advertise their targeting settings in a way that allows this filter to work.

Attempting to use this filter on SimpleSdk will result in a run-time error at search time since these SDKs do not parse SDKSettings files.

Define the sorting order for returned SDKs.

Default is SdkSorting::None.

Perform a search, yielding found SDKs sorted by the search’s preferences.

May return an empty vector.

Whether an SDK matches our search filter.

This is exposed as a convenience method to allow custom implementations of SDK searching using the filtering logic on this type.

Examples found in repository?
src/search.rs (line 561)
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
    pub fn search<SDK: AppleSdk>(&self) -> Result<Vec<SDK>, Error> {
        let mut sdks = vec![];

        // Track searched locations to avoid redundant work.
        let mut searched_platform_dirs = HashSet::new();
        let mut searched_sdks_dirs = HashSet::new();

        for location in &self.locations {
            if let Some(cb) = &self.progress_callback {
                cb(SdkSearchEvent::SearchingLocation(location.clone()));
            }

            // Expand each location to SDKs.
            let resolved = location.resolve_location()?;

            let candidate_sdks = match &resolved {
                SdkSearchResolvedLocation::None => {
                    vec![]
                }
                SdkSearchResolvedLocation::PlatformDirectories(dirs) => dirs
                    .iter()
                    // Apply platform filter.
                    .filter(|dir| {
                        if let Some(wanted_platform) = &self.platform {
                            if &dir.platform == wanted_platform {
                                if let Some(cb) = &self.progress_callback {
                                    cb(SdkSearchEvent::PlatformDirectoryInclude(dir.path.clone()));
                                }

                                true
                            } else {
                                if let Some(cb) = &self.progress_callback {
                                    cb(SdkSearchEvent::PlatformDirectoryExclude(dir.path.clone()));
                                }

                                false
                            }
                        } else {
                            if let Some(cb) = &self.progress_callback {
                                cb(SdkSearchEvent::PlatformDirectoryInclude(dir.path.clone()));
                            }

                            true
                        }
                    })
                    // Apply duplicate search filter.
                    .filter(|dir| {
                        if searched_platform_dirs.contains(dir.path()) {
                            false
                        } else {
                            searched_platform_dirs.insert(dir.path().to_path_buf());
                            true
                        }
                    })
                    .map(|dir| dir.find_sdks::<SDK>())
                    .collect::<Result<Vec<_>, Error>>()?
                    .into_iter()
                    .flatten()
                    .collect::<Vec<_>>(),
                SdkSearchResolvedLocation::SdksDirectory(path) => {
                    if searched_sdks_dirs.contains(path) {
                        vec![]
                    } else {
                        searched_sdks_dirs.insert(path.clone());
                        SDK::find_in_directory(path)?
                    }
                }
                SdkSearchResolvedLocation::SdkDirectory(path)
                | SdkSearchResolvedLocation::SdkDirectoryUnfiltered(path) => {
                    vec![SDK::from_directory(path)?]
                }
            };

            let mut added_count = 0;

            for sdk in candidate_sdks {
                let include = if resolved.apply_sdk_filter() {
                    self.filter_sdk(&sdk)?
                } else {
                    if let Some(cb) = &self.progress_callback {
                        cb(SdkSearchEvent::SdkFilterSkip(sdk.sdk_path()));
                    }

                    true
                };

                if include {
                    sdks.push(sdk);
                    added_count += 1;
                }
            }

            if location.is_terminal() && added_count > 0 {
                break;
            }
        }

        // Sorting should be stable with None variant. But we can avoid the
        // overhead.
        if self.sorting != SdkSorting::None {
            sdks.sort_by(|a, b| self.sorting.compare_version(a.version(), b.version()))
        }

        Ok(sdks)
    }

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.