Makefile duplicate symbol for architecture x86_64 error? - c

I am attempting to create a makefile for a simple program which relies on a simple file and a function stored in a c file. Here are the files:
function.c:
int random_fun(int n, int m)
{ int g;
n = n+m;
m=n/3;
g=n*m;
return g;
}
main.c:
#include <stdio.h>
#include "function.c"
int main()
{
int a, b;
printf("Enter numbers a, and b: ");
scanf("%d %d", &a, &b);
printf("Here is ur answer: %d", random_fun(a, b));
return 0;
}
And here is my makefile:
OBJS = main.o function.o
program: $(OBJS)
$(CC) -o $# $?
clean:
rm $(OBJS) program
Whenever I try type make, I get the following error:
duplicate symbol _random_fun in:
main.o
function.o
ld: 1 duplicate symbol for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see
invocation)
make: *** [program] Error 1"
Not sure what I am doing wrong. I can compile each code separately and main works. I was getting the same error for another project I was working on, so I tried with a very simple case involving only these 2 C files, and I get the same issues. I am fairly new to makefiles and what not, so bear with me if I am making a stupid mistake.

You should read about difference between definition and declaration in C.
As you're including function.c into your main.c, your function random_func is defined two times. Linker can't decide for you which one to use, so it errors out.
For your use case you should declare random_func in main.c or additional header file.

This is what happens with your files after preprocessing:
// function.c
int random_fun(int n, int m)
{ int g;
n = n+m;
m=n/3;
g=n*m;
return g;
}
-
// main.c
// contents of stdio.h goes first. I omit it for brevity
int random_fun(int n, int m)
{ int g;
n = n+m;
m=n/3;
g=n*m;
return g;
}
int main()
{
int a, b;
printf("Enter numbers a, and b: ");
scanf("%d %d", &a, &b);
printf("Here is ur answer: %d", random_fun(a, b));
return 0;
}
It means that now you have the same function in two separate files. When you compile both of them the linker sees two valid functions random_fun, it simply does not know which one to use.
There two ways to solve this problem.
Using header
In this case, you would need to create another file, e.g. function.h:
// random.h
int random_fun(int n, int m);
Then, in main.cyou include the header instead of .c:
#include <stdio.h>
#include "function.h" // <-- .h, not .c
int main()
{
int a, b;
printf("Enter numbers a, and b: ");
scanf("%d %d", &a, &b);
printf("Here is ur answer: %d", random_fun(a, b));
return 0;
}
This way you will have only one random_fun function across two files, the linker would not be confused.
Using extern keyword
In your main.c you can define the random_fun function as external. It basically says to a compiler that the function exists somewhere and it will be resolved later by a linker.
#include <stdio.h>
extern int random_fun(int n, int m);
int main()
{
int a, b;
printf("Enter numbers a, and b: ");
scanf("%d %d", &a, &b);
printf("Here is ur answer: %d", random_fun(a, b));
return 0;
}
Again, in this case, you will have just one random_fun function across two files and the linker would not be confused.
As a rule of thumb, I would say you never include .c files unless you absolutely need to. (I can hardly imagine when it may be needed.)

Related

(C) Undefined symbols for architecture arm64

Currently having issues compiling programs that contain multiple files, and working on files outside of main. I suspect it has something to do with the compiler, something to do with the -c command or perhaps something I messed up during installation. Any help wrapping my head around this would be a huge help, I have been asking fellow classmates and checking online but it seems the solution must be a very simple one.
[Running] cd "/Users/shawn/Desktop/c-course/M03/calc/src/" && gcc tempCodeRunnerFile.c -o tempCodeRunnerFile && "/Users/shawn/Desktop/c-course/M03/calc/src/"tempCodeRunnerFile
Undefined symbols for architecture arm64:
"_main", referenced from:
implicit entry/start for main executable
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
[Done] exited with code=1 in 0.254 seconds`your text
This is the source.c file, the one I was meant to alter.
#include "source.h"
#include <math.h>
#include <stdio.h>
void simple_math(void){
float num1;
float num2;
float result;
char operator;
char space = ' ';
scanf("%f", &num1);
scanf("%c", &space);
scanf("%f", &num2);
scanf("%c", &space);
scanf("%c", &operator); //taking user input
switch(operator) {
case '+':
result = num1 + num2;
printf("%.1f", result);
break;
case '-':
result = num1 - num2;
printf("%.1f", result);
case '*':
result = num1 * num2;
printf("%.1f", result);
case '/':
result = num1 / num2;
printf("%.1f", result);
default:
printf("ERR");
}
printf("%.1f", result);
}
The source.h file just contains
void simple_math(void);
The main file contains the following, with the #include tag including the other files.
#include "source.h"
#include <stdio.h>
int main()
{
printf("\n--- Testing calculator ---\n");
simple_math();
return 0;
}
All the files need to be linked and compiled:
gcc file1.c file2.c -o myprogram
And then run the executable:
./myprogram
You may refer to this answer:
How do I link object files in C? Fails with "Undefined symbols for architecture x86_64"

C: undefined reference to 'WinMain#16'

I'm very new to coding and I have been trying to write code to adds two integers. But whenever I try to run it using 'gcc addition.c' in the terminal I always reports an error. I tried reinstalling the compiler i.e Mingw several times but the problem does not gets fixed.
(I m currently doing C language on VS CODE software, when you answer to my issue please use layman language)
#include <stdio.h>
int main() {
int x=1;
int y=2;
int z=0;
z=x+y;
printf("%d", z);
return 0;
}
Windows PowerShell
PS D:\C tutorials> gcc addition.c
c:/mingw/bin/../lib/gcc/mingw32/6.3.0/../../../libmingw32.a(main.o):(.text.startup+0xa0): undefined reference to "WinMain#16' collect.exe: error: ld returned 1 exit status
I added a \n to clean up the printf().
#include <stdio.h>
int main(void) {
int x=1;
int y=2;
int z=0;
z=x+y;
printf("%d\n", z);
return 0;
}
% gcc -o addition addition.c -lc ; ./addition
3
You needed to include the C library, represented by the -lc in the gcc line.

Putting error or warning message (extern variable)

My a.c file:
int sum(int a, int b) {
return a + b;
}
My b.c file:
#include<stdio.h>
extern int sum(int, int);
int main() {
printf ("%d", sum(2, 3));
return 0;
}
gcc a.c b.c -o output, working fine.
Let say tomorrow, I change the definition of "a.c file" sum function by increasing the argument to three. Like this,
int sum(int a, int b, int c) {
return a + b + c;
}
But forget to change the usage in b.c file (means I'm still using with two variable)
gcc a.c b.c -o output (doesn't give compilation error or warning mssg, printf gives wrong answer, obviously)
Now consider I'm working in huge set of c file and I cannot make new header file, because it will create unnecessary dependency problem which may take huge time to resolve.
What is the best way to throw error or even warning message in case the extern original definition is changed in terms of argument ?
Regards
What is the best way to throw error or even warning message in case the extern original definition is changed in terms of argument?
Neither compiler nor linker will object to that. You'll just find out at runtime (if you are lucky) when your program stops working.
If this was C++ then name mangling would allow the linker to reject such mal-formed programs. However, for C the linker only needs to find a symbol with the right name. It has no means of checking the signature.
Using header files is the accepted way to get the compiler to make sure you do things right. Repeating function declarations over and over throughout your program is usually a very bad idea. Whatever downsides you perceive to using header files pale into insignificance when compared to your proposed approach.
If you simply won't use header files, then you'll just have to always be right!
Normally editors like (SourceInsight,Sublime) have the options to browse the symbols. By using this option you can easily find function calls and prototype.
Compiler never generate warnings or error for your problem.Self contained header files are best option to avoid this situation.
The best thing to do is try to avoid "extern" and include the header file for sum(). Using header files and prototyping your functions will help the compiler catch these issues.
test.c:
#include <stdio.h>
#include "math.h"
int main(void)
{
printf("%d", sum(2, 3));
return 0;
}
math.h:
int sum(int a, int b, int c)
{
return (a + b + c);
}
output:
~]$ gcc test.c -o test
test.c: In function ‘main’:
test.c:6:5: error: too few arguments to function ‘sum’
printf("%d", sum(2, 3));
^
In file included from test.c:2:0:
math.h:1:5: note: declared here
int sum(int a, int b, int c)

Share global variable between .c file

Hi I just wondering how to Share global variable between .c file.
I try to add follow code, but still get error.
test.c file
#include <stdio.h>
int max = 50;
int main()
{
printf("max %d", max); // result max 50
}
pass.h
extern int max;
passed.c
#include <stdio.h>
#include "pass.h"
max;
int main()
{
printf("pass %d \n", max);
return 0;
}
But when I compile passed.c I get follow error
Undefined symbols for architecture x86_64:
"_max", referenced from:
_main in passed-iOMugx.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Can anyone help? Thank you so much.
You can declare the variable in a header file, e.g. let's say in declareGlobal.h-
//declareGlobal.h
extern int max;
Then you should define the variable in one and only file, e.g. let's say, test.c. Remember to include the header file where the variable was declared, e.g. in this case, declareGlobal.c
//test.c
#include "declareGlobal.h"
int max = 50;
You can then use this variable in any file- just remember to include the header file where it's declared (i.e. declareGlobal.c), for example, if you want to use it in passed.c, you can do the following:
//passed.c
#include <stdio.h>
#include "declareGlobal.h"
#include "test.c"
int main()
{
printf("pass %d \n", max);
return 0;
}
The problem is that you have two programs, and data (like variables) can not be shared that simply between programs.
You might want to read about shared memory and other inter-process communication methods.
If on the other hand you only want to have one program, and use a variable defined in another file, you still are doing it wrong. You can only have one main function in a single program, so remove the main function from one of the source files. Also in pass.c the expression max; does nothing and you don't need it.
Then pass both files when compiling, like
$ clang -Wall -g test.c pass.c -o my_program
After the above command, you will (hopefully) have an executable program named my_program.

"undefined reference to 'cblas_ddot'" when using cblas library

I was testing the cblas ddot, and the code I used is from the link and I fixed it as
#include <stdio.h>
#include <stdlib.h>
#include <cblas.h>
int main()
{
double m[10],n[10];
int i;
int result;
printf("Enter the elements into first vector.\n");
for(i=0;i<10;i++)
scanf("%lf",&m[i]);
printf("Enter the elements into second vector.\n");
for(i=0;i<10;i++)
scanf("%lf",&n[i]);
result = cblas_ddot(10, m, 1, n, 1);
printf("The result is %d\n",result);
return 0;
}
Then when I compiled it, it turned out to be:
/tmp/ccJIpqKH.o: In function `main':
test.c:(.text+0xbc): undefined reference to `cblas_ddot'
collect2: ld returned 1 exit status
I checked the cblas file in /usr/include/cblas.h, and noticed there is
double cblas_ddot(const int N, const double *X, const int incX,
const double *Y, const int incY);
I don't know where it is going wrong. Why does the compiler said the "cblas_ddot" is undefined reference?
You can't just include the header - that only tells the compiler that the functions exist somewhere. You need to tell the linker to link against the cblas library.
Assuming you have a libcblas.a file, you can tell GCC about it with -lcblas.
The web site for GNU Scientific Library tells you how to do this:
2.2 Compiling and Linking
My problem was just solved. The reason is that I made a mistake when inputed the link path. Thanks for Jonathon Reinhart's answers, they are really helpful when learning how to code in linux.
The compile commands are:
gcc -c test.c
gcc -L/usr/lib64 test.o -lgsl -lgslcblas -lm
Where "/usr/lib64" is the correct link path.

Resources