-------------- next part --------------
From 94816f65ce4337749ccee2ba051dbb51ef77927d Mon Sep 17 00:00:00 2001
From: jhauga <johnhaugabook@gmail.com>
Date: Tue, 5 Aug 2025 19:31:50 -0400
Subject: [PATCH setup] add --build-depend option

Use option --build-depend to pass packages from setup property build-depends
to use with -P --packages option (as if it were used with parsed packages).
---
 Makefile.am      |   2 +
 build_depends.cc | 145 +++++++++++++++++++++++++++++++++++++++++++++++
 build_depends.h  |  34 +++++++++++
 package_meta.cc  |  14 ++++-
 res/en/res.rc    |   1 +
 resource.h       |   1 +
 6 files changed, 195 insertions(+), 2 deletions(-)
 create mode 100644 build_depends.cc
 create mode 100644 build_depends.h

diff --git a/Makefile.am b/Makefile.am
index 4046d37..daf1609 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -136,6 +136,8 @@ endif
 	archive_tar.cc \
 	archive_tar.h \
 	archive_tar_file.cc \
+	build_depends.h \
+	build_depends.cc \
 	choose.cc \
 	choose.h \
 	compactos.cc \
diff --git a/build_depends.cc b/build_depends.cc
new file mode 100644
index 0000000..755065b
--- /dev/null
+++ b/build_depends.cc
@@ -0,0 +1,145 @@
+/*
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     A copy of the GNU General Public License can be found at
+ *     http://www.gnu.org/
+ *
+ */
+
+#include "build_depends.h"
+
+#include <fstream>
+#include <algorithm>
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <cstdio>
+
+#include "io_stream.h"
+#include "ini.h"
+#include "resource.h"
+#include "site.h"
+#include "state.h"
+#include "csu_util/rfc1738.h"
+#include "package_meta.h"
+#include "getopt++/StringArrayOption.h"
+
+// Forward declare class for ==build-depend option.
+StringOption BuildDependsOption ("", '\0', "build-depend", IDS_HELPTEXT_BUILD_DEPENDS, false);
+
+/* Used in package_meta to redefine PackageOption so output from
+build-depend can be substituted. */
+bool buildDependPackage;
+
+// Add extern declarations for variables from ini.cc
+extern std::string local_dir;
+extern SiteList site_list;
+
+// Add extern declaration for PackageOption from package_meta.cc
+extern StringArrayOption PackageOption;
+
+std::string
+build_depend(std::string pkg_search)
+{
+  // Use option passed as argument.
+  std::string target_pkg = pkg_search;
+
+  // Mark and property for identifying package and extracting value.
+  std::string pkg_marker = "@";
+  std::string key = "build-depends:";
+
+  std::string depend_packages; // for final output
+
+  // Use the cached setup.ini file created by ini.cc instead of parameter
+  std::string cached_ini_path = local_dir + "/" +
+                                rfc1738_escape_part(site_list.begin()->url) +
+                                "/" + SetupArch() + "/" + SetupBaseName() + ".ini";
+
+  std::ifstream infile(cached_ini_path);
+
+  // Ensure setup.ini was identified
+  if (!infile) {
+    depend_packages = "Error opening cached setup.ini";
+    return depend_packages;
+  }
+
+  // Start process of reading setup.
+  std::string line;
+  bool inPkg = false;
+  while (std::getline(infile, line)) {
+    std::istringstream iss(line);
+    std::string first, second;
+    iss >> first >> second;
+
+    // For each pkg_marker check if name matches option.
+    if (first == pkg_marker)
+    {
+      if (second == target_pkg)
+      {
+        // Package found, handle next lines accordingly.
+        inPkg = true;
+        continue;
+      }
+      else
+      {
+        inPkg = false;
+        continue;
+      }
+    }
+
+    // If package found and has property build-depends.
+    if (inPkg && line.find(key) == 0) {
+      /* Extract by property length, then remove space character
+      using ASCII encoding. */
+      depend_packages = line.substr(key.size());
+
+      // Trim leading whitespace.
+      depend_packages.erase(0, depend_packages.find_first_not_of(" \t"));
+      depend_packages.erase(depend_packages.find_last_not_of(" \t") + 1);
+
+      // Set condition to use build-depend output in package_meta.cc.
+      buildDependPackage = true;
+
+      // Output to PackageOption.
+      return depend_packages;
+    }
+  }
+  // Output package passed to variable if none found.
+  buildDependPackage = false;
+  return target_pkg;
+}
+
+// Process build_depend() output and use to create PackageOption class.
+void
+build_depend_to_packages(std::string pkg_search)
+{
+  // Get build dependencies from build_depend function using the passed parameter.
+  std::string build_deps_result = build_depend(pkg_search);
+
+  // Ensure results are returned.
+  if (build_deps_result != "no-build-depends-found" &&
+      build_deps_result != "Error opening cached setup.ini" &&
+      !build_deps_result.empty())
+  {
+    // Also parse individual dependencies for PackageOption.
+    std::istringstream deps_stream(build_deps_result);
+    std::string dep_name;
+
+    while (std::getline(deps_stream, dep_name, ','))
+    {
+      // Trim whitespace.
+      dep_name.erase(0, dep_name.find_first_not_of(" \t"));
+      dep_name.erase(dep_name.find_last_not_of(" \t") + 1);
+
+      if (!dep_name.empty())
+      {
+        /* Add the entire dependency string to PackageOption as one entry
+        This simulates: ./setup -P package1,package2,etc... */
+        PackageOption.Process(dep_name.c_str(), 0);
+      }
+    }
+  }
+}
diff --git a/build_depends.h b/build_depends.h
new file mode 100644
index 0000000..ade24e7
--- /dev/null
+++ b/build_depends.h
@@ -0,0 +1,34 @@
+/*
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     A copy of the GNU General Public License can be found at
+ *     http://www.gnu.org/
+ *
+ */
+
+#ifndef USE_BUILD_DEPENDS_H
+#define USE_BUILD_DEPENDS_H
+
+#include "getopt++/StringOption.h"
+#include "getopt++/StringArrayOption.h"
+#include "resource.h"
+
+// Declare as extern, final definition in build_depends.cc.
+extern StringOption BuildDependsOption;
+
+// Use to pass build-depends packages in package_meta.cc.
+extern bool buildDependPackage;
+
+// Forward declare external PackageOption from package_meta.cc.
+extern StringArrayOption PackageOption;
+
+// Forward declare function for use.
+std::string build_depend(std::string pkg_search);
+
+// Forward declare function to pass data to PackageOption.
+void build_depend_to_packages(std::string pkg_search);
+
+#endif /* USE_BUILD_DEPENDS_H */
diff --git a/package_meta.cc b/package_meta.cc
index 3daa970..9369c14 100644
--- a/package_meta.cc
+++ b/package_meta.cc
@@ -26,6 +26,7 @@
 
 #include "io_stream.h"
 #include "compress.h"
+#include "build_depends.h"
 
 #include "filemanip.h"
 #include "LogSingleton.h"
@@ -47,7 +48,7 @@
 
 static StringArrayOption DeletePackageOption ('x', "remove-packages", IDS_HELPTEXT_REMOVE_PACKAGES);
 static StringArrayOption DeleteCategoryOption ('c', "remove-categories", IDS_HELPTEXT_REMOVE_CATEGORIES);
-static StringArrayOption PackageOption ('P', "packages", IDS_HELPTEXT_PACKAGES);
+StringArrayOption PackageOption ('P', "packages", IDS_HELPTEXT_PACKAGES);
 static StringArrayOption CategoryOption ('C', "categories", IDS_HELPTEXT_CATEGORIES);
 bool hasManualSelections = 0;
 
@@ -342,6 +343,15 @@ bool packagemeta::isManuallyWanted(packageversion &version) const
     option string and store them away in an STL set.  */
   if (!parsed_yet)
   {
+    // Check --build-depend first and process it into PackageOption.
+    std::string build_depends_options = BuildDependsOption;
+    if (!build_depends_options.empty())
+    {
+      // Process build depends and add directly to PackageOption
+      build_depend_to_packages(build_depends_options);
+    }
+
+    // Now use PackageOption for all processing.
     std::vector<std::string> packages_options = PackageOption;
     std::vector<std::string> categories_options = CategoryOption;
 
@@ -845,7 +855,7 @@ packagemeta::scan (const packageversion &pkg, bool mirror_mode)
           && ::source == IDC_SOURCE_LOCALDIR)
         return false;
     }
-  catch (Exception * e)
+    catch (Exception * e)
     {
       // We can ignore these, since we're clearing the source list anyway
       if (e->errNo () == APPERR_CORRUPT_PACKAGE)
diff --git a/res/en/res.rc b/res/en/res.rc
index 0bdd4c7..d8b2298 100644
--- a/res/en/res.rc
+++ b/res/en/res.rc
@@ -656,6 +656,7 @@ BEGIN
     IDS_HELPTEXT_ALLOW_UNSUPPORTED_WINDOWS "Allow old, unsupported Windows versions"
     IDS_HELPTEXT_ARCH "Architecture to install (x86_64 or x86)"
     IDS_HELPTEXT_CATEGORIES "Specify categories to install"
+    IDS_HELPTEXT_BUILD_DEPENDS "Install the build requirements of a package"
     IDS_HELPTEXT_COMPACTOS "Compress installed files with Compact OS (xpress4k, xpress8k, xpress16k, lzx)"
     IDS_HELPTEXT_DELETE_ORPHANS "Remove orphaned packages"
     IDS_HELPTEXT_DISABLE_ANTIVIRUS "Disable known or suspected buggy anti virus software packages during execution"
diff --git a/resource.h b/resource.h
index a08489c..11fef73 100644
--- a/resource.h
+++ b/resource.h
@@ -158,6 +158,7 @@
 #define IDS_HELPTEXT_HEADER              1546
 #define IDS_HELPTEXT_FOOTER              1547
 #define IDS_HELPTEXT_NO_WRITE_REGISTRY   1548
+#define IDS_HELPTEXT_BUILD_DEPENDS       1549
 
 // Dialogs
 
-- 
2.49.0.windows.1

