views:

144

answers:

3

I'm working on one of my first projects that will span more than one C file. For my first couple practice programs, I just wrote my code in main.c and compiled using gcc main.c -o main. This worked for me as I was learning.

Now, I'm working on a much bigger project on my own. I want to continue doing compilation on my own (or at least setting it up manually) so I can understand the process. After reading a bit, I decided to make a Makefile.

Note: I'm also using GTK+, so I had to look up how to add that into the compile command.

This is what it looks like after a bit of research:

main:
    gcc -Wall -g main.c -o main `pkg-config --cflags --libs gtk+-2.0`

At first, I was just running "make". Then I was having some problems getting the error "main is up to date" even though I had changed the file.

So I wrote a script:

#!/bin/bash
rm main
make
./main

So I make changes, and then I run this script.

Is this a good/normal system? I want to have scalable system, since my project will grow. I assume I can keep that script and just add dependencies to the makefile and change the main compile command in the makefile. Am I correct?

Thanks in advance.

EDIT:

Thanks for the feedback about how to fix my Makefile.

So is the typical compilation process 1) type make then 2) ./main regardless of how the project is setup or its size (assuming you've written a proper makefile)?

+9  A: 

You need to tell make that main depends on main.c. That way every time you make changes to main.c and then run make, main is regenerated. To delete main you can have a phony target called clean as:

main:main.c
    gcc -Wall -g main.c -o main `pkg-config --cflags --libs gtk+-2.0`

.PHONY: clean
clean:
    rm -f main

Now to delete main you can do : make clean

If you get make: main is up to date. It means you've not modified main.c and hence there is not need for regenerating main. But if you have to force regenerating main even when the dependencies have not been updated you can also use the -B option of make as suggested by Sjoerd in other answer.

codaddict
It's useful to add a line `.PHONY: clean` above the the `clean` target just in case a file named 'clean' (A shell script for instance) ends up in the directory. If that happens, make will see the file and not run the clean target. `PHONY` tells it to not even look.
aaronasterling
@aaronasterling: Thanks for pointing.
codaddict
Very helpful comment, @aaron. Thanks.
mouche
+2  A: 
  • Use make -B or make --always-make to compile even though the target is up to date
  • Append filenames after the colon to check whether these are updated.

Example:

a: a.c
        gcc -o a a.c

a would only be built if a.c is newer than a.

Sjoerd
For a larger project, `make -B` is probably not what people want to use.
Christopher Creutzig
Right. -B would be useful if the modified time of some files are incorrect. This happens for example when you copy something over your output file.
Sjoerd
+2  A: 

I find command-line make to be quite sufficient for my needs, but writing Makefiles by hand becomes quite a chore. As your project grows in complexity, you'll find managing the dependencies by hand to become more and more annoying. What I suggest you do is learn how to do at least one of the following:

  • Write a dependency-tracking Makefile by calling e.g., gcc -M.
  • Learn to use a Makefile generator such as automake or CMake. I personally prefer automake because it is more mature (and doesn't do stupid things like try to put semicolon-separated lists on a command line).
Jack Kelly
+1 for mentioning available Makefile generators. I'll check them out.
mouche