views:

1039

answers:

6

Is there a way to determine all the dependencies of an .m file and any of the dependencies of the files it calls using a command in a script (command-line)?

There was a question like this before and it was really good because it suggested using the depfun function. BUT the issue with this was that it is outputting the MATLAB related files that it depends on as well.

EXAMPLE: testing.m

disp('TESTING!!');

The output of depfun('testing')

'C:\testing.m'
'C:\MATLAB\R2008a\toolbox\matlab\datatypes\@opaque\char.m'
'C:\MATLAB\R2008a\toolbox\matlab\datatypes\@opaque\double.m'
'C:\MATLAB\R2008a\toolbox\matlab\datatypes\@opaque\toChar.m'
'C:\MATLAB\R2008a\toolbox\matlab\elfun\log10.m'
'C:\MATLAB\R2008a\toolbox\matlab\elmat\ans.m'

etc.

The list is a little bit longer.

The point here is that I was hoping there would be some similar function or a flag that would remove these unwanted dependencies.

+1  A: 

Try DepSubFun from TMW FileExchange.

+1  A: 

Here are a couple of links I found helpful when I wrote up a simple function to create a table of contents for an m-file:

  • A thread discussing the undocumented function MLINTMEX
  • FDEP by Urs Schwarz on the MathWorks File Exchange
  • FARG by Urs Schwarz on the MathWorks File Exchange

EDIT: Since this problem piqued my curiosity, I started trying out a few ways I might approach it. Finding the dependencies on non-toolbox .m and .mex files was relatively trivial (I did this in MATLAB version 7.1.0.246):

fcnName = 'myfile.m';
fcnList = depfun(fcnName,'-quiet');
listIndex = strmatch('C:\Program Files\MATLAB71\toolbox',fcnList);
fcnList = fcnList(setdiff(1:numel(fcnList),listIndex));

Here, I just used DEPFUN to get the dependencies, then I removed any files that began with 'C:\Program Files\MATLAB71\toolbox', where the MATLAB toolboxes are located on my machine. Note that this assumes you aren't placing any of your own code in these MATLAB directories (which you shouldn't do anyway).

To get dependencies on .mat and .txt files, I took another approach. For each of the files you get from the above code, you could load the text of the file into MATLAB and parse it with a regular expression to find strings that end in a '.mat' or '.txt':

fid = fopen(fcnName,'rt');
fcnText = fscanf(fid,'%c');
fclose(fid);
expr = '[^\'']\''([^\''\n\r]+(?:\w\.(?:mat|txt)){1})\''[^\'']';
dataFiles = regexp(fcnText,expr,'tokens');
dataFiles = unique([dataFiles{:}]).';

There are a few limitations to the regular expression I used:

  • If you have a string like 'help.txt' that appears in a comment (such as the help comment block of a function), it will still be detected by the regular expression. I tried to get around this with a lookaround operator, but that took too long to run.

  • If you build a string from variables (like "fileString = [someString '.mat']"), it will not be detected by the regular expression.

  • The returned strings of file names will be relative path strings. In other words, if you have the strings 'help.txt' or 'C:\temp\junk.mat' in the function, the regular expression matching will return 'help.txt' or 'C:\temp\junk.mat', exactly as they appear in the function. To find the full path, you can use the WHICH function on each data file (assuming the files reside somewhere on the MATLAB path).

Hope you find these useful! =)

gnovice
A: 

Another way is just to exclude folders you don't need: localdep = depfunresult(cellfun(@isempty,regexp(a,'toolbox'))); You can use any regexp pattern there.

A: 

Thank you for the responses so far.

I do not think that these are quite what I am looking to accomplish.

I was hoping there was already something that would determine local functions called within the main m-file, add them to the list, and proceed to look in each one until there are none left. It doesn't seem that any of these solutions do this

I have come up with a scheme that I will try to implement. It may be a bit brute force and the design might change as I work on it, but here is the concept.

There are quite a few assumptions made in this initial design but since it is mostly for me and a few others I don't think it will be a big issue for my general solution.

Files types to look for: .m .mat .mex* .txt (will be updated as needed)

Determine matlabpath and weed out toolbox paths (this is where it is an assumption your working directories are not called toolbox or that you don't have any special m-files you added to the other toolboxes)

hopefully leaving you only with directories you use and can call functions from. (also assumes you don't hardcode some type of [run 'C:\random\myscript.m']

brute force part: look for the file types you are interested in and make a list of the ones in your working directory (pwd) and the remaining matlab paths

remove filenames that match one in the working directory.

iterate through searching the main m-file for each filename, if found add it to the array of dependent files. remove dependent files from the original list. search dependent files list with the "new" original list, repeat until no files left or no matches at all.

So far this is just the concept I have, I will also be searching a little more as well.

Wanting to look for dependencies on .mat and .txt files makes this kinda difficult. Most of the above options should be able to handle .m (and I think .mex) files. For example, MLINTMEX can be called, the results trimmed to non-toolbox m-files, then recursively call MLINTMEX on these, etc.
gnovice
A: 

I got this script finally running today, it is a windows matlab based one as it makes a '!findstr "something" file.txt' call. (I would have preferred a grep but didn't know matlab equivalent.

I am going to ask my boss if I am allowed to post it on the matlab file exchange to share with others so hopefully I will update this soon with the link.

gnovice: I don't have enough rep to comment on gnovice's comment of my description I wrote prior to writing the code.

But basically to determine which what it does is takes the filename of all files (broken into category of filetype), strips off the fullpathname and the extension, uses the above mentioned !findstr command to search it in the .m file that you are building the dependency for and outputs that to a temp.txt file (this is because I couldn't figure out a way to get a 1 or 0 or isempty return on the output of the command)

here is a breakdown of what I personally search for to determine if each file is used:

.m : 'filename ' or 'filename(' % covers the 'filename (' case .mex* : same as above .mat : was doing same as above but am going to change to some sort of load and the 'filename.mat' working on this probably tomorrow .txt : simply searches for 'filename.txt'

With this method you may end up with a few extra text files or .m files but the key here is you should at least have all the files you need.

It also recursively calls itself on all the dependent files so that their dependencies are taken into account too.

-TaRDy

This is somewhat off topic, but I'm curious why it appears as though you have 3 different logins? If they were all added up you would have enough rep to comment by now! =)
gnovice
A: 
shabbychef

related questions