(This smells like a homework assignment.)
First, the error message:
boo.c multiple definition of main
light.o:light.c:first defined here.
It indicates the files you're attempting to link together have multiple copies of a function named
main(), and that is clearly not correct.
You're trying to reuse
light.o, but that would really work only if it had a function other than
main(). Let's call it
light(). You would also need a
boo.c, so that the compiler will know the properties (basically the types of the parameters and the type of return value, if it has any) of the function
light() without yet seeing its source code.
It seems to me that your files fit together somewhat differently from what is expected in the assignment. Your professor may have created a series of assignments that tie together: if you take shortcuts in the previous assignments in the series, the later assignments that reuse code from the previous ones won't work right.
Your professor is attempting to teach you how to arrange your code so that it'll be reusable, and what happens if you fail to do so.
The basic form of Makefile rules is:
<name of target>: <names of files the creation process depends on>
<command(s) to create the target file>
The creation of a
.c file depends not only of the file itself, but also of the
.h files it includes. Generally you can assume that any system include files (those you include with
#include <filename> won't change on you, so you won't need to add those into your Makefile rules. But any
.h files that are part of your project should be included too.
There can also be "virtual targets" that are not actually files. They allow you to do things like
make clean. You can also use a virtual target as a dependency of another target: since a virtual target does not have a real file associated with it, the commands to "create" the virtual target will be executed each time the virtual target is listed as a dependency for something else and that something else needs to be built.
Also, there can be Makefile rules that don't have any commands in them, but list one or more Makefile targets as their dependencies. If there is just one dependency, then the target with no commands acts just as an another name to the target listed as a dependency. If it has multiple dependencies, then the command-less target becomes a way to have multiple Makefile targets built with a single command.
It sounds to me like your professor intended the
build: target to become such a target with no commands of its own. It should just depend on two targets:
- a separate target to build the actual executable
You may wonder how I knew about the contents of
light.o without seeing its source code? Simple - I downloaded your
light.o and then used this command:
$ readelf -s light.o
Symbol table '.symtab' contains 12 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FILE LOCAL DEFAULT ABS light.c
2: 00000000 0 SECTION LOCAL DEFAULT 1
3: 00000000 0 SECTION LOCAL DEFAULT 3
4: 00000000 0 SECTION LOCAL DEFAULT 4
5: 00000000 0 SECTION LOCAL DEFAULT 5
6: 00000000 0 SECTION LOCAL DEFAULT 7
7: 00000000 0 SECTION LOCAL DEFAULT 8
8: 00000000 0 SECTION LOCAL DEFAULT 6
9: 00000000 51 FUNC GLOBAL DEFAULT 1 main
10: 00000000 0 NOTYPE GLOBAL DEFAULT UND puts
11: 00000000 0 NOTYPE GLOBAL DEFAULT UND sound
That tells me
light.o comes from a source file named
light.c, defines a function named
main() and uses functions named
sound(), which are not defined here.
puts() comes from the standard library, but
sound() needs to be defined in some other file that is linked together with this one to make a complete executable.