Create directories using make file

makefile
makefile build directory
makefile tutorial
makefile example
makefile multiple source directories
makefile variables
makefile phony
makefile include

I'm a very new to makefiles and i want to create directories using makefile. My project directory is like this

+--Project  
   +--output  
   +--source  
     +Testfile.cpp  
   +Makefile  

I want to put all the objects and output into the respective output folder. I want to create folder structure which would be like this after compiling.

+--Project
   +--output
     +--debug (or release)
       +--objs
         +Testfile.o
       +Testfile (my executable file)
   +--source
     +Testfile.cpp
   +Makefile

I tried with several options, but could not succeed. Please help me to make directories using make file. I'm posting my Makefile for your consideration.

#---------------------------------------------------------------------
# Input dirs, names, files
#---------------------------------------------------------------------
OUTPUT_ROOT := output/

TITLE_NAME := TestProj 

ifdef DEBUG 
    TITLE_NAME += _DEBUG
else
ifdef RELEASE
    TITLE_NAME += _RELEASE
endif
endif


# Include all the source files here with the directory tree
SOURCES := \
        source/TestFile.cpp \

#---------------------------------------------------------------------
# configs
#---------------------------------------------------------------------
ifdef DEBUG
OUT_DIR     := $(OUTPUT_ROOT)debug
CC_FLAGS    := -c -Wall
else
ifdef RELEASE
OUT_DIR     := $(OUTPUT_ROOT)release
CC_FLAGS    := -c -Wall
else
$(error no build type defined)
endif
endif

# Put objects in the output directory.
OUT_O_DIR   := $(OUT_DIR)/objs

#---------------------------------------------------------------------
# settings
#---------------------------------------------------------------------
OBJS = $(SOURCES:.cpp=.o)
DIRS = $(subst /,/,$(sort $(dir $(OBJS))))
DIR_TARGET = $(OUT_DIR)

OUTPUT_TARGET = $(OUT_DIR)/$(TITLE_NAME)

CC_FLAGS +=   

LCF_FLAGS := 

LD_FLAGS := 

#---------------------------------------------------------------------
# executables
#---------------------------------------------------------------------
MD := mkdir
RM := rm
CC := g++

#---------------------------------------------------------------------
# rules
#---------------------------------------------------------------------
.PHONY: all clean title 

all: title 

clean:
    $(RM) -rf $(OUT_DIR)

$(DIR_TARGET):
    $(MD) -p $(DIRS)

.cpp.o: 
    @$(CC) -c $< -o $@

$(OBJS): $(OUT_O_DIR)/%.o: %.cpp
    @$(CC) -c $< -o $@

title: $(DIR_TARGET) $(OBJS)

Thanks in advance. Please guide me if i made any mistakes also.

This would do it - assuming a Unix-like environment.

MKDIR_P = mkdir -p

.PHONY: directories

all: directories program

directories: ${OUT_DIR}

${OUT_DIR}:
        ${MKDIR_P} ${OUT_DIR}

This would have to be run in the top-level directory - or the definition of ${OUT_DIR} would have to be correct relative to where it is run. Of course, if you follow the edicts of Peter Miller's "Recursive Make Considered Harmful" paper, then you'll be running make in the top-level directory anyway.

I'm playing with this (RMCH) at the moment. It needed a bit of adaptation to the suite of software that I am using as a test ground. The suite has a dozen separate programs built with source spread across 15 directories, some of it shared. But with a bit of care, it can be done. OTOH, it might not be appropriate for a newbie.


As noted in the comments, listing the 'mkdir' command as the action for 'directories' is wrong. As also noted in the comments, there are other ways to fix the 'do not know how to make output/debug' error that results. One is to remove the dependency on the the 'directories' line. This works because 'mkdir -p' does not generate errors if all the directories it is asked to create already exist. The other is the mechanism shown, which will only attempt to create the directory if it does not exist. The 'as amended' version is what I had in mind last night - but both techniques work (and both have problems if output/debug exists but is a file rather than a directory).

Making directories in GNU Make, Solution 1: build the directory when the Makefile is parsed Before any targets are created or commands run the Makefile is read and parsed. If you put $(shell mkdir -p $(OUT)) somewhere in the Makefile then GNU Make will run the mkdir every time the Makefile is loaded. Using make. Create a Makefile listing the rules for building the executable the file should be named 'Makefile' or 'makefile'. This only has to be done once, except when new modules are added to the program, the Makefile must be updated to add new module dependencies to existing rules and to add new rules to build the new modules.

In my opinion, directories should not be considered targets of your makefile, either in technical or in design sense. You should create files and if a file creation needs a new directory then quietly create the directory within the rule for the relevant file.

If you're targeting a usual or "patterned" file, just use make's internal variable $(@D), that means "the directory the current target resides in" (cmp. with $@ for the target). For example,

$(OUT_O_DIR)/%.o: %.cpp
        @mkdir -p $(@D)
        @$(CC) -c $< -o $@

title: $(OBJS)

Then, you're effectively doing the same: create directories for all $(OBJS), but you'll do it in a less complicated way.

The same policy (files are targets, directories never are) is used in various applications. For example, git revision control system doesn't store directories.


Note: If you're going to use it, it might be useful to introduce a convenience variable and utilize make's expansion rules.

dir_guard=@mkdir -p $(@D)

$(OUT_O_DIR)/%.o: %.cpp
        $(dir_guard)
        @$(CC) -c $< -o $@

$(OUT_O_DIR_DEBUG)/%.o: %.cpp
        $(dir_guard)
        @$(CC) -g -c $< -o $@

title: $(OBJS)

Automatic Directory Creation in Make, We'd like to write our makefile to achieve this in a nice way that won't In particular, creating directories like this is the typical use case for� The simplest makefile you could create would look something like: Makefile 1 hellomake: hellomake.c hellofunc.c gcc -o hellomake hellomake.c hellofunc.c -I. If you put this rule into a file called Makefile or makefile and then type make on the command

Or, KISS.

DIRS=build build/bins

... 

$(shell mkdir -p $(DIRS))

This will create all the directories after the Makefile is parsed.

Makefile Basics (GNU make), (the build directory) and $(srcdir)/ (the source directory) is important because users can build in a separate directory using the ' --srcdir ' option to configure . Create directory hierarchy We can create multiple directories hierarchy (creating folder and sub folders with a single command) using mkdir command. For example, the below command would create a new folder called ‘folder1’ and a sub folder ‘folder2’ and a sub sub folder ‘folder3’. mkdir folder1\folder2\folder3.

make in, and off itself, handles directory targets just the same as file targets. So, it's easy to write rules like this:

outDir/someTarget: Makefile outDir
    touch outDir/someTarget

outDir:
    mkdir -p outDir

The only problem with that is, that the directories timestamp depends on what is done to the files inside. For the rules above, this leads to the following result:

$ make
mkdir -p outDir
touch outDir/someTarget
$ make
touch outDir/someTarget
$ make
touch outDir/someTarget
$ make
touch outDir/someTarget

This is most definitely not what you want. Whenever you touch the file, you also touch the directory. And since the file depends on the directory, the file consequently appears to be out of date, forcing it to be rebuilt.

However, you can easily break this loop by telling make to ignore the timestamp of the directory. This is done by declaring the directory as an order-only prerequsite:

# The pipe symbol tells make that the following prerequisites are order-only
#                           |
#                           v
outDir/someTarget: Makefile | outDir
    touch outDir/someTarget

outDir:
    mkdir -p outDir

This correctly yields:

$ make
mkdir -p outDir
touch outDir/someTarget
$ make
make: 'outDir/someTarget' is up to date.

TL;DR:

Write a rule to create the directory:

$(OUT_DIR):
    mkdir -p $(OUT_DIR)

And have the targets for the stuff inside depend on the directory order-only:

$(OUT_DIR)/someTarget: ... | $(OUT_DIR)

Tutorial on writing makefiles, To use this makefile, simply cd to the directory and type “ makepp ”. Makepp will attempt to build the first target in the makefile, which is my_program . (If you don't � Create a folder in a directory Open Finder and navigate to the directory in which you'd like to create the folder. Click on File in the upper-left corner of the screen. Select New Folder in the drop-down menu that appears.

All solutions including the accepted one have some issues as stated in their respective comments. The accepted answer by @jonathan-leffler is already quite good but does not take into effect that prerequisites are not necessarily to be built in order (during make -j for example). However simply moving the directories prerequisite from all to program provokes rebuilds on every run AFAICT. The following solution does not have that problem and AFAICS works as intended.

MKDIR_P := mkdir -p
OUT_DIR := build

.PHONY: directories all clean

all: $(OUT_DIR)/program

directories: $(OUT_DIR)

$(OUT_DIR):
    ${MKDIR_P} $(OUT_DIR)

$(OUT_DIR)/program: | directories
    touch $(OUT_DIR)/program

clean:
    rm -rf $(OUT_DIR)

create dir in makefile, i'm writing a makefile and i want to create directories in the install option. i've tried using mkdir to no avail. i read about using install() to do this but� What to Know To create directories in Linux, you can open Terminal and use the command line with the mkdir command. Once you create a new directory in Linux, then you can change permissions and create folders within the directory. You can also create a directory and set permissions at the same time.

Create your first directory, Use the command mkdir to create a directory. mkdir is short for "make always create folders and files for your code via the command line. To create an entire path you have to call mkdir () once per directory level. Alternatively, if you want to create multiple directories at once, make use of the makedirs () method instead (which you can see in Listing 4 below). As an optional parameter you can specify the access rights to the directory within your mkdir () call.

Working With Files and Directories – The Unix Shell, Create a directory hierarchy that matches a given diagram. Create files in that hierarchy using an editor or by copying and renaming existing files. Delete, copy and� md “Test A”. If there are spaces in the folder name, then the folder name should be given in quotes. mkdir \a\b\c. The above command creates directories recursively and is the same as issuing the following set of commands. mkdir \a chdir \a mkdir b chdir b mkdir c. batch_script_functions.htm. Previous Page Print Page.

Conventions for Recursive Makefiles and Directories, The contents of Makefile.dnm aren't examined in any way — you can use touch to create an empty file for it. Macros. The above command will create a directory called "dir1" in the current working directory. To create multiple directories, we use: $ mkdir dir1 dir2 dir3. Or, $ mkdir dir{1,2,3} This command creates three directories namely dir1, dir2, and dir3 in the current working directory. To create nested directories, we do: $ mkdir -p dir1/dir2/dir3. The

Comments
  • Thank you Jonathan. when i tried that i got an error "make: *** No rule to make target output/debug', needed by directories'. Stop." But i'm not going to worry about that now. will stick with the basic rules. :). Thank you for guiding. And i'm running "make" from toplevel directory only.
  • Just delete the ${OUT_DIR} behind directories:, then it should work.
  • Implementing this requires that you catch every possible case where you use the directories from the command-line though. Furthermore, you can't make any file generating build rules dependant on directories without causing them to always rebuild..
  • @mtalexan You've provided a couple of comments explaining what's wrong with some of these answers but you haven't proposed an alternative answer. Anxious to hear your solution for this problem.
  • @Samuel I pointed out the problems without providing a solution because I was looking for the same thing and never found a solution. I ended up just dealing with the fall out of a less than ideal solution.
  • While linking the directory requirement to files is a better option in my opinion, your solution also has the significant drawback that the mkdir process will be called by the make file for every single file that's rebuilt, most of which won't need to make the directory again. When adapted to non-Linux build systems like Windows, it actually causes both an unblockable error output since there is no -p equivalent to the mkdir command, and more importantly a gigantic amount of overhead since the shell invocation is not minimally invasive.
  • Instead of directly calling mkdir, I did the following to avoid trying to create the directory if it already exists: $(shell [ ! -d $(@D) ] && mkdir -p $(@D))
  • I like this approach because I don't have to clutter each target with commands to handle the directories.
  • I just needed to create directory if it doesn't exist. This answer fits perfect for my issue.
  • Not only that, this prevents the modified timestamps of each directory from triggering an unnecessary build step. This should be the answer
  • This is better: $(info $(shell mkdir -p $(DIRS))) Without the $(info ...), the output of the mkdir command will be pasted into the Makefile, leading to syntax errors at best. The $(info ...) call ensures that a) the errors (if any) are visible to the user, and b) that the function call expands to nothing.
  • On what broken OS/FS did you see touch modify any stat data on the parent directory? That makes non sense to me. The mtime of a dir only depends on the filenames it contains. I could not reproduce your issue.
  • @JohanBoulé Debian.
  • And did you fill a bug for such a broken behavior?
  • Creating a variable that holds "the file name of every file that your makefile will build" is kind of an onerous requirement - I like to define my top-level targets, then the things they depend on, and so on. Having a flat list of all the target files goes against the hierarchical nature of the makefile specification, and may not be (easily) possible when target files depend on runtime computations.