4

I am using a makefile to compile a MATLAB/C project. MATLAB can typically be installed into a number of standard locations, depending on its version, e.g. /Applications/MATLAB_2012b.app, /Applications/MATLAB_2013a.app, etc.

What is the simplest way to see if these paths exist, one by one, and take the first one found? There will be at least five values I'd like to test. I found the $(wildcard filename) syntax, but I was wondering if there's anything shorter than writing these out one by one.


Clarifications, as requested. I can piece together something working, but I am sure that this is far from the best/most-concise way of doing this. Is there a better way?

ifeq ($(MATLAB),)
ifneq ($(wildcard /Applications/MATLAB_2011b.app),)
    MATLAB = /Applications/MATLAB_2011b.app
endif
endif

ifeq ($(MATLAB),)
ifneq ($(wildcard /Applications/MATLAB_2012a.app),)
    MATLAB = /Applications/MATLAB_2012a.app
endif
endif

ifeq ($(MATLAB),)
ifneq ($(wildcard /Applications/MATLAB_2012b.app),)
    MATLAB = /Applications/MATLAB_2012b.app
endif
endif

ifeq ($(MATLAB),)
ifneq ($(wildcard /Applications/MATLAB_2013a.app),)
    MATLAB = /Applications/MATLAB_2013a.app
endif
endif
Szabolcs
  • 24,728
  • 9
  • 85
  • 174

2 Answers2

1

You can get the first such directory if it exist

MATLAB_DIR := $(firstword $(wildcard /Applications/MATLAB_*.app))

If it doesn't exist, the variable will be empty

ifeq (,$(MATLAB_DIR))
  $(error Matlab not found)
endif

If your path has spaces, you can use the shell instead. Something like this might work:

MATLAB_DIR := $(shell ls -d /Applications/MATLAB_*.app | tail -n 1)
Szabolcs
  • 24,728
  • 9
  • 85
  • 174
Etienne Laurin
  • 6,731
  • 2
  • 27
  • 31
  • Thanks, this is very useful! I think I'll use `lastword` though. Is is important that you used `:=` here instead of `=`? (I am now looking up the difference) – Szabolcs Mar 19 '13 at 16:29
  • In this case `:=` is better but not required. http://stackoverflow.com/questions/448910/makefile-variable-assignment – Etienne Laurin Mar 19 '13 at 16:33
  • This will fail if the path to MATLAB has spaces in it because `firstword` will break it apart. Do you have any suggestions on how to fix this problem while keeping the generality of the wildcard? Maybe I should ask a separate question for this. – Szabolcs Mar 19 '13 at 16:44
  • If your path has spaces, you can use the shell instead. Something like this might work: `MATLAB_DIR := $(shell ls /Applications/MATLAB_*.app | tail -n 1)` – Etienne Laurin Mar 19 '13 at 16:46
  • Thanks. I added that to your answer if you don't mind. The final problem was escaping that space so I could use the path properly. I did this: `space :=` then `space +=` then `$(subst $(space),\ ,$(MATLAB_DIR))`. Is this the simplest way? – Szabolcs Mar 19 '13 at 17:00
  • If your shell is bash you can use `printf %q` to escape the string: $(shell printf %q `ls /Applications/MATLAB_*.app | tail -n 1`) – Etienne Laurin Mar 19 '13 at 17:46
1

To answer your question regarding spaces in file/directory names, most of the Makefile functions do not handle spaces in filename, and most do not respect even the \ way of escaping spaces.

Few variables like $@, $<, $% and the function wildcard seem to handle the \ escape sequence as a space correctly but most other makefile variables and functions like firstword,etc. cannot handle spaces.

Say if you find a valid directory in wildcard, it would be impossible to distinguish between 2 valid directories in the list versus a single directory with spaces in the path.

If you're using Makefiles, I would suggest to avoid having spaces in the path as much as possible.

But there are always workarounds ;) Assuming you're in a *nix environment with find and sort commands available, this seems to work.

BASE_DIR_NAME := .
MATLAB_DIR := $(subst $(NULL) ,\ ,$(shell find $(BASE_DIR_PATH) -mindepth 1 -maxdepth 1 -name 'MATLAB_*.app' -type d -print | sort | head -1))

default:
    @echo MATLAB_DIR="$(MATLAB_DIR)"
    ls -l $(MATLAB_DIR)

.PHONY: default

This is the directory structure and the output from the Makefile:

$ ls -l
total 16
-rw-r--r-- 1 ash users  236 Mar 20 01:15 Makefile
drwxr-xr-x 2 ash users 4096 Mar 20 01:13 MATLAB_ a.app
drwxr-xr-x 2 ash users 4096 Mar 20 01:13 MATLAB_ b.app
drwxr-xr-x 2 ash users 4096 Mar 20 01:13 MATLAB_ c.app

$ find . -type f
./Makefile
./MATLAB_ a.app/file1
./MATLAB_ b.app/file2

$ make
MATLAB_DIR=./MATLAB_\ a.app
ls -l ./MATLAB_\ a.app
total 0
-rw-r--r-- 1 ash users 0 Mar 20 01:13 file1
Tuxdude
  • 47,485
  • 15
  • 109
  • 110