[PATCH] winegcc: fix cross linking on multiarch platforms

Jacek Caban jacek at codeweavers.com
Tue Nov 20 07:38:41 CST 2018


On 11/20/18 2:24 PM, Andre Heider wrote:
> Hi,
>
> On 20/11/2018 13:53, Jacek Caban wrote:
>> Hi Andre,
>>
>> On 11/20/18 1:10 PM, Andre Heider wrote:
>>> If e.g. the 64bit libdir was set to /foo/lib/x86_64-linux-gnu/bar, 
>>> winegcc
>>> will now look for the 32bit libdir at /foo/lib/i386-linux-gnu/bar.
>>>
>>> Signed-off-by: Andre Heider <a.heider at gmail.com>
>>> ---
>>> Tested on non-standard prefixes like /opt/foo as well as more exotic
>>> variations like Debian's wine-development package, which uses
>>> /usr/lib/x86_64-linux-gnu/wine-development
>>> and
>>> /usr/lib/i386-linux-gnu/wine-development
>>>
>>>   tools/winegcc/winegcc.c | 40 ++++++++++++++++++++++++++++++----------
>>>   1 file changed, 30 insertions(+), 10 deletions(-)
>>>
>>> diff --git a/tools/winegcc/winegcc.c b/tools/winegcc/winegcc.c
>>> index 6b3b4b6aab..d463d7a4bf 100644
>>> --- a/tools/winegcc/winegcc.c
>>> +++ b/tools/winegcc/winegcc.c
>>> @@ -444,6 +444,21 @@ static int check_platform( struct options 
>>> *opts, const char *file )
>>>       return ret;
>>>   }
>>> +static const char *get_multiarch_dir( enum target_cpu cpu )
>>> +{
>>> +   switch(cpu)
>>> +   {
>>> +   case CPU_x86:     return "/i386-linux-gnu";
>>> +   case CPU_x86_64:  return "/x86_64-linux-gnu";
>>> +   case CPU_ARM:     return "/arm-linux-gnueabi";
>>> +   case CPU_ARM64:   return "/aarch64-linux-gnu";
>>> +   case CPU_POWERPC: return "/powerpc-linux-gnu";
>>> +   default:
>>> +       assert(0);
>>> +       return NULL;
>>> +   }
>>> +}
>>> +
>>>   static char *get_lib_dir( struct options *opts )
>>>   {
>>>       static const char *stdlibpath[] = { LIBDIR, "/usr/lib", 
>>> "/usr/local/lib", "/lib" };
>>> @@ -471,19 +486,24 @@ static char *get_lib_dir( struct options *opts )
>>>           strcpy( p, bit_suffix );
>>>           strcat( p, libwine );
>>>           if (check_platform( opts, buffer )) goto found;
>>> -        switch(opts->target_cpu)
>>> -        {
>>> -        case CPU_x86:     strcpy( p, "/i386-linux-gnu" ); break;
>>> -        case CPU_x86_64:  strcpy( p, "/x86_64-linux-gnu" ); break;
>>> -        case CPU_ARM:     strcpy( p, "/arm-linux-gnueabi" ); break;
>>> -        case CPU_ARM64:   strcpy( p, "/aarch64-linux-gnu" ); break;
>>> -        case CPU_POWERPC: strcpy( p, "/powerpc-linux-gnu" ); break;
>>> -        default:
>>> -            assert(0);
>>> -        }
>>> +        strcpy( p, get_multiarch_dir( opts->target_cpu ));
>>>           strcat( p, libwine );
>>>           if (check_platform( opts, buffer )) goto found;
>>> +        /* try s/$build_cpu/$target_cpu/ on multiarch */
>>> +        if (build_cpu != opts->target_cpu && (p = strstr( 
>>> stdlibpath[i], get_multiarch_dir( build_cpu ) )))
>>> +        {
>>> +            char *suffix = p + strlen( get_multiarch_dir( build_cpu 
>>> ) );
>>> +            strcpy( buffer, stdlibpath[i] );
>>> +            p = buffer + (p - stdlibpath[i]);
>>> +            strcpy( p, get_multiarch_dir( opts->target_cpu ) );
>>> +            p += strlen( get_multiarch_dir( opts->target_cpu ) );
>>> +            strcpy( p, suffix );
>>> +            while (p > buffer && p[-1] == '/') p--;
>>> +            strcat( p, libwine );
>>> +            if (check_platform( opts, buffer )) goto found;
>>> +        }
>>
>>
>> It seems to me that extending the existing loop that tries to replace 
>> lib* path components would be better (it's the loop just a few lines 
>> bellow the code that you modify).
>
> Sure, I can do that, but doesn't that go against the idea of multiarch?
>
> If your distro uses /lib/$triple it shouldn't use /lib[32|64]/$triple 
> - at least I've never seen such a setup.
>
> Or would that solve the issue on a setup I didn't yet encounter? 


We would try to change that in this case only if $triple heuristic 
doesn't work. Instead of using strstr, there is a loop that tries to 
replace one component at the time. So if you build with -m32 on 64-bit 
host on a distro that uses an exotic /usr/lib/$triple/lib64/subdir 
libdir, we'd do following in the loop:

- skip subdir

- try to replace lib64 with lib32 or lib, if that fails

- try to replace $triple with 32-bit triple, if that fails

- try to replace lib with lib32, if that fails

- skip usr

- if we got here, we didn't find valid 32-bit libdir


Does that make sense?


Jacek




More information about the wine-devel mailing list