mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-11-28 18:03:04 +00:00
darwin.AvailabilityVersions: init at 140.1
This commit is contained in:
parent
91d8dd928f
commit
3a545f673e
@ -0,0 +1,244 @@
|
|||||||
|
From dd3a2378cca465ec783fd792158b2fc11f83722c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Randy Eckenrode <randy@largeandhighquality.com>
|
||||||
|
Date: Tue, 2 Jul 2024 20:04:56 -0400
|
||||||
|
Subject: [PATCH] Support setting an upper bound on versions
|
||||||
|
|
||||||
|
---
|
||||||
|
availability | 94 ++++++++++++++++++++++++++++++++++------------------
|
||||||
|
1 file changed, 61 insertions(+), 33 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/availability b/availability
|
||||||
|
index 8ebd250..5bb9edb 100755
|
||||||
|
--- a/availability
|
||||||
|
+++ b/availability
|
||||||
|
@@ -17,12 +17,34 @@ MIN_PYTHON = (3, 7) #Required for ordered dictionaries as default
|
||||||
|
if sys.version_info < MIN_PYTHON:
|
||||||
|
sys.exit("Python %s.%s or later is required.\n" % MIN_PYTHON)
|
||||||
|
|
||||||
|
+
|
||||||
|
+def parse_version(ver):
|
||||||
|
+ if hasattr(ver, "string"):
|
||||||
|
+ ver = ver.string()
|
||||||
|
+
|
||||||
|
+ return (tuple(map(int, ver.split("."))) + (0, 0))[:3]
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def version_older_or_equal(lhs, rhs):
|
||||||
|
+ if not rhs:
|
||||||
|
+ return True
|
||||||
|
+
|
||||||
|
+ lhs_major, lhs_minor, lhs_patch = parse_version(lhs)
|
||||||
|
+ rhs_major, rhs_minor, rhs_patch = parse_version(rhs)
|
||||||
|
+
|
||||||
|
+ return (
|
||||||
|
+ lhs_major < rhs_major
|
||||||
|
+ or (lhs_major == rhs_major and lhs_minor < rhs_minor)
|
||||||
|
+ or (lhs_major == rhs_major and lhs_minor == rhs_minor and lhs_patch <= rhs_patch)
|
||||||
|
+ )
|
||||||
|
+
|
||||||
|
+
|
||||||
|
# The build script will embed the DSL content here, otherwise we build it at runtime
|
||||||
|
dslContent = None
|
||||||
|
# @@INSERT_DSL_CONTENT()@@
|
||||||
|
|
||||||
|
class VersionSetDSL:
|
||||||
|
- def __init__(self, data): self.parsedDSL = self.Parser(data)
|
||||||
|
+ def __init__(self, data, threshold): self.parsedDSL = self.Parser(data, threshold)
|
||||||
|
def sets(self): return self.parsedDSL.version_sets
|
||||||
|
def platforms(self): return self.parsedDSL.platforms
|
||||||
|
|
||||||
|
@@ -104,12 +126,15 @@ class VersionSetDSL:
|
||||||
|
self.availability_deprecation_define_name = optionals["availability_deprecation_define_name"]
|
||||||
|
if "version_define_name" in optionals:
|
||||||
|
self.availability_define_prefix = f"__{optionals['version_define_name']}_"
|
||||||
|
- def add_version(self, version): return self.versions.append(version);
|
||||||
|
+ def add_version(self, version, threshold):
|
||||||
|
+ if version_older_or_equal(version, threshold):
|
||||||
|
+ self.versions.append(version)
|
||||||
|
def add_variant(self, variant): return self.variants.append(variant);
|
||||||
|
class Parser:
|
||||||
|
platforms = {}
|
||||||
|
version_sets = []
|
||||||
|
- def __init__(self, data):
|
||||||
|
+ def __init__(self, data, threshold):
|
||||||
|
+ self.threshold = threshold
|
||||||
|
for line in data.splitlines():
|
||||||
|
line = line.strip().split('#',1)[0]
|
||||||
|
if not line:
|
||||||
|
@@ -129,7 +154,7 @@ class VersionSetDSL:
|
||||||
|
def set(self, name, version, uversion):
|
||||||
|
platforms = {}
|
||||||
|
for (platformName, platform) in self.platforms.items():
|
||||||
|
- if platform.versioned:
|
||||||
|
+ if platform.versioned and platform.versions:
|
||||||
|
platforms[platformName] = platform.versions[-1]
|
||||||
|
version_set = {}
|
||||||
|
version_set["name"] = name
|
||||||
|
@@ -138,7 +163,7 @@ class VersionSetDSL:
|
||||||
|
self.version_sets.append(version_set)
|
||||||
|
# TODO add error checking for version decrease
|
||||||
|
def version(self, platform, version):
|
||||||
|
- if platform in self.platforms: self.platforms[platform].add_version(VersionSetDSL.Version(version))
|
||||||
|
+ if platform in self.platforms: self.platforms[platform].add_version(VersionSetDSL.Version(version), self.threshold)
|
||||||
|
else:
|
||||||
|
print(f"Unknown platform \"{platform}\"")
|
||||||
|
exit(-1)
|
||||||
|
@@ -165,9 +190,8 @@ if not dslContent:
|
||||||
|
parts = line.split()
|
||||||
|
if uversion and parts and parts[0] == "set" and parts[3] == uversion:
|
||||||
|
break
|
||||||
|
-versions = VersionSetDSL(dslContent)
|
||||||
|
|
||||||
|
-def print_sets():
|
||||||
|
+def print_sets(versions):
|
||||||
|
print("---")
|
||||||
|
for set in versions.sets():
|
||||||
|
print(f'{set["name"]}:')
|
||||||
|
@@ -178,7 +202,8 @@ def print_versions(platform):
|
||||||
|
print(" ".join([version.string() for version in versions.platforms()[platform].versions]))
|
||||||
|
|
||||||
|
class Preprocessor:
|
||||||
|
- def __init__(self, inputFile, outputFile):
|
||||||
|
+ def __init__(self, versions, inputFile, outputFile):
|
||||||
|
+ self.versions = versions
|
||||||
|
bufferedOutput = ""
|
||||||
|
with tempfile.NamedTemporaryFile('w') as tmp:
|
||||||
|
with open(inputFile, 'r') as input:
|
||||||
|
@@ -207,10 +232,10 @@ class Preprocessor:
|
||||||
|
output.write("\"\"\"\n")
|
||||||
|
def VERSION_MAP(self, output):
|
||||||
|
sets = []
|
||||||
|
- for set in versions.sets():
|
||||||
|
+ for set in self.versions.sets():
|
||||||
|
set_string = ", ".join(sorted({".{} = {}".format(os,osVersion.hex()) for (os,osVersion) in set["platforms"].items()}))
|
||||||
|
sets.append("\t{{ .set = {}, {} }}".format(set["version"].hex(), set_string))
|
||||||
|
- platform_string = "\n".join([" uint32_t {} = 0;".format(name) for name in versions.platforms().keys()])
|
||||||
|
+ platform_string = "\n".join([" uint32_t {} = 0;".format(name) for name in self.versions.platforms().keys()])
|
||||||
|
output.write("""
|
||||||
|
#include <set>
|
||||||
|
#include <array>
|
||||||
|
@@ -229,16 +254,16 @@ static const std::array<VersionSetEntry, {}> sVersionMap = {{{{
|
||||||
|
}};
|
||||||
|
""".format(platform_string, len(sets), ",\n".join(sets)))
|
||||||
|
def DYLD_HEADER_VERSIONS(self, output):
|
||||||
|
- for (name,platform) in versions.platforms().items():
|
||||||
|
+ for (name,platform) in self.versions.platforms().items():
|
||||||
|
for version in platform.versions:
|
||||||
|
output.write(f"#define {platform.dyld_version_define_name + version.symbol() : <48}{version.hex()}\n");
|
||||||
|
output.write("\n")
|
||||||
|
- for set in versions.sets():
|
||||||
|
+ for set in self.versions.sets():
|
||||||
|
set_string = " / ".join(sorted({"{} {}".format(os,osVersion.string()) for(os,osVersion) in set["platforms"].items()}))
|
||||||
|
output.write("// dyld_{}_os_versions => {}\n".format(set["name"], set_string))
|
||||||
|
output.write("#define dyld_{}_os_versions".format(set["name"]).ljust(56, ' '))
|
||||||
|
output.write("({{ (dyld_build_version_t){{0xffffffff, {}}}; }})\n\n".format(set["version"].hex()))
|
||||||
|
- for (name,platform) in versions.platforms().items():
|
||||||
|
+ for (name,platform) in self.versions.platforms().items():
|
||||||
|
for version in platform.versions:
|
||||||
|
output.write("#define dyld_platform_version_{}_{}".format(platform.stylized_name, version.symbol()).ljust(56, ' '))
|
||||||
|
output.write("({{ (dyld_build_version_t){{{}, {}{}}}; }})\n".format(platform.platform_define, platform.dyld_version_define_name, version.symbol()))
|
||||||
|
@@ -247,14 +272,14 @@ static const std::array<VersionSetEntry, {}> sVersionMap = {{{{
|
||||||
|
def ALIAS_VERSION_MACROS(self, output, platformString, newName, oldName, **optionals):
|
||||||
|
minVersion = literal_eval(optionals.get("minVersion", "0x00000000"))
|
||||||
|
maxVersion = literal_eval(optionals.get("maxVersion", "0xFFFFFFFF"))
|
||||||
|
- platform = versions.platforms()[platformString];
|
||||||
|
+ platform = self.versions.platforms()[platformString];
|
||||||
|
for version in platform.versions:
|
||||||
|
if literal_eval(version.hex()) < minVersion: continue
|
||||||
|
if literal_eval(version.hex()) >= maxVersion: continue
|
||||||
|
output.write(f'#define {newName + version.symbol() : <48} {oldName + version.symbol()}\n')
|
||||||
|
def AVAILABILITY_DEFINES(self, output):
|
||||||
|
- for platformString in versions.platforms():
|
||||||
|
- platform = versions.platforms()[platformString];
|
||||||
|
+ for platformString in self.versions.platforms():
|
||||||
|
+ platform = self.versions.platforms()[platformString];
|
||||||
|
if platform.bleached:
|
||||||
|
output.write(f"#ifndef __APPLE_BLEACH_SDK__\n")
|
||||||
|
output.write(f"#ifndef __API_TO_BE_DEPRECATED_{platform.availability_deprecation_define_name}\n")
|
||||||
|
@@ -268,16 +293,16 @@ static const std::array<VersionSetEntry, {}> sVersionMap = {{{{
|
||||||
|
output.write(f"#endif /* __APPLE_BLEACH_SDK__ */\n")
|
||||||
|
output.write(f"\n");
|
||||||
|
def AVAILABILITY_VERSION_DEFINES(self, output):
|
||||||
|
- for platformString in versions.platforms():
|
||||||
|
- short = platform = versions.platforms()[platformString].short_version_numbers
|
||||||
|
- platform = versions.platforms()[platformString];
|
||||||
|
+ for platformString in self.versions.platforms():
|
||||||
|
+ short = platform = self.versions.platforms()[platformString].short_version_numbers
|
||||||
|
+ platform = self.versions.platforms()[platformString];
|
||||||
|
for version in platform.versions:
|
||||||
|
output.write(f"#define {platform.availability_define_prefix + version.symbol() : <48}{version.decimal(short)}\n")
|
||||||
|
output.write(f"/* {platform.availability_define_prefix}_NA is not defined to a value but is used as a token by macros to indicate that the API is unavailable */\n\n")
|
||||||
|
def AVAILABILITY_MIN_MAX_DEFINES(self, output):
|
||||||
|
- for platformString in versions.platforms():
|
||||||
|
- platform = versions.platforms()[platformString];
|
||||||
|
- if not platform.versioned:
|
||||||
|
+ for platformString in self.versions.platforms():
|
||||||
|
+ platform = self.versions.platforms()[platformString];
|
||||||
|
+ if not platform.versioned or not platform.versions:
|
||||||
|
continue
|
||||||
|
if platform.bleached:
|
||||||
|
output.write(f"#ifndef __APPLE_BLEACH_SDK__\n")
|
||||||
|
@@ -310,8 +335,8 @@ static const std::array<VersionSetEntry, {}> sVersionMap = {{{{
|
||||||
|
output.write(f" #define __API_UNAVAILABLE_PLATFORM_{displayName} {realName},unavailable\n")
|
||||||
|
output.write(f"#if defined(__has_feature) && defined(__has_attribute)\n")
|
||||||
|
output.write(f" #if __has_attribute(availability)\n")
|
||||||
|
- for platformString in versions.platforms():
|
||||||
|
- platform = versions.platforms()[platformString];
|
||||||
|
+ for platformString in self.versions.platforms():
|
||||||
|
+ platform = self.versions.platforms()[platformString];
|
||||||
|
if platform.bleached:
|
||||||
|
output.write(f"#ifndef __APPLE_BLEACH_SDK__\n")
|
||||||
|
writeDefines(platformString, platformString, platform.versioned)
|
||||||
|
@@ -326,9 +351,9 @@ static const std::array<VersionSetEntry, {}> sVersionMap = {{{{
|
||||||
|
output.write(f" #endif /* __has_attribute(availability) */\n")
|
||||||
|
output.write(f"#endif /* defined(__has_feature) && defined(__has_attribute) */\n")
|
||||||
|
def AVAILABILITY_MACRO_IMPL(self, output, prefix, dispatcher, **optionals):
|
||||||
|
- count = len(versions.platforms())
|
||||||
|
- for platformString in versions.platforms():
|
||||||
|
- platform = versions.platforms()[platformString]
|
||||||
|
+ count = len(self.versions.platforms())
|
||||||
|
+ for platformString in self.versions.platforms():
|
||||||
|
+ platform = self.versions.platforms()[platformString]
|
||||||
|
count = count + len(platform.variants)
|
||||||
|
platformList = []
|
||||||
|
argList = []
|
||||||
|
@@ -344,9 +369,9 @@ static const std::array<VersionSetEntry, {}> sVersionMap = {{{{
|
||||||
|
scoped_availablity = False
|
||||||
|
if "scoped_availablity" in optionals and optionals["scoped_availablity"] == "TRUE":
|
||||||
|
scoped_availablity=True
|
||||||
|
- count = len(versions.platforms())
|
||||||
|
- for platformString in versions.platforms():
|
||||||
|
- platform = versions.platforms()[platformString]
|
||||||
|
+ count = len(self.versions.platforms())
|
||||||
|
+ for platformString in self.versions.platforms():
|
||||||
|
+ platform = self.versions.platforms()[platformString]
|
||||||
|
count = count + len(platform.variants)
|
||||||
|
argList = ','.join([f'{macroName}{x}' for x in reversed(range(0, count))])
|
||||||
|
if "argCount" in optionals:
|
||||||
|
@@ -358,8 +383,9 @@ static const std::array<VersionSetEntry, {}> sVersionMap = {{{{
|
||||||
|
output.write(f" #define {name}(...) {macroName}_GET_MACRO(__VA_ARGS__,{argList},0)(__VA_ARGS__)\n")
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
+parser.add_argument("--threshold", default=False, help='Specifies the maximum version (inclusive) included in pre-processed headers')
|
||||||
|
group = parser.add_mutually_exclusive_group()
|
||||||
|
-for (name, platform) in versions.platforms().items():
|
||||||
|
+for (name, platform) in VersionSetDSL(dslContent, threshold=None).platforms().items():
|
||||||
|
group.add_argument("--{}".format(name), default=False, action='store_true', help="Prints all SDK versions defined for {}".format(name))
|
||||||
|
for alias in platform.cmd_aliases:
|
||||||
|
group.add_argument("--{}".format(alias), dest=name, default=False, action='store_true', help="Alias for --{}".format(name))
|
||||||
|
@@ -367,8 +393,10 @@ group.add_argument("--sets", default=False, actio
|
||||||
|
group.add_argument("--preprocess", nargs=2, help=argparse.SUPPRESS)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
-if args.sets: print_sets();
|
||||||
|
-elif args.preprocess: Preprocessor(args.preprocess[0], args.preprocess[1]);
|
||||||
|
+versions = VersionSetDSL(dslContent, threshold=args.threshold)
|
||||||
|
+
|
||||||
|
+if args.sets: print_sets(versions);
|
||||||
|
+elif args.preprocess: Preprocessor(versions, args.preprocess[0], args.preprocess[1]);
|
||||||
|
else:
|
||||||
|
for platform in versions.platforms().keys():
|
||||||
|
if getattr(args, platform, None):
|
||||||
|
--
|
||||||
|
2.45.2
|
||||||
|
|
@ -0,0 +1,99 @@
|
|||||||
|
{
|
||||||
|
lib,
|
||||||
|
stdenvNoCC,
|
||||||
|
appleDerivation',
|
||||||
|
gnused,
|
||||||
|
python3,
|
||||||
|
unifdef,
|
||||||
|
}:
|
||||||
|
|
||||||
|
appleDerivation' stdenvNoCC {
|
||||||
|
nativeBuildInputs = [ unifdef ];
|
||||||
|
|
||||||
|
patches = [ ./0001-Support-setting-an-upper-bound-on-versions.patch ];
|
||||||
|
|
||||||
|
buildPhase = ''
|
||||||
|
runHook preBuild
|
||||||
|
|
||||||
|
declare -a unifdef_sources=(
|
||||||
|
os_availability.modulemap
|
||||||
|
os_availability_private.modulemap
|
||||||
|
AvailabilityPrivate.modulemap
|
||||||
|
)
|
||||||
|
unifdef -x2 -UBUILD_FOR_DRIVERKIT -m $(for x in "''${unifdef_sources[@]}"; do echo templates/$x; done)
|
||||||
|
|
||||||
|
runHook postBuild
|
||||||
|
'';
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
|
||||||
|
mkdir -p "$out/bin" "$out/libexec" "$out/share/availability"
|
||||||
|
|
||||||
|
cp -r availability.dsl templates "$out/share/availability/"
|
||||||
|
|
||||||
|
substitute availability "$out/libexec/availability" \
|
||||||
|
--replace-fail '/usr/bin/env python3' '${lib.getBin python3}/bin/python3' \
|
||||||
|
--replace-fail 'f"{os.path.abspath(os.path.dirname(sys.argv[0]))}/' "\"$out/share/availability/"
|
||||||
|
chmod a+x "$out/libexec/availability"
|
||||||
|
|
||||||
|
cat <<SCRIPT > "$out/bin/gen-headers"
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
declare -a headers=(
|
||||||
|
Availability.h
|
||||||
|
AvailabilityInternal.h
|
||||||
|
AvailabilityInternalLegacy.h
|
||||||
|
AvailabilityMacros.h
|
||||||
|
AvailabilityVersions.h
|
||||||
|
os/availability.h
|
||||||
|
)
|
||||||
|
|
||||||
|
dest=\$2
|
||||||
|
threshold=\$1
|
||||||
|
|
||||||
|
for header in "\''${headers[@]}"; do
|
||||||
|
header_src=\''${header/\//_}
|
||||||
|
mkdir -p "\$(dirname "\$dest/include/\$header")"
|
||||||
|
"$out/libexec/availability" \\
|
||||||
|
--threshold "\$threshold" \\
|
||||||
|
--preprocess "$out/share/availability/templates/\$header_src" "\$dest/include/\$header"
|
||||||
|
done
|
||||||
|
|
||||||
|
# `__ENVIRONMENT_OS_VERSION_MIN_REQUIRED__` is only defined by clang 17+, so define it for older versions.
|
||||||
|
${lib.getExe gnused} -E '/#ifndef __MAC_OS_X_VERSION_MIN_REQUIRED/{
|
||||||
|
i#ifndef __ENVIRONMENT_OS_VERSION_MIN_REQUIRED__
|
||||||
|
i#define __ENVIRONMENT_OS_VERSION_MIN_REQUIRED__ __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
|
||||||
|
i#endif
|
||||||
|
}' \\
|
||||||
|
-i "\$dest/include/AvailabilityInternal.h"
|
||||||
|
|
||||||
|
# Remove macros from newer SDKs because they can confuse some programs about the SDK version.
|
||||||
|
declare -a versionParts=(\''${threshold//./ })
|
||||||
|
if [ "\''${versionParts[0]}" == "10" ]; then
|
||||||
|
sdkMajor=\''${versionParts[1]}
|
||||||
|
sdkMinor=\''${versionParts[2]:-0}
|
||||||
|
for minor in \$(seq \$(("\$sdkMinor" + 1)) 9); do
|
||||||
|
${lib.getExe gnused} \\
|
||||||
|
-E "/VERSION_10_\''${sdkMajor}_\$minor/,/#endif/c\\ */" \\
|
||||||
|
-i "\$dest/include/AvailabilityMacros.h"
|
||||||
|
done
|
||||||
|
for major in \$(seq \$(("\$sdkMajor" + 1)) 15); do
|
||||||
|
${lib.getExe gnused} \\
|
||||||
|
-E "/VERSION_10_\$major/,/#endif/c\\ */" \\
|
||||||
|
-i "\$dest/include/AvailabilityMacros.h"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
cp "$out/share/availability/templates/os_availability.modulemap" "\$dest/include/"
|
||||||
|
SCRIPT
|
||||||
|
chmod a+x "$out/bin/gen-headers"
|
||||||
|
|
||||||
|
patchShebangs "$out/bin"
|
||||||
|
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta.mainProgram = "gen-headers";
|
||||||
|
}
|
@ -10,6 +10,9 @@ let
|
|||||||
# a stdenv out of something like this. With some care we can probably get rid of this, but for
|
# a stdenv out of something like this. With some care we can probably get rid of this, but for
|
||||||
# now it's staying here.
|
# now it's staying here.
|
||||||
versions = {
|
versions = {
|
||||||
|
"macos-14.4" = {
|
||||||
|
AvailabilityVersions = "140.1";
|
||||||
|
};
|
||||||
"macos-14.3" = {
|
"macos-14.3" = {
|
||||||
system_cmds = "970.0.4";
|
system_cmds = "970.0.4";
|
||||||
};
|
};
|
||||||
@ -248,6 +251,7 @@ developerToolsPackages_11_3_1 // macosPackages_11_0_1 // {
|
|||||||
|
|
||||||
inherit (adv_cmds-boot) ps locale;
|
inherit (adv_cmds-boot) ps locale;
|
||||||
architecture = applePackage "architecture" "osx-10.11.6" "sha256-cUKeMx6mOAxBSRHIdfzsrR65Qv86m7+20XvpKqVfwVI=" {};
|
architecture = applePackage "architecture" "osx-10.11.6" "sha256-cUKeMx6mOAxBSRHIdfzsrR65Qv86m7+20XvpKqVfwVI=" {};
|
||||||
|
AvailabilityVersions = applePackage "AvailabilityVersions" "macos-14.4" "sha256-O9/EOsbK5ZXxh6iDSTwGWWrY5GX/viUwdfG3tdvZwcQ=" {};
|
||||||
bsdmake = applePackage "bsdmake" "dev-tools-3.2.6" "sha256-CW8zP5QZMhWTGp+rhrm8oHE/vSLsRlv1VRAGe1OUDmI=" {};
|
bsdmake = applePackage "bsdmake" "dev-tools-3.2.6" "sha256-CW8zP5QZMhWTGp+rhrm8oHE/vSLsRlv1VRAGe1OUDmI=" {};
|
||||||
CarbonHeaders = applePackage "CarbonHeaders" "osx-10.6.2" "sha256-UNaHvxzYzEBnYYuoMLqWUVprZa6Wqn/3XleoSCco050=" {};
|
CarbonHeaders = applePackage "CarbonHeaders" "osx-10.6.2" "sha256-UNaHvxzYzEBnYYuoMLqWUVprZa6Wqn/3XleoSCco050=" {};
|
||||||
CommonCrypto = applePackage "CommonCrypto" "osx-10.12.6" "sha256-FLgODBrfv+XsGaAjddncYAm/BIJJYw6LcwX/z7ncKFM=" {};
|
CommonCrypto = applePackage "CommonCrypto" "osx-10.12.6" "sha256-FLgODBrfv+XsGaAjddncYAm/BIJJYw6LcwX/z7ncKFM=" {};
|
||||||
|
Loading…
Reference in New Issue
Block a user