-1

I have a bunch of tasks in making a Makefile file, I have these files:

https://raw.githubusercontent.com/systems-cs-pub-ro/uso/master/tema1/boo.c
https://github.com/systems-cs-pub-ro/uso/raw/master/tema1/light.o
https://raw.githubusercontent.com/systems-cs-pub-ro/uso/master/tema1/sound.c 
https://raw.githubusercontent.com/systems-cs-pub-ro/uso/master/tema1/sound.h

And I have to create a Makefile that: "generates an executable exec using light.o and sound.o created when compiled sound.c previously implemented. At receiveing any command make or make build it has to generate the file exec. Add a rule in Makefile run which complies the whole program, if it's necessary, and then runs it. also, add a rule clean which deletes the object files created by you. Also add a ruletemplates which creates intermediate files (boo.s, boo.o) after compiling boo.c".

and this is my makefile

build: light.o sound.o
        gcc light.o sound.o -o exec
sound.o: sound.c
        gcc -c sound.c
templates: boo.c
        gcc -c boo.c
        gcc -S boo.c
run: exec
     ./exec
clean:
      rm -f sound.o boo.o boo.s exec

But it tells me that I don't create the "right" executable file, what am I doing wrong? And I thought that I should add boo.o in the exec file but when I try to do that, I get: boo.c multiple definition of main light.o:light.c:first defined here.

1 Answer 1

2

(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 .h file #included in 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
  • the templates target

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 puts() and 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.

4
  • I understand that light.c has a main function on it's own but how do I solve this? I think i have to link all of the objects togheter light.o boo.o sound.o togheter into the exec but it does not work, so what should I do? Commented Oct 31, 2018 at 10:30
  • You should probably revisit the assignment that produced light.o and redo it so that light.o will only contain the reusable function and not main(). Your main() also needs to call sound() and the function in light.o - just linking the .o files together won't result in a program that displays all three messages. And calling a function that is defined in another .c file usually requires an #include "otherfile.h" in the calling file, so the compiler will know the types of the called functions without seeing the actual function definitions. Commented Oct 31, 2018 at 10:48
  • I can't access light.c, neither can I change boo.c Commented Oct 31, 2018 at 10:49
  • Then you'd better contact the people responsible for helping students in need of advice on your programming course, otherwise you'll have to take a failure from this assignment. If the assignment automation enforces the use of old light.o from a previous assignment, and you solved that assignment in a "wrong" way, you've now sort of painted yourself into a corner you can't escape on your own. Don't worry, you won't be the only one making that mistake. Commented Oct 31, 2018 at 11:53

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.