Opened 6 years ago
#12711 new Bugs
Cross-compiling with GCC on windows will hang due cygwin path resolution
Reported by: | 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 59 59 head = ; 60 60 } 61 61 tail = $(tail:R=$(head:D=)) ; 62 62 63 if $(head) = /63 if $(head) = "/" || [ MATCH "^([a-zA-Z]:/)$" : $(head) ] 64 64 { 65 65 head = ; 66 66 } 67 67 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)