The kernel Makefile init the variables like KBUILD_OUTPUT outside any target's make process. The code is like this:
ifeq ("$(origin O)", "command line")
KBUILD_OUTPUT := $(O)
endif
But when I try to output KBUILD_OUTPUT in the target's make process, for example, the target help, I find it is not defined. The code I modified is like this:
help:
#echo 'KBUILD_OUTPUT: ${KBUILD_OUTPUT}'
When I execute make O=../build help, the KBUILD_OUTPUT variable is empty. I want to know when will it init?
Thanks a lot.
Update
However, when I just write a Makefile with this:
ifeq ("$(origin O)", "command line")
KBUILD_OUTPUT := $(O)
endif
help:
#echo 'KBUILD_OUTPUT: ${KBUILD_OUTPUT}'
Then I run make O=../build help, I will see KBUILD_OUTPUT: ../build.
Is there anything special in kernel's Makefile?
The kernel make process is a bit more complicated than most makes. The main kernel makefile will recursively call itself (that is, it calls make specifying itself as the makefile, but giving different target sets). Because of this, large portions of the main kernel Makefile has conditionals around them, some parts meant to be executed when the Make is first invoked, and others which are meant to be executed when the makefile is invoked as a child of itself. The code you are quoting, is actually:
ifeq ($(KBUILD_SRC),)
# OK, Make called in directory where kernel src resides
# Do we want to locate output files in a separate directory?
ifeq ("$(origin O)", "command line")
KBUILD_OUTPUT := $(O)
endif
When you create the help target, the Makefile will run only that rule, and thus not recursively call itself, and therefore, KBUILD_SRC will not be set, and thus KBUILD_OUTPUT will remain unset.
John
Related
I have a makefile in a directory of mine which builds scripts with certain environment variables set. What if I want to create another makefile in the same directory with different environment variables set? How should I name the two make files? Does makefile.1 and makefile.2 work? How do I call them?
You can give sensible names to the files like makefile.win and makefile.nix and use them:
make -f makefile.win
make -f makefile.nix
or have a Makefile that contains:
win:
make -f makefile.win
nix:
make -f makefile.nix
and use make win or make nix
You can name makefile whatever you want. I usually name it like somename.mk. To use it later you need to tell make what makefile you want. Use -f option for this:
make -f somename.mk
Actually you can have two set of environment variables in the same make file. for example
COMPILER = gcc
CCFLAGS1 = -g
CCFLAGS2 = -Wall
a: main.c
${COMPILER} ${CCFLAGS1} main.c
b: test.c
${COMPILER} ${CCFLAGS2} test.c
then you can just say make a or make b. Depending on what you want.
Also it is possible with -f flag to call which makefile you want to call.
You can do something like this rather than using multiple makefiles for the same purpose. You can pass the environment or set a flag to the same makefile. For eg:
ifeq ($(ENV),ENV1)
ENV_VAR = THIS
else
ENV_VAR = THAT
endif
default : test
.PHONY : test
test:
#echo $(ENV_VAR)
Then you can simply run the make command with arguments
make ENV=ENV1
I have two makefiles in the same directory. Many of the recipes have identical names and here are two solutions:
1. Prefix in make
proja_hello:
#echo "hello A"
projb_hello:
#echo "hello N"
2. Keep two separate files
Project A has makefile. Type make hello.
Project B has a separate make file called projb.mk. Type bmake hello.
This works since I've added alias bmake ='make -f projb.mk to my .bashrc. Note! This command can be called anywhere but only works where projb.mk exists.
Note! You lose autocompletion of make with the alias and typing make -f projb.mk hello is not better than typing make projb_hello.
These are simplified examples of my question.
I have:
Makefile in top/sub/sub/dir:
THINGSTODO := dothis
dothis:
#echo Do cool stuff
Main makefile in top dir:
all: $(THINGSTODO)
#echo do important stuff
Makefile in the sub dirs get included automatically.
If I run this (make all) I get:
No rule to make target 'dothis', needed by 'all'.
My conclusion is that the variable THINGSTODO gets a value but for some reason the rule "dothis" is not visible.
If I place the "dothis" rule in the main makefile it works like a charm.
But I don't want to change the main makefile, I just want to add a rule, in the sub/sub/dir makefile, that is executed before the "all" rule is executed.
I must be missing a vital bit of knowledge to solve this. Any suggestions?
Thanks.
system: Linux 4.18.13-100.fc27.x86_64
make: GNU Make 4.2.1 (Built for x86_64-redhat-linux-gnu)
I have a environment variable set with name $MY_ENV_VARIABLE.
How do I use this variable inside my makefile to (for example) include some source files?
LOCAL_SRC_FILES = $(MY_ENV_VARIABLE)/libDEMO.so
Something like above doesn't seem to work.
Note: in my case this is needed for building with the Android NDK but I guess this applies to make in general.
Just to add some information...
The syntax to access the environment variable in make is like other variables in make...
#export the variable. e.g. in the terminal,
export MY_ENV_VARIABLE="hello world"
...
#in the makefile (replace before call)
echo $(MY_ENV_VARIABLE)
This performs the substitution before executing the commmand. If you instead, want the substitution to happen during the command execution, you need to escape the $ (For example, echo $MY_ENV_VARIABLE is incorrect and will attempt to substitute the variable M in make, and append it to Y_ENV_VARIABLE)...
#in the makefile (replace during call)
echo $$MY_ENV_VARIABLE
Make sure you exported the variable from your shell. Running:
echo $MY_ENV_VARIABLE
shows you whether it's set in your shell. But to know whether you've exported it so that subshells and other sub-commands (like make) can see it try running:
env | grep MY_ENV_VARIABLE
If it's not there, be sure to run export MY_ENV_VARIABLE before running make.
That's all you need to do: make automatically imports all environment variables as make variables when it starts up.
I just had a similar issue (under Cygwin):
Running echo $OSTYPE on the shell prints the value, but
running env | grep OSTYPE doesn't give any output.
As I can't guarantee that this variable is exported on all machines I want to run that makefile on, I used the following to get the variable from within the makefile:
OSTYPE = $(shell echo $$OSTYPE)
Which of course can also be used within a condition like the following:
ifeq ($(shell echo $$OSTYPE),cygwin)
# ...do something...
else
# ...do something else...
endif
EDIT:
Some things I found after experimenting with the info from jozxyqk's answer, all from within the makefile:
If I run #echo $$OSTYPE or #echo "$$OSTYPE" in a recipe, the variable is successfully expanded into cygwin.
However, using that in a condition like ifeq ($$OSTYPE,cygwin) or ifeq ("$$OSTYPE","cygwin") doesn't expand it.
Thus it is logical that first setting a variable like TEST = "$$OSTYPE" will lead to echo $(TEST) printing cygwin (the expansion is done by the echo call) but that doesn't work in a condition - ifeq ($(TEST),cygwin) is false.
I have a very simple Makefile that isn't doing what I expect it would do. The ultimate goal is that it should call itself recursively, including the appropriate file each time, resulting in a build specific to what was included (I'm building several projects that all share the same code base, but utilize different combinations of the source files). I've never really dealt with recursive calls to make, so I must be missing something obvious. At the moment, I only have one .mk file in the same folder as my Makefile. It's a simple one-liner just for the purposes of this test. It will eventually contain various per-project settings.
Makefile:
SHELL = /bin/sh
ifdef MYFILE
include $(MYFILE)
PROGRAM = $(basename $(MYFILE))
endif
all: $(wildcard *.mk)
dummy:
#echo -- Entering dummy stub ... why do I need this?
%.mk: dummy
#echo Calling $(MAKE) MYFILE=$# $*
$(MAKE) MYFILE=$# $*
$(PROGRAM): objs
#echo Time to link!
objs:
#echo Building objs!
test.mk
SOMEVAR = SomeValue
I have the following two problems:
Problem 1
If I remove the dummy prerequisite from my pattern rule, the pattern rule never gets called (I get the dreaded 'Nothing to be done for all' error). Is there a way I can get the recipes under the %.mk rule to run without needing that dummy prerequisite?
Problem 2
Given the two aforementioned files, I would expect make to do the following:
make[1] starts and hit the all rule
make[1] jumps down to the %.mk pattern rule
make[1] calls itself recursively (the call would look like make MYFILE=test.mk test)
make[2] starts, includes the test.mk file, and sets up the PROGRAM variable
make[2] jumps down to the $(PROGRAM) rule (since we were explicitly called with that target)
make[2] jumps to the objs rule, runs the recipes, and returns back up the chain
In actuality, make gets stuck on the %.mk pattern rule and enters an infinite loop. I don't understand why it's insisting on hitting the pattern rule, when I explicitly told it to build test in my first recursive call (which should correspond to the $(PROGRAM) target). What am I missing here?
Problem 0:
This is overdesigned. You don't need to use recursive Make here.
Problem 1:
The reason Make doesn't try to rebuild test.mk (without a dummy preq) is that test.mk is up to date. A better approach is to switch to a static pattern rule and use PHONY:
MKS = $(wildcard *.mk)
.PHONY: $(MKS)
$(MKS): %.mk:
#echo Calling $(MAKE) MYFILE=$# $*
$(MAKE) MYFILE=$# $*
An even better approach is not to use the name of a real file as a target of a rule that doesn't rebuild (or even "touch") that file.
Problem 2:
In make[2], the makefile includes test.mk. If a makefile includes another file, Make will attempt to rebuild that file before doing anything else. If there is a rule for that file (which there is) and if it succeeds (which it does) Make then reinvokes itself.
You should reconsider this design from the ground up. There are many ways to get the behavior you're looking for, depending on the specifics (how many variable will be defined in a foo.mk? do you really want to manage the build by manually moving those files around? and so on).
P.S. Here's one kludge that springs to mind. Whether it suits your case depends on the specifics:
makefile:
# includes nothing
%.mk: dummy
#echo Calling $(MAKE) MYFILE=$# -f $# $*
$(MAKE) MYFILE=$# -f $# $*
test.mk:
SOMEVAR = SomeValue
include makefile
I am trying to generate a make file in Linux that is fairly dynamic and will take get all the files from the /src directory of a certain type. Essentially the output of ls *.type I seem to be having difficulties in doing this. Below is what I currently have but it does not seem to work. Hopefully someone can help me out. Thanks!
JIL_B_TMPL : sh = ls *.type
JIL_LIST = $(JIL_B_TMPL)
I will also add this is not for compiling a C program.
To capture the output of a shell command in a makefile, you can do:
JIL_B_TMPL := $(shell ls *.type)
JIL_LIST := $(JIL_B_TMPL)
This is of course the same as writing:
JIL_LIST := $(shell ls *.type)
This works with GNU make, but since you mention Linux, I suppose you're using that.
Pat got the core of something that works, but in your case, you'll probably want something more like
JIL_LIST := $(wildcard *.type)
This gets rid of a call to an external program, which will be important if you decide in the future that you want to support Windows. Also, if you're using makepp, the wildcard function will also catch any .type files that can be built, regardless of whether or not they already have been.