[GRADLE-1942] Do whatever possible to limit paths lengths in Windows Created: 18/Nov/11  Updated: 04/Jan/13  Resolved: 17/May/12

Status: Resolved
Project: Gradle
Affects Version/s: 1.0-milestone-5
Fix Version/s: 1.0-rc-1

Type: Bug
Reporter: Mauro Molinari Assignee: Unassigned
Resolution: Fixed Votes: 0


 Description   

I'm working on a huge project with many JARs.
I can't build this project anymore, because dependency paths have become so long that they break the 8K limit of paths length supported by Windows (see http://support.microsoft.com/kb/830473/en-us).
Where Gradle is failing:

  • running external Java Processes where paths must be passed as command line arguments
  • compiling Groovy code with Groovyc when the default fork behaviour is used
  • applying operations on file collections; for instance, I'm now getting the following error:
org.gradle.api.UncheckedIOException: Could not normalise path for file '<a series of JAR file paths separated by ";" and of about 13K of total length written here>'.
        at org.gradle.api.internal.file.AbstractFileResolver.normalise(AbstractFileResolver.java:110)
        at org.gradle.api.internal.file.AbstractFileResolver.resolve(AbstractFileResolver.java:54)
        at org.gradle.api.internal.file.AbstractFileResolver.resolve(AbstractFileResolver.java:48)
        at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext$FileCollectionConverter.convertInto(DefaultFileCollectionResolveContext.java:165)
        at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext.doResolve(DefaultFileCollectionResolveContext.java:126)
        at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext.resolveAsFileCollections(DefaultFileCollectionResolveContext.java:80)
        at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext$FileCollectionConverter.convertInto(DefaultFileCollectionResolveContext.java:149)
        at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext.doResolve(DefaultFileCollectionResolveContext.java:96)
        at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext.resolveAsFileCollections(DefaultFileCollectionResolveContext.java:80)
        at org.gradle.api.internal.changedetection.DefaultFileCacheListener.cacheable(DefaultFileCacheListener.java:29)
        at org.gradle.api.internal.changedetection.FileCacheBroadcastTaskArtifactStateRepository$1.isUpToDate(FileCacheBroadcastTaskArtifactStateRepository.java:34)
        at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:44)
        at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:57)
        at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:41)
        at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:51)
        at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:52)
        at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:42)
        at org.gradle.api.internal.AbstractTask.executeWithoutThrowingTaskFailure(AbstractTask.java:243)
        at org.gradle.execution.DefaultTaskGraphExecuter.executeTask(DefaultTaskGraphExecuter.java:192)
        at org.gradle.execution.DefaultTaskGraphExecuter.doExecute(DefaultTaskGraphExecuter.java:177)
        at org.gradle.execution.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:83)
        at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:36)
        at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:70)
        at org.gradle.execution.DefaultBuildExecuter.access$300(DefaultBuildExecuter.java:23)
        at org.gradle.execution.DefaultBuildExecuter$2.proceed(DefaultBuildExecuter.java:80)
        at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)
        at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:70)
        at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:63)
        at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:157)
        at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:112)
        at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:80)
        at org.gradle.launcher.cli.RunBuildAction.execute(RunBuildAction.java:42)
        at org.gradle.launcher.cli.RunBuildAction.execute(RunBuildAction.java:28)
        at org.gradle.launcher.exec.ExceptionReportingAction.execute(ExceptionReportingAction.java:32)
        at org.gradle.launcher.exec.ExceptionReportingAction.execute(ExceptionReportingAction.java:21)
        at org.gradle.launcher.cli.CommandLineActionFactory$WithLoggingAction.execute(CommandLineActionFactory.java:233)
        at org.gradle.launcher.cli.CommandLineActionFactory$WithLoggingAction.execute(CommandLineActionFactory.java:217)
        at org.gradle.launcher.Main.doAction(Main.java:48)
        at org.gradle.launcher.exec.EntryPoint$1.execute(EntryPoint.java:53)
        at org.gradle.launcher.exec.EntryPoint$1.execute(EntryPoint.java:51)
        at org.gradle.launcher.exec.Execution.execute(Execution.java:28)
        at org.gradle.launcher.exec.EntryPoint.run(EntryPoint.java:39)
        at org.gradle.launcher.Main.main(Main.java:39)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.gradle.launcher.ProcessBootstrap.runNoExit(ProcessBootstrap.java:51)
        at org.gradle.launcher.ProcessBootstrap.run(ProcessBootstrap.java:33)
        at org.gradle.launcher.GradleMain.main(GradleMain.java:24)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.gradle.wrapper.BootstrapMainStarter.start(BootstrapMainStarter.java:33)
        at org.gradle.wrapper.WrapperExecutor.execute(WrapperExecutor.java:124)
        at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:53)
Caused by: java.io.IOException: La sintassi del nome del file, della directory o del volume non Þ corretta
        at java.io.WinNTFileSystem.canonicalize0(Native Method)
        at java.io.Win32FileSystem.canonicalize(Win32FileSystem.java:396)
        at java.io.File.getCanonicalPath(File.java:559)
        at java.io.File.getCanonicalFile(File.java:583)
        at org.gradle.api.internal.file.AbstractFileResolver.normalise(AbstractFileResolver.java:66)
        ... 56 more

This happens even if I'm using a very short path for my project (like d:\K520) and an even shorter path for Gradle home (g:\G - I'm specifying it to Gradle using -g switch).

JAR chaches produced by Gradle are using very long paths. As an example:
G:\G\caches\artifacts-3\org.springframework\org.springframework.context\595e29a604c1f3c816a938635de21eb2\jars\org.springframework.context-3.0.5.RELEASE.jar
This is for just one dependency! And, if you consider that the default Gradle home is not at G:\G, but at C:\Users\<username>\.gradle (for Windows 7... it's even worse in Windows XP, where "Documents And Settings" is used instead of "Users"), it's quite easy to get out of the 8191 max path length.

Please do something in this area, otherwise I won't be able to build with Gradle anymore on my Windows system!



 Comments   
Comment by Adam Murdoch [ 08/May/12 ]

There have been many improvements in this area in Gradle since milestone-5. Can you try your build with a recent nightly build from http://gradle.org/nightly, and let us know how you go?

Comment by Mauro Molinari [ 14/May/12 ]

Hi Adam, I just made some checkings with 1.0-rc-3. Is it a good candidate to test? Or should I actually use a nightly build?

I completely emptied the Gradle home directory and invoked Gradle 1.0-rc-3 so that JARs were re-cached. The same JAR I mentioned in my report is now located at:

G:\G\caches\artifacts-13\filestore\org.springframework\org.springframework.context\3.0.5.RELEASE\jar\6b05e397566cc7750d2d25f81a7441fe1aeecb75\org.springframework.context-3.0.5.RELEASE.jar

which doesn't seem any shorter to me... It's even longer, because even if "jar" replaces "jars", the "filestore" subfolder was introduced.

Comment by Adam Murdoch [ 14/May/12 ]

Right, but does your build work? Many things in Gradle don't care about the path length any more, and will quite happily deal with any length of path and any number of class path entries. I'd like to know if we've missed any.

Comment by Mauro Molinari [ 15/May/12 ]

Hi Adam,
today I was able to complete a full build of our project. Actually, with 1.0-rc-3 I can complete it even if fork is enabled for the Groovy compiler.
With previous versions I had to set

[compileGroovy, compileTestGroovy]*.groovyOptions*.fork = false

otherwise the build failed with the aforementioned error (or something similar).

So, yes, the situation has improved here.
For me, you can close this bug. If I'll ever encounter other problems related to this aspect, I'll let you know.

Thank you Adam!

Generated at Wed Jun 30 12:08:31 CDT 2021 using Jira 8.4.2#804003-sha1:d21414fc212e3af190e92c2d2ac41299b89402cf.