Instal·leu el paquet build-essential:
$ sudo apt-get install build-essential S'està llegint la llista de paquets... Fet S'està construint l'arbre de dependències Reading state information... Fet S'instal·laran els següents paquets extres: dpkg-dev g++ g++-4.2 libc6-dev libstdc++6-4.2-dev libtimedate-perl linux-libc-dev patch Paquets suggerits: debian-keyring g++-multilib g++-4.2-multilib gcc-4.2-doc libstdc++6-4.2-dbg glibc-doc manpages-dev \ libstdc++6-4.2-doc diff-doc S'instal·laran els següents paquets NOUS: build-essential dpkg-dev g++ g++-4.2 libc6-dev libstdc++6-4.2-dev libtimedate-perl linux-libc-dev patch 0 actualitzats, 9 nous a instal·lar, 0 a eliminar i 0 no actualitzats. Es necessita obtenir 8702kB d'arxius. After this operation, 34,3MB of additional disk space will be used. Voleu continuar [S/n]?
Es recomanable instal·lar els paquets suggerits:
$ sudo apt-get install debian-keyring g++-multilib g++-4.2-multilib gcc-4.2-doc \ libstdc++6-4.2-dbg glibc-doc manpages-dev libstdc++6-4.2-doc diff-doc
Ara ja teniu totes les eines necessàries per a compilar aplicacions en C. Per exemple, el típic hola mon. Primer creem un directori on treballar:
$ cd $ mkdir holamon $ cd holamon
Ara instal·leu un Editor de text per a modificar el fitxer. Per exemple ho podeu fer amb joe:
$ sudo apt-get install joe $ joe holamon.c
Escriviu el següent codi:
#include <stdio.h> int main() { printf("Hola mon!\n"); return 0; }
I compilem amb:
$ gcc -Wall holamon.c -o holamon
On:
Veiem que s'ha creat un fitxer executable nou anomenat holamon:
$ ls -l total 16 -rwxr-xr-x 1 sergi sergi 6364 2008-06-28 10:37 holamon -rw-r--r-- 1 sergi sergi 79 2008-06-28 10:37 holamon.c -rw-r--r-- 1 sergi sergi 78 2008-06-28 10:37 holamon.c~
Sabem que és executable per la x dels permisos (vegeu Permisos Linux). L'executem amb:
$ ./holamon Hola mon!
GNU toolchain és un terme que s'utilitza per referir-se a un conjunt d'eines de programació creades pel projecte GNU. Aquestes eines s'utilitzen en cadena (s'utilitzen en sèrie) per tal de desenvolupar aplicacions i sistemes operatius.
GNU toolchain té un rol vital en la creació del kernel de Linux, BSD i en programari per a sistemes encastats.
Els projectes inclosos a GNU Toolchain són:
En cada fase (veieu imatge de la dreta) intervé una eina diferent de la cadena:
GNU Compiler Collection (GCC) és un conjunt de compiladors i un front-end creat pel projecte GNU per a diferents llenguatges de programació. GCC és el component clau de GNU toolchain i és el compilador oficial dels sistemes GNU/Linux, BSD i Mac OS X. GCC ha estat portat a altres arquitectures, programari propietari i sistemes com Symbian, Playstation o Sega Dreamcast.
Originalment és deia GNU C Compiler perquè només era capaç de treballar amb el llenguatge de programació C (GCC 1.0 va ser creat el 1987). Més tard es va incorporar suport per a C++. Actualment també es pot utilitzar per compilar els següents llenguatges de programació:
GCC es distribuït per la Free Software Foundation (FSF) sota les llicències GNU General Public License (GNU GPL) i GNU Lesser General Public License (GNU LGPL), GCC és programari lliure.
Recursos:
Exemple hello.c:
#include <stdio.h> int main (void) { printf ("Hello, world!\n"); return 0; }
$ gcc -v Usant especificacions internes. Target: i486-linux-gnu Configurat amb: ../src/configure -v --enable-languages=c,c++,fortran,objc,obj-c++,treelang --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.1.3 --program- suffix=-4.1 --enable-__cxa_atexit --enable-clocale=gnu --enable-libstdcxx-debug --enable-mpfr --enable-checking=release i486-linux-gnu Model de fils: posix gcc versió 4.1.3 20070929 (prerelease) (Ubuntu 4.1.2-16ubuntu2)
$ gcc -Wall hello.c -o hello
La opció -o indica el nom del fitxer executable (fitxer amb codi màquina). hello.c és el codi font i la opció -Wall indica que volem que es mostrin tots els avisos/warnings (és molt recomanable utilitzar aquesta opció sempre). Per executar el programa:
$ ./hello Hello, world!
Si no s'especifica l'opció -o:
$ gcc -Wall hello.c
El fitxer de sortida és el fitxer:
a.out
També executable (./a.out).
$ gcc -Wall main.c hello_fn.c -o newhello
$ gcc main.o hello.o -o hello
S'utilitza el paràmetre -g.
$ gcc -Wall -g null.c
Ara ja podem utilitzar gdb per depurar.
$ gcc -Wall -I/opt/gdbm-1.8.3/include -L/opt/gdbm-1.8.3/lib dbmain.c -lgdbm
o alternativament utilitzar la variable d'entorn:
$ LIBRARY_PATH=/opt/gdbm-1.8.3/lib $ export LIBRARY_PATH
També són importants les variables d'entorn:
$ LD_LIBRARY_PATH=/opt/gdbm-1.8.3/lib $ export LD_LIBRARY_PATH
i
C_INCLUDE_PATH=.:/opt/gdbm-1.8.3/include:/net/include
$ gcc -Wall -O0 test.c -lm
Creeu un fitxer anomenat Makefile
CC=gcc CFLAGS=-Wall main: main.o hello_fn.o clean: rm -f main main.o hello_fn.o
Aquest fitxer indica que utilitzarem gcc com a compilador i amb l'opció -Wall i que crearem un executable a partir dels fitxers objecte main.o i hello_fn.o. Com a norma implícita, al seu torn, els fitxer .o es generen a partir dels fitxers .c equivalents.
La norma clean no té dependències i elimina els fitxers compilats.
Per utilitzar aquest fitxer podem executar:
$ make
Si no donem cap opció s'exeduta la primera norma (en aquest cas main)
Si volem executar la norma clean executem:
$ make clean
Les proporciona el paquet:
binutils
tal i com podem observar executant:
$ dpkg -S /usr/bin/nm binutils: /usr/bin/nm
Les comandes que ens proporciona aquest paquet són:
$ dpkg -L binutils | grep /usr/bin /usr/bin/size /usr/bin/objdump /usr/bin/ar /usr/bin/strings /usr/bin/ranlib /usr/bin/objcopy /usr/bin/addr2line /usr/bin/readelf /usr/bin/nm /usr/bin/strip /usr/bin/c++filt /usr/bin/as /usr/bin/gprof /usr/bin/ld
$ man ld ... ld - The GNU linker
Serveix per enllaçar fitxers objecte (*.o) a un programa. Aquests enllaços són estàtics. Les bilioteques compartides tenen extensió *.so i es gestionen amb ld.so.
Consulteu ld.so
Mostra la taula de símbols:
$ nm a.out 08049484 d _DYNAMIC 08049558 d _GLOBAL_OFFSET_TABLE_ 08048458 R _IO_stdin_used w _Jv_RegisterClasses 08049474 d __CTOR_END__ 08049470 d __CTOR_LIST__ 0804947c d __DTOR_END__ 08049478 d __DTOR_LIST__ 0804846c r __FRAME_END__ 08049480 d __JCR_END__ 08049480 d __JCR_LIST__ 0804957c A __bss_start 08049570 D __data_start 08048410 t __do_global_ctors_aux 08048320 t __do_global_dtors_aux 08049574 D __dso_handle w __gmon_start__ 0804840a T __i686.get_pc_thunk.bx 08049470 d __init_array_end 08049470 d __init_array_start 080483a0 T __libc_csu_fini 080483b0 T __libc_csu_init U [email protected]@GLIBC_2.0 0804957c A _edata 08049580 A _end 08048438 T _fini 08048454 R _fp_hw 08048274 T _init 080482f0 T _start 0804957c b completed.5982 08049570 W data_start 08048350 t frame_dummy 08048374 T main 08049578 d p.5980 U [email protected]@GLIBC_2.0
El primer de tot per poder depurar es utilitzar el paràmetre -g al compilar.
$ gcc -g hello.c
Un exemple:
int foo (int *p); int main (void) { int *p = 0; /* null pointer */ return foo (p); } int foo (int *p) { int y = *p; return y; }
$ gcc -Wall -g null.c
$ ./a.out Segmentation fault (core dumped)
Realment els cores normalment no es volquen al disc dur perquè:
$ ulimit -c 0
Ho podem modificar amb:
$ ulimit -c unlimited
I aleshores:
$ gdb a.out core Core was generated by `./a.out'. Program terminated with signal 11, Segmentation fault. Reading symbols from /lib/libc.so.6...done. Loaded symbols for /lib/libc.so.6 Reading symbols from /lib/ld-linux.so.2...done. Loaded symbols for /lib/ld-linux.so.2 #0 0x080483ed in foo (p=0x0) at null.c:13 13 int y = *p; (gdb)
Podem veure l'error amb:
(gdb) print p $1 = (int *) 0x0
Mostrar backtrace:
(gdb) backtrace #0 0x080483ed in foo (p=0x0) at null.c:13 #1 0x080483d9 in main () at null.c:7
Col·locant un punt d'interrupció a main:
$ gdb a.out
(gdb) break main
Breakpoint 1 at 0x80483c6: file null.c, line 6. (gdb) run Starting program: a.out Breakpoint 1, main () at null.c:6 6 int *p = 0; /* null pointer */
Movent-se pel programa:
(gdb) step 7 return foo (p);
Mostrant valors de variables:
gdb) print p $1 = (int *) 0x0
Modificant variables:
(gdb) set variable p = malloc(sizeof(int)) (gdb) print p $2 = (int *) 0x40013f98 (address allocated by malloc)
(gdb) set variable *p = 255 (gdb) print *p $3 = 255
Continuar amb l'execució:
(gdb) finish Run till exit from #0 0x08048400 in foo (p=0x40013f98) at null.c:15 0x080483d9 in main () at null.c:7 7 return foo (p); Value returned is $13 = 255
(gdb) continue Continuing. Program exited with code 0377.
Recursos:
$ gdb programa ... (gdb) run parametre1 parametre2 parametre3 ...
$ sudo apt-get install cgdb ...
$ cgdb
GNU build system, també coneguts com Autotools, és un conjunt d'eines de programació creat pel projecte GNU. Aquestes eines estan dissenyades per assistir als programadors en la tasca de crear codi portable a diferents sistemes Unix. GNU build system és part de la GNU toolchain i és molt utilitzat en molts projectes de programari lliure. La eina és GPL però es poden crear/portat programari propietari amb aquestes eines.
Hi han tres eines principals:
Recursos:
Va haver-hi un temps en que va haver-hi un fork de GNU libc. Actualment ja no és així i tots dos projectes són el mateix (GNU libc). Consulteu els recursos.
Recursos:
La llibreria estàndard de C, també coneguda com a libc, és una col·leció de fitxers de capçalera i rutines de llibreria utilitzada per implementar operacions comunes com operacions d'E/S, gestió de cadenes de caràcters, etc.
Tot i que al principi no era així, actualment libc forma part de l'estàndard ISO de C.
La implementació més utilitzada d'aquestes llibreries estàndard és la GNU C Library, també coneguda com a glibc.
En sistemes Debian aquesta llibreria és proporcionada per:
$ dpkg -l libc6 Desired=Unknown/Install/Remove/Purge/Hold | Status=Not/Installed/Config-f/Unpacked/Failed-cfg/Half-inst/t-aWait/T-pend |/ Err?=(none)/Hold/Reinst-required/X=both-problems (Status,Err: uppercase=bad) ||/ Nom Versió Descripció +++-=================================-=================================-=============================================================================== ii libc6 2.6.1-1ubuntu10 GNU C Library: Shared libraries
Les llibreries es troben normalment a les carpetes del sistema:
/usr/lib /lib
Podem consultar les llibreries amb la comanda:
$ dpkg -L libc6 | grep lib
NOTA: En versions noves de Debian/Ubuntu el paquet és libc-bin:
$ dpkg -L libc-bin | grep bin
La documentació es troba a:
/usr/share/doc/libc6
Les comandes que proporciona aquest paquet són:
$ dpkg -L libc6 | grep bin /usr/bin /usr/bin/iconv /usr/bin/getent /usr/bin/getconf /usr/bin/catchsegv /usr/bin/tzselect /usr/bin/ldd /usr/bin/zdump /usr/bin/rpcinfo /usr/sbin /usr/sbin/zic /usr/sbin/iconvconfig /sbin /sbin/ldconfig /sbin/ldconfig.real
NOTA: Cal tenir en compte que el paquet libc6 no aporta el codi font de les llibreries estàndard de C
Per treballar amb el codi font i les capçaleres de les llibreries estàndard de C, tenim el paquet libc6-dev:
$ dpkg -l libc6-dev Desired=Unknown/Install/Remove/Purge/Hold | Status=Not/Installed/Config-f/Unpacked/Failed-cfg/Half-inst/t-aWait/T-pend |/ Err?=(none)/Hold/Reinst-required/X=both-problems (Status,Err: uppercase=bad) ||/ Nom Versió Descripció +++-=================================-=================================-=============================================================================== ii libc6-dev 2.6.1-1ubuntu10 GNU C Library: Development Libraries and Header Files
Amb:
$ dpkg -L libc6-dev
Consultem els fitxers d'aquest paquet.
Els executables són:
$ dpkg -L libc6-dev | grep bin /usr/bin /usr/bin/gencat /usr/bin/mtrace /usr/bin/rpcgen /usr/bin/sprof
Les llibreries es troben a:
/usr/lib/
$ dpkg -L libc6-dev | grep /usr/lib
I les capçaleres (fitxers *.h) és troben a:
/usr/include
$ dpkg -L libc6-dev | grep include
A una Ubuntu karmic 9.10 aquesta ordre es proporcionada pel paquet libc-bin:
$ dpkg -S /usr/bin/getconf libc-bin: /usr/bin/getconf
Es poden consultar tots els paràmetres de configuració relacionats amb la llibreria estàndard de C amb:
$ getconf -a
La llista és llarga i per aquesta raó us recomanem utilitzar un paginador com more o less:
$ getconf -a | more LINK_MAX 32000 _POSIX_LINK_MAX 32000 MAX_CANON 255 _POSIX_MAX_CANON 255 MAX_INPUT 255 _POSIX_MAX_INPUT 255 NAME_MAX 255 _POSIX_NAME_MAX 255 PATH_MAX 4096 _POSIX_PATH_MAX 4096 PIPE_BUF 4096 _POSIX_PIPE_BUF 4096 SOCK_MAXBUF ...
Es poden consultar paràmetres concrets amb:
$ getconf LOGIN_NAME_MAX 256
Destaquem els següents paràmetres:
Consulteu també el manual:
$ man getconf
També conegudes com llibreries compartides.
Carrega dinàmica de llibreries:
S'utilitzen les funcions dl* (man dlopen): dladdr, dlclose, dlerror, dlopen, dlsym, dlvsym
void* sdl_library = dlopen("libsdl.so", RTLD_LAZY); if(sdl_library == NULL) { // report error ... } else { // use the result in a call to dlsym }
Recursos
Consulteu ldconfig.
Consulteu ldd.
Si executeu aquestes comandes en màquines diferents veureu que les adreces de memòria no tenen per que coincidir.
És el preprocessador de C:
Mostrar les MACROS predefinides:
$ cpp -dM /dev/null #define __DBL_MIN_EXP__ (-1021) #define __FLT_MIN__ 1.17549435e-38F #define __CHAR_BIT__ 8 #define __WCHAR_MAX__ 2147483647 ...
Mostra informació sobre els fitxers compilats (executables):
Fitxer executable:
$ file a.out a.out: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.6.8, dynamically linked (uses shared libs), not stripped
El tipus de fitxer binari és Executable and Linkable Format (ELF) que és un format de fitxer estàndard per a executables, codi objecte, llibreries compartides i core dumps.
Llibreria compartida:
$ file /lib/libcap.so.1.10 /lib/libcap.so.1.10: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), stripped
Core dump:
$ file core core: ELF 32-bit LSB core file Intel 80386, version 1 (SYSV), SVR4-style
LSB és Linux Standard Base.
Els fitxers executables de Windows no segueixen aquest estàndard:
$ file /media/sda1/windows/system32/hal.dll /media/sda1/windows/system32/hal.dll: MS-DOS executable PE for MS Windows (DLL) (native) Intel 80386 32-bit
http://en.wikipedia.org/wiki/Valgrind
El següent codi és ANSI C
#include <stdio.h> int main (void) { const char asm[] = "6502"; printf ("the string asm is '%s'\n", asm); return 0; }
Però amb gcc us donarà el següent error de compilació:
$ gcc -Wall prova1.c prova1.c: In function ‘main’: prova1.c:6: error: expected identifier or ‘(’ before ‘asm’ prova1.c:7: error: expected expression before ‘asm’ prova1.c:12:7: avís: no hi ha caràcter de fi de línia al final del fitxer
El compilador GCC suporta C estàndard (ANSI C) més extensions de GNU.
Per compilar amb GCC ANSI C:
$ gcc -Wall -ansi ansi.c
També pot passar al revés, que no compili un programa en ANSI C perquè té extensions de GNU:
#include <math.h> #include <stdio.h> int main (void) { printf ("the value of pi is %f\n", M_PI); return 0; }
La variables M_PI no és ANSI C:
$ gcc -Wall -ansi pi.c pi.c: In function `main': pi.c:7: `M_PI' undeclared (first use in this function) pi.c:7: (Each undeclared identifier is reported only once pi.c:7: for each function it appears in.)
També podem utilitzar l'opció pedantic per tal de mostrar avisos sobre incompatibilitats amb la ISO:
int main (int argc, char *argv[]) { int i, n = argc; double x[n]; for (i = 0; i < n; i++) x[i] = i; return 0; }
$ gcc -Wall -ansi -pedantic gnuarray.c gnuarray.c: In function `main': gnuarray.c:5: warning: ISO C90 forbids variable-size array `x'
Per compilar altres versions de l'estàndard s'utilitza el paràmetre -std :
-std=c89 or -std=iso9899:1990 The original ANSI/ISO C language standard (ANSI X3.159-1989, ISO/IEC 9899:1990). GCC incorporates the corrections in the two ISO Technical Corrigenda to the original standard. -std=iso9899:199409 The ISO C language standard with ISO Amendment 1, published in 1994. This amendment was mainly concerned with internationalization, such as adding support for multibyte characters to the C library. -std=c99 or -std=iso9899:1999 The revised ISO C language standard, published in 1999 (ISO/IEC 9899:1999).