2

I was wondering is anyone knows what the stand alone @ symbol and the 'dir' command in my makefile does here (second & third line) :

$(BUILD)/%.o: %.cpp
    @mkdir -p $(dir $@) 
    $(CC) $(CFLAGS) -c $? -o $@

I understand what $@ is however @ by itself is not listed in the GNU handbook (https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html) and all my searches talk about the $@.

Furthermore, in the third line, I understand that mkdir -p creates nested directories but I was hoping if someone can please elaborate on $(dir $@) specifically the "dir" part.

Thank you for your time.

Amr
  • 411
  • 6
  • 21
  • You should remove the c++, symbols and symbol tag as this question is entirely `GNU make` centric. – typetetris Aug 16 '17 at 13:41
  • Possible duplicate of [What do @, - and + do as prefixes to recipe lines in Make?](https://stackoverflow.com/questions/3477292/what-do-and-do-as-prefixes-to-recipe-lines-in-make) – Renaud Pacalet Aug 16 '17 at 14:45
  • If it wasn't for the part with the `dir` keyword, I would second that duplicate flag. – typetetris Aug 16 '17 at 17:53

2 Answers2

5

If @ starts a recipe line, the command itself isn't echoed.

$(dir $@) expands to the directory part of the target $@. In this case that is $(BUILD)/rest/path/to/ if the target is $(BUILD)/rest/path/to/target.o.

From GNU make manual, 5.2 Recipe Echoing:

5.2 Recipe Echoing

Normally 'make' prints each line of the recipe before it is executed. We call this "echoing" because it gives the appearance that you are typing the lines yourself.

When a line starts with '@', the echoing of that line is suppressed. The '@' is discarded before the line is passed to the shell. Typically you would use this for a command whose only effect is to print something, such as an 'echo' command to indicate progress through the makefile:

 @echo About to make distribution files

and from the same, 8.3 Functions for File Names

8.3 Functions for File Names

Several of the built-in expansion functions relate specifically to taking apart file names or lists of file names.

Each of the following functions performs a specific transformation on a file name. The argument of the function is regarded as a series of file names, separated by whitespace. (Leading and trailing whitespace is ignored.) Each file name in the series is transformed in the same way and the results are concatenated with single spaces between them.

'$(dir NAMES...)' Extracts the directory-part of each file name in NAMES. The directory-part of the file name is everything up through (and including) the last slash in it. If the file name contains no slash, the directory part is the string './'. For example,

      $(dir src/foo.c hacks)

produces the result 'src/ ./'.

typetetris
  • 4,586
  • 16
  • 31
  • Just for some new readers, the construct `$(dir $@)` can be replaced with `$(@D)`. (Same goes for the file name in the target as `$(@F)`.) – BUFU Aug 28 '20 at 14:16
2

It is a silencer. When @ is the first character of a command, the said command is executed without being printed in stdout beforehand.

See Makefile documentation for additional info:

Normally make prints each line of the recipe before it is executed. We call this echoing because it gives the appearance that you are typing the lines yourself.

When a line starts with ‘@’, the echoing of that line is suppressed. The ‘@’ is discarded before the line is passed to the shell. Typically you would use this for a command whose only effect is to print something, such as an echo command to indicate progress through the makefile:

@echo About to make distribution files

When make is given the flag ‘-n’ or ‘--just-print’ it only echoes most recipes, without executing them. See Summary of Options. In this case even the recipe lines starting with ‘@’ are printed. This flag is useful for finding out which recipes make thinks are necessary without actually doing them.

The ‘-s’ or ‘--silent’ flag to make prevents all echoing, as if all recipes started with ‘@’. A rule in the makefile for the special target .SILENT without prerequisites has the same effect (see Special Built-in Target Names). .SILENT is essentially obsolete since ‘@’ is more flexible.

Community
  • 1
  • 1
YSC
  • 38,212
  • 9
  • 96
  • 149