Complete Guide to Getting Current Relative Directory in Makefile

Nov 16, 2025 · Programming · 11 views · 7.8

Keywords: Makefile | Directory Identification | MAKEFILE_LIST | GNU Make | Path Processing

Abstract: This article provides an in-depth exploration of various methods to obtain the current relative directory in Makefile, focusing on the limitations of the $(CURDIR) variable and presenting reliable solutions based on the MAKEFILE_LIST variable. Through detailed code examples and comparative analysis, it helps developers understand the applicable scenarios and implementation principles of different approaches, ensuring Makefile can correctly identify the current directory in various execution environments.

Overview of Directory Identification Issues in Makefile

In complex project structures, Makefiles often need to set output paths or other configurations based on the current directory location. As shown in the Q&A data, developers expect to place compiled binaries in output paths corresponding to the directory where the Makefile resides. However, directly using the $(CURDIR) variable leads to path redundancy issues because this variable returns the current working directory when the make command is executed, not the directory of the Makefile file itself.

Analysis of $(CURDIR) Variable Limitations

$(CURDIR) is a built-in variable in GNU Make that always points to the working directory when the make command is executed. This means that regardless of where the Makefile is located, $(CURDIR) only reflects the directory state at command execution time. As shown in the example:

OUTPUT_PATH = /project1/bin/$(CURDIR)

When executing make from the /projects/users/bob/project1/apps/app_typeA directory, $(CURDIR) returns the complete absolute path, causing the output path to become:

/project1/bin/projects/users/bob/project1/apps/app_typeA

This clearly does not meet expectations since developers only need the app_typeA level directory name.

Preliminary Solution Based on Shell Function

The first method proposed in Answer 1 utilizes Makefile's shell function to obtain the current working directory:

current_dir = $(shell pwd)

This method can obtain the absolute path but similarly depends on the execution environment. To extract the last level of the directory name, it can be combined with the notdir function:

current_dir = $(notdir $(shell pwd))

However, this approach still has limitations. As noted by @Flimm, when specifying the Makefile from another directory using the -f parameter, the shell function still returns the command execution directory, not the directory where the Makefile resides.

Reliable Solution Based on MAKEFILE_LIST

The updated solution provided in Answer 1 utilizes the MAKEFILE_LIST variable, which contains the list of Makefiles currently being parsed. This method does not depend on the execution environment and can accurately obtain the path information of the Makefile itself:

mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
current_dir := $(notdir $(patsubst %/,%,$(dir $(mkfile_path))))

Let's analyze the implementation principle of this code step by step:

MAKEFILE_LIST Variable Analysis

MAKEFILE_LIST is a special variable in GNU Make that sequentially records all included Makefile files. The lastword function is used to get the last element in the list, which is the Makefile currently being executed.

Path Processing Function Chain

The abspath function converts relative paths to absolute paths, ensuring path format consistency. The dir function extracts the directory part of the path, the patsubst function removes the trailing slash from the directory, and the notdir function ultimately extracts the last level name of the directory.

Practical Application Example

Assuming the Makefile is located at /project1/apps/app_typeA/Makefile, regardless of where the make command is executed from, the above code will correctly return app_typeA as the value of current_dir.

Supplementary Solution from Answer 2

Answer 2 provides another similar implementation:

ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))

This method uses firstword instead of lastword and utilizes the shell command dirname to process the path. Although the implementation differs slightly, the core idea is based on MAKEFILE_LIST to obtain the accurate path of the Makefile.

Verification and Supplement from Reference Article

The reference article "How to get the full path and directory of a Makefile itself?" provides the same methodology:

mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
mkfile_dir := $(dir $(mkfile_path))

This article emphasizes the independence of this method from the working directory, further validating the correctness and reliability of the solution in Answer 1.

Solution Comparison and Selection Recommendations

Comprehensive comparison of various methods shows that the solution based on MAKEFILE_LIST has clear advantages:

Environment Independence

This method is completely independent of the execution environment, accurately identifying the directory where the Makefile resides regardless of where the make command is called from.

Path Accuracy

Using abspath ensures path format uniformity, avoiding ambiguities that relative paths might introduce.

Flexibility of Function Combination

Different path processing functions can be flexibly combined according to specific needs, such as omitting notdir when the full path is needed, or adjusting the application of the dir function when the parent directory is required.

Extension of Practical Application Scenarios

Beyond setting output paths, this directory identification technique can also be applied to:

Conditional Compilation Configuration

Enabling different compilation options or dependency libraries based on characteristics of different subdirectories.

Resource File Location

Accurately referencing resource files in the same directory as the Makefile or in relative directories.

Unified Management of Multiple Projects

Ensuring each subproject can correctly identify its own position in complex structures containing multiple subprojects.

Best Practice Recommendations

In actual project development, it is recommended to:

Standardize Variable Naming

Use meaningful variable names such as MAKEFILE_DIR or CURRENT_MODULE to improve code readability.

Implement Error Handling Mechanisms

Add path validation logic to ensure the obtained directory actually exists and is accessible.

Complete Documentation Comments

Add detailed comments in the code to explain the directory identification logic and expected behavior.

Conclusion

Through in-depth analysis of various methods for directory identification in Makefile, we have clarified the limitations of $(CURDIR) and shell pwd, and established the solution based on MAKEFILE_LIST as the best practice. This method not only solves the path redundancy problem but also provides reliable, environment-independent directory identification capabilities, offering a solid technical foundation for building complex multi-directory projects.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.