Fix python zip file name when target name has dot (.)
To fix https://buildkite.com/bazel/bazel-at-head-plus-disabled/builds/351#26e616ad-56b1-4d78-b64c-fcb3c5c66f41/436-470
When building python zip file on linux and mac, we accidentally remove the last segment when a python target name has dot (.).
For example, `create_tensorflow.python_api_2_keras_python_api_gen_compat_v2 -> create_tensorflow`
This commit replace the usage of `ruleContext.getDerivedArtifact` with a custom implementation to fix this problem.
Closes #10119.
PiperOrigin-RevId: 277685509
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/python/BazelPythonSemantics.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/python/BazelPythonSemantics.java
index edda16d..8817271 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/python/BazelPythonSemantics.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/python/BazelPythonSemantics.java
@@ -131,14 +131,6 @@
return result;
}
- /**
- * Returns an artifact next to the executable file with ".temp" suffix. Used only if we're
- * building a zip.
- */
- public Artifact getPythonIntermediateStubArtifact(RuleContext ruleContext, Artifact executable) {
- return ruleContext.getRelatedArtifact(executable.getRootRelativePath(), ".temp");
- }
-
private static String boolToLiteral(boolean value) {
return value ? "True" : "False";
}
@@ -308,7 +300,7 @@
if (!ruleContext.hasErrors()) {
// Create the stub file that's needed by the python zip file.
- Artifact stubFileForZipFile = getPythonIntermediateStubArtifact(ruleContext, executable);
+ Artifact stubFileForZipFile = common.getPythonIntermediateStubArtifact(executable);
createStubFile(ruleContext, stubFileForZipFile, common, /* isForZipFile= */ true);
createPythonZipAction(
diff --git a/src/main/java/com/google/devtools/build/lib/rules/python/PyCommon.java b/src/main/java/com/google/devtools/build/lib/rules/python/PyCommon.java
index ede7f3a..161cc8b 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/python/PyCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/python/PyCommon.java
@@ -858,9 +858,34 @@
addPyExtraActionPseudoAction();
}
- /** @return An artifact next to the executable file with ".zip" suffix */
+ /** @return an artifact next to the executable file with a given suffix. */
+ private Artifact getArtifactWithExtension(Artifact executable, String extension) {
+ // On Windows, the Python executable has .exe extension on Windows,
+ // On Linux, the Python executable has no extension.
+ // We can't use ruleContext#getRelatedArtifact because it would mangle files with dots in the
+ // name on non-Windows platforms.
+ PathFragment pathFragment = executable.getRootRelativePath();
+ String fileName = executable.getFilename();
+ if (OS.getCurrent() == OS.WINDOWS) {
+ Preconditions.checkArgument(fileName.endsWith(".exe"));
+ fileName = fileName.substring(0, fileName.length() - 4) + extension;
+ } else {
+ fileName = fileName + extension;
+ }
+ return ruleContext.getDerivedArtifact(pathFragment.replaceName(fileName), executable.getRoot());
+ }
+
+ /** Returns an artifact next to the executable file with ".zip" suffix. */
public Artifact getPythonZipArtifact(Artifact executable) {
- return ruleContext.getRelatedArtifact(executable.getRootRelativePath(), ".zip");
+ return getArtifactWithExtension(executable, ".zip");
+ }
+
+ /**
+ * Returns an artifact next to the executable file with ".temp" suffix. Used only if we're
+ * building a zip.
+ */
+ public Artifact getPythonIntermediateStubArtifact(Artifact executable) {
+ return getArtifactWithExtension(executable, ".temp");
}
/** Returns an artifact next to the executable file with no suffix. Only called for Windows. */
diff --git a/src/test/py/bazel/py_test.py b/src/test/py/bazel/py_test.py
index 085ec2b..b770e10 100644
--- a/src/test/py/bazel/py_test.py
+++ b/src/test/py/bazel/py_test.py
@@ -114,6 +114,23 @@
self.assertFalse(
os.path.exists('bazel-bin/src/a/a.runfiles/__main__/src/a/__init__.py'))
+ # Regression test for https://github.com/bazelbuild/bazel/pull/10119
+ def testBuildingZipFileWithTargetNameWithDot(self):
+ self.CreateWorkspaceWithDefaultRepos('WORKSPACE')
+ self.ScratchFile('BUILD', [
+ 'py_binary(',
+ ' name = "bin.v1", # .v1 should not be treated as extension and removed accidentally',
+ ' srcs = ["bin.py"],',
+ ' main = "bin.py",',
+ ')',
+ ])
+ self.ScratchFile('bin.py', 'print("Hello, world")')
+ exit_code, _, stderr = self.RunBazel(
+ ['build', '--build_python_zip', '//:bin.v1'])
+ self.AssertExitCode(exit_code, 0, stderr)
+ self.assertTrue(os.path.exists('bazel-bin/bin.v1.temp'))
+ self.assertTrue(os.path.exists('bazel-bin/bin.v1.zip'))
+
if __name__ == '__main__':
unittest.main()