I'm a beginner and I tried to run a simple project but received
o:main.c:(.text+0xde): undefined reference to `max'collect2.exe: error: ld returned 1 exit status.
I have searched on the Internet for hours but still failed. I really need your help. Thanks
my project :
my first try
I searched on the Internet and realized visual studio code compile one file one time. So I modify my tasks.json as follows
{
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: gcc.exe 生成活动文件",
"command": "C:\\TDM-GCC-64\\bin\\gcc.exe",
"args": [
"-fdiagnostics-color=always",
"-g",
"${file}",
//I modify the following sentences as
"${fileDirname}\\function.c",
"${fileDirname}\\main.c",
"${fileDirname}\\main.h",
"-o",
"${fileDirname}\\${fileBasenameNoExtension}.exe"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "调试器生成的任务。"
}
],
"version": "2.0.0"
}
But I still received
C:/TDM-GCC-64/bin/../lib/gcc/x86_64-w64-mingw32/10.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\DELL\AppData\Local\Temp\ccZp5xjY.o:main.c:(.text+0xde): undefined reference to `max'
collect2.exe: error: ld returned 1 exit status
by the way, my project :
enter image description here
and my settings
enter image description here
2.my second try
I use the MakeFile but still the same error(another project but also a simple one)
MakeFile
sum : main.o sum.o
gcc main.o sum.o -o sum
main.o : main.o sum.h
gcc -c main.c
sum.o : sum.c sum.h
gcc -c sum.c
main.c
#include <stdio.h>
#include "sum.h"
int main()
{
printf("%d\n", sum(8,3));
// printf("1");
return 0;
}
sum.c
#include "sum.h"
int sum(int a, int b)
{
return a + b;
}
sum.h
int sum(int a, int b);
error
enter image description here
so I doubt if I should adjust some settings of vscode
Undefined reference errors happen when the compiler can't find the function that you are referencing. This is usually due to missing/incorrect arguments in one's Makefile.
I see you have a header file in the arguments of tasks.json, which is unnecessary.
EDIT: You did not put '-o' as an argument for main.o and sum.o You also put main.o as a required file for main.o, which wont work.
FIX:
sum: main.o sum.o
gcc -o sum main.o sum.o
main.o: main.c
gcc -o main.o -c main.c
sum.o: sum.c
gcc -o sum.o -c sum.c
Related
When I try to run a C project with multiple modules it by default only compiles the selected module. I tried editing the tasks.json to compile every C and header file in a folder but it just passes the asterisk as an asterisk to my command line.
I edited the tasks.json and tried to build the project with the following output:
Starting build...
/usr/bin/gcc -f diagnostics-color=always -g /home/user/VSCodeProjects/multimodule/main.c /home/user/VSCodeProjects/multimodule/*.c /home/user/VSCodeProjects/multimodule/*.h -o /home/user/VSCodeProjects/multimodule/main
/usr/bin/ld: /tmp/ccgdRy3t.o: in function `main':
/home/user/VSCodeProjects/multimodule/main.c:4: multiple definition of `main'; /tmp/ccW8LBPU.o:/home/user/VSCodeProjects/multimodule/main.c:4: first defined here
collect2: Fehler: ld gab 1 als Ende-Status zurück
Build finished with error(s).
As seen here it just uses the asterisk when running the gcc command instead of addressing all .c and .h files in the folder.
I already searched for the issue and found some issues e.g. this issue on the VSCode GitHub page, but none of the solutions seemed to work. Most of the answers I found don't apply here, as I'm already using version 2.0.0.
Contents of main.c:
#include "test.h"
int main(void)
{
printTest();
return 0;
}
Contents of test.c:
#include "test.h"
#include<stdio.h>
void printTest(){
printf("Test");
}
Contents of test.h:
#if !defined(TEST_H)
#define TEST_H
void printTest();
#endif // TEST_H
Contents of tasks.json:
{
"version": "2.0.0",
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: gcc build active file",
"command": "/usr/bin/gcc",
"args": [
"-fdiagnostics-color=always",
"-g",
"${file}",
"${fileDirname}/*.c",
"${fileDirname}/*.h",
"-o",
"${fileDirname}/${fileBasenameNoExtension}"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "Task generated by Debugger."
}
]
}
Why is my following code not throwing duplicate symbol conflict?
I referred to name mangling, but that seems only when there is difference in parameters. But, here there is not difference in parameters. But, still it does not throw conflict. Why?
good.c
#include <stdio.h>
void printGood() {
printf("I am good");
}
perfect.c
#include <stdio.h>
void printGood() {
printf("I am perfect");
}
A.c
extern void printGood();
void bringGood() {
printGood();
}
B.c
extern void printGood();
void bringPerfect() {
printGood();
}
orchestrator.c
#include <stdio.h>
void bringGood();
void bringPerfect();
int main() {
printf("bringing good");
bringGood();
printf("bringing perfect");
bringPerfect();
return 1;
}
compile line:
gcc -g -c good.c
gcc -g -c perfect.c
gcc -g -c A.c
gcc -g -c B.c
gcc -g -c orchestrator.c
ar rcs libA.a perfect.o A.o
ar rcs libB.a good.o B.o
gcc -o orchestrator orchestrator.o -L. -lA -lB
Why is my following code not throwing duplicate symbol conflict?
The linker looks for undefined symbols in the libraries in the order in which they are specified in the linker line. When it finds a symbol in a library, it uses that definition and stops. It does not check whether that symbol is defined in any of the other libraries specified in the linker line.
In your case, if the linker finds a symbol in A.lib, it stops there. It does not look for the symbol in B.lib.
With your commands, the linker will find function printGood() in object perfect.o in library A. It will not use the function of the same name in good.o from library B. So you effectively link orchestrator.o, A.o, B.o and perfect.o. That's why the executable program prints I am perfect twice and not I am good.
Multiple definition errors are reported only when the object files used in the linker line contain multiple definitions.
You will see the error if you use:
gcc -o orchestrator orchestrator.o a.o b.o perfect.o good.o
There are 4 files:
helper.h //contains the signatures of functions in helper.c
helper.c //implements the signatures in helper.h
file.h //has all the includes needed to run file.h
file.c //this file includes file.h and helper.h
In file.c, I need to use the function that is defined in helper.c in my main function. However, file.c is saying that there is an undefined reference to 'func_found_in_helper.c'
Is this structure correct?
Yes, provided file.c contains
#include "helper.h"
and when building your program you link together helper.o and file.o.
You also need to ensure you compile each of the files with -c so that the compiler only compiles (and not links); do the link later with all the object files.
Here's a working example (I don't actually need a main.h but if you have one of those, #include it from main.c):
main.c
#include <stdio.h>
#include <stdlib.h>
#include "helper.h"
int
main (int argc, char **argv)
{
test ();
exit (0);
}
helper.c
#include <stdio.h>
void
test ()
{
printf ("Hello world\n");
}
helper.h
void test ();
To compile
gcc -Wall -Werror -c -o main.o main.c
gcc -Wall -Werror -c -o helper.o helper.c
To link
gcc -Wall -Werror -o test main.o helper.o
In a Makefile
test: main.o helper.o
gcc -Wall -Werror -o test main.o helper.o
%.o: %.c
gcc -c -Wall -Werror -o $# $<
clean:
rm -f *.o test
To run
$ ./test
Hello world
It's a bit difficult to tell what else might be wrong without the program; my guess is you simply forgot the -c flag to gcc, or forgot to link in helper.o.
undefined reference to 'func_found_in_helper.c'
That's a little odd, as it suggests you have tried to call the function using the '.c' extension, rather than just the function name. Maybe the '.' is just a typo in the question ?
Also a linker will flag an undefined symbol, so it may also be that you have not told the linker where to find helper.o ( the helper.c file compiled to the an object file ). The compiler will start the linker automatically. Did you compile helper.c first ?
I've written a sample program about structs. I wrote 3 source file and a 1 header file. This is the complete source of the program:
main.c:
#include <stdio.h>
#include <stdlib.h>
#include "fish.h"
/*
struct fish
{
const char *name;
const char *species;
int teeth;
int age;
};
*/
/*
void catalog(struct fish f)
{
printf("%s is a %s with %i teeth. He is %i.",
f.name, f.species, f.teeth, f.age);
}
void label(struct fish f)
{
printf("Name: %s\n", f.name);
printf("Species: %s\n", f.species);
printf("Teeth: %i\n", f.teeth);
printf("Age: %i\n", f.age);
}
*/
int main()
{
struct fish snappy = {"Snappy", "Piranha", 69, 4};
catalog(snappy);
label(snappy);
return 0;
}
label.c:
#include "fish.h"
void label(struct fish f)
{
printf("Name: %s\n", f.name);
printf("Species: %s\n", f.species);
printf("Teeth: %i\n", f.teeth);
printf("Age: %i\n", f.age);
}
catalog.c:
#include "fish.h"
void catalog(struct fish f)
{
printf("%s is a %s with %i teeth. He is %i.",
f.name, f.species, f.teeth, f.age);
}
I also wrote a makefile:
fish.o: main.c label.c catalog.c fish.h
gcc -c main.c label.c catalog.c
fish: fish.o
gcc fish.o -o fish
I compile the program in cmd:
make fish
It says:
gcc -c main.c label.c catalog.c
label.c: In function 'label':
label.c:5:5: warning: incompatible implicit declaration of built-in function 'printf' [enabled by default]
catalog.c: In function 'catalog':
catalog.c:5:5: warning: incompatible implicit declaration of built-in function 'printf' [enabled by default]
cc fish.o -o fish
cc.exe: error: fish.o: No such file or directory
cc.exe: fatal error: no input files
compilation terminated.
make: *** [fish] Error 1
If I remove the comments in the main.c and compile only it, It works, But when I broke into small pieces as mentioned above it doesn't work.
What's the wrong?
You'll need to compile all of the .c files together so that you can use your functions defined in label.c and catalog.c in main.c.
You can do this with one step using gcc:
gcc main.c label.c catalog.c -o fish
This will compile each individual source file and produce object files, which will be linked together to produce your executable. The errors that you're seeing occur during the link phase, when gcc is trying to find the catalog and label functions.
gcc main.c -o fish only compiles main.c. main.c does not know about label.c. It only knows that it has to call some function called "label", which is defined elsewhere. Then, the linker looks at all of the generated object files, and 'links' them into a single executable:
gcc main.c -c
gcc label.c -c
gcc catalog.c -c
ld main.o label.o catalog.o -o fish
This is the explicit version of
gcc main.c label.c catalog.c -o fish
This linking rule:
fish: fish.o
gcc fish.o -o fish
is appropriate for building a program fish from a single object file fish.o (which is presumably compiled from fish.c).
You need a different rule:
OBJECTS = main.o label.o catalog.o
fish: ${OBJECTS}
${CC} -o $# ${OBJECTS}
You can add ${CFLAGS} and ${LDFLAGS} and ${LDLIBS} (or ${LDLIBES}) to the link line as appropriate if you want to, but for simple programs, what I showed suffices.
You don't have to tell make how to convert main.c into main.o; it knows that already. It will use a rule such as:
%.o: %.c
${CC} -c ${CFLAGS} $<
to create the .o file from the matching .c file. (This is the GNU Make notation; POSIX make and other classic versions of make use an alternative but loosely equivalent notation .c.o: in place of %.o: %.c.)
If you don't mind compiling all the sources each time, you can use a similar rule:
SOURCES = main.c label.c catalog.c
fish: ${OBJECTS}
${CC} ${CFLAGS} -o $# ${SOURCES}
This time, ${CFLAGS} is practically mandatory (though you'd just about get away without it in your bare-bones sample program).
Note that make is fussy; the command lines such as the ${CC} lines must start with a TAB; blanks will not do.
I am new to g++ and Makefile. I am trying to link this BeBOP SMC library, which is in my lib directory. Under the lib directory are bebop_util and sparse_matrix_converter, both of which have already been built without errors. I see libbebop_util.a, libbebop_util.so under bebop_util and libsparse_matrix_converter.a, libsparse_matrix_converter.so under sparse_matrix_converter. Below is the source:
Makefile
CC=g++
CFLAGS=-c -Wall
test.out: test.o
$(CC) -o test.out -Ilib/sparse_matrix_converter/include -Llib/bebop_util \
-Llib/sparse_matrix_converter -lbebop_util -lsparse_matrix_converter test.o
test.o: test.cpp
$(CC) $(CFLAGS) -Ilib/sparse_matrix_converter/include test.cpp
clean:
rm -f test.o test.out
test.cpp
#include <bebop/smc/sparse_matrix.h>
#include <bebop/smc/sparse_matrix_ops.h>
int main(int argc, const char* argv[])
{
struct sparse_matrix_t* A = load_sparse_matrix (MATRIX_MARKET, "sample_input");
destroy_sparse_matrix(A);
return 0;
}
Output:
login3% make
g++ -c -Wall -Ilib/sparse_matrix_converter/include test.cpp
g++ -o test.out -Ilib/sparse_matrix_converter/include -Llib/bebop_util -Llib/sparse_matrix_converter -lbebop_util -lsparse_matrix_converter test.o
test.o: In function `main':
test.cpp:(.text+0x1a): undefined reference to `load_sparse_matrix(sparse_matrix_file_format_t, char const*)'
test.cpp:(.text+0x27): undefined reference to `destroy_sparse_matrix(sparse_matrix_t*)'
collect2: ld returned 1 exit status
make: *** [test.out] Error 1
Please note that test.cpp depends on sparse_matrix_converter, which depends on bebop_util. Would you please let me know what mistakes I may have made? Thanks.
Tom
The BeBOP code looks to be C code but hasn't add the correct C++ guards. Surround your includes with extern "C" to fix that:
extern "C" {
#include <bebop/smc/sparse_matrix.h>
#include <bebop/smc/sparse_matrix_ops.h>
}