private String generateManifest(PrintWriter writer, Summary summary, Path binaryManifest)
			throws OSGiException, IOException {
		// no manifest, so create one with bndtools
		Analyzer analyzer = new Analyzer();
		analyzer.setJar(new Jar(binaryDir.toFile())); // give bnd the contents
		analyzer.setProperty("Bundle-SymbolicName",
			GhidraSourceBundle.sourceDirHash(getSourceDirectory()));
		analyzer.setProperty("Bundle-Version", GENERATED_VERSION);

		if (importPackageValues.isEmpty()) {
			analyzer.setProperty("Import-Package", "*");
		}
		else {
			// constrain analyzed imports according to what's declared in @importpackage tags
			analyzer.setProperty("Import-Package",
				importPackageValues.stream().collect(Collectors.joining(",")) + ",*");
		}

		analyzer.setProperty("Export-Package", "!*.private.*,!*.internal.*,*");

		try {
			Manifest manifest;
			try {
				manifest = analyzer.calcManifest();
			}
			catch (Exception e) {
				summary.print("Bad manifest");
				throw new OSGiException("Failed to calculate manifest by analyzing code", e);
			}

			if (!addActivatorClass(writer, analyzer, manifest, summary)) {
				return summary.getValue();
			}

			// write the manifest
			Files.createDirectories(binaryManifest.getParent());
			try (OutputStream out = Files.newOutputStream(binaryManifest)) {
				manifest.write(out);
			}
		}
		finally {
			analyzer.close();
		}
		return summary.getValue();
	}
Generate a manifest (and an activator)

<p>Assumes that {@link #updateRequirementsFromMetadata()} has been called recently
Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/osgi/GhidraSourceBundle.java