public void run() {
    var showVersion = arguments.getBoolean("version", "show version then exit", false);
    var buildInfo = BuildInfo.get();
    if (buildInfo != null && LOGGER.isInfoEnabled()) {
      LOGGER.info("Planetiler build git hash: {}", buildInfo.githash());
      LOGGER.info("Planetiler build version: {}", buildInfo.version());
      LOGGER.info("Planetiler build timestamp: {}", buildInfo.buildTimeString());
    }
    if (showVersion) {
      System.exit(0);
    }
    if (profile() == null) {
      throw new IllegalArgumentException("No profile specified");
    }
    if (output == null) {
      throw new IllegalArgumentException("No output specified");
    }
    if (stages.isEmpty()) {
      throw new IllegalArgumentException("No sources specified");
    }
    if (ran) {
      throw new IllegalArgumentException("Can only run once");
    }
    ran = true;

    if (arguments.getBoolean("help", "show arguments then exit", false)) {
      System.exit(0);
    } else if (onlyRunTests != null) {
      boolean success = JavaProfileValidator.validate(profile(), onlyRunTests, config());
      System.exit(success ? 0 : 1);
    } else if (onlyDownloadSources) {
      // don't check files if not generating map
    } else if (config.append()) {
      if (!output.format().supportsAppend()) {
        throw new IllegalArgumentException("cannot append to " + output.format().id());
      }
      if (!output.exists()) {
        throw new IllegalArgumentException(output.uri() + " must exist when appending");
      }
    } else if (overwrite || config.force()) {
      output.delete();
    } else if (output.exists()) {
      throw new IllegalArgumentException(
        output.uri() + " already exists, use the --force argument to overwrite or --append.");
    }

    Path layerStatsPath = arguments.file("layer_stats", "layer stats output path",
      // default to <output file>.layerstats.tsv.gz
      TileSizeStats.getDefaultLayerstatsPath(Optional.ofNullable(output.getLocalPath()).orElse(Path.of("output"))));

    if (config.tileWriteThreads() < 1) {
      throw new IllegalArgumentException("require tile_write_threads >= 1");
    }
    if (config.tileWriteThreads() > 1) {
      if (!output.format().supportsConcurrentWrites()) {
        throw new IllegalArgumentException(output.format() + " doesn't support concurrent writes");
      }
      IntStream.range(1, config.tileWriteThreads())
        .mapToObj(output::getPathForMultiThreadedWriter)
        .forEach(p -> {
          if (!config.append() && (overwrite || config.force())) {
            FileUtils.delete(p);
          }
          if (config.append() && !output.exists(p)) {
            throw new IllegalArgumentException("indexed archive \"" + p + "\" must exist when appending");
          } else if (!config.append() && output.exists(p)) {
            throw new IllegalArgumentException("indexed archive \"" + p + "\" must not exist when not appending");
          }
        });
    }

    LOGGER.info("Building {} profile into {} in these phases:", profile.getClass().getSimpleName(), output.uri());

    if (!toDownload.isEmpty()) {
      LOGGER.info("  download: Download sources {}", toDownload.stream().map(d -> d.id).toList());
    }

    if (!onlyDownloadSources && fetchWikidata) {
      LOGGER.info("  wikidata: Fetch translations from wikidata query service");
    }

    if (!onlyDownloadSources && !onlyFetchWikidata) {
      for (Stage stage : stages) {
        for (String details : stage.details) {
          LOGGER.info("  {}", details);
        }
      }
      LOGGER.info("  sort: Sort rendered features by tile ID");
      LOGGER.info("  archive: Encode each tile and write to {}", output);
    }

    // in case any temp files are left from a previous run...
    FileUtils.delete(tmpDir, nodeDbPath, featureDbPath, multipolygonPath);
    FileUtils.createDirectory(tmpDir);
    FileUtils.createParentDirectories(nodeDbPath, featureDbPath, multipolygonPath, output.getLocalBasePath());

    if (!toDownload.isEmpty()) {
      download();
    }
    if (fetchOsmTileStats) {
      TopOsmTiles.downloadPrecomputed(config);
    }
    ensureInputFilesExist();

    if (fetchWikidata) {
      Wikidata.fetch(osmInputFile(), wikidataNamesFile, config(), profile(), stats(), wikidataMaxAge,
        wikidataUpdateLimit);
    }
    if (useWikidata) {
      translations().addFallbackTranslationProvider(Wikidata.load(wikidataNamesFile));
    }
    if (onlyDownloadSources || onlyFetchWikidata) {
      return; // exit only if just fetching wikidata or downloading sources
    }

    if (osmInputFile != null) {
      checkDiskSpace();
      checkMemory();
      var bounds = config.bounds();
      if (!parseNodeBounds) {
        bounds.addFallbackProvider(osmInputFile);
      }
      bounds.addFallbackProvider(new OsmNodeBoundsProvider(osmInputFile, config, stats));
    }
    // must construct this after bounds providers are added in order to infer bounds from the input source if not provided
    tileArchiveMetadata = new TileArchiveMetadata(profile, config);

    try (WriteableTileArchive archive = TileArchives.newWriter(output, config)) {
      featureGroup =
        FeatureGroup.newDiskBackedFeatureGroup(archive.tileOrder(), featureDbPath, profile, config, stats);
      stats.monitorFile("nodes", nodeDbPath);
      stats.monitorFile("features", featureDbPath);
      stats.monitorFile("multipolygons", multipolygonPath);
      stats.monitorFile("archive", output.getLocalPath(), archive::bytesWritten);

      for (Stage stage : stages) {
        try {
          stage.task.run();
        } catch (Exception e) {
          throw new PlanetilerException("Error occurred during stage " + stage.id, e);
        }
      }

      LOGGER.info("Deleting node.db to make room for output file");
      profile.release();
      for (var inputPath : inputPaths) {
        if (inputPath.freeAfterReading()) {
          LOGGER.info("Deleting {} ({}) to make room for output file", inputPath.id, inputPath.path);
          FileUtils.delete(inputPath.path());
        }
      }

      featureGroup.prepare();

      TileArchiveWriter.writeOutput(featureGroup, archive, archive::bytesWritten, tileArchiveMetadata, layerStatsPath,
        config, stats);
    } catch (IOException e) {
      throw new PlanetilerException("Unable to write to " + output, e);
    }

    overallTimer.stop();
    LOGGER.info("FINISHED!");
    stats.printSummary();
    try {
      stats.close();
    } catch (Exception e) {
      throw new PlanetilerException(e);
    }
  }
Reads all elements from all sourced that have been added, generates map features according to the profile, and
writes the rendered tiles to the output archive.

@throws IllegalArgumentException if expected inputs have not been provided
planetiler-core/src/main/java/com/onthegomap/planetiler/Planetiler.java