com.google.gwt.dev.Compiler.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gwt.dev.Compiler.java

Source

/*
 * Copyright 2008 Google Inc.
 * 
 * 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 com.google.gwt.dev;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.linker.ArtifactSet;
import com.google.gwt.dev.CompileTaskRunner.CompileTask;
import com.google.gwt.dev.Link.LinkOptionsImpl;
import com.google.gwt.dev.cfg.ModuleDef;
import com.google.gwt.dev.cfg.ModuleDefLoader;
import com.google.gwt.dev.javac.CompilationStateBuilder;
import com.google.gwt.dev.jjs.JJSOptions;
import com.google.gwt.dev.jjs.PermutationResult;
import com.google.gwt.dev.shell.CheckForUpdates;
import com.google.gwt.dev.shell.CheckForUpdates.UpdateResult;
import com.google.gwt.dev.util.FileBackedObject;
import com.google.gwt.dev.util.Memory;
import com.google.gwt.dev.util.Util;
import com.google.gwt.dev.util.arg.ArgHandlerDeployDir;
import com.google.gwt.dev.util.arg.ArgHandlerExtraDir;
import com.google.gwt.dev.util.arg.ArgHandlerLocalWorkers;
import com.google.gwt.dev.util.arg.ArgHandlerWarDir;
import com.google.gwt.dev.util.arg.ArgHandlerWorkDirOptional;
import com.google.gwt.dev.util.log.speedtracer.CompilerEventType;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event;
import com.google.gwt.util.tools.Utility;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.FutureTask;

/**
 * The main executable entry point for the GWT Java to JavaScript compiler.
 */
public class Compiler {

    static class ArgProcessor extends PrecompileTaskArgProcessor {
        public ArgProcessor(CompilerOptions options) {
            super(options);

            registerHandler(new ArgHandlerLocalWorkers(options));

            // Override the ArgHandlerWorkDirRequired in the super class.
            registerHandler(new ArgHandlerWorkDirOptional(options));

            registerHandler(new ArgHandlerWarDir(options));
            registerHandler(new ArgHandlerDeployDir(options));
            registerHandler(new ArgHandlerExtraDir(options));
        }

        @Override
        protected String getName() {
            return Compiler.class.getName();
        }
    }

    static class CompilerOptionsImpl extends PrecompileTaskOptionsImpl implements CompilerOptions {

        private LinkOptionsImpl linkOptions = new LinkOptionsImpl();
        private int localWorkers;

        public CompilerOptionsImpl() {
        }

        public CompilerOptionsImpl(CompilerOptions other) {
            copyFrom(other);
        }

        public void copyFrom(CompilerOptions other) {
            super.copyFrom(other);
            linkOptions.copyFrom(other);
            localWorkers = other.getLocalWorkers();
        }

        @Override
        public File getDeployDir() {
            return linkOptions.getDeployDir();
        }

        @Override
        public File getExtraDir() {
            return linkOptions.getExtraDir();
        }

        @Override
        public int getLocalWorkers() {
            return localWorkers;
        }

        @Override
        @Deprecated
        public File getOutDir() {
            return linkOptions.getOutDir();
        }

        @Override
        public File getWarDir() {
            return linkOptions.getWarDir();
        }

        @Override
        public void setDeployDir(File extraDir) {
            linkOptions.setDeployDir(extraDir);
        }

        @Override
        public void setExtraDir(File extraDir) {
            linkOptions.setExtraDir(extraDir);
        }

        @Override
        public void setLocalWorkers(int localWorkers) {
            this.localWorkers = localWorkers;
        }

        @Override
        @Deprecated
        public void setOutDir(File outDir) {
            linkOptions.setOutDir(outDir);
        }

        @Override
        public void setWarDir(File outDir) {
            linkOptions.setWarDir(outDir);
        }
    }

    public static void main(String[] args) {
        Memory.initialize();
        if (System.getProperty("gwt.jjs.dumpAst") != null) {
            System.out.println("Will dump AST to: " + System.getProperty("gwt.jjs.dumpAst"));
        }

        SpeedTracerLogger.init();

        /*
         * NOTE: main always exits with a call to System.exit to terminate any
         * non-daemon threads that were started in Generators. Typically, this is to
         * shutdown AWT related threads, since the contract for their termination is
         * still implementation-dependent.
         */
        final CompilerOptions options = new CompilerOptionsImpl();
        if (new ArgProcessor(options).processArgs(args)) {
            CompileTask task = new CompileTask() {
                @Override
                public boolean run(TreeLogger logger) throws UnableToCompleteException {
                    FutureTask<UpdateResult> updater = null;
                    if (!options.isUpdateCheckDisabled()) {
                        updater = CheckForUpdates.checkForUpdatesInBackgroundThread(logger,
                                CheckForUpdates.ONE_DAY);
                    }
                    boolean success = new Compiler(options).run(logger);
                    if (success) {
                        CheckForUpdates.logUpdateAvailable(logger, updater);
                    }
                    return success;
                }
            };
            if (CompileTaskRunner.runWithAppropriateLogger(options, task)) {
                // Exit w/ success code.
                System.exit(0);
            }
        }
        // Exit w/ non-success code.
        System.exit(1);
    }

    private final CompilerOptionsImpl options;

    public Compiler(CompilerOptions options) {
        this.options = new CompilerOptionsImpl(options);
    }

    public boolean run(TreeLogger logger) throws UnableToCompleteException {
        ModuleDef[] modules = new ModuleDef[options.getModuleNames().size()];
        int i = 0;
        for (String moduleName : options.getModuleNames()) {
            modules[i++] = ModuleDefLoader.loadFromClassPath(logger, moduleName, true);
        }
        return run(logger, modules);
    }

    public boolean run(TreeLogger logger, ModuleDef... modules) throws UnableToCompleteException {
        boolean tempWorkDir = false;
        try {
            if (options.getWorkDir() == null) {
                options.setWorkDir(Utility.makeTemporaryDirectory(null, "gwtc"));
                tempWorkDir = true;
            }
            if (options.isSoycEnabled() && options.getExtraDir() == null) {
                options.setExtraDir(new File("extras"));
            }

            File persistentUnitCacheDir = null;
            if (options.getWarDir() != null && !options.getWarDir().getName().endsWith(".jar")) {
                persistentUnitCacheDir = new File(options.getWarDir(), "../");
            }
            CompilationStateBuilder.init(logger, persistentUnitCacheDir);

            for (ModuleDef module : modules) {
                String moduleName = module.getCanonicalName();
                if (options.isValidateOnly()) {
                    if (!Precompile.validate(logger, options, module, options.getGenDir())) {
                        return false;
                    }
                } else {
                    long compileStart = System.currentTimeMillis();
                    TreeLogger branch = logger.branch(TreeLogger.INFO, "Compiling module " + moduleName);

                    // Optimize early since permutation compiles will run in process.
                    options.setOptimizePrecompile(true);
                    Precompilation precompilation = Precompile.precompile(branch, options, module,
                            options.getGenDir());
                    if (precompilation == null) {
                        return false;
                    }

                    Event compilePermutationsEvent = SpeedTracerLogger
                            .start(CompilerEventType.COMPILE_PERMUTATIONS);
                    Permutation[] allPerms = precompilation.getPermutations();
                    List<FileBackedObject<PermutationResult>> resultFiles = CompilePerms
                            .makeResultFiles(options.getCompilerWorkDir(moduleName), allPerms);
                    CompilePerms.compile(branch, precompilation, allPerms, options.getLocalWorkers(), resultFiles);
                    compilePermutationsEvent.end();

                    ArtifactSet generatedArtifacts = precompilation.getGeneratedArtifacts();
                    JJSOptions precompileOptions = precompilation.getUnifiedAst().getOptions();

                    precompilation = null; // No longer needed, so save the memory

                    Event linkEvent = SpeedTracerLogger.start(CompilerEventType.LINK);
                    File absPath = new File(options.getWarDir(), module.getName());
                    absPath = absPath.getAbsoluteFile();

                    String logMessage = "Linking into " + absPath;
                    if (options.getExtraDir() != null) {
                        File absExtrasPath = new File(options.getExtraDir(), module.getName());
                        absExtrasPath = absExtrasPath.getAbsoluteFile();
                        logMessage += "; Writing extras to " + absExtrasPath;
                    }
                    Link.link(logger.branch(TreeLogger.TRACE, logMessage), module, generatedArtifacts, allPerms,
                            resultFiles, options.getWarDir(), options.getDeployDir(), options.getExtraDir(),
                            precompileOptions);

                    linkEvent.end();
                    long compileDone = System.currentTimeMillis();
                    long delta = compileDone - compileStart;
                    if (branch.isLoggable(TreeLogger.INFO)) {
                        branch.log(TreeLogger.INFO,
                                "Compilation succeeded -- " + String.format("%.3f", delta / 1000d) + "s");
                    }
                }
            }

        } catch (IOException e) {
            logger.log(TreeLogger.ERROR, "Unable to create compiler work directory", e);
            return false;
        } finally {
            if (tempWorkDir) {
                Util.recursiveDelete(options.getWorkDir(), false);
            }
        }
        return true;
    }
}