Você está na página 1de 12

Sistemas Operativos

Criação de um Projecto no Eclipse e Linguagem C

1 Ambiente de Desenvolvimento em C com IDE


1.1 Criação de um projecto
Na sequência do que foi falado a respeito de ambientes de desenvolvimento utilizaremos nesta
disciplina o IDE eclipse. Vamos então começar por criar um novo projeto e onde iremos criar um
“Hello World” na linguagem C.

O eclipse consegue inclusive gerar um “Hello World” automaticamente, para tal deveremos fazer o
seguinte:
File → New → Project…
Tal sequência de instruções levará à obtenção da seguinte caixa de diálogo que se observa na
imagem abaixo:

SO-2022/2023-João Pavia e Daniel Silveira 1


Devemos agora selecionar a opção C Project e prosseguir ao carregar no botão “Next”.

SO-2022/2023-João Pavia e Daniel Silveira 2


Devemos dar um nome ao projeto sem esquecer de selecionar as opções que se podem observar
acima. Tal como é possível de se observar, o eclipse permite criar um projecto vazio, ou já com um
ficheiro em C a fazer o “Hello World”. Para concluir o processo devemos então carregar no botão
“Finish” e deverão obter o que se observa na seguinte imagem:

Para que o código possa ser executado primeiro há que fazer o build do código para gerar o
executável. Tal é possível ao carregar no ícone do “martelo” tal como mostrado em baixo:

Ao carregarem no botão de Run (indicado através da seta a vermelho na imagem abaixo),


conseguirão correr o executável gerado. Numa na primeira vez irá aparecer uma janela de diálogo
a perguntar onde querem executar o programa e deverão escolher a opção “Local C/C++
Application” e carregar OK.

SO-2022/2023-João Pavia e Daniel Silveira 3


O resultado desta ação será a execução do programa escrevendo na linha de comandos Hello
World.

SO-2022/2023-João Pavia e Daniel Silveira 4


Ambiente de Desenvolvimento em C usando linha de comandos
Para escrever programas e os executar, é necessário utilizar um conjunto de ferramentas que no
seu conjunto constituem um ambiente de desenvolvimento.
O ambiente de desenvolvimento C em Linux pode ser extremamente simples, sendo no mínimo
constituído pelas aplicações que a seguir se descrevem.

Editor de Texto
É a aplicação que irá permitir a escrita do programa. Inúmeros editores de texto estão disponíveis
em Linux, desde os mais simples (e.g., vim, nano) até aos mais complexos (e.g., emacs, visual
studio code) passando pelos mais clássicos (e.g., gedit), que fazem parte das aplicações
disponíveis na barra de comandos do ambiente gráfico.
Os ficheiros criados contendo programas em C deverão ser guardados com a extensão .c Assim,
por exemplo para editar um programa hello.c com o editor nano pode-se escrever:
$ nano hello.c

ou então abrir o editor através do menu de programas e procurar o programa na pasta de trabalho.
Se este não existir deverá obviamente ser usada a opção Save As para o guardar.

Compilador C
Uma vez criado o programa em C, será necessário transformá-lo num programa executável. Para
que isto seja possível é utilizado o compilador C (gcc) que irá realizar uma série de operações sobre
o programa (englobando o pré-processamento, a verificação do código, a compilação, a
assemblagem e a edição de ligações), para finalmente consigamos obter a imagem executável.
Para realizar esta operação deverá ser executado o comando:
$ gcc nome_ficheiro.c

Se não for especificado o nome do ficheiro executável, este recebe o nome por defeito que é a.out.
Para definir o nome do programa executável utiliza-se a opção:
$ gcc nome_ficheiro.c -o nome_executavel
É também aconselhado utilizar a opção -Wall que, durante o processo de compilação, irá mostrar
warnings relativos a eventuais problemas que possam existir no código. De salientar que mesmo
que estes warnings sejam lançados, a não ser que exista algum erro, que o código irá ser compilado
na mesma. Estes avisos servem para dirigir o programador a determinadas partes do código que
eventualmente poderiam ser escritas de uma forma mais correta ou poderem eventualmente gerar
resultados que não são os esperados.
$ gcc nome_ficheiro.c -o nome_executavel -Wall

Execução e Depuração
A execução de um programa é realizada através da invocação do seu nome na linha de comandos.
Assim para executar o programa acima criado:
$ ./nome_executavel

A utilização do “./” em frente do nome é necessária para que o bash procure o nome na pasta em
que foi criado o executável.
Existe outra forma de definir a pasta onde se encontram os programas executáveis do utilizador,
através da modificação da variável de ambiente (environment) PATH, que indica ao interpretador de
comandos onde deve procurar os comandos executáveis. Por exemplo, o comando:

SO-2022/2023-João Pavia e Daniel Silveira 5


$ PATH=$PATH:/home/aluno/a123456/guiao1

adiciona à variável PATH o caminho para a pasta guiao1 onde estão armazenados os ficheiros
deste trabalho. No caso do programa apresentar erros na sua execução que sejam difíceis de
encontrar, pode-se recorrer ao GNU Debugger, uma aplicação que permite realizar a execução do
programa de forma controlada.
Para tal é necessário compilar o programa com a opção -g de forma a que o executável guarde
informação adicional sobre o programa (tabela de símbolos, dentre outros):
$ gcc nome_ficheiro.c -g -o nome_executavel

O debugger é de seguida invocado através do comando:


$ gdb nome_executavel

Desta forma, o debugger toma o controlo da sessão, ou seja, os comandos inseridos serão agora
por ele interpretados, e não pela bash. Assim, a prompt que aparece agora é o seguinte:
(gdb)

As opções desta ferramenta são múltiplas pelo que convém consultar o manual de utilização,
através da invocação do comando man gdb (ou consultando o manual online).

As opções mais utilizadas são as seguintes:


▪ l: para listar o código fonte do ficheiro
▪ b: para colocar um breakpoint (ponto de paragem)
▪ r: para lançar a execução do programa
▪ s: para executar o programa passo a passo

Exemplo:

(gdb) l
1 main()
2 {
3 printf("Hello\n");
4 }
(gdb) b 3
Breakpoint 1 at 0x804837c: file hello.c, line 3.
(gdb) r
Starting program: /home/aluno/a123456/hello
Breakpoint 1, main () at hello.c:3
3 printf("Hello\n");
(gdb) s
Hello
4 }

Como se pode ver no exemplo a listagem, inserção de um breakpoint, execução do programa que
pára no breakpoint inserido, e a execução passo a passo da instrução printf. O programa poderia
ser assim executado passo a passo até se descobrir a eventual causa de erro.

Utilização de bibliotecas de funções


Um programa pode utilizar funções definidas externamente tanto noutros ficheiros-fonte como em
módulos objeto já previamente compilados. Vamos agora ver como tratar cada um destes casos.

SO-2022/2023-João Pavia e Daniel Silveira 6


Ligação de múltiplos ficheiros-fonte
Se na geração de um executável quisermos incluir um segundo ficheiro-fonte, que contém uma
biblioteca com funções de suporte, então é preciso adicioná-lo à lista da seguinte forma:
gcc nome_ficheiro.c nome_biblioteca.c -o nome_executavel

Ligação com bibliotecas em módulos-objeto


Se pretendermos utilizar funções de bibliotecas previamente compiladas, então devemos compilar
o ficheiro-fonte e ligar o módulo-objeto resultante com o módulo-objeto da biblioteca da seguinte
forma:
gcc nome_ficheiro.c -c
gcc nome_ficheiro.o nome_biblioteca.o -o nome_executavel
Ligação com bibliotecas integradas
Existem várias bibliotecas com funções muito úteis que estão habitualmente disponíveis num
ambiente de desenvolvimento em Linux (contidas no diretório /usr/lib32). As que iremos utilizar
são as seguintes:
• libc – contem as funções especificadas no padrão ANSI/ISO C (incluída por omissão)
• libm – contem as funções matemáticas (incluída com -lm)
• librt – biblioteca com extensões de tempo-real (incluída com -lrt)
• libpthread – biblioteca de threads POSIX (incluída com -lpthread)

A biblioteca libc é incluída automaticamente pelo GCC na produção de um executável. Esta inclui
múltiplos conjuntos de funções tais como as definidas nos ficheiros cabeçalho:
• stdio.h
• stdlib.h
• string.h
• …

As funções printf e scanf têm a sua implementação na biblioteca padrão de C (libc) e podem
ser utilizadas simplesmente através de incluir o ficheiro cabeçalho stdio.h. Já a utilização de
funções de outras bibliotecas, como por exemplo a libm, requerem a indicação ao GCC da
biblioteca a incluir através do parâmetro -l logo seguido da designação da biblioteca. Este
parâmetro pode surgir múltiplas vezes na linha de comando. Um exemplo de utilização de uma
função externa definida numa biblioteca que não é incluída automaticamente é a função que calcula
a potência de um valor:

float powf(float base, float exponent);

O ficheiro fonte que utilizar esta função deve incluir no início o ficheiro math.h (que define apenas
a interface da função). O comando GCC para geração do executável deverá ser:

gcc nome_ficheiro.c -o nome_executavel -lm

Makefiles
Um makefile é o ficheiro que automatiza a compilação de um projecto. Este permite não só a
compilação, mas também a limpeza dos ficheiros binários criados e a sua instalação no sistema
operativo. Permite ainda a criação de variáveis globais que serão tidas em conta na execução do
makefile. A compilação em C é realizada da seguinte forma

SO-2022/2023-João Pavia e Daniel Silveira 7


gcc file.c –o file

Para criar um Makefile para o exemplo anterior, o mesmo deve ser criado utilizando um editor de
texto da seguinte forma:
file: file.c
gcc file.c –o file

Ora como podemos verificar o ficheiro Makefile segue a seguinte sintaxe:


target: dependencies
[tab] shell command

Portanto para utilizarmos o Makefile utilizamos o comando make bem como o target no mesmo
caminho (path) onde estão os ficheiros C e o Makefile.
make file

Para visualizar as opções adicionais que estão disponíveis basta digitar man make.

1.2 Múltiplas opções


Podemos criar um Makefile com múltiplas opções, tais as que se ilustram de seguida:

all: file file2


file:
gcc file.c –o file
file2:
gcc file2.c –o file2
clean:
rm –f file file2

De salientar que quando se executa o make sem fornecer nenhum parâmetro, que ele executará
por defeito a opção all, existindo também a opção clean que removerá os ficheiros binários criados.

1.3 Variáveis e comentários


No make existe também a possibilidade de definirmos variáveis comentários conforme o exemplo
que se segue:

#Um comentário

SO-2022/2023-João Pavia e Daniel Silveira 8


#CC, CFLAGS and EXECS são variáveis
CC = gcc
CFLAGS = -Wall
EXECS = file file2
all: $(EXECS)
file:
$(CC) $(CFLAGS) file.c –o file
file2:
$(CC) $(CFLAGS) file2.c –o file2
clean:
rm –f $(EXECS)

De notar que é também comum a utilização da variável LDFLAGS com opções para serem
passadas ao linking.

1.4 Compilação em múltiplas partes


Neste exemplo que se ilustra de seguida a compilação é realizada primeiro para objectos (*.o) e só
depois é criado o executável.

all: executable

executable: source.o main.o


gcc source.o main.o -o executable

source.o: source.c source.h


gcc -c source.c -o source.o

main.o: main.c
gcc -c main.c -o main.o

Exercícios Fundamentais
Num primeiro exercício vamos criar um programa que calcula a dimensão em volume de um
armário, recebendo 3 valores:

• Largura
• Comprimento
• Altura

O programa é composto pelo código que se observa na seguinte imagem:

SO-2022/2023-João Pavia e Daniel Silveira 9


Quando realizarem o “build” do projecto serão capazes de correr o programa bem como de
visualizar o makefile que é gerado automaticamente conforme as seguintes figuras:

SO-2022/2023-João Pavia e Daniel Silveira 10


Como podem observar a formatação deste ficheiro parece algo complicada por ser ainda extensa
em comparação ao que verificámos no ponto 2.5. Esclarecimentos mais objetivos serão abordados
com recurso à apresentação powerpoint onde explicamos os makefiles e onde faremos um outro
exercício neste âmbito.

Exercício Complementar
Após terem feito o primeiro exercício convidamos-vos a criarem um novo source file Lampada.c.
Para tal devem fazer clicar em New → Source File

SO-2022/2023-João Pavia e Daniel Silveira 11


Pedimos-vos que façam um programa em C para calcular o número de lâmpadas 60 watts
necessárias para uma determinada divisão. O programa deverá ler um conjunto de informações,
tais como: tipo, largura e comprimento da divisão. O programa termina quando o tipo de divisão for
igual -1. A tabela abaixo mostra, para cada tipo de divisão, a quantidade de watts por metro
quadrado.
Tipo de divisão Potência
(watt/m2)
0 12
1 15
2 18
3 20
4 22

Dica: Use uma estrutura struct para agrupar logicamente as informações de uma divisão (int tipo
de divisao, float largura e float comprimento). Recorra a uma função (float CalulaArea) para calcular
a área da divisão. Os atributos de entrada serão a largura e comprimento da divisão. Utilize uma
função (float Lampada) para calcular a quantidade de lâmpadas necessárias para a divisão. Os
atributos de entrada serão o tipo de divisão e a metragem (em m2) da divisão.
Observações: Utilize a função ceil(numero) em #include math.h para realizar o arredondamento
para cima.

SO-2022/2023-João Pavia e Daniel Silveira 12

Você também pode gostar