Reputation: 5526
I have a complex Android project consisting of multiple Java and C++ modules and using several build tools (e.g. CMake, swig). The project builds just fine when built from the command line using ./gradlew clean assembleDebug
but fails to build when built from Android Studio. I cleaned, invalidated caches, synced, etc to no avail.
Important to note: this project builds fine in Android Studio too on other systems like Ubuntu (17.* and 18.*) but fails on MacOS (10.13 but also earlier if I remember correctly).
Here is the error reported by Android Studio:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':IndoorsLocator:runSwig'.
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:84)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:55)
at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:62)
at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:88)
at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:46)
at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:51)
at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:54)
at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:34)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker$1.execute(DefaultTaskGraphExecuter.java:236)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker$1.execute(DefaultTaskGraphExecuter.java:228)
at org.gradle.internal.Transformers$4.transform(Transformers.java:169)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:106)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:61)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:228)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:215)
at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:77)
at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:58)
at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:32)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:113)
at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:37)
at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
at org.gradle.execution.DefaultBuildExecuter.access$000(DefaultBuildExecuter.java:23)
at org.gradle.execution.DefaultBuildExecuter$1.proceed(DefaultBuildExecuter.java:43)
at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)
at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:30)
at org.gradle.initialization.DefaultGradleLauncher$3.execute(DefaultGradleLauncher.java:196)
at org.gradle.initialization.DefaultGradleLauncher$3.execute(DefaultGradleLauncher.java:193)
at org.gradle.internal.Transformers$4.transform(Transformers.java:169)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:106)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:56)
at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:193)
at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:119)
at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:102)
at org.gradle.launcher.exec.GradleBuildController.run(GradleBuildController.java:71)
at org.gradle.tooling.internal.provider.runner.BuildModelActionRunner.run(BuildModelActionRunner.java:50)
at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
at org.gradle.tooling.internal.provider.runner.RunAsBuildOperationBuildActionRunner$1.execute(RunAsBuildOperationBuildActionRunner.java:43)
at org.gradle.tooling.internal.provider.runner.RunAsBuildOperationBuildActionRunner$1.execute(RunAsBuildOperationBuildActionRunner.java:40)
at org.gradle.internal.Transformers$4.transform(Transformers.java:169)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:106)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:56)
at org.gradle.tooling.internal.provider.runner.RunAsBuildOperationBuildActionRunner.run(RunAsBuildOperationBuildActionRunner.java:40)
at org.gradle.tooling.internal.provider.runner.SubscribableBuildActionRunner.run(SubscribableBuildActionRunner.java:75)
at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:41)
at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:26)
at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:75)
at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:49)
at org.gradle.tooling.internal.provider.ServicesSetupBuildActionExecuter.execute(ServicesSetupBuildActionExecuter.java:44)
at org.gradle.tooling.internal.provider.ServicesSetupBuildActionExecuter.execute(ServicesSetupBuildActionExecuter.java:29)
at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:67)
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:47)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:26)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:34)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:74)
at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:72)
at org.gradle.util.Swapper.swap(Swapper.java:38)
at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:72)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.LogAndCheckHealth.execute(LogAndCheckHealth.java:55)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:60)
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:72)
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:50)
at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:297)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)
at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.gradle.process.internal.ExecException: A problem occurred starting process 'command 'swig''
at org.gradle.process.internal.DefaultExecHandle.setEndStateInfo(DefaultExecHandle.java:198)
at org.gradle.process.internal.DefaultExecHandle.failed(DefaultExecHandle.java:329)
at org.gradle.process.internal.ExecHandleRunner.run(ExecHandleRunner.java:86)
... 5 more
Caused by: net.rubygrapefruit.platform.NativeException: Could not start 'swig'
at net.rubygrapefruit.platform.internal.DefaultProcessLauncher.start(DefaultProcessLauncher.java:27)
at net.rubygrapefruit.platform.internal.WrapperProcessLauncher.start(WrapperProcessLauncher.java:36)
at org.gradle.process.internal.ExecHandleRunner.run(ExecHandleRunner.java:68)
... 5 more
Caused by: java.io.IOException: Cannot run program "swig" (in directory "/Users/tom/workspace/indoors-scripts/setup-scripts/workspace-android/IndoorsAndroid/IndoorsLocator"): error=2, No such file or directory
at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048)
at net.rubygrapefruit.platform.internal.DefaultProcessLauncher.start(DefaultProcessLauncher.java:25)
... 7 more
Caused by: java.io.IOException: error=2, No such file or directory
at java.lang.UNIXProcess.forkAndExec(Native Method)
at java.lang.UNIXProcess.<init>(UNIXProcess.java:247)
at java.lang.ProcessImpl.start(ProcessImpl.java:134)
at java.lang.ProcessBuilder.start(ProcessBuilder.java:1029)
... 8 more
Here is what the definition of "runSwig"-task looks like:
task runSwig(type: Exec) {
commandLine 'swig'
doFirst {
coreWrapperDir.mkdirs()
}
def swigFileCore = "${projectDir}/src/" + "swig.i"
def headerFiles = "${projectDir}/include"
def swigWrapFile = 'src/swig_wrap.cxx'
inputs.file swigFileCore
inputs.dir headerFiles
outputs.dir coreWrapperDir.absolutePath
outputs.file swigWrapFile
// this write the generated swig C++ file to "${projectDir}/src"
args '-c++', '-java', '-package', javaPackage, '-noexcept', '-outdir', coreWrapperDir.absolutePath, "-I${headerFiles}", '-o', swigWrapFile, swigFileCore
}
The log indicates that Android Studio is looking for swig in the current working directory instead of looking it up inside $PATH, but I am clueless about how to tell Android Studio where to look instead. Any ideas?
Cannot run program "swig" (in directory "/Users/tom/workspace/indoors-scripts/setup-scripts/workspace-android/IndoorsAndroid/IndoorsLocator")
Upvotes: 9
Views: 1467
Reputation: 5526
Turns out this is due to a "bug" in OSX: https://github.com/gradle/gradle/issues/5631#issuecomment-401775152
I did not find a way to easily fix it for the latest version of OSX (https://apple.stackexchange.com/questions/106355/setting-the-system-wide-path-environment-variable-in-mavericks) but worked around it by hardcoding the path in build.gradle:
task runSwig(type: Exec) {
// workaround for OSX, see https://stackoverflow.com/q/51383822/198996
File testFile = new File('/usr/local/bin/swig');
if (testFile.isFile()) {
commandLine '/usr/local/bin/swig'
} else {
commandLine 'swig'
}
}
That's an awful workaround if you ask me, so I would be happy to award the bounty to whoever comes up with a cleaner solution.
Upvotes: 2
Reputation: 6901
There is a need for some debugging to get more info about the problem. Add the code below to your build.gradle
file of IndoorsLocator
module and run it again. This should print the path environment variable and also run a java command which I'm assuming is also within the path. Then perform a gradle sync and compile or run the code. Open the build window as in your first image and when the build stops, find the testPath
within the Run tasks
list and share it's output. Or more preferably, switch the Build
to text view as in the image below and share the complete log. Testing it from the command would also help to make sure that it's running as expected.
tasks.whenTaskAdded { addedTask ->
if (addedTask.name.startsWith("preDebugBuild")) {
addedTask.dependsOn 'testPath'
}
}
task testPath {
mustRunBefore 'checkDebugManifest'
doLast {
exec {
commandLine 'echo', '$PATH'
}
exec {
commandLine 'java', '-version'
}
}
}
Based on your first comment, this is a weird outcome! Java is supposed to be in the path, so $PATH must've been set somehow yet echo $PATH
didn't work. Updated the code to further go down the rabbit hole.
tasks.whenTaskAdded { addedTask ->
if (addedTask.name.startsWith("preDebugBuild")) {
addedTask.dependsOn 'testPath'
}
}
task testPath {
doLast {
exec {
commandLine 'printenv'
}
exec {
commandLine 'which', 'java'
}
exec {
commandLine 'which', 'swig'
}
}
}
PS: my mistake on the mustRunBefore
, it doesn't exist and I added it accident!
Upvotes: 2
Reputation: 2623
Have you added this line in your build.gradle?
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn runSwig
}
Anyway you can refer to this github's project that uses swig: https://github.com/sureshjoshi/android-ndk-swig-example
Upvotes: 1