Alias target name in Makefile

WaelJ picture WaelJ · Apr 17, 2014 · Viewed 18.3k times · Source

The Problem:

Is it possible to give a target a different name or alias, such that it can be invoked using either the original target name or the alias.

For example something like

/very/long/path/my_binary: dep_a dep_b dep_c
    # Compile

# Desired command
ALIAS my_binary = /very/long/path/my_binary

# NOTE: Notice the use of 'my_binary' in the dependencies
data1: my_binary datafile
    # Build data file using compiled my_binary

Attempt 1: .PHONY

I have tried using a .PHONY target:

.PHONY: my_binary
my_binary: /very/long/path/my_binary

This works great when invoked from the command-line:

# Runs rule 'my_binary' and then *only* runs rule '/very/long/path/my_binary'
# if the rule '/very/long/path/my_binary' needs updating.
make my_binary

However, this does not work well when the alias my_binary is listed as a dependency:

# *Always* thinks that rule 'data1' needs updating, because it always thinks that
# the .PHONY target 'my_binary' "needs updating". As a result, 'data1' is
# rebuilt every time.
make /very/long/path/my_binary

Possible hack?

A possible hack is to use an empty target as suggested in an answer to this question, but that would require introducing fake files with names corresponding to the alias:

my_binary: /very/long/path/my_binary
    touch my_binary

This will clutter the main directory with files! Placing the fake files in a sub-directory would defeat the purpose, as the alias would have to be referred to as 'directory/my_binary'

Answer

frncmx picture frncmx · Nov 8, 2015

Okay, I needed something similar. The path to my output artifacts were quite long, but I wanted short target names and also benefit easily from bash-completion.

Here is what I'm came up with:

os := [arbitrary long path to an artifact]
platform := [arbitrary long path to a differ artifact]
packer := [common parts of my packer build command]

.PHONY: all
all: $(platform)

.PHONY: platform
platform: $(platform)

$(platform): platform.json  $(os)
    @$(packer) $<

.PHONY: os
os: $(os)

$(os): os.json
    @$(packer) $<

.PHONY: clean
clean:
    rm -fr build/

With the Makefile above you can say:

$ make os
$ make platform

Which will be aliases for the long artifact names. I've made the snippet above quite long, because it's important to see the relationships between the .PHONY aliases and the real targets. I hope that works for you.

Note: I did not delete the clean target from the above example, because many people does not make that a .PHONY target. However, semantically it should be.