0

I am learning C++, though I have now a general question, i.e. not for programmers, but IMHO best fit for Linux users.

I want the:

make

command to always build a new binary, which could easily be accomplished by creating a Bash alias, something like:

alias make='\make clean && \make'

I would like not to be defining that alias, can this be achieved on the Makefile's side?

The simplest Makefile, I could come up with, follows:

PROGRAM=project

CXXFLAGS=-std=c++17 -Wall -Wextra -Werror -Wpedantic -pedantic-errors

OPTIMIZATION=-O2

.PHONY: build
.PHONY: clean
.PHONY: distrib

build: ${PROGRAM}

clean:
    rm ${PROGRAM}

distrib:
    tar -czf ${PROGRAM}.tar.gz ${PROGRAM}.cpp Makefile

${PROGRAM}:
    g++ ${PROGRAM}.cpp ${CXXFLAGS} ${OPTIMIZATION} -o ${PROGRAM}

Now, in this state it says:

make: Nothing to be done for 'build'.

Essentially, it probably sees recent timestamp and does not build, I think.

EDIT1:

I will only add, that this issue is not Tab related, it builds normal when binary is not in place.

EDIT2:

After I have made modifications as per Sato Katsura's answer:

The Makefile looks like this:

https://www.vlastimilburian.cz/public/linux/Makefile.gz

(I uploaded it, because Tabs can't be shown in text)

and it still says as the above information:

make: Nothing to be done for 'build'.

EDIT3:

$ make --version

GNU Make 4.1
Built for x86_64-pc-linux-gnu
Copyright (C) 1988-2014 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.
  • 1
    You told make that build depends on ${PROGRAM}, but didn't tell it that ${PROGRAM} depends on ${PROGRAM}.cpp – steeldriver Nov 10 '17 at 14:27
  • 1
    Change ${PROGRAM}: to ${PROGRAM}: ${PROGRAM}.cpp. Add header files on the same line if any. – Satō Katsura Nov 10 '17 at 14:30
  • Ah yes, you also need to use $(...) to expand variables, not ${...}. – Satō Katsura Nov 10 '17 at 14:46
3

Here's a quick checklist:

  • use TABs to indent action lines (rm, tar, g++ etc.)
  • use $(FOO) to expand variable FOO instead of ${FOO} or $FOO
  • add dependencies where relevant.

Your Makefile should look something like this (again, lines are indented with TABs, not spaces):

PROGRAM=project
CXXFLAGS=-std=c++17 -Wall -Wextra -Werror -Wpedantic -pedantic-errors
OPTIMIZATION=-O2

.PHONY: build
.PHONY: clean
.PHONY: distrib      

build: $(PROGRAM)

clean:
        rm $(PROGRAM)

distrib:
        tar -czf $(PROGRAM).tar.gz $(PROGRAM).cpp Makefile

$(PROGRAM): $(PROGRAM).cpp
        g++ $(PROGRAM).cpp $(CXXFLAGS) $(OPTIMIZATION) -o $(PROGRAM)
  • At least for GNU make, braces for variable substitution are allowed I think: see Basics of Variable References – steeldriver Nov 10 '17 at 15:08
  • @steeldriver Could be, but using them is a bad idea, since {...} are shell patterns in some contexts. – Satō Katsura Nov 10 '17 at 15:30
  • Your file works fine here with GNU make and pmake on Linux, and with BSD make on OpenBSD (assuming you have a pswdgen.cpp). shrug – Satō Katsura Nov 10 '17 at 16:04
  • I don't require any other file, as I said, it works fine here. I have no idea why it doesn't work for you, sorry. – Satō Katsura Nov 10 '17 at 16:12
2

I have found the answer on StackOverflow.

I quote:

Make is behaving correctly. hello already exists and is not older than the .c files, and therefore there is no more work to be done. There are four scenarios in which make will need to (re)build:

  • If you modify one of your .c files, then it will be newer than hello, and then it will have to rebuild when you run make.
  • If you delete hello, then it will obviously have to rebuild it
  • You can force make to rebuild everything with the -B option. make -B all
  • make clean all will delete hello and require a rebuild. (I suggest you look at @Mat's comment about rm -f *.o hello

I will therefore stop insisting on building always, unless I change the source code file, which was what I incorrectly evaluated as a sort of an error before. If I indeed change the source code, the first time I run make, it builds correctly. And there is obviously no point to build it for a second time, so it is intelligent, man may say.

For those wanting to re-build always under any circumstances, you may define something like:

alias make='make -B'

or more self-explanatory:

alias make='make --always-make'

But beware, it states that it will:

Unconditionally make all targets.

The all targets smells bad to me, so I won't use it. Anyway, I state it here, so we know for future reference.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.