I'm trying to start developing a program using ncurses on Linux. I can't even get the Hello World example to compile. Here's the code:
#include <curses.h>
int main()
{
initscr();
printw("Hello, world.");
refresh();
getch();
endwin();
return 0;
}
When I attempt to compile, I get:
hello.c:(.text+0x12): undefined reference to `initscr'
For every one of those called functions.
I installed ncurses via apt-get, and also by downloading the sources and compiling, installing, etc.
I have tried #include both curses.h and ncurses.h.
What is going on?
Have you used the -lcurses option when linking?
Including the header files let the code compile (because the compiler knows what the function call looks like from the .h file), but the linker needs the library file to find the actual code to link into your program.
As Greg Hewgill said, you need to pass in -lcurses or -lncurses to link to the curses library.
gcc -o hello hello.c -lncurses
You also probably mean to use initscr() and getch(). Once I make those substitutions, the above compiles for me.
I was having a similar issue and found a solution which helped me, but was slightly different from the other answers posted here. I was trying to use the panels library with curses and my compile command was:
$ gcc -o hello hello.c -lncurses -lpanel
when I read the other answers, I was baffled because I was including the -lncurses flag, but it still was not compiling, and with similar errors to what you were getting:
$ gcc -o hello hello.c -lncurses -lpanel
/usr/lib/gcc/i686-linux-gnu/4.7/../../../../lib/libpanel.a(p_new.o): In function `new_panel':
p_new.c:(.text+0x18): undefined reference to `_nc_panelhook'
I finally found my answer in the tldp:
"To use panels library functions, you have to include panel.h and to link the program with panels library the flag -lpanel should be added along with -lncurses in that order."
So, it appears that order is important when using the compile flags! I tried switching the order:
gcc -o hello hello.c -lpanel -lncurses
This allowed it to compile successfully. I know you already have your answer, so I hope this helps someone.
For anyone having similar problems: -lx arguments, where x is your library, should always follow the source and object files.
Related
I am doing the CS50 class, I have installed the cs50.h.
Based on the instructions I used the following command in terminal to compile my simple program and just want to make sure I understand everything im asking terminal to do.
Line is:
gcc -g hello.c -o hello -lcs50 -lm
I know the following*: gcc =
gcc = gnu compiler for C
-g = generate source-level debug information
Hello.c = name of the file we want to compile
-o = write output file
hello = our output file name
Can anyone tell me what -lcs50 and -lm are? My guess is that its calling on the library lcs50 in (-lcs50) but again this is a guess and would like to know for sure.
Everything works as it should with no issues
Thanks,
Mostly correct.
-o is not required to generate the output file, it's only needed to customize the name. (-o and the following name can only appear together).
-lcs50 means "link the library called cs50", not lcs50. It will try to find this file using several different name patterns, e.g. libcs50.so (on Linux), [lib]cs50.dll[.a] (on Windows), libcs50.a (on both), something else on Mac.
-lm links the standard math library, but I don't think you need to manually specify it on most modern GCC distributions.
Yes. For -lm, it's for the maths library, which is not linked by default. This is explained well at Why do you need an explicit `-lm` compiler option.
I've been trying all day to build and run a simple Ruby inside of C program.
This is a recurring topic here, and none of them are identical to my issue nor have any of the solutions helped me. I have the ruby-dev installed.
The pkg-config command gives this:
$ pkg-config --cflags --libs ruby-2.7
-I/usr/include/x86_64-linux-gnu/ruby-2.7.0 -I/usr/include/ruby-2.7.0 -lruby-2.7 -lm
The compile command gives this:
$ gcc -I/usr/include/x86_64-linux-gnu/ruby-2.7.0 -I/usr/include/ruby-2.7.0 -I. -lruby-2.7 -o hello *.c
/usr/bin/ld: /tmp/ccdKXtnU.o: in function 'main':
hello.c:(.text+0x9): undefined reference to 'ruby_setup'
collect2: error: ld returned 1 exit status
I have tried switching up the order of the includes. I have tried removing one then the other include. I have tried using a Makefile and running it thru make. I have tried breaking the program up into multiple files. I have tried symbolically linking the architecture relative config.h file into the main header file directory.
The only thing I can think of that I haven't tried is putting the name of the ruby object library that needs to be linked in on the command line, but I don't know the name, or location, of that file.
Here's the latest rendition of the program:
#include <stdio.h>
#include <ruby.h>
int main(void)
{
if (ruby_setup()){
puts("Hola!");
}
else{
printf("Hello World\n");
}
return(0);
}
One of the reasons that pkg-config separates cflags and libs is that they go in different places in the command-line (and sometimes different commands).
If you're going to compile and link in one command, it goes like this:
c99 -o hello $(pkg-config --cflags ruby-2.7) *.c $(pkg-config --libs ruby-2.7)
There's a certain logic to this arrangement. First, we tell the compiler where to look for header files (which it must see before it compiles your program), then where to find the program to compile, and finally where to find the libraries which are referred to by the program.
I'm trying to understand C compilation in a little more depth, and so I'm compiling and linking "manually". Here is my code
int main()
{
return 0;
}
And here is what I'm putting into my console (Windows):
gcc -S main.c
as main.s -o main.o
ld main.o
And when trying to link, I get:
main.o:main.c:(text+0x7): undefined reference to `__main'
You didn't link any of the necessary support libraries. C global objects like stdin, stdout, stderr don't just appear from nowhere. Command arguments and environment variables are pulled from the operating system. And on exit all those atexit() functions get called and the return code from main is passed to exit(return_code). Etc.
Check out the commands gcc -dumpspecs, gcc -print-libgcc-file-name. Look at all of the other libraries in that directory. You'll find a lot of those libraries and object files referenced in the output of dumpspecs. I don't know exactly when or how those spec rules are interpreted but you can probably get the idea. And I think the GCC info pages info gcc explain it in detail if you dig in far enough.
info gcc and then press 'g' and then enter 'Spec Files'
And as Jonathan Leffler said, the shortcut is to run gcc with the verbose option: gcc -v and just see what commands it used.
So I've been working on a small app that at some runs runs an application as another user, I'm writing it in C and using the MinGW GCC compiler to compile and link it. My issue is that whenever I try to use the WINAPI function CreateProcessWithLogonW() I get an error that says "Undefined reference to CreateProcessWithLogonW()."
This is in spite of the fact that I link the Advapi32 when I compile it like so,
gcc file.c -lAdvApi32 -o filename
The correct solution is to actually #include the correct mingw32 headers: i.e.
#include <windows.h>
Though the solution that Anthales proposed works, it doesn't scale well.
Try linking with the dll in question directly, like so:
gcc file.c %windir%\system32\advapi32.dll -o filename
When you use the switch -lAdvApi32 instead, you will link with libadvapi32.a from MinGW/lib. Sadly, I can't answer why this won't work; maybe this lib is outdated, or has a completely different meaning
Trying to get getch() working to capture key press.
#include <curses.h>
...
...
WINDOW *w;
char f;
w = initscr();
timeout(3000);
f = getch();
endwin();
is giving me following error:-
undefined reference to `wgetch'
undefined reference to `stdscr'
That's a linking error. Are you linking to the curses library correctly?
There are two steps involved in using a library in C.
You #include the relevant header files from your source files. This is so your code knows what signatures of the library functions are. So you're doing this correctly.
When compiling your code, you need to tell the linker to link to the relevant libraries, so it can find the definition of those functions. This is what you're not doing. Assuming you're using gcc then adding -lncurses to the compile line should do it. Here's an explanation of linking.
The above answers are correct but the format is:
gcc -Wall program.c -o name_of_binary -lncurses
When I did:
gcc -Wall -lncurses program.c...
It did not work so apparently it should be tacked on the end.