All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gwt.dev.BuildTarget Maven / Gradle / Ivy

There is a newer version: 2.7.0.vaadin7
Show newest version
/*
 * Copyright 2014 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.dev.cfg.ModuleDef;
import com.google.gwt.dev.cfg.RuntimeRebindRuleGenerator;
import com.google.gwt.dev.resource.Resource;
import com.google.gwt.thirdparty.guava.common.annotations.VisibleForTesting;
import com.google.gwt.thirdparty.guava.common.base.Function;
import com.google.gwt.thirdparty.guava.common.collect.Iterables;
import com.google.gwt.thirdparty.guava.common.collect.Lists;
import com.google.gwt.thirdparty.guava.common.collect.Sets;

import java.io.File;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

import javax.annotation.Nullable;

/**
 * Represents a module in a module tree, knows how to build that module into an output library and
 * checks output library freshness.
 * 

* Build requests will first build all dependency libraries (even if some fail). But the current * target will only be built if all dependency library builds were successful. */ class BuildTarget { /** * Represents a combination of whether output is current and whether output is good. For example * if a build is run and it fails, then output is fresh and does not need to be rebuilt but it is * also known to be bad. */ public enum OutputFreshness { FRESH_KNOWN_BAD, FRESH_KNOWN_GOOD, STALE, UNKNOWN } public static final Function LIBRARY_PATH_FUNCTION = new Function() { @Override public String apply(@Nullable BuildTarget buildTarget) { return buildTarget.computeLibraryPath(); } }; @VisibleForTesting public static String formatCompilingModuleMessage(String canonicalModuleName) { return "\n" + "Compiling module " + canonicalModuleName; } @VisibleForTesting public static String formatReusingCachedLibraryMessage(String canonicalModuleName) { return "Reusing cached library for " + canonicalModuleName; } private final BuildTargetOptions buildTargetOptions; private final String canonicalModuleName; private final List dependencyBuildTargets; private ModuleDef module; private OutputFreshness outputFreshness = OutputFreshness.UNKNOWN; private Set transitiveDependencyBuildTargets; BuildTarget(String canonicalModuleName, BuildTargetOptions buildTargetOptions, BuildTarget... dependencyBuildTargets) { this.canonicalModuleName = canonicalModuleName; this.buildTargetOptions = buildTargetOptions; this.dependencyBuildTargets = Arrays.asList(dependencyBuildTargets); } public boolean build(TreeLogger logger) { return build(logger, false); } public boolean build(TreeLogger logger, boolean link) { if (outputFreshness == OutputFreshness.FRESH_KNOWN_GOOD || outputFreshness == OutputFreshness.FRESH_KNOWN_BAD) { logger.log(TreeLogger.SPAM, formatReusingCachedLibraryMessage(canonicalModuleName)); return outputFreshness == OutputFreshness.FRESH_KNOWN_GOOD; } boolean dependencyBuildsSucceeded = true; // Build all my dependencies before myself. for (BuildTarget dependencyBuildTarget : dependencyBuildTargets) { // If any dependency fails to build then I have failed to build as well. dependencyBuildsSucceeded &= dependencyBuildTarget.build(logger); } if (!dependencyBuildsSucceeded) { outputFreshness = OutputFreshness.FRESH_KNOWN_BAD; return false; // Build failed. } TreeLogger branch = logger.branch(TreeLogger.INFO, formatCompilingModuleMessage(canonicalModuleName)); boolean thisBuildSucceeded; try { RuntimeRebindRuleGenerator.RUNTIME_REBIND_RULE_SOURCES_BY_SHORT_NAME.clear(); LibraryCompiler libraryCompiler = new LibraryCompiler(computeCompileOptions(link)); libraryCompiler.setResourceLoader(buildTargetOptions.getResourceLoader()); thisBuildSucceeded = libraryCompiler.run(branch); module = libraryCompiler.getModule(); } catch (Throwable t) { logger.log(TreeLogger.ERROR, t.getMessage()); outputFreshness = OutputFreshness.FRESH_KNOWN_BAD; return false; } outputFreshness = thisBuildSucceeded ? OutputFreshness.FRESH_KNOWN_GOOD : OutputFreshness.FRESH_KNOWN_BAD; return thisBuildSucceeded; } public CompilerOptions computeCompileOptions(boolean link) { CompilerOptions compilerOptions = new CompilerOptionsImpl(); // Must compile the canonical name, not name, since after module-renames there may be more // than one module in the classpath with the same name and we don't want to find and recompile // the same one over and over. compilerOptions.setModuleNames(Lists.newArrayList(canonicalModuleName)); compilerOptions.setLink(link); compilerOptions.setLogLevel(TreeLogger.ERROR); compilerOptions.setGenDir(new File(buildTargetOptions.getGenDir())); compilerOptions.setWorkDir(new File(buildTargetOptions.getOutputDir())); compilerOptions.setLibraryPaths(Lists.newArrayList( Iterables.transform(getTransitiveDependencyBuildTargets(), LIBRARY_PATH_FUNCTION))); compilerOptions.setFinalProperties(buildTargetOptions.getFinalProperties()); if (!link) { compilerOptions.setOutputLibraryPath(computeLibraryPath()); } else { compilerOptions.setWarDir(new File(buildTargetOptions.getWarDir())); } return compilerOptions; } public String computeLibraryPath() { return buildTargetOptions.getOutputDir() + "/" + canonicalModuleName + ".gwtlib"; } public void computeOutputFreshness(TreeLogger logger) { if (outputFreshness != OutputFreshness.UNKNOWN) { return; } for (BuildTarget dependencyBuildTarget : dependencyBuildTargets) { dependencyBuildTarget.computeOutputFreshness(logger); } if (module == null) { logger.log(TreeLogger.SPAM, "Library " + canonicalModuleName + " is stale: the module hasn't been loaded yet"); outputFreshness = OutputFreshness.STALE; return; } for (BuildTarget dependencyBuildTarget : dependencyBuildTargets) { if (dependencyBuildTarget.outputFreshness == OutputFreshness.STALE) { logger.log(TreeLogger.SPAM, "Library " + canonicalModuleName + " is stale: has a stale dependency"); outputFreshness = OutputFreshness.STALE; return; } } File libraryFile = new File(computeLibraryPath()); if (!libraryFile.exists()) { logger.log(TreeLogger.SPAM, "Library " + canonicalModuleName + " is stale: the library file is missing"); outputFreshness = OutputFreshness.STALE; return; } long libraryFileLastModified = libraryFile.lastModified(); module.refresh(); if (libraryFileLastModified < module.getResourceLastModified()) { Set newerResources = module.getResourcesNewerThan(libraryFileLastModified); TreeLogger branch = logger.branch(TreeLogger.SPAM, "Library " + canonicalModuleName + " is stale: library is older than some resource(s)"); for (Resource newerResource : newerResources) { branch.log(TreeLogger.SPAM, newerResource.getPath() + " has changed"); } outputFreshness = OutputFreshness.STALE; return; } logger.log(TreeLogger.SPAM, "Library " + canonicalModuleName + " is fresh"); outputFreshness = OutputFreshness.FRESH_KNOWN_GOOD; } public String getCanonicalModuleName() { return canonicalModuleName; } public List getDependencyBuildTargets() { return dependencyBuildTargets; } public Set getTransitiveDependencyBuildTargets() { if (transitiveDependencyBuildTargets == null) { transitiveDependencyBuildTargets = Sets.newHashSet(); transitiveDependencyBuildTargets.addAll(dependencyBuildTargets); for (BuildTarget buildTarget : dependencyBuildTargets) { transitiveDependencyBuildTargets.addAll(buildTarget.getTransitiveDependencyBuildTargets()); } } return transitiveDependencyBuildTargets; } public boolean isOutputFreshAndGood() { return outputFreshness == OutputFreshness.FRESH_KNOWN_GOOD; } public boolean link(TreeLogger logger) { return build(logger, true); } public void setModule(ModuleDef module) { this.module = module; } public void setOutputFreshness(OutputFreshness outputFreshness) { this.outputFreshness = outputFreshness; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy