-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.

closed as off-topic by muru, Thomas Dickey, schily, JigglyNaga, Toby Speight Oct 31 '18 at 12:37

  • This question does not appear to be about Unix or Linux within the scope defined in the help center.
If this question can be reworded to fit the rules in the help center, please edit the question.

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.

  • 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? – C. Cristi Oct 31 '18 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. – telcoM Oct 31 '18 at 10:48
  • I can't access light.c, neither can I change boo.c – C. Cristi Oct 31 '18 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. – telcoM Oct 31 '18 at 11:53

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