private Loaded<Program> loadLibraryFromSearchPaths(String library, ByteProvider provider,
			List<LibrarySearchPath> searchPaths, String libraryDestFolderPath,
			Queue<UnprocessedLibrary> unprocessed, int depth, LoadSpec desiredLoadSpec,
			List<Option> options, MessageLog log, Object consumer, TaskMonitor monitor)
			throws CancelledException, IOException {

		if (searchPaths.isEmpty()) {
			return null;
		}

		log.appendMsg("Searching %d path%s for library %s...".formatted(searchPaths.size(),
			searchPaths.size() > 1 ? "s" : "", library));

		Program libraryProgram = null;
		String simpleLibraryName = FilenameUtils.getName(library);
		boolean isAbsolute = new File(library).isAbsolute();

		boolean success = false;
		try {
			List<FSRL> candidateLibraryFsrls =
				findLibraryOnDisk(library, searchPaths, log, monitor);
			if (candidateLibraryFsrls.isEmpty()) {
				log.appendMsg("Library not found.");
				return null;
			}

			for (FSRL candidateLibraryFsrl : candidateLibraryFsrls) {
				monitor.checkCancelled();
				List<String> newLibraryList = new ArrayList<>();
				libraryProgram = loadLibrary(simpleLibraryName, candidateLibraryFsrl,
					desiredLoadSpec, newLibraryList, options, consumer, log, monitor);
				for (String newLibraryName : newLibraryList) {
					unprocessed.add(new UnprocessedLibrary(newLibraryName, depth - 1, false));
				}
				if (libraryProgram == null) {
					continue;
				}
				processLibrary(libraryProgram, library, candidateLibraryFsrl, provider, unprocessed,
					depth, desiredLoadSpec, options, log, monitor);
				success = true;
				String folderPath = libraryDestFolderPath;
				if (folderPath != null) {
					if (isAbsolute) {
						folderPath = joinPaths(folderPath, FilenameUtils.getFullPath(library));
					}
				}
				return new Loaded<Program>(libraryProgram, simpleLibraryName, folderPath);
			}
		}
		finally {
			if (!success && libraryProgram != null) {
				libraryProgram.release(consumer);
			}
		}
		return null;
	}
Loads the given library into the given {@link DomainFolder folder} if it can find it in
the given {@link List} of search paths

@param library The library to load
@param provider The {@link ByteProvider} of the program being loaded
@param searchPaths A {@link List} of {@link LibrarySearchPath}s that will be searched
@param libraryDestFolderPath The path of the project folder to load the libraries into. 
  Could be null if the specified project is null or a destination folder path could not be 
  determined.
@param unprocessed The {@link Queue} of {@link UnprocessedLibrary unprocessed libraries}
@param depth The load depth of the library to load
@param desiredLoadSpec The desired {@link LoadSpec}
@param options The load options
@param log The log
@param consumer A consumer object for {@link DomainObject}s generated
@param monitor A cancelable task monitor
@return The {@link Loaded} library, or null if it was not found. The returned library is the
  caller's responsibility to release.
@throws IOException if there was an IO-related problem loading
@throws CancelledException if the user cancelled the load
Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/AbstractLibrarySupportLoader.java