In last blog I explained how to compile application with Gnu C Compiler as knows as ‘gcc‘. In blog I try to explain what are RPM devel packages and how to use them in C-application with ‘gcc‘.
RPM Package Manager
RPM started as Redhat Package Manager but now it seems to get along with nesting acronym RPM Package Manager (Like GNU is acronym from GNU’s Not Unix) so it doesn’t mean anything special. There is neat how to install RPM in openSUSE-guide and complete Wikipedia article about RPM.
RPM Packages what are they
One can think RPM packages are just like Zip archives or tar-balls with binaries inside them so if you install rpm package it just knows where to copy application information to get this particular application running. Source RPM packages contains ways to build particular application to binary form so end user can make use of it. So simple is that. If it’s not you can read more from openSUSE wiki.
RPM packages are named after format ‘project_name-version-build-arch‘ they can be more difficult when we are dealing with C-libraries example GUI library GTK3 is named after scheme ‘liblibname-libversion-apiversion-version-build‘. Most of the libraries tends to follow that naming scheme.
It just get fuzzier
There is possibility to RPM have subpackages like ‘project_name-subname-version-build-arch‘. There is three should know subpackages that are commonly available (most cases not)
- docs – contains doumentation
- lang – contains localization
- devel – hmm.. this one is little bit trickier
RPM devel packages
Devel package contains files needed develop your/new application with library. If we use
rpm -ql libSDL_image-devel
we see as output what pacakge ‘libSDL_image-devel’ really contains
/usr/include/SDL /usr/include/SDL/SDL_image.h /usr/lib64/libSDL_image.so /usr/lib64/pkgconfig/SDL_image.pc
what are all these files? There is one C-header file at least ‘/usr/include/SDL/SDL_image.h‘. Then there seems to be ‘/usr/lib64/libSDL_image.so‘ symlink to C-library and ‘/usr/lib64/pkgconfig/SDL_image.pc‘ which I’ll get back in future blogs (since it make ones life easier). but what is ‘/usr/lib64/libSDL_image.so’ file? Like said it’s symbolic link to C-library. you can check where it locates with (I assume you are using AMD64/x86_64 openSUSE if you are using something else like i586 use ‘/usr/lib‘ instead of ‘/usr/lib64‘
readlink /usr/lib64/libSDL_image.so
in my case it prints ‘libSDL_image-1.2.so.0.8.4‘.
Shared objects
Microsoft Windows operating system have DLL and Apple Mac OS X have dylib. In linux world they are Shared Objects (.so files). Shared Objects contains all the library functions in binary format. So you can link your applications with it (If you have headers).
GCC Linker (ld) seeks only for ‘.so‘ ending file but in these days most of the Shared Objects follow scheme with number file-ending which is ‘so.API.MINOR.PATCH’. Every API numbering (greater that 0) should be compatible with each other. If new functions are in place older stays API/ABI compatible. It should be like that so ‘so.1.0.0‘ is normally first stable. version ‘so.1.0.1‘ there is bug fixed and ‘so.1.1.0‘ there is new functions declared. It can be like that or project has adapted it’s own system.
How to use these files
I wondered what would be easy enough example with this? I Thought NCurses would do just fine. So copy text from Paul Griffiths Ncurses Hello World example or below to file ‘ncurseshelloworld.c‘:
/* CURHELL2.C ========== (c) Copyright Paul Griffiths 1999 Email: mail@paulgriffiths.net "Hello, world!", ncurses style (now in colour!) */ #include <stdlib.h> #include <stdio.h> #include <unistd.h> /* for sleep() */ #include <curses.h> int main(void) { WINDOW * mainwin; /* Initialize ncurses */ if ( (mainwin = initscr()) == NULL ) { fprintf(stderr, "Error initialising ncurses.\n"); exit(EXIT_FAILURE); } start_color(); /* Initialize colours */ /* Print message */ mvaddstr(6, 32, " Hello, world! "); /* Make sure we are able to do what we want. If has_colors() returns FALSE, we cannot use colours. COLOR_PAIRS is the maximum number of colour pairs we can use. We use 13 in this program, so we check to make sure we have enough available. */ if ( has_colors() && COLOR_PAIRS >= 13 ) { int n = 1; /* Initialize a bunch of colour pairs, where: init_pair(pair number, foreground, background); specifies the pair. */ init_pair(1, COLOR_RED, COLOR_BLACK); init_pair(2, COLOR_GREEN, COLOR_BLACK); init_pair(3, COLOR_YELLOW, COLOR_BLACK); init_pair(4, COLOR_BLUE, COLOR_BLACK); init_pair(5, COLOR_MAGENTA, COLOR_BLACK); init_pair(6, COLOR_CYAN, COLOR_BLACK); init_pair(7, COLOR_BLUE, COLOR_WHITE); init_pair(8, COLOR_WHITE, COLOR_RED); init_pair(9, COLOR_BLACK, COLOR_GREEN); init_pair(10, COLOR_BLUE, COLOR_YELLOW); init_pair(11, COLOR_WHITE, COLOR_BLUE); init_pair(12, COLOR_WHITE, COLOR_MAGENTA); init_pair(13, COLOR_BLACK, COLOR_CYAN); /* Use them to print of bunch of "Hello, world!"s */ while ( n <= 13 ) { color_set(n, NULL); mvaddstr(6 + n, 32, " Hello, world! "); n++; } } /* Refresh the screen and sleep for a while to get the full screen effect */ refresh(); sleep(3); /* Clean up after ourselves */ delwin(mainwin); endwin(); refresh(); return EXIT_SUCCESS; }
if you just try to compile it with
gcc -o ncurseshelloworld ncurseshelloworld.c /tmp/cc7CD9vN.o: In function `main': ncurseshelloworld.c:(.text+0x9): undefined reference to `initscr' ncurseshelloworld.c:(.text+0x41): undefined reference to `start_color' ncurseshelloworld.c:(.text+0x48): undefined reference to `stdscr' ncurseshelloworld.c:(.text+0x5a): undefined reference to `wmove' ncurseshelloworld.c:(.text+0x66): undefined reference to `stdscr' ncurseshelloworld.c:(.text+0x78): undefined reference to `waddnstr' ncurseshelloworld.c:(.text+0x7d): undefined reference to `has_colors' ncurseshelloworld.c:(.text+0x8b): undefined reference to `COLOR_PAIRS' ncurseshelloworld.c:(.text+0xaf): undefined reference to `init_pair' ncurseshelloworld.c:(.text+0xc3): undefined reference to `init_pair' ncurseshelloworld.c:(.text+0xd7): undefined reference to `init_pair' ncurseshelloworld.c:(.text+0xeb): undefined reference to `init_pair' ncurseshelloworld.c:(.text+0xff): undefined reference to `init_pair' /tmp/cc7CD9vN.o:ncurseshelloworld.c:(.text+0x113): more undefined references to `init_pair' follow /tmp/cc7CD9vN.o: In function `main': ncurseshelloworld.c:(.text+0x1ae): undefined reference to `stdscr' ncurseshelloworld.c:(.text+0x1bd): undefined reference to `wcolor_set' ncurseshelloworld.c:(.text+0x1ca): undefined reference to `stdscr' ncurseshelloworld.c:(.text+0x1d9): undefined reference to `wmove' ncurseshelloworld.c:(.text+0x1e5): undefined reference to `stdscr' ncurseshelloworld.c:(.text+0x1f7): undefined reference to `waddnstr' ncurseshelloworld.c:(.text+0x208): undefined reference to `stdscr' ncurseshelloworld.c:(.text+0x210): undefined reference to `wrefresh' ncurseshelloworld.c:(.text+0x226): undefined reference to `delwin' ncurseshelloworld.c:(.text+0x22b): undefined reference to `endwin' ncurseshelloworld.c:(.text+0x232): undefined reference to `stdscr' ncurseshelloworld.c:(.text+0x23a): undefined reference to `wrefresh' collect2: error: ld returned 1 exit status
so what to do? Probably you already have ncurses Development package installed like me but if not first install ncurses devel rpm to you system
zypper install ncurses-devel
then we little bit make our gcc line different:
gcc -o ncurseshelloworld ncurseshelloworld.c -lncurses ./ncurseshelloworld
which ‘-l’ tells you how to use ncurses library when seeking dependencies, After that you see many colors. So that was that and next time we go little bit into SDL_image 1.2 world and learn how to use pkg-config so we know what libraries are needed.
Both comments and pings are currently closed.
Your code is broken in the #include section – got filtered out.
* <text> got filtered out
Thanks fixed.. Damn visual editor ain’t working so gotta do it live with pure HTML code :D!