@Override
	public boolean build(PrintWriter writer) throws Exception {

		writer = NullPrintWriter.dummyIfNull(writer);
		boolean needsCompile = false;

		if (hasSourceManifest()) {
			sourceFileToRequirements.clear();
			requirementToSourceFileMap.clear();
			List<BundleRequirement> reqs = new ArrayList<>(getAllRequirements());
			bundleHost.resolve(reqs);
			Set<String> newMissedRequirements = new HashSet<>();
			for (BundleRequirement req : reqs) {
				newMissedRequirements.add(req.toString());
			}
			if (hasNewManifest() || !newMissedRequirements.equals(missedRequirements)) {
				missedRequirements.clear();
				missedRequirements.addAll(newMissedRequirements);
				wipeBinDir();
				buildErrors.clear();
			}
			updateFromFilesystem(writer);
		}
		else {

			// this gets all source files from the file system that we know need to be compiled 
			// based upon missing or outdated class files
			updateFromFilesystem(writer);
			updateRequirementsFromMetadata();

			// these 2 calls handle source files that need to be compiled based upon changes in 
			// added or removed bundles / requirements
			addSourcesThatNoLongerHaveMissingRequirements();
			addSourcesThatNowHaveMissingRequirements();
		}

		int buildErrorsLastTime = getBuildErrorCount();
		int newSourceCount = getNewSourcesCount();
		if (newSourceCount == 0) {
			if (buildErrorsLastTime > 0) {
				writer.printf("%s hasn't changed, with %d file%s failing in previous build(s):\n",
					getSourceDirectory().toString(), buildErrorsLastTime,
					buildErrorsLastTime > 1 ? "s" : "");
				writer.printf("%s\n", getPreviousBuildErrors());
				writer.flush();
			}
		}
		else {
			needsCompile = true;
		}

		// finally, we should be able to handle empty directories
		if (!binaryDir.toFile().exists()) {
			needsCompile = true;
		}

		if (needsCompile) {
			// if there is a bundle at our locations, uninstall it
			Bundle osgiBundle = bundleHost.getOSGiBundle(getLocationIdentifier());
			if (osgiBundle != null) {
				bundleHost.deactivateSynchronously(osgiBundle);
			}

			// once we've committed to recompile and regenerate classes, delete the old stuff
			deleteOldBinaries();

			String summary = compileToExplodedBundle(writer);
			bundleHost.notifyBundleBuilt(this, summary);
			return true;
		}
		bundleHost.notifyBundleBuilt(this, null);
		return false;
	}
If a file that previously built without errors is now missing some requirements, rebuild it 
to capture errors (if any).
Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/osgi/GhidraSourceBundle.java