public static void linkGhidraToProject(IJavaProject javaProject,
			GhidraApplicationLayout ghidraLayout, AppConfig appConfig,
			ProjectPythonInterpreter pythonInterpreter, IProgressMonitor monitor)
			throws CoreException, IOException {

		// Gets the Ghidra installation directory to link to from the Ghidra layout
		File ghidraInstallDir = ghidraLayout.getApplicationInstallationDir().getFile(false);

		// Get the Java VM used to launch the Ghidra to link to
		IVMInstall vm = getGhidraVm(appConfig);
		IPath vmPath =
			new Path(JavaRuntime.JRE_CONTAINER).append(vm.getVMInstallType().getId()).append(
				vm.getName());

		// Get the project's existing linked Ghidra installation folder and path (it may not exist)
		IFolder ghidraFolder =
			javaProject.getProject().getFolder(GhidraProjectUtils.GHIDRA_FOLDER_NAME);
		IPath oldGhidraPath = null;
		GhidraApplicationLayout oldGhidraLayout = null;
		if (ghidraFolder.exists() ) {
			oldGhidraPath = ghidraFolder.getLocation();
			if (oldGhidraPath != null) {
				File oldGhidraDir = oldGhidraPath.toFile();
				if (oldGhidraDir.exists()) {
					oldGhidraLayout = new GhidraApplicationLayout(oldGhidraDir);
				}
			}
		}

		// Loop through the project's existing classpath to decide what to keep (things that aren't
		// related to Ghidra), and things to not keep (things that will be added fresh from the new
		// Ghidra).
		IClasspathEntry vmEntryCandidate = null;
		List<IClasspathEntry> classpathEntriesToKeep = new ArrayList<>();
		for (IClasspathEntry entry : javaProject.getRawClasspath()) {

			// If the project is not linked to an old Ghidra, save off the project's existing VM.  
			// We'll decide whether or not to keep it later.
			if (entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER &&
				entry.getPath().toString().startsWith(JavaRuntime.JRE_CONTAINER)) {
				if (oldGhidraPath == null) {
					vmEntryCandidate = entry;
				}
			}
			else if (entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER &&
				entry.getPath().toString().startsWith(JUnitCore.JUNIT_CONTAINER_ID)) {
				// Keep existing JUnit
				classpathEntriesToKeep.add(entry);
			}
			else if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
				// Keep all project dependencies
				classpathEntriesToKeep.add(entry);
			}
			else {
				// If the project is linked to an old Ghidra, keep the list of source folders that are
				// linked to the Ghidra installation (after updating their paths to point to the new
				// Ghidra installation).
				IFolder entryFolder = null;
				if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
					entryFolder = ResourcesPlugin.getWorkspace().getRoot().getFolder(entry.getPath());
				}
				if (entryFolder != null && entryFolder.isLinked() &&
					inGhidraInstallation(oldGhidraPath, entryFolder.getLocation())) {
					String origPath = entryFolder.getLocation().toString();
					String newPath = ghidraInstallDir.getAbsolutePath() +
						origPath.substring(oldGhidraPath.toString().length());
					entryFolder.createLink(new Path(newPath), IResource.REPLACE, monitor);
					classpathEntriesToKeep.add(JavaCore.newSourceEntry(entryFolder.getFullPath()));
				}
				// If it's anything else that doesn't live in the old Ghidra installation, keep it.
				// Note that installed Ghidra extensions can live in the user settings directory
				// which is outside the installation directory.  We don't want to keep these.
				else if (!inGhidraInstallation(oldGhidraPath, entry.getPath()) &&
					!isGhidraExtension(oldGhidraLayout, entry.getPath())) {
					classpathEntriesToKeep.add(entry);
					ghidraLayout.getExtensionInstallationDirs();
				}
			}
		}

		// If we detected a VM to potentially keep, we should ask the user if they are OK with using 
		// the VM that Ghidra wants to use.  Changing it automatically might cause problems for their 
		// existing Java project.
		if (vmEntryCandidate == null || (!vmEntryCandidate.getPath().equals(vmPath) &&
			EclipseMessageUtils.showConfirmDialog("Java Conflict",
				"Current Java: " + JavaRuntime.getVMInstall(javaProject).getName() +
					"\nGhidra Java: " + vm.getName() +
					"\n\nPress OK to use Ghidra's Java, or cancel to keep current Java."))) {
			classpathEntriesToKeep.add(JavaCore.newContainerEntry(vmPath));
		}
		else {
			classpathEntriesToKeep.add(vmEntryCandidate);
		}

		// Add the Ghidra libraries from the new Ghidra installation directory to the classpath
		List<IClasspathEntry> libraryClasspathEntries =
			getGhidraLibraryClasspathEntries(ghidraLayout);
		classpathEntriesToKeep.addAll(libraryClasspathEntries);

		// Set classpath
		javaProject.setRawClasspath(
			classpathEntriesToKeep.toArray(new IClasspathEntry[classpathEntriesToKeep.size()]),
			null);

		// Update link to the Ghidra installation directory
		ghidraFolder.createLink(new Path(ghidraInstallDir.getAbsolutePath()), IResource.REPLACE,
			monitor);

		// Update language ant properties file, if applicable
		GhidraModuleUtils.writeAntProperties(javaProject.getProject(), ghidraLayout);

		// Setup Python for the project
		try {
			PyDevUtils.setupPythonForProject(javaProject, libraryClasspathEntries,
				pythonInterpreter, monitor);
		}
		catch (OperationNotSupportedException e) {
			EclipseMessageUtils.showErrorDialog("PyDev error",
				"Failed to setup Python for the project.  PyDev version is not supported.");
		}
	}
Links the Ghidra layout to the given Java project.  This effectively makes the project's 
build path "Ghidra aware." 
<p>
If the project already has a Ghidra installation directory linked to it, that link is deleted
and the new Ghidra installation directory is freshly linked back in.

@param javaProject The Java project to link.
@param ghidraLayout The Ghidra layout to link the project to.
@param appConfig Ghidra's application configuration.
@param pythonInterpreter The Python interpreter to use.
@param monitor The progress monitor used during link.
@throws IOException If there was a file-related problem with linking in Ghidra.
@throws CoreException If there was an Eclipse-related problem with linking in Ghidra.
GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/src/main/java/ghidradev/ghidraprojectcreator/utils/GhidraProjectUtils.java