org.robovm.compiler.util.XCFrameworkPlist Maven / Gradle / Ivy
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.robovm.compiler.util;
import com.dd.plist.NSArray;
import com.dd.plist.NSDictionary;
import com.dd.plist.NSObject;
import com.dd.plist.PropertyListParser;
import org.robovm.compiler.config.CpuArch;
import org.robovm.compiler.config.Environment;
import org.robovm.compiler.config.OS;
import java.io.File;
import java.io.IOException;
import java.util.*;
/**
* Reads/Writes .xcframework/Info.plist
*/
public class XCFrameworkPlist {
private static final String KEY_AVAILABLE_LIBRARIES = "AvailableLibraries";
private static final String KEY_LIBRARY_IDENTIFIER = "LibraryIdentifier";
private static final String KEY_LIBRARY_PATH = "LibraryPath";
private static final String KEY_SUPPORTED_ARCHITECTURES = "SupportedArchitectures";
private static final String KEY_SUPPORTED_PLATFORM = "SupportedPlatform";
private static final String KEY_SUPPORTED_PLATFORM_VARIANT = "SupportedPlatformVariant";
private static final String KEY_DEBUG_SYMBOLS_PATH = "DebugSymbolsPath";
private static final String KEY_CFBUNDLE_PACKAGE_TYPE = "CFBundlePackageType";
private static final String KEY_XCFRAMEWORK_FORMAT_VERSION = "XCFrameworkFormatVersion";
private final Library[] availableLibraries;
public XCFrameworkPlist(Library[] availableLibraries) {
this.availableLibraries = availableLibraries;
}
public Library[] getAvailableLibraries() {
return availableLibraries;
}
public static class Library {
private final String identifier;
private final String path;
private final OS platform;
private final CpuArch[] supportedArchitectures;
private final Environment variant;
private final String debugSymbolPath;
public Library(String identifier, String path, OS platform, CpuArch[] supportedArchitectures,
Environment variant, String debugSymbolPath) {
this.identifier = identifier;
this.path = path;
this.platform = platform;
this.supportedArchitectures = supportedArchitectures;
this.variant = variant;
this.debugSymbolPath = debugSymbolPath;
}
public String getIdentifier() {
return identifier;
}
public String getPath() {
return path;
}
public OS getPlatform() {
return platform;
}
public CpuArch[] getSupportedArchitectures() {
return supportedArchitectures;
}
public Environment getVariant() {
return variant;
}
public boolean supportCpuArch(CpuArch cpuArch) {
for (CpuArch c: supportedArchitectures)
if (c == cpuArch) return true;
return false;
}
}
public static class Builder {
private final List libraries = new ArrayList<>();
public Builder addLibrary(Library lib) {
libraries.add(lib);
return this;
}
public XCFrameworkPlist build() {
return new XCFrameworkPlist(libraries.toArray(new Library[0]));
}
}
/**
* Builds plist and writes to file
*/
public void writeTo(File infoPlistFile) throws IOException {
// construct plist object
NSDictionary plist = new NSDictionary();
if (availableLibraries.length > 0) {
NSArray arrayLibs = new NSArray(availableLibraries.length);
for (int libIdx = 0; libIdx < availableLibraries.length; libIdx++) {
Library lib = availableLibraries[libIdx];
NSDictionary dictLib = new NSDictionary();
dictLib.put(KEY_LIBRARY_IDENTIFIER, lib.identifier);
dictLib.put(KEY_LIBRARY_PATH, lib.path);
dictLib.put(KEY_SUPPORTED_PLATFORM, lib.platform.toString());
if (lib.variant != Environment.Native)
dictLib.put(KEY_SUPPORTED_PLATFORM_VARIANT, lib.variant.getLlvmName());
if (lib.debugSymbolPath != null)
dictLib.put(KEY_DEBUG_SYMBOLS_PATH, lib.debugSymbolPath);
NSArray arrayArches = new NSArray(lib.supportedArchitectures.length);
for (int archIdx = 0; archIdx < lib.supportedArchitectures.length; archIdx++)
arrayArches.setValue(archIdx, lib.supportedArchitectures[archIdx].getClangName());
dictLib.put(KEY_SUPPORTED_ARCHITECTURES, arrayArches);
arrayLibs.setValue(libIdx, dictLib);
}
plist.put(KEY_AVAILABLE_LIBRARIES, arrayLibs);
plist.put(KEY_CFBUNDLE_PACKAGE_TYPE, "XFWK");
plist.put(KEY_XCFRAMEWORK_FORMAT_VERSION, "1.0");
}
PropertyListParser.saveAsXML(plist, infoPlistFile);
}
/**
* Parses XCFramework structure from plist
*/
public static XCFrameworkPlist loadPlist(File f) throws IOException {
try {
List libraries = new ArrayList<>();
NSDictionary plist = (NSDictionary) PropertyListParser.parse(f);
NSArray arrayLibs = (NSArray) plist.get(KEY_AVAILABLE_LIBRARIES);
for (NSObject o: arrayLibs.getArray()) {
// if something failed -- just ignore the entry
try {
// pick values
NSDictionary dictLib = (NSDictionary) o;
String identifier = dictLib.get(KEY_LIBRARY_IDENTIFIER).toString();
String libraryPath = dictLib.get(KEY_LIBRARY_PATH).toString();
String supportedPlatform = dictLib.get(KEY_SUPPORTED_PLATFORM).toString();
String supportedPlatformVariant = toStringOrNull(dictLib.get(KEY_SUPPORTED_PLATFORM_VARIANT));
String debugSymbolsPath = toStringOrNull(dictLib.get(KEY_DEBUG_SYMBOLS_PATH));
NSArray arrayArches = (NSArray) dictLib.get(KEY_SUPPORTED_ARCHITECTURES);
// parse
OS os = OS.valueOf(supportedPlatform);
Environment env = supportedPlatformVariant != null ? Environment.parse(supportedPlatformVariant)
: Environment.Native;
Set arches = new LinkedHashSet<>();
for (NSObject archO: arrayArches.getArray()) {
CpuArch arch = parse(archO.toString());
if (arch != null)
arches.add(arch);
}
// if there are all object add library
if (!arches.isEmpty())
libraries.add(new Library(identifier, libraryPath, os, arches.toArray(new CpuArch[0]), env,
debugSymbolsPath));
} catch (Throwable ignored) {
}
}
return new XCFrameworkPlist(libraries.toArray(new Library[0]));
} catch (IOException e) {
throw e;
} catch (Throwable t) {
throw new IOException(t);
}
}
/**
* Parses XCFramework structure from .xcframework directory
*/
public static XCFrameworkPlist load(File xcFramework) throws IOException {
return loadPlist(new File(xcFramework, "Info.plist"));
}
private static CpuArch parse(String s) {
for (CpuArch v: CpuArch.values())
if (s.equals(v.getClangName()))
return v;
return null;
}
private static String toStringOrNull(Object o) {
return o != null ? o.toString() : null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy