https://gcc.gnu.org/g:a514707ffd7d58b140686036c2dece43ecb7d33c

commit r17-1532-ga514707ffd7d58b140686036c2dece43ecb7d33c
Author: Jeff Law <[email protected]>
Date:   Sat Jun 13 09:05:32 2026 -0600

    [PATCH v6 4/4] find_a_program: Search with machine prefix in some cases
    
    Prefatory note:
    
    I've since learned that this quite similar to
    
https://inbox.sourceware.org/gcc-patches/[email protected]/,
    postdating my original patch series, but predating this version. See
    that thread for additional motivation. That patch updated a few specific
    callsite for various programs; I instead opted to enhance find_a_program
    (which I myself originally factored out of find_a_file in
    5fee8a0a9223d030c66d53c104fb0a431369248f for this purpose) to catch all
    such cases programmatically.
    
    Behavior Change:
    
    Today, GCC will search for:
    
    1. path/$machine/$version/prog
    2. path/$machine/prog
    3. path/prog
    
    This means, we might search for:
    
    1. path/$machine/$version/prog
    2. path/$machine/prog
    3. path/$machine-prog # new
    4. path/prog
    
    But it will not search for:
    
    - path/$machine/$version/$machine-prog
    - path/$machine/$machine-prog
    
    I want this change because when cross compiling, users expect prefixed
    tools, like
    
     - $AS = $machine-as
     - $LD = $machine-ld
    
    etc. and it would be less confusing if GCC would find those same tools
    in a similar way. GCC instead looking for its own (less widely used than
    prefixing) nested-directory way of disambiguating, and then falling back
    looking for *unprefixed* tools (which typically are for the wrong
    platform in cross cases) is quite confusing. In my distro, Nixpkgs, and
    elsewhere, I've seen people draw the wrong conclusions because of this,
    which is that one must use absolute paths hard-coded at build time in
    order to get the right behavior, and dodge the incorrect unprefixed
    tools.
    
    For what its worth, Clang/LLVM also look for prefixed tools in this
    manner, so this isn't the first time it would be done. The difference is
    that they will look for prefixed tools in *all* cases --- i.e. also
    within the machine-specific locations as I outlined above (as things
    this patch does *not* do). I think that was done for mere coding
    convenience, and there is no actual motivation "doubly disambiguating"
    tools with machine directories and machine prefixes. So in the interest
    of sticking strictly to the motivation / being conservative in how much
    new behavior is implemented, I did not implement that part.
    
    gcc/ChangeLog:
    
            * gcc.cc (find_a_program): Implement the new behavior described
            above.
            (driver::set_up_specs): Initilize variable. It would be nice to
            have less spooky-action-at-a-distince using C++ features, but I
            just matched how the corresponding suffix variable worked for
            now for uniformity.
    
    Signed-off-by: John Ericson <[email protected]>

Diff:
---
 gcc/gcc.cc | 54 +++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 39 insertions(+), 15 deletions(-)

diff --git a/gcc/gcc.cc b/gcc/gcc.cc
index c2a5abe916ee..9ef2a21745a4 100644
--- a/gcc/gcc.cc
+++ b/gcc/gcc.cc
@@ -1631,6 +1631,11 @@ static const char *machine_suffix = 0;
 
 static const char *just_machine_suffix = 0;
 
+/* Prefix to attach to *basename* of commands being searched.
+   This is just `MACHINE-'.  */
+
+static const char *just_machine_prefix = 0;
+
 /* Adjusted value of GCC_EXEC_PREFIX envvar.  */
 
 static const char *gcc_exec_prefix;
@@ -3128,34 +3133,52 @@ find_a_program (const char *name)
 
   const char *suffix = HOST_EXECUTABLE_SUFFIX;
   const int name_len = strlen (name);
+  const int prefix_len = strlen (just_machine_prefix);
   const int suffix_len = strlen (suffix);
 
   /* Callback appends the file name to the directory path.  If the
      resulting file exists in the right mode, return the full pathname
      to the file.  */
   return for_each_path (&exec_prefixes, false,
-                       name_len + suffix_len,
-                       [=](char *path, bool) -> char*
+                       prefix_len + name_len + suffix_len,
+                       [=](char *path, bool machine_specific) -> char*
     {
-      size_t len = strlen (path);
-
-      memcpy (path + len, name, name_len);
-      len += name_len;
+      size_t path_len = strlen (path);
 
-      /* Some systems have a suffix for executable files.
-        So try appending that first.  */
-      if (suffix_len)
+      auto search = [=](size_t len) -> char*
        {
-         memcpy (path + len, suffix, suffix_len + 1);
+         memcpy (path + len, name, name_len + 1);
+         len += name_len;
+
+         /* Some systems have a suffix for executable files.
+            So try appending that first.  */
+         if (suffix_len)
+           {
+             memcpy (path + len, suffix, suffix_len + 1);
+             if (access_check (path, X_OK) == 0)
+               return path;
+           }
+
+         path[len] = '\0';
          if (access_check (path, X_OK) == 0)
            return path;
-       }
 
-      path[len] = '\0';
-      if (access_check (path, X_OK) == 0)
-       return path;
+         return NULL;
+       };
 
-      return NULL;
+      /* Additionally search for $target-prog in machine-agnostic dirs,
+        as an additional way to disambiguate targets. Do not do this in
+        machine-specific dirs because so further disambiguation is
+        needed. */
+      if (!machine_specific)
+       {
+         memcpy (path + path_len, just_machine_prefix, prefix_len);
+         auto ret = search(path_len + prefix_len);
+         if (ret)
+           return ret;
+       }
+
+      return search(path_len);
     });
 }
 
@@ -8589,6 +8612,7 @@ driver::set_up_specs () const
   machine_suffix = concat (spec_host_machine, dir_separator_str, spec_version,
                           accel_dir_suffix, dir_separator_str, NULL);
   just_machine_suffix = concat (spec_machine, dir_separator_str, NULL);
+  just_machine_prefix = concat (spec_machine, "-", NULL);
 
   specs_file = find_a_file (&startfile_prefixes, "specs", true);
   /* Read the specs file unless it is a default one.  */

Reply via email to