Hello I am a bit new to makefiles, i know the basics and thought I'd work through an example i found online. However i ran into something that doesn't seem right and i was hopping somone could help clear things up. The example can be found at the following link:
https://riptutorial.com/makefile/example/21376/building-from-different-source-folders-to-different-target-folders
My specific question is regarding the following line:
SOURCEDIRS = $(foreach dir, $(DIRS), $(addprefix $(SOURCEDIR)/, $(dir)))
I was wondering how the makefile could evaluate $(dir) when the dir variable was not assigned anywhere? is dir some sort of pre defined GNU Makefile variable or am i missing something?
Any help is appreciated, thanks
First, look up foreach. The function iterates through $(DIRS), assigning each word of it to dir in turn, and evaluating $(addprefix $(SOURCEDIR)/, $(dir)). This has the effect of prepending $(SOURCEDIR)/ to each word in $(DIRS).
Then look up addprefix. This function can do all of the work by itself, so foreach is completely unnecessary in this example. This will suffice:
SOURCEDIRS = $(addprefix $(SOURCEDIR)/,$(DIRS))
Related
NOTE: I use Mingw Make.
Basically, I've got a makefile with the following snippet for source files:
SRC_FILES = $(wildcard $(SRC_DIR)/*.c $(SRC_DIR)/*/*.c $(SRC_DIR)/*/*/*.c)
SRC_FILES := $(filter-out $(SRC_DIR)/sys/mswin/win_main.c, $(SRC_FILES))
Not the prettiest, I'll admit I'm still a beginner, but it does work. However, the second line shows what I'd like to exclude. Issue is, I currently have to do this per file I want to exclude. (Note: I've tried replacing win_main.c with *.c, doesn't work).
What I'd like to be able to do is exclude the entire 'sys' directory from SRC_FILES, but I'm honestly unsure of how to do this. I attempted to have:
SRC_FILES := $(filter-out $(SRC_DIR)/sys, $(SRC_FILES))
But this didn't work, either. I'm honestly unsure if this is even possible at this point, but I hope I'm just missing something. Any help is appreciated!
EDIT: I know that the project structure itself isn't ideal, but that's not really the point of this, however improvement tips are certainly apprectiated, and if you need any other information to answer the question just ask.
Easy enough; filter-out takes a %-pattern as an argument:
SRC_FILES := $(filter-out $(SRC_DIR)/sys/%,$(SRC_FILES))
I have a makefile that looks something like this:
include anotherFile.mk
all:
someStuff
The file anotherFile.mk is like this:
include yetAnotherFile.mk
export SOME_VAR = 93
The problem is that anotherFile.mk and yetAnotherFile.mk are in a different directory from my Makefile. So my makefile can't just be changed to this:
include $(OTHER_PROJECT_PATH)/anotherFile.mk
all:
someStuff
The problem with this approach is that the include statement in anotherFile.mk will fail because it will be searching in the current directory.
A partial solution that I found is to pass the --include-dir=$OTHER_PROJECT_PATH flag to the invocation of make, but that's a bit user-unfriendly.
So my question is: Is there something I can put inside my makefile that will add to the directories that make searches for when executing an include? Something like MAKE_INCLUDE_DIRS += $(OTHER_PROJECT_PATH)
Surprisingly there doesn't seem to be a good answer to that question. Forcing .INCLUDE_DIR doesn't help and there doesn't seem to be any way around invoking make with --include-dir=$OTHER_PROJECT_PATH.
It is however possible to put the appropriate recursive make invocation inside the makefile but, in order to get it to work for all reasonable cases it quickly becomes too complicated to be worth it. In summary it requires:
a top level condition to check if the OTHER_PROJECT_PATH is in .INCLUDE_DIR
the appropriate target with the recipe invoking make recursively
possibly additional targets if there are multiple command goals
the real make file enclosed in the else part of the conditional
You Makefile would look like this:
OTHER_PROJECT_PATH := other
ifeq (,$(filter $(OTHER_PROJECT_PATH), $(.INCLUDE_DIRS)))
# this is the mechanism to add the include dir in a recursive make
$(or $(firstword $(MAKECMDGOALS)),all):
$(MAKE) -I$(OTHER_PROJECT_PATH) $(MAKECMDGOALS)
# add empty targets for additional goals if needed
ifneq (,$(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS)))
$(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS)):
endif
else
# this is where the real makefile starts
all more:
echo $#: $< $^
include a.mak
endif
It still does not seem possible from a makefile, but if you have a script that sets up environment variables, you can use MAKEFLAGS (e.g. export MAKEFLAGS=I/your/path ordentlich on Linux, or SET on Windows)
im trying to write a non recursive make build system.
what im trying to accomplish is that each makefile will define its own variables and "feel" like he is the only one in the system.
for example:
Project layout:
-Makefile
-src1
----Makefile
----example1.c
-src2
----Makfile
----example2.c
the main Makefile looks like this:
include src1/Makefile
include src2/Makefile
all: $(TARGETS)
each of src1/src2 makefile looks like this:
SRC:=...
OBJ:=...
TARGETS+=bin1 #in src2 its bin2
bin1: $(OBJ)
----gcc ....
$(OBJ_DIR)/%.o : $(SRC_DIR)/%.c
----gcc ....
but this design pattern does not work as the evaluation of recipe in the targets is deferred.
this means all the variables with the same name in src1 gets the value of src2 variables(the last assignment). i tried to replace the include with $(eval include ...) but no luck.
please note that all the variables assignment is done with :=
is there a way to accomplish that each makefile can define what he wants or each variable should be unique?
thanks,
tal
It's difficult to do that. When I've done this in one or two places I've started with make snippets in each directory that can be included from the master make file, and ended up with a scripted approach which scans the make snippets and generates something else. And I had a VPATH in there as well.
There's an example of how this might be achieved in the 'recursive make considered harmful' paper which might be of help.
I would like do something like following. I would like to have a variable argument list for a Makefile.
make VAR_ARG_LIST=src1,src2,src3,src4
Can I do like this? If I can, how do I extract src1,src2 or src3 from the variable VAR_ARG_LIST inside the Makefile?
Thanks,
If you want a list of targets in a macro for make to use, use blanks to separate them (and quotes to enclose them) on the command line:
make VAR_ARG_LIST="src1 src2 src3 src4"
This can be used inside the makefile without much trouble at all:
PROGRAMS = ${VAR_ARG_LIST}
all: ${PROGRAMS}
and it will go off and create the programs src1, ... src4 from the rest of the rules in the makefile.
If that isn't roughly what you're after, then you need to clarify your question.
You really haven't provided enough information for a solution. Why do you want to extract those values? What do you want to do with them?
However, I can answer the question you asked and hope it is useful. If you're using GNU make you can do this:
COMMA := ,
VAR_ARG_LIST_A := $(subst $(COMMA), ,$(VAR_ARG_LIST))
VAR_ARG_LIST_1 := $(word 1,$(VAR_ARG_LIST_A))
VAR_ARG_LIST_2 := $(word 2,$(VAR_ARG_LIST_A))
etc.
please I need your help!
In order to get a list of thumbnails associated with a list of photos, I've use the following Makefile (the project's directory has 2 subdirectories thumbs and pictures)
all: $(patsubst pictures/%.jpg, thumbs/%.jpg, $(wilcard pictures/*.jpg))
thumbs/%.jpg: pictures/%.jpg
convert -thumbnail 100 $< $*
The problem is that I always get the same error message "Nothing to be done for 'all'", as if there was no dependencies. :(
Has anybody an explanation for that?
It is a simple typo: just add the missing d to $(wildcard ...)
Make does not throw an error when you make a call to a function that does not exist, so the result of that function call is simply an empty string. This makes your all target have no dependencies, and there you are!
For future reference, I found this error by adding the following line at the beginning of the makefile:
$(info $(patsubst pictures/%.jpg, thumbs/%.jpg, $(wilcard pictures/*.jpg)))
The $(info ...) function will print out to the console, which can be very useful for debugging. In this case, it printed a blank line. To debug further, I tried this:
$(info $(wilcard pictures/*.jpg))
Which also dumped an empty string. At that point, all it took was some careful squinting :)