Pages

Friday, October 21, 2011

Uma visão básica e essencial sobre Autotools - Parte I


O que é o Autotools?

O Autotools ou, como também é chamado, GNU build system é comumentemente utilizado por desenvolvedores de software livre para tornar seu programa bastante portável e, principalmente, para prover uma automatização ao projeto.
Com o GNU Make já é possível obter uma automatização sensível na elaboração e construção de qualquer projeto, entretanto, quando usamos o GNU Automake até o próprio arquivo de Makefile é gerado automaticamente, ou seja, não é mais necessário gastar tempo na codificação de um arquivo Makefile, por exemplo.
A Ferramenta GNU Autoconf é mais interessante ainda. Com ela é possível gerar scripts que configuram seu projeto de forma automática, adaptando-o ao sistema que está sendo usado e verificando as dependências necessárias.


Colocando a mão na massa!

Neste post, abordaremos uma visão simples e fácil para utilizarmos o Autotools em nossos projetos.

Antes de iniciar, devemos baixar os pacotes essenciais. Com um simples apt-get (para sistemas Debian-like) resolvemos o problema.

$ sudo apt-get install autoconf automake

Depois de instalados, podemos iniciar a automatização de nosso projeto com um "Hello World!" básico a seguir,

// helloworld.c
#include <stdio.h>

int main(int argc, char *argv[]) {

printf("Hello world!\n");

return 0;
}

Para dificultar colocaremos o código-fonte em uma pasta chamada "src" e na pasta base criaremos o makefile a seguir,

#makefile

all:
gcc -o helloworld src/helloworld.c

clean:
rm -r -f helloworld *.o src/*.o

Portanto, já temos nosso código base na pasta "src" e o makefile na pasta raiz. Agora iniciaremos o uso do GNU Autotools. Para isso, realizaremos todas as operações na pasta raiz (onde se encontra o makefile). Portanto, no shell devemos efetuar primeiramente,

$ autoscan

Gerando dois arquivos: o autoscan.log e o configure.scan. Devemos renomear esse útlimo para que ele sirva como entrada para geração do script de configuração pelo comando autoconf.

$ mv configure.scan configure.ac

e por fim,

$ autoconf

Notemos que foi criado um script chamado "configure" e uma pasta chamada "autom4te.cache". Veremos mais a frente o porquê esta pasta é necessária.

Antes de executarmos nosso script devemos renomear o nosso makefile para "makefile.in". Afinal, ele será um input para o script gerar o makefile.

mv makefile makefile.in

Já podemos então executar o script configure.

./configure

A saída esperada será:

checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
checking whether we are cross compiling... no
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
configure: creating ./config.status
config.status: creating makefile
config.status: error: cannot find input file: `config.h.in'

Notemos que ele não achou o arquivo de entrada "config.h.in", porém ele gerou o makefile.
Logo, podemos executar esse script em qualquer máquina para gerar o makefile automaticamente, verificando as dependências.

Agora basta um simples comando make para compilar e gerar o binário desejado.

Por fim, chegamos aos primeiros passos da utilização do GNU Autotools, mais a frente iremos aprender novos conceitos, inserir bibliotecas e gerar um makefile a partir do Automake.


Referências

Algumas Referências interessantes sobre Autotools:

http://www.lrde.epita.fr/~adl/autotools.html
http://markuskimius.wikidot.com/programming:tut:autotools

Tuesday, August 23, 2011

How to Develop a Cairo Clock using Common Lisp and GTK+

A Short Introduction

In my last project based on Lisp and GTK+ Toolkit, I need to use some graphics to build a drawing module. Then, the best solution found was the use of cairo libraries to render this kind of graphics. The Cairo API provides anti-aliasing and a simple handling.  However, I didn't find some books or tutorials that show how I could do it. With some searchs at Google, I found a tutorial made by the author of the Cairo bindings for Common Lisp, but the article didn't show an Cairo integration with Gtk+.

Then, in our laboratory, we understood the source code of the Cairo bindings for Lisp and built a solution to implement a application Lisp based, using Gtk+ and Cairo.

If you interested yourself or only want to learn the Common Lisp Language, I suggest the on-line book: "Practical Common Lisp". A suggestions for people who want to start programming Lisp is download, or a Eclipse plug-in called Cusp, or use Emacs running Slime. You can install the essentials packages using the command line,

$ sudo apt-get install emacs23 sbcl slime cl-alexandria cl-asdf cl-babel cl-cffi cl-closer-mop cl-clg cl-trivial-features cl-swank

The source packages of cl-cairo2 can be found at Cliki cl-cairo2 project. The installation is so easy, you need to extract the source and paste it in ~/.sbcl/site/. After create the symbolic links of all .asd,

$ ln -s ~/.sbcl/site/YOUR_CAIRO_FOLDER/*.asd ~/.sbcl/systems

Now, you're ready to start developing common lisp, gtk+ and cairo applications.


Developing Lisp Apps using Cairo and Gtk+

First you need to import the libraries using Asdf,

(asdf:load-system :cl-gtk2-gtk)
(asdf:load-system :cl-cairo2)
(asdf:load-system :cl-cairo2-x11)

The assignment of cairo context can be made with,

...
(let ((cr (make-instance 'cl-cairo2:context
                     :pointer cr-p
                     :width draw-w
                     :height draw-h
                     :pixel-based-p t)))
             (setq cl-cairo2:*context* cr)
             (cl-cairo2:rectangle 0 0 500 500 cr)
             (cl-cairo2:clip cr)
             (draw-clock cr)))))
...

The function that draws the cairo clock is,

;; Function to create the clock from a Cairo context
(defun draw-clock (context)
   (setq radius 180)
   (cl-cairo2:set-source-rgb 1 1 1 context)
   (cl-cairo2:arc (/ draw-h 2) (/ draw-w 2) (/ radius 2) 0 (* 2 pi) context)
   (cl-cairo2:fill-path context)
   (cl-cairo2:set-source-rgb 0 0 0 context)
   (cl-cairo2:arc (/ draw-h 2) (/ draw-w 2) (/ radius 2) 0 (* 2 pi) context)
   (cl-cairo2:stroke context)

   ;; 0 to 11 hours
   (loop for i from 1 to 12 do
          ...
   )
)

Then, we finished an example of using Cairo and Gtk on Lisp.
You can download the source code here: cairoclock.lisp


Thursday, August 4, 2011

Criando um Servidor Git usando Gitweb, Gitosis e o próprio Git

Todos nós desenvolvedores, um dia, utilizaremos ou, senão, já usamos Controles de Versões de projetos. Nesse post, eu comentarei um pouco sobre a criação de um servidor Git particular para ser usado como repositório. Além disso, indicarei possíveis erros que possam ocorrer durante a criação do mesmo.

Primeiramente devemos instalar no servidor os pacotes necessários.

$ sudo apt-get install git-core gitosis gitweb


Aplicando o Gitosis

Com os pacotes já instalados, recomendamos que seja criado um usuário no servidor chamado 'git' exclusivo e sem senha,

$ sudo adduser \
  --system \
  --shell /bin/bash \
  --gecos 'Git Version Control' \
  --group \
  --disabled-password \
  --home /home/git \
  git

 Criado o usuário, vamos ter como resposta,

Adding system user 'git'...
Adding new group 'git' (211).
Adding new user 'git' (211) with group 'git'.
Creating home directory '/home/git'.

Como queremos acessar o usuário 'git' sem senha, criaremos uma chave RSA pública em nossa própria máquina e não no servidor. Primeiramente, devemos criar (se ela ainda não existir) uma pasta chamada .ssh em /home/git/ com,

$ mkdir .ssh

Já em nossa máquina devemos criar a chave pública fazendo,

$ ssh-keygen -t rsa

e compiamos ela para a pasta /tmp/ do servidor,

$ scp ~/.ssh/id_rsa.pub seu_login@servidor_hostname:/tmp/

Feito isso, liberamos o acesso com,

$ sudo cat /tmp/id_rsa.pub >> /home/git/.ssh/authorized_keys

Agora podemos acessar via SSH nosso usuário Git sem senha. Para começarmos a utilizar o Gitosis, devemos efetuar o seguinte comando no home folder do usuário git,

$ sudo -H -u git gitosis-init < id_rsa.pub

Sendo a saída esperada justamente duas vezes a mesma mensagem,

Initialized empty Git repository in ./
Initialized empty Git repository in ./

Devemos habilitar o script para execução do git update-server-info com,

$ sudo chmod 755 /home/git/repositories/gitosis-admin.git/hooks/post-update

Na sua máquina agora será possível realizar um git clone via SSH.

$ git clone git@servidor_hostname:~/repositories/gitosis-admin.git
$ cd gitosis-admin.git

Você, primeiramente, irá clonar um repositório vazio e, posteriormente, poderá inserir arquivos a serem adicionados ao commit.

Para adicionar permissões, é possível editar o arquivo encontrado em /home/git/repositories/gitosis-admin.git/gitosis.conf no servidor. Editando-o da seguinte maneira,

[gitosis]

[group gitosis-admin]
writable = giosis-admin
members = nome_do_usuário

Para adicionar mais grupos, repositórios ou membros, podemos exemplificar com o modelo abaixo,

[group laboratório]
writable = projeto
members = usuário1 usuário2 usuário3

* Importante: Se optarmos por garantir o acesso público utilizando o protocolo Git, devemos efetuar,

$ touch ~/repositories/gitosis-admin.git/git-daemon-export-ok

e iniciaremos o daemon com,

$ sudo -u git git daemon --base-path=/home/git/repositories --export-all

Assim, podemos usar o git clone efetuando,

$ git clone git://servidor_hostname/gitosis-admin.git

Devemos lembrar que o protocolo Git é usado somente leitura. Portanto em casos de git push essa URL não será válida levando a erros que serão reportados em outros posts.


Criando outros Repositórios de Projetos

Podemos criar pastas no mesmo diretório que o gitosis-admin. No meu caso, como utilizarei o Gitweb criarei uma outra pasta dentro de /home/git/repositories/, chamada de "projects" e dentro de "projects" criarei o "meuprojeto".

$ cd /home/git/repositories/
$ mkdir projects
$ cd projects
$ mkdir meuprojeto

Para fazer com que "meuprojeto" seja um repositório git, devemos realizar os seguintes comandos,

$ cd meuprojeto
$ git --bare init
$ cp ~/repositories/gitosis-admin.git/hooks/post-update /hooks/
$ touch ~/repositories/projects/meuprojeto/git-daemon-export-ok

Voltando a máquina local, podemos cloná-lo para adicionar os arquivos referentes ao projeto. Obviamente, temos a liberdade de fazer isso diretamente no servidor, entretanto, essa é uma forma que eu acredito ser mais organizada e mais lógica. Portanto, efetuaremos o seguinte comando,

$ git clone git://servidor_hostname/projects/meuprojeto

Uma mensagem de alerta aparecerá, informando que o repositório git clonado está vazio. Uma mensagem absolutamente normal.

Podemos copiar todos os arquivos referentes, efetuando, por exemplo,

$ cd meuprojeto
$ git add .
$ git commit -a -m "Qualquer informação válida sobre o commit"
$ git push origin master

O git push origin master irá realizar um commit inicial no branch master da origem que é o servidor. É muito importante realizar esse primeiro comando no primeiro push.

* Importante: Após realizarmos essas alterações no projeto, o mais lógico seria enviá-las ao servidor como forma de atualização do repositório do projeto, mas quando efetuamos o comando acima,

$ git push origin master

Uma mensagem como essa aparecerá,

fatal: The remote end hung up unexpectedly

Isso acontece graças ao clone realizado com o protocolo git, na qual, é um protocolo usado somente para leitura e não para a escrita de dados vindos do servidor. Então, quando efetuamos um push ele tentará acessar a URL usada no clone que será git://servidor_hostname/projects/meuprojeto, não obtendo sucesso. Para corrigirmos essa situação, temos a opção de atualizar as configurações do nosso projeto verificadas em,

$ git config --list

podemos observar o campo remote.origin.url="..." como sendo igual a URL clonada. Para alterarmos, basta executar um editor e alterar esse campo com a URL destinada ao SSH.

$ vim .git/config

e editarmos o campo,

...
[remote "origin"]
fetch = +refs/heads/*:refs/remotes/origin/*
url = git@servidor_hostname:~/repositories/projects/meuprojeto
...

Agora, podemos executar o git push,

$ git push origin master

Não iremos cobrir nesse post a configuração do Apache para assim usarmos o protocolo HTTP em clones de repositórios. Futuramente, iremos abordar melhor como fazer tal procedimento.

Finalizando, por questões de segurança, podemos limitar o acesso via SSH ao usuário Git fazendo,

$ chsh -s /usr/bin/git-shell

Terminamos aqui uma configuração básica e essencial de um servidor Git utilizado para hospedar projetos e trabalhos.


Configurando o Gitweb

A configuração do Gitweb é relativamente fácil. Procedemos,

$ sudo mkdir /var/www/git

Criada a pasta, configuremos o Git no Apache,

$ sudo vim /etc/apache2/conf.d/git

preenchendo, então, o arquivo com os seguinte dados:

<Directory /var/www/git>
        Allow from all
        AllowOverride all
        Order allow,deny
        Options ExecCGI
        <Files gitweb.cgi>
                SetHandler cgi-script
        </Files>
</Directory>

O Próximo passo é mover todos os arquivos provenientes do Gitweb para a nova pasta criada.

$ sudo mv /usr/share/gitweb/* /var/www/git/
$ sudo mv /usr/lib/cgi-bin/gitweb.cgi /var/www/git/

Para terminarmos a configuração, editemos o arquivo de configuração do Gitweb,

$ sudo vim /etc/gitweb.conf

como o exemplo abaixo (que segue o exemplo da criação do repositório "meuprojeto"),

# path to git projects (<project>.git)
$projectroot = "/home/git/repositories/projects/";

# directory to use for temp files
$git_temp = "/tmp";

# target of the home link on top of all pages
#$home_link = $my_uri || "/";

# html text to include at home page
$home_text = "indextext.html";

# file with project list; by default, simply scan the projectroot dir.
$projects_list = $projectroot;

# stylesheet to use
$stylesheet = "gitweb.css";

# javascript code for gitweb
$javascript = "gitweb.js";

# logo to use
$logo = "git-logo.png";

# the 'favicon'
$favicon = "git-favicon.png";

Terminamos assim a configuração do Gitweb e podemos acessar nossos projetos, seus commits, diffs via página HTML.


Problemas que podem ocorrer durante a configuração do Servidor

Alguns problemas já foram descritos acima, como problemas decorrentes do protocolo Git que se comporta como somente leitura sendo corrigida.

Um problema enfrentado quando eu solicitei um git clone foi o bloqueio da porta 9418 (utilizada pelo git daemon) recebendo um,

fatal: unable to connect a socket (Connection timed out)

Para liberarmos o firewall para utilizarmos o Git, no meu caso eu abilitei a porta 9418, no iptables, da seguinte maneira,

$ sudo vim /etc/init.d/iptables

Adicinando a seguinte linha ao Documento,

# git
iptables -A INPUT -p tcp -s 0/0 -d 0/0 --destination-port 9418 -j ACCEPT

É sempre bom documentarmos para quem estamos adicionando uma liberação, isso ajuda outros utilizadores do servidor em caso de alguma manutenção ou outros usos. Documentação é essencial pra qualquer prática de programação.

Por fim reiniciaremos o firewall aplicando as mudanças com,

$ sudo /etc/init.d/iptables restart

Quem seguiu as práticas citadas acima, verificou exatamente tudo, prestou a atenção em cada linha de comando, mas ainda não consegue realizar um clone ou um push, pode analisar os logs mantidos pelo git daemon. Esse arquivo, para mim, foi uma peça chave para identificar problemas relacionados a localização dos repositórios e a erros relacionados a conexão. Para analisarmos esse arquivo, realizemos um,

$ sudo cat /var/log/git-daemon/current

Na qual a minha saída no shell foi,

2011-08-01_12:36:40.42770 git-daemon starting.

Mas há todo o tipo de mensagem que envolva o git-daemon.


Considerações Finais

Não há muita complexidade para criarmos um servidor de repositórios Git em um servidor pessoal, entretanto algumas dificuldades são providas com base em outros serviços que podem influenciar na conexão, ou os próprios protocolos muitas vezes merecem um estudo antes de serem usados como o protocolo Git. Erros também aparecem devido a erros de sintaxe no momento da configuração do servidor, por isso, é sempre bom estarmos atentos aos procedimentos.

As referências usadas no auxílio da elaboração desse post são listadas a seguir, bem como um tutorial básico da utilização do Git:

[Tutorial de Git] - Tutorial elaborado por mim que abrange o essencial de Git.

[scie.nti.st] - Tutorial bem bacana sobre Git Server.
[noroyalties.org] - Um outro tutorial usado na referência.
Pro Git - Professional Version Control - Livro on-line interessante a respeito de Git.