Glaudiston's profileSite pessoal de Glaudist...PhotosBlogListsMore ![]() | Help |
|
|
December 10 autotools parte2 - adicionando dependenciasBem, no artigo anterior, já expliquei como funciona o autotools: http://glaudiston.spaces.live.com/blog/cns!50A3054EE15AB96C!298.entry Agora vou explicar como adicionar dependências. Neste exemplo, vou puxar pro lado de desenvolvimento de games, usando SDL que é uma biblioteca portável, que tem funções de controle de hardware entre outras coisas que facilitam muito nossa vida, e outras bibliotecas derivadas do SDL, como o SDL_image para controle de imagens de vários formatos, o SDL_mixer para o controle de mid, wav, ogg e mp3, o SDL_gfx, para rotação e zoom de imagens ou filmes, o SDL_mpeg para reprodução de filmes... etc. Vamos começar com a teoria: Pelo que já vimos, você deve ter percebido que o autotools trabalha com macros, macros são funções prontas, programas que você passa um comando com parâmetros ou não e eles executam determinadas funções. Você também já deve ter percebido que estas configurações são centralizadas nos arquivos configure.ac e Makefile.am. Sim... continua assim, porém vamos colocar mais um arquivo importante: o acinclude.m4 . acinclude.m4: Este arquivo é uma forma de adicionar macros que podem ser usadas dentro do configure.ac, por exemplo: o Sam Lantinga, desenvolvedor do SDL, criou um arquivo chamado sdl.m4 que está no código fonte do SDL, você pode baixar este código na página do SDL em http://www.libsdl.org, e copiar este arquivo sdl.m4 para o nosso diretório base. depois disto é só adicionar sdl.m4 em nosso arquivo acinclude.m4.in ou acinclude.m4, adicionar o teste desta biblioteca no arquivo configure.ac e executar o autogen.sh Depois de copiar o sdl.m4, só é necessário adionar uma linha com o conteudo sdl.m4 no acinclude.m4.in ... NÃO é preciso nada como #include sdl.m4 ... apenas o sdl.m4... depois disto o script de teste no configure.ac, deve ser colocado na parte de libraries é assim: dnl Check for SDLPara mais informações, consulte o artigo: http://www.samhart.com/snh/files/docs/sdl-kdev/sdl-kdev-mini-how2-2.html Agora se tudo está certo, você pode executar nosso script de reconfiguração (vide artigo anteiror citado acima): $ sh autogen.sh O resultado esperado é: sh autogen.sh checking for a BSD-compatible install... /usr/bin/install -c checking whether build environment is sane... yes checking for a thread-safe mkdir -p... /bin/mkdir -p checking for gawk... gawk checking whether make sets $(MAKE)... yes checking for gcc... gcc checking for C compiler default output file name... a.out checking whether the C compiler works... yes checking whether we are cross compiling... no checking for suffix of executables... checking for suffix of object files... o checking whether we are using the GNU C compiler... yes checking whether gcc accepts -g... yes checking for gcc option to accept ISO C89... none needed checking for style of include used by make... GNU checking dependency style of gcc... gcc3 checking for sdl-config... /usr/bin/sdl-config checking for SDL - version >= 1.2.0... yes configure: creating ./config.status config.status: creating Makefile config.status: creating src/Makefile config.status: creating config.h config.status: config.h is unchanged config.status: executing depfiles commands Observe que agora temos uma parte onde o SDL está sendo checado por uma versão superior à 1.2.0 Isto é suficiente pro SDL, mas e quando temos outras dependências que não nos dão as macros m4 prontas ? A primeira coisa é procurar no google... muitas vezes, no código fonte não vem o arquivo m4, mas alguém criou e postou em algum lugar. Então, se você encontrar vai simplificar muito seu configure.ac da forma q fizemos acima. Mas se o google não achar ? como fazer ? Neste caso, você pode criar seu arquivo m4, ou pode simplesmente adicionar o uma verificação no configure.ac, só q vai poluir um pouco nosso arquivo configure.ac que até então está bem simples. Depois vou postar mais entrada a respeito disto: autotools, criando seu próprio m4. Por hora é só. Tenho que fazer algum código também Abs, Ton December 07 ifconfig não funciona??? net-tools!!!Hahaaa!!! Usando o LinuxFromScratch, e tentando executar alguns programas que configuram VPN, tive vários problemas, e testando, descobri que o problema é que o ifconfig que eu estava usando era o do netutils, e não o do net-tools... segue alguns: 'ifconfig: can not resolve`down`: No address associated with name" "ifconfig: cannot resolve `up': No address associated with name" "ifconfig eth0 up" "ifconfig: can not resolve `up': Unknown host" # ifconfig -a ifconfig: option requires an argument -- a Usage: ifconfig [OPTION]... [SYSTEM OPTION]... Try `ifconfig --help' for more information.': No address associated with name" "ifconfig: can not resolve `up': No address associated with name" "ifconfig eth0 up" "ifconfig: can not resolve `up': Unknown host" # ifconfig -a ifconfig: option requires an argument -- a Usage: ifconfig [OPTION]... [SYSTEM OPTION]... E o incrível, é q o google não acha nenhum resultado com a maioria destas pesquisas. O LFS Book bem q me avisou pra não instalar o ifconfig do netutils... mas não disse q tinha ifconfig no net-tools tbm... então eu q fiquei quebrando a cabeça e consegui resolver com a ajuda do Guedes... valeu mais esta Bill! resumindo, é só instalar o net-tools: http://www.linuxfromscratch.org/blfs/view/stable/basicnet/net-tools.html Abs November 22 Autotools, ah se todos usassem !!!autotools é um conjunto de ferramentas que simplifica a verificação de dependências e compilação de programas. É tão usado no mundo opensource que é até um padrão usado e recomendado pelo gnu. tudo se torna simples quando se tem um projeto usando autotools... Você apenas descompacta os fontes com: tar xvf nomedoarquivo.tar.bz2 depois usa: ./configure make make install Se o código depender de outro componente que não exista em seu ambiente, ele vai ser detectado no ./configure ... sendo assim fica fácil descobrir o que está faltando e instalar esta dependência antes de executar o make que é a parte demorada do processo. O make é a compilação do programa... isto costuma demorar... e muitas vezes tem que executar centenas de subcompilações com linhas de comandos que incluem várias bibliotecas e que seria inviável para um usuário digitá-las na mão, um script para esta compilação poderia ser mantido pelo desenvolvedor do programa, mas daria muito trabalho a ele. É aqui que entra o autotools, ele cria este script automaticamente com um esforço mínimo do desenvolvedor. Mas infelismente muitos projetos não o usam. Vou mostrar em um exemplo prático como é fácil e prático usá-lo. Vamos criar um novo diretório com o nome autotools-example: $ mkdir autotools-example $ cd autotools-example teremos um subdiretório src onde ficaram os fontes: $ mkdir src e agora vamos criar um arquivo representando o nosso código: cat > src/main.c << "EOF" #include <stdio.h> int main(int argc, char** argv) { printf("funciona!!!\n"); return 0; } EOF pronto... já temos um código do programa, hora de usar o autotools pra compilar. O autotools precisa de um arquivo de referência onde ele vai pesquisar para saber o nome do programa que está sendo compilado e qual é a versão atual, onde estão os arquivos fontes, além de validações obrigatórias ou opcionais, como por exemplo um programa que pode ou não ter suporte a som, dependendo de um parâmetro que o usuário passa para o ./configure... também é no configure.ac que o desenvolvedor personaliza mensagens para o usuário e adiciona verificações adicionais para certificar que o código será compilado. parece complicado né ? mas na prática é simples... olhe: Primeiro use o autoscan que varre todos os arquivos do diretório e subdiretórios para detectar os arquivos fontes e criar o configure.ac que é um dos arquivos essenciais do autotools que o programador deve editar. $ autoscan agora devem ter sido criados 2 arquivos: autoscan.log e configure.scan. o arquivo configure.scan é o configure.ac que nós precisamos para o autotools, e que foi criado automaticamente pelo comando autoscan e o autoscan.log registra algum erro ou mensagens ocorridas durante o processo do autoscan. renomeie o arquivo configure.scan para configure.ac : $ mv configure.scan configure.ac vamos olhar o conteúdo do configure.ac e analisar o que precisaremos atualizar: $ more configure.ac # -*- Autoconf -*- # Process this file with autoconf to produce a configure script AC_PREREQ(2.61) AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS) AC_CONFIG_SRCDIR([src/main.c]) AC_CONFIG_HEADER([config.h]) # Checks for programs. AC_PROG_CC # Checks for libraries. # Checks for header files. # Checks for typedefs, structures, and compiler characteristics. # Checks for library functions. AC_OUTPUT bom... vamos ver... todas as linhas começando com #(sharp, cerquilha, ou jogo da velha, como preverir) são comentários, e ignorados pelo autotools, então a primeira linha de código é: AC_PREREQ(2.61) está dizendo que no ambiente onde será compilado, deve existir instalado o autotools versão 2.61 ou superior. Logo após vem: AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS) aqui temos o lugar onde dizemos ao autotools qual é o nosso programa, a versão do nosso programa, e o endereço de email para onde os usuários devem mandar emails em caso de erros. atualize isto como preferir como no exemplo abaixo: AC_INIT(autotools-example, 1.0, [seuemail at dominio dot com] ) depois temos: AC_CONFIG_SRCDIR([src/main.c]) aqui ele detectou corretamente o nosso diretório de códigos fontes. AC_CONFIG_HEADER([config.h]) este arquivo config.h deve pelo comando autoheader e server para definir variáveis de compilação para o autotools, como o PACKAGE_NAME, opções ativas por padrão... etc... $ autoheader agora vamos criar nosso script configure... $ autoconf pronto... se tudo deu certo, agora você terá um arquivo configure em seu diretório, execute-o: $ ./configure ele vai verificar tudo pela primeira vez e criar o config.h... mas ainda precisamos cuidar do automake que irá compilar o nosso projeto. para isto precisamos adicionar um AM_INIT_AUTOMAKE( nomedoprograma, versao ) no configure.ac, então adicione isto logo abaixo de AC_CONFIG_HEADER. AM_INIT_AUTOMAKE(exemplo, 1.0) além disto também é necessário informar quais Makefiles precisam ser criados... então no finao do arquivo configure.ac altere a linha AC_OUTPUT para: AC_OUTPUT([ Makefile src/Makefile ]) pronto, agora execute um autoreconf para atualizar os arquivos: $ autoreconf vamos atualizar o automake agora com o parâmetro --add-missing, para que ele crie os arquivos faltantes: $ automake --add-missing agora um ultimo passo é criar o Makefile.am que é bem simples: cat > Makefile.am << "EOF" SUBDIRS = src EXTRA_DIST = NOTES autogen.sh EOF e um Makefile.ac no diretório de fontes, onde informaremos quem deve ser compilado: cat > src/Makefile.am <<"EOF" bin_PROGRAMS = exemplo exemplo_SOURCES = main.c EOF vamos criar um script pra reconfigurar os arquivos, já fizemos isto, mas precisaremos fazer varias vezes durante o desenvolvimento, um script vai ajudar muito: cat > autogen.sh <<"EOF" #!/bin/sh # aclocal automake --add-missing --foreign autoconf ./configure $* EOF agora execute ele: $ sh autogen.sh bem... se vc executar o automake: $ automake vai receber várias mensagens de erros dizendo q ele não encontrou arquivos necessários... alguns podem ser criados automaticamentes com o parâmetro --add-missing... então vamos criá-los: $ automake --add-missing $ touch NEWS README AUTHORS ChangeLog lembre-se de transformar os links simbólicos possivelmente criados pelo automake --add-missing em arquivos reais antes de compartilhar seu projeto, vc pode fazer isto copiando os arquivos dos links e substituindo-os. Neste ponto já deve estar tudo pronto, e você já pode executar: ./configure make e já deve ter um arquivo executavel com o nome exemplo na pasta src... então execute: $ src/exemplo funciona!!! se apareceu funciona!!! parabéns, vc acaba de criar seu primeiro projeto com autotools... depois vou mostrar como gerenciar dependências, como o SDL e outros... Qualquer dúvida usem os comentários. Abs... Ton August 20 ANSI C - Portabilidade - WINMAIN LPSTR lpCmdLine to char **argvSempre tento criar minhas rotinas portáveis... mesmo que elas sejam apenas para aprendizado. Recentemente testei o SDL_mixer que traz uma rotina exemplo bem legal de como funciona, roda todos os formatos suportados, wav, ogg, mp3... etc. Segue o link: http://jcatki.no-ip.org/SDL_mixer/demos/ Mas enfrentei alguns problemas de compilação por causa dos argumentos passados pela linha de comando, com certeza a rotina foi desenvolvida em linux... aprecio isto... mas não acho interessante para um software ser restrito pelo sistema operacional, mesmo que este seja aberto. Pesquisei coisas como LPSTR to char** e LPWSTR* to char* mas sem sucesso. É, a microsoft sempre nos dá um trabalho extra totalmente desnecessário, mas vamos lá... Como vocês já sabem (ou deveriam saber), o windows possui uma forma diferente de iniciar o programa. ao invés do famoso, fácil e perfeito: int main(int argc, char **argv) ele usa INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, INT nShowCmd) Assim sendo, você não tem o array para pegar is itens da linha de comando da forma que está acostumado. Então tive que criar uma forma de resolver isto para que eu possa criar meu código sem me preocupar com OS em que está sendo compilado. Segue: #ifndef WIN32 int main(int argc, char **argv) { #else #include <windows.h> INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, INT nShowCmd) { int argc; char **argv; LPWSTR *szArglist; szArglist = CommandLineToArgvW(GetCommandLineW(), &argc); int __i; if( NULL == szArglist ) { wprintf(L"CommandLineToArgvW failed\n"); return 0; } else { argv = malloc(sizeof(char *) * argc); for( __i=0; __i<argc; __i++) { int tmp = wcslen(szArglist[__i]); char *c = malloc(sizeof(char) * tmp); wcstombs(c, szArglist[__i], tmp); argv[__i] = c; } } // Free memory allocated for CommandLineToArgvW arguments. LocalFree(szArglist); #endif // O código vem aqui... // e vc pode acessar o argv normalmente: int i; for( i=0; i<argc; i++) printf("%d: %s\n", i, argv[i]); #ifdef WIN32 // Free memory allocated for CommandLineToArgvW arguments. for ( __i = 0; __i < argc; __i++ ) free(argv[__i]); free(argv); #endif return(0); } Me avise se isto for util pra você, ficarei feliz em saber. Até a próxima, Abs, Ton |
|
|