Accept --target_label, --injecting_rule_kind in ijar.

This is a rollforward with fixes.

The values (if present) are written into the manifest with this format:

Target-Label: <label>
Injecting-Rule-Kind: <kind>

In the future, JavaBuilder will make sure of this instead of command line arguments to find owners for jars for its add_dep commands.

PiperOrigin-RevId: 185159950
diff --git a/third_party/ijar/ijar.cc b/third_party/ijar/ijar.cc
index 144120e..d7742ee 100644
--- a/third_party/ijar/ijar.cc
+++ b/third_party/ijar/ijar.cc
@@ -36,6 +36,14 @@
 const char* CLASS_EXTENSION = ".class";
 const size_t CLASS_EXTENSION_LENGTH = strlen(CLASS_EXTENSION);
 
+const char *MANIFEST_HEADER =
+    "Manifest-Version: 1.0\n"
+    "Created-By: bazel\n";
+// These attributes are used by JavaBuilder, Turbine, and ijar.
+// They must all be kept in sync.
+const char *TARGET_LABEL_KEY = "Target-Label: ";
+const char *INJECTING_RULE_KIND_KEY = "Injecting-Rule-Kind: ";
+
 // ZipExtractorProcessor that select only .class file and use
 // StripClass to generate an interface class, storing as a new file
 // in the specified ZipBuilder.
@@ -105,9 +113,39 @@
   }
 }
 
+// Copies the string into the buffer without the null terminator, returns length
+static size_t WriteStr(u1 *buf, const char *str) {
+  size_t len = strlen(str);
+  memcpy(buf, str, len);
+  return len;
+}
+
+static void WriteManifest(ZipBuilder *out, const char *target_label,
+                          const char *injecting_rule_kind) {
+  if (target_label == NULL) {
+    return;
+  }
+  out->WriteEmptyFile("META-INF/");
+  u1 *start = out->NewFile("META-INF/MANIFEST.MF", 0);
+  u1 *buf = start;
+  buf += WriteStr(buf, MANIFEST_HEADER);
+  buf += WriteStr(buf, TARGET_LABEL_KEY);
+  buf += WriteStr(buf, target_label);
+  *buf++ = '\n';
+  if (injecting_rule_kind) {
+    buf += WriteStr(buf, INJECTING_RULE_KIND_KEY);
+    buf += WriteStr(buf, injecting_rule_kind);
+    *buf++ = '\n';
+  }
+  size_t total_len = buf - start;
+  out->FinishFile(total_len);
+}
+
 // Opens "file_in" (a .jar file) for reading, and writes an interface
 // .jar to "file_out".
-void OpenFilesAndProcessJar(const char *file_out, const char *file_in) {
+static void OpenFilesAndProcessJar(const char *file_out, const char *file_in,
+                                   const char *target_label,
+                                   const char *injecting_rule_kind) {
   JarStripperProcessor processor;
   std::unique_ptr<ZipExtractor> in(ZipExtractor::Create(file_in, &processor));
   if (in.get() == NULL) {
@@ -129,6 +167,7 @@
     fprintf(stderr, "%s\n", in->GetError());
     abort();
   }
+  WriteManifest(out.get(), target_label, injecting_rule_kind);
 
   // Add dummy file, since javac doesn't like truly empty jars.
   if (out->GetNumberFiles() == 0) {
@@ -148,25 +187,39 @@
             static_cast<int>(100.0 * out_length / in_length));
   }
 }
-
 }  // namespace devtools_ijar
 
 //
 // main method
 //
 static void usage() {
-  fprintf(stderr, "Usage: ijar [-v] x.jar [x_interface.jar>]\n");
+  fprintf(stderr,
+          "Usage: ijar "
+          "[-v] [--target label label] [--injecting_rule_kind kind] "
+          "x.jar [x_interface.jar>]\n");
   fprintf(stderr, "Creates an interface jar from the specified jar file.\n");
   exit(1);
 }
 
 int main(int argc, char **argv) {
+  const char *target_label = NULL;
+  const char *injecting_rule_kind = NULL;
   const char *filename_in = NULL;
   const char *filename_out = NULL;
 
   for (int ii = 1; ii < argc; ++ii) {
     if (strcmp(argv[ii], "-v") == 0) {
       devtools_ijar::verbose = true;
+    } else if (strcmp(argv[ii], "--target_label") == 0) {
+      if (++ii >= argc) {
+        usage();
+      }
+      target_label = argv[ii];
+    } else if (strcmp(argv[ii], "--injecting_rule_kind") == 0) {
+      if (++ii >= argc) {
+        usage();
+      }
+      injecting_rule_kind = argv[ii];
     } else if (filename_in == NULL) {
       filename_in = argv[ii];
     } else if (filename_out == NULL) {
@@ -199,6 +252,7 @@
     fprintf(stderr, "INFO: writing to '%s'.\n", filename_out);
   }
 
-  devtools_ijar::OpenFilesAndProcessJar(filename_out, filename_in);
+  devtools_ijar::OpenFilesAndProcessJar(filename_out, filename_in, target_label,
+                                        injecting_rule_kind);
   return 0;
 }
diff --git a/third_party/ijar/test/BUILD b/third_party/ijar/test/BUILD
index 455ab29..6b4eeb9 100644
--- a/third_party/ijar/test/BUILD
+++ b/third_party/ijar/test/BUILD
@@ -101,6 +101,14 @@
     tools = ["//third_party/ijar"],
 )
 
+genrule(
+    name = "interface_ijar_testlib_with_target_label",
+    srcs = [":ijar_testlib"],
+    outs = ["interface_ijar_testlib_with_target_label.jar"],
+    cmd = "$(location //third_party/ijar) --target_label //foo:foo --injecting_rule_kind foo_library $< $@",
+    tools = ["//third_party/ijar"],
+)
+
 java_library(
     name = "typeannotations2",
     srcs = glob(["typeannotations2/**/*.java"]),
diff --git a/third_party/ijar/test/IjarTests.java b/third_party/ijar/test/IjarTests.java
index 4e0fb5d..4676805 100644
--- a/third_party/ijar/test/IjarTests.java
+++ b/third_party/ijar/test/IjarTests.java
@@ -23,15 +23,19 @@
 import com.google.devtools.build.java.bazel.BazelJavaCompiler;
 import java.io.File;
 import java.io.IOException;
+import java.time.Instant;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Enumeration;
+import java.util.GregorianCalendar;
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
+import java.util.jar.Attributes;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
+import java.util.jar.Manifest;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 import javax.annotation.processing.AbstractProcessor;
@@ -274,4 +278,18 @@
     assertThat(new String(lib.get("module-info.class"), UTF_8)).isEqualTo("hello");
     assertThat(new String(lib.get("foo/module-info.class"), UTF_8)).isEqualTo("goodbye");
   }
+
+  @Test
+  public void testTargetLabel() throws Exception {
+    try (JarFile jf =
+        new JarFile("third_party/ijar/test/interface_ijar_testlib_with_target_label.jar")) {
+      Manifest manifest = jf.getManifest();
+      Attributes attributes = manifest.getMainAttributes();
+      assertThat(attributes.getValue("Target-Label")).isEqualTo("//foo:foo");
+      assertThat(attributes.getValue("Injecting-Rule-Kind")).isEqualTo("foo_library");
+      assertThat(jf.getEntry(JarFile.MANIFEST_NAME).getLastModifiedTime().toInstant())
+          .isEqualTo(
+              Instant.ofEpochMilli(new GregorianCalendar(1980, 0, 1, 0, 0, 0).getTimeInMillis()));
+    }
+  }
 }