Make/CVS example 1: Difference between revisions

From Wiki**3

(Redirected page to ist:Make/CVS example 1)
 
(9 intermediate revisions by the same user not shown)
Line 1: Line 1:
{{TOCright}}
#REDIRECT [[ist:Make/CVS example 1]]
== The Problem (in Portuguese) ==
 
Considere quatro ficheiros <tt><span style="color: #990000">recurs.cpp</span></tt> (contendo a função <tt><span style="color: #990000">factrecurs</span></tt>), <tt><span style="color: #990000">recurs.h</span></tt> (contendo a declaração da função  <tt><span style="color: #990000">factrecurs</span>),</tt> <tt><span style="color: #990000">iter.cpp</span></tt> (contendo a função <tt><span style="color: #990000">factiter</span> </tt>), <tt><span style="color: #990000">iter.h</span></tt> (contendo a declaração da função <tt><span style="color: #990000">factiter</span>)</tt> e <tt><span style="color: #990000">main.cpp</span></tt> (contendo a função <tt><span style="color: #990000">main</span></tt> que invoca sequencialmente ambas as funções anteriores e que inclui <tt><span style="color: #990000">recurs.h</span></tt> e <tt><span style="color: #990000">iter.h</span></tt>).
 
# Construa, com estes cinco ficheiros, um projecto designado <strong>factorial</strong>, indicando os comandos para o colocar sob o controlo de versões do CVS. Admita que o repositório já existe em <tt><span style="color: #990000">/cvs</span></tt>.
# Construa uma <tt><span style="color: #990000">Makefile</span></tt> para gerar o executável  <tt><span style="color: #990000">fact</span></tt>, a partir dos ficheiros anteriores. Indique os comandos necessários para colocar a <tt><span style="color: #990000">Makefile</span></tt> no repositório CVS.
# Considere agora que vai ter dois executáveis, cada um invocando a sua função. Indique as alterações à <span style="color: #990000"> <tt>Makefile</tt></span> para que passe a gerar os executáveis <tt><span style="color: #990000">recurs</span></tt> e <tt><span style="color: #990000">iter</span></tt>, utilizando ambos o mesmo ficheiro <tt><span style="color: #990000">main.cpp</span></tt> (mas diferentes implementações do factorial). Indique as operações do CVS para criar a nova versão do projecto, assumindo que o projecto est&aacute; checked-out no directório corrente.
# Considere uma nova versão do projecto: pretende-se construir um único executável <span style="color: #990000">  <tt>fact</tt></span>, mas a escolha da implementação do factorial é efectuada em tempo de execução. Considere que os ficheiros <tt><span style="color: #990000">recurs.cpp</span></tt> e <tt><span style="color: #990000">recurs.h</span></tt> existem num subdirectório <tt><span style="color: #990000">recurs</span></tt> e, analogamente, existe um directório <tt><span style="color: #990000">iter</span></tt> para a outra versão. Cada um dos conjuntos apresenta agora a mesma interface para a função que calcula o factorial: <tt><span style="color: #990000">fact</span></tt>. Construa duas bibliotecas dinâmicas, ambas designadas por <span style="color: #990000"><tt>fact.so</tt></span>, cada uma em seu directório (<tt><span style="color: #990000">recurs/fact.so</span></tt> e <tt><span style="color: #990000">iter/fact.so</span></tt>). A selecção da variante a utilizar faz-se definindo a variável de ambiente <tt><span style="color: #990000">LD_LIBRARY_PATH</span></tt> com o directório apropriado. Indique quais os ficheiros iniciais modificados, face à alínea anterior, a nova <tt><span style="color: #990000">Makefile</span></tt> e os comandos CVS necessários para que o repositório passe a conter a nova versão.
# Modifique a alínea anterior para que o utilizador possa escolher a variante a utilizar através de um argumento na linha do comando <tt><span style="color: #990000">fact</span></tt>, respectivamente <tt><span style="color: #990000">recurs</span></tt> ou <tt><span style="color: #990000">iter</span></tt>. Indique quais os ficheiros iniciais modificados, a nova <tt><span style="color: #990000">Makefile</span></tt> e os comandos CVS necessários para registar a nova versão.
 
== Implementation ==
The following sections present possible implementations.
 
All shell commands are prefixed with <tt>prompt%</tt> (their output is presented for explanation purposes only and is not required to answer the problem).
 
It is assumed that the <tt>CVSROOT</tt> variable has been defined:
<bash>
  export CVSROOT=/cvs
</bash>
 
=== Step 1: Building the Project ===
 
Assuming that all files are in directory <tt>/some/temporary/directory</tt>, the following commands may be used to create the '''factorial''' project ().
 
  prompt% cd /some/temporary/directory
  prompt% cvs import factorial david initial
  N factorial/recurs.cpp
  N factorial/recurs.h
  N factorial/iter.cpp
  N factorial/iter.h
  N factorial/main.cpp
 
Then, after import is complete, we can check-out a fresh copy of the project and change to that directory:
 
  prompt% cvs co factorial
  U factorial/iter.cpp
  U factorial/iter.h
  U factorial/main.cpp
  U factorial/recurs.cpp
  U factorial/recurs.h
  prompt% cd factorial
 
=== Step 2: Building the Makefile ===
 
The following is a simple Makefile for building the executable.
<text>
fact: main.o iter.o recurs.o
 
recurs.o: recurs.cpp
        g++ -c recurs.cpp
 
iter.o: iter.cpp
        g++ -c iter.cpp
 
main.o: main.cpp iter.h recurs.h
        g++ -c main.cpp
</text>
 
The following is a slightly more complex Makefile for doing exactly the same thing. The possible advanytage of using this version is that it automates a few error-prone tasks (such as keeping dependencies up to date).
<text>
.PHONY: all depend
 
CXXFILES = $(wildcard *.cpp)
CXXHEADS = $(wildcard *.h)
OFILES  = $(CXXFILES:%.cpp=%.o)
PROG    = fact
 
%.o: %.cpp
        $(CXX) $(CXXFLAGS) -c $< -o $@
 
all: depend $(PROG)
 
$(PROG): $(OFILES)
        $(CXX) -o $@ $^
 
depend: .makedeps
 
.makedeps: $(CXXFILES) $(CXXHEADS)
        $(CXX) $(CXXFLAGS) -MM $(CXXFILES) > .makedeps
 
-include .makedeps
</text>
 
<tt>.PHONY</tt> indicates targets that do not correspond to actual files and attempts should not be made to build them (e.g. from implicit rules). <tt>all</tt> depends on <tt>depend</tt> to force the Makefile to keep its dependencies updated without explicitly calling "make depend".
 
Finally, to put the Makefile under CVS control, the following two commands would be needed:
 
  prompt% cvs add Makefile
  cvs add: use `cvs commit' to add this file permanently
 
  prompt% cvs commit
  /cvs/factorial/Makefile,v  <--  Makefile
  initial revision: 1.1
 
=== Step 3: The New Makefile ===
 
The following Makefile (a straightforward adaptation of the previous one) would solve the problem:
<text>
.PHONY: all depend
 
CXXFILES = $(wildcard *.cpp)
CXXHEADS = $(wildcard *.h)
ITER = iter
RECURS = recurs
 
%.o: %.cpp
        $(CXX) $(CXXFLAGS) -c $< -o $@
 
all: depend $(ITER) $(RECURS)
 
$(ITER): main.o iter.o
        $(CXX) -o $@ $^
 
$(RECURS): main.o recurs.o
        $(CXX) -o $@ $^
 
depend: .makedeps
 
.makedeps: $(CXXFILES) $(CXXHEADS)
        $(CXX) $(CXXFLAGS) -MM $(CXXFILES) > .makedeps
 
-include .makedeps
</text>
 
Note that we are assuming that the appropriate changes have been made to the code in the C++ files to allow for a single interface (the function is now called simply "fact") and multiple implementations.
 
Regarding CVS, only updates and commits are needed at this stage (new versions of the files will be sent to the repository).

Latest revision as of 18:41, 6 December 2018