Opened 6 years ago

#12711 new Bugs

Cross-compiling with GCC on windows will hang due cygwin path resolution

Reported by: kirill.erofeev@… Owned by: Vladimir Prus
Milestone: To Be Determined Component: build
Version: Boost 1.61.0 Severity: Regression
Keywords: windows cross-compiling Cc:

Description

Recently, since release 1.61. There were changes in Boost.Build which breaks cross-compilation on windows platform with GCC toolchain.

How to reproduce

We use following user-config.jam

   using gcc : 4.9 : arm-linux-androideabi-g++.exe ;

or we tried

   using gcc : 4.9 : arm-linux-androideabi-g++.exe : <flavor>android ;

The toolchain is in %PATH%

Trying to run bjam command:

   b2 --clean-all  -d+5 variant=release

Will leads to endless loops in cygwin path resolving:

(builtin):>>>>|>>>>|>>>>|>>>>|>>>> cygwin.software-registry-value Cygnus Solutions\Cygwin\mounts v2\c:/ : native
(builtin):>>>>|>>>>|>>>>|>>>>|>>>>|> W32_GETREG HKEY_CURRENT_USER\SOFTWARE\Cygnus Solutions\Cygwin\mounts v2\c:/ : native
(builtin):>>>>|>>>>|>>>>|>>>>|>>>>|> W32_GETREG HKEY_CURRENT_USER\SOFTWARE\Wow6432node\Cygnus Solutions\Cygwin\mounts v2\c:/ : native
(builtin):>>>>|>>>>|>>>>|>>>>|>>>>|> W32_GETREG HKEY_LOCAL_MACHINE\SOFTWARE\Cygnus Solutions\Cygwin\mounts v2\c:/ : native
(builtin):>>>>|>>>>|>>>>|>>>>|>>>>|> W32_GETREG HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432node\Cygnus Solutions\Cygwin\mounts v2\c:/ : native

Under the hood

There is new rule (since Boost 1.61)

# Uses -print-prog-name to get the name of the tool.
# Converts the path to native form if using cygwin.
rule .get-prog-name ( command-string : tool : flavor ? )
{
    local prog-name = [ NORMALIZE_PATH [ MATCH "(.*)[\n]+" :
        [ SHELL "$(command-string) -print-prog-name=$(tool)" ] ] ] ;
    if $(flavor) != mingw && [ os.name ] = NT
    {
        prog-name = [ cygwin.cygwin-to-windows-path $(prog-name) ] ;
    }
    return $(prog-name) ;
}

flavor will be empty or android. And the cygwin path resolution will be triggered. Though no Cygwin is used or installed. I think this is not a good idea to trigger cygwin specific code but checking another falavor. Probably it is better to define cygwin flavor and check if $(flavor) = cygwin && [ os.name ] = NT

But why the cygwin.cygwin-to-windows-path goes to dead loop?

rule cygwin-to-windows-path ( path )
{
    path = $(path:R="") ; # strip any trailing slash

    local drive-letter = [ SUBST $(path) $(.cygwin-drive-letter-re) $1:/$2 ] ;
    if $(drive-letter)
    {
        path = $(drive-letter) ;
    }
    else if $(path:R=/x) = $(path) # already rooted?
    {
        # Look for a cygwin mount that includes each head sequence in $(path).
        local head = $(path) ;
        local tail = "" ;

        while $(head)
        {
            local root = [ software-registry-value
                "Cygnus Solutions\\Cygwin\\mounts v2\\"$(head) : native ] ;

            if $(root)
            {
                path = $(tail:R=$(root)) ;
                head = ;
            }
            tail = $(tail:R=$(head:D=)) ;

            if $(head) = /
            {
                head = ;
            }
            else
            {
                head = $(head:D) ;
            }
        }
    }
    return [ regex.replace $(path:R="") / \\ ] ;
}

path is already rooted since it starts with c:/ and $(path:R=/x) = $(path) will be true. root will be empty since not cygwin is involved. head variable will finally ends equal to c:/ but never / or empty.

Possible solutions

So as a quick solution I create a patch for cygwin.jam

  • boost_1_63_0/tools/build/src/tools/cygwin.jam

    diff -r -u4 a/boost_1_63_0/tools/build/src/tools/cygwin.jam b/boost_1_63_0/tools/build/src/tools/cygwin.jam
    a b  
    5959                head = ;
    6060            }
    6161            tail = $(tail:R=$(head:D=)) ;
    6262
    63             if $(head) = /
     63            if $(head) = "/" || [ MATCH  "^([a-zA-Z]:/)$" : $(head) ]
    6464            {
    6565                head = ;
    6666            }
    6767            else

This will change cygwin-to-windows-path behavior to accepts full windows path (but not UNC path unfortunately).

Another, I think better, approach is to introduce cygwin flavor and do cygwin specific things only for this flavor. But deeper knowledge is required for this (I think there is a reason for introducing mingw flavor but not cygwin, and it is necessary to track all dependency)

Change History (0)

Note: See TracTickets for help on using tickets.