Vinod
Vinod

Reputation: 1073

A question about specific GNU Makefile entry

I am trying to make sense of the following lines in a GNU Makefile (modified to obscure proprietary stuff):

KERNEL_SEARCH := /lib/modules/$(shell uname -r)/build  \
     /usr/src/linux-headers-$(shell uname -r) \
     /usr/src/linux
     
      temp_dir = $(shell [ -e $(dir)/include/linux ] && echo $(dir))
      KERNEL_SEARCH := $(foreach dir, $(K_SEARCH), $(temp_dir))

My understanding is that in the first line, KERNEL_SEARCH is successively assigned each of the paths separated by \. However, I am not sure what do the subsequent lines do? Can someone provide a quick explanation?

TIA

Vinod

Upvotes: 0

Views: 43

Answers (1)

Beta
Beta

Reputation: 99094

Suppose the Make variable dir has been given a value, say /usr/src/linux. Now consider:

temp_dir = $(shell [ -e $(dir)/include/linux ] && echo $(dir))

This is a Make statement that constructs the line

[ -e /usr/src/linux/include/linux ] && echo /usr/src/linux

then passes it to the shell, then stores the result in the variable temp_dir.

The fist part, in the brackets, is a shell conditional, which tests the existence of that file. The second part is a simple echo statement which prints something to the screen. The && in the middle is a boolean AND; if the first part evaluates as False, then evaluation stops, but if the first part evaluates as True, then the shell proceeds to the second part. So if the dir contains include/linux, then the shell will print the dir, otherwise it will do nothing.

So if the directory named by dir contains include/linux, then temp_dir will contain the value of dir, otherwise temp_dir will wind up empty.

Now consider:

KERNEL_SEARCH := ...

The variable KERNEL_SEARCH contains a list. It is not successively assigned various things, it's just a list, a long string with some spaces in it. (I'd show you what it looks like, but that depends on the shell, and it would be kind of cryptic.) Those backslashes (\) are there just to allow wrapping of the long line, to make the makefile easier to read.

Now the last line:

KERNEL_SEARCH := $(foreach dir, $(K_SEARCH), $(temp_dir))

I strongly suspect that you got the variable names swapped when you were obfuscating the code. I'll swap them back:

K_SEARCH := $(foreach dir, $(KERNEL_SEARCH), $(temp_dir))

The foreach directive takes three arguments. Roughly, the first is a variable name, the second is a list, and the third is something to be expanded. Make iterates over the list, and for each word in the list it assigns that word to the variable, and expands the third argument. In this case, for each directory in $(KERNEL_SEARCH), Make expands $(temp_dir) and gets either the name of the directory, or nothing.

So the result is a list of those directories (from the original list) which contain include/linux.

Upvotes: 1

Related Questions