Kirill Bulygin
Kirill Bulygin

Reputation: 3826

Is there a way to force rebuilding a target (make -B) without rebuilding its dependencies?

GNU Make has -B option that forces make to ignore existing targets. It allows to rebuild a target, but it also rebuilds all the dependency tree of the target. I wonder is there a way to force rebuilding a target without rebuilding its dependencies (using GNU Make options, settings in Makefile, compatible make-like software, etc.)?

Illustration of the problem:

$ mkdir test; cd test
$ unexpand -t4 >Makefile <<EOF
huge:
    @echo "rebuilding huge"; date >huge
small: huge
    @echo "rebuilding small"; sh -c 'cat huge; date' >small
EOF
$ make small
rebuilding huge
rebuilding small
$ ls
huge  Makefile  small
$ make small
make: 'small' is up to date.
$ make -B small
rebuilding huge  # how to get rid of this line?
rebuilding small
$ make --version | head -n3
GNU Make 4.0
Built for x86_64-pc-linux-gnu
Copyright (C) 1988-2013 Free Software Foundation, Inc.

Of course one can rm small; make small, but is there a built-in way?

Upvotes: 8

Views: 5237

Answers (5)

Kirill Bulygin
Kirill Bulygin

Reputation: 3826

Well, so far I'm using this partial solution:

$ cat >~/bin/remake <<'EOF'
#!/bin/sh
# http://stackoverflow.com/questions/42139227
for f in "$@"; do
  if [ -f "$f" ]; then
    # Make the file very old; it's safer than removing.
    touch --date=@0 "$f" 
  fi
done
make "$@"
EOF
$ chmod u+x ~/bin/remake
$ # PATH="$HOME/bin:$PATH" in .bashrc
$ remake --debug=b small
GNU Make 4.0
Built for x86_64-pc-linux-gnu
Copyright (C) 1988-2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Reading makefiles...
Updating goal targets....
 Prerequisite 'huge' is newer than target 'small'.
Must remake target 'small'.
rebuilding small

Upvotes: 0

reinierpost
reinierpost

Reputation: 8591

I use something like this:

remake()
{
  for f in "$@"
  do
    [ -f "$f" ] && rm -f "$f"
  done
  make "$@"
}

Upvotes: 0

MadScientist
MadScientist

Reputation: 100836

One way is to use the -o option for all targets you don't want to be remade:

-o FILE, --old-file=FILE, --assume-old=FILE
        Consider FILE to be very old and don't remake it.

EDIT

I think you're misreading the documentation for -B; it says:

  -B, --always-make
        Unconditionally make all targets.

Note, the all targets here; huge is certainly a target, and so if you use -B it will be remade.

However, I also misread your question a bit. I thought you wanted to rebuild small without rebuilding huge even though huge is new, but you're trying to get small to be rebuilt even though huge has not changed, right?

You definitely don't want to use -B. That option is not at all what you are looking for.

Normally people would do that by deleting small:

rm -f small
make small

It might be useful to have an option that forced a given target to be recreated, but that option doesn't exist.

You could use -W huge, but again this means you need to know the name of the prerequisite not just the target you want built.

Upvotes: 6

Alexey Semenyuk
Alexey Semenyuk

Reputation: 704

Will this help:

touch huge; make small

?

Upvotes: 3

bobbogo
bobbogo

Reputation: 15483

File under rather nasty hack:

huge:
    @echo "rebuilding huge"; date >huge

small: $(if $(filter just,${MAKECMDGOALS}),huge)
    @echo "rebuilding small"; sh -c 'cat huge; date' >small

.PHONY: just
just: ;

Now you can

$ make -B just small

Upvotes: 4

Related Questions