Malo mi je neobično to što želiš da uradiš, moguće je da postoji bolje rešenje, više u duhu C++-a, iako komplikovanije (nekakve fabrike mi se vrzmaju po glavi...) S druge strane, zaista biva s vremena na vreme da je potrebno „spolja“ izvršiti neku izmenu na izvornoj datoteci, kao to što ti sada nameravaš. Tako da ću nešto o tome da kažem.
Obično se te spoljašnje izmene u kodu ne sprovode preko preprocesorskih naredbi, ne samo jer je to možda nemoguće, već i zato što često dovode do rusvaja kada se pokušaju upotrebiti van uobičajenih namena. Umesto toga, taj deo posla se uglavnom prebacuje na
sistem za gradnju.
Na Linuksu, najčešći sistem za gradnju je
make, uz nadgradnju u vidu kombinacije Automejk/Autokonf koje se oslanjaju na njega (to je ono što stvara sveprisutno
./configure && make && make install za izvorne pakete). Međutim, iako u širokoj upotrebi i dobro podržan, ovaj lanac alata malo pokazuje godine, tako da počinju sve češće da se koriste neki noviji sistemi. Jedan od izgleda omiljenijih (npr. KDE uskoro prelazi na njega), jeste Skons (
Scons); to je u stvari sistem naredbi za gradnju na bazi pitona, tako da se u njegovim spravljačkim datotekama mogu koristiti sve pitonske baterije.
Za primer koji si naveo, imaš ovakve izvore u jednom direktorijumu:
Code:
// player.h
#ifndef PLAYER_H
#define PLAYER_H
class player {};
#endif
Code:
// igrach1.h
#ifndef IGRACH1_H
#define IGRACH1_H
#include "player.h"
class igrach1 : public player {};
#endif
Code:
// igrach2.h
#ifndef IGRACH2_H
#define IGRACH2_H
#include "player.h"
class igrach2 : public player {};
#endif
Onda recimo napišeš glavni program ovako:
Code:
// proba.cc
#include <iostream>
using namespace std;
#include "igrachi-spec.h"
int main ()
{
#include "igrachi-spec.cc"
return 0;
}
gde će ova uključenija da navedu odgovarajuća zaglavlja i kod za alociranje onih igrača, a napraviće ih Skons. U istom direktorijumu napraviš spravljačku datoteku po imenu
SConstruct (mora baš tako da se zove, sa sve velikim i malim slovima), u kojoj se nalazi ovo:
Code:
# SConstruct - napisao Pera Haker
# -*- coding: utf8 -*-
import os
import re
# Sve stavke iz tekućeg direktorijuma.
files = os.listdir('.')
# Regiz za imena unosa koje želimo da izdvojimo.
sito = re.compile('igrach[0-9]+\.h')
# Filtriraj listu stavki u direktorijumu.
igrachi = filter(sito.search, files)
# Pravimo posebnu datoteku koja uključuje zaglavlja svih igrača.
fincl = open('igrachi-spec.h', 'w')
for igrach in igrachi:
fincl.write('#include "%s"\n' % igrach);
fincl.close()
# Pravimo posebnu datoteku koja sadrži kod za stvaranje svih igrača.
fcode = open('igrachi-spec.cc', 'w')
fcode.write('int npls = %d;\n' % len(igrachi))
fcode.write('player *p[npls];\n')
ind = 0;
for igrach in igrachi:
fcode.write('p[%d] = new %s(/*argumenti*/);\n' % (ind, igrach[:-2]))
ind += 1
fcode.close()
# Skonsova naredba za spravljanje programa.
# (deo CPPPATH... kaže Skonsu da postoji zavisnost od nekih zaglavlja)
Program('proba.cc', CPPPATH = '.')
Zatim u tom direktorijumu izvršiš naredbu
scons, koja će automatski da pokupi datoteku
SConstruct i sagradi program na osnovu nje:
Code:
$ scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
g++ -I. -c -o proba.o proba.cc
g++ -o proba proba.o
scons: done building targets.
Ako opet izvršiš isto, ne dirajući izvore, dobićeš ovo:
Code:
$ scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
scons: `.' is up to date.
scons: done building targets.
To je Skons uvideo da nije bilo nikakvih izmena u izvorima, pa je odlučio da ne gradi program ponovo. Čim izmeniš neki izvor, Skons će primetiti i ponovo sagraditi program.