Methods and Practices for Passing Arguments to Makefile Targets

Nov 19, 2025 · Programming · 9 views · 7.8

Keywords: Makefile | argument_passing | build_tool | GNU_make | automated_build

Abstract: This article provides a comprehensive exploration of various methods for passing arguments to run targets in Makefiles, with a focus on the standard approach using variable assignment. The paper compares the advantages and disadvantages of different techniques, including the concise ARGS variable solution, advanced GNU make tricks, and alternative external script approaches. Complete code examples and practical recommendations are provided, along with an in-depth analysis of make's argument processing mechanism to help developers choose the most suitable parameter passing method for their project requirements.

Introduction

In software development, Makefile serves as a classic build tool widely used for project construction and task automation. However, many developers encounter difficulties when attempting to pass arguments to Makefile targets, particularly when aiming for concise invocation patterns like make run argument. Based on practical development scenarios, this article systematically explores multiple parameter passing approaches, providing comprehensive technical reference for developers.

Standard Argument Passing Approach

The most direct and recommended method involves using Makefile variables to pass arguments. This approach aligns with make's design philosophy and offers excellent readability and maintainability.

Basic implementation as follows:

prog: main.c utils.c
    gcc -o prog main.c utils.c

run: prog
    ./prog $(ARGS)

Usage examples:

make ARGS="asdf" run
# or
make run ARGS="asdf"

The advantage of this approach lies in its simplicity and standardization. The variable ARGS is assigned during make execution and expanded within the run target's recipe. When executing make run ARGS="hello world", the actual command executed is ./prog hello world, with arguments correctly passed to the target program.

Technical Details of Argument Handling

When using variables to pass arguments, careful attention must be paid to argument quoting, as improper quoting may lead to incorrect argument parsing.

Correct approach:

run: prog
    ./prog $(ARGS)

Incorrect approach:

run: prog
    ./prog "$(ARGS)"  # This passes all arguments as a single entity

When passing arguments containing spaces, appropriate escaping is required:

make run ARGS="foo \"bar baz\""
# or
make run ARGS="foo bar\\ baz"

Advanced Argument Processing Techniques

For GNU make users, more advanced techniques can achieve direct command-line argument passing. This method leverages make's target parsing mechanism.

Implementation code:

ifeq (run,$(firstword $(MAKECMDGOALS)))
  RUN_ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
  $(eval $(RUN_ARGS):;@:)
endif

prog: main.c utils.c
    gcc -o prog main.c utils.c

.PHONY: run
run: prog
    ./prog $(RUN_ARGS)

This method offers more intuitive invocation:

make run foo bar baz

However, this approach has limitations: arguments cannot contain equals signs (interpreted as variable assignments), arguments starting with hyphens require special handling, and potential conflicts with existing target names may occur.

Alternative Approach: External Script Wrapper

When argument passing requirements become complex, using an external shell script as a wrapper layer may be a better choice.

Create build_and_run.sh script:

#!/bin/sh
make prog
./prog "$@"

Usage:

./build_and_run.sh argument1 "argument with spaces"

Advantages of this approach:

Practical Recommendations and Best Practices

When selecting argument passing approaches, consider the following factors:

  1. Simplicity First: For most scenarios, variable passing (make run ARGS=...) is the optimal choice
  2. Compatibility Considerations: If projects require portability across different make versions, avoid GNU make-specific advanced features
  3. Complexity Assessment: When argument processing logic becomes complex, consider external script wrapping
  4. Team Collaboration: Choose methods familiar to and understood by all team members to ensure code maintainability

Conclusion

As a build tool, Makefile's core strengths lie in dependency management and incremental building. While various techniques can achieve argument passing, the most appropriate solution should be selected based on actual requirements. For simple argument passing, the variable approach is both standard and reliable; for complex argument scenarios, external script wrapping offers better flexibility and maintainability. Understanding the applicable scenarios and limitations of each method helps make informed technical choices in 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.