László Csomor has uploaded this change for review.
WIP: android on windows
Change-Id: I3e966dfae841ba1ce7116d880f09bb775c5b5cdf
---
M WORKSPACE
M src/main/java/com/google/devtools/build/lib/BUILD
M src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaSemantics.java
M src/main/java/com/google/devtools/build/lib/bazel/rules/java/java_stub_template.txt
M src/main/java/com/google/devtools/build/lib/bazel/rules/java/java_stub_template_windows.txt
M src/main/java/com/google/devtools/build/lib/bazel/rules/sh/ShBinary.java
A src/main/java/com/google/devtools/build/lib/bazel/rules/sh/sh_stub_template_windows.txt
M src/main/java/com/google/devtools/build/lib/rules/android/AarGeneratorBuilder.java
M src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourceMergingActionBuilder.java
M src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourceValidatorActionBuilder.java
M src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourcesProcessorBuilder.java
M src/main/java/com/google/devtools/build/lib/rules/android/LibraryRGeneratorActionBuilder.java
M src/main/java/com/google/devtools/build/lib/rules/android/ManifestMergerActionBuilder.java
M src/main/java/com/google/devtools/build/lib/rules/android/RClassGeneratorActionBuilder.java
M src/main/java/com/google/devtools/build/lib/rules/android/ResourceShrinkerActionBuilder.java
M src/main/java/com/google/devtools/build/lib/rules/android/RobolectricResourceSymbolsActionBuilder.java
M src/main/java/com/google/devtools/build/lib/util/ProcessUtils.java
M src/main/java/com/google/devtools/build/lib/windows/WindowsFileSystem.java
D src/main/java/com/google/devtools/build/lib/windows/WindowsJniLoader.java
M src/main/java/com/google/devtools/build/lib/windows/WindowsSubprocess.java
M src/main/java/com/google/devtools/build/lib/windows/WindowsSubprocessFactory.java
A src/main/java/com/google/devtools/build/lib/windows/jni/BUILD
R src/main/java/com/google/devtools/build/lib/windows/jni/WindowsFileOperations.java
A src/main/java/com/google/devtools/build/lib/windows/jni/WindowsJniLoader.java
R src/main/java/com/google/devtools/build/lib/windows/jni/WindowsProcesses.java
R src/main/java/com/google/devtools/build/lib/windows/jni/WindowsRunfiles.java
M src/main/native/windows_processes.cc
M src/tools/android/java/com/google/devtools/build/android/AarGeneratorAction.java
M src/tools/android/java/com/google/devtools/build/android/AndroidDataWriter.java
M src/tools/android/java/com/google/devtools/build/android/AndroidResourceMerger.java
M src/tools/android/java/com/google/devtools/build/android/AndroidResourceMergingAction.java
M src/tools/android/java/com/google/devtools/build/android/AndroidResourceOutputs.java
M src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessingAction.java
M src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java
M src/tools/android/java/com/google/devtools/build/android/AndroidResourceValidatorAction.java
M src/tools/android/java/com/google/devtools/build/android/BUILD
M src/tools/android/java/com/google/devtools/build/android/DependencySymbolFileProvider.java
M src/tools/android/java/com/google/devtools/build/android/FullyQualifiedName.java
A src/tools/android/java/com/google/devtools/build/android/JunctionCreator.java
A src/tools/android/java/com/google/devtools/build/android/NoopJunctionCreator.java
M src/tools/android/java/com/google/devtools/build/android/ResourceProcessorBusyBox.java
M src/tools/android/java/com/google/devtools/build/android/ResourceShrinkerAction.java
A src/tools/android/java/com/google/devtools/build/android/WindowsJunctionCreator.java
M tools/android/android_sdk_repository_template.bzl
M tools/android/incremental_install.py
M tools/android/zip_manifest_creator.sh
46 files changed, 712 insertions(+), 229 deletions(-)
diff --git a/WORKSPACE b/WORKSPACE
index c083719..41a4997 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -33,6 +33,11 @@
actual = "//third_party/py/six",
)
+local_repository(
+ name = "protobuf",
+ path = "c:\\work\\protobuf",
+)
+
# For tools/cpp/test/...
load("//tools/cpp/test:docker_repository.bzl", "docker_repository")
@@ -108,3 +113,16 @@
"https://cdn.azul.com/zulu/bin/zulu8.21.0.1-jdk8.0.131-win_x64.zip",
],
)
+
+android_sdk_repository(
+ name = "androidsdk",
+ path = "c:\\Users\\laszlocsomor\\AppData\\Local\\Android\\sdk",
+ api_level = 25,
+ build_tools_version = "25.0.3",
+)
+
+android_ndk_repository(
+ name = "androidndk",
+ path = "c:\\Users\\laszlocsomor\\AppData\\Local\\Android\\sdk\\ndk-bundle",
+ api_level = 25,
+)
diff --git a/src/main/java/com/google/devtools/build/lib/BUILD b/src/main/java/com/google/devtools/build/lib/BUILD
index 8686b47..d6deab3 100644
--- a/src/main/java/com/google/devtools/build/lib/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/BUILD
@@ -42,6 +42,7 @@
"//src/main/java/com/google/devtools/build/lib/sandbox:srcs",
"//src/main/java/com/google/devtools/build/lib/ssd:srcs",
"//src/main/java/com/google/devtools/build/lib/standalone:srcs",
+ "//src/main/java/com/google/devtools/build/lib/windows/jni:srcs",
"//src/main/java/com/google/devtools/build/lib/worker:srcs",
"//src/main/java/com/google/devtools/build/skyframe:srcs",
"//src/main/java/com/google/devtools/common/options:srcs",
@@ -102,6 +103,7 @@
":preconditions",
":shell",
":vfs",
+ "//src/main/java/com/google/devtools/build/lib/windows/jni",
"//src/main/java/com/google/devtools/common/options",
"//third_party:guava",
"//third_party:jsr305",
@@ -727,6 +729,7 @@
"bazel/rules/java/java_stub_template.txt",
"bazel/rules/java/java_stub_template_windows.txt",
"bazel/rules/python/python_stub_template.txt",
+ "bazel/rules/sh/sh_stub_template_windows.txt",
],
deps = [
":bazel",
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaSemantics.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaSemantics.java
index 293091f..4d3f7e2 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaSemantics.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaSemantics.java
@@ -330,13 +330,6 @@
ruleContext
.getFragment(BazelConfiguration.class)
.getShellExecutable()
- .getPathString()),
- Substitution.of(
- "%cygpath_exe_path%",
- ruleContext
- .getFragment(BazelConfiguration.class)
- .getShellExecutable()
- .replaceName("cygpath.exe")
.getPathString())),
true));
return newExecutable;
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/java_stub_template.txt b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/java_stub_template.txt
index ba35a95..fc8fdad 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/java_stub_template.txt
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/java_stub_template.txt
@@ -44,6 +44,9 @@
#
# The remainder of the command line is passed to the program.
+export MSYS_NO_PATHCONV=1
+export MSYS2_ARG_CONV_EXCL="*"
+
# Make it easy to insert 'set -x' or similar commands when debugging problems with this script.
eval "$JAVA_STUB_DEBUG"
@@ -173,7 +176,7 @@
JAVA_RUNFILES=$(cygpath --windows "$JAVA_RUNFILES")
fi
-RUNFILES_MANIFEST_FILE="${JAVA_RUNFILES}/MANIFEST"
+export RUNFILES_MANIFEST_FILE="${JAVA_RUNFILES}/MANIFEST"
RUNFILES_MANIFEST_ONLY=%runfiles_manifest_only%
if [ -z "$RUNFILES_MANIFEST_ONLY" ]; then
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/java_stub_template_windows.txt b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/java_stub_template_windows.txt
index 445da77..a765474 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/java_stub_template_windows.txt
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/java_stub_template_windows.txt
@@ -17,16 +17,37 @@
@rem See the header comments in the accompanying shell script (same path as that
@rem of this file, minus the ".cmd" extension) for available command line flags.
-@SETLOCAL ENABLEEXTENSIONS
+@echo off
+SETLOCAL ENABLEEXTENSIONS
-@set bash_path=%bash_exe_path%
+set bash_path=%bash_exe_path%
-@rem launcher=${$0%.cmd}
-@set launcher=%~dp0%~n0
+rem sh_path=${$0%.cmd}
+set sh_path=%~dp0%~n0
-@set sh_path=%launcher:\=/%
+set argv=%*
-@rem replaces $ with \$ in $*, then puts it on the command line
-@rem Cribbed from here: http://ss64.com/nt/syntax-replace.html
-@set all_args=%*
-@call %bash_path% -c "'%sh_path%' %all_args:$=\$%"
+rem Create temp file for Bash params file
+for /f %%i in ('c:\tools\msys64\usr\bin\mktemp.exe -p c:/tempdir %~n0.XXXXXXXX.flags') do set sh_flags=%%i
+
+rem Touch %sh_flags% to ensure it exists.
+echo. > %sh_flags%
+
+rem Check that %1, stripped of its outer double quotes if any, is not equal
+rem to a pair of double quotes, i.e. it's not empty, therefore there's at
+rem least one argument to write to %sh_flags%.
+rem This is the right way to check if a string is empty (as opposed to
+rem "if [foo] == []", because it also works for args with spaces in them):
+rem Found in https://stackoverflow.com/a/2544545/7778502 .
+rem If there were no arguments and %argv% were empty, echo'ing it would
+rem print "ECHO is off." instead of an empty string.
+if not "%~1" == "" echo %argv% > %sh_flags%
+
+set sh_path=%sh_path:\=/%
+set sh_flags=%sh_flags:\=/%
+
+set TMP=c:\tempdir\tmp
+set TEMP=c:\tempdir\tmp
+set TMPDIR=c:\tempdir\tmp
+if not exist %TMP% md %TMP%
+call %bash_path% -c "'%sh_path%' $(/usr/bin/cat %sh_flags%)"
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/sh/ShBinary.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/sh/ShBinary.java
index 6da83aa..8c52a2e 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/sh/ShBinary.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/sh/ShBinary.java
@@ -23,15 +23,22 @@
import com.google.devtools.build.lib.analysis.RunfilesProvider;
import com.google.devtools.build.lib.analysis.RunfilesSupport;
import com.google.devtools.build.lib.analysis.actions.ExecutableSymlinkAction;
+import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction;
+import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction.Substitution;
+import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction.Template;
+import com.google.devtools.build.lib.bazel.rules.BazelConfiguration;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException;
import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory;
+import com.google.devtools.build.lib.util.OS;
/**
* Implementation for the sh_binary rule.
*/
public class ShBinary implements RuleConfiguredTargetFactory {
+ private static final Template STUB_SCRIPT_WINDOWS =
+ Template.forResource(ShBinary.class, "sh_stub_template_windows.txt");
@Override
public ConfiguredTarget create(RuleContext ruleContext) throws RuleErrorException {
@@ -53,20 +60,48 @@
ruleContext.registerAction(
new ExecutableSymlinkAction(ruleContext.getActionOwner(), src, symlink));
- NestedSet<Artifact> filesToBuild = NestedSetBuilder.<Artifact>stableOrder()
+ NestedSetBuilder<Artifact> filesToBuildBuilder = NestedSetBuilder.<Artifact>stableOrder()
.add(src)
- .add(symlink)
- .build();
- Runfiles runfiles = new Runfiles.Builder(
+ .add(symlink);
+
+ Artifact mainExecutable = symlink;
+ if (OS.getCurrent() == OS.WINDOWS &&
+ !symlink.getFilename().endsWith(".exe") &&
+ !symlink.getFilename().endsWith(".bat") &&
+ !symlink.getFilename().endsWith(".cmd")) {
+ mainExecutable =
+ ruleContext.getImplicitOutputArtifact(ruleContext.getTarget().getName() + ".cmd");
+ ruleContext.registerAction(
+ new TemplateExpansionAction(
+ ruleContext.getActionOwner(),
+ mainExecutable,
+ STUB_SCRIPT_WINDOWS,
+ ImmutableList.of(
+ Substitution.of(
+ "%bash_exe_path%",
+ ruleContext
+ .getFragment(BazelConfiguration.class)
+ .getShellExecutable()
+ .getPathString())),
+ true));
+ filesToBuildBuilder.add(mainExecutable);
+ }
+ NestedSet<Artifact> filesToBuild = filesToBuildBuilder.build();
+
+ Runfiles.Builder runfilesBuilder = new Runfiles.Builder(
ruleContext.getWorkspaceName(), ruleContext.getConfiguration().legacyExternalRunfiles())
.addTransitiveArtifacts(filesToBuild)
- .addRunfiles(ruleContext, RunfilesProvider.DEFAULT_RUNFILES)
- .build();
+ .addRunfiles(ruleContext, RunfilesProvider.DEFAULT_RUNFILES);
+ if (symlink != mainExecutable) {
+ runfilesBuilder.addArtifact(symlink);
+ }
+ Runfiles runfiles = runfilesBuilder.build();
+
RunfilesSupport runfilesSupport = RunfilesSupport.withExecutable(
ruleContext, runfiles, symlink);
return new RuleConfiguredTargetBuilder(ruleContext)
.setFilesToBuild(filesToBuild)
- .setRunfilesSupport(runfilesSupport, symlink)
+ .setRunfilesSupport(runfilesSupport, mainExecutable)
.addProvider(RunfilesProvider.class, RunfilesProvider.simple(runfiles))
.build();
}
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/sh/sh_stub_template_windows.txt b/src/main/java/com/google/devtools/build/lib/bazel/rules/sh/sh_stub_template_windows.txt
new file mode 100644
index 0000000..a765474
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/sh/sh_stub_template_windows.txt
@@ -0,0 +1,53 @@
+@rem Copyright 2016 The Bazel Authors. All rights reserved.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem http://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+@rem This script was generated from java_stub_template_windows.txt. Please
+@rem don't edit it directly.
+@rem See the header comments in the accompanying shell script (same path as that
+@rem of this file, minus the ".cmd" extension) for available command line flags.
+
+@echo off
+SETLOCAL ENABLEEXTENSIONS
+
+set bash_path=%bash_exe_path%
+
+rem sh_path=${$0%.cmd}
+set sh_path=%~dp0%~n0
+
+set argv=%*
+
+rem Create temp file for Bash params file
+for /f %%i in ('c:\tools\msys64\usr\bin\mktemp.exe -p c:/tempdir %~n0.XXXXXXXX.flags') do set sh_flags=%%i
+
+rem Touch %sh_flags% to ensure it exists.
+echo. > %sh_flags%
+
+rem Check that %1, stripped of its outer double quotes if any, is not equal
+rem to a pair of double quotes, i.e. it's not empty, therefore there's at
+rem least one argument to write to %sh_flags%.
+rem This is the right way to check if a string is empty (as opposed to
+rem "if [foo] == []", because it also works for args with spaces in them):
+rem Found in https://stackoverflow.com/a/2544545/7778502 .
+rem If there were no arguments and %argv% were empty, echo'ing it would
+rem print "ECHO is off." instead of an empty string.
+if not "%~1" == "" echo %argv% > %sh_flags%
+
+set sh_path=%sh_path:\=/%
+set sh_flags=%sh_flags:\=/%
+
+set TMP=c:\tempdir\tmp
+set TEMP=c:\tempdir\tmp
+set TMPDIR=c:\tempdir\tmp
+if not exist %TMP% md %TMP%
+call %bash_path% -c "'%sh_path%' $(/usr/bin/cat %sh_flags%)"
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AarGeneratorBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/android/AarGeneratorBuilder.java
index b0ffa9e..8fd7e3c 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AarGeneratorBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AarGeneratorBuilder.java
@@ -26,6 +26,7 @@
import com.google.devtools.build.lib.analysis.actions.CommandLine;
import com.google.devtools.build.lib.analysis.actions.SpawnAction;
import com.google.devtools.build.lib.rules.android.ResourceContainer.ResourceType;
+import com.google.devtools.build.lib.util.OS;
import java.util.ArrayList;
import java.util.List;
@@ -115,6 +116,9 @@
args.add(aarOut.getExecPathString());
outs.add(aarOut);
+ args.add("--hostPlatform");
+ args.add(OS.getCurrent().getCanonicalName());
+
ruleContext.registerAction(
this.builder
.addInputs(ImmutableList.<Artifact>copyOf(ins))
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourceMergingActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourceMergingActionBuilder.java
index dc84ee5..e04d7d3 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourceMergingActionBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourceMergingActionBuilder.java
@@ -25,6 +25,7 @@
import com.google.devtools.build.lib.analysis.actions.SpawnAction;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.rules.android.ResourceContainerConverter.Builder.SeparatorType;
+import com.google.devtools.build.lib.util.OS;
import java.util.ArrayList;
import java.util.List;
@@ -131,6 +132,7 @@
.getRunfilesArtifactsWithoutMiddlemen());
builder.addExecPath("--androidJar", sdk.getAndroidJar());
+ builder.add("--hostPlatform").add(OS.getCurrent().getCanonicalName());
inputs.add(sdk.getAndroidJar());
Preconditions.checkNotNull(primary);
@@ -181,6 +183,7 @@
.addTransitiveInputs(inputs.build())
.addOutputs(ImmutableList.copyOf(outs))
.setCommandLine(builder.build())
+ .alwaysUseParameterFile(ParameterFileType.UNQUOTED)
.setExecutable(
ruleContext.getExecutablePrerequisite("$android_resources_busybox", Mode.HOST))
.setProgressMessage("Merging Android resources for " + ruleContext.getLabel())
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourceValidatorActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourceValidatorActionBuilder.java
index 66e8b8b..c76dc68 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourceValidatorActionBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourceValidatorActionBuilder.java
@@ -24,6 +24,7 @@
import com.google.devtools.build.lib.analysis.actions.CustomCommandLine;
import com.google.devtools.build.lib.analysis.actions.SpawnAction;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
+import com.google.devtools.build.lib.util.OS;
import java.util.ArrayList;
import java.util.List;
@@ -99,6 +100,7 @@
}
builder.addExecPath("--aapt", sdk.getAapt().getExecutable());
+ builder.add("--hostPlatform").add(OS.getCurrent().getCanonicalName());
// Use a FluentIterable to avoid flattening the NestedSets
NestedSetBuilder<Artifact> inputs = NestedSetBuilder.naiveLinkOrder();
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourcesProcessorBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourcesProcessorBuilder.java
index 6bee442..118628c 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourcesProcessorBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourcesProcessorBuilder.java
@@ -24,6 +24,7 @@
import com.google.devtools.build.lib.analysis.actions.SpawnAction;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.rules.android.ResourceContainerConverter.Builder.SeparatorType;
+import com.google.devtools.build.lib.util.OS;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -218,6 +219,7 @@
}
builder.addExecPath("--aapt", sdk.getAapt().getExecutable());
+ builder.add("--hostPlatform").add(OS.getCurrent().getCanonicalName());
// Use a FluentIterable to avoid flattening the NestedSets
NestedSetBuilder<Artifact> inputs = NestedSetBuilder.naiveLinkOrder();
inputs.addAll(
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/LibraryRGeneratorActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/android/LibraryRGeneratorActionBuilder.java
index 361a70a..cf89d21 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/LibraryRGeneratorActionBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/LibraryRGeneratorActionBuilder.java
@@ -26,6 +26,7 @@
import com.google.devtools.build.lib.analysis.actions.SpawnAction;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.collect.nestedset.Order;
+import com.google.devtools.build.lib.util.OS;
/** Builder for the action that generates the R class for libraries. */
public class LibraryRGeneratorActionBuilder {
@@ -98,6 +99,7 @@
builder.addExecPath("--classJarOutput", rJavaClassJar);
builder.addExecPath("--androidJar", sdk.getAndroidJar());
+ builder.add("--hostPlatform").add(OS.getCurrent().getCanonicalName());
inputs.add(sdk.getAndroidJar());
// Create the spawn action.
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/ManifestMergerActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/android/ManifestMergerActionBuilder.java
index c84e3fd..f8ec20d 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/ManifestMergerActionBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/ManifestMergerActionBuilder.java
@@ -18,6 +18,7 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.ParameterFile.ParameterFileType;
import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.actions.ActionConstructionContext;
@@ -138,6 +139,7 @@
.addTransitiveInputs(inputs.build())
.addOutputs(outputs.build())
.setCommandLine(builder.build())
+ .alwaysUseParameterFile(ParameterFileType.UNQUOTED)
.setExecutable(
ruleContext.getExecutablePrerequisite("$android_resources_busybox", Mode.HOST))
.setProgressMessage("Merging manifest for " + ruleContext.getLabel())
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/RClassGeneratorActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/android/RClassGeneratorActionBuilder.java
index aec1682..cb074a1 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/RClassGeneratorActionBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/RClassGeneratorActionBuilder.java
@@ -72,7 +72,7 @@
@Override
public String apply(ResourceContainer container) {
return (container.getRTxt() != null ? container.getRTxt().getExecPath() : "")
- + ":"
+ + ";"
+ (container.getManifest() != null ? container.getManifest().getExecPath() : "");
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/ResourceShrinkerActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/android/ResourceShrinkerActionBuilder.java
index 60d414d..5c50083 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/ResourceShrinkerActionBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/ResourceShrinkerActionBuilder.java
@@ -22,6 +22,7 @@
import com.google.devtools.build.lib.analysis.actions.CustomCommandLine;
import com.google.devtools.build.lib.analysis.actions.SpawnAction;
import com.google.devtools.build.lib.analysis.config.CompilationMode;
+import com.google.devtools.build.lib.util.OS;
import java.util.Collections;
import java.util.List;
@@ -157,6 +158,7 @@
.getRunfilesArtifactsWithoutMiddlemen());
commandLine.addExecPath("--aapt", sdk.getAapt().getExecutable());
+ commandLine.add("--hostPlatform").add(OS.getCurrent().getCanonicalName());
commandLine.addExecPath("--annotationJar", sdk.getAnnotationsJar());
inputs.add(sdk.getAnnotationsJar());
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/RobolectricResourceSymbolsActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/android/RobolectricResourceSymbolsActionBuilder.java
index 20fe410..9b1efac 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/RobolectricResourceSymbolsActionBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/RobolectricResourceSymbolsActionBuilder.java
@@ -24,6 +24,7 @@
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.rules.android.ResourceContainerConverter.Builder.SeparatorType;
+import com.google.devtools.build.lib.util.OS;
import java.util.ArrayList;
import java.util.List;
@@ -81,6 +82,7 @@
List<Artifact> inputs = new ArrayList<>();
builder.addExecPath("--androidJar", sdk.getAndroidJar());
+ builder.add("--hostPlatform").add(OS.getCurrent().getCanonicalName());
inputs.add(sdk.getAndroidJar());
if (!Iterables.isEmpty(dependencies.getResources())) {
diff --git a/src/main/java/com/google/devtools/build/lib/util/ProcessUtils.java b/src/main/java/com/google/devtools/build/lib/util/ProcessUtils.java
index c6a4758..e4eaf8e 100644
--- a/src/main/java/com/google/devtools/build/lib/util/ProcessUtils.java
+++ b/src/main/java/com/google/devtools/build/lib/util/ProcessUtils.java
@@ -15,7 +15,7 @@
package com.google.devtools.build.lib.util;
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
-import com.google.devtools.build.lib.windows.WindowsProcesses;
+import com.google.devtools.build.lib.windows.jni.WindowsProcesses;
/**
* OS Process related utilities.
diff --git a/src/main/java/com/google/devtools/build/lib/windows/WindowsFileSystem.java b/src/main/java/com/google/devtools/build/lib/windows/WindowsFileSystem.java
index 893a563..4fdbf85 100644
--- a/src/main/java/com/google/devtools/build/lib/windows/WindowsFileSystem.java
+++ b/src/main/java/com/google/devtools/build/lib/windows/WindowsFileSystem.java
@@ -24,6 +24,7 @@
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.Path.PathFactory;
import com.google.devtools.build.lib.vfs.PathFragment;
+import com.google.devtools.build.lib.windows.jni.WindowsFileOperations;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
diff --git a/src/main/java/com/google/devtools/build/lib/windows/WindowsJniLoader.java b/src/main/java/com/google/devtools/build/lib/windows/WindowsJniLoader.java
deleted file mode 100644
index bc59eac..0000000
--- a/src/main/java/com/google/devtools/build/lib/windows/WindowsJniLoader.java
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2016 The Bazel Authors. All rights reserved.
-//
-// 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.devtools.build.lib.windows;
-
-import java.io.IOException;
-
-/**
- * Loads native code under Windows.
- */
-public class WindowsJniLoader {
- private static boolean jniLoaded = false;
- public static synchronized void loadJni() {
- if (jniLoaded) {
- return;
- }
-
- try {
- System.loadLibrary("windows_jni");
- } catch (UnsatisfiedLinkError ex) {
- // We are probably in tests, let's try to find the library in the runfiles
- try {
- System.load(WindowsRunfiles.getRunfile("io_bazel/src/main/native/windows_jni.dll"));
- } catch (IOException e) {
- // We throw the UnsatisfiedLinkError if we cannot find the runfiles
- throw ex;
- }
- }
- jniLoaded = true;
- }
-}
diff --git a/src/main/java/com/google/devtools/build/lib/windows/WindowsSubprocess.java b/src/main/java/com/google/devtools/build/lib/windows/WindowsSubprocess.java
index 16f05e4..cbab795 100644
--- a/src/main/java/com/google/devtools/build/lib/windows/WindowsSubprocess.java
+++ b/src/main/java/com/google/devtools/build/lib/windows/WindowsSubprocess.java
@@ -15,6 +15,7 @@
package com.google.devtools.build.lib.windows;
import com.google.devtools.build.lib.shell.Subprocess;
+import com.google.devtools.build.lib.windows.jni.WindowsProcesses;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
diff --git a/src/main/java/com/google/devtools/build/lib/windows/WindowsSubprocessFactory.java b/src/main/java/com/google/devtools/build/lib/windows/WindowsSubprocessFactory.java
index e85325d..fa69d6b 100644
--- a/src/main/java/com/google/devtools/build/lib/windows/WindowsSubprocessFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/windows/WindowsSubprocessFactory.java
@@ -19,6 +19,8 @@
import com.google.devtools.build.lib.shell.SubprocessBuilder;
import com.google.devtools.build.lib.shell.SubprocessBuilder.StreamAction;
import com.google.devtools.build.lib.vfs.PathFragment;
+import com.google.devtools.build.lib.windows.jni.WindowsJniLoader;
+import com.google.devtools.build.lib.windows.jni.WindowsProcesses;
import java.io.File;
import java.io.IOException;
import java.util.List;
diff --git a/src/main/java/com/google/devtools/build/lib/windows/jni/BUILD b/src/main/java/com/google/devtools/build/lib/windows/jni/BUILD
new file mode 100644
index 0000000..c51bdbf
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/windows/jni/BUILD
@@ -0,0 +1,19 @@
+package(
+ default_visibility = ["//src:__subpackages__"],
+)
+
+filegroup(
+ name = "srcs",
+ srcs = glob(["**"]),
+ visibility = ["//src:__pkg__"],
+)
+
+java_library(
+ name = "jni",
+ srcs = glob(["*.java"]),
+ visibility = ["//visibility:public"],
+ deps = [
+ "//third_party:guava",
+ "//third_party:jsr305",
+ ],
+)
diff --git a/src/main/java/com/google/devtools/build/lib/windows/WindowsFileOperations.java b/src/main/java/com/google/devtools/build/lib/windows/jni/WindowsFileOperations.java
similarity index 98%
rename from src/main/java/com/google/devtools/build/lib/windows/WindowsFileOperations.java
rename to src/main/java/com/google/devtools/build/lib/windows/jni/WindowsFileOperations.java
index 0d68c36..9eddda1 100644
--- a/src/main/java/com/google/devtools/build/lib/windows/WindowsFileOperations.java
+++ b/src/main/java/com/google/devtools/build/lib/windows/jni/WindowsFileOperations.java
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.devtools.build.lib.windows;
+package com.google.devtools.build.lib.windows.jni;
import java.io.IOException;
diff --git a/src/main/java/com/google/devtools/build/lib/windows/jni/WindowsJniLoader.java b/src/main/java/com/google/devtools/build/lib/windows/jni/WindowsJniLoader.java
new file mode 100644
index 0000000..aad196d
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/windows/jni/WindowsJniLoader.java
@@ -0,0 +1,80 @@
+// Copyright 2016 The Bazel Authors. All rights reserved.
+//
+// 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.devtools.build.lib.windows.jni;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.FileOutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+/**
+ * Loads native code under Windows.
+ */
+public class WindowsJniLoader {
+ private static boolean jniLoaded = false;
+ public static synchronized void loadJni() {
+ if (jniLoaded) {
+ return;
+ }
+
+ try {
+ System.loadLibrary("windows_jni");
+ } catch (UnsatisfiedLinkError ex) {
+ if (!loadFromJar("io_bazel/src/main/native/windows_jni.dll")) {
+ // We are probably in tests, let's try to find the library in the runfiles
+ try {
+ System.load(WindowsRunfiles.getRunfile("io_bazel/src/main/native/windows_jni.dll"));
+ } catch (IOException e) {
+ // We throw the UnsatisfiedLinkError if we cannot find the runfiles
+ throw ex;
+ }
+ }
+ }
+ jniLoaded = true;
+ }
+
+ private static boolean loadFromJar(String path) {
+ try {
+ System.load("c:\\work\\bazel\\windows_jni.dll");
+ return true;
+ } catch (Exception e) {
+ return false;
+ }
+// // TODO: attempt to load the path, path.subpath(1), path.subpath(2), etc.
+// // the jar file may omit the "src" from "src/main/native/windows_jni.dll" because the java root
+// // is also under "src/java"...
+//System.out.printf("DEBUG: loadFromJar 1\n");
+// try (InputStream istm = WindowsJniLoader.class.getClassLoader().getResourceAsStream("main/native/windows_jni.dll")) {
+//System.out.printf("DEBUG: loadFromJar 2\n");
+// Path tmp = Files.createTempDirectory("cica");
+//System.out.printf("DEBUG: loadFromJar 2.5, tmp=(%s)\n", tmp);
+// Path jniLib = tmp.resolve("windows_jni.dll").toAbsolutePath();
+//System.out.printf("DEBUG: loadFromJar 3, jniLib=(%s)\n", jniLib);
+// try (FileOutputStream ostm = new FileOutputStream(jniLib.toFile())) {
+// byte[] data = new byte[0x10000];
+// while (istm.read(data) > 0) {
+// ostm.write(data);
+// }
+// }
+//System.out.printf("DEBUG: loadFromJar 4\n");
+// System.loadLibrary(jniLib.toString());
+// return true;
+// } catch (IOException e) {
+//System.out.printf("DEBUG: loadFromJar 5, e=(%s)\n", e);
+// return false;
+// }
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/windows/WindowsProcesses.java b/src/main/java/com/google/devtools/build/lib/windows/jni/WindowsProcesses.java
similarity index 84%
rename from src/main/java/com/google/devtools/build/lib/windows/WindowsProcesses.java
rename to src/main/java/com/google/devtools/build/lib/windows/jni/WindowsProcesses.java
index 9aac2a7..946e1e0 100644
--- a/src/main/java/com/google/devtools/build/lib/windows/WindowsProcesses.java
+++ b/src/main/java/com/google/devtools/build/lib/windows/jni/WindowsProcesses.java
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.devtools.build.lib.windows;
+package com.google.devtools.build.lib.windows.jni;
import java.util.List;
@@ -29,7 +29,7 @@
/**
* returns the PID of the current process.
*/
- static native int nativeGetpid();
+ public static native int nativeGetpid();
/**
* Creates a process with the specified Windows command line.
@@ -50,7 +50,7 @@
* work.
* @return the opaque identifier of the created process
*/
- static native long nativeCreateProcess(
+ public static native long nativeCreateProcess(
String argv0, String argvRest, byte[] env, String cwd, String stdoutFile, String stderrFile);
/**
@@ -60,13 +60,13 @@
*
* @return the number of bytes written
*/
- static native int nativeWriteStdin(long process, byte[] bytes, int offset, int length);
+ public static native int nativeWriteStdin(long process, byte[] bytes, int offset, int length);
/** Returns an opaque identifier of stdout stream for the process. */
- static native long nativeGetStdout(long process);
+ public static native long nativeGetStdout(long process);
/** Returns am opaque identifier of stderr stream for the process. */
- static native long nativeGetStderr(long process);
+ public static native long nativeGetStderr(long process);
/**
* Reads data from the stream into the given array. {@code stream} should come from {@link
@@ -76,7 +76,7 @@
*
* @return the number of bytes read, 0 on EOF, or -1 if there was an error.
*/
- static native int nativeReadStream(long stream, byte[] bytes, int offset, int length);
+ public static native int nativeReadStream(long stream, byte[] bytes, int offset, int length);
/**
* Waits until the given process terminates. If timeout is non-negative, it indicates the number
@@ -87,23 +87,23 @@
* <li>1: Timeout</li>
* <li>2: Something went wrong</li>
*/
- static native int nativeWaitFor(long process, long timeout);
+ public static native int nativeWaitFor(long process, long timeout);
/**
* Returns the exit code of the process. Throws {@code IllegalStateException} if something
* goes wrong.
*/
- static native int nativeGetExitCode(long process);
+ public static native int nativeGetExitCode(long process);
/**
* Returns the process ID of the given process or -1 if there was an error.
*/
- static native int nativeGetProcessPid(long process);
+ public static native int nativeGetProcessPid(long process);
/**
* Terminates the given process. Returns true if the termination was successful.
*/
- static native boolean nativeTerminate(long process);
+ public static native boolean nativeTerminate(long process);
/**
* Releases the native data structures associated with the process.
@@ -111,7 +111,7 @@
* <p>Calling any other method on the same process after this call will result in the JVM crashing
* or worse.
*/
- static native void nativeDeleteProcess(long process);
+ public static native void nativeDeleteProcess(long process);
/**
* Closes the stream
@@ -119,7 +119,7 @@
* @param stream should come from {@link #nativeGetStdout(long)} or {@link
* #nativeGetStderr(long)}.
*/
- static native void nativeCloseStream(long stream);
+ public static native void nativeCloseStream(long stream);
/**
* Returns a string representation of the last error caused by any call on the given process or
@@ -130,16 +130,16 @@
* <p>After this call returns, subsequent calls will return the empty string if there was no
* failed operation in between.
*/
- static native String nativeProcessGetLastError(long process);
+ public static native String nativeProcessGetLastError(long process);
- static native String nativeStreamGetLastError(long process);
+ public static native String nativeStreamGetLastError(long process);
public static int getpid() {
WindowsJniLoader.loadJni();
return nativeGetpid();
}
- static String quoteCommandLine(List<String> argv) {
+ public static String quoteCommandLine(List<String> argv) {
StringBuilder result = new StringBuilder();
for (int iArg = 0; iArg < argv.size(); iArg++) {
if (iArg != 0) {
diff --git a/src/main/java/com/google/devtools/build/lib/windows/WindowsRunfiles.java b/src/main/java/com/google/devtools/build/lib/windows/jni/WindowsRunfiles.java
similarity index 97%
rename from src/main/java/com/google/devtools/build/lib/windows/WindowsRunfiles.java
rename to src/main/java/com/google/devtools/build/lib/windows/jni/WindowsRunfiles.java
index 8765310..be4ff59 100644
--- a/src/main/java/com/google/devtools/build/lib/windows/WindowsRunfiles.java
+++ b/src/main/java/com/google/devtools/build/lib/windows/jni/WindowsRunfiles.java
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.devtools.build.lib.windows;
+package com.google.devtools.build.lib.windows.jni;
import java.io.BufferedReader;
import java.io.FileInputStream;
diff --git a/src/main/native/windows_processes.cc b/src/main/native/windows_processes.cc
index cf0b677..86e2130 100644
--- a/src/main/native/windows_processes.cc
+++ b/src/main/native/windows_processes.cc
@@ -37,7 +37,7 @@
"jchar and WCHAR should be the same size");
extern "C" JNIEXPORT jint JNICALL
-Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeGetpid(
+Java_com_google_devtools_build_lib_windows_jni_WindowsProcesses_nativeGetpid(
JNIEnv* env, jclass clazz) {
return GetCurrentProcessId();
}
@@ -166,7 +166,7 @@
}
extern "C" JNIEXPORT jlong JNICALL
-Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeCreateProcess(
+Java_com_google_devtools_build_lib_windows_jni_WindowsProcesses_nativeCreateProcess(
JNIEnv* env, jclass clazz, jstring java_argv0, jstring java_argv_rest,
jbyteArray java_env, jstring java_cwd, jstring java_stdout_redirect,
jstring java_stderr_redirect) {
@@ -377,7 +377,7 @@
}
extern "C" JNIEXPORT jint JNICALL
-Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeWriteStdin(
+Java_com_google_devtools_build_lib_windows_jni_WindowsProcesses_nativeWriteStdin(
JNIEnv *env, jclass clazz, jlong process_long, jbyteArray java_bytes,
jint offset, jint length) {
NativeProcess* process = reinterpret_cast<NativeProcess*>(process_long);
@@ -401,21 +401,21 @@
}
extern "C" JNIEXPORT jlong JNICALL
-Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeGetStdout(
+Java_com_google_devtools_build_lib_windows_jni_WindowsProcesses_nativeGetStdout(
JNIEnv* env, jclass clazz, jlong process_long) {
NativeProcess* process = reinterpret_cast<NativeProcess*>(process_long);
return PtrAsJlong(&process->stdout_);
}
extern "C" JNIEXPORT jlong JNICALL
-Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeGetStderr(
+Java_com_google_devtools_build_lib_windows_jni_WindowsProcesses_nativeGetStderr(
JNIEnv* env, jclass clazz, jlong process_long) {
NativeProcess* process = reinterpret_cast<NativeProcess*>(process_long);
return PtrAsJlong(&process->stderr_);
}
extern "C" JNIEXPORT jint JNICALL
-Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeReadStream(
+Java_com_google_devtools_build_lib_windows_jni_WindowsProcesses_nativeReadStream(
JNIEnv* env, jclass clazz, jlong stream_long, jbyteArray java_bytes,
jint offset, jint length) {
NativeOutputStream* stream =
@@ -454,7 +454,7 @@
}
extern "C" JNIEXPORT jint JNICALL
-Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeGetExitCode(
+Java_com_google_devtools_build_lib_windows_jni_WindowsProcesses_nativeGetExitCode(
JNIEnv *env, jclass clazz, jlong process_long) {
NativeProcess* process = reinterpret_cast<NativeProcess*>(process_long);
DWORD exit_code;
@@ -471,7 +471,7 @@
// 1: Timeout
// 2: Wait returned with an error
extern "C" JNIEXPORT jint JNICALL
-Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeWaitFor(
+Java_com_google_devtools_build_lib_windows_jni_WindowsProcesses_nativeWaitFor(
JNIEnv *env, jclass clazz, jlong process_long, jlong java_timeout) {
NativeProcess* process = reinterpret_cast<NativeProcess*>(process_long);
HANDLE handles[1] = { process->process_ };
@@ -520,7 +520,7 @@
}
extern "C" JNIEXPORT jint JNICALL
-Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeGetProcessPid(
+Java_com_google_devtools_build_lib_windows_jni_WindowsProcesses_nativeGetProcessPid(
JNIEnv *env, jclass clazz, jlong process_long) {
NativeProcess* process = reinterpret_cast<NativeProcess*>(process_long);
process->error_ = "";
@@ -528,7 +528,7 @@
}
extern "C" JNIEXPORT jboolean JNICALL
-Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeTerminate(
+Java_com_google_devtools_build_lib_windows_jni_WindowsProcesses_nativeTerminate(
JNIEnv *env, jclass clazz, jlong process_long) {
static const UINT exit_code = 130; // 128 + SIGINT, like on Linux
NativeProcess* process = reinterpret_cast<NativeProcess*>(process_long);
@@ -551,7 +551,7 @@
}
extern "C" JNIEXPORT void JNICALL
-Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeDeleteProcess(
+Java_com_google_devtools_build_lib_windows_jni_WindowsProcesses_nativeDeleteProcess(
JNIEnv* env, jclass clazz, jlong process_long) {
NativeProcess* process = reinterpret_cast<NativeProcess*>(process_long);
@@ -574,7 +574,7 @@
}
extern "C" JNIEXPORT void JNICALL
-Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeCloseStream(
+Java_com_google_devtools_build_lib_windows_jni_WindowsProcesses_nativeCloseStream(
JNIEnv* env, jclass clazz, jlong stream_long) {
NativeOutputStream* stream =
reinterpret_cast<NativeOutputStream*>(stream_long);
@@ -582,7 +582,7 @@
}
extern "C" JNIEXPORT jstring JNICALL
-Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeProcessGetLastError(
+Java_com_google_devtools_build_lib_windows_jni_WindowsProcesses_nativeProcessGetLastError(
JNIEnv* env, jclass clazz, jlong process_long) {
NativeProcess* process = reinterpret_cast<NativeProcess*>(process_long);
jstring result = env->NewStringUTF(process->error_.c_str());
@@ -591,7 +591,7 @@
}
extern "C" JNIEXPORT jstring JNICALL
-Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeStreamGetLastError(
+Java_com_google_devtools_build_lib_windows_jni_WindowsProcesses_nativeStreamGetLastError(
JNIEnv* env, jclass clazz, jlong stream_long) {
NativeOutputStream* stream =
reinterpret_cast<NativeOutputStream*>(stream_long);
@@ -601,7 +601,7 @@
}
extern "C" JNIEXPORT jint JNICALL
-Java_com_google_devtools_build_lib_windows_WindowsFileOperations_nativeIsJunction(
+Java_com_google_devtools_build_lib_windows_jni_WindowsFileOperations_nativeIsJunction(
JNIEnv* env, jclass clazz, jstring path, jobjectArray error_msg_holder) {
int result = windows_util::IsJunctionOrDirectorySymlink(
GetJavaWstring(env, path).c_str());
@@ -614,7 +614,7 @@
}
extern "C" JNIEXPORT jboolean JNICALL
-Java_com_google_devtools_build_lib_windows_WindowsFileOperations_nativeGetLongPath(
+Java_com_google_devtools_build_lib_windows_jni_WindowsFileOperations_nativeGetLongPath(
JNIEnv* env, jclass clazz, jstring path, jobjectArray result_holder,
jobjectArray error_msg_holder) {
std::unique_ptr<WCHAR[]> result;
@@ -634,7 +634,7 @@
}
extern "C" JNIEXPORT jboolean JNICALL
-Java_com_google_devtools_build_lib_windows_WindowsFileOperations_nativeCreateJunction(
+Java_com_google_devtools_build_lib_windows_jni_WindowsFileOperations_nativeCreateJunction(
JNIEnv* env, jclass clazz, jstring name, jstring target,
jobjectArray error_msg_holder) {
std::string error = windows_util::CreateJunction(GetJavaWstring(env, name),
diff --git a/src/tools/android/java/com/google/devtools/build/android/AarGeneratorAction.java b/src/tools/android/java/com/google/devtools/build/android/AarGeneratorAction.java
index 3a047f3..05d1fa9 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AarGeneratorAction.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AarGeneratorAction.java
@@ -20,6 +20,7 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Ordering;
import com.google.devtools.build.android.AndroidResourceMerger.MergingException;
+import com.google.devtools.build.android.AndroidResourceProcessor.AaptConfigOptions;
import com.google.devtools.build.android.Converters.ExistingPathConverter;
import com.google.devtools.build.android.Converters.PathConverter;
import com.google.devtools.build.android.Converters.UnvalidatedAndroidDataConverter;
@@ -105,10 +106,12 @@
public static void main(String[] args) {
Stopwatch timer = Stopwatch.createStarted();
- OptionsParser optionsParser = OptionsParser.newOptionsParser(Options.class);
+ OptionsParser optionsParser = OptionsParser.newOptionsParser(Options.class, AaptConfigOptions.class);
optionsParser.parseAndExitUponError(args);
Options options = optionsParser.getOptions(Options.class);
+ AaptConfigOptions aaptConfigOptions = optionsParser.getOptions(AaptConfigOptions.class);
+
checkFlags(options);
try (ScopedTemporaryDirectory scopedTmp = new ScopedTemporaryDirectory("aar_gen_tmp")) {
@@ -122,6 +125,7 @@
// res/assets directories into a single res and single assets directory.
MergedAndroidData mergedData =
AndroidResourceMerger.mergeData(
+ aaptConfigOptions.hostPlatform,
options.mainData,
ImmutableList.<DependencyAndroidData>of(),
ImmutableList.<DependencyAndroidData>of(),
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidDataWriter.java b/src/tools/android/java/com/google/devtools/build/android/AndroidDataWriter.java
index 2e2f85e..1f44303 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AndroidDataWriter.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidDataWriter.java
@@ -29,6 +29,7 @@
import com.google.common.util.concurrent.MoreExecutors;
import com.google.devtools.build.android.AndroidResourceMerger.MergingException;
import com.google.devtools.build.android.AndroidResourceMergingAction.Options;
+import com.google.devtools.build.android.AndroidResourceProcessor.AaptConfigOptions.OS;
import com.google.devtools.build.android.xml.Namespaces;
import java.io.BufferedWriter;
import java.io.File;
@@ -61,18 +62,22 @@
private final Path destinationPath;
private final Path source;
private final PngCruncher cruncher;
+ private final OS hostPlatform;
- private CrunchTask(PngCruncher cruncher, Path destinationPath, Path source) {
+ private CrunchTask(PngCruncher cruncher, Path destinationPath, Path source, OS hostPlatform) {
this.cruncher = cruncher;
this.destinationPath = destinationPath;
this.source = source;
+ this.hostPlatform = hostPlatform;
}
@Override
public Boolean call() throws Exception {
- try {
+ try (JunctionCreator junc = (hostPlatform == OS.WINDOWS)
+ ? new WindowsJunctionCreator(Files.createTempDirectory("pngcrunch"))
+ : new NoopJunctionCreator()) {
Files.createDirectories(destinationPath.getParent());
- cruncher.crunchPng(0, source.toFile(), destinationPath.toFile());
+ cruncher.crunchPng(0, junc.create(source).toFile(), junc.create(destinationPath).toFile());
} catch (PngException e) {
throw MergingException.wrapException(e);
}
@@ -95,6 +100,7 @@
public Boolean call() throws Exception {
Files.createDirectories(destinationPath.getParent());
Files.copy(sourcePath, destinationPath, StandardCopyOption.REPLACE_EXISTING);
+ Files.setAttribute(destinationPath, "dos:readonly", Boolean.FALSE);
return Boolean.TRUE;
}
}
@@ -158,6 +164,7 @@
public void end(int key) {}
};
+ private final OS hostPlatform;
private final Path destination;
private final Map<String, ResourceValuesDefinitions> valueTags = new HashMap<>();
@@ -168,11 +175,13 @@
private final ListeningExecutorService executorService;
private AndroidDataWriter(
+ OS hostPlatform,
Path destination,
Path resourceDirectory,
Path assetsDirectory,
PngCruncher cruncher,
ListeningExecutorService executorService) {
+ this.hostPlatform = hostPlatform;
this.destination = destination;
this.resourceDirectory = resourceDirectory;
this.assetDirectory = assetsDirectory;
@@ -192,6 +201,7 @@
@VisibleForTesting
static AndroidDataWriter createWithDefaults(Path destination) {
return createWith(
+ OS.LINUX,
destination,
destination.resolve("res"),
destination.resolve("assets"),
@@ -210,14 +220,16 @@
* @param executorService An execution service for multi-threaded writing.
* @return A new {@link AndroidDataWriter}.
*/
- public static AndroidDataWriter createForLibrary(
- Path manifestDirectory,
- Path resourceDirectory,
- Path assetsDirectory,
- ListeningExecutorService executorService) {
- return createWith(
- manifestDirectory, resourceDirectory, assetsDirectory, STUB_CRUNCHER, executorService);
- }
+// public static AndroidDataWriter createForLibrary(
+// OS hostPlatform,
+// Path manifestDirectory,
+// Path resourceDirectory,
+// Path assetsDirectory,
+// ListeningExecutorService executorService) {
+// return createWith(
+// hostPlatform,
+// manifestDirectory, resourceDirectory, assetsDirectory, STUB_CRUNCHER, executorService);
+// }
/**
* Creates a new writer.
@@ -231,12 +243,14 @@
* @return A new {@link AndroidDataWriter}.
*/
public static AndroidDataWriter createWith(
+ OS hostPlatform,
Path manifestDirectory,
Path resourceDirectory,
Path assetsDirectory,
@Nullable PngCruncher cruncher,
ListeningExecutorService executorService) {
return new AndroidDataWriter(
+ hostPlatform,
manifestDirectory,
resourceDirectory,
assetsDirectory,
@@ -272,7 +286,8 @@
final Path destinationPath = resourceDirectory.resolve(relativeDestinationPath);
if (!source.getParent().getFileName().toString().startsWith(SdkConstants.FD_RES_RAW)
&& source.getFileName().toString().endsWith(SdkConstants.DOT_PNG)) {
- writeTasks.add(executorService.submit(new CrunchTask(cruncher, destinationPath, source)));
+ writeTasks.add(
+ executorService.submit(new CrunchTask(cruncher, destinationPath, source, hostPlatform)));
} else {
copy(source, destinationPath);
}
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceMerger.java b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceMerger.java
index 8fc6075..8842145 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceMerger.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceMerger.java
@@ -19,6 +19,7 @@
import com.google.common.base.Stopwatch;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
+import com.google.devtools.build.android.AndroidResourceProcessor.AaptConfigOptions.OS;
import java.io.Closeable;
import java.io.IOException;
import java.nio.file.Path;
@@ -54,6 +55,7 @@
/** Merges all secondary resources with the primary resources. */
public static MergedAndroidData mergeData(
+ final OS hostPlatform,
final ParsedAndroidData primary,
final Path primaryManifest,
final List<? extends SerializedAndroidData> direct,
@@ -97,6 +99,7 @@
}
AndroidDataWriter writer =
AndroidDataWriter.createWith(
+ hostPlatform,
resourcesOut.getParent(), resourcesOut, assetsOut, cruncher, executorService);
return merged.write(writer);
} catch (IOException e) {
@@ -132,6 +135,7 @@
* have not yet been parsed and serialized.
*/
public static MergedAndroidData mergeData(
+ OS hostPlatform,
final UnvalidatedAndroidData primary,
final List<? extends SerializedAndroidData> direct,
final List<? extends SerializedAndroidData> transitive,
@@ -145,6 +149,7 @@
try {
final ParsedAndroidData parsedPrimary = ParsedAndroidData.from(primary);
return mergeData(
+ hostPlatform,
parsedPrimary,
primary.getManifest(),
direct,
@@ -166,6 +171,7 @@
* have been separately parsed and serialized.
*/
public static MergedAndroidData mergeData(
+ OS hostPlatform,
final SerializedAndroidData primary,
final Path primaryManifest,
final List<? extends SerializedAndroidData> direct,
@@ -182,6 +188,7 @@
primary.deserialize(deserializer, primaryBuilder.consumers());
ParsedAndroidData primaryData = primaryBuilder.build();
return mergeData(
+ hostPlatform,
primaryData,
primaryManifest,
direct,
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceMergingAction.java b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceMergingAction.java
index 707c245..145b1ce 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceMergingAction.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceMergingAction.java
@@ -184,9 +184,11 @@
Strings.nullToEmpty(options.packageForR));
resourceClassWriter.setIncludeClassFile(true);
resourceClassWriter.setIncludeJavaFile(false);
-
+
+ File xmlPath = tmp.resolve("AndroidManifest.xml").toFile();
final MergedAndroidData mergedData =
AndroidResourceMerger.mergeData(
+ aaptConfigOptions.hostPlatform,
options.primaryData,
options.primaryManifest,
options.directData,
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceOutputs.java b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceOutputs.java
index 472e71f..f236b4b 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceOutputs.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceOutputs.java
@@ -160,7 +160,7 @@
protected void addEntry(Path file, byte[] content) throws IOException {
String prefix = directoryPrefix != null ? (directoryPrefix + "/") : "";
String relativeName = root.relativize(file).toString();
- ZipEntry entry = new ZipEntry(prefix + relativeName);
+ ZipEntry entry = new ZipEntry((prefix + relativeName).replace("\\", "/"));
entry.setMethod(storageMethod);
entry.setTime(normalizeTime(relativeName));
entry.setSize(content.length);
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessingAction.java b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessingAction.java
index 7ed92d7..a55d4f9 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessingAction.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessingAction.java
@@ -255,6 +255,7 @@
final MergedAndroidData mergedData =
AndroidResourceMerger.mergeData(
+ aaptConfigOptions.hostPlatform,
options.primaryData,
options.directData,
options.transitiveData,
@@ -307,6 +308,8 @@
}
resourceProcessor.processResources(
+ aaptConfigOptions.hostPlatform,
+ tmp,
aaptConfigOptions.aapt,
aaptConfigOptions.androidJar,
aaptConfigOptions.buildToolsVersion,
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java
index e5ae303..8c1f843 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java
@@ -44,6 +44,7 @@
import com.google.devtools.build.android.SplitConfigurationFilter.UnrecognizedSplitsException;
import com.google.devtools.build.android.resources.ResourceSymbols;
import com.google.devtools.common.options.Converters.CommaSeparatedOptionListConverter;
+import com.google.devtools.common.options.EnumConverter;
import com.google.devtools.common.options.Option;
import com.google.devtools.common.options.OptionsBase;
import com.google.devtools.common.options.TriState;
@@ -57,9 +58,10 @@
import java.nio.file.attribute.FileTime;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import java.util.Map.Entry;
+import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.logging.Logger;
@@ -154,6 +156,28 @@
help = "A list of resource config filters to pass to aapt.")
public List<String> resourceConfigs;
+ @Option(name = "hostPlatform",
+ defaultValue = "unknown",
+ converter = OSConverter.class,
+ category = "tool",
+ help = "")
+ public OS hostPlatform;
+
+ // Same enum names as the canonical names in c.g.devtools.build.lib.util.OS
+ public enum OS {
+ OSX,
+ FREEBSD,
+ LINUX,
+ WINDOWS,
+ UNKNOWN;
+ }
+
+ public static final class OSConverter extends EnumConverter<OS> {
+ public OSConverter() {
+ super(OS.class, "OS name");
+ }
+ }
+
private static final String ANDROID_SPLIT_DOCUMENTATION_URL =
"https://developer.android.com/guide/topics/resources/providing-resources.html"
+ "#QualifierRules";
@@ -235,6 +259,8 @@
// TODO(bazel-team): Clean up this method call -- 13 params is too many.
/** Processes resources for generated sources, configs and packaging resources. */
public void processResources(
+ AaptConfigOptions.OS hostPlatform,
+ Path tempRoot,
Path aapt,
Path androidJar,
@Nullable Revision buildToolsVersion,
@@ -261,7 +287,10 @@
if (publicResourcesOut != null) {
prepareOutputPath(publicResourcesOut.getParent());
}
- runAapt(aapt,
+ runAapt(
+ hostPlatform,
+ tempRoot,
+ aapt,
androidJar,
buildToolsVersion,
variantType,
@@ -306,6 +335,8 @@
}
public void runAapt(
+ AaptConfigOptions.OS hostPlatform,
+ Path tempRoot,
Path aapt,
Path androidJar,
@Nullable Revision buildToolsVersion,
@@ -324,59 +355,65 @@
@Nullable Path mainDexProguardOut,
@Nullable Path publicResourcesOut)
throws InterruptedException, LoggedErrorException, IOException {
- AaptCommandBuilder commandBuilder =
- new AaptCommandBuilder(aapt)
- .forBuildToolsVersion(buildToolsVersion)
- .forVariantType(variantType)
- // first argument is the command to be executed, "package"
- .add("package")
- // If the logger is verbose, set aapt to be verbose
- .when(stdLogger.getLevel() == StdLogger.Level.VERBOSE).thenAdd("-v")
- // Overwrite existing files, if they exist.
- .add("-f")
- // Resources are precrunched in the merge process.
- .add("--no-crunch")
- // Do not automatically generate versioned copies of vector XML resources.
- .whenVersionIsAtLeast(new Revision(23)).thenAdd("--no-version-vectors")
- // Add the android.jar as a base input.
- .add("-I", androidJar)
- // Add the manifest for validation.
- .add("-M", androidManifest.toAbsolutePath())
- // Maybe add the resources if they exist
- .when(Files.isDirectory(resourceDir)).thenAdd("-S", resourceDir)
- // Maybe add the assets if they exist
- .when(Files.isDirectory(assetsDir)).thenAdd("-A", assetsDir)
- // Outputs
- .when(sourceOut != null).thenAdd("-m")
- .add("-J", prepareOutputPath(sourceOut))
- .add("--output-text-symbols", prepareOutputPath(sourceOut))
- .add("-F", packageOut)
- .add("-G", proguardOut)
- .whenVersionIsAtLeast(new Revision(24)).thenAdd("-D", mainDexProguardOut)
- .add("-P", publicResourcesOut)
- .when(debug).thenAdd("--debug-mode")
- .add("--custom-package", customPackageForR)
- // If it is a library, do not generate final java ids.
- .whenVariantIs(VariantType.LIBRARY).thenAdd("--non-constant-id")
- .add("--ignore-assets", aaptOptions.getIgnoreAssets())
- .when(aaptOptions.getFailOnMissingConfigEntry()).thenAdd("--error-on-missing-config-entry")
- // Never compress apks.
- .add("-0", "apk")
- // Add custom no-compress extensions.
- .addRepeated("-0", aaptOptions.getNoCompress())
- // Filter by resource configuration type.
- .add("-c", Joiner.on(',').join(resourceConfigs))
- // Split APKs if any splits were specified.
- .whenVersionIsAtLeast(new Revision(23)).thenAddRepeated("--split", splits);
- for (String additional : aaptOptions.getAdditionalParameters()) {
- commandBuilder.add(additional);
- }
- try {
- new CommandLineRunner(stdLogger).runCmdLine(commandBuilder.build(), null);
- } catch (LoggedErrorException e) {
- // Add context and throw the error to resume processing.
- throw new LoggedErrorException(
- e.getCmdLineError(), getOutputWithSourceContext(aapt, e.getOutput()), e.getCmdLine());
+ try (JunctionCreator junctions = (hostPlatform == AaptConfigOptions.OS.WINDOWS)
+ ? new WindowsJunctionCreator(Files.createDirectories(tempRoot.resolve("juncts")))
+ : new NoopJunctionCreator()) {
+ sourceOut = junctions.create(sourceOut);
+
+ AaptCommandBuilder commandBuilder =
+ new AaptCommandBuilder(junctions.create(aapt))
+ .forBuildToolsVersion(buildToolsVersion)
+ .forVariantType(variantType)
+ // first argument is the command to be executed, "package"
+ .add("package")
+ // If the logger is verbose, set aapt to be verbose
+ .when(stdLogger.getLevel() == StdLogger.Level.VERBOSE).thenAdd("-v")
+ // Overwrite existing files, if they exist.
+ .add("-f")
+ // Resources are precrunched in the merge process.
+ .add("--no-crunch")
+ // Do not automatically generate versioned copies of vector XML resources.
+ .whenVersionIsAtLeast(new Revision(23)).thenAdd("--no-version-vectors")
+ // Add the android.jar as a base input.
+ .add("-I", junctions.create(androidJar))
+ // Add the manifest for validation.
+ .add("-M", junctions.create(androidManifest).toAbsolutePath())
+ // Maybe add the resources if they exist
+ .when(Files.isDirectory(resourceDir)).thenAdd("-S", junctions.create(resourceDir))
+ // Maybe add the assets if they exist
+ .when(Files.isDirectory(assetsDir)).thenAdd("-A", junctions.create(assetsDir))
+ // Outputs
+ .when(sourceOut != null).thenAdd("-m")
+ .add("-J", prepareOutputPath(sourceOut))
+ .add("--output-text-symbols", prepareOutputPath(sourceOut))
+ .add("-F", junctions.create(packageOut))
+ .add("-G", junctions.create(proguardOut))
+ .whenVersionIsAtLeast(new Revision(24)).thenAdd("-D", junctions.create(mainDexProguardOut))
+ .add("-P", junctions.create(publicResourcesOut))
+ .when(debug).thenAdd("--debug-mode")
+ .add("--custom-package", customPackageForR)
+ // If it is a library, do not generate final java ids.
+ .whenVariantIs(VariantType.LIBRARY).thenAdd("--non-constant-id")
+ .add("--ignore-assets", aaptOptions.getIgnoreAssets())
+ .when(aaptOptions.getFailOnMissingConfigEntry()).thenAdd("--error-on-missing-config-entry")
+ // Never compress apks.
+ .add("-0", "apk")
+ // Add custom no-compress extensions.
+ .addRepeated("-0", aaptOptions.getNoCompress())
+ // Filter by resource configuration type.
+ .add("-c", Joiner.on(',').join(resourceConfigs))
+ // Split APKs if any splits were specified.
+ .whenVersionIsAtLeast(new Revision(23)).thenAddRepeated("--split", splits);
+ for (String additional : aaptOptions.getAdditionalParameters()) {
+ commandBuilder.add(additional);
+ }
+ try {
+ new CommandLineRunner(stdLogger).runCmdLine(commandBuilder.build(), null);
+ } catch (LoggedErrorException e) {
+ // Add context and throw the error to resume processing.
+ throw new LoggedErrorException(
+ e.getCmdLineError(), getOutputWithSourceContext(aapt, e.getOutput()), e.getCmdLine());
+ }
}
}
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceValidatorAction.java b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceValidatorAction.java
index 40ca01c..a631425 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceValidatorAction.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceValidatorAction.java
@@ -126,6 +126,8 @@
resourceProcessor.writeDummyManifestForAapt(dummyManifest, options.packageForR);
resourceProcessor.runAapt(
+ aaptConfigOptions.hostPlatform,
+ tmp,
aaptConfigOptions.aapt,
aaptConfigOptions.androidJar,
aaptConfigOptions.buildToolsVersion,
@@ -147,7 +149,6 @@
AndroidResourceOutputs.copyRToOutput(
generatedSources, options.rOutput, VariantType.LIBRARY == packageType);
-
AndroidResourceOutputs.createSrcJar(
generatedSources, options.srcJarOutput, VariantType.LIBRARY == packageType);
} catch (Exception e) {
diff --git a/src/tools/android/java/com/google/devtools/build/android/BUILD b/src/tools/android/java/com/google/devtools/build/android/BUILD
index 209f8c0..025a95f 100644
--- a/src/tools/android/java/com/google/devtools/build/android/BUILD
+++ b/src/tools/android/java/com/google/devtools/build/android/BUILD
@@ -36,6 +36,7 @@
]),
deps = [
"//src/main/java/com/google/devtools/common/options",
+ "//src/main/java/com/google/devtools/build/lib/windows/jni",
"//src/main/protobuf:package_manifest_java_proto",
"//src/tools/android/java/com/google/devtools/build/android/proto:serialize_format_java_pb",
"//src/tools/android/java/com/google/devtools/build/android/resources",
@@ -47,6 +48,7 @@
"//third_party/java/aosp_gradle_core",
"//third_party/protobuf:protobuf_java",
],
+ resources = ["//src/main/native:windows_jni.dll"],
)
filegroup(
diff --git a/src/tools/android/java/com/google/devtools/build/android/DependencySymbolFileProvider.java b/src/tools/android/java/com/google/devtools/build/android/DependencySymbolFileProvider.java
index 871dd7f..ca64e20 100644
--- a/src/tools/android/java/com/google/devtools/build/android/DependencySymbolFileProvider.java
+++ b/src/tools/android/java/com/google/devtools/build/android/DependencySymbolFileProvider.java
@@ -27,7 +27,7 @@
*/
class DependencySymbolFileProvider implements SymbolFileProvider {
- private static final Pattern VALID_REGEX = Pattern.compile(".*:.*");
+ private static final Pattern VALID_REGEX = Pattern.compile(".*;.*");
private final File symbolFile;
private final File manifest;
@@ -60,7 +60,7 @@
if (!VALID_REGEX.matcher(text).find()) {
throw new IllegalArgumentException(text + " is not in the format " + commandlineFormat(""));
}
- String[] parts = text.split(File.pathSeparator);
+ String[] parts = text.split(";");
return new DependencySymbolFileProvider(getFile(parts[0], fileSystem),
getFile(parts[1], fileSystem));
}
@@ -78,7 +78,7 @@
}
public static String commandlineFormat(String libNum) {
- return String.format("lib%s/R.txt:lib%s/AndroidManifest.xml", libNum, libNum);
+ return String.format("lib%s/R.txt;lib%s/AndroidManifest.xml", libNum, libNum);
}
@Override
diff --git a/src/tools/android/java/com/google/devtools/build/android/FullyQualifiedName.java b/src/tools/android/java/com/google/devtools/build/android/FullyQualifiedName.java
index 938627a..3a55507 100644
--- a/src/tools/android/java/com/google/devtools/build/android/FullyQualifiedName.java
+++ b/src/tools/android/java/com/google/devtools/build/android/FullyQualifiedName.java
@@ -377,8 +377,11 @@
+ "The path is expected to be <resource type>/<file name>.",
source));
}
+ // Manually compose a forward-slash-using relative path from the basenames of the last two
+ // path elements, instead of using Path.subpath, because on Windows that'd return a path with
+ // backslashes, and later code (e.g. PARSING_REGEX) expects a Unix-style path.
String pathWithExtension =
- source.subpath(source.getNameCount() - 2, source.getNameCount()).toString();
+ source.getParent().toFile().getName() + "/" + source.toFile().getName();
int extensionStart = pathWithExtension.indexOf('.');
if (extensionStart > 0) {
return pathWithExtension.substring(0, extensionStart);
diff --git a/src/tools/android/java/com/google/devtools/build/android/JunctionCreator.java b/src/tools/android/java/com/google/devtools/build/android/JunctionCreator.java
new file mode 100644
index 0000000..9ee590e
--- /dev/null
+++ b/src/tools/android/java/com/google/devtools/build/android/JunctionCreator.java
@@ -0,0 +1,24 @@
+// Copyright 2017 The Bazel Authors. All rights reserved.
+//
+// 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.devtools.build.android;
+
+import com.android.annotations.Nullable;
+import java.io.Closeable;
+import java.io.IOException;
+import java.nio.file.Path;
+
+public interface JunctionCreator extends Closeable {
+ @Nullable
+ public abstract Path create(@Nullable Path path) throws IOException;
+}
diff --git a/src/tools/android/java/com/google/devtools/build/android/NoopJunctionCreator.java b/src/tools/android/java/com/google/devtools/build/android/NoopJunctionCreator.java
new file mode 100644
index 0000000..f4bf565
--- /dev/null
+++ b/src/tools/android/java/com/google/devtools/build/android/NoopJunctionCreator.java
@@ -0,0 +1,28 @@
+// Copyright 2017 The Bazel Authors. All rights reserved.
+//
+// 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.devtools.build.android;
+
+import com.android.annotations.Nullable;
+import java.io.IOException;
+import java.nio.file.Path;
+
+public final class NoopJunctionCreator implements JunctionCreator {
+ @Nullable
+ public Path create(@Nullable Path path) throws IOException {
+ return path;
+ }
+
+ @Override
+ public void close() throws IOException { }
+}
diff --git a/src/tools/android/java/com/google/devtools/build/android/ResourceProcessorBusyBox.java b/src/tools/android/java/com/google/devtools/build/android/ResourceProcessorBusyBox.java
index 59f0aeb..3a7bb15 100644
--- a/src/tools/android/java/com/google/devtools/build/android/ResourceProcessorBusyBox.java
+++ b/src/tools/android/java/com/google/devtools/build/android/ResourceProcessorBusyBox.java
@@ -134,6 +134,20 @@
public Tool tool;
}
+ private static String join(String[] args) {
+ if (args.length == 0) {
+ return "";
+ }
+ StringBuilder result = new StringBuilder();
+ for (int i = 0; i < args.length; i++) {
+ if (i > 0) {
+ result.append(", ");
+ }
+ result.append(args[i]);
+ }
+ return result.toString();
+ }
+
public static void main(String[] args) throws Exception {
OptionsParser optionsParser = OptionsParser.newOptionsParser(Options.class);
optionsParser.setAllowResidue(true);
diff --git a/src/tools/android/java/com/google/devtools/build/android/ResourceShrinkerAction.java b/src/tools/android/java/com/google/devtools/build/android/ResourceShrinkerAction.java
index ece53c6..ba25a5c 100644
--- a/src/tools/android/java/com/google/devtools/build/android/ResourceShrinkerAction.java
+++ b/src/tools/android/java/com/google/devtools/build/android/ResourceShrinkerAction.java
@@ -236,6 +236,8 @@
// Build ap_ with shrunk resources.
resourceProcessor.processResources(
+ aaptConfigOptions.hostPlatform,
+ working,
aaptConfigOptions.aapt,
aaptConfigOptions.androidJar,
aaptConfigOptions.buildToolsVersion,
diff --git a/src/tools/android/java/com/google/devtools/build/android/WindowsJunctionCreator.java b/src/tools/android/java/com/google/devtools/build/android/WindowsJunctionCreator.java
new file mode 100644
index 0000000..be32d01
--- /dev/null
+++ b/src/tools/android/java/com/google/devtools/build/android/WindowsJunctionCreator.java
@@ -0,0 +1,63 @@
+// Copyright 2017 The Bazel Authors. All rights reserved.
+//
+// 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.devtools.build.android;
+
+import com.android.annotations.Nullable;
+import com.google.common.base.Preconditions;
+import com.google.devtools.build.lib.windows.jni.WindowsFileOperations;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.HashMap;
+import java.util.Map;
+
+public final class WindowsJunctionCreator implements JunctionCreator {
+ private final Map<Path, Path> paths = new HashMap<>();
+ private final Path root;
+ private int junctionIndex = 0;
+
+ public WindowsJunctionCreator(Path root) {
+ this.root = Preconditions.checkNotNull(root);
+ }
+
+ @Nullable
+ public Path create(@Nullable Path path) throws IOException {
+ if (path == null) {
+ return null;
+ }
+
+ path = path.toAbsolutePath();
+ if (path.toFile().isDirectory()) {
+ Path link = paths.get(path);
+ if (link == null) {
+ link = root.resolve(Integer.toString(junctionIndex++));
+ WindowsFileOperations.createJunction(link.toString(), path.toString());
+ paths.put(path, link);
+ }
+ return link;
+ }
+
+ Path parent = path.getParent();
+ return (parent == null) ? path : create(parent).resolve(path.getFileName());
+ }
+
+ @Override
+ public void close() throws IOException {
+ // delete all junctions, otherwise the temp directory deleter would
+ // follow them and delete files from directories they point to
+ for (Path link : paths.values()) {
+ link.toFile().delete();
+ }
+ root.toFile().delete();
+ }
+}
diff --git a/tools/android/android_sdk_repository_template.bzl b/tools/android/android_sdk_repository_template.bzl
index 0e9ec0c..48947d9 100644
--- a/tools/android/android_sdk_repository_template.bzl
+++ b/tools/android/android_sdk_repository_template.bzl
@@ -66,21 +66,56 @@
name = "sdk-%d" % api_level,
build_tools_version = build_tools_version,
proguard = ":proguard_binary",
- aapt = ":aapt_binary",
+ aapt = select({
+ ":windows": ":aapt_binary.exe",
+ ":windows_msvc": ":aapt_binary.exe",
+ ":windows_msys": ":aapt_binary.exe",
+ "//conditions:default": ":aapt_binary_posix",
+ }),
dx = ":dx_binary",
main_dex_list_creator = ":main_dex_list_creator",
- adb = "platform-tools/adb",
+ adb = select({
+ ":windows": "platform-tools/adb.exe",
+ ":windows_msvc": "platform-tools/adb.exe",
+ ":windows_msys": "platform-tools/adb.exe",
+ "//conditions:default": "platform-tools/adb",
+ }),
framework_aidl = "platforms/android-%d/framework.aidl" % api_level,
- aidl = ":aidl_binary",
+ aidl = select({
+ ":windows": ":aidl_binary.exe",
+ ":windows_msvc": ":aidl_binary.exe",
+ ":windows_msys": ":aidl_binary.exe",
+ "//conditions:default": ":aidl_binary_posix",
+ }),
android_jar = "platforms/android-%d/android.jar" % api_level,
shrinked_android_jar = "platforms/android-%d/android.jar" % api_level,
annotations_jar = "tools/support/annotations.jar",
main_dex_classes = "build-tools/%s/mainDexClasses.rules" % build_tools_directory,
apksigner = ":apksigner",
- zipalign = ":zipalign_binary",
+ zipalign = select({
+ ":windows": ":zipalign_binary.exe",
+ ":windows_msvc": ":zipalign_binary.exe",
+ ":windows_msys": ":zipalign_binary.exe",
+ "//conditions:default": ":zipalign_binary_posix",
+ }),
resource_extractor = "@bazel_tools//tools/android:resource_extractor",
)
+ native.config_setting(
+ name = "windows",
+ values = {"host_cpu": "x64_windows"},
+ )
+
+ native.config_setting(
+ name = "windows_msvc",
+ values = {"host_cpu": "x64_windows_msvc"},
+ )
+
+ native.config_setting(
+ name = "windows_msys",
+ values = {"host_cpu": "x64_windows_msys"},
+ )
+
native.alias(
name = "org_apache_http_legacy",
actual = ":org_apache_http_legacy-%d" % default_api_level,
@@ -134,23 +169,28 @@
)
native.sh_binary(
- name = tool + "_binary",
+ name = tool + "_binary_posix",
srcs = [tool + "_runner.sh"],
data = [
":build_tools_libs",
- "build-tools/%s/%s" % (build_tools_directory, tool)
+ "build-tools/%s/%s" % (build_tools_directory, tool),
],
)
- native.sh_binary(
+ native.sh_binary(
+ name = tool + "_binary.exe",
+ srcs = ["build-tools/%s/%s.exe" % (build_tools_directory, tool)],
+ )
+
+ native.cc_binary(
name = "fail",
- srcs = ["fail.sh"])
+ srcs = ["fail.cc"])
native.genrule(
- name = "generate_fail_sh",
+ name = "generate_fail_cc",
srcs = [],
- outs = ["fail.sh"],
- cmd = "echo -e '#!/bin/bash\\nexit 1' >> $@; chmod +x $@",
+ outs = ["fail.cc"],
+ cmd = "echo 'int main(int, char**) { return 1; }' > $@",
)
diff --git a/tools/android/incremental_install.py b/tools/android/incremental_install.py
index b02d722..976fa9d 100644
--- a/tools/android/incremental_install.py
+++ b/tools/android/incremental_install.py
@@ -18,6 +18,7 @@
import hashlib
import logging
import os
+import posixpath
import re
import shutil
import subprocess
@@ -111,6 +112,10 @@
"""Raised when the SDK on the target device is older than the app allows."""
+hostpath = os.path
+targetpath = posixpath
+
+
class Adb(object):
"""A class to handle interaction with adb."""
@@ -174,7 +179,7 @@
def _CreateLocalFile(self):
"""Returns a path to a temporary local file in the temp directory."""
- local = os.path.join(self._temp_dir, "adbfile_%d" % self._file_counter)
+ local = hostpath.join(self._temp_dir, "adbfile_%d" % self._file_counter)
self._file_counter += 1
return local
@@ -336,14 +341,14 @@
"""
# Fetch the manifest on the device
- dex_dir = os.path.join(app_dir, "dex")
+ dex_dir = targetpath.join(app_dir, "dex")
adb.Mkdir(dex_dir)
old_manifest = None
if not full_install:
logging.info("Fetching dex manifest from device...")
- old_manifest_contents = adb.Pull("%s/manifest" % dex_dir)
+ old_manifest_contents = adb.Pull(targetpath.join(dex_dir, "manifest"))
if old_manifest_contents:
old_manifest = ParseManifest(old_manifest_contents)
else:
@@ -354,7 +359,7 @@
# was interrupted. Wipe the slate clean. Do this also in case we do a full
# installation.
old_manifest = {}
- adb.Delete("%s/*" % dex_dir)
+ adb.Delete(targetpath.join(dex_dir, "*"))
new_manifest = ParseManifest(dexmanifest)
dexes_to_delete = set(old_manifest) - set(new_manifest)
@@ -373,7 +378,7 @@
# Delete the manifest so that we know how to get back to a consistent state
# if we are interrupted.
- adb.Delete("%s/manifest" % dex_dir)
+ adb.Delete(targetpath.join(dex_dir, "manifest"))
# Tuple of (local, remote) files to push to the device.
files_to_push = []
@@ -385,26 +390,27 @@
for i, dexzip_name in enumerate(dexzips_in_upload):
zip_dexes = [
d for d in dexes_to_upload if new_manifest[d].input_file == dexzip_name]
- dexzip_tempdir = os.path.join(temp_dir, "dex", str(i))
- with zipfile.ZipFile(os.path.join(execroot, dexzip_name)) as dexzip:
+ dexzip_tempdir = hostpath.join(temp_dir, "dex", str(i))
+ with zipfile.ZipFile(hostpath.join(execroot, dexzip_name)) as dexzip:
for dex in zip_dexes:
zippath = new_manifest[dex].zippath
dexzip.extract(zippath, dexzip_tempdir)
files_to_push.append(
- (os.path.join(dexzip_tempdir, zippath), "%s/%s" % (dex_dir, dex)))
+ (hostpath.join(dexzip_tempdir, zippath),
+ targetpath.join(dex_dir, dex)))
# Now gather all the dexes that are not within a .zip file.
dexes_to_upload = set(
d for d in dexes_to_upload if new_manifest[d].zippath == "-")
for dex in dexes_to_upload:
files_to_push.append(
- (new_manifest[dex].input_file, "%s/%s" % (dex_dir, dex)))
+ (new_manifest[dex].input_file, targetpath.join(dex_dir, dex)))
num_files = len(dexes_to_delete) + len(files_to_push)
logging.info("Updating %d dex%s...", num_files, "es" if num_files > 1 else "")
# Delete the dexes that are not in the new manifest
- adb.DeleteMultiple(os.path.join(dex_dir, dex) for dex in dexes_to_delete)
+ adb.DeleteMultiple(targetpath.join(dex_dir, dex) for dex in dexes_to_delete)
# Upload all the files.
upload_walltime_start = time.time()
@@ -426,7 +432,7 @@
# If no dex upload failed, upload the manifest. If any upload failed, the
# exception should have been re-raised above.
# Call result() to raise the exception if there was one.
- adb.PushString(dexmanifest, "%s/manifest" % dex_dir).result()
+ adb.PushString(dexmanifest, targetpath.join(dex_dir, "manifest")).result()
def Checksum(filename):
@@ -459,7 +465,7 @@
new_checksum = Checksum(resource_apk)
# Fetch the checksum of the resources file on the device, if it exists
- device_checksum_file = "%s/%s" % (app_dir, "resources_checksum")
+ device_checksum_file = targetpath.join(app_dir, "resources_checksum")
old_checksum = adb.Pull(device_checksum_file)
if old_checksum == new_checksum:
logging.info("Application resources up-to-date")
@@ -469,7 +475,7 @@
# Remove the checksum file on the device so that if the transfer is
# interrupted, we know how to get the device back to a consistent state.
adb.Delete(device_checksum_file)
- adb.Push(resource_apk, "%s/%s" % (app_dir, "resources.ap_")).result()
+ adb.Push(resource_apk, targetpath.join(app_dir, "resources.ap_")).result()
# Write the new checksum to the device.
adb.PushString(new_checksum, device_checksum_file).result()
@@ -524,13 +530,14 @@
device_manifest = None
if not full_install:
- device_manifest = adb.Pull("%s/native/native_manifest" % app_dir)
+ device_manifest = adb.Pull(
+ targetpath.join(app_dir, "native", "native_manifest"))
device_checksums = {}
if device_manifest is None:
# If we couldn't fetch the device manifest or if this is a non-incremental
# install, wipe the slate clean
- adb.Delete("%s/native" % app_dir)
+ adb.Delete(targetpath.join(app_dir, "native"))
else:
# Otherwise, parse the manifest. Note that this branch is also taken if the
# manifest is empty.
@@ -545,7 +552,8 @@
libs_to_upload.update([l for l in common_libs
if install_checksums[l] != device_checksums[l]])
- libs_to_push = [(basename_to_path[lib], "%s/native/%s" % (app_dir, lib))
+ libs_to_push = [(basename_to_path[lib],
+ targetpath.join(app_dir, "native", lib))
for lib in libs_to_upload]
if not libs_to_delete and not libs_to_push and device_manifest is not None:
@@ -556,11 +564,11 @@
logging.info("Updating %d native lib%s...",
num_files, "s" if num_files != 1 else "")
- adb.Delete("%s/native/native_manifest" % app_dir)
+ adb.Delete(targetpath.join(app_dir, "native", "native_manifest"))
if libs_to_delete:
adb.DeleteMultiple([
- "%s/native/%s" % (app_dir, lib) for lib in libs_to_delete])
+ targetpath.join(app_dir, "native", lib) for lib in libs_to_delete])
upload_walltime_start = time.time()
fs = [adb.Push(local, remote) for local, remote in libs_to_push]
@@ -581,13 +589,13 @@
install_manifest = [
name + " " + checksum for name, checksum in install_checksums.iteritems()]
adb.PushString("\n".join(install_manifest),
- "%s/native/native_manifest" % app_dir).result()
+ targetpath.join(app_dir, "native", "native_manifest")).result()
def VerifyInstallTimestamp(adb, app_package):
"""Verifies that the app is unchanged since the last mobile-install."""
- expected_timestamp = adb.Pull("%s/%s/install_timestamp" % (
- DEVICE_DIRECTORY, app_package))
+ expected_timestamp = adb.Pull(
+ targetpath.join(DEVICE_DIRECTORY, app_package, "install_timestamp"))
if not expected_timestamp:
raise TimestampException(
"Cannot verify last mobile install. At least one non-incremental "
@@ -609,10 +617,10 @@
def SplitIncrementalInstall(adb, app_package, execroot, split_main_apk,
split_apks):
"""Does incremental installation using split packages."""
- app_dir = os.path.join(DEVICE_DIRECTORY, app_package)
- device_manifest_path = "%s/split_manifest" % app_dir
+ app_dir = targetpath.join(DEVICE_DIRECTORY, app_package)
+ device_manifest_path = targetpath.join(app_dir, "split_manifest")
device_manifest = adb.Pull(device_manifest_path)
- expected_timestamp = adb.Pull("%s/install_timestamp" % app_dir)
+ expected_timestamp = adb.Pull(targetpath.join(app_dir, "install_timestamp"))
actual_timestamp = adb.GetInstallTime(app_package)
device_checksums = {}
if device_manifest is not None:
@@ -623,9 +631,9 @@
install_checksums = {}
install_checksums["__MAIN__"] = Checksum(
- os.path.join(execroot, split_main_apk))
+ hostpath.join(execroot, split_main_apk))
for apk in split_apks:
- install_checksums[apk] = Checksum(os.path.join(execroot, apk))
+ install_checksums[apk] = Checksum(hostpath.join(execroot, apk))
reinstall_main = False
if (device_manifest is None or actual_timestamp is None or
@@ -655,20 +663,20 @@
if reinstall_main:
logging.info("Installing main APK...")
adb.Uninstall(app_package)
- adb.InstallMultiple(os.path.join(execroot, split_main_apk))
+ adb.InstallMultiple(targetpath.join(execroot, split_main_apk))
adb.PushString(
adb.GetInstallTime(app_package),
- "%s/install_timestamp" % app_dir).result()
+ targetpath.join(app_dir, "install_timestamp")).result()
logging.info("Reinstalling %s APKs...", len(apks_to_update))
for apk in apks_to_update:
- adb.InstallMultiple(os.path.join(execroot, apk), app_package)
+ adb.InstallMultiple(targetpath.join(execroot, apk), app_package)
install_manifest = [
name + " " + checksum for name, checksum in install_checksums.iteritems()]
adb.PushString("\n".join(install_manifest),
- "%s/split_manifest" % app_dir).result()
+ targetpath.join(app_dir, "split_manifest")).result()
def IncrementalInstall(adb_path, execroot, stub_datafile, output_marker,
@@ -697,8 +705,8 @@
temp_dir = tempfile.mkdtemp()
try:
adb = Adb(adb_path, temp_dir, adb_jobs, user_home_dir)
- app_package = GetAppPackage(os.path.join(execroot, stub_datafile))
- app_dir = os.path.join(DEVICE_DIRECTORY, app_package)
+ app_package = GetAppPackage(hostpath.join(execroot, stub_datafile))
+ app_dir = targetpath.join(DEVICE_DIRECTORY, app_package)
if split_main_apk:
SplitIncrementalInstall(adb, app_package, execroot, split_main_apk,
split_apks)
@@ -706,20 +714,20 @@
if not apk:
VerifyInstallTimestamp(adb, app_package)
- with file(os.path.join(execroot, dexmanifest)) as f:
+ with file(hostpath.join(execroot, dexmanifest)) as f:
dexmanifest = f.read()
UploadDexes(adb, execroot, app_dir, temp_dir, dexmanifest, bool(apk))
# TODO(ahumesky): UploadDexes waits for all the dexes to be uploaded, and
# then UploadResources is called. We could instead enqueue everything
# onto the threadpool so that uploading resources happens sooner.
- UploadResources(adb, os.path.join(execroot, resource_apk), app_dir)
+ UploadResources(adb, hostpath.join(execroot, resource_apk), app_dir)
UploadNativeLibs(adb, native_libs, app_dir, bool(apk))
if apk:
- apk_path = os.path.join(execroot, apk)
+ apk_path = targetpath.join(execroot, apk)
adb.Install(apk_path)
future = adb.PushString(
adb.GetInstallTime(app_package),
- "%s/%s/install_timestamp" % (DEVICE_DIRECTORY, app_package))
+ targetpath.join(DEVICE_DIRECTORY, app_package, "install_timestamp"))
future.result()
else:
if start_type == "warm":
diff --git a/tools/android/zip_manifest_creator.sh b/tools/android/zip_manifest_creator.sh
index b421f32..f507df3 100755
--- a/tools/android/zip_manifest_creator.sh
+++ b/tools/android/zip_manifest_creator.sh
@@ -29,18 +29,42 @@
RUNFILES=${RUNFILES:-$0.runfiles}
+PLATFORM="$(uname | tr [:upper:] [:lower:])"
+case "${PLATFORM}" in
+msys*|mingw*|cygwin*)
+ PLATFORM=windows
+esac
+
+if [[ "$PLATFORM" == windows ]]; then
+ function die() {
+ echo >&2 "ERROR: $@"
+ exit 1
+ }
+
+ function rlocation() {
+ [ -e "${RUNFILES}/MANIFEST" ] || die "${RUNFILES}/MANIFEST not found"
+ # Look for the requested file in the MANIFEST, allowing a non-directory
+ # component suffix, e.g. an ".exe" executable.
+ cat "${RUNFILES}/MANIFEST" | grep "^$1[^/\\]*\b" | awk '{print $2}'
+ }
+else
+ function rlocation() {
+ ls "${RUNFILES}/$1"
+ }
+fi
+
# For the sh_binary in BUILD.tools, zipper is here.
-ZIPPER=$RUNFILES/*/tools/zip/zipper/zipper
+ZIPPER="$(rlocation "[^/]*/tools/zip/zipper/zipper")"
if [ ! -x $ZIPPER ]; then
# For the sh_test in BUILD.oss, zipper is here.
- ZIPPER=$RUNFILES/third_party/ijar/zipper
+ ZIPPER="$(rlocation "third_party/ijar/zipper")"
fi
-if [ ! -x $ZIPPER ]; then
+if [ -z "$ZIPPER" -o ! -x "$ZIPPER" ]; then
echo "zip_manifest_creator could not find zipper executable"
exit 1
fi
-$ZIPPER v "$INPUT_ZIP" \
+"$ZIPPER" v "$INPUT_ZIP" \
| cut -d ' ' -f3 \
| grep -v \/$ \
| grep -x "$REGEX" \
To view, visit change 12176. To unsubscribe, visit settings.
László Csomor uploaded patch set #2 to this change.
46 files changed, 706 insertions(+), 229 deletions(-)
To view, visit change 12176. To unsubscribe, visit settings.
László Csomor uploaded patch set #3 to this change.
WIP: android on windows
Change-Id: I3e966dfae841ba1ce7116d880f09bb775c5b5cdf
---
M WORKSPACE
M src/main/java/com/google/devtools/build/lib/BUILD
M src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaSemantics.java
M src/main/java/com/google/devtools/build/lib/bazel/rules/java/java_stub_template.txt
M src/main/java/com/google/devtools/build/lib/bazel/rules/java/java_stub_template_windows.txt
M src/main/java/com/google/devtools/build/lib/bazel/rules/sh/ShBinary.java
A src/main/java/com/google/devtools/build/lib/bazel/rules/sh/sh_stub_template_windows.txt
M src/main/java/com/google/devtools/build/lib/rules/android/AarGeneratorBuilder.java
M src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourceMergingActionBuilder.java
M src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourceValidatorActionBuilder.java
M src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourcesProcessorBuilder.java
M src/main/java/com/google/devtools/build/lib/rules/android/LibraryRGeneratorActionBuilder.java
M src/main/java/com/google/devtools/build/lib/rules/android/ManifestMergerActionBuilder.java
M src/main/java/com/google/devtools/build/lib/rules/android/RClassGeneratorActionBuilder.java
M src/main/java/com/google/devtools/build/lib/rules/android/ResourceShrinkerActionBuilder.java
M src/main/java/com/google/devtools/build/lib/rules/android/RobolectricResourceSymbolsActionBuilder.java
M src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java
M src/main/java/com/google/devtools/build/lib/rules/cpp/CppActionConfigs.java
M src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java
M src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java
50 files changed, 726 insertions(+), 270 deletions(-)
To view, visit change 12176. To unsubscribe, visit settings.