It is actually executing the command, changing the directory to some_directory
, however, this is performed in a sub-process shell, and affects neither make nor the shell you're working from.
If you're looking to perform more tasks within some_directory
, you need to add a semi-colon and append the other commands as well. Note that you cannot use newlines as they are interpreted by make as the end of the rule, so any newlines you use for clarity needs to be escaped by a backslash.
For example:
all:
cd some_dir; echo "I'm in some_dir"; \
gcc -Wall -o myTest myTest.c
Note also that the semicolon is necessary between every command even though you add a backslash and a newline. This is due to the fact that the entire string is parsed as a single line by the shell. As noted in the comments, you should use '&&' to join commands, which mean they only get executed if the preceding command was successful.
all:
cd some_dir && echo "I'm in some_dir" && \
gcc -Wall -o myTest myTest.c
This is especially crucial when doing destructive work, such as clean-up, as you'll otherwise destroy the wrong stuff, should the cd
fail for whatever reason.
A common usage though is to call make in the sub directory, which you might want to look into. There's a command line option for this so you don't have to call cd
yourself, so your rule would look like this
all:
$(MAKE) -C some_dir all
which will change into some_dir
and execute the Makefile
in there with the target "all". As a best practice, use $(MAKE)
instead of calling make
directly, as it'll take care to call the right make instance (if you, for example, use a special make version for your build environment), as well as provide slightly different behavior when running using certain switches, such as -t
.
For the record, make always echos the command it executes (unless explicitly suppressed), even if it has no output, which is what you're seeing.
In my opinion, directories should not be considered targets of your makefile, either in technical or in design sense. You should create files and if a file creation needs a new directory then quietly create the directory within the rule for the relevant file.
If you're targeting a usual or "patterned" file, just use make
's internal variable $(@D)
, that means "the directory the current target resides in" (cmp. with $@
for the target). For example,
$(OUT_O_DIR)/%.o: %.cpp
@mkdir -p $(@D)
@$(CC) -c $< -o $@
title: $(OBJS)
Then, you're effectively doing the same: create directories for all $(OBJS)
, but you'll do it in a less complicated way.
The same policy (files are targets, directories never are) is used in various applications. For example, git
revision control system doesn't store directories.
Note: If you're going to use it, it might be useful to introduce a convenience variable and utilize make
's expansion rules.
dir_guard=@mkdir -p $(@D)
$(OUT_O_DIR)/%.o: %.cpp
$(dir_guard)
@$(CC) -c $< -o $@
$(OUT_O_DIR_DEBUG)/%.o: %.cpp
$(dir_guard)
@$(CC) -g -c $< -o $@
title: $(OBJS)
Best Answer
The shell function.
You can use
shell
function:current_dir = $(shell pwd)
. Orshell
in combination withnotdir
, if you need not absolute path:current_dir = $(notdir $(shell pwd))
.Update.
Given solution only works when you are running
make
from the Makefile's current directory.As @Flimm noted:
Code below will work for Makefiles invoked from any directory: