Dylibs find.m

From Octave
Jump to: navigation, search

An m-file function used in support of creating a MacOS X App bundle.

## Copyright (C) 2012 Ben Abbott
## 
## 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; either version 3 of the License, or
## (at your option) any later version.
## 
## 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 Octave; see the file COPYING.  If not, see
## <http://www.gnu.org/licenses/>.

## -*- texinfo -*-
## @deftypefn {Function File} dylibs = dylibs_find (@var{directory})
##
## Recursively finds all dylibs in @var{directory}, and returns a structure
## with fields @code{name}, @code{location}, and @code{dependents}.  The
## @var{directory} defaults to the present working directory.
##
## @table
## @item @code{name}
## Is the name of a dynamic library.
## @item @code{location}
## Is the path to the named dynamic library.
## @item @code{dependents}
## Is a cellstr array listing the dynamic libraries the named library
## depends upon.
## @item @code{islink}
## Logical scalar indicating whether the file is a symbolic link to a
## dynamically loadable library.
## @end table
##
## @seealso {dylibs_get_deps, dylibs_fix}
## @end deftypefn

## Author: Ben Abbott <bpabbott@mac.com>
## Created: 2012-06-27

function dylibs = dylibs_find (directory = ".")

  persistent root_dir={"/opt/local/lib/", "@executable_path"}

  remove_symbolic_links = false;
  
  cwd = pwd ();

  unwind_protect
    cd (directory);
    f = dir ();
    ## Remove ".", "..", and ".hidden_files"
    f = f(! strncmp ({f.name}, ".", 1));
    ## Separate directories
    d = [f.isdir];
    dirs = {f(d).name};
    dirs = dirs (! strcmpi (dirs, "share"));
    f(d) = [];
    str = sprintf ("Working in directory -> ""%s"" ...", directory);
    nstr = numel (str);
    printf ("%s", str);
    ## Find dylibs
    if (numel (f))
      names = {f.name};
      [status, output] = system ("find . -maxdepth 1 -type l -print");
      symlinks = strtrim (strrep (strsplit (output, char (10)), "./", ""));
      symlinks(cellfun (@isempty, symlinks)) = [];
      ## Remove symbolic links
      if (remove_symbolic_links)
        names = setdiff (names, symlinks);
      endif
      names = names(dylibs_isdylib(names));
      if (numel (names))
        deps = dylibs_get_deps (names, {"@", root_dir{:}});
        if (numel (names) == 1)
          deps = {deps};
        endif
        islink = ismember (names, symlinks);
        dylibs = cell2struct ([names; repmat({pwd()}, size (names)); deps; mat2cell(islink,1,ones(size(islink)))],
                              {"name", "location", "depdendents", "islink"});
        str = sprintf (" %d dynamic libraries.", numel (dylibs));
      else
        dylibs = struct ("name", "", "location", "", ...
                         "dependents", {}, "islink", logical([]));
        str =  " NO dynamic libraries.";
      endif
    else
      dylibs = struct ("name", "", "location", ...
                       "", "dependents", {}, "islink", logical([]));
      str =  " NO dynamic libraries.";
    endif
    printf ("%s %s\n", repmat (".", [1, (80 - nstr - numel (str))]), str);
    for n = 1:numel(dirs)
      new_dylibs = dylibs_find (dirs{n});
      if (numel (new_dylibs))
        if (numel (dylibs))
          dylibs = [dylibs; new_dylibs];
        else
          dylibs = new_dylibs;
        endif
      endif
    endfor

  unwind_protect_cleanup
    cd (cwd);
  end_unwind_protect

endfunction