Idan Nachum
Idan Nachum

Reputation: 21

Allow Makefile both append and override target

I have base Makefile for all my services, in some cases I want to use my default "test" target, in other cases I want to override\add to it. These are the files I have so far (and obviously its not working as expect..).

MakefileBase

test:
    ./.../run-tests.sh

Makefile

BASE_FILE := /path/to/MakefileBase
include ${BASE_FILE}
test:
    @$(MAKE) -f $(BASE_FILE) test # un/comment this line in order to run the default tests.
#   echo "custom test"

When I run the test with the first line commented out I get the following

Makefile:10: warning: overriding commands for target `test'
/.../MakefileBase:63: warning: ignoring old commands for target `test'
echo "no tests"
no tests

except of the warning it works as expected, the problem is when I try to use the parent function then I get the following errors:

Makefile:9: warning: overriding commands for target `test'
/.../MakefileBase:63: warning: ignoring old commands for target `test'
make[1]: test: No such file or directory
make[1]: *** No rule to make target `test'.  Stop.
make: *** [test] Error 2

Upvotes: 2

Views: 6591

Answers (3)

philipp2100
philipp2100

Reputation: 272

Actually, both answers so far are wrong or incomplete:

exit 0 in a rule will just exit the current shell (which runs only the exit 0 command, so it is a no-op in this case). So this won't override.

It's not true that you cannot override a command without warning. If it is not necessary that both targets have the same name, you can do:

MakefileBase

.PHONY: test-base
test-base:
    echo base

%: %-base  # handles cases where you don't want to override

Makefile1

include MakefileBase

.PHONY: test
test:
    echo override

Makefile

include MakefileBase

.PHONY: test
test: test-base
    echo append

As with double colon rules, the effects of each targets (on each other) have to be considered, especially if you move away from .PHONY (for example, files considered up-to-date because the other rule just updated them).

BTW, I don't see the problem with your approach (aside from the warning). For me it worked fine.

Upvotes: 5

cwingrav
cwingrav

Reputation: 989

Hacky, but you can get add, and a limited form of override that can never be deeper than one override. Both use double colon rules.

add: use double colons on both rules

override: use double colons on both rules, appending command exit 0 to the last rule

# "addcmd" echoes "BA", "overridecmd" echoes "B"

addcmd ::
  echo "A"

addcmd ::
  echo "B"

overridecmd ::
  echo "A"

overridecmd ::
  echo "B"
  exit 0

Upvotes: 0

MadScientist
MadScientist

Reputation: 100856

This is what double-colon rules are for:

test::
        ./.../run-tests.sh

and:

BASE_FILE := /path/to/MakefileBase
include ${BASE_FILE}

test::
        @$(MAKE) -f $(BASE_FILE) test

This will "add to" an existing target. There is no way to override a target with a different recipe without incurring a warning.

If you want to do that the only way is to use variables to hold the recipe then override the variable value. For example:

test_recipe = ./.../run-tests.sh

test:
        $(test_recipe)

and:

BASE_FILE := /path/to/MakefileBase
include ${BASE_FILE}

test_recipe = @$(MAKE) -f $(BASE_FILE) test

Upvotes: 0

Related Questions