I've been starting a small project in C with the purpose to create a library of my own to use single linked lists without hassle.
I use three files for the project: the main file (main.c), a header (with a header guard, sll.h) and it's declaration + definition file "sll.c"
However, I ran into three errors when trying to compile the C program in this state:
FILE 1 main.c
#include <stdio.h>
#include <stdlib.h>
#include "sll.h"
int main(){
return 0;
}
FILE 2 sll.h
#ifndef SLL_H_11_14_2019
#define SLL_H_11_14_2019
typedef struct Node {
int data;
struct Node * next;
} Node;
typedef struct List {
int size;
Node * head;
} List;
List createSLList();
void appendSLList(List list);
int searchSLList(List list, int key);
void popSLList(List list);
void removekeySLList(List list, int key);
void removeSLList(List list, int index);
void deleteList(List list);
#endif
FILE 3 sll.c
#include <stdio.h>
#include <stdlib.h>
#include "sll.h"
/* Contains source code for sll.h. Should not be used standalone without sll.h to avoid duplication issues. */
/* This library provides definition for functions to create and manipulate a single linked list. */
List createSLList(){
List list;
list.size = 0;
list.head = NULL;
return list;
}
void appendSLList(List list);
int searchSLList(List list, int key);
void popSLList(List list);
void removekeySLList(List list, int key);
void removeSLList(List list, int index);
void deleteList(List list);
The errors:
sll.o In function `createSLList':
7 sll.c multiple definition of `createSLList'
main.o sll.c:17: first defined here
collect2.exe [Error] ld returned 1 exit status
25 Makefile.win recipe for target 'sll.exe' failed
I'm honestly baffled; createSLList is only defined once. I looked and (obviously) stdio.h and stdlib.h should not be throwing any errors, considering they've got header guards of their own, so what's the catch?
Edit: Compiled with GCC 4.9.2 64-bit Debug
with Language Standard C99 & all warnings enabled + making them fatal errors.
Edit2: In hindsight, I did #include "sll.h". Edited and posted the new code, yet the error remains. Posted makefile.win too.
//makefile.win
# Project: single linked list
# Makefile created by Dev-C++ 5.11
CPP = g++.exe -D__DEBUG__
CC = gcc.exe -D__DEBUG__
WINDRES = windres.exe
OBJ = main.o sll.o
LINKOBJ = main.o sll.o
LIBS = -L"C:/Program Files (x86)/Dev-Cpp/MinGW64/lib" -L"C:/Program Files (x86)/Dev-Cpp/MinGW64/x86_64-w64-mingw32/lib" -static-libgcc -g3
INCS = -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/x86_64-w64-mingw32/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/lib/gcc/x86_64-w64-mingw32/4.9.2/include"
CXXINCS = -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/x86_64-w64-mingw32/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/lib/gcc/x86_64-w64-mingw32/4.9.2/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/lib/gcc/x86_64-w64-mingw32/4.9.2/include/c++"
BIN = sll.exe
CXXFLAGS = $(CXXINCS) -std=c99 -Wall -Werror -g3
CFLAGS = $(INCS) -std=c99 -Wall -Werror -g3
RM = rm.exe -f
.PHONY: all all-before all-after clean clean-custom
all: all-before $(BIN) all-after
clean: clean-custom
${RM} $(OBJ) $(BIN)
$(BIN): $(OBJ)
$(CC) $(LINKOBJ) -o $(BIN) $(LIBS) //ERROR IS HERE
main.o: main.c
$(CC) -c main.c -o main.o $(CFLAGS)
sll.o: sll.c
$(CC) -c sll.c -o sll.o $(CFLAGS)
The problem was Dev-C++ initially compiled my program as a C++ program, even though I had "picked" C as the default language. As a result, this had destructive consequences.
For anyone facing similar problems, what worked for me was deleting all the files created by the compiler and restarting the IDE. Please note that you should manually set what compiler to use under "project settings".
Related
I am forced to link two version of the same third party dynamic library (Linux .so, C language) into the same executable to support old and new functionality in the same process. Having two executables or remote services are undesirable.
I made the assumption that this must be a doable task. I tried to experiment with the naive approach of creating 2 proxy dynamic libraries each linked against one of the real libraries and have function renamed.
Unfortunately, this attempt failed – both new functions call the same target function.
I still want to believe that the problem is in the lack of my knowledge as there are plenty of compiler and linker ( gcc and ld) options.
I will appreciate any help. I also look forward to using dlopen/dlsym, but first want to check if the original approach can work.
Here is the sample code
/* ./old/b.c */
#include <stdio.h>
int b (int i)
{
printf("module OLD %d\n",i);
return 0;
}
/* ./old/Makefile */
libold.so: b.c
gcc -c -g b.c
gcc -shared b.o -o $#
/* ./new/b.c */
#include <stdio.h>
int b (int i)
{
printf("module new %d\n",i);
return 0;
}
/* ./new/Makefile */
libnew.so: b.c
gcc -c -g b.c
gcc -shared b.o -o $#
/* ./a1.c */
#include <stdio.h>
int b(int);
void call_new(void)
{
printf("will call new 1\n");
b(1);
printf("called new 1\n");
}
/* ./a2.c */
#include <stdio.h>
int b(int);
void call_old(void)
{
printf("will call old 2\n");
b(2);
printf("called old 2\n");
}
/* ./main.c */
#include <stdio.h>
int call_new(void);
int call_old(void);
int main()
{
call_new();
call_old();
return 0;
}
/* ./Makefile */
.PHONY: DEPSNEW DEPSOLD clean
main: liba1.so liba2.so main.c
gcc -c main.c
gcc -o main main.o -rdynamic -Wl,-rpath=new -Wl,-rpath=old -L . -la1 -la2
DEPSNEW:
make -C new
DEPSOLD:
make -C old
liba1.so: DEPSNEW a1.c
gcc -c -fpic a1.c
gcc -shared a1.o -L new -lnew -o liba1.so
liba2.so: DEPSOLD a2.c
gcc -c -fpic a2.c
gcc -shared a2.o -L old -lold -o liba2.so
clean:
find -name "*.so" -o -name "*.o" -o -name main | xargs -r rm
/* ./run.sh */
#/bin/sh
LD_LIBRARY_PATH=new:old:. main
The result is not that I want - function from "new" library is called twice
will call new 1
module new 1
called new 1
will call old 2
module new 2
called old 2
In this case, you can not control the automatic loading of the dynamic library in order to assure which library will be loaded for the depending libraries. What you can do, is to use one of the libraries (the new one) for the dynamic linker and to link the second library manually as follows:
Add function to dynamically load and link the function from the library.
a2.c
#include <stdio.h>
#include <dlfcn.h>
static int (*old_b)(int);
void init_old(void) {
void* lib=dlopen("./old/libold.so", RTLD_LOCAL | RTLD_LAZY);
old_b=dlsym(lib,"b");
}
void call_old(void)
{
printf("will call old 2\n");
old_b(2);
printf("called old 2\n");
}
call the initialization function
main.c
#include <stdio.h>
void init_old(void);
int call_new(void);
int call_old(void);
int main()
{
init_old();
call_new();
call_old();
return 0;
}
Modify the linker options to add the dynamic loading library -ldl
liba2.so: DEPSOLD a2.c
gcc -c -fpic a2.c
gcc -shared a2.o -L old -lold -ldl -o liba2.so
After this modification
~$ ./run.sh
will call new 1
module new 1
called new 1
will call old 2
module OLD 2
called old 2
#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!..
How would I set up a structure such that I have methods in
helper.c
main.c
main.h
... how can I include helper.c in my main.c and use the methods built in helper.c?
I am running makefile as:
all:
gcc -o main main.c
gcc -o helper helper.c
clean:
rm -f main
rm -f helper
I understand I need a helper.h, but how do I properly set that up.. say I'd like my helper file to look like this:
struct Node{
struct Node* nxt;
int x;
};
int isThere(struct Node *head, int value){
if(head==NULL){
return 0;
}
struct Node *tmp=head;
while(tmp!=NULL){
if(tmp->x==value){
return 1;
}
tmp=tmp->nxt;
}
return 0;
}
struct Node *nodeInsert(struct Node *head, int value){
if(head==NULL){
head=malloc(sizeof(struct Node));
head->x=value;
head->nxt=NULL;
printf("inserted\n");
return head;
} else if(head!=NULL && isThere(head,value)==1){
printf("duplicate\n");
return head;
} else{
struct Node *new;
struct Node *tmp=head;
while(tmp->nxt!=NULL){
tmp=tmp->nxt;
}
new=malloc(sizeof(struct Node));
new->x=value;
tmp->nxt=new;
new->nxt=NULL;
printf("inserted\n");
return head;
}}
I think the problem is that you miss understanding compiling and linking in C.
There is a lot of source to explain this, here is a good one : http://courses.cms.caltech.edu/cs11/material/c/mike/misc/compiling_c.html
what you should do is compile all of them to object files then link them together.
you can do this in single command
gcc -o executable main.c helper.c
or compile each one first then link them together
gcc -c main.c
gcc -c helper.c
gcc -o executable main.o helper.o
Make sure you write prototypes for all functions of helper.c in helper.h
and include helper.h at the beginning of main.c
gcc -o helper helper.c would attempt both compilation and linking, but since helper.c
doesn't define a main(), it won't link.
What you want to do is simply compile main.c and helper.c separately into object files:
gcc -c main.c #-o main.o (the -o main.o part is implied if missing)
gcc -c helper.c #-o helper.o
and then link the resulting object files into the final executable.
gcc -o main main.o helper.o
As for the header: helper.c defines struct Node and methods nodeInsert and isThere. In order to use these properly, main needs their prototypes, so the standard way to provide them to it would be to define a helper.h header:
#ifndef HELPER_H
#define HELPER_H /*header guard to protect against double inclusion*/
struct Node{
struct Node* nxt;
int x;
};
int isThere(struct Node *head, int value);
struct Node *nodeInsert(struct Node *head, int value);
#endif
and include it at the top of main.c:
#include "helper.h"
//...
(You can also include it in helper.c. That should allow the compiler to help you catch possible erroneous
inconsistencies.)
Change your makefile so that all the .c files that are supposed to be in the binary are referenced:
all:
gcc -o main main.c helper.c
Also, your code in main.c needs to know the method declarations in helper.c, which is why the struct declarations and the function declarations for the code in helper.c should be in main.h (or in helper.h and included in main.h)
I would like to add to #John Weldon answer that you can include your helper.c in your main.c directly and declare functions in it as static like this example:
// main.c
#include "helper.c"
int main(void)
{
HelloWorld();
return 0;
}
// helper.c
#include <stdio.h>
static void HelloWorld(void)
{
puts("Hello World!!!");
}
And in your Makefile you compile helper.c and main.c together like:
gcc -o main main.c helper.c
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.
I have two .c files that both have mains. One of the files has a function that I would like to use in the other main. Is it possible to reference this other function without copying and pasting it into the other .c file?
No you don't need to copy and paste, suppose you have this
program-one.c
First program.
#include "common.h" /* This should be implemented */
int main(void)
{
do_program_one_stuff();
common_function();
return 0;
}
program-two.c
Second program.
#include "common.h" /* This should be implemented */
int main(void)
{
do_program_two_stuff();
common_function();
return 0;
}
You need a third .c file and a .h file, like this
common.c
Common Functions Implementation.
void common_function()
{
/* Do it here */
}
common.h
Common Functions Header.
void common_function();
You now can compile a single binary for each program consisting of two files, the program specific .c file and common.c.
The right way to do it is to have a Makefile and generate object code first, and then link the object files togeather, thus compiling each file only once.
Makefile
This is a GNU make Makefile using gcc as the compiler.
CC = gcc
CFLAGS = -Wall -Wextra -Werror -g3 -O0 # enable debug symbols and warnings
LDFLAGS = # linker flags here ...
OBJ = common.o program-one.o program-two.o
all:
$(CC) $(LDFLAGS) common.o program-one.o -o program-one
$(CC) $(LDFLAGS) common.o program-two.o -o program-two
%.o: %.c
$(CC) $(CFLAGS) -c $<
clean:
#rm -fv *.o program-one program-two
EDIT: in response to your comment I would suggest the following
#define main ignore /* Or whatever name you want */
#include "the-student-implementation.c"
#undef main
int main(void)
{
/* This would be your `main()' */
return 0;
}
The best solution is what iharob suggested, but if for some reason that isn't possible, you could surround the main() in the file containing the common function with #ifdef USE_MAIN, then only define the USE_MAIN identifier in the command to build that project. When you build the other project that doesn't have USE_MAIN defined, the preprocessor will cause the second main() to be skipped, so the compiler won't be confused.
But unless this is really needed, I highly recommend splitting this into three files: main1.c, main2.c, and common.c/common.h