iOS initial support

Usage:

	IPHONEOS_DEPLOYMENT_TARGET="13.1 cargo build --target aarch64-apple-ios --release
	codesign -d -s - --entitlements build_tools/ios_entitlements.xml target/aarch64-apple-ios/release/fish

Closes #10993
This commit is contained in:
kekeimiku
2024-04-05 21:42:50 +08:00
committed by Johannes Altmanninger
parent 039df1c7c7
commit 841687a1af
13 changed files with 419 additions and 22 deletions

View File

@@ -88,6 +88,7 @@ fn detect_cfgs(target: &mut Target) {
"",
&(|_: &Target| Ok(false)) as &dyn Fn(&Target) -> Result<bool, Box<dyn Error>>,
),
("apple", &detect_apple),
("bsd", &detect_bsd),
("gettext", &have_gettext),
("small_main_stack", &has_small_stack),
@@ -123,6 +124,10 @@ fn detect_cfgs(target: &mut Target) {
}
}
fn detect_apple(_: &Target) -> Result<bool, Box<dyn Error>> {
Ok(cfg!(any(target_os = "ios", target_os = "macos")))
}
/// Detect if we're being compiled for a BSD-derived OS, allowing targeting code conditionally with
/// `#[cfg(bsd)]`.
///
@@ -199,14 +204,14 @@ fn have_gettext(target: &Target) -> Result<bool, Box<dyn Error>> {
/// 0.5 MiB is small enough that we'd have to drastically reduce MAX_STACK_DEPTH to less than 10, so
/// we instead use a workaround to increase the main thread size.
fn has_small_stack(_: &Target) -> Result<bool, Box<dyn Error>> {
#[cfg(not(any(target_os = "macos", target_os = "netbsd")))]
#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "netbsd")))]
return Ok(false);
// NetBSD 10 also needs this but can't find pthread_get_stacksize_np.
#[cfg(target_os = "netbsd")]
return Ok(true);
#[cfg(target_os = "macos")]
#[cfg(any(target_os = "ios", target_os = "macos"))]
{
use core::ffi;

View File

@@ -0,0 +1,392 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>platform-application</key>
<true/>
<key>com.apple.private.security.no-container</key>
<true/>
<key>com.apple.private.security.container-manager</key>
<true/>
<key>com.apple.private.skip-library-validation</key>
<true/>
<key>com.apple.private.MobileContainerManager.allowed</key>
<true/>
<key>com.apple.private.security.storage.adprivacyd</key>
<true/>
<key>com.apple.private.security.storage.amfid</key>
<true/>
<key>com.apple.private.security.storage.AppBundles</key>
<true/>
<key>com.apple.private.security.storage.AppDataContainers</key>
<true/>
<key>com.apple.private.security.storage.automation-mode</key>
<true/>
<key>com.apple.private.security.storage.Biome</key>
<true/>
<key>com.apple.private.security.storage.Calendar</key>
<true/>
<key>com.apple.private.security.storage.CallHistory</key>
<true/>
<key>com.apple.private.security.storage.CarrierBundles</key>
<true/>
<key>com.apple.private.security.storage.chronod</key>
<true/>
<key>com.apple.private.security.storage.CloudDocsDB</key>
<true/>
<key>com.apple.private.security.storage.CloudKit</key>
<true/>
<key>com.apple.private.security.storage.containers</key>
<true/>
<key>com.apple.private.security.storage.CoreFollowUp</key>
<true/>
<key>com.apple.private.security.storage.CoreKnowledge</key>
<true/>
<key>com.apple.private.security.storage.Cryptex</key>
<true/>
<key>com.apple.private.security.storage.demo_backup</key>
<true/>
<key>com.apple.private.security.storage.DocumentRevisions</key>
<true/>
<key>com.apple.private.security.storage.DumpPanic</key>
<true/>
<key>com.apple.private.security.storage.ExposureNotification</key>
<true/>
<key>com.apple.private.security.storage.FaceTime</key>
<true/>
<key>com.apple.private.security.storage.familycircled</key>
<true/>
<key>com.apple.private.security.storage.FindMy</key>
<true/>
<key>com.apple.private.security.storage.fpsd</key>
<true/>
<key>com.apple.private.security.storage.Health</key>
<true/>
<key>com.apple.private.security.storage.HomeAI</key>
<true/>
<key>com.apple.private.security.storage.HomeKit</key>
<true/>
<key>com.apple.private.security.storage.iCloudDrive</key>
<true/>
<key>com.apple.private.security.storage.idcredd</key>
<true/>
<key>com.apple.private.security.storage.IdentityServices</key>
<true/>
<key>com.apple.private.security.storage.kbd</key>
<true/>
<key>com.apple.private.security.storage.Keychains</key>
<true/>
<key>com.apple.private.security.storage.Lockdown</key>
<true/>
<key>com.apple.private.security.storage.Mail</key>
<true/>
<key>com.apple.private.security.storage.Messages</key>
<true/>
<key>com.apple.private.security.storage.MessagesMetaData</key>
<true/>
<key>com.apple.private.security.storage.MobileContainerManager</key>
<true/>
<key>com.apple.private.security.storage.MobileDocuments</key>
<true/>
<key>com.apple.private.security.storage.MobileIdentityService</key>
<true/>
<key>com.apple.private.security.storage.mobilesync</key>
<true/>
<key>com.apple.private.security.storage.multimodalsearchd</key>
<true/>
<key>com.apple.private.security.storage.NanoTimeKit.FaceSupport</key>
<true/>
<key>com.apple.private.security.storage.News</key>
<true/>
<key>com.apple.private.security.storage.Notes</key>
<true/>
<key>com.apple.private.security.storage.Photos</key>
<true/>
<key>com.apple.private.security.storage.PhotosLibraries</key>
<true/>
<key>com.apple.private.security.storage.pipelined</key>
<true/>
<key>com.apple.private.security.storage.preferences</key>
<true/>
<key>com.apple.private.security.storage.PrivacyAccounting</key>
<true/>
<key>com.apple.private.security.storage.Safari</key>
<true/>
<key>com.apple.private.security.storage.SearchParty</key>
<true/>
<key>com.apple.private.security.storage.SecureElementService</key>
<true/>
<key>com.apple.private.security.storage.SensorKit</key>
<true/>
<key>com.apple.private.security.storage.SFAnalytics</key>
<true/>
<key>com.apple.private.security.storage.SiriInference</key>
<true/>
<key>com.apple.private.security.storage.SiriReferenceResolution</key>
<true/>
<key>com.apple.private.security.storage.SiriVocabulary</key>
<true/>
<key>com.apple.private.security.storage.SoC</key>
<true/>
<key>com.apple.private.security.storage.SpeechPersonalizedLM</key>
<true/>
<key>com.apple.private.security.storage.Spotlight</key>
<true/>
<key>com.apple.private.security.storage.StatusKit</key>
<true/>
<key>com.apple.private.security.storage.Stocks</key>
<true/>
<key>com.apple.private.security.storage.Suggestions</key>
<true/>
<key>com.apple.private.security.storage.SymptomFramework</key>
<true/>
<key>com.apple.private.security.storage.sysdagnose.ScreenshotServicesService</key>
<true/>
<key>com.apple.private.security.storage.TCC</key>
<true/>
<key>com.apple.private.security.storage.TimeMachine</key>
<true/>
<key>com.apple.private.security.storage.triald</key>
<true/>
<key>com.apple.private.security.storage.trustd</key>
<true/>
<key>com.apple.private.security.storage.trustd-private</key>
<true/>
<key>com.apple.private.security.storage.universalaccess</key>
<true/>
<key>com.apple.private.security.storage.Voicemail</key>
<true/>
<key>com.apple.private.security.storage.Wireless</key>
<true/>
<key>com.apple.private.security.disk-device-access</key>
<true/>
<key>com.apple.rootless.storage.ane_model_cache</key>
<true/>
<key>com.apple.rootless.storage.apfs_boot_mount</key>
<true/>
<key>com.apple.rootless.storage.clientScripter</key>
<true/>
<key>com.apple.rootless.storage.com.apple.mediaanalysisd</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.CarPlayAppBlacklist</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.DeviceCheck</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.DictionaryServices.dictionary2</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.DuetExpertCenterAsset</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.EmbeddedNL</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.Font5</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.Font6</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.HealthKt.FeatureAvailability</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.HomeKit</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.MacinTalkVoiceAssets</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.MailDynamicData</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.MXLongFormVideoApps</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.network.networknomicon</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.PKITrustSupplementals</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.SharingDeviceAssets</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.SiriShortcutsMobileAsset</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.TimeZoneUpdate</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.VoiceServices.CombinedVocalizerVoices</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.VoiceServices.CustomVoice</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.VoiceServices.GryphonVoice</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.VoiceServicesVocalizerVoice</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.VoiceServices.VoiceResources</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.VoiceTriggerAssets</key>
<true/>
<key>com.apple.rootless.storage.CoreAnalytics</key>
<true/>
<key>com.apple.rootless.storage.coreduet_knowledge_store</key>
<true/>
<key>com.apple.rootless.storage.coreidvd</key>
<true/>
<key>com.apple.rootless.storage.coreknowledge</key>
<true/>
<key>com.apple.rootless.storage.CoreRoutine</key>
<true/>
<key>com.apple.rootless.storage.CoreSpeech</key>
<true/>
<key>com.apple.rootless.storage.dmd</key>
<true/>
<key>com.apple.rootless.storage.dprivacyd_storage</key>
<true/>
<key>com.apple.rootless.storage.ExtensibleSSO</key>
<true/>
<key>com.apple.rootless.storage.facekit</key>
<true/>
<key>com.apple.rootless.storage.fpsd</key>
<true/>
<key>com.apple.rootless.storage.MobileStorageMounter</key>
<true/>
<key>com.apple.rootless.storage.MusicApp</key>
<true/>
<key>com.apple.rootless.storage.nsurlsessiond</key>
<true/>
<key>com.apple.rootless.storage.pearl-field-diagnostics</key>
<true/>
<key>com.apple.rootless.storage.proactivepredictions</key>
<true/>
<key>com.apple.rootless.storage.QLThumbnailCache</key>
<true/>
<key>com.apple.rootless.storage.remotemanagementd</key>
<true/>
<key>com.apple.rootless.storage.RoleAccountStaging</key>
<true/>
<key>com.apple.rootless.storage.sensorkit</key>
<true/>
<key>com.apple.rootless.storage.shortcuts</key>
<true/>
<key>com.apple.rootless.storage.siriremembers</key>
<true/>
<key>com.apple.rootless.storage.timezone</key>
<true/>
<key>com.apple.rootless.storage.triald</key>
<true/>
<key>com.apple.rootless.storage.voiceshortcuts</key>
<true/>
<key>com.apple.private.security.storage-exempt.heritable</key>
<true/>
<key>com.apple.private.security.storage.AppleMediaServices</key>
<true/>
<key>com.apple.private.security.storage.ContactlessReader</key>
<true/>
<key>com.apple.private.security.storage.CoreRoutine</key>
<true/>
<key>com.apple.private.security.storage.DiagnosticReports</key>
<true/>
<key>com.apple.private.security.storage.DiagnosticReports.read-write</key>
<true/>
<key>com.apple.private.security.storage.DoNotDisturb</key>
<true/>
<key>com.apple.private.security.storage.Home</key>
<true/>
<key>com.apple.private.security.storage.IntelligencePlatform</key>
<true/>
<key>com.apple.private.security.storage.Location</key>
<true/>
<key>com.apple.private.security.storage.ManagedConfiguration</key>
<true/>
<key>com.apple.private.security.storage.MapsSync</key>
<true/>
<key>com.apple.private.security.storage.MobileBackup</key>
<true/>
<key>com.apple.private.security.storage.MobileStorageMounter</key>
<true/>
<key>com.apple.private.security.storage.PassKit</key>
<true/>
<key>com.apple.private.security.storage.SiriFeatureStore</key>
<true/>
<key>com.apple.private.security.storage.SiriSELF</key>
<true/>
<key>com.apple.private.security.storage.SoundProfileAsset</key>
<true/>
<key>com.apple.private.security.storage.TextUnderstanding</key>
<true/>
<key>com.apple.private.security.storage.Weather</key>
<true/>
<key>com.apple.private.security.storage.appleaccountd</key>
<true/>
<key>com.apple.private.security.storage.ciconia</key>
<true/>
<key>com.apple.private.security.storage.clipserviced</key>
<true/>
<key>com.apple.private.security.storage.coreduet_knowledge_store</key>
<true/>
<key>com.apple.private.security.storage.driverkitd</key>
<true/>
<key>com.apple.private.security.storage.geoanalyticsd</key>
<true/>
<key>com.apple.private.security.storage.geod</key>
<true/>
<key>com.apple.private.security.storage.launchd</key>
<true/>
<key>com.apple.private.security.storage.sessionkitd</key>
<true/>
<key>com.apple.private.security.storage.sysdiagnose.ScreenshotServicesService</key>
<true/>
<key>com.apple.private.security.storage.sysdiagnose.sysdiagnose</key>
<true/>
<key>com.apple.private.security.storage.tmp</key>
<true/>
<key>com.apple.rootless.critical</key>
<true/>
<key>com.apple.rootless.datavault.metadata</key>
<true/>
<key>com.apple.rootless.install</key>
<true/>
<key>com.apple.rootless.install.heritable</key>
<true/>
<key>com.apple.rootless.restricted-block-devices</key>
<true/>
<key>com.apple.rootless.storage.MobileAssetDownload</key>
<true/>
<key>com.apple.rootless.storage.amsengagementd</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.HealthKit.FeatureAvailability</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.Trial.Siri.SiriDialogAssets</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.Trial.Siri.SiriExperienceCam</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.Trial.Siri.SiriFindMyConfigurationFiles</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.Trial.Siri.SiriInferredHelpfulness</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.Trial.Siri.SiriTextToSpeech</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.Trial.Siri.SiriUnderstandingAsrAssistant</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.Trial.Siri.SiriUnderstandingAsrHammer</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.Trial.Siri.SiriUnderstandingAsrUaap</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.Trial.Siri.SiriUnderstandingAttentionAssets</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.Trial.Siri.SiriUnderstandingMorphun</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.Trial.Siri.SiriUnderstandingNL</key>
<true/>
<key>com.apple.rootless.storage.com.apple.MobileAsset.Trial.Siri.SiriUnderstandingNLOverrides</key>
<true/>
<key>com.apple.rootless.storage.coreparsec_feedbacks</key>
<true/>
<key>com.apple.rootless.storage.coreparsec_uploadables</key>
<true/>
<key>com.apple.rootless.storage.early_boot_mount</key>
<true/>
<key>com.apple.rootless.storage.screentime</key>
<true/>
<key>com.apple.rootless.volume.ISCRecovery</key>
<true/>
<key>com.apple.rootless.volume.Preboot</key>
<true/>
<key>com.apple.rootless.volume.Recovery</key>
<true/>
<key>com.apple.rootless.volume.Update</key>
<true/>
<key>com.apple.rootless.volume.VM</key>
<true/>
<key>com.apple.rootless.volume.iSCPreboot</key>
<true/>
</dict>
</plist>

View File

@@ -229,7 +229,7 @@ fn tv_to_msec(tv: &libc::timeval) -> i64 {
fn print_rusage_self() {
let rs = getrusage(RUsage::RSelf);
let rss_kb = if cfg!(target_os = "macos") {
let rss_kb = if cfg!(apple) {
// mac use bytes.
rs.ru_maxrss / 1024
} else {

View File

@@ -496,7 +496,7 @@ fn update_fish_color_support(vars: &EnvStack) {
/// Apply any platform- or environment-specific hacks to our terminfo [`Term`] instance.
fn apply_term_hacks(vars: &EnvStack, term: &mut Term) {
if cfg!(target_os = "macos") {
if cfg!(apple) {
// Hack in missing italics and dim capabilities omitted from macOS xterm-256color terminfo.
// Improves the user experience under Terminal.app and iTerm.
let term_prog = vars

View File

@@ -28,10 +28,10 @@
use std::os::unix::prelude::MetadataExt;
// Pull in the O_EXLOCK constant if it is defined, otherwise set it to 0.
#[cfg(any(bsd, target_os = "macos"))]
#[cfg(any(apple, bsd))]
const O_EXLOCK: OFlag = OFlag::O_EXLOCK;
#[cfg(not(any(bsd, target_os = "macos")))]
#[cfg(not(any(apple, bsd)))]
const O_EXLOCK: OFlag = OFlag::empty();
/// Callback data, reflecting a change in universal variables.

View File

@@ -317,7 +317,7 @@ fn exit_code_from_exec_error(err: libc::c_int) -> libc::c_int {
// The file is not executable for various reasons.
STATUS_NOT_EXECUTABLE
}
#[cfg(target_os = "macos")]
#[cfg(apple)]
libc::EBADARCH => {
// This is for e.g. running ARM app on Intel Mac.
STATUS_NOT_EXECUTABLE

View File

@@ -110,12 +110,12 @@ pub fn fish_wcswidth(s: &wstr) -> isize {
// otherwise it uses mkstemp followed by fcntl
pub fn fish_mkstemp_cloexec(name_template: CString) -> Result<(File, CString), Errno> {
let name = name_template.into_raw();
#[cfg(not(target_os = "macos"))]
#[cfg(not(apple))]
let fd = {
use libc::O_CLOEXEC;
unsafe { libc::mkostemp(name, O_CLOEXEC) }
};
#[cfg(target_os = "macos")]
#[cfg(apple)]
let fd = {
use libc::{FD_CLOEXEC, F_SETFD};
let fd = unsafe { libc::mkstemp(name) };

View File

@@ -42,14 +42,14 @@ pub fn poll_fd_readable(fd: i32) -> bool {
/// This allows accumulating a set of fds and then seeing if they are readable.
/// This only handles readability.
/// Apple's `man poll`: "The poll() system call currently does not support devices."
#[cfg(target_os = "macos")]
#[cfg(apple)]
pub struct FdReadableSet {
// The underlying fdset and nfds value to pass to select().
fdset_: libc::fd_set,
nfds_: c_int,
}
#[cfg(target_os = "macos")]
#[cfg(apple)]
impl FdReadableSet {
/// Construct an empty set.
pub fn new() -> FdReadableSet {
@@ -124,12 +124,12 @@ pub fn poll_fd_readable(fd: RawFd) -> bool {
}
}
#[cfg(not(target_os = "macos"))]
#[cfg(not(apple))]
pub struct FdReadableSet {
pollfds_: Vec<libc::pollfd>,
}
#[cfg(not(target_os = "macos"))]
#[cfg(not(apple))]
impl FdReadableSet {
/// Construct an empty set.
pub fn new() -> FdReadableSet {

View File

@@ -263,7 +263,7 @@ mod o_search {
/// On macOS we have O_SEARCH, which is defined as O_EXEC | O_DIRECTORY,
/// where O_EXEC is 0x40000000. This is only on macOS 12.0+ or later; however
/// prior macOS versions ignores O_EXEC so it is treated the same as O_RDONLY.
#[cfg(target_os = "macos")]
#[cfg(apple)]
pub const BEST_O_SEARCH: OFlag = OFlag::from_bits_truncate(libc::O_DIRECTORY | 0x40000000);
/// On FreeBSD, we have O_SEARCH = 0x00040000.
@@ -277,10 +277,10 @@ mod o_search {
/// Fall back to O_RDONLY.
#[cfg(not(any(
apple,
target_os = "linux",
target_os = "android",
target_os = "freebsd",
target_os = "macos"
)))]
pub const BEST_O_SEARCH: OFlag = OFlag::O_RDONLY;
}

View File

@@ -131,7 +131,7 @@ pub fn execute_setpgid(pid: Pid, pgroup: Pid, is_parent: bool) -> i32 {
// 12.2) does not consider a child that has already forked, exec'd, and exited to "exist"
// and returns ESRCH (process not found) instead of EACCES (child has called exec).
// See https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=251227
#[cfg(any(bsd, target_os = "macos"))]
#[cfg(any(apple, bsd))]
if err == libc::ESRCH && is_parent {
// Handle this just like we would EACCES above, as we're virtually certain that
// setpgid(2) was called against a process that was at least at one point in time a
@@ -484,7 +484,7 @@ pub(crate) fn safe_report_exec_error(
);
}
#[cfg(target_os = "macos")]
#[cfg(apple)]
libc::EBADARCH => {
FLOG_SAFE!(
exec,

View File

@@ -401,10 +401,10 @@ macro_rules! signal_entry {
signal_entry!(SIGSYS, "Bad system call"),
signal_entry!(SIGIOT, "Abort (Alias for SIGABRT)"),
#[cfg(any(bsd, target_os = "macos"))]
#[cfg(any(apple, bsd))]
signal_entry!(SIGEMT, "Unused signal"),
#[cfg(any(bsd, target_os = "macos"))]
#[cfg(any(apple, bsd))]
signal_entry!(SIGINFO, "Information request"),
#[cfg(target_os = "linux")]

View File

@@ -263,7 +263,7 @@ pub fn die(&self, msg: &str) {
// sem_destroy has been deprecated since macOS 10.10 but we only use it under Linux so silence the
// warning.
#[cfg_attr(target_os = "macos", allow(deprecated))]
#[cfg_attr(apple, allow(deprecated))]
impl Drop for BinarySemaphore {
fn drop(&mut self) {
if let Self::Semaphore(sem) = self {

View File

@@ -1,7 +1,7 @@
use once_cell::sync::OnceCell;
use std::os::fd::RawFd;
#[cfg(target_os = "macos")]
#[cfg(apple)]
mod notifyd;
#[cfg(any(target_os = "android", target_os = "linux"))]
@@ -53,7 +53,7 @@ fn notification_fd_became_readable(&self, _fd: RawFd) -> bool {
/// Create a notifier.
pub fn create_notifier() -> Box<dyn UniversalNotifier> {
#[cfg(target_os = "macos")]
#[cfg(apple)]
if let Some(notifier) = notifyd::NotifydNotifier::new() {
return Box::new(notifier);
}