Compile time error while running multiple c files - c

#Edited
I am tested on simple two files now that are add.h and add.c.
I made a Makefile in order to compile my program. Here is my makefile.
# Make file for running the project
CC=gcc
CFLAGS= -Wall -g
LDFLAGS = -include
OBJFILES = add.o
LIB = add.h
TARGET = add
all: ${TARGET}
%.o: %.c
${CC} ${CFLAGS} -c -o $# $<
${TARGET}: ${OBJFILES}
${CC} ${CFLAGS} -o ${TARGET} ${OBJFILES}
clean:
rm -f $(OBJFILES) $(TARGET) *~
when I run
make add
I get the following error:
gcc -Wall -g -c -o add.o add.c
gcc -Wall -g -o add add.o
Undefined symbols for architecture x86_64:
"_b", referenced from:
_main in add.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [add] Error 1
here are snippets of my code
add.c
#include <stdio.h>
#include <stdlib.h>
#include "add.h"
int main(void) {
int a = 10, b=20;
add(a, b);
return 0;
}
add.h
#ifndef __ADD_H_
#define __ADD_H_
extern int a,b;
int add(a,b)
{
return a+b;
}
#endif // __ADD_H_

You are lacking a rule to actually build your object files. Right now you only have one to link them all together once they already exist. Try adding:
%.o: %.c
${CC} ${CFLAGS} -c -o $# $<
This tells make how to build object files out of source files.

You are misusing the extern keyword, losing track of your variables and making your code too complicated.
Let's try something very simple:
int main(void) {
int a = 10; b=20;
return 0;
}
This fails. The compiler complains about the statement b=20;, since it has never heard of this b. The semicolon that made this a separate statement was either a typo or a conceptual error caused by declaring extern int b elsewhere. There is no need for extern here, at least not yet.
This:
int main(void) {
int a=10, b=20;
return 0;
}
works.
Now for an add function.
int add(int a, int b)
{
return a+b;
}
int main(void) {
int a = 10, b=20;
add(a,b);
return 0;
}
Note that the a and b in add are not the same variables as the a and b in main. This is crucial; do not proceed until you understand it.
Now add a declaration of the add function:
int add(int a, int b); // <- declaration
int add(int a, int b) // <- definition
{
return a+b;
}
The declaration can be moved into a header file (add.h); the definition belongs in a source file (add.c).
Finally, I would advise you to add a line to the makefile:
add.o: add.h

Aren't you missing an #endif at the end of the last header file queue.h ?
This can be for sure an issue when compiling. Moreover, aren't you missing the main_application.h header file you are then including within the stack.h one for example?
Have a look at this: https://medium.com/#m.muizzsuddin_25037/error-ld-symbol-not-found-for-architecture-x86-64-a5e5b648ffc seems helpful here and point our attention to the header files again!..

Related

Create a static libary and link against it

Hello beautiful people,
i'm trying to create a static libary and to compile against it.
I've allready created a small static libary and a header for it.
Header (math.h):
int add (int a, int b);
int sub (int a, int b);
add.c:
int add (int a, int b) { return a + b; }
sub.c:
int sub (int a, int b) { return a - b; }
I've created my static libary with the following commands:
gcc -c add.c
gcc -c sub.c
ar rcs libmymath.a add.o sub.o
Now my main.c
#include <stdio.h>
#include "math.h"
int main( int argc, char **argv ) {
printf("Result : %d\n", add(5,7) );
return 0;
}
I can compile it with the following command:
gcc main.c libmymath.a -o main
But if i compile it the following way, it fails.
gcc main.c -lmymath -L. -o main
It fails with the following error:
/usr/bin/ld: cannot find -lmymath collect2:
error: ld returned 1 exit status
even a change to
gcc main.c -llibmymath -L. -o main
fails and even if i include the header mymath.h to gcc
Can you help me ?
gcc understood -lmymath by libmath.so or libmath.a already. So when you add lib word in -llibmymath. This case the gcc understood your library name being liblibmymath.a. So, please replace this command
gcc main.c -llibmymath -L. -o main
by
gcc main.c -o main -L. -lmymath
It should work.

C - multiple definition with makefile

I am trying to compile my C program using make and I've come across this problem that I can't quite understand. I have 3 files in the 'calc' folder of my project: add.c sub.c and main.c. I have my Makefile located in the root folder of my project, which has the calc folder that I mentioned in it. This is what my Makefile looks like:
CC=gcc
OBJECTS=obj/main.o obj/add.o obj/sub.o
elf/new: ${OBJECTS}
${CC} -o elf/new ${OBJECTS}
obj/main.o: calc/main.c
${CC} -c -g calc/main.c -o obj/main.o
obj/add.o: calc/add.c
${CC} -c -g calc/add.c -o obj/add.o
obj/sub.o: calc/sub.c
${CC} -c -g calc/sub.c -o obj/sub.o
clean:
rm obj/${OBJECTS} elf/new
When I type 'make' into the terminal to compile, I get an error like this:
gcc -c -g calc/add.c -o obj/add.o
gcc -c -g calc/sub.c -o obj/sub.o
gcc -o elf/new obj/main.o obj/add.o obj/sub.o
obj/add.o: In function `add':
/home/bigger/workspace/test/calc/add.c:1: multiple definition of `add'
obj/main.o:/home/bigger/workspace/test/calc/add.c:1: first defined here
obj/sub.o: In function `sub':
/home/bigger/workspace/test/calc/sub.c:1: multiple definition of `sub'
obj/main.o:/home/bigger/workspace/test/calc/sub.c:1: first defined here
collect2: error: ld returned 1 exit status
makefile:5: recipe for target 'elf/new' failed
make: *** [elf/new] Error 1
And my code are there:
bigger#linux:~/workspace/test> cat calc/add.c
int add(int a, int b){
return a+b;
}
bigger#linux:~/workspace/test> cat calc/sub.c
int sub(int a, int b) {
return a-b;
}
bigger#linux:~/workspace/test> cat calc/main.c
#include <stdio.h>
#include "add.c"
#include "sub.c"
int main(int argc, char* argv[])
{
int a = 10;
int b = 5;
printf("add: %d\nsub:%d\n", a+b, a-b);
return 0;
}
When you include it is making the functions add and sub part of your main.c, then when you make you are linking main (which already has the functions by include) to the add and sub objects which have the same function symbols. You need to include header files with function declarations rather than include function definitions. See http://www.cprogramming.com/declare_vs_define.html for a longer discussion.

Linking files having multiple main function in c

Is it possible to link two C files using makefile which calls each other function but both have a main function of their own.
e.g:
C1.c uses function f() from C2.c.but both have main function and I want the main in C1.c to be considered as main only.
FILES.o=set.o hash.o printnfa.o input.o nfa.o dfa.o terp.o minimize.o defnext.o print_ar.o pairs.o squash.o signon.o print.o lex.o assort.o prnt.o printv.o bintoasc.o ferr.o onferr.o fputstr.o pchar.o driver.o searchenv.o hashadd.o esc.o
PROGRAM= Lexer
INC := -I./debug.h -I./global.h -I./stack.h -I./set.h -I./hash.h
CFLAGS=-DMAIN
all: ${PROGRAM}
${PROGRAM}: ${FILES.o}
${CC} -o $# ${CFLAGS} $(INC) $^ ${LDFLAGS} ${LDLIBS}
Now terp.c has a main and lex.c also has a main. I want only the main for lex.c to be considered.
This will be specific for the linker you use. On Linux you can pass the --allow-multiple-definition flag to the linker in order to use only the first symbol in case of multiple definitions:
${PROGRAM}: ${FILES.o}
${CC} -Xlinker --allow-multiple-definition -o $# ${CFLAGS} $(INC) $^ ${LDFLAGS} ${LDLIBS}
This will omit all errors about duplicate symbols and cause the linker to ignore any redefinitions. Make sure that the object file containing the symbol you wish to use comes before any redefinitions in the list.
The short answer... NO ... it is NOT possible
First of all I would recommend that you refactor the code so that you don't have functions that will be used by many programs in the same file as a main function.
Any way, here is an example on how to use the pre-processor to include only one of the main functions.
We have two source code files both with a main function plus one other function, foo() in file1.c and bar() in file2.c. foo() and baa() are called from both of the main functions.
By changing the MAIN_ALT value in the Makefile we can switch between the main functions:
Use the main function in file1.c:
DEFINES += -DMAIN_ALT=1
Use the main function in file2.c:
DEFINES += -DMAIN_ALT=2
Makefile:
OBJS = file1.o file2.o
DEFINES += -DMAIN_ALT=1
CFLAGS += -Wall $(DEFINES)
prog:$(OBJS)
$(CC) $(CFLAGS) -o $# $^
file1.c:
#include "stdio.h"
#include "def.h"
void foo(){
printf("From foo\n");
}
#if MAIN_ALT == 1
int main(){
printf("Main in file1.c\n");
bar();
foo();
return 0;
}
#endif
file2.c:
#include "stdio.h"
#include "def.h"
void bar(){
printf("From bar\n");
}
#if MAIN_ALT == 2
int main(){
printf("Main in file2.c\n");
bar();
foo();
return 0;
}
#endif
def.h:
#ifndef __DEF_H__
#define __DEF_H__
void foo();
void bar();
#endif

multiple definition in g++?

The code is as follows:
global.h
#ifndef GLOBAL_H
#define GLOBAL_H
#include <stdio.h>
int test;
void test_fun(void);
#endif
global.c
#include "global.h"
void test_fun()
{
printf("%d\n", test);
}
main.c
#include "global.h"
int main(void)
{
test_fun();
test = 1;
printf("%d\n", test);
}
Makefile using gcc compiler
main: main.o global.o
gcc -o main main.o global.o
main.o: main.c global.h
gcc -c main.c
global.o: global.c global.h
gcc -c global.c
clean:
rm -f global.o main.o main
This works well.
However, when I change my code to C++, as follows:
global.h
#ifndef GLOBAL_H
#define GLOBAL_H
#include <iostream>
int test;
void test_fun(void);
#endif
global.cpp
#include "global.h"
void test_fun()
{
cout << test
}
main.cpp
#include "global.h"
int main(void)
{
test_fun();
test = 1;
std::cout << test;
}
Makefile using g++ compiler
main: main.o global.o
g++ -o main main.o global.o
main.o: main.cpp global.h
g++ main.cpp
global.o: global.cpp global.h
g++ global.cpp
clean:
rm -f global.o main.o main
The code above throws the output:
global.o:(.bss+0x0): multiple definition of `test'
What makes the different here?
You've int test; in a header which is included in 2 TUs, hence the error. Both the translation units main.c (or .cpp depending upon the compiler used) and global.c have global.h included, which leads to two definitions of the same variable in two object files, thus the linker error.
Pass test as an arguement to test_fun, thereby avoiding the usage of a global.
If you absolutely have to share the variable between the TUs, then remove int test; from global.h and in main.cpp do
int test;
and in global.cpp do
extern int test;
As an aside, since it's a global variable, test would be initialized to 0 and hence in main when you test_fun();, it should print 0 and then after setting it to 1, it'll print 1.
It's illegal in both C and C++ from a language standpoint, but as for why it works with a C compilers (like GCC) is because they implement a common extension, a legacy cruft.
... You are using a different programming language

undefined reference to function called 'full_adder(BIT A, BIT B, BIT Ci, BIT *Co)'

I am a CS student learning how to program in C. I have 3 files and a Makefile. I have
logic.c logic.h main.c
the top of logic.c is:
#include "logic.h"
//use this function in 4 bit adder
//BIT full_adder(BIT A, BIT B, BIT Ci, BIT *Co);
int adder(int O1, int O2, BIT carryIn, BIT *carryOut){
printf("in adder");
return 0x0;
}
BIT full_adder(BIT A, BIT B, BIT Ci, BIT *Co){
BIT S = FALSE;
//implementation of if else's based on Truth Table <br>
if((A==FALSE)&&(B==FALSE)&&(Ci==FALSE)){
S=FALSE;
*Co = FALSE;
} <br>
return S;
}
the top of main.c is:
#include "logic.h"
BIT full_adder(BIT A, BIT B, BIT Ci, BIT *Co);
in main.c I have my main function, at the bottom of main function I have :
assert((full_adder(FALSE,FALSE,FALSE,&Co)==FALSE) && (Co==FALSE));
adder(FALSE,FALSE,FALSE,&Co2);
return 0;
I am getting the error:
main.o: In function 'main': main.c:158: undefined referenceto 'full_adder'
collect2: ld returned 1 exit status <br>
make: *** [pa3] Error 1 <br>
./bscript: line 3: pa3: command not found
This is homework, but I have spent a good deal of time on this problem and am looking for some help. I have the correct return type for adder, full_adder, and I declare the function in the top of both logic.c and main.c.
The questions that did not answer my question were:
Undefined Reference to a function
"Undefined reference to function" error
Any help is appreciated.
EDIT:
logic.c is getting compiled and it does create a logic.o file.
EDIT: my prof says that I cannot edit logic.h
EDIT: makefile:
# Makefile template for CS 270 (specialized for PA3)
# List of files
C_SRCS = main.c logic.c
C_OBJS = main.o logic.o
C_HEADERS = logic.h
OBJS = ${C_OBJS}
EXE = pa3
# Compiler and loader commands and flags
GCC = gcc
GCC_FLAGS = -g -std=c99 -Wall -O0 -c
LD_FLAGS = -g -std=c99 -Wall -O0
# Target is the executable
pa3 : $(OBJS)
#echo "Linking all object modules ..."
$(GCC) $(LD_FLAGS) $(OBJS) -o $(EXE)
#echo ""
# Recompile C objects if headers change
${C_OBJS}: ${C_HEADERS}
# Compile .c files to .o files
.c.o:
#echo "Compiling each C source file separately ..."
$(GCC) $(GCC_FLAGS) $<
#echo ""
# Clean up the directory
clean:
#echo "Cleaning up project directory ..."
rm -f *.o $(EXE) core a.out
#echo ""
EDIT: I compile my code with the script:
#!/usr/bin/sh
make
pa3
First of all, separate definitions from declarations:
logic.h:
#ifndef _LOGIC_H_
#define _LOGIC_H_
/* Define BIT as before */
int adder(int O1, int O2, BIT carryIn, BIT *carryOut);
BIT full_adder(BIT A, BIT B, BIT Ci, BIT *Co);
#endif
logic.c:
#include <stdio.h>
#include "logic.h"
int adder(int O1, int O2, BIT carryIn, BIT *carryOut){
printf("in adder");
return 0x0;
}
BIT full_adder(BIT A, BIT B, BIT Ci, BIT *Co){
BIT S = FALSE;
//implementation of if else's based on Truth Table
if((A==FALSE)&&(B==FALSE)&&(Ci==FALSE)){
S=FALSE;
*Co = FALSE;
}
return S;
}
main.c:
#include "logic.h"
int main(int argc, char* argv[]) {
/* Do your stuff */
return 0;
}
Now things are where they should be and your logic.h supplies the needed information to the compiler.
Your makefile should not need any fancy stuff with only these three files.
This needs to be done via the makefile:
gcc -c -o main.o main.c
gcc -c -o logic.o logic.c
gcc -o main main.o logic.o
(The logical problems that you have in your full_adder are left for your to solve...)
I have seen linkers not-find/find functions depending on the order of the object files.
In your makefile you may want to try changing the order:
C_OBJS = logic.o main.o
I declare the function in the top of both logic.c and main.c.
The function prototype
BIT full_adder(BIT A, BIT B, BIT Ci, BIT *Co);
should only occur once, in logic.h.
The error you are getting is from the linker.
You may want to just try and compile/link it outside the Makefile:
gcc -c logic.c
gcc -o main main.c logic.o

Resources