1# -*- cperl -*- 2# Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. 3# 4# This program is free software; you can redistribute it and/or modify 5# it under the terms of the GNU General Public License, version 2.0, 6# as published by the Free Software Foundation. 7# 8# This program is also distributed with certain software (including 9# but not limited to OpenSSL) that is licensed under separate terms, 10# as designated in a particular file or component or in included license 11# documentation. The authors of MySQL hereby grant you an additional 12# permission to link the program and your derivative works with the 13# separately licensed software that they have included with MySQL. 14# 15# This program is distributed in the hope that it will be useful, 16# but WITHOUT ANY WARRANTY; without even the implied warranty of 17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18# GNU General Public License, version 2.0, for more details. 19# 20# You should have received a copy of the GNU General Public License 21# along with this program; if not, write to the Free Software 22# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 23 24 25package My::Find; 26 27# 28# Utility functions to find files in a MySQL source or bindist 29# 30 31use strict; 32use Carp; 33use My::Platform; 34 35use base qw(Exporter); 36our @EXPORT= qw(my_find_bin my_find_dir my_find_file NOT_REQUIRED); 37 38my $bin_extension= ".exe" if IS_WINDOWS; 39 40# Helper function to be used for fourth parameter to find functions 41sub NOT_REQUIRED { return 0; } 42 43# 44# my_find_bin - find an executable with "name_1...name_n" in 45# paths "path_1...path_n" and return the full path 46# 47# Example: 48# my $mysqld_exe= my_find_bin($basedir. 49# ["sql", "bin"], 50# ["mysqld", "mysqld-debug"]); 51# my $mysql_exe= my_find_bin($basedir, 52# ["client", "bin"], 53# "mysql"); 54# 55# 56# To check if something exists, use the required parameter 57# set to 0, the function will return an empty string if the 58# binary is not found 59# my $mysql_exe= my_find_bin($basedir, 60# ["client", "bin"], 61# "mysql", NOT_REQUIRED); 62# 63# NOTE: The function honours MTR_VS_CONFIG environment variable 64# 65# 66sub my_find_bin { 67 my ($base, $paths, $names, $required)= @_; 68 croak "usage: my_find_bin(<base>, <paths>, <names>, [<required>])" 69 unless @_ == 4 or @_ == 3; 70 71 # ------------------------------------------------------- 72 # Find and return the first executable 73 # ------------------------------------------------------- 74 foreach my $path (my_find_paths($base, $paths, $names, $bin_extension)) { 75 return $path if ( -x $path or (IS_WINDOWS and -f $path) ); 76 } 77 if (defined $required and $required == NOT_REQUIRED){ 78 # Return empty string to indicate not found 79 return ""; 80 } 81 find_error($base, $paths, $names); 82} 83 84 85# 86# my_find_file - find a file with "name_1...name_n" in 87# paths "path_1...path_n" and return the full path 88# 89# Example: 90# my $mysqld_exe= my_find_file($basedir. 91# ["sql", "bin"], 92# "filename"); 93# 94# 95# Also supports NOT_REQUIRED flag 96# 97# NOTE: The function honours MTR_VS_CONFIG environment variable 98# 99# 100sub my_find_file { 101 my ($base, $paths, $names, $required)= @_; 102 croak "usage: my_find_file(<base>, <paths>, <names>, [<required>])" 103 unless @_ == 4 or @_ == 3; 104 105 # ------------------------------------------------------- 106 # Find and return the first executable 107 # ------------------------------------------------------- 108 foreach my $path (my_find_paths($base, $paths, $names, $bin_extension)) { 109 return $path if ( -f $path ); 110 } 111 if (defined $required and $required == NOT_REQUIRED){ 112 # Return empty string to indicate not found 113 return ""; 114 } 115 find_error($base, $paths, $names); 116} 117 118 119# 120# my_find_dir - find the first existing directory in one of 121# the given paths 122# 123# Example: 124# my $charset_set= my_find_dir($basedir, 125# ["mysql/share","sql/share", "share"], 126# ["charset"]); 127# or 128# my $charset_set= my_find_dir($basedir, 129# ['client_release', 'client_debug', 130# 'client', 'bin']); 131# 132# NOTE: The function honours MTR_VS_CONFIG environment variable 133# 134# 135sub my_find_dir { 136 my ($base, $paths, $dirs, $optional)= @_; 137 croak "usage: my_find_dir(<base>, <paths>[, <dirs>[, <optional>]])" 138 unless (@_ == 3 or @_ == 2 or @_ == 4); 139 140 # ------------------------------------------------------- 141 # Find and return the first directory 142 # ------------------------------------------------------- 143 foreach my $path (my_find_paths($base, $paths, $dirs)) { 144 return $path if ( -d $path ); 145 } 146 return "" if $optional; 147 find_error($base, $paths, $dirs); 148} 149 150 151sub my_find_paths { 152 my ($base, $paths, $names, $extension)= @_; 153 154 # Convert the arguments into two normal arrays to ease 155 # further mappings 156 my (@names, @paths); 157 push(@names, ref $names eq "ARRAY" ? @$names : $names); 158 push(@paths, ref $paths eq "ARRAY" ? @$paths : $paths); 159 160 #print "base: $base\n"; 161 #print "names: @names\n"; 162 #print "paths: @paths\n"; 163 164 # User can select to look in a special build dir 165 # which is a subdirectory of any of the paths 166 my @extra_dirs; 167 my $build_dir= $::opt_vs_config || $ENV{MTR_VS_CONFIG} || $ENV{MTR_BUILD_DIR}; 168 push(@extra_dirs, $build_dir) if defined $build_dir; 169 170 if (defined $extension){ 171 # Append extension to names, if name does not already have extension 172 map { $_.=$extension unless /\.(.*)+$/ } @names; 173 } 174 175 # ------------------------------------------------------- 176 # CMake generator specific (Visual Studio and Xcode have multimode builds) 177 # ------------------------------------------------------- 178 179 # Add the default extra build dirs unless a specific one has 180 # already been selected 181 push(@extra_dirs, 182 ("Release", 183 "Relwithdebinfo", 184 "Debug")) if @extra_dirs == 0; 185 186 187 #print "extra_build_dir: @extra_dirs\n"; 188 189 # ------------------------------------------------------- 190 # Build cross product of "paths * extra_build_dirs" 191 # ------------------------------------------------------- 192 push(@paths, map { my $path= $_; 193 map { "$path/$_" } @extra_dirs 194 } @paths); 195 #print "paths: @paths\n"; 196 197 # ------------------------------------------------------- 198 # Build cross product of "paths * names" 199 # ------------------------------------------------------- 200 @paths= map { my $path= $_; 201 map { "$path/$_" } @names 202 } @paths; 203 #print "paths: @paths\n"; 204 205 # ------------------------------------------------------- 206 # Prepend base to all paths 207 # ------------------------------------------------------- 208 @paths= map { "$base/$_" } @paths; 209 #print "paths: @paths\n"; 210 211 # ------------------------------------------------------- 212 # Glob all paths to expand wildcards 213 # ------------------------------------------------------- 214 @paths= map { glob("$_") } @paths; 215 #print "paths: @paths\n"; 216 217 # ------------------------------------------------------- 218 # Return the list of paths 219 # ------------------------------------------------------- 220 return @paths; 221} 222 223 224sub commify { 225 return 226 (@_ == 0) ? '' : 227 (@_ == 1) ? $_[0] : 228 (@_ == 2) ? join(" or ", @_) : 229 join(", ", @_[0..($#_-1)], "or $_[-1]"); 230 231} 232 233 234sub fnuttify { 235 return map('\''.$_.'\'', @_); 236} 237 238 239sub find_error { 240 my ($base, $paths, $names)= @_; 241 242 my (@names, @paths); 243 push(@names, ref $names eq "ARRAY" ? @$names : $names); 244 push(@paths, ref $paths eq "ARRAY" ? @$paths : $paths); 245 246 croak "** ERROR: Could not find ", 247 commify(fnuttify(@names)), " in ", 248 commify(fnuttify(my_find_paths($base, $paths, $names))), "\n"; 249} 250 2511; 252