I have simplified the code to the minimum
#include "frozen.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
int main()
{
char *json = "{ \"a\": 123, \"b\": \"hi\", c: true }";
int value = 0;
json_scanf(json, strlen(json), "{c: %B}", &value);
printf("Hello World\n");
// assert( json != NULL );
printf( "json: %s\n", json );
printf( "json.c: %s\n", value );
// free( json );
return 0;
}
directory structure:
/home/projects/json-test/main.c
/home/projects/json-test/frozen/{contents of https://github.com/cesanta/frozen repo}
What I do:
gcc main.c -Ifrozen -o main
What is being displayed in output:
main /tmp/ccsYWNAP.o: In function `main': main.c:(.text+0x43):
undefined reference to `json_scanf' collect2: error: ld returned 1
exit status
I have very limited knowledge in C, thus I may be missing some steps, so take into account that I literally did not do anything else than written above, maybe I should have. I am used to loosely typed php/js/python kind of languages, but I was reading that just including file does not tell gcc that "you should search for json_scanf inside frozen.h". Should there be some sort of a "glue", or "linking" step I am missing?
UPDATE: Based on responses, I have created this Makefile:
CC = gcc
FLAGS = -std=c99
DEST_DIR = ./bin
DEST_PATH = "$(DEST_DIR)/main"
BUILD_DIR = ./build
all: clean directories json main.o
$(CC) $(BUILD_DIR)/*.o -o $(DEST_PATH) $(FLAGS)
main.o: src/main.c $(BUILD_DIR)/frozen.o
$(CC) src/main.c -c -o $(BUILD_DIR)/main.o $(FLAGS)
json: json.o
json.o: src/frozen/frozen.c src/frozen/frozen.h
$(CC) src/frozen/frozen.c -c -o $(BUILD_DIR)/frozen.o $(FLAGS)
clean:
rm -rf $(BUILD_DIR)
directories:
mkdir -p $(DEST_DIR)/
mkdir -p $(BUILD_DIR)/
And changing #include "frozen.h" to #include "frozen/frozen.h", and running make, creates build/main file that can be successfully ran with ./bin/main command. Thank you!
Ugh. You don't have a mistake. The library developer has some really bad coding practices. Basically, for whatever reason, his header is not sufficient for compilation. If you look at the unit_test.c in the repository of frozen, you will see he's actually including frozen.c instead of frozen.h. If you change your #include "frozen.h" to #include "frozen.c" it will work fine. The other option is to provide the .c file explicitly:
gcc frozen/frozen.c main.c -Ifrozen
Normally, you'd put everything in the header, or require the library to be compiled, as a .a file and then linked when you use it, but he hasn't provided a makefile that does that.
EDIT: You can also compile frozen.o beforehand, but the library's author should've really provided a makefile to do that...
gcc -c frozen.c -o ../frozen.o
cd ..
gcc main.c frozen.o -Ifrozen
Related
I have 3 files:
main.c
#include "fle.h"
int main(int argc, char **argv) {
FILE *fptr = checkFile(argv[1]);
}
fle.c
#include "fle.h"
FILE *checkFile(char *path)
{
...
}
fle.h
#include <stdio.h>
#include <stdlib.h>
#ifndef FLE_H_
#define FLE_H_
FILE *checkFile(char *path);
#endif
My makefile looks like this
CC = gcc
CFLAGS = -g -Wall
TARGET = main
all: $(TARGET)
$(TARGET): $(TARGET).c
$(CC) $(CFLAGS) -o $(TARGET) $(TARGET).c
clean:
$(RM) $(TARGET)
As a minimal (non)working example, it throws an error
/main.c:4: undefined reference to `checkFile'
I'm curious why the checkFile function is surrounded by backtick from the left and apostrophe from the right, it doesn't seem right, but I don't think that's the problem.
I'd appreciate any help regarding this issue, it might be something trivial, but clearly I'm not skilled enough to resolve it myself.
EDIT: I have renamed the names from file to fle everywhere to prevent some collisions with the system libraries, but it didn't change a thing.
While you include the declaration you need to link in the definition. The easiest thing is to change the Makefile as follows:
CC = gcc
CFLAGS = -g -Wall
TARGET = main
all: $(TARGET)
$(TARGET): $(TARGET).c fle.c
clean:
rm -f $(TARGET)
I have a problem including my own library.
I have created some functions in a few archives .c,
after that i have created the header file .h,
but when i try to compile a main.c that call a function that was in my own lib
i must to type gcc ownlib.a main.c -o prog.out and include the lib ownlib.a archive
as a parameter of gcc.
In this case i was trying to call my own strlen() called ft_strlen() function that is in my own lib.
I know when i compile any program using a function that is in a compiler library i only must
include the header in the code for example: #include <string.h>,
but when i call my own function i add #include "ownlib.h".
If i compile the main.c calling system function strlen() i have to compile only the main.c
archive and it works.
When i create a lib with my own ft_strlen() and in the main.c i include my own lib
#include "ownlib.h" it doesn´t work if i do this gcc main.c -o program.out
but it works if i add my lib archive like this gcc main.c ownlib.a -o program.out
I want to know why when i use a system library function i don´t need to compile with the library archive,
for example gcc main.c string.c -o program.out,
only whith the #include <string.h> it works,
and why i must to include my ownlib.a in the compiation gcc libft.a main.c -o program.out.
I don't know if I explained myself well
LIBNAME = ownlib.a
HEADERNAME = ownlib.h
SRCS = ft_strlen.c
OBJS = $(SRCS:.c=.o)
CC = gcc
CFLAGS = -Wall -Wextra -Werror
AR = ar
ARFLAGS = -rcs
$(LIBNAME): $(OBJS) $(HEADERNAME)
#$(AR) $(ARFLAGS) $(LIBNAME) $(OBJS)
all: $(LIBNAME)
clean:
$(RM) $(OBJS)
fclean: clean
$(RM) $(LIBNAME)
re: fclean all
%.o: %.c $(HEADERNAME)
#${CC} ${CFLAGS} -c $< -o ${<:.c=.o}
.PHONY: all clean fclean re
one of the functions is like this:
#include "ownlib.h"
size_t ft_strlen(const char *str)
{
int i;
i = 0;
while (str[i] != '\0')
i++;
return (i);
}
Th main function is:
#include <stdio.h>
#include "ownlib.h"
int main(void)
{
char *str;
str = "How many characters";
printf("%i", ft_strlen(str);
return (0);
}
If i compile gcc main.c -o program.out don´t know what is ft_strlen()
Thanks so much
I have really simple program that checks if the word that user types is palindrome: ( I know that this program could be written much better but let's leave that aside for now )
I have to use readline function to get users input or create my own, but because I don't have enough knowledge to create my own I'm using readline.
#include <stdio.h>
#include <stdlib.h>
#include <readline/readline.h>
#include <readline/history.h>
int IsPalindrome(char* niz)
{
int y=0;
int n=0;
int i;
for(i=1;i<strlen(niz)/2+1;i++)
{
if(niz[i-1]==niz[strlen(niz)-i]){
y++;
}
else{
n++;
}
}
if(n>0){
return 0;
}
else{
return 1;
}
}
int main()
{
char *inpt;
inpt = readline("enter text: ");
if(IsPalindrome(inpt)==1)
{
printf("\nIs palindrome\n");
}
else{
printf("\nNot palindrome\n");
}
return 0;
}
I'm using Code::Blocks and if I click on "build and run" I get following error:
Undefined reference to 'readline'
I have to compile and then run my program from terminal with makefile and this is where I'm lost. I just recently started using Ubuntu so I don't really know much about it and how it works.
Now I have to compile my program with makefile ( all in run ). This is makefile that we can use ( I'm at university and we got this as help ) we just have to change some data ( name of the program, add some flags ):
GCC=gcc
CFLAGS=-c -g
LFLAGS=-lreadline
EXE=main
all: ${EXE}.o
${GCC} ${LFLAGS} ${EXE}.o -o ${EXE}
${EXE}.o: ${EXE}.c
${GCC} ${CFLAGS} ${EXE}.c
clean:
rm -rf *.o
rm -rf ${EXE}
Now because I'm using readline function I added flag -lreadline and added name of my program to EXE=main ( my program is called main.c ) but if I run makefile ( make all ) I get following error:
make all
gcc -lreadline main.o -o main
main.o: In function `main':
/home/yack/Desktop/NPO/Palindrom/Palindrom/main.c:67: undefined reference to `readline'
collect2: error: ld returned 1 exit status
Makefile:7: recipe for target 'all' failed
make: *** [all] Error 1
I installed Readline-6.3 and I was reading on the internet that I have to somehow link readline to tell compiler about it or something but looks like adding -lreadline flag is not enough.
Yesterday I found temporary fix so that I could test if my program works with this command:
gcc main.c -L/usr/local/lib -I/usr/local/include -lreadline -c -g
With this command I managed to create executable file and test if my program works, but today even that doesn't work anymore.
NOTE:
I have to compile my program from makefile, the last command in terminal was just to check if my program works since my makefile didn't work.
What am I doing wrong ?
The order of arguments passed to GCC (and the linker) is relevant.
Your Makefile should have the use of libreadline come before where you actually link libreadline with LFLAGS, like so:
GCC=gcc
CFLAGS=-c -g
LFLAGS=-lreadline
EXE=main
all: ${EXE}.o
${GCC} ${EXE}.o -o ${EXE} ${LFLAGS}
${EXE}.o: ${EXE}.c
${GCC} ${CFLAGS} ${EXE}.c
clean:
rm -rf *.o
rm -rf ${EXE}
In your "temporary fix" you fixed the ordering, and that is why it worked for you.
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 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