$${HOME} or ${HOME} in Makefile?
Yes and no. It is best to use $$
to be explicit. However, there is a special rule for environment variables:
Variables in make can come from the environment in which make is run. Every environment variable that make sees when it starts up is transformed into a make variable with the same name and value. But an explicit assignment in the makefile, or with a command argument, overrides the environment. (If the `-e' flag is specified, then values from the environment override assignments in the makefile. See section Summary of Options. But this is not recommended practice.)
How to read $HOME in Makefile?
Use $()
in Makefiles
echo $(HOME)
How to get current relative directory of your Makefile?
The shell function.
You can use shell
function: current_dir = $(shell pwd)
.
Or shell
in combination with notdir
, 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:
Note that this returns the current working directory, not the parent directory of the Makefile.
For example, if you runcd /; make -f /home/username/project/Makefile
, thecurrent_dir
variable will be/
, not/home/username/project/
.
Code below will work for Makefiles invoked from any directory:
mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
current_dir := $(notdir $(patsubst %/,%,$(dir $(mkfile_path))))
Make file echo displaying $PATH string
In the manual for GNU make, they talk about this specific example when describing the value
function:
The value function provides a way for you to use the value of a
variable without having it expanded. Please note that this does not
undo expansions which have already occurred; for example if you create
a simply expanded variable its value is expanded during the
definition; in that case the value function will return the same
result as using the variable directly.The syntax of the value function is:
$(value variable)
Note that variable is the name of a variable; not a reference to that variable. Therefore you would not normally use
a ‘$’ or parentheses when writing it. (You can, however, use a
variable reference in the name if you want the name not to be a
constant.)The result of this function is a string containing the value of
variable, without any expansion occurring. For example, in this
makefile:FOO = $PATH
all:
@echo $(FOO)
@echo $(value FOO)
The first output line would be ATH, since the “$P” would be expanded as a make variable, while the second
output line would be the current value of your $PATH environment
variable, since the value function avoided the expansion.
Linux - environment variables $HOME versus $(HOME)
make
is not bash
They deal with variables differently. $foo
is how you read a variable called foo in bash, and $(foo)
is how you read it in a makefile.
simple loop over files in some directory makefile
Maybe you can do it purely Makefile way?
MYDIR = .
list: $(MYDIR)/*
@echo $^
You can still run command from Makefile like this
MYDIR = .
list: $(MYDIR)/*
for file in $^ ; do \
echo "Hello" $${file} ; \
done
If I were you, I'd rather not mix Makefile and bash loops based on $(shell ...)
. I'd rather pass dir name to some script and run loop there - inside script.
How do I write the 'cd' command in a makefile?
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 new lines as they are interpreted by make as the end of the rule, so any new lines you use for clarity need 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 means 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 subdirectory, 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 that directory, 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.
How do i get the user name in a Makefile?
Well, if you want that file during runtime I would recommend that you create it during runtime. The Makefile is considered only during compile time. This is obviously a problem if the program is compiled and then executed by different users, some of which may not even exist at compile time.
During runtime you can get the home directory as shown here (if you are using C/C++). Then you can check for existance of the highscore folder/file and create it if you need to. If you want a highscore file for all users, you should put it in the home directory of a special user, but rather somewhere else in the file system. This is for example done by the game xjump.
And about your Makefile, the $USER variable is translated to root because of the sudo command on
sudo make install
The user actually running make is the superuser: root.
Defining local variable in Makefile target
You can't define a make variable inside a recipe. Recipes are run in the shell and must use shell syntax.
If you want to define a make variable, define it outside of a recipe, like this:
FILENAME := text.txt
zsh:
@echo "Copying ${FILENAME}...";
scp "${FILENAME}" "user@host:/home/user/${FILENAME}"
Note, it's virtually never correct to add quotes around a value when assigning it to a make variable. Make doesn't care about quotes (in variable values or expansion) and doesn't treat them specially in any way.
Related Topics
Why Does The Linker Modify a -Defsym "Absolute Address"
Does There Exist Kernel Stack for Each Process
How to Execute an Arbitrary Script with a Working Directory of The Directory Its In
Posix_Fadvise(Willneed) Makes Io Slower
When Will Send() Return Less Than The Length Argument
Is Overwriting a Small File Atomic on Ext4
Change Script Directory to User's Homedir in a Shell Script
How Does This Perl One Liner in The Bash Works
Ensure Config.H Is Included Once
Base Address at Which The Linux Kernel Is Loaded
Can Perf-Stat Results Be Generated from a Perf.Data File
Redirecting Stdout & Stderr from Background Process
Where Does Dmidecode Get The Smbios Table
How Is Preemptive Scheduling Implemented for User-Level Threads in Linux
Simplest Way to Build Dotnet Sdk Project Requiring Net461 on Macos