1 # Copyright (C) 2010 The Android Open Source Project 2 # 3 # Licensed under the Apache License, Version 2.0 (the "License"); 4 # you may not use this file except in compliance with the License. 5 # You may obtain a copy of the License at 6 # 7 # http://www.apache.org/licenses/LICENSE-2.0 8 # 9 # Unless required by applicable law or agreed to in writing, software 10 # distributed under the License is distributed on an "AS IS" BASIS, 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 # See the License for the specific language governing permissions and 13 # limitations under the License. 14 # 15 16 # This script is used to generate a Makefile fragment that will be evaluated 17 # at runtime by the NDK build system during its initialization pass. 18 # 19 # The purpose of this generated fragment is to define a function, named 20 # 'cygwin-to-host-path' that will transform a Cygwin-specific path into the 21 # corresponding Windows specific one, i.e. calling 22 # 23 # $(call cygwin-to-host-path,/cygdrive/c/Stuff/) --> c:/Stuff 24 # 25 # A naive implementation of this function would be the following: 26 # 27 # cygwin-to-host-path = $(shell cygpath -m $1) 28 # 29 # Unfortunately, calling 'cygpath -m' from GNU Make is horridly slow and people 30 # have complained that this was adding several minutes to their builds, even in 31 # the case where there is nothing to do. 32 # 33 # The script expects its input to be the output of the Cygwin "mount" command 34 # as in: 35 # 36 # C:/cygwin/bin on /usr/bin type ntfs (binary,auto) 37 # C:/cygwin/lib on /usr/lib type ntfs (binary,auto) 38 # C:/cygwin on / type ntfs (binary,auto) 39 # C: on /cygdrive/c type ntfs (binary,posix=0,user,noumount,auto) 40 # D: on /cygdrive/d type udf (binary,posix=0,user,noumount,auto) 41 # 42 # The script's output will be passed to the GNU Make 'eval' function 43 # and will look like: 44 # 45 # $(patsubst /%,C:/cygwin/, 46 # $(patsubst /usr/bin/%,C:/cygwin/bin/, 47 # $(patsubst /usr/lib/%,C:/cygwin/lib/, 48 # $(patsubst /cygdrive/C/%,C:/, 49 # $(patsubst /cygdrive/D/%,D:/, 50 # $(patsubst /cygdrive/c/%,C:/, 51 # $(patsubst /cygdrive/d/%,D:/,$1))))) 52 # 53 BEGIN { 54 # setup our count 55 count = 0 56 } 57 58 $2 == "on" { 59 # record a new (host-path,cygwin-path) pair 60 count ++ 61 host[count] = $1 62 cygwin[count] = $3 63 } 64 65 END { 66 # Drive letters are special cases because we must match both 67 # the upper and lower case versions to the same drive, i.e. 68 # if "mount" lists that /cygdrive/c maps to C:, we need to 69 # map both /cygdrive/c and /cygdrive/C to C: in our final rules. 70 # 71 count1 = count 72 for (nn = 1; nn <= count1; nn++) { 73 if (!match(host[nn],"^[A-Za-z]:$")) { 74 # not a driver letter mapping, skip this pair 75 continue 76 } 77 letter = substr(host[nn],1,1) 78 lo = tolower(letter) 79 up = toupper(letter) 80 81 # If the cygwin path ends in /<lo>, then substitute it with /<up> 82 # to create a new pair. 83 if (match(cygwin[nn],"/"lo"$")) { 84 count++ 85 host[count] = host[nn] 86 cygwin[count] = substr(cygwin[nn],1,length(cygwin[nn])-1) up 87 continue 88 } 89 90 # If the cygwin path ends in /<up>, then substitute it with /<lo> 91 # to create a new pair. 92 if (match(cygwin[nn],"/"up"$")) { 93 count++ 94 host[count] = host[nn] 95 cygwin[count] = substr(cygwin[nn],1,length(cygwin[nn])-1) lo 96 continue 97 } 98 } 99 100 # We have recorded all (host,cygwin) path pairs, 101 # now try to sort them so that the ones with the longest cygwin path 102 # appear first 103 for (ii = 2; ii <= count; ii++) { 104 for (jj = ii-1; jj > 0; jj--) { 105 if (length(cygwin[jj]) > length(cygwin[jj+1])) { 106 break; 107 } 108 if (length(cygwin[jj]) == length(cygwin[jj+1]) && 109 cygwin[jj] > cygwin[jj+1]) { 110 break 111 } 112 tmp = cygwin[jj] 113 cygwin[jj] = cygwin[jj+1] 114 cygwin[jj+1] = tmp 115 tmp = host[jj] 116 host[jj] = host[jj+1] 117 host[jj+1] = tmp 118 } 119 } 120 121 # build/core/init.mk defines VERBOSE to 1 when it needs to dump the 122 # list of substitutions in a human-friendly format, generally when 123 # NDK_LOG is defined in the environment 124 # 125 # Otherwise, just generate the corresponding Make function definition 126 # 127 if (VERBOSE == 1) { 128 for (nn = 1; nn <= count; nn++) { 129 printf( "$(info %s => %s)", cygwin[nn], host[nn]); 130 } 131 } else { 132 RESULT = "$1" 133 for (nn = 1; nn <= count; nn++) { 134 add_drive_rule(host[nn], cygwin[nn]) 135 } 136 print RESULT 137 } 138 } 139 140 function add_drive_rule (hostpath,cygpath) 141 { 142 if (cygpath == "/") { 143 # Special case for / 144 RESULT = "$(patsubst /%," hostpath "/%,\n" RESULT ")" 145 return 146 } 147 # default rule otherwise 148 RESULT = "$(patsubst " cygpath "/%," hostpath "/%,\n" RESULT ")" 149 } 150