# -*- cperl -*- # Copyright (c) 2007, 2011, Oracle and/or its affiliates. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; version 2 of the License. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA package My::Find; # # Utility functions to find files in a MySQL source or bindist # use strict; use Carp; use My::Platform; use base qw(Exporter); our @EXPORT= qw(my_find_bin my_find_dir my_find_file NOT_REQUIRED); my $bin_extension= ".exe" if IS_WINDOWS; # Helper function to be used for fourth parameter to find functions sub NOT_REQUIRED { return 0; } # # my_find_bin - find an executable with "name_1...name_n" in # paths "path_1...path_n" and return the full path # # Example: # my $mysqld_exe= my_find_bin($basedir. # ["sql", "bin"], # ["mysqld", "mysqld-debug"]); # my $mysql_exe= my_find_bin($basedir, # ["client", "bin"], # "mysql"); # # # To check if something exists, use the required parameter # set to 0, the function will return an empty string if the # binary is not found # my $mysql_exe= my_find_bin($basedir, # ["client", "bin"], # "mysql", NOT_REQUIRED); # # NOTE: The function honours MTR_VS_CONFIG environment variable # # sub my_find_bin { my ($base, $paths, $names, $required)= @_; croak "usage: my_find_bin(, , , [])" unless @_ == 4 or @_ == 3; # ------------------------------------------------------- # Find and return the first executable # ------------------------------------------------------- foreach my $path (my_build_path_list($base, $paths, $names, $bin_extension)) { return $path if ( -x $path or (IS_WINDOWS and -f $path) ); } if (defined $required and $required == NOT_REQUIRED){ # Return empty string to indicate not found return ""; } find_error($base, $paths, $names); } # # my_find_file - find a file with "name_1...name_n" in # paths "path_1...path_n" and return the full path # # Example: # my $mysqld_exe= my_find_file($basedir. # ["sql", "bin"], # "filename"); # # # Also supports NOT_REQUIRED flag # # NOTE: The function honours MTR_VS_CONFIG environment variable # # sub my_find_file { my ($base, $paths, $names, $required)= @_; croak "usage: my_find_file(, , , [])" unless @_ == 4 or @_ == 3; # ------------------------------------------------------- # Find and return the first executable # ------------------------------------------------------- foreach my $path (my_build_path_list($base, $paths, $names, $bin_extension)) { return $path if ( -f $path ); } if (defined $required and $required == NOT_REQUIRED){ # Return empty string to indicate not found return ""; } find_error($base, $paths, $names); } # # my_find_dir - find the existing directories in one of # the given paths. Returns the first found in the scalar context # and all of them in the list context. # # Example: # my $charset_set= my_find_dir($basedir, # ["mysql/share","sql/share", "share"], # ["charset"]); # or # my $charset_set= my_find_dir($basedir, # ['client_release', 'client_debug', # 'client', 'bin']); # # NOTE: The function honours MTR_VS_CONFIG environment variable # # sub my_find_dir { my ($base, $paths, $dirs, $required)= @_; croak "usage: my_find_dir(, [, [, ]])" unless (@_ >= 2 and @_ <= 4); my @all; foreach my $path (my_build_path_list($base, $paths, $dirs)) { next unless -d $path; return $path unless wantarray; push @all, $path; } return @all if @all; return wantarray ? () : "" if defined $required and $required == NOT_REQUIRED; find_error($base, $paths, $dirs); } sub my_build_path_list { my ($base, $paths, $names, $extension)= @_; # Convert the arguments into two normal arrays to ease # further mappings my (@names, @paths); push(@names, ref $names eq "ARRAY" ? @$names : $names); push(@paths, ref $paths eq "ARRAY" ? @$paths : $paths); #print "base: $base\n"; #print "names: @names\n"; #print "paths: @paths\n"; # User can select to look in a special build dir # which is a subdirectory of any of the paths my @extra_dirs; my $build_dir= $::multiconfig || $ENV{MTR_VS_CONFIG} || $ENV{MTR_BUILD_DIR}; push(@extra_dirs, $build_dir) if defined $build_dir; if (defined $extension){ # Append extension to names, if name does not already have extension map { $_.=$extension unless /\.(.*)+$/ } @names; } # ------------------------------------------------------- # CMake generator specific (Visual Studio and Xcode have multimode builds) # ------------------------------------------------------- # Add the default extra build dirs unless a specific one has # already been selected push(@extra_dirs, ("Release", "Relwithdebinfo", "Debug")) if @extra_dirs == 0; #print "extra_build_dir: @extra_dirs\n"; # ------------------------------------------------------- # Build cross product of "paths * extra_build_dirs" # ------------------------------------------------------- push(@paths, map { my $path= $_; map { "$path/$_" } @extra_dirs } @paths); #print "paths: @paths\n"; # ------------------------------------------------------- # Build cross product of "paths * names" # ------------------------------------------------------- @paths= map { my $path= $_; map { "$path/$_" } @names } @paths; #print "paths: @paths\n"; # ------------------------------------------------------- # Prepend base to all paths # ------------------------------------------------------- @paths= map { "$base/$_" } @paths; #print "paths: @paths\n"; # ------------------------------------------------------- # Glob all paths to expand wildcards # ------------------------------------------------------- @paths= map { glob("$_") } @paths; #print "paths: @paths\n"; # ------------------------------------------------------- # Return the list of paths # ------------------------------------------------------- return @paths; } sub commify { return (@_ == 0) ? '' : (@_ == 1) ? $_[0] : (@_ == 2) ? join(" or ", @_) : join(", ", @_[0..($#_-1)], "or $_[-1]"); } sub fnuttify { return map('\''.$_.'\'', @_); } sub find_error { my ($base, $paths, $names)= @_; my (@names, @paths); push(@names, ref $names eq "ARRAY" ? @$names : $names); push(@paths, ref $paths eq "ARRAY" ? @$paths : $paths); croak "** ERROR: Could not find ", commify(fnuttify(@names)), " in ", commify(fnuttify(my_build_path_list($base, $paths, $names))), "\n"; } 1;