    public Config buildArchive(OS os, Arch arch, TargetType targetType) throws MojoExecutionException, MojoFailureException {
        getLog().info("Building RoboVM app for: " + os + " (" + arch + ")");
        Config.Builder builder = new Config.Builder();
        File robovmSrcDir = new File(project.getBasedir(), "src/main/robovm");
        if (propertiesFile != null) {
            if (!propertiesFile.exists()) {
                throw new MojoExecutionException("Invalid 'propertiesFile' specified for RoboVM compile: " + propertiesFile);
            }
            try {
                getLog().debug("Including properties file in RoboVM compiler config: " + propertiesFile.getAbsolutePath());
                builder.addProperties(propertiesFile);
            } catch (IOException e) {
                throw new MojoExecutionException("Failed to add properties file to RoboVM config: " + propertiesFile);
            }
        } else {
            File file = new File(robovmSrcDir, "Info.plist");
            if (file.exists()) {
                getLog().debug("Using default properties file: " + file.getAbsolutePath());
                builder.iosInfoPList(file);
            }
        }
        if (configFile != null) {
            if (!configFile.exists()) {
                throw new MojoExecutionException("Invalid 'configFile' specified for RoboVM compile: " + configFile);
            }
            try {
                getLog().debug("Loading config file for RoboVM compiler: " + configFile.getAbsolutePath());
                builder.read(configFile);
            } catch (Exception e) {
                throw new MojoExecutionException("Failed to read RoboVM config file: " + configFile);
            }
        } else {
            File file = new File(robovmSrcDir, "config.xml");
            if (file.exists()) {
                getLog().debug("Using default config file: " + file.getAbsolutePath());
                builder.iosInfoPList(file);
            }
        }
        File osDir = new File(installDir, os.name());
        File archiveDir = new File(new File(osDir, arch.name()), "");
        builder.home(new Config.Home(unpackRoboVMDist()))
                .logger(getRoboVMLogger())
                .mainClass(mainClass)
                .executableName(executableName)
                .tmpDir(archiveDir)
                .targetType(targetType)
                .skipInstall(true)
                .os(os)
                .arch(arch);
        if (forceLinkClasses != null) {
            for (String pattern : forceLinkClasses) {
                getLog().debug("Including class pattern for linking: " + pattern);
                builder.addForceLinkClass(pattern);
            }
        }
        if (frameworks != null) {
            for (String framework : frameworks) {
                getLog().debug("Including framework: " + framework);
                builder.addFramework(framework);
            }
        }
        if (libs != null) {
            for (String lib : libs) {
                getLog().debug("Including lib: " + lib);
                builder.addLib(lib);
            }
        }
        if (iosSdkVersion != null) {
            getLog().debug("Using explicit iOS SDK version: " + iosSdkVersion);
            builder.iosSdkVersion(iosSdkVersion);
        }
        if (iosSignIdentity != null) {
            getLog().debug("Using explicit iOS Signing identity: " + iosSignIdentity);
            builder.iosSignIdentity(iosSignIdentity);
        }
        if (iosInfoPList != null) {
            if (!iosInfoPList.exists()) {
                throw new MojoExecutionException("Invalid 'iosInfoPList' specified for RoboVM compile: " + iosInfoPList);
            }
            getLog().debug("Using Info.plist input file: " + iosInfoPList.getAbsolutePath());
            builder.iosInfoPList(iosInfoPList);
        } else {
            File file = new File(robovmSrcDir, "Info.plist");
            if (file.exists()) {
                getLog().debug("Using default Info.plist input file: " + file.getAbsolutePath());
                builder.iosInfoPList(file);
            }
        }
        if (iosEntitlementsPList != null) {
            if (!iosEntitlementsPList.exists()) {
                throw new MojoExecutionException("Invalid 'iosEntitlementsPList' specified for RoboVM compile: " + iosEntitlementsPList);
            }
            getLog().debug("Using Entitlements.plist input file: " + iosEntitlementsPList.getAbsolutePath());
            builder.iosEntitlementsPList(iosEntitlementsPList);
        } else {
            File file = new File(robovmSrcDir, "Entitlements.plist");
            if (file.exists()) {
                getLog().debug("Using default Entitlements.plist input file: " + file.getAbsolutePath());
                builder.iosEntitlementsPList(file);
            }
        }
        if (iosResourceRulesPList != null) {
            if (!iosResourceRulesPList.exists()) {
                throw new MojoExecutionException("Invalid 'iosResourceRulesPList' specified for RoboVM compile: " + iosResourceRulesPList);
            }
            getLog().debug("Using ResourceRules.plist input file: " + iosResourceRulesPList.getAbsolutePath());
            builder.iosResourceRulesPList(iosResourceRulesPList);
        } else {
            File file = new File(robovmSrcDir, "ResourceRules.plist");
            if (file.exists()) {
                getLog().debug("Using default ResourceRules.plist input file: " + file.getAbsolutePath());
                builder.iosResourceRulesPList(file);
            }
        }
        if (resources != null) {
            for (File resource : resources) {
                if (!resource.exists()) {
                    throw new MojoExecutionException("Invalid 'resource' directory specified for RoboVM compile: " + resource);
                }
                getLog().debug("Including resource directory: " + resource.getAbsolutePath());
                builder.addResource(resource);
            }
        } else {
            File resource = new File(robovmSrcDir, "resources");
            if (resource.exists()) {
                getLog().debug("Using default resource directory: " + resource.getAbsolutePath());
                builder.addResource(resource);
            }
        }
        builder.clearClasspathEntries();
        if (includeJFX) {
            getLog().info("Including JavaFX Runtime in build");
            File jfxJar = resolveJavaFXRuntimeArtifact();
            getLog().debug("JavaFX runtime JAR found at: " + jfxJar);
            builder.addClasspathEntry(jfxJar);
            File iosNativesBaseDir = unpackJavaFXNativeIOSArtifact();
            builder.addLib(new File(iosNativesBaseDir, "libdecora-sse-armv7.a").getAbsolutePath());
            builder.addLib(new File(iosNativesBaseDir, "libglass-armv7.a").getAbsolutePath());
            builder.addLib(new File(iosNativesBaseDir, "libjavafx-font-armv7.a").getAbsolutePath());
            builder.addLib(new File(iosNativesBaseDir, "libjavafx-iio-armv7.a").getAbsolutePath());
            builder.addLib(new File(iosNativesBaseDir, "libprism-common-armv7.a").getAbsolutePath());
            builder.addLib(new File(iosNativesBaseDir, "libprism-es2-armv7.a").getAbsolutePath());
            builder.addLib(new File(iosNativesBaseDir, "libprism-sw-armv7.a").getAbsolutePath());
            builder.addForceLinkClass("com.sun.javafx.tk.quantum.QuantumToolkit");
            builder.addForceLinkClass("com.sun.prism.es2.ES2Pipeline");
            builder.addForceLinkClass("com.sun.prism.es2.IOSGLFactory");
            builder.addForceLinkClass("com.sun.glass.ui.ios.**.*");
            builder.addForceLinkClass("javafx.scene.CssStyleHelper");
            builder.addForceLinkClass("com.sun.prism.shader.**.*");
            builder.addForceLinkClass("com.sun.scenario.effect.impl.es2.ES2ShaderSource");
            builder.addForceLinkClass("sun.util.logging.PlatformLogger");
            builder.addFramework("UIKit");
            builder.addFramework("OpenGLES");
            builder.addFramework("QuartzCore");
            builder.addFramework("CoreGraphics");
            builder.addFramework("CoreText");
            builder.addFramework("ImageIO");
            builder.addFramework("MobileCoreServices");
        }
        try {
            for (Object object : project.getRuntimeClasspathElements()) {
                String path = (String) object;
                if (getLog().isDebugEnabled()) {
                    getLog().debug("Including classpath element for RoboVM app: " + path);
                }
                builder.addClasspathEntry(new File(path));
            }
        } catch (DependencyResolutionRequiredException e) {
            throw new MojoExecutionException("Error resolving application classpath for RoboVM build", e);
        }
        try {
            Config config = builder.build();
            AppCompiler compiler = new AppCompiler(config);
            compiler.compile();
            return config;
        } catch (IOException e) {
            throw new MojoExecutionException("Error building RoboVM executable for app", e);
        }
    }

    public Config buildArchive(OS os, Arch arch, TargetType targetType) throws MojoExecutionException, MojoFailureException {
        getLog().info("Building RoboVM app for: " + os + " (" + arch + ")");
        Config.Builder builder = new Config.Builder();
        File robovmSrcDir = new File(project.getBasedir(), "src/main/robovm");
        if (propertiesFile != null) {
            if (!propertiesFile.exists()) {
                throw new MojoExecutionException("Invalid 'propertiesFile' specified for RoboVM compile: " + propertiesFile);
            }
            try {
                getLog().debug("Including properties file in RoboVM compiler config: " + propertiesFile.getAbsolutePath());
                builder.addProperties(propertiesFile);
            } catch (IOException e) {
                throw new MojoExecutionException("Failed to add properties file to RoboVM config: " + propertiesFile);
            }
        } else {
            File file = new File(robovmSrcDir, "Info.plist");
            if (file.exists()) {
                getLog().debug("Using default properties file: " + file.getAbsolutePath());
                builder.iosInfoPList(file);
            }
        }
        if (configFile != null) {
            if (!configFile.exists()) {
                throw new MojoExecutionException("Invalid 'configFile' specified for RoboVM compile: " + configFile);
            }
            try {
                getLog().debug("Loading config file for RoboVM compiler: " + configFile.getAbsolutePath());
                builder.read(configFile);
            } catch (Exception e) {
                throw new MojoExecutionException("Failed to read RoboVM config file: " + configFile);
            }
        } else {
            File file = new File(robovmSrcDir, "config.xml");
            if (file.exists()) {
                getLog().debug("Using default config file: " + file.getAbsolutePath());
                builder.iosInfoPList(file);
            }
        }
        File osDir = new File(installDir, os.name());
        File archiveDir = new File(new File(osDir, arch.name()), "");
        builder.home(new Config.Home(unpackRoboVMDist()))
                .logger(getRoboVMLogger())
                .mainClass(mainClass)
                .executableName(executableName)
                .tmpDir(archiveDir)
                .targetType(targetType)
                .skipInstall(true)
                .os(os)
                .arch(arch);
        if (forceLinkClasses != null) {
            for (String pattern : forceLinkClasses) {
                getLog().debug("Including class pattern for linking: " + pattern);
                builder.addForceLinkClass(pattern);
            }
        }
        if (frameworks != null) {
            for (String framework : frameworks) {
                getLog().debug("Including framework: " + framework);
                builder.addFramework(framework);
            }
        }
        if (libs != null) {
            for (String lib : libs) {
                getLog().debug("Including lib: " + lib);
                builder.addLib(lib);
            }
        }
        if (iosSdkVersion != null) {
            getLog().debug("Using explicit iOS SDK version: " + iosSdkVersion);
            builder.iosSdkVersion(iosSdkVersion);
        }
        if (iosSignIdentity != null) {
            getLog().debug("Using explicit iOS Signing identity: " + iosSignIdentity);
            builder.iosSignIdentity(iosSignIdentity);
        }
        if (iosInfoPList != null) {
            if (!iosInfoPList.exists()) {
                throw new MojoExecutionException("Invalid 'iosInfoPList' specified for RoboVM compile: " + iosInfoPList);
            }
            getLog().debug("Using Info.plist input file: " + iosInfoPList.getAbsolutePath());
            builder.iosInfoPList(iosInfoPList);
        } else {
            File file = new File(robovmSrcDir, "Info.plist");
            if (file.exists()) {
                getLog().debug("Using default Info.plist input file: " + file.getAbsolutePath());
                builder.iosInfoPList(file);
            }
        }
        if (iosEntitlementsPList != null) {
            if (!iosEntitlementsPList.exists()) {
                throw new MojoExecutionException("Invalid 'iosEntitlementsPList' specified for RoboVM compile: " + iosEntitlementsPList);
            }
            getLog().debug("Using Entitlements.plist input file: " + iosEntitlementsPList.getAbsolutePath());
            builder.iosEntitlementsPList(iosEntitlementsPList);
        } else {
            File file = new File(robovmSrcDir, "Entitlements.plist");
            if (file.exists()) {
                getLog().debug("Using default Entitlements.plist input file: " + file.getAbsolutePath());
                builder.iosEntitlementsPList(file);
            }
        }
        if (iosResourceRulesPList != null) {
            if (!iosResourceRulesPList.exists()) {
                throw new MojoExecutionException("Invalid 'iosResourceRulesPList' specified for RoboVM compile: " + iosResourceRulesPList);
            }
            getLog().debug("Using ResourceRules.plist input file: " + iosResourceRulesPList.getAbsolutePath());
            builder.iosResourceRulesPList(iosResourceRulesPList);
        } else {
            File file = new File(robovmSrcDir, "ResourceRules.plist");
            if (file.exists()) {
                getLog().debug("Using default ResourceRules.plist input file: " + file.getAbsolutePath());
                builder.iosResourceRulesPList(file);
            }
        }
        if (resources != null) {
            for (File resource : resources) {
                if (!resource.exists()) {
                    throw new MojoExecutionException("Invalid 'resource' directory specified for RoboVM compile: " + resource);
                }
                getLog().debug("Including resource directory: " + resource.getAbsolutePath());
                builder.addResource(resource);
            }
        } else {
            File resource = new File(robovmSrcDir, "resources");
            if (resource.exists()) {
                getLog().debug("Using default resource directory: " + resource.getAbsolutePath());
                builder.addResource(resource);
            }
        }
        builder.clearClasspathEntries();
        if (includeJFX) {
            getLog().info("Including JavaFX Runtime in build");
            File jfxJar = resolveJavaFXRuntimeArtifact();
            getLog().debug("JavaFX runtime JAR found at: " + jfxJar);
            builder.addClasspathEntry(jfxJar);
            File iosNativesBaseDir = unpackJavaFXNativeIOSArtifact();
            builder.addLib(new File(iosNativesBaseDir, "libglass-" + arch.getClangName() + ".a").getAbsolutePath());
            builder.addLib(new File(iosNativesBaseDir, "libjavafx-font-" + arch.getClangName() + ".a").getAbsolutePath());
            builder.addLib(new File(iosNativesBaseDir, "libjavafx-iio-" + arch.getClangName() + ".a").getAbsolutePath());
            builder.addLib(new File(iosNativesBaseDir, "libprism-common-" + arch.getClangName() + ".a").getAbsolutePath());
            builder.addLib(new File(iosNativesBaseDir, "libprism-es2-" + arch.getClangName() + ".a").getAbsolutePath());
            builder.addForceLinkClass("com.sun.javafx.tk.quantum.QuantumToolkit");
            builder.addForceLinkClass("com.sun.prism.es2.ES2Pipeline");
            builder.addForceLinkClass("com.sun.prism.es2.IOSGLFactory");
            builder.addForceLinkClass("com.sun.glass.ui.ios.**.*");
            builder.addForceLinkClass("javafx.scene.CssStyleHelper");
            builder.addForceLinkClass("com.sun.prism.shader.**.*");
            builder.addForceLinkClass("com.sun.scenario.effect.impl.es2.ES2ShaderSource");
            builder.addForceLinkClass("com.sun.javafx.font.coretext.CTFactory");
            builder.addForceLinkClass("sun.util.logging.PlatformLogger");
            builder.addFramework("UIKit");
            builder.addFramework("OpenGLES");
            builder.addFramework("QuartzCore");
            builder.addFramework("CoreGraphics");
            builder.addFramework("CoreText");
            builder.addFramework("ImageIO");
            builder.addFramework("MobileCoreServices");
        }
        try {
            for (Object object : project.getRuntimeClasspathElements()) {
                String path = (String) object;
                if (getLog().isDebugEnabled()) {
                    getLog().debug("Including classpath element for RoboVM app: " + path);
                }
                builder.addClasspathEntry(new File(path));
            }
        } catch (DependencyResolutionRequiredException e) {
            throw new MojoExecutionException("Error resolving application classpath for RoboVM build", e);
        }
        try {
            Config config = builder.build();
            AppCompiler compiler = new AppCompiler(config);
            compiler.compile();
            return config;
        } catch (IOException e) {
            throw new MojoExecutionException("Error building RoboVM executable for app", e);
        }
    }
