use of org.robovm.compiler.config.Arch in project robovm by robovm.
the class AppCompiler method main.
public static void main(String[] args) throws IOException {
AppCompiler compiler = null;
Config.Builder builder = null;
boolean verbose = false;
boolean run = false;
boolean archive = false;
List<Arch> archs = new ArrayList<>();
String dumpConfigFile = null;
List<String> runArgs = new ArrayList<String>();
try {
builder = new Config.Builder();
Map<String, PluginArgument> pluginArguments = builder.fetchPluginArguments();
int i = 0;
while (i < args.length) {
if ("-cp".equals(args[i]) || "-classpath".equals(args[i])) {
for (String p : args[++i].split(File.pathSeparator)) {
builder.addClasspathEntry(new File(p));
}
} else if ("-bcp".equals(args[i]) || "-bootcp".equals(args[i]) || "-bootclasspath".equals(args[i])) {
for (String p : args[++i].split(File.pathSeparator)) {
builder.addBootClasspathEntry(new File(p));
}
} else if ("-jar".equals(args[i])) {
builder.mainJar(new File(args[++i]));
} else if ("-o".equals(args[i])) {
builder.executableName(args[++i]);
} else if ("-d".equals(args[i])) {
builder.installDir(new File(args[++i]));
} else if ("-cache".equals(args[i])) {
builder.cacheDir(new File(args[++i]));
} else if ("-home".equals(args[i])) {
builder.home(new Config.Home(new File(args[++i])));
} else if ("-tmp".equals(args[i])) {
builder.tmpDir(new File(args[++i]));
} else if ("-threads".equals(args[i])) {
String s = args[++i];
try {
int n = Integer.parseInt(s);
// Make sure n > 0 and cap at 128 threads.
n = Math.max(n, 1);
n = Math.min(n, 128);
builder.threads(n);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Unparsable thread count: " + s);
}
} else if ("-run".equals(args[i])) {
run = true;
} else if ("-verbose".equals(args[i])) {
verbose = true;
} else if ("-config".equals(args[i])) {
builder.read(new File(args[++i]));
} else if ("-dumpconfig".equals(args[i])) {
dumpConfigFile = args[++i];
} else if ("-properties".equals(args[i])) {
builder.addProperties(new File(args[++i]));
} else if (args[i].startsWith("-P")) {
int index = args[i].indexOf('=');
if (index <= 0) {
throw new IllegalArgumentException("Malformed property: " + args[i]);
}
String name = args[i].substring(2, index);
String value = args[i].substring(index + 1);
builder.addProperty(name, value);
} else if ("-debug".equals(args[i])) {
builder.debug(true);
} else if ("-use-debug-libs".equals(args[i])) {
builder.useDebugLibs(true);
} else if ("-dump-intermediates".equals(args[i])) {
builder.dumpIntermediates(true);
} else if ("-dynamic-jni".equals(args[i])) {
// TODO: Old option not used any longer. We still accept it
// for now. Delete it in a future release.
} else if ("-skiprt".equals(args[i])) {
builder.skipRuntimeLib(true);
} else if ("-skipsign".equals(args[i])) {
builder.iosSkipSigning(true);
} else if ("-clean".equals(args[i])) {
builder.clean(true);
} else if ("-help".equals(args[i]) || "-?".equals(args[i])) {
printUsageAndExit(null, builder.getPlugins());
} else if ("-version".equals(args[i])) {
printVersionAndExit();
} else if ("-cc".equals(args[i])) {
builder.ccBinPath(new File(args[++i]));
} else if ("-os".equals(args[i])) {
String s = args[++i];
builder.os("auto".equals(s) ? null : OS.valueOf(s));
} else if ("-arch".equals(args[i])) {
String s = args[++i];
if (!"auto".equals(s)) {
archs.add(Arch.valueOf(s));
}
} else if ("-archs".equals(args[i])) {
for (String s : args[++i].split(":")) {
if (!"auto".equals(s)) {
archs.add(Arch.valueOf(s));
}
}
// } else if ("-cpu".equals(args[i])) {
// builder.cpu(args[++i]);
} else if ("-target".equals(args[i])) {
String s = args[++i];
builder.targetType("auto".equals(s) ? null : s);
} else if ("-treeshaker".equals(args[i])) {
String s = args[++i];
builder.treeShakerMode(TreeShakerMode.valueOf(s));
} else if ("-forcelinkclasses".equals(args[i])) {
for (String p : args[++i].split(":")) {
p = p.replace('#', '*');
builder.addForceLinkClass(p);
}
} else if ("-libs".equals(args[i])) {
for (String p : args[++i].split(":")) {
builder.addLib(new Config.Lib(p, true));
}
} else if ("-exportedsymbols".equals(args[i])) {
for (String p : args[++i].split(":")) {
builder.addExportedSymbol(p);
}
} else if ("-unhidesymbols".equals(args[i])) {
for (String p : args[++i].split(":")) {
builder.addUnhideSymbol(p);
}
} else if ("-frameworks".equals(args[i])) {
for (String p : args[++i].split(":")) {
builder.addFramework(p);
}
} else if ("-weakframeworks".equals(args[i])) {
for (String p : args[++i].split(":")) {
builder.addWeakFramework(p);
}
} else if ("-resources".equals(args[i])) {
for (String p : args[++i].split(":")) {
if (AntPathMatcher.isPattern(p)) {
File dir = new File(AntPathMatcher.rtrimWildcardTokens(p));
String pattern = AntPathMatcher.extractPattern(p);
builder.addResource(new Resource(dir, null).include(pattern));
} else {
builder.addResource(new Resource(new File(p)));
}
}
} else if ("-cacerts".equals(args[i])) {
String name = args[++i];
Config.Cacerts cacerts = null;
if (!"none".equals(name)) {
try {
cacerts = Config.Cacerts.valueOf(name);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("Illegal -cacerts value: " + name);
}
}
builder.cacerts(cacerts);
} else if ("-plist".equals(args[i])) {
builder.infoPList(new File(args[++i]));
} else if ("-entitlements".equals(args[i])) {
builder.iosEntitlementsPList(new File(args[++i]));
} else if ("-signidentity".equals(args[i])) {
builder.iosSignIdentity(SigningIdentity.find(SigningIdentity.list(), args[++i]));
} else if ("-provisioningprofile".equals(args[i])) {
builder.iosProvisioningProfile(ProvisioningProfile.find(ProvisioningProfile.list(), args[++i]));
} else if ("-sdk".equals(args[i])) {
builder.iosSdkVersion(args[++i]);
} else if ("-printdevicetypes".equals(args[i])) {
printDeviceTypesAndExit();
} else if ("-devicetype".equals(args[i])) {
builder.iosDeviceType(args[++i]);
} else if ("-archive".equals(args[i])) {
archive = true;
} else if ("-createipa".equals(args[i])) {
archive = true;
} else if ("-ipaarchs".equals(args[i])) {
for (String s : args[++i].split(":")) {
if (!"auto".equals(s)) {
archs.add(Arch.valueOf(s));
}
}
} else if (args[i].startsWith("-D")) {
} else if (args[i].startsWith("-X")) {
} else if (args[i].startsWith("-rvm:")) {
runArgs.add(args[i]);
} else if (args[i].startsWith("-")) {
String argName = args[i].substring(1, args[i].length());
if (argName.contains("=")) {
argName = argName.substring(0, argName.indexOf('='));
}
PluginArgument arg = pluginArguments.get(argName);
if (arg != null) {
builder.addPluginArgument(args[i].substring(1));
} else {
throw new IllegalArgumentException("Unrecognized option: " + args[i]);
}
} else {
builder.mainClass(args[i++]);
break;
}
i++;
}
builder.archs(archs.toArray(new Arch[archs.size()]));
while (i < args.length) {
runArgs.add(args[i++]);
}
if (archive && run) {
throw new IllegalArgumentException("Specify either -run or -createipa/-archive, not both");
}
builder.logger(new ConsoleLogger(verbose));
builder.skipInstall(run);
if (dumpConfigFile != null) {
if (dumpConfigFile.equals("-")) {
builder.write(new OutputStreamWriter(System.out), new File("."));
} else {
File file = new File(dumpConfigFile);
if (file.exists()) {
throw new IllegalArgumentException("Cannot dump config to " + file.getAbsolutePath() + ". The file already exists.");
}
builder.write(file);
}
return;
}
compiler = new AppCompiler(builder.build());
} catch (Throwable t) {
String message = t.getMessage();
if (t instanceof ArrayIndexOutOfBoundsException) {
message = "Missing argument";
}
if (t instanceof IndexOutOfBoundsException) {
message = "Missing argument";
}
if (verbose && !(t instanceof StringIndexOutOfBoundsException) && !(t instanceof IllegalArgumentException)) {
t.printStackTrace();
}
printUsageAndExit(message, builder != null ? builder.getPlugins() : null);
}
try {
if (archive) {
compiler.build();
compiler.archive();
} else {
if (run && !compiler.config.getTarget().canLaunch()) {
throw new IllegalArgumentException("Cannot launch when building " + compiler.config.getTarget().getType() + " binaries");
}
if (run) {
// Just compile the first slice if multiple archs have been specified
compiler.compile();
LaunchParameters launchParameters = compiler.config.getTarget().createLaunchParameters();
if (launchParameters instanceof IOSSimulatorLaunchParameters) {
IOSSimulatorLaunchParameters simParams = (IOSSimulatorLaunchParameters) launchParameters;
String deviceName = null;
String sdkVersion = null;
if (compiler.config.getIosDeviceType() != null) {
String[] parts = compiler.config.getIosDeviceType().split("[:;, ]+");
deviceName = parts[0].trim();
sdkVersion = parts.length > 1 ? parts[1].trim() : null;
}
DeviceType type = DeviceType.getBestDeviceType(compiler.config.getArch(), null, deviceName, sdkVersion);
simParams.setDeviceType(type);
}
launchParameters.setArguments(runArgs);
compiler.launch(launchParameters);
} else {
compiler.build();
compiler.config.getTarget().install();
}
}
} catch (Throwable t) {
String message = t.getMessage();
if (verbose && !(t instanceof ExecuteException)) {
t.printStackTrace();
}
printUsageAndExit(message, builder.getPlugins());
}
}
use of org.robovm.compiler.config.Arch in project robovm by robovm.
the class Linker method link.
public void link(Set<Clazz> classes) throws IOException {
for (CompilerPlugin plugin : config.getCompilerPlugins()) {
plugin.beforeLinker(config, this, classes);
}
Arch arch = config.getArch();
OS os = config.getOs();
Set<Clazz> linkClasses = new TreeSet<Clazz>(classes);
config.getLogger().info("Linking %d classes (%s %s %s)", linkClasses.size(), os, arch, config.isDebug() ? "debug" : "release");
ModuleBuilder mb = new ModuleBuilder();
mb.addInclude(getClass().getClassLoader().getResource(String.format("header-%s-%s.ll", os.getFamily(), arch)));
mb.addInclude(getClass().getClassLoader().getResource("header.ll"));
mb.addGlobal(new Global("_bcRuntimeData", runtimeDataToBytes()));
ArrayConstantBuilder staticLibs = new ArrayConstantBuilder(I8_PTR);
for (Config.Lib lib : config.getLibs()) {
String p = lib.getValue();
if (p.endsWith(".a")) {
p = new File(p).getName();
String libName = p.substring(0, p.length() - 2);
if (libName.startsWith("lib")) {
libName = libName.substring(3);
}
staticLibs.add(mb.getString(libName));
}
}
staticLibs.add(new NullConstant(Type.I8_PTR));
mb.addGlobal(new Global("_bcStaticLibs", new ConstantGetelementptr(mb.newGlobal(staticLibs.build()).ref(), 0, 0)));
HashTableGenerator<String, Constant> bcpHashGen = new HashTableGenerator<String, Constant>(new ModifiedUtf8HashFunction());
HashTableGenerator<String, Constant> cpHashGen = new HashTableGenerator<String, Constant>(new ModifiedUtf8HashFunction());
int classCount = 0;
Map<ClazzInfo, TypeInfo> typeInfos = new HashMap<ClazzInfo, TypeInfo>();
for (Clazz clazz : linkClasses) {
TypeInfo typeInfo = new TypeInfo();
typeInfo.clazz = clazz;
typeInfo.id = classCount++;
typeInfos.put(clazz.getClazzInfo(), typeInfo);
StructureConstant infoErrorStruct = createClassInfoErrorStruct(mb, clazz.getClazzInfo());
Global info = null;
if (infoErrorStruct == null) {
info = new Global(Symbols.infoStructSymbol(clazz.getInternalName()), external, I8_PTR, false);
} else {
typeInfo.error = true;
info = new Global(Symbols.infoStructSymbol(clazz.getInternalName()), infoErrorStruct);
}
mb.addGlobal(info);
if (clazz.isInBootClasspath()) {
bcpHashGen.put(clazz.getInternalName(), new ConstantBitcast(info.ref(), I8_PTR));
} else {
cpHashGen.put(clazz.getInternalName(), new ConstantBitcast(info.ref(), I8_PTR));
}
}
mb.addGlobal(new Global("_bcBootClassesHash", new ConstantGetelementptr(mb.newGlobal(bcpHashGen.generate(), true).ref(), 0, 0)));
mb.addGlobal(new Global("_bcClassesHash", new ConstantGetelementptr(mb.newGlobal(cpHashGen.generate(), true).ref(), 0, 0)));
ArrayConstantBuilder bootClasspathValues = new ArrayConstantBuilder(I8_PTR);
ArrayConstantBuilder classpathValues = new ArrayConstantBuilder(I8_PTR);
List<Path> allPaths = new ArrayList<Path>();
allPaths.addAll(config.getClazzes().getPaths());
allPaths.addAll(config.getResourcesPaths());
for (Path path : allPaths) {
String entryName = null;
if (config.isSkipInstall() && config.getTarget().canLaunchInPlace()) {
entryName = path.getFile().getAbsolutePath();
} else {
entryName = config.getTarget().getInstallRelativeArchivePath(path);
}
if (path.isInBootClasspath()) {
bootClasspathValues.add(mb.getString(entryName));
} else {
classpathValues.add(mb.getString(entryName));
}
}
bootClasspathValues.add(new NullConstant(Type.I8_PTR));
classpathValues.add(new NullConstant(Type.I8_PTR));
mb.addGlobal(new Global("_bcBootclasspath", new ConstantGetelementptr(mb.newGlobal(bootClasspathValues.build()).ref(), 0, 0)));
mb.addGlobal(new Global("_bcClasspath", new ConstantGetelementptr(mb.newGlobal(classpathValues.build()).ref(), 0, 0)));
if (config.getMainClass() != null) {
mb.addGlobal(new Global("_bcMainClass", mb.getString(config.getMainClass())));
}
ModuleBuilder[] mbs = new ModuleBuilder[config.getThreads() + 1];
FunctionRef[] stubRefs = new FunctionRef[mbs.length];
ArrayConstantBuilder stubRefsArray = new ArrayConstantBuilder(I8_PTR);
mbs[0] = mb;
for (int i = 1; i < mbs.length; i++) {
mbs[i] = new ModuleBuilder();
mbs[i].addInclude(getClass().getClassLoader().getResource(String.format("header-%s-%s.ll", os.getFamily(), arch)));
mbs[i].addInclude(getClass().getClassLoader().getResource("header.ll"));
Function fn = new FunctionBuilder("_stripped_method" + i, new FunctionType(VOID, ENV_PTR)).linkage(external).build();
call(fn, BC_THROW_NO_SUCH_METHOD_ERROR, fn.getParameterRef(0), mbs[i].getString("Method has been stripped out of the executable"));
fn.add(new Unreachable());
mbs[i].addFunction(fn);
mb.addFunctionDeclaration(new FunctionDeclaration(fn.ref()));
stubRefs[i] = fn.ref();
stubRefsArray.add(new ConstantBitcast(fn.ref(), I8_PTR));
}
stubRefsArray.add(new NullConstant(I8_PTR));
mb.addGlobal(new Global("_bcStrippedMethodStubs", stubRefsArray.build()));
Random rnd = new Random();
buildTypeInfos(typeInfos);
Set<String> checkcasts = new HashSet<>();
Set<String> instanceofs = new HashSet<>();
Set<String> invokes = new HashSet<>();
for (Clazz clazz : linkClasses) {
ClazzInfo ci = clazz.getClazzInfo();
checkcasts.addAll(ci.getCheckcasts());
instanceofs.addAll(ci.getInstanceofs());
invokes.addAll(ci.getInvokes());
}
Set<String> reachableMethods = new HashSet<>();
for (Triple<String, String, String> node : config.getDependencyGraph().findReachableMethods()) {
reachableMethods.add(node.getLeft() + "." + node.getMiddle() + node.getRight());
}
int totalMethodCount = 0;
int reachableMethodCount = 0;
for (Clazz clazz : linkClasses) {
int mbIdx = rnd.nextInt(mbs.length - 1) + 1;
ClazzInfo ci = clazz.getClazzInfo();
// symbols errors.
for (MethodInfo mi : ci.getMethods()) {
if (!mi.isAbstract()) {
totalMethodCount++;
if (!reachableMethods.contains(clazz.getInternalName() + "." + mi.getName() + mi.getDesc())) {
createStrippedMethodStub(stubRefs[mbIdx], mbs[mbIdx], clazz, mi);
} else {
reachableMethodCount++;
}
}
}
TypeInfo typeInfo = typeInfos.get(ci);
if (typeInfo.error) {
// Add an empty TypeInfo
mb.addGlobal(new Global(Symbols.typeInfoSymbol(clazz.getInternalName()), new StructureConstantBuilder().add(new IntegerConstant(typeInfo.id)).add(new IntegerConstant(0)).add(new IntegerConstant(-1)).add(new IntegerConstant(0)).add(new IntegerConstant(0)).build()));
} else {
int[] classIds = new int[typeInfo.classTypes.length];
for (int i = 0; i < typeInfo.classTypes.length; i++) {
classIds[i] = typeInfo.classTypes[i].id;
}
int[] interfaceIds = new int[typeInfo.interfaceTypes.length];
for (int i = 0; i < typeInfo.interfaceTypes.length; i++) {
interfaceIds[i] = typeInfo.interfaceTypes[i].id;
}
mb.addGlobal(new Global(Symbols.typeInfoSymbol(clazz.getInternalName()), new StructureConstantBuilder().add(new IntegerConstant(typeInfo.id)).add(new IntegerConstant((typeInfo.classTypes.length - 1) * 4 + 5 * 4)).add(new IntegerConstant(-1)).add(new IntegerConstant(typeInfo.classTypes.length)).add(new IntegerConstant(typeInfo.interfaceTypes.length)).add(new ArrayConstantBuilder(I32).add(classIds).build()).add(new ArrayConstantBuilder(I32).add(interfaceIds).build()).build()));
if (!config.isDebug() && !ci.isInterface() && !ci.isFinal() && typeInfo.children.isEmpty()) {
// which doesn't do any lookup.
for (MethodInfo mi : ci.getMethods()) {
String name = mi.getName();
if (!name.equals("<clinit>") && !name.equals("<init>") && !mi.isPrivate() && !mi.isStatic() && !mi.isFinal() && !mi.isAbstract()) {
if (invokes.contains(clazz.getInternalName() + "." + name + mi.getDesc())) {
if (reachableMethods.contains(clazz.getInternalName() + "." + name + mi.getDesc())) {
mbs[mbIdx].addFunction(createLookup(mbs[mbIdx], ci, mi));
}
}
}
}
}
}
if (checkcasts.contains(clazz.getInternalName())) {
mbs[mbIdx].addFunction(createCheckcast(mbs[mbIdx], clazz, typeInfo));
}
if (instanceofs.contains(clazz.getInternalName())) {
mbs[mbIdx].addFunction(createInstanceof(mbs[mbIdx], clazz, typeInfo));
}
}
config.getLogger().info("%d methods out of %d included in the executable", reachableMethodCount, totalMethodCount);
List<File> objectFiles = new ArrayList<File>();
generateMachineCode(config, mbs, objectFiles);
for (Clazz clazz : linkClasses) {
objectFiles.add(config.getOFile(clazz));
}
/*
* Assemble the lines files for all linked classes into the module.
*/
for (Clazz clazz : linkClasses) {
File f = config.getLinesOFile(clazz);
if (f.exists() && f.length() > 0) {
objectFiles.add(f);
}
}
config.getTarget().build(objectFiles);
}
use of org.robovm.compiler.config.Arch in project robovm by robovm.
the class RamDiskTools method cleanCache.
private void cleanCache(FileStore store, File volume, Config config) throws IOException {
OS currOs = config.getOs();
Arch currArch = config.getArch();
CacheDir currCacheDir = constructCacheDir(volume, currOs, currArch, config.isDebug());
// Enumerate all directories that are not our current cache
// dir
List<CacheDir> cacheDirs = new ArrayList<CacheDir>();
for (OS os : OS.values()) {
for (Arch arch : Arch.values()) {
for (boolean isDebug : new boolean[] { false, true }) {
CacheDir cacheDir = constructCacheDir(volume, os, arch, isDebug);
if (cacheDir != null && !cacheDir.directory.equals(currCacheDir.directory)) {
cacheDirs.add(cacheDir);
}
}
}
}
// sort the directories by their last modified
// date in ascending order (oldest first). We
// start deleting the oldest cache files first
// before we start deleting the cache files for
// the current os/arch
Collections.sort(cacheDirs, new Comparator<CacheDir>() {
@Override
public int compare(CacheDir o1, CacheDir o2) {
return new Date(o1.lastModified).compareTo(new Date(o2.lastModified));
}
});
// exists. This way we delete its cache files last
if (currCacheDir != null) {
cacheDirs.add(currCacheDir);
}
// space
for (CacheDir dir : cacheDirs) {
for (File file : dir.objFiles) {
file.delete();
if (store.getUsableSpace() > MIN_FREE_SPACE) {
return;
}
}
}
// nuclear option, we couldn't delete enough files
FileUtils.deleteDirectory(new File(volume, "cache"));
}
use of org.robovm.compiler.config.Arch in project robovm by robovm.
the class AppCompiler method build.
/**
* Builds the binary (possibly a fat binary with multiple archs).
*/
public void build() throws IOException {
List<Arch> archs = this.config.getArchs();
if (archs.isEmpty()) {
archs = config.getTarget().getDefaultArchs();
}
if (archs.isEmpty()) {
throw new IllegalArgumentException("No archs specified in config");
}
if (archs.size() == 1 && this.config.getArch().equals(archs.get(0))) {
// No need to clone configs for each slice.
compile();
} else {
Map<Arch, File> slices = new TreeMap<>();
for (Arch arch : archs) {
this.config.getLogger().info("Building %s slice", arch);
Config sliceConfig = this.config.builder().arch(arch).tmpDir(new File(this.config.getTmpDir(), arch.toString())).build();
new AppCompiler(sliceConfig).compile();
slices.put(arch, new File(sliceConfig.getTmpDir(), sliceConfig.getExecutableName()));
for (Path path : sliceConfig.getResourcesPaths()) {
if (!this.config.getResourcesPaths().contains(path)) {
this.config.addResourcesPath(path);
}
}
}
this.config.getTarget().buildFat(slices);
}
}
use of org.robovm.compiler.config.Arch in project robovm by robovm.
the class ToolchainUtil method lipoRemoveArchs.
public static void lipoRemoveArchs(Config config, File inFile, File outFile, Arch... archs) throws IOException {
List<Object> args = new ArrayList<>();
args.add(inFile);
for (Arch arch : archs) {
args.add("-remove");
args.add(arch.getClangName());
}
args.add("-output");
args.add(outFile);
new Executor(Logger.NULL_LOGGER, getLipo()).args(args).exec();
}
Aggregations