0

In macOS With Visual Studio Code, I tried to compile C source code. (There are 3 parts of source code bellow)

head.h(edited)

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

int add_number(int a, int b);

body.c

#include "head.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

int add_number(int a, int b)
{
    return a + b;
}

main.c

#include "head.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
    int result = add_number (1, 2);
    printf("%d", result);
    return 0;
}

AND

gcc main.c

However, when I pushed F5 to compile this c code, following error occured:

Undefined symbols for architecture x86_64:
  "_add_number", referenced from:
      _main in main-49215f.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Is it link fail messages? Is anyone help me to fix this errors? for example, vsc setting or ...

P.S. my vsc's tasks.json is as bellow:

{
    "version": "2.0.0",
    "tasks": [
        {
            "type": "shell",
            "label": "gcc build",
            "command": "/usr/bin/gcc",
            "args": [
                "-g",
                "-o",
                "${fileDirname}/${fileBasenameNoExtension}",
                "${file}"
            ],
            "options": {
                "cwd": "/usr/bin"
            },
            "problemMatcher": 
            { 
                "fileLocation": [ 
                "relative", "${workspaceRoot}" 
                ], 
                "pattern": 
                { 
                    // The regular expression. 
                    //Example to match: helloWorld.c:5:3: warning: implicit declaration of function 'prinft' 
                    "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning error):\\s+(.*)$", 
                    "file": 1, 
                    "line": 2, 
                    "column": 3, 
                    "severity": 4, 
                    "message": 5 
                }
            },
        "group": "build"
        },
    {
        "label": "execute", 
        "command": "cd ${fileDirname} && ./${fileBasenameNoExtension}", 
        "group": "test"
    }
]
}
stonesteel
  • 25
  • 6
  • 1
    Define the function add_number. What is unclear? – Vlad from Moscow Jan 23 '20 at 08:29
  • You need to add the C source file (or the library) where you define that function to your project. – Gerhardh Jan 23 '20 at 08:31
  • Do you have a definition (implementation) of an `add_number` function somewhere? Where? In another source file? Then you need to build with that source file as well, so they will be linked together into the final executable program. – Some programmer dude Jan 23 '20 at 08:32
  • Thanks guys, for your comments I added my souce codes. There are header file + c body file + main c file. – stonesteel Jan 23 '20 at 08:49
  • 1
    Maybe ``head.c`` should be called ``head.h`` – skratpa Jan 23 '20 at 09:00
  • As I suspected. You need to build both `body.c` and `main.c`, as in `gcc main.c body.c`. – Some programmer dude Jan 23 '20 at 09:01
  • Sorry for my mistake. Head file name is fixed. And I tried to build both of them @Someprogrammerdude thanks! – stonesteel Jan 23 '20 at 09:08
  • The two source file needs to be built *together*, and *at the same time*. As (again) `gcc main.c body.c`. The command you show only builds `main.c`. Please show us the build configuration. – Some programmer dude Jan 23 '20 at 09:13
  • @Someprogrammerdude you mean vsc's biuld configuration?? tasks.json is as bellow: – stonesteel Jan 23 '20 at 09:25
  • That shown configuration will only build the *current* file in the editor, not both files together. I recommend that you start learning about `make` and makefiles, for one way to build multi-file projects. You could also use other tools such as [CMake](https://cmake.org/) (and many others) to auto-generate build configurations and makefiles which can then be handled by your build task. – Some programmer dude Jan 23 '20 at 09:46
  • Does this answer your question? [What is an undefined reference/unresolved external symbol error and how do I fix it?](https://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix) – Ulrich Eckhardt Jan 24 '20 at 08:57

2 Answers2

2

Yes, it's an error from the linker. The reason is that you built your application by means of

gcc main.c

which has a declaration of add_number (from head.h), but no definition because the module / compilation unit which implements that function is missing. A quick fix is to

gcc body.c main.c

emacs drives me nuts
  • 2,785
  • 13
  • 23
  • Thanks a lot. And another question it is. Is it a solution what I found that? >>> head.h `inline int add_number(int a, int b);` head.c `int add_number(int a, int b);` main.c `external add_number(int a, int b);` . <-- exclude other souces. – stonesteel Jan 23 '20 at 16:17
  • I answered this one in a separate answer (https://stackoverflow.com/a/59892960/1556746) because of the length restriction in comments. – emacs drives me nuts Jan 24 '20 at 08:46
1

When you

inline int add_number(int a, int b); // head.h

int add_number(int a, int b) { ... } // head.c

extern int add_number(int a, int b); // main.c

Then the problem is still the same: The code works because there is an implementation of add_number provided you compile like in the other answer, i.e. with

gcc body.c main.c

If you return to your previous compile that did only

gcc main.c

then the implementation of add_number is still missing. If you want to have the function inline, then remove the implementation from head.c and do it in head.h like so:

static inline int add_number (int a, int b)
{
    return a + b;
}

and remove the prototype from main.c (in general it is a bad idea to have external declarations in C-modules, they should go to the headers so that all modules including the header agree on the prototype).

In your special case, after moving add_number from head.c to an inline function in head.h, the C file will be empty so that

gcc main.c

Works as expected.

emacs drives me nuts
  • 2,785
  • 13
  • 23
  • @M.M: Yes. As I wrote in an other comment: "I answered this one in a separate answer (stackoverflow.com/a/59892960/1556746) because of the length restriction in comments." – emacs drives me nuts Jan 27 '20 at 09:03
  • 1
    the Answer should answer what's posted in the Question . It would be better to make a new question (either OP can or you can make one based on their comment) – M.M Jan 27 '20 at 10:36