0
build: source1.c source2.c header.h lib.so
        gcc source1.c source2.c -shared lib.so -o exec.bin
exec.bin: source1.o source.o
source1.o: source1.c
        gcc source1.c -c -o source1.o
source2.o: source2.c
        gcc source2.c -c -o source2.o
clean:
        rm exec.bin source1.o source2.o

I have some instructions to make this Makefile which depends on those 4 source files to compile a program(the program context is irrelevant). It also has to create the object files and compile only if modifications were made. The code above is what I managed to write. I'm new at this and I can't seem to find out the problem is.

deeplow
  • 58
  • 4

2 Answers2

2

Generally, your prerequisites are messed up. You want to declare the prerequisites for the targets that need them. You also want each recipe to build exactly the target that you wrote in the makefile.

For example, you have a rule with a target build, but it creates an output file named exec.bin. That's not right: if the recipe creates a file named exec.bin then the target should be named exec.bin. If you want to have a pretend rule like build then you should declare it to be phony.

Also, you have header.h as a prerequisite of build. Even leaving aside the target name, do you re-link the objects when a header file changes? Not directly. You recompile source files when a header file changes. So the header file should be a prerequisite of the object file, not the executable.

Lastly, your life is much simpler if you leverage the built-in rules. You can rewrite your makefile like this:

CC  = gcc
SRC = source1.c source2.c
LIB = lib.so

OBJ = $(SRC:%.c=%.o)

.PHONY: build
build: exec.bin

exec.bin: $(OBJ)
        $(CC) $(OBJ) $(LIB) -o $@

$(OBJ): header.h

clean:
       rm -f exec.bin $(OBJ)

We aren't defining rules on how to build object files from source files, because make already has built-in rules that will do that for us.

ETA:

If you can't use the built-in rules, then create your own pattern rule. For example:

XOBJ = $(SRC:%.c=%.xo)

%.xo : %.c
        <whatever command>

$(XOBJ): header.h
MadScientist
  • 92,819
  • 9
  • 109
  • 136
  • and what if the obj files have to be ".xo" ? – deeplow Nov 23 '13 at 16:23
  • Then you need to write a rule for that. There are no built-in rules for that. Is that something you need to do? – MadScientist Nov 23 '13 at 17:16
  • 1
    I've changed my answer. It's best if you state all the requirements in the original question, rather than introducing new ones after answers have been given. Also, this is beginning to sound like homework. Your teachers can look at StackOverflow too... – MadScientist Nov 23 '13 at 21:15
0

Here's a tip for writing new Makefiles: don't do it. There are better tools available. For example, CMake is a very usable tool which generates Makefiles from a more legible language (unfortunately not a standard language like Python, but otherwise it's pretty nice).

CMake will automatically generate "clean" and "help" and other targets, plus more features you don't yet know you need (like optimized builds).

Here's something to get you started (name this file CMakeLists.txt):

add_library(foo SHARED source1.c source2.c)
add_executable(exec source3.c)
target_link_libraries(exec foo)
John Zwinck
  • 239,568
  • 38
  • 324
  • 436