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.
Related
I am trying to compile two c files into one executable. In the directory I have only three files; Makefile, main.c and myfunction.c.
Makefile:
CC = gcc
CFLAGS = -Wall -g -O0
LIBS = -lm
SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)
MAIN = main
all: $(MAIN)
#echo Program has been compiled
$(MAIN): $(OBJS)
$(CC) $(CFLAGS) $(INCLUDES) -o $(MAIN) $(OBJS) $(LIBS)
clean:
$(RM) *.o *~ $(MAIN)
main.c:
#include <stdio.h>
void myfunc();
int main (int argc, char *argv[]) {
myfunc();
return 0;
}
myfunction.c:
#include <stdio.h>
void myfunc() { printf("hello world"); }
output after make:
gcc -Wall -g -O0 -c -o main.o main.c
gcc -Wall -g -O0 -c -o myfunction.o myfunction.c
gcc -Wall -g -O0 -o main main.o myfunction.o -lm
Undefined symbols for architecture x86_64:
"_myfunc", referenced from:
_main in main.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: *** [main] Error 1
I had something nearly identical working in the past. I have since clean installed MacOS and updated to Big Sur. Is this the issue or have I overlooked something?
I fixed the issue. I’m not sure what part fixed it, but installed Homebrew and used it to install gcc-10. I also deleted the project and started over.
myfunc would define like file header
myfunc.h
void myfunc()
Declare in another file
myfunc.c
void myfunc() { printf("hello world"); }
Follow the following tutorial
https://developer.gnome.org/anjuta-build-tutorial/stable/build-make.html.en
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
Header lab3p2.h
#ifndef LAB3P2_H
#define LAB3P2_H
long power(int integer1, int integer2);
#endif
Power Function: lab3p2f1.c
#include "lab3p2.h"
#include <stdio.h>
long power(int integer1, int integer2){
int i;
long ret =(long) integer1;
if(integer2 ==0)
{
ret = 1;
}else{
for( i =1 ; i < integer2; i++)
{
ret = ret * integer1;
}
}
return ret;
}
Main: lab3p2.c
#include <stdio.h>
#include "lab3p2.h"
/*Takes in integers from the command line and returns the power function result*/
int main(int argc, char **argv){
int a = atoi( *(argv+1));
int b = atoi( *(argv+2));
int c =atoi( *(argv+3));
long functionResult;
functionResult = power(b,c);
printf("The result of the power function is %ld \n", functionResult);
}
MakeFile: makefile
all: lab3p2
mkprog: lab3p2.o lab3p2f1.o
gcc lab3p2.o lab3p2f1.o -o lab3p2
lab3p2.o: lab3p2.c
gcc -ansi -pedantic -c lab3p2.c
lab3p2f1.o: lab3p2f1.c
gcc -ansi -pedantic -c lab3p2f1.c
clean:
rm -rf *.o lab3p2
Why can the main not access the function?
Is something wrong with how I am compiling?
Any help is greatly appreciated.
You're missing the rule for target lab3p2; i.e. mkprog should be lab3p2:
all: lab3p2
lab3p2: lab3p2.o lab3p2f1.o
gcc lab3p2.o lab3p2f1.o -o lab3p2
lab3p2.o: lab3p2.c
gcc -ansi -pedantic -c lab3p2.c
lab3p2f1.o: lab3p2f1.c
gcc -ansi -pedantic -c lab3p2f1.c
clean:
rm -rf *.o lab3p2
With your current Makefile, when you run make without arguments, you will get the following output:
% make
gcc -ansi -pedantic -c lab3p2.c
cc lab3p2.o -o lab3p2
lab3p2.o: In function `main':
lab3p2.c:(.text+0x6b): undefined reference to `power'
collect2: error: ld returned 1 exit status
<builtin>: recipe for target 'lab3p2' failed
make: *** [lab3p2] Error 1
What happens is that make tries to satisfy the first target (i.e. all); this then requires lab3p2. As make cannot find an explicit rule to build lab3p2 it then tries an implicit one - it knows that one can build foo by linking foo.o into a program; thus it runs the command
cc lab3p2.o -o lab3p2
However, this command doesn't link in the lab3p2f1.o where the definition for power resides.
These implicit rules can be quite handy with simple projects; for example for your project, the Makefile for GNU make could be simply written as
CC = gcc
CFLAGS = -ansi -pedantic
all: lab3p2
lab3p2: lab3p2.o lab3p2f1.o
clean:
rm -rf *.o lab3p2
and make would automatically figure out how to build the .o from corresponding .c and that it should use the compiler from the CC variable, and pass arguments from the CFLAGS.
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.
For some reason I have having an issue compiling a shared object that uses ncurses. Even though I include and link with -lncurses, compiling the .so file fails. Please advise.
#include <string.h>
#include "../include/mod_curse.h" /* Includes ncurses.h and friends */
int OnConsoleCmd(McapiS *API, ArgS *CmdArgs) /* Just ignore these, they're included in mod_curse.h */
{
if(!strcmp(CmdArgs->Data, "help"))
{
API->BPrintf(STD, "\n-- mod_curse.so --\n");
return 0;
}
}
int OnLoad(McapiS *API, va_list Args)
{
initscr(); /* These are the problems */
}
/* Time to clean up and unload the module */
int OnDeload(McapiS *API, va_list Args)
{
endwin();
}
Here is the Makefile:
CC = clang
CFLAGS = -Wall -fPIC
# Object Files
OBJ = mod_curse.o
# Header Files
INCLUDE = include/mod_curse.h
# Main Module
mod_setup.so: $(OBJ) $(INCLUDE)
$(CC) -shared -Wl,-soname,mod_curse.so,--no-undefined -o ../../mod_curse.so -lncurses $(OBJ)
# Source Files
mod_curse.o: src/mod_curse.c $(INCLUDE)
$(CC) $(CFLAGS) -c src/mod_curse.c
clean:
rm $(OBJ)
Here are the errors:
3 warnings generated.
clang -shared -Wl,-soname,mod_curse.so,--no-undefined -o ../../mod_curse.so -lncurses mod_curse.o
mod_curse.o: In function `OnLoad':
src/mod_curse.c:(.text+0x81): undefined reference to `initscr'
mod_curse.o: In function `OnDeload':
src/mod_curse.c:(.text+0xb1): undefined reference to `endwin'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [mod_setup.so] Error 1
I needed to change my make command to have -lncurses appear after $(OBJ).