0

I got 5 files that I'm trying to link using gcc on a raspberry pi, I have gone through a few posts and I cant seem to find the solution to this issue so I though I would ask and see if anyone can see what I'm doing wrong.

Got a make file that I run that looks like this

Mainfile: 
    gcc -c ./Include/func_1.c 
    gcc -c ./Include/func_2.c
    gcc -c ./Include/func_3.c
    gcc -c ./Include/func_4.c 
    gcc -c ./Include/func_5.c 
    gcc -c Mainfile.c 

    gcc -o Mainfile func_1.o func_2.o func_3.o func_4.o func_5.o Mainfile.o
    

Line 1 - 6 seem to work fine and I manage to make the object files but when I try to link them to the Mainfile in line 8 I get the following error

/usr/bin/ld: /tmp/cc5NQuqi.o: in function `main':
Mainfile.c:(.text+0xfc): undefined reference to `func1_1'
/usr/bin/ld: Mainfile.c:(.text+0x104): undefined reference to `func1_2'
/usr/bin/ld: Mainfile.c:(.text+0x10c): undefined reference to `func2_1'
/usr/bin/ld: Mainfile.c:(.text+0x114): undefined reference to `func2_2'
/usr/bin/ld: Mainfile.c:(.text+0x11c): undefined reference to `func3'
/usr/bin/ld: Mainfile.c:(.text+0x124): undefined reference to `func4_1'
/usr/bin/ld: Mainfile.c:(.text+0x12c): undefined reference to `func4_2'
/usr/bin/ld: Mainfile.c:(.text+0x134): undefined reference to `func5'
collect2: error: ld returned 1 exit status
make: *** [makefile:9: Mainfile] Error 1

Cant seem to figure out what is wrong with it.. got my func c files in the include folder along with their headers and I included the headers in the Mainfile and to test if it was the code I included the c files in the headers and then it builds fine.

Anyone have any idea what I'm doing wrong in my make file? First time trying to link so many files and using a make file so advice would be greatly appreciated.

Edit :

my main file looks something like

#include "./Include/func_1.h" 
#include "./Include/func_2.h" 
... 
#include "./Include/func_5.h" 

in main()
{
    func1_1(argument);
    ... 
    func5_1(argument); 

    return 0; 
}

my func_1.h files look something like

#ifndef FUNC_1_H
#define FUNC_1_H

// Argument check, is Host name and Port number default? 
static void func1_1(int argument);

#endif

Then the func_1.c file looks something like

#include "math.h"
#include "func_1.h"

static void func1_1(int argument)
{
    printf(argument + 1);
}
Parko
  • 23
  • 6
  • Note: all the `gcc -c` commands are useless, they create .o files that you aren't using. If you want to use the .o files then tell it to link the .o files instead of the .c files (which make it compile them again) – user253751 Nov 24 '20 at 14:41
  • 1
    And the obvious guess would be that func1_1, 1_2, 2_1, 2_2, 3, 4_1, 4_2 and 5 aren't defined anywhere. Why not? Where is the code where you think you're defining them? – user253751 Nov 24 '20 at 14:41
  • Tried gcc -o Mainfile func_1.o func_2.o func_3.o func_4.o func_5.o Mainfile.o and got the same error, And all the functions are defined in the headers and then used inside the corresponding c files. – Parko Nov 24 '20 at 14:49
  • 1
    Can you create a [mcve]? Cut it down to one or two short source files that exhibit the problem, and post them complete. It sounds like you have some sort of weird confusion between inclusion and linking (e.g. it's not normal to keep `.c` files in an Include directory), but from your description it's hard to tell exactly what you are doing. – Nate Eldredge Nov 24 '20 at 14:52
  • @Parko: If you mean that last comment literally, then that is your problem - you should not *define* your functions in the headers, you should only *declare* them there, and actually *define* them in the .c files. – Nate Eldredge Nov 24 '20 at 14:54
  • (As a side note, your Makefile defeats the purpose of a Makefile in that it will not detect when source files have changed, nor will it recompile only those files that need to be recompiled. As it stands it's just a glorified shell script. You might want to look for some examples that use rules properly.) – Nate Eldredge Nov 24 '20 at 14:56
  • What headers are you referring to? I only see code files, which confusingly seem to be located where I would expect headers. You are not including code files, are you? – Yunnosch Nov 24 '20 at 15:08
  • Does this answer your question? [multiple definition of a function](https://stackoverflow.com/questions/44789458/multiple-definition-of-a-function) – Yunnosch Nov 24 '20 at 15:10
  • The duplicate I proposed might seem to be "reverse", i.e. "multiple" instead of "not". But the methods described in answers (one of them admittedly mine) should solve the part of your problem which is not about the unhelpful makefile, i.e. the part which will become visible when you fixed the makefile according to comments above. – Yunnosch Nov 24 '20 at 15:12
  • @NateEldredge Right now I keep the c files in the include directory instead of a src directory just to try to get it working and I'm declaring my functions in the headers then define them in the corresponding c file. func1.h would have `int func1_1(int something);` then the c file would have `#include "func1.h"` and `int func1_1(int something) { return something +1;}` then func1_1 would be given an argument in Mainfile. Guess I'll also have to look into make files more if I manage to get this building again haha. – Parko Nov 24 '20 at 15:24
  • @Parko: Please, [edit] you question post and add the code into it. This is how Stack Overflow works: all information about the problem should be in the **question post**, not in the comments. See also [ask]. – Tsyvarev Nov 24 '20 at 15:30
  • @Tsyvarev Was working on it, hope I added enough code to explain what I got in the files. Thanks for the information, I'll make sure to post code examples in the future when I'm asking questions. – Parko Nov 24 '20 at 15:42
  • @Parko: Indeed, a lot of time (both yours and other peoples') would have been saved if you had shown code from the beginning, which would have made it immediately clear that the problem was with your use of `static` - a detail which you omitted to mention in your other descriptions. – Nate Eldredge Nov 24 '20 at 16:05

2 Answers2

0
static void func1_1(int argument)

The static keyword causes the function to not be visible from other modules ("translation units") - that is its entire purpose. (See What does "static" mean in C?). In particular the symbol func1_1 will not be made global, and references to this symbol from other modules will not resolve, just as you have seen.

If you want to use the function from other source files, drop the static keyword, both in the declaration and the definition.

Nate Eldredge
  • 48,811
  • 6
  • 54
  • 82
  • Awesome thanks! This fixed the issue, now I just have to look up how to make my makefile better and it will be half decent. Thanks again. How do I mark this as solved by the way? – Parko Nov 24 '20 at 16:15
  • @Parko: You can accept the answer by clicking the check mark to the left of it. – Nate Eldredge Nov 24 '20 at 16:18
0

Why are you declaring your functions static while you want to use them elsewhere than in their own file? Remove all these static qualifiers and things should be a bit better.

But if I may suggest, you should:

  1. Create a Src directory and move all your *.c files in it (yes, Mainfile.c too). Storing them in a directory named Include is weird.

  2. Improve your Makefile. The following is an untested starting point:

     # Tell the compiler about the headers directory
     CFLAGS += -I./Includes
     # Find all C source files
     SRCS := $(wildcard Src/*.c)
     # Compute object file names from source file names
     OBJS := $(patsubst Src/%.c,%.o,$(SRCS))
    
     # Static pattern rule to tell make how to build an
     # object file from its source file
     $(OBJS): %.o: Src/%.c
         $(CC) $(CFLAGS) -c -o $@ $<
    
     # Tell make that `funcXX.o` depends on the `Includes/funcXX.h`
     # such that it rebuilds the former if the latter changes
     func_%.o: Includes/func_%.h
    
     # Tell make that `Mainfile.o` depends on all `Includes/funcXX.h`
     # files such that it rebuilds the former if any of the latter
     # changes
     Mainfile.o: $(wildcard Includes/func_*.h)
    
     # Tell make how to build the executable from the object files
     Mainfile: $(OBJS)
         $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)
    

According what you show it is technically not needed to include funcXX.h in funcXX.c. You need to include them in Mainfile.c only. So, if you want to strip your project remove these include statements and also the:

func_%.o: Includes/func_%.h

rule from the Makefile. But, as noted in the comments, even if it is not strictly needed it can detect mismatches between declarations and definitions. Up to you.

Renaud Pacalet
  • 25,260
  • 3
  • 34
  • 51
  • There is a benefit to including `funcXX.h` into `funcXX.c`: if your declarations and definitions don't match, it will be detected. – Nate Eldredge Nov 24 '20 at 16:08
  • @NateEldredge: You're right. I never do this but yes, it has this benefit. I will update my answer to show how to do this. – Renaud Pacalet Nov 24 '20 at 16:10
  • Thanks, I will try to make the makefile better tomorrow since it is getting a bit late here. Hopefully this will serve as a good base, thanks again. – Parko Nov 24 '20 at 16:31