To recursively include all files in a folder in makefile - makefile

I am new to makefiles. I want to recursively find all the files in a root_folder and store it to a variable. The code I have written to achieve this in makefile is as below:
dirs:=$(root_folder)/*/
SOURCE:=$(foreach dir,$(dirs),$(wildcard $(dir)/*.cpp))
But the .cpp files are not getting included to the SOURCE variable with this implementation.I think my approach is wrong.Any help in this matter will much be appreciated.
Regards,
newbie_in

Assuming you're using linux, use find:
SOURCE:=$(shell find $(root_folder) -name *.cpp)
or
SOURCE:=$(shell cd $(root_folder) && find . -name *.cpp)

Related

How to tar a directory with using makefile

I have few files in sub directories, all the files are just text files like faq, user guides.There are no c/cpp src code
in it. Following is the file and directory structure.
scr
|_Makefile #Top level Makefile
|_other_dirs
|_some_other_dirs
|_mydir
|_Makefile #Makefile of mydir, need to put some code here
|_dir1
| |_textfile0
| |_textfile1
|_dir2
|_textfile2
|_textfile3
Question, How can I tar the contents of dir1 and dir2 into one tar ball? I tried searching over internet about the Makefile and how to use it to create the take ball from top Makefile but no success yet. I am not very familiar with Makefiles, any starting point will be appreciated. Thanks.
Following is my novice attempt to have a very basic Makefile:
-->cat Makefile
mydir.tgz : *
tar -zcvf mydir.tgz mydir/
-->make
Makefile:1: *** missing separator. Stop.
Idea is to run top Makefile and have tar file generated for mydir.
You can add all files and directories in mydir recursively as a prerequisite of mydir.tgz. That way, your tar file will be executed if, and only if, a change occurs somewhere under mydir. For example like this:
mydir.tgz: $(shell find mydir)
tar -zcvf mydir.tgz mydir
The line with the tar command should start with at TAB.
Most of the mechanisms of this answer are also described in this SO question, but it seemed to make sense to me to add it here to concisely answer your specific question.

How to write a Make rule for files of certain type in a directory tree?

Imagine a directory tree (which might be more than one level deep) containing several Markdown files. A PDF version of each file exist in the same directory and must be updated each time the corresponding Markdown file is updated. What rule must be written in a single Makefile in the root directory of this tree to achieve this?
I am looking a for a solution where files can be added or removed from the directory tree without a need for updating the Makefile.
Assumptions:
all markdown files follow a certain pattern in their name; for example they end with a .md postfix.
GNU Make is being used.
You can use $(shell find) to find files recursively. For example:
markdown := $(shell find . -name '*.md')
all: $(patsubst %.md, %.pdf, $(markdown))
%.pdf: %.md
pandoc -o $# $<

Dot in front of variables in make files

I am not able to figure out what does a dot . in front of a variable in makefile does. For e.g.:
SOURCEDIRS = . $(PROJECTDIRS) $(TARGET_DIRS_CONCAT)
vpath %.c $(SOURCEDIRS)
It would be great if someone could tell me.
Thanks!
Generally it just refers to your current directory.
I.e. If you were on a linux machine, and you cd /home/user/Darth and run ls ., you should see the contents of the the folder Darth. So in this case, it looks like it's just including the current directory that you're in into the SOURCEDIRS.

How to use make to convert files in subdirectories?

I have a directory with a bunch of subdirectories. Each subdirectory contains a traj.dat file. I want to use a Makefile to make sure that the file traj.dat gets converted to a different format, and the output file is printed in the same subdirectory as the original file.
Therefore, if I wanted to specify the names of the subdirectories, I could just use:
subdir1/traj.dat.xyz: subdir1/traj.dat
my_convert subdir1/traj.dat subdir1/traj.dat.xyz
subdir2/traj.dat.xyz: subdir2/traj.dat
my_convert subdir2/traj.dat subdir2/traj.dat.xyz
and so on.
How can I get the above result FOR ALL the subdirectories containing a traj.dat file, regardless of their name, without having to list them explicitly?
Cheers!
Assuming you're using GNU make, try:
DATFILES := $(shell find . -name traj.dat)
OUTFILES := $(addsuffix .xyz,$(DATFILES))
all: $(OUTFILES)
%.dat.xyz : %.dat
my_convert $< $#
You weren't really clear what you mean by "subdirectories"; if you just mean immediate subdirectories you can use this instead of the shell function, which is more efficient (and works on Windows):
DATFILES := $(wildcard */traj.dat)

Wildcard to obtain list of all directories

In my Makefile I need to get a list of all directories present in some other directory.
To get a list of all directories in the same folder as my Makefile I use:
DIRECTORIES = $(wildcard */)
all:
echo $(DIRECTORIES)
which works fine, and gives me the desired list. However if I want to have a list of all directories in another directory using
DIRECTORIES = $(wildcard ../Test/*/)
all:
echo $(DIRECTORIES)
I get a list of ALL files (with paths) in that directory, including .h and .cpp files.
Any suggestions why this happens and how to fix it? Other solutions to obtain the list are also welcome.
Use sort and dir functions together with wildcard:
DIRECTORY = $(sort $(dir $(wildcard ../Test/*/)))
From GNU make manual:
$(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 ‘./’.
$(sort list)
Sorts the words of list in lexical order, removing duplicate words. The output is a list of words separated by single spaces.
Also look at the second and the third method in this article: Automatically Creating a List of Directories
Try:
$(shell find <directory> -maxdepth 1 -type d)
which will give you the list of directories inside a given directory without going into subdirectories. You may need to clean that list up since it will include . and ./ before every directory listed.
Use:
$(wildcard ../Test/*/.)
This works fine.

Resources