diff options
author | Tor Norbye <tnorbye@google.com> | 2013-05-01 12:55:43 -0700 |
---|---|---|
committer | Tor Norbye <tnorbye@google.com> | 2013-05-01 12:55:43 -0700 |
commit | 8fb0021093e7d978cc06043ba4c06b0a47778294 (patch) | |
tree | b95f5f920574415ae49b26ad6abac86eb6d7b38d /jps | |
parent | b17587c84879dd2ea42495f1fbdadbc806b9475b (diff) | |
download | idea-8fb0021093e7d978cc06043ba4c06b0a47778294.tar.gz |
Snapshot dddb119296e7ee16fa8180784610b89b89112ebb from master branch of git://git.jetbrains.org/idea/community.git
Change-Id: I5fe892d3e4d06009445cc2270aa90bb57dea9d39
Diffstat (limited to 'jps')
13 files changed, 233 insertions, 63 deletions
diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildRunner.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildRunner.java index f2650717ff50..7fe98f331a26 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildRunner.java +++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildRunner.java @@ -18,14 +18,12 @@ package org.jetbrains.jps.cmdline; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.io.FileUtil; import gnu.trove.THashSet; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.api.BuildType; import org.jetbrains.jps.api.CanceledStatus; import org.jetbrains.jps.api.GlobalOptions; -import org.jetbrains.jps.builders.BuildRootDescriptor; -import org.jetbrains.jps.builders.BuildTarget; -import org.jetbrains.jps.builders.BuildTargetLoader; -import org.jetbrains.jps.builders.BuildTargetType; +import org.jetbrains.jps.builders.*; import org.jetbrains.jps.builders.impl.BuildDataPathsImpl; import org.jetbrains.jps.builders.impl.BuildRootIndexImpl; import org.jetbrains.jps.builders.impl.BuildTargetIndexImpl; @@ -59,14 +57,12 @@ public class BuildRunner { public static final boolean PARALLEL_BUILD_ENABLED = Boolean.parseBoolean(System.getProperty(GlobalOptions.COMPILE_PARALLEL_OPTION, "false")); private static final boolean STORE_TEMP_CACHES_IN_MEMORY = PARALLEL_BUILD_ENABLED || System.getProperty(GlobalOptions.USE_MEMORY_TEMP_CACHE_OPTION) != null; private final JpsModelLoader myModelLoader; - private final List<TargetTypeBuildScope> myScopes; private final List<String> myFilePaths; private final Map<String, String> myBuilderParams; private boolean myForceCleanCaches; - public BuildRunner(JpsModelLoader modelLoader, List<TargetTypeBuildScope> scopes, List<String> filePaths, Map<String, String> builderParams) { + public BuildRunner(JpsModelLoader modelLoader, List<String> filePaths, Map<String, String> builderParams) { myModelLoader = modelLoader; - myScopes = scopes; myFilePaths = filePaths; myBuilderParams = builderParams; } @@ -116,11 +112,15 @@ public class BuildRunner { myForceCleanCaches = forceCleanCaches; } - public void runBuild(ProjectDescriptor pd, CanceledStatus cs, @Nullable Callbacks.ConstantAffectionResolver constantSearch, - MessageHandler msgHandler, BuildType buildType) throws Exception { + public void runBuild(ProjectDescriptor pd, + CanceledStatus cs, + @Nullable Callbacks.ConstantAffectionResolver constantSearch, + MessageHandler msgHandler, + BuildType buildType, + List<TargetTypeBuildScope> scopes, final boolean includeDependenciesToScope) throws Exception { for (int attempt = 0; attempt < 2; attempt++) { final boolean forceClean = myForceCleanCaches && myFilePaths.isEmpty(); - final CompileScope compileScope = createCompilationScope(pd, myScopes, myFilePaths, forceClean); + final CompileScope compileScope = createCompilationScope(pd, scopes, myFilePaths, forceClean, includeDependenciesToScope); final IncProjectBuilder builder = new IncProjectBuilder(pd, BuilderRegistry.getInstance(), myBuilderParams, cs, constantSearch); builder.addMessageHandler(msgHandler); try { @@ -151,8 +151,8 @@ public class BuildRunner { } } - private static CompileScope createCompilationScope(ProjectDescriptor pd, List<TargetTypeBuildScope> scopes, - Collection<String> paths, final boolean forceClean) throws Exception { + private static CompileScope createCompilationScope(ProjectDescriptor pd, List<TargetTypeBuildScope> scopes, Collection<String> paths, + final boolean forceClean, final boolean includeDependenciesToScope) throws Exception { Set<BuildTargetType<?>> targetTypes = new HashSet<BuildTargetType<?>>(); Set<BuildTargetType<?>> targetTypesToForceBuild = new HashSet<BuildTargetType<?>>(); Set<BuildTarget<?>> targets = new HashSet<BuildTarget<?>>(); @@ -184,6 +184,9 @@ public class BuildRunner { } } } + if (includeDependenciesToScope) { + includeDependenciesToScope(targetTypes, targets, pd); + } final Timestamps timestamps = pd.timestamps.getStorage(); if (!paths.isEmpty()) { @@ -211,7 +214,28 @@ public class BuildRunner { return new CompileScopeImpl(targetTypes, targetTypesToForceBuild, targets, files); } - public List<TargetTypeBuildScope> getScopes() { - return myScopes; + private static void includeDependenciesToScope(Set<BuildTargetType<?>> targetTypes, Set<BuildTarget<?>> targets, + ProjectDescriptor descriptor) { + //todo[nik] get rid of CompileContext parameter for BuildTargetIndex.getDependencies() and use it here + TargetOutputIndex dummyIndex = new TargetOutputIndex() { + @Override + public Collection<BuildTarget<?>> getTargetsByOutputFile(@NotNull File file) { + return Collections.emptyList(); + } + }; + + List<BuildTarget<?>> current = new ArrayList<BuildTarget<?>>(targets); + while (!current.isEmpty()) { + List<BuildTarget<?>> next = new ArrayList<BuildTarget<?>>(); + for (BuildTarget<?> target : current) { + for (BuildTarget<?> depTarget : target.computeDependencies(descriptor.getBuildTargetIndex(), dummyIndex)) { + if (!targets.contains(depTarget) && !targetTypes.contains(depTarget.getTargetType())) { + next.add(depTarget); + } + } + } + targets.addAll(next); + current = next; + } } } diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java index e246ad13a5fa..b1ffe29b9788 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java +++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java @@ -72,7 +72,8 @@ final class BuildSession implements Runnable, CanceledStatus { private final ConstantSearch myConstantSearch = new ConstantSearch(); private final BuildRunner myBuildRunner; private final boolean myForceModelLoading; - private BuildType myBuildType; + private final BuildType myBuildType; + private final List<TargetTypeBuildScope> myScopes; BuildSession(UUID sessionId, Channel channel, @@ -85,7 +86,7 @@ final class BuildSession implements Runnable, CanceledStatus { myProjectPath = FileUtil.toCanonicalPath(params.getProjectId()); String globalOptionsPath = FileUtil.toCanonicalPath(globals.getGlobalOptionsPath()); myBuildType = convertCompileType(params.getBuildType()); - List<TargetTypeBuildScope> scopes = params.getScopeList(); + myScopes = params.getScopeList(); List<String> filePaths = params.getFilePathList(); Map<String, String> builderParams = new HashMap<String, String>(); for (CmdlineRemoteProto.Message.KeyValuePair pair : params.getBuilderParameterList()) { @@ -94,7 +95,7 @@ final class BuildSession implements Runnable, CanceledStatus { myInitialFSDelta = delta; JpsModelLoaderImpl loader = new JpsModelLoaderImpl(myProjectPath, globalOptionsPath, null); myForceModelLoading = Boolean.parseBoolean(builderParams.get(BuildMain.FORCE_MODEL_LOADING_PARAMETER.toString())); - myBuildRunner = new BuildRunner(loader, scopes, filePaths, builderParams); + myBuildRunner = new BuildRunner(loader, filePaths, builderParams); } public void run() { @@ -138,13 +139,16 @@ final class BuildSession implements Runnable, CanceledStatus { CustomBuilderMessage builderMessage = (CustomBuilderMessage)buildMessage; response = CmdlineProtoUtil.createCustomBuilderMessage(builderMessage.getBuilderId(), builderMessage.getMessageType(), builderMessage.getMessageText()); } - else { + else if (!(buildMessage instanceof BuildingTargetProgressMessage)) { float done = -1.0f; if (buildMessage instanceof ProgressMessage) { done = ((ProgressMessage)buildMessage).getDone(); } response = CmdlineProtoUtil.createCompileProgressMessageResponse(buildMessage.getMessageText(), done); } + else { + response = null; + } if (response != null) { Channels.write(myChannel, CmdlineProtoUtil.toMessage(mySessionId, response)); } @@ -181,7 +185,7 @@ final class BuildSession implements Runnable, CanceledStatus { // optimization: check whether we can skip the build final boolean hasWorkToDoWithModules = fsStateStream.readBoolean(); if (!myForceModelLoading && (myBuildType == BuildType.BUILD || myBuildType == BuildType.UP_TO_DATE_CHECK) && !hasWorkToDoWithModules - && scopeContainsModulesOnlyForIncrementalMake(myBuildRunner.getScopes()) && !containsChanges(myInitialFSDelta)) { + && scopeContainsModulesOnlyForIncrementalMake(myScopes) && !containsChanges(myInitialFSDelta)) { updateFsStateOnDisk(dataStorageRoot, fsStateStream, myInitialFSDelta.getOrdinal()); return; } @@ -213,7 +217,7 @@ final class BuildSession implements Runnable, CanceledStatus { // ensure events from controller are processed after FSState initialization myEventsProcessor.startProcessing(); - myBuildRunner.runBuild(pd, cs, myConstantSearch, msgHandler, myBuildType); + myBuildRunner.runBuild(pd, cs, myConstantSearch, msgHandler, myBuildType, myScopes, false); } finally { saveData(fsState, dataStorageRoot); diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java index 2e6a288e900d..37ea688b5101 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java @@ -809,6 +809,7 @@ public class IncProjectBuilder { private void buildTargetsChunk(CompileContext context, final BuildTargetChunk chunk) throws ProjectBuildException { boolean doneSomething; try { + sendBuildingTargetMessages(chunk.getTargets(), BuildingTargetProgressMessage.Event.STARTED); Utils.ERRORS_DETECTED_KEY.set(context, Boolean.FALSE); for (BuildTarget<?> target : chunk.getTargets()) { @@ -864,9 +865,14 @@ public class IncProjectBuilder { finally { Utils.REMOVED_SOURCES_KEY.set(context, null); } + sendBuildingTargetMessages(chunk.getTargets(), BuildingTargetProgressMessage.Event.FINISHED); } } + private void sendBuildingTargetMessages(@NotNull Set<? extends BuildTarget<?>> targets, @NotNull BuildingTargetProgressMessage.Event event) { + myMessageDispatcher.processMessage(new BuildingTargetProgressMessage(targets, event)); + } + private static void createClasspathIndex(final BuildTargetChunk chunk) { final Set<File> outputDirs = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY); for (BuildTarget<?> target : chunk.getTargets()) { diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/builders/ArtifactLayoutCustomizationService.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/builders/ArtifactLayoutCustomizationService.java new file mode 100644 index 000000000000..e82fc15c918d --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/builders/ArtifactLayoutCustomizationService.java @@ -0,0 +1,34 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * 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 org.jetbrains.jps.incremental.artifacts.builders; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jps.model.artifact.JpsArtifact; +import org.jetbrains.jps.model.artifact.elements.JpsPackagingElement; + +import java.util.Collection; +import java.util.List; + +/** + * @author nik + */ +public abstract class ArtifactLayoutCustomizationService { + @Nullable + public abstract List<JpsPackagingElement> getCustomizedLayout(@NotNull JpsArtifact artifact, + @NotNull Collection<JpsArtifact> parentArtifacts); + +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/builders/LayoutElementBuildersRegistry.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/builders/LayoutElementBuildersRegistry.java index 0d0e90f0a532..5cef20f4dfb4 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/builders/LayoutElementBuildersRegistry.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/builders/LayoutElementBuildersRegistry.java @@ -16,7 +16,6 @@ package org.jetbrains.jps.incremental.artifacts.builders; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.containers.ClassMap; import org.jetbrains.annotations.NotNull; @@ -25,8 +24,6 @@ import org.jetbrains.jps.builders.BuildTarget; import org.jetbrains.jps.builders.TargetOutputIndex; import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType; import org.jetbrains.jps.incremental.ModuleBuildTarget; -import org.jetbrains.jps.model.module.JpsModule; -import org.jetbrains.jps.util.JpsPathUtil; import org.jetbrains.jps.incremental.artifacts.instructions.ArtifactCompilerInstructionCreator; import org.jetbrains.jps.incremental.artifacts.instructions.ArtifactInstructionsBuilderContext; import org.jetbrains.jps.incremental.artifacts.instructions.CopyToDirectoryInstructionCreator; @@ -34,12 +31,15 @@ import org.jetbrains.jps.model.artifact.JpsArtifact; import org.jetbrains.jps.model.artifact.elements.*; import org.jetbrains.jps.model.java.JpsProductionModuleOutputPackagingElement; import org.jetbrains.jps.model.java.JpsTestModuleOutputPackagingElement; +import org.jetbrains.jps.model.module.JpsModule; import org.jetbrains.jps.service.JpsServiceManager; +import org.jetbrains.jps.util.JpsPathUtil; import java.io.File; import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Set; /** * @author nik @@ -305,11 +305,19 @@ public class LayoutElementBuildersRegistry { final JpsArtifact artifact = element.getArtifactReference().resolve(); if (artifact == null) return; + Set<JpsArtifact> parentArtifacts = builderContext.getParentArtifacts(); + List<JpsPackagingElement> customLayout = getCustomArtifactLayout(artifact, parentArtifacts); + final String outputPath = artifact.getOutputPath(); - if (StringUtil.isEmpty(outputPath)) { + if (StringUtil.isEmpty(outputPath) || customLayout != null) { try { if (builderContext.enterArtifact(artifact)) { - generateSubstitutionInstructions(element, instructionCreator, builderContext); + if (customLayout != null) { + LayoutElementBuildersRegistry.this.generateInstructions(customLayout, instructionCreator, builderContext); + } + else { + generateSubstitutionInstructions(element, instructionCreator, builderContext); + } } } finally { @@ -328,5 +336,16 @@ public class LayoutElementBuildersRegistry { instructionCreator.addDirectoryCopyInstructions(outputDir); } } + + @Nullable + private List<JpsPackagingElement> getCustomArtifactLayout(@NotNull JpsArtifact artifact, @NotNull Set<JpsArtifact> parentArtifacts) { + for (ArtifactLayoutCustomizationService service : JpsServiceManager.getInstance().getExtensions(ArtifactLayoutCustomizationService.class)) { + List<JpsPackagingElement> elements = service.getCustomizedLayout(artifact, parentArtifacts); + if (elements != null) { + return elements; + } + } + return null; + } } } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JpsArtifactUtil.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JpsArtifactUtil.java index f91a576366b6..55c8b3478269 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JpsArtifactUtil.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JpsArtifactUtil.java @@ -15,6 +15,7 @@ */ package org.jetbrains.jps.incremental.artifacts.impl; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.Processor; import com.intellij.util.containers.HashSet; import org.jetbrains.annotations.NotNull; @@ -55,4 +56,8 @@ public class JpsArtifactUtil { } return true; } + + public static boolean isArchiveName(String name) { + return name.length() >= 4 && name.charAt(name.length() - 4) == '.' && StringUtil.endsWithIgnoreCase(name, "ar"); + } } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderContext.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderContext.java index 5d201f17e529..91256a63ab4b 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderContext.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderContext.java @@ -15,10 +15,13 @@ */ package org.jetbrains.jps.incremental.artifacts.instructions; +import org.jetbrains.annotations.NotNull; import org.jetbrains.jps.builders.storage.BuildDataPaths; import org.jetbrains.jps.model.JpsModel; import org.jetbrains.jps.model.artifact.JpsArtifact; +import java.util.Set; + /** * @author nik */ @@ -31,4 +34,7 @@ public interface ArtifactInstructionsBuilderContext { BuildDataPaths getDataPaths(); JpsModel getModel(); + + @NotNull + Set<JpsArtifact> getParentArtifacts(); } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderContextImpl.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderContextImpl.java index 0d2cf4b2dc4d..88e9139f4579 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderContextImpl.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderContextImpl.java @@ -15,6 +15,7 @@ */ package org.jetbrains.jps.incremental.artifacts.instructions; +import org.jetbrains.annotations.NotNull; import org.jetbrains.jps.builders.storage.BuildDataPaths; import org.jetbrains.jps.model.JpsModel; import org.jetbrains.jps.model.artifact.JpsArtifact; @@ -52,6 +53,12 @@ public class ArtifactInstructionsBuilderContextImpl implements ArtifactInstructi } @Override + @NotNull + public Set<JpsArtifact> getParentArtifacts() { + return myParentArtifacts; + } + + @Override public void leaveArtifact(JpsArtifact artifact) { myParentArtifacts.remove(artifact); } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/BuildingTargetProgressMessage.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/BuildingTargetProgressMessage.java new file mode 100644 index 000000000000..50399f74baab --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/BuildingTargetProgressMessage.java @@ -0,0 +1,47 @@ +package org.jetbrains.jps.incremental.messages; + +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.NotNullFunction; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.builders.BuildTarget; + +import java.util.Collection; + +/** + * @author nik + */ +public class BuildingTargetProgressMessage extends BuildMessage { + private final Collection<? extends BuildTarget<?>> myTargets; + @NotNull private final Event myEventType; + + public enum Event { + STARTED, FINISHED + } + + public BuildingTargetProgressMessage(@NotNull Collection<? extends BuildTarget<?>> targets, @NotNull Event event) { + super(composeMessageText(targets, event), Kind.PROGRESS); + myTargets = targets; + myEventType = event; + } + + private static String composeMessageText(Collection<? extends BuildTarget<?>> targets, Event event) { + String targetsString = StringUtil.join(targets, new NotNullFunction<BuildTarget<?>, String>() { + @NotNull + @Override + public String fun(BuildTarget<?> dom) { + return dom.getPresentableName(); + } + }, ", "); + return (event == Event.STARTED ? "Started" : "Finished") + " building " + targetsString; + } + + @NotNull + public Collection<? extends BuildTarget<?>> getTargets() { + return myTargets; + } + + @NotNull + public Event getEventType() { + return myEventType; + } +} diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java b/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java index 6e38f95a7c52..3fec8d342cbb 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java +++ b/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java @@ -16,6 +16,7 @@ package org.jetbrains.ether; import com.intellij.openapi.application.ex.PathManagerEx; +import com.intellij.openapi.util.io.FileSystemUtil; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.Processor; @@ -110,12 +111,15 @@ public abstract class IncrementalTestCase extends JpsBuildTestCase { return true; } }); + final long[] timestamp = {0}; FileUtil.processFilesRecursively(baseDir, new Processor<File>() { @Override public boolean process(File file) { try { if (file.getName().endsWith(newSuffix)) { - FileUtil.copyContent(file, getTargetFile(file, newSuffix)); + File targetFile = getTargetFile(file, newSuffix); + FileUtil.copyContent(file, targetFile); + timestamp[0] = Math.max(timestamp[0], FileSystemUtil.lastModified(targetFile)); } } catch (IOException e) { @@ -124,13 +128,7 @@ public abstract class IncrementalTestCase extends JpsBuildTestCase { return true; } }); - if (TIMESTAMP_ACCURACY > 1) { - try { - Thread.sleep(TIMESTAMP_ACCURACY); - } - catch (InterruptedException ignored) { - } - } + sleepUntil(timestamp[0]); } private File getTargetFile(File sourceFile, final String suffix) { diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JpsBuildTestCase.java b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JpsBuildTestCase.java index 68b617670adc..5e353c9315c8 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JpsBuildTestCase.java +++ b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JpsBuildTestCase.java @@ -17,7 +17,6 @@ package org.jetbrains.jps.builders; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.application.ex.PathManagerEx; -import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileSystemUtil; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; @@ -67,7 +66,6 @@ import static org.jetbrains.jps.builders.CompileScopeTestBuilder.make; * @author nik */ public abstract class JpsBuildTestCase extends UsefulTestCase { - protected static final long TIMESTAMP_ACCURACY = SystemInfo.isMac ? 1000 : 1; private File myProjectDir; protected JpsProject myProject; protected JpsModel myModel; @@ -118,19 +116,15 @@ public abstract class JpsBuildTestCase extends UsefulTestCase { long time = System.currentTimeMillis(); setLastModified(file, time); if (FileSystemUtil.lastModified(file) <= oldTimestamp) { - setLastModified(file, time + TIMESTAMP_ACCURACY); + setLastModified(file, time + 1); long newTimeStamp = FileSystemUtil.lastModified(file); - assertTrue("Failed to change timestamp for " + file.getAbsolutePath(), newTimeStamp > oldTimestamp); - long delta; - while ((delta = newTimeStamp - System.currentTimeMillis()) > 0) { - try { - //we need this to ensure that the file won't be treated as changed by user during compilation and marked for recompilation - //noinspection BusyWait - Thread.sleep(delta); - } - catch (InterruptedException ignored) { - } + if (newTimeStamp <= oldTimestamp) { + //Mac OS and some versions of Linux truncates timestamp to nearest second + setLastModified(file, time + 1000); + newTimeStamp = FileSystemUtil.lastModified(file); + assertTrue("Failed to change timestamp for " + file.getAbsolutePath(), newTimeStamp > oldTimestamp); } + sleepUntil(newTimeStamp); } } catch (IOException e) { @@ -138,6 +132,19 @@ public abstract class JpsBuildTestCase extends UsefulTestCase { } } + protected static void sleepUntil(long time) { + //we need this to ensure that the file won't be treated as changed by user during compilation and therefore marked for recompilation + long delta; + while ((delta = time - System.currentTimeMillis()) > 0) { + try { + //noinspection BusyWait + Thread.sleep(delta); + } + catch (InterruptedException ignored) { + } + } + } + private static void setLastModified(File file, long time) { boolean updated = file.setLastModified(time); assertTrue("Cannot modify timestamp for " + file.getAbsolutePath(), updated); diff --git a/jps/standalone-builder/src/org/jetbrains/jps/build/Standalone.java b/jps/standalone-builder/src/org/jetbrains/jps/build/Standalone.java index e52c8ac3b087..4572c4d32d1c 100644 --- a/jps/standalone-builder/src/org/jetbrains/jps/build/Standalone.java +++ b/jps/standalone-builder/src/org/jetbrains/jps/build/Standalone.java @@ -55,6 +55,9 @@ public class Standalone { @Argument(value = "modules", prefix = "--", delimiter = ",", description = "Comma-separated list of modules to compile") public String[] modules = ArrayUtil.EMPTY_STRING_ARRAY; + @Argument(value = "all-modules", prefix = "--", description = "Compile all modules") + public boolean allModules; + @Argument(value = "artifacts", prefix = "--", delimiter = ",", description = "Comma-separated list of artifacts to build") public String[] artifacts = ArrayUtil.EMPTY_STRING_ARRAY; @@ -81,8 +84,6 @@ public class Standalone { printUsageAndExit(); } - - instance.loadAndRunBuild(projectPaths.get(0)); System.exit(0); } @@ -114,6 +115,11 @@ public class Standalone { initializer = new GroovyModelInitializer(scriptFile); } + if (modules.length == 0 && artifacts.length == 0 && !allModules) { + System.err.println("Nothing to compile: at least one of --modules, --artifacts or --all-modules parameters must be specified"); + return; + } + JpsModelLoaderImpl loader = new JpsModelLoaderImpl(projectPath, globalOptionsPath, initializer); Set<String> modulesSet = new HashSet<String>(Arrays.asList(modules)); List<String> artifactsList = Arrays.asList(artifacts); @@ -131,7 +137,7 @@ public class Standalone { long start = System.currentTimeMillis(); try { - runBuild(loader, dataStorageRoot, !incremental, modulesSet, artifactsList, true, new ConsoleMessageHandler()); + runBuild(loader, dataStorageRoot, !incremental, modulesSet, allModules, artifactsList, true, new ConsoleMessageHandler()); } catch (Throwable t) { System.err.println("Internal error: " + t.getMessage()); @@ -140,28 +146,35 @@ public class Standalone { System.out.println("Build finished in " + Utils.formatDuration(System.currentTimeMillis() - start)); } + @Deprecated public static void runBuild(JpsModelLoader loader, final File dataStorageRoot, boolean forceBuild, Set<String> modulesSet, List<String> artifactsList, final boolean includeTests, final MessageHandler messageHandler) throws Exception { + runBuild(loader, dataStorageRoot, forceBuild, modulesSet, modulesSet.isEmpty(), artifactsList, includeTests, messageHandler); + } + + public static void runBuild(JpsModelLoader loader, final File dataStorageRoot, boolean forceBuild, Set<String> modulesSet, + final boolean allModules, List<String> artifactsList, final boolean includeTests, + final MessageHandler messageHandler) throws Exception { List<TargetTypeBuildScope> scopes = new ArrayList<TargetTypeBuildScope>(); for (JavaModuleBuildTargetType type : JavaModuleBuildTargetType.ALL_TYPES) { if (includeTests || !type.isTests()) { TargetTypeBuildScope.Builder builder = TargetTypeBuildScope.newBuilder().setTypeId(type.getTypeId()).setForceBuild(forceBuild); - if (modulesSet.isEmpty()) { - builder.setAllTargets(true); + if (allModules) { + scopes.add(builder.setAllTargets(true).build()); } - else { - builder.addAllTargetId(modulesSet); + else if (!modulesSet.isEmpty()) { + scopes.add(builder.addAllTargetId(modulesSet).build()); } - scopes.add(builder.build()); } } if (!artifactsList.isEmpty()) { scopes.add(TargetTypeBuildScope.newBuilder().setTypeId(ArtifactBuildTargetType.INSTANCE.getTypeId()).setForceBuild(forceBuild).addAllTargetId(artifactsList).build()); } - final BuildRunner buildRunner = new BuildRunner(loader, scopes, Collections.<String>emptyList(), Collections.<String, String>emptyMap()); + + final BuildRunner buildRunner = new BuildRunner(loader, Collections.<String>emptyList(), Collections.<String, String>emptyMap()); ProjectDescriptor descriptor = buildRunner.load(messageHandler, dataStorageRoot, new BuildFSState(true)); try { - buildRunner.runBuild(descriptor, CanceledStatus.NULL, null, messageHandler, BuildType.BUILD); + buildRunner.runBuild(descriptor, CanceledStatus.NULL, null, messageHandler, BuildType.BUILD, scopes, true); } finally { descriptor.release(); diff --git a/jps/standalone-builder/src/org/jetbrains/jps/gant/JpsGantProjectBuilder.java b/jps/standalone-builder/src/org/jetbrains/jps/gant/JpsGantProjectBuilder.java index 3ec94962dd20..838b9ebbd60a 100644 --- a/jps/standalone-builder/src/org/jetbrains/jps/gant/JpsGantProjectBuilder.java +++ b/jps/standalone-builder/src/org/jetbrains/jps/gant/JpsGantProjectBuilder.java @@ -133,19 +133,19 @@ public class JpsGantProjectBuilder { } public void makeModule(JpsModule module) { - runBuild(getModuleDependencies(module, false), false); + runBuild(getModuleDependencies(module, false), false, false); } public void makeModuleTests(JpsModule module) { - runBuild(getModuleDependencies(module, true), true); + runBuild(getModuleDependencies(module, true), false, true); } public void buildAll() { - runBuild(Collections.<String>emptySet(), true); + runBuild(Collections.<String>emptySet(), true, true); } public void buildProduction() { - runBuild(Collections.<String>emptySet(), false); + runBuild(Collections.<String>emptySet(), true, false); } public void exportModuleOutputProperties() { @@ -166,14 +166,14 @@ public class JpsGantProjectBuilder { return names; } - private void runBuild(final Set<String> modulesSet, boolean includeTests) { + private void runBuild(final Set<String> modulesSet, final boolean allModules, boolean includeTests) { if (!myDryRun) { final AntMessageHandler messageHandler = new AntMessageHandler(); Logger.setFactory(new AntLoggerFactory(messageHandler)); info("Starting build: modules = " + modulesSet + ", caches are saved to " + myDataStorageRoot.getAbsolutePath()); try { - Standalone.runBuild(myModelLoader, myDataStorageRoot, true, modulesSet, Collections.<String>emptyList(), - includeTests, messageHandler); + Standalone.runBuild(myModelLoader, myDataStorageRoot, true, modulesSet, allModules, Collections.<String>emptyList(), includeTests, + messageHandler); } catch (Throwable e) { error(e); |