Example #1
0
def buildApp():
    # ----------------------
    # Under Windows, we're just going to grab the xulrunner-stub.exe and run Resource Hacker
    # to rename it to "Kylo", set the icon, and set some version info, etc.
    reshack_temp_dir = os.path.join(Settings.prefs.build_dir, "stub")
    if not os.path.exists(reshack_temp_dir):
        os.makedirs(reshack_temp_dir)
    
    build_stub.main(Settings.config.get('App','Version'), 
                    Settings.config.get('App','BuildID'), 
                    temp_dir = reshack_temp_dir, 
                    stub_dir = os.path.join(Settings.prefs.build_dir, "application"))
    
    # ----------------------
    # We also need mozilla DLLS
    for lib in ["mozcrt19.dll", "mozutils.dll", "gkmedias.dll"]:
        f = os.path.join(Settings.prefs.xul_dir, lib)
        if (os.path.isfile(f)):
            shutil.copy2(f, os.path.join(Settings.prefs.build_dir, "application"))

    # ----------------------
    # Now let's grab the XULRunner directory and drop it in to our working application directory
    xulrunner_dir = os.path.join(Settings.prefs.build_dir, "application", "xulrunner")
    if not os.path.exists(xulrunner_dir):
        os.makedirs(xulrunner_dir)
        
    build_util.syncDirs(Settings.prefs.xul_dir, xulrunner_dir, exclude=["xulrunner-stub.exe"])
def buildApp():
    # ----------------------
    # Under Windows, we're just going to grab the xulrunner-stub.exe and run Resource Hacker
    # to rename it to "Kylo", set the icon, and set some version info, etc.
    reshack_temp_dir = os.path.join(Settings.prefs.build_dir, "stub")
    if not os.path.exists(reshack_temp_dir):
        os.makedirs(reshack_temp_dir)

    build_stub.main(Settings.config.get('App', 'Version'),
                    Settings.config.get('App', 'BuildID'),
                    temp_dir=reshack_temp_dir,
                    stub_dir=os.path.join(Settings.prefs.build_dir,
                                          "application"))

    # ----------------------
    # We also need mozilla DLLS
    for lib in ["mozcrt19.dll", "mozutils.dll", "gkmedias.dll"]:
        f = os.path.join(Settings.prefs.xul_dir, lib)
        if (os.path.isfile(f)):
            shutil.copy2(f,
                         os.path.join(Settings.prefs.build_dir, "application"))

    # ----------------------
    # Now let's grab the XULRunner directory and drop it in to our working application directory
    xulrunner_dir = os.path.join(Settings.prefs.build_dir, "application",
                                 "xulrunner")
    if not os.path.exists(xulrunner_dir):
        os.makedirs(xulrunner_dir)

    build_util.syncDirs(Settings.prefs.xul_dir,
                        xulrunner_dir,
                        exclude=["xulrunner-stub.exe"])
def buildApp():
    # ----------------------
    # Under Linux, we're just going to grab the xulrunner-stub and rename it Kylo
    appDir = os.path.join(Settings.prefs.build_dir, "application")
    shutil.copy2(os.path.join(Settings.prefs.xul_dir, "xulrunner-stub"), appDir)
    
    # ----------------------
    # We also need mozilla DLLS
    for lib in ["mozcrt19.so", "mozutils.so", "gkmedias.so"]:
        f = os.path.join(Settings.prefs.xul_dir, lib)
        if (os.path.isfile(f)):
            shutil.copy2(f, appDir)

    # ----------------------
    # Now let's grab the XULRunner directory and drop it in to our working application directory
    xulrunner_dir = os.path.join(Settings.prefs.build_dir, "application", "xulrunner")
    if not os.path.exists(xulrunner_dir):
        os.makedirs(xulrunner_dir)
        
    build_util.syncDirs(Settings.prefs.xul_dir, xulrunner_dir, exclude=["xulrunner-stub"])
Example #4
0
def build():
    """Build Kylo according to program inputs"""

    # Update the build and dist directories to include platform info and product id
    Settings.prefs.build_dir = os.path.normpath(
        os.path.join(Settings.prefs.build_dir, Settings.platform,
                     Settings.config.get('App', 'ProdID')))
    Settings.prefs.dist_dir = os.path.normpath(
        os.path.join(Settings.prefs.dist_dir, Settings.platform,
                     Settings.config.get('App', 'ProdID')))

    # Set the path to the selected version of the XULRunner runtime
    Settings.prefs.xul_dir = os.path.abspath(
        os.path.join(Settings.prefs.moz_dir, "xulrunner"))

    # Set the path to the selected version of the Gecko SDK
    Settings.prefs.sdk_dir = os.path.abspath(
        os.path.join(Settings.prefs.moz_dir, "xulrunner-sdk"))

    # Kylo source goes into different directories depending on platform
    if Settings.platform == "osx":
        kylo_build_dir = os.path.join(Settings.prefs.build_dir, "Kylo.app")
    else:  # win32, linux, etc.
        kylo_build_dir = os.path.join(Settings.prefs.build_dir, "application")

    Settings.prefs.kylo_build_dir = kylo_build_dir

    # Clean up previous builds
    if Settings.prefs.clean:
        path = Settings.prefs.build_dir
        if os.path.exists(path):
            logger.info("Cleaning directory: %s", path)
            shutil.rmtree(path, ignore_errors=False, onerror=build_util.RMFail)

        # Clean up binary components
        for component in Settings.config.options('components'):
            platform_build.cleanComponent(component)

        # Clean up binary components in extensions
        for ext in Settings.config.options('extensions'):
            ext_components_dir = os.path.join(Settings.prefs.src_dir,
                                              "extensions", ext, "components")
            if os.path.isdir(ext_components_dir):
                for component in os.listdir(ext_components_dir):
                    if os.path.isdir(
                            os.path.join(ext_components_dir, component)):
                        platform_build.cleanComponent(
                            component,
                            componentDir=os.path.join(ext_components_dir,
                                                      component))

        # Check to see if we should clean the dist directory too
        if Settings.prefs.clean_dist:
            path = Settings.prefs.dist_dir
            if os.path.exists(path):
                logger.info("Cleaning output directory: %s", path)
                shutil.rmtree(path,
                              ignore_errors=False,
                              onerror=build_util.RMFail)

    # ---------------------
    # Build C++ components
    if len(Settings.prefs.compile) > 0:
        logger.info("=" * 72)
        logger.info("Building C++ Components: %s" % Settings.prefs.compile)
        logger.info("=" * 72)

        # Build main set of components
        if "com" in Settings.prefs.compile:
            for component in Settings.config.options('components'):
                if not Settings.prefs.clean:
                    platform_build.cleanComponent(component)
                platform_build.buildComponent(component)

        # Build extensions' components
        if "ext" in Settings.prefs.compile:
            for ext in Settings.config.options('extensions'):
                ext_components_dir = os.path.join(Settings.prefs.src_dir,
                                                  "extensions", ext,
                                                  "components")
                if os.path.isdir(ext_components_dir):
                    for component in os.listdir(ext_components_dir):
                        if os.path.isdir(
                                os.path.join(ext_components_dir, component)):
                            if not Settings.prefs.clean:
                                platform_build.cleanComponent(
                                    component,
                                    componentDir=os.path.join(
                                        ext_components_dir, component))
                            for part in platform_build.buildComponent(
                                    component,
                                    componentDir=os.path.join(
                                        ext_components_dir, component)):
                                shutil.copy2(part, ext_components_dir)

    # ---------------------
    # Copy source materials into our build directory
    if Settings.prefs.update:
        # Start counting how many updates we do...
        numUpdates = 0

        kylo_src_dir = os.path.join(Settings.prefs.src_dir, "kylo")

        # Create build_dir if it doesn't exist
        if not os.path.exists(Settings.prefs.build_dir):
            logger.info("Creating build directory: %s",
                        Settings.prefs.build_dir)
            os.makedirs(Settings.prefs.build_dir)
            numUpdates += 1

        # Check if we have an existing omni.ja[r]
        omni_path = os.path.join(Settings.prefs.kylo_build_dir, "omni.jar")
        if os.path.isfile(omni_path) or os.path.isfile(omni_path[:-1]):
            # delete the chrome.manifest, because it's been tainted by the
            # omni.jar process
            del_files = ["chrome.manifest"]

            if not Settings.prefs.omnify:
                # if we're not omnify-ing again, delete the old jar
                del_files += ["omni.jar", "omni.ja"]

            for f in del_files:
                file = os.path.join(Settings.prefs.kylo_build_dir, f)
                if (os.path.isfile(file)):
                    logger.info("Cleaning up - deleting %s" % file)
                    os.remove(file)

        # Sync our source directory
        logger.info("Copying Kylo source from %s to %s" %
                    (kylo_src_dir, kylo_build_dir))
        syncSrcReport = build_util.syncDirs(
            kylo_src_dir,
            kylo_build_dir,
            purge=False,
            force_write=True,
            exclude=[".hc.copyright.rules", "application.ini"])
        numUpdates += sum(syncSrcReport[1:])

        # Copy Component outputs into BUILD_DIR
        logger.info("Copying components into build directory...")
        component_build_dir = os.path.join(kylo_build_dir, "components")
        binary_mfst_contents = []
        mfst_count = 0
        for component in Settings.config.options('components'):
            # Copy binaries first
            compDir = os.path.join(Settings.prefs.src_dir, "components",
                                   component)
            binDir = os.path.join(compDir, "bin")
            for f in [os.path.join(binDir, pattern % component) \
                          for pattern in ('%s.dll', '%s.dylib', '%s.so', 'I%s.xpt')]:
                if os.path.exists(f):
                    if build_util.syncFile(f, component_build_dir):
                        logger.info("Copied %s to %s" %
                                    (os.path.basename(f), component_build_dir))
                        numUpdates += 1

            # Grab component-specific manifests
            mfst = os.path.join(compDir, "%s.manifest" % component)
            if os.path.isfile(mfst):
                if (mfst_count):
                    binary_mfst_contents.append("\r\n")
                binary_mfst_contents.append("# %s.manifest" % component)
                mfst_file = open(mfst, 'r')
                for line in mfst_file.readlines():
                    if not line.startswith("#"):
                        binary_mfst_contents.append(line)
                #binary_mfst_contents.extend(mfst_file.readlines())
                mfst_file.close()

                # increment our counter
                mfst_count += 1

            # Grab component-specific preferences
            pref = os.path.join(compDir, "%s-prefs.js" % component)
            if os.path.isfile(pref):
                outpref = os.path.join(kylo_build_dir, "defaults",
                                       "preferences")
                if build_util.syncFile(pref, outpref, force_write=True):
                    numUpdates += 1

        # Write binary.manifest
        if len(binary_mfst_contents) > 0:
            logger.info("Writing binary.manifest")

            bin_mfst_path = os.path.join(kylo_build_dir, "components",
                                         "binary.manifest")

            if os.path.exists(bin_mfst_path):
                logger.info("... writing temp file")
                temp_bin_mfst_path = os.path.join(kylo_build_dir, "components",
                                                  "~binary.manifest")
                temp_binary_mfst = open(temp_bin_mfst_path, "w+")
                temp_binary_mfst.writelines(binary_mfst_contents)
                temp_binary_mfst.close()

                logger.info("... comparing temp")
                if not filecmp.cmp(
                        temp_bin_mfst_path, bin_mfst_path, shallow=False):
                    logger.info("... replacing original with temp")
                    os.remove(bin_mfst_path)
                    os.rename(temp_bin_mfst_path, bin_mfst_path)
                    numUpdates += 1
                else:
                    logger.info("... temp same as original")
                    os.remove(temp_bin_mfst_path)
            else:
                binary_mfst = open(bin_mfst_path, "w+")
                binary_mfst.writelines(binary_mfst_contents)
                binary_mfst.close()
                numUpdates += 1

        # Copy extensions into BUILD_DIR
        logger.info("Copying extensions into build directory...")
        extensions_build_dir = os.path.join(kylo_build_dir, "extensions")
        for ext in Settings.config.options('extensions'):
            ext_src = os.path.join(Settings.prefs.src_dir, "extensions", ext)
            ext_build = os.path.join(extensions_build_dir, ext)
            syncExtReport = build_util.syncDirs(
                ext_src,
                ext_build,
                purge=True,
                force_write=True,
                exclude=[".hc.copyright.rules", "components"])
            numUpdates += sum(syncExtReport[1:])

            # Handle components directory separately to avoid syncing binary source
            ext_com_src = os.path.join(ext_src, "components")
            if os.path.isdir(ext_com_src):
                ext_com_build = os.path.join(ext_build, "components")
                if not os.path.isdir(ext_com_build):
                    os.makedirs(ext_com_build)
                    numUpdates += 1
                for f in os.listdir(ext_com_src):
                    if os.path.isfile(os.path.join(ext_com_src, f)):
                        if build_util.syncFile(os.path.join(ext_com_src, f),
                                               ext_com_build):
                            logger.info("--> copied %s" % f)
                            numUpdates += 1

        # ---------------------
        # Create our application.ini
        # TODO: May want to move this under buildApp()
        logger.info("Creating application.ini...")
        ini = ConfigParser(allow_no_value=True)
        ini.optionxform = str

        sections = ('App', 'Gecko', 'Crash Reporter', 'XRE')
        for section in sections:
            ini.add_section(section)
            opts = Settings.config.items(section)
            for (opt, val) in opts:
                ini.set(section, opt, val)

        ini_path = os.path.join(kylo_build_dir, "application.ini")

        if os.path.exists(ini_path):
            logger.info("... writing temp file")
            temp_ini_path = os.path.join(kylo_build_dir, "~application.ini")
            temp_ini_file = open(temp_ini_path, "w+")
            ini.write(temp_ini_file)
            temp_ini_file.close()

            for line in fileinput.input(temp_ini_path, inplace=1):
                print line.replace(" = ", "="),

            logger.info("... comparing temp")
            if not filecmp.cmp(temp_ini_path, ini_path, shallow=False):
                logger.info("... replacing original with temp")
                os.remove(ini_path)
                os.rename(temp_ini_path, ini_path)
                numUpdates += 1
            else:
                logger.info("... temp same as original")
                os.remove(temp_ini_path)
        else:
            ini_file = open(ini_path, "w+")
            ini.write(ini_file)
            ini_file.close()

            # Seems to be a weird incompatibility - ConfigParser writes values as "name = value", but XUL runner needs "name=value" (no spaces)
            for line in fileinput.input(ini_path, inplace=1):
                print line.replace(" = ", "="),

            numUpdates += 1

        logger.info("### Number of updates: %d" % numUpdates)

    # ---------------------
    # Jar up the app
    if Settings.prefs.update and Settings.prefs.omnify:
        logger.info("Creating omni.jar/omni.ja")
        if numUpdates > 0:
            omnify.makejar()
        else:
            logger.info("... skipping, nothing to add to jar")

    # ---------------------
    # We're going to leave the binary.manifest in the components directory
    # and reference it from a new/modified chrome.manifest in root.
    if os.path.isfile(
            os.path.join(Settings.prefs.kylo_build_dir, "components",
                         "binary.manifest")):
        chrome_mfst = open(
            os.path.join(Settings.prefs.kylo_build_dir, "chrome.manifest"),
            "a+")
        found = False
        line_count = 0
        for line in chrome_mfst:
            line_count += 1
            if "binary.manifest" in line:
                found = True
                break
        if not found:
            if line_count > 0:
                chrome_mfst.write("\n")
            chrome_mfst.write("manifest    components/binary.manifest")
        chrome_mfst.close()

    # ---------------------
    # Build the app itself
    if Settings.prefs.buildapp:
        logger.info("Building Kylo")
        platform_build.buildApp()

    # ---------------------
    # Prep installer
    if Settings.prefs.installer:
        logger.info("Create installer")
        platform_build.buildInstaller()

    # ---------------------
    # Kill the logging
    logger.info("=" * 72)
    logger.info("Build Complete!")
    build_util.stopLogging()

    return
Example #5
0
def build():
    """Build Kylo according to program inputs"""

    # Update the build and dist directories to include platform info and product id
    Settings.prefs.build_dir = os.path.normpath(
        os.path.join(Settings.prefs.build_dir, Settings.platform, Settings.config.get("App", "ProdID"))
    )
    Settings.prefs.dist_dir = os.path.normpath(
        os.path.join(Settings.prefs.dist_dir, Settings.platform, Settings.config.get("App", "ProdID"))
    )

    # Set the path to the selected version of the XULRunner runtime
    Settings.prefs.xul_dir = os.path.abspath(os.path.join(Settings.prefs.moz_dir, "xulrunner"))

    # Set the path to the selected version of the Gecko SDK
    Settings.prefs.sdk_dir = os.path.abspath(os.path.join(Settings.prefs.moz_dir, "xulrunner-sdk"))

    # Kylo source goes into different directories depending on platform
    if Settings.platform == "osx":
        kylo_build_dir = os.path.join(Settings.prefs.build_dir, "Kylo.app")
    else:  # win32, linux, etc.
        kylo_build_dir = os.path.join(Settings.prefs.build_dir, "application")

    Settings.prefs.kylo_build_dir = kylo_build_dir

    # Clean up previous builds
    if Settings.prefs.clean:
        path = Settings.prefs.build_dir
        if os.path.exists(path):
            logger.info("Cleaning directory: %s", path)
            shutil.rmtree(path, ignore_errors=False, onerror=build_util.RMFail)

        # Clean up binary components
        for component in Settings.config.options("components"):
            platform_build.cleanComponent(component)

        # Clean up binary components in extensions
        for ext in Settings.config.options("extensions"):
            ext_components_dir = os.path.join(Settings.prefs.src_dir, "extensions", ext, "components")
            if os.path.isdir(ext_components_dir):
                for component in os.listdir(ext_components_dir):
                    if os.path.isdir(os.path.join(ext_components_dir, component)):
                        platform_build.cleanComponent(
                            component, componentDir=os.path.join(ext_components_dir, component)
                        )

        # Check to see if we should clean the dist directory too
        if Settings.prefs.clean_dist:
            path = Settings.prefs.dist_dir
            if os.path.exists(path):
                logger.info("Cleaning output directory: %s", path)
                shutil.rmtree(path, ignore_errors=False, onerror=build_util.RMFail)

    # ---------------------
    # Build C++ components
    if len(Settings.prefs.compile) > 0:
        logger.info("=" * 72)
        logger.info("Building C++ Components: %s" % Settings.prefs.compile)
        logger.info("=" * 72)

        # Build main set of components
        if "com" in Settings.prefs.compile:
            for component in Settings.config.options("components"):
                if not Settings.prefs.clean:
                    platform_build.cleanComponent(component)
                platform_build.buildComponent(component)

        # Build extensions' components
        if "ext" in Settings.prefs.compile:
            for ext in Settings.config.options("extensions"):
                ext_components_dir = os.path.join(Settings.prefs.src_dir, "extensions", ext, "components")
                if os.path.isdir(ext_components_dir):
                    for component in os.listdir(ext_components_dir):
                        if os.path.isdir(os.path.join(ext_components_dir, component)):
                            if not Settings.prefs.clean:
                                platform_build.cleanComponent(
                                    component, componentDir=os.path.join(ext_components_dir, component)
                                )
                            for part in platform_build.buildComponent(
                                component, componentDir=os.path.join(ext_components_dir, component)
                            ):
                                shutil.copy2(part, ext_components_dir)

    # ---------------------
    # Copy source materials into our build directory
    if Settings.prefs.update:
        # Start counting how many updates we do...
        numUpdates = 0

        kylo_src_dir = os.path.join(Settings.prefs.src_dir, "kylo")

        # Create build_dir if it doesn't exist
        if not os.path.exists(Settings.prefs.build_dir):
            logger.info("Creating build directory: %s", Settings.prefs.build_dir)
            os.makedirs(Settings.prefs.build_dir)
            numUpdates += 1

        # Check if we have an existing omni.ja[r]
        omni_path = os.path.join(Settings.prefs.kylo_build_dir, "omni.jar")
        if os.path.isfile(omni_path) or os.path.isfile(omni_path[:-1]):
            # delete the chrome.manifest, because it's been tainted by the
            # omni.jar process
            del_files = ["chrome.manifest"]

            if not Settings.prefs.omnify:
                # if we're not omnify-ing again, delete the old jar
                del_files += ["omni.jar", "omni.ja"]

            for f in del_files:
                file = os.path.join(Settings.prefs.kylo_build_dir, f)
                if os.path.isfile(file):
                    logger.info("Cleaning up - deleting %s" % file)
                    os.remove(file)

        # Sync our source directory
        logger.info("Copying Kylo source from %s to %s" % (kylo_src_dir, kylo_build_dir))
        syncSrcReport = build_util.syncDirs(
            kylo_src_dir,
            kylo_build_dir,
            purge=False,
            force_write=True,
            exclude=[".hc.copyright.rules", "application.ini"],
        )
        numUpdates += sum(syncSrcReport[1:])

        # Copy Component outputs into BUILD_DIR
        logger.info("Copying components into build directory...")
        component_build_dir = os.path.join(kylo_build_dir, "components")
        binary_mfst_contents = []
        mfst_count = 0
        for component in Settings.config.options("components"):
            # Copy binaries first
            compDir = os.path.join(Settings.prefs.src_dir, "components", component)
            binDir = os.path.join(compDir, "bin")
            for f in [
                os.path.join(binDir, pattern % component) for pattern in ("%s.dll", "%s.dylib", "%s.so", "I%s.xpt")
            ]:
                if os.path.exists(f):
                    if build_util.syncFile(f, component_build_dir):
                        logger.info("Copied %s to %s" % (os.path.basename(f), component_build_dir))
                        numUpdates += 1

            # Grab component-specific manifests
            mfst = os.path.join(compDir, "%s.manifest" % component)
            if os.path.isfile(mfst):
                if mfst_count:
                    binary_mfst_contents.append("\r\n")
                binary_mfst_contents.append("# %s.manifest" % component)
                mfst_file = open(mfst, "r")
                for line in mfst_file.readlines():
                    if not line.startswith("#"):
                        binary_mfst_contents.append(line)
                # binary_mfst_contents.extend(mfst_file.readlines())
                mfst_file.close()

                # increment our counter
                mfst_count += 1

            # Grab component-specific preferences
            pref = os.path.join(compDir, "%s-prefs.js" % component)
            if os.path.isfile(pref):
                outpref = os.path.join(kylo_build_dir, "defaults", "preferences")
                if build_util.syncFile(pref, outpref, force_write=True):
                    numUpdates += 1

        # Write binary.manifest
        if len(binary_mfst_contents) > 0:
            logger.info("Writing binary.manifest")

            bin_mfst_path = os.path.join(kylo_build_dir, "components", "binary.manifest")

            if os.path.exists(bin_mfst_path):
                logger.info("... writing temp file")
                temp_bin_mfst_path = os.path.join(kylo_build_dir, "components", "~binary.manifest")
                temp_binary_mfst = open(temp_bin_mfst_path, "w+")
                temp_binary_mfst.writelines(binary_mfst_contents)
                temp_binary_mfst.close()

                logger.info("... comparing temp")
                if not filecmp.cmp(temp_bin_mfst_path, bin_mfst_path, shallow=False):
                    logger.info("... replacing original with temp")
                    os.remove(bin_mfst_path)
                    os.rename(temp_bin_mfst_path, bin_mfst_path)
                    numUpdates += 1
                else:
                    logger.info("... temp same as original")
                    os.remove(temp_bin_mfst_path)
            else:
                binary_mfst = open(bin_mfst_path, "w+")
                binary_mfst.writelines(binary_mfst_contents)
                binary_mfst.close()
                numUpdates += 1

        # Copy extensions into BUILD_DIR
        logger.info("Copying extensions into build directory...")
        extensions_build_dir = os.path.join(kylo_build_dir, "extensions")
        for ext in Settings.config.options("extensions"):
            ext_src = os.path.join(Settings.prefs.src_dir, "extensions", ext)
            ext_build = os.path.join(extensions_build_dir, ext)
            syncExtReport = build_util.syncDirs(
                ext_src, ext_build, purge=True, force_write=True, exclude=[".hc.copyright.rules", "components"]
            )
            numUpdates += sum(syncExtReport[1:])

            # Handle components directory separately to avoid syncing binary source
            ext_com_src = os.path.join(ext_src, "components")
            if os.path.isdir(ext_com_src):
                ext_com_build = os.path.join(ext_build, "components")
                if not os.path.isdir(ext_com_build):
                    os.makedirs(ext_com_build)
                    numUpdates += 1
                for f in os.listdir(ext_com_src):
                    if os.path.isfile(os.path.join(ext_com_src, f)):
                        if build_util.syncFile(os.path.join(ext_com_src, f), ext_com_build):
                            logger.info("--> copied %s" % f)
                            numUpdates += 1

        # ---------------------
        # Create our application.ini
        # TODO: May want to move this under buildApp()
        logger.info("Creating application.ini...")
        ini = ConfigParser(allow_no_value=True)
        ini.optionxform = str

        sections = ("App", "Gecko", "Crash Reporter", "XRE")
        for section in sections:
            ini.add_section(section)
            opts = Settings.config.items(section)
            for (opt, val) in opts:
                ini.set(section, opt, val)

        ini_path = os.path.join(kylo_build_dir, "application.ini")

        if os.path.exists(ini_path):
            logger.info("... writing temp file")
            temp_ini_path = os.path.join(kylo_build_dir, "~application.ini")
            temp_ini_file = open(temp_ini_path, "w+")
            ini.write(temp_ini_file)
            temp_ini_file.close()

            for line in fileinput.input(temp_ini_path, inplace=1):
                print line.replace(" = ", "="),

            logger.info("... comparing temp")
            if not filecmp.cmp(temp_ini_path, ini_path, shallow=False):
                logger.info("... replacing original with temp")
                os.remove(ini_path)
                os.rename(temp_ini_path, ini_path)
                numUpdates += 1
            else:
                logger.info("... temp same as original")
                os.remove(temp_ini_path)
        else:
            ini_file = open(ini_path, "w+")
            ini.write(ini_file)
            ini_file.close()

            # Seems to be a weird incompatibility - ConfigParser writes values as "name = value", but XUL runner needs "name=value" (no spaces)
            for line in fileinput.input(ini_path, inplace=1):
                print line.replace(" = ", "="),

            numUpdates += 1

        logger.info("### Number of updates: %d" % numUpdates)

    # ---------------------
    # Jar up the app
    if Settings.prefs.update and Settings.prefs.omnify:
        logger.info("Creating omni.jar/omni.ja")
        if numUpdates > 0:
            omnify.makejar()
        else:
            logger.info("... skipping, nothing to add to jar")

    # ---------------------
    # We're going to leave the binary.manifest in the components directory
    # and reference it from a new/modified chrome.manifest in root.
    if os.path.isfile(os.path.join(Settings.prefs.kylo_build_dir, "components", "binary.manifest")):
        chrome_mfst = open(os.path.join(Settings.prefs.kylo_build_dir, "chrome.manifest"), "a+")
        found = False
        line_count = 0
        for line in chrome_mfst:
            line_count += 1
            if "binary.manifest" in line:
                found = True
                break
        if not found:
            if line_count > 0:
                chrome_mfst.write("\n")
            chrome_mfst.write("manifest    components/binary.manifest")
        chrome_mfst.close()

    # ---------------------
    # Build the app itself
    if Settings.prefs.buildapp:
        logger.info("Building Kylo")
        platform_build.buildApp()

    # ---------------------
    # Prep installer
    if Settings.prefs.installer:
        logger.info("Create installer")
        platform_build.buildInstaller()

    # ---------------------
    # Kill the logging
    logger.info("=" * 72)
    logger.info("Build Complete!")
    build_util.stopLogging()

    return