OVH Cloud OVH Cloud

Boost.Build vs make

22 réponses
Avatar
Alain Gaillard
Bonjour à tous,

Je commence à m'intéresser à Boost. Mieux vaut tard que jamais :-)
Du coup je découvre aussi Boost.build.
Alors, en espérant ne pas être trop hors sujet et en espérant ne pas
lancer un troll non plus, je voudrais savoir si tous les expérimentés de
la construction de projets C++ que vous êtes, pensez que Boost.build est
une bonne alternative à make ou bien est-ce que vous préférez restez
avec ce bon vieux make ?

--
Alain

10 réponses

1 2 3
Avatar
Jean-Marc Bourguet
"kanze" writes:

La côté négative, au moins en ce qui me concerne, c'est que
c'est un langage fonctionnelle, ce dont je n'ai absoluement pas
l'habitude. (Qu'est-ce que j'en étais fier quand j'ai réussi à
faire marcher ma première boucle :

multiPatSubst = $(if $(1),$(patsubst $(firstword $(1)),$(2),$(call
multiPatSubst,$(wordlist 2,1000,$(1)),$(2),$(3))),$(3))

Quelque chose qui pour moi est trivial en C++, mais il m'a fallu
un certain temps pour le faire marcher en make.)


Ce qui me gène, c'est que c'est un langage de macro... avec les problèmes
habituels de savoir quand les macros sont substituées, la nécessité de
faire des $(eval...) pour avoir une passe supplémentaire,...

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Avatar
fabien.chene
Alain Gaillard writes:

Je commence à m'intéresser à Boost. Mieux vaut tard que jamais :-)
Du coup je découvre aussi Boost.build.


Peut-être est-il utile de préciser que Boost.build se base sur l'outil
«jam», développé par Perforce, puis sur FTJam, je crois -- Boost.Jam
étant compatible avec jam de Perforce.

Je me demande s'il n'est pas un peu rude de passer directement à
Boost.Jam sans passer par ses ancêtres. Personnellement, je suis parti
du Jam originelle. La documentation qui se trouve sur cette page :
http://www.perforce.com/jam/jam.html est plutôt bonne -- lire en
particulier Jam.html, Jambase.html, Jamfile.html, Getting Started with
Jam - A Tutorial -- et avec un peu de temps et sueur, on parvient à
écrire quelques règles. Et c'est quand même assez puissant !

Ses principaux points forts, AMHA :

-- jam gère tout seul Les dépendances des includes; pas besoin de
demander de l'aide au compilateur via -MM -MD -MT ou du
genre... (il se débrouille aussi avec les dépendances de templates
exporté, mais je crois qu'icc fait tout le boulot)

-- jam est rapide pour construire un gros projet, il fabrique son
arbre de dépendance dès le départ, puis ne travaille plus du tout,
à la différence de la récursivité légendaire de make. Sur le
projet sur lequel je travaille, l'impact a été énorme.

A cause de la limitation du nombre de caractères pour une édition de
lien, de rage, je suis passé à Boost.Jam, c'est compatible et il n'y a
pas ces limitations hallucinantes. Je ne suis pas allé bien plus loin.
Je pense que les extensions de Boost.Jam sont à assimiler dans un
second temps.

ça doit valoir le coup, en plus, à tous les coups, Boost.Jam est
«strongly exception safe» ;-)

Alors, en espérant ne pas être trop hors sujet et en espérant ne pas
lancer un troll non plus, je voudrais savoir si tous les expérimentés
de la construction de projets C++ que vous êtes, pensez que
Boost.build est une bonne alternative à make ou bien est-ce que vous
préférez restez avec ce bon vieux make ?


C'est qui déjà ? :-)

--
Fab

Avatar
Alain Gaillard


Peut-être est-il utile de préciser que Boost.build se base sur l'outil
«jam», développé par Perforce, puis sur FTJam, je crois -- Boost.Jam
étant compatible avec jam de Perforce.


En effet


Je me demande s'il n'est pas un peu rude de passer directement à
Boost.Jam sans passer par ses ancêtres.


Si...
Enfin je commence à y voir un peu clair; (un peu)

Personnellement, je suis parti
du Jam originelle. La documentation qui se trouve sur cette page :
http://www.perforce.com/jam/jam.html est plutôt bonne -- lire en
particulier Jam.html, Jambase.html, Jamfile.html, Getting Started with
Jam - A Tutorial --


Je vais aller voir ça illico.
Merci pour l'info.


Ses principaux points forts, AMHA :

-- jam gère tout seul Les dépendances des includes; pas besoin de
demander de l'aide au compilateur via -MM -MD -MT ou du
genre... (il se débrouille aussi avec les dépendances de templates
exporté, mais je crois qu'icc fait tout le boulot)

-- jam est rapide pour construire un gros projet, il fabrique son
arbre de dépendance dès le départ, puis ne travaille plus du tout,
à la différence de la récursivité légendaire de make. Sur le
projet sur lequel je travaille, l'impact a été énorme.


Oui en effet j'ai remarqué ça. Deux arguments de poids en faveur de
Boost.Build.

C'est qui déjà ? :-)


LOL


--
Alain

Avatar
kanze
Alain Gaillard wrote:

La côté négative, au moins en ce qui me concerne, c'est que
c'est un langage fonctionnelle, ce dont je n'ai absoluement pas
l'habitude.


Moi j'aime bien les langages fonctionnels.

(Qu'est-ce que j'en étais fier quand j'ai réussi à
faire marcher ma première boucle :


LOL.
Ca me rappelle comme j'étais fier quand j'ai écrit mes
premières lignes de Haskell ;)


Je crois que c'est général. Il y a quelque chose de spécial la
première fois qu'on réussit quelque chose dans un paradigme
qu'on ne connaissait pas avant.

multiPatSubst = $(if $(1),$(patsubst $(firstword $(1)),$(2),$(call
multiPatSubst,$(wordlist 2,1000,$(1)),$(2),$(3))),$(3))


Heu oui, bon, on dirait qu'on a là une fonction récursive.


C'est une fonction récursive. C'est le seul constructe de boucle
en GNU make.

Mais ce qu'on ne dirait pas c'est que la syntaxe soit très
élégante non plus.


Pour ça, c'est bien make:-). (Encore que les paramètres
positionnels n'aident en rien.)

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
kanze
Jean-Marc Bourguet wrote:
"kanze" writes:

La côté négative, au moins en ce qui me concerne, c'est que
c'est un langage fonctionnelle, ce dont je n'ai absoluement pas
l'habitude. (Qu'est-ce que j'en étais fier quand j'ai réussi à
faire marcher ma première boucle :

multiPatSubst = $(if $(1),$(patsubst $(firstword $(1)),$(2),$(call
multiPatSubst,$(wordlist 2,1000,$(1)),$(2),$(3))),$(3))

Quelque chose qui pour moi est trivial en C++, mais il m'a fallu
un certain temps pour le faire marcher en make.)


Ce qui me gène, c'est que c'est un langage de macro... avec
les problèmes habituels de savoir quand les macros sont
substituées, la nécessité de faire des $(eval...) pour avoir
une passe supplémentaire,...


Sans parler du problème à savoir combien de fois il faut
redoubler les $ pour qu'ils soient évalués au bon moment, ni des
deux types d'affectation:-).

Il a d'une part tous les problèmes d'un langage qui s'est
développé de façon ad hoc, un feature à la fois (problème qu'on
connaît bien du C++ -- mais le point du départ était encore
bien pire que le C), auquel on ajoute des problèmes associés à
un langage où le programme, les données qu'il manipule, et le
résultat ne sont pas proprement séparés : c'est, je crois, ce
que tu veux dire par « langage de macro », mais le problème
est à mon avis plus général, et touche aussi des langages du
genre TeX ou... le méta-langage des templates en C++.

Si on reflechit le problème qu'on veut resoudre avec lui en
termes de programme, en revanche, on trouve que c'est en général
un programme très, très simple. On y arrive donc, malgré les
faiblesses du langage. Mais c'est vrai qu'une solution à partir
des scripts de shell, qui génèrent chaque fois un fichier de
make très simple, serait peut-être plus simple. J'avoue que je
n'y avais pas pensé -- mon système de build est aussi le
résultat d'une accrétion graduelle, à partir d'un fichier de
make tout à fait classique au départ. Même la réécriture que je
suis en train de finir à commencer comme un simple coup de
balai ; après tant d'accrétions, je sentais le besoin d'un coup
de balai.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
Jean-Marc Bourguet
"kanze" writes:

Jean-Marc Bourguet wrote:
"kanze" writes:

La côté négative, au moins en ce qui me concerne, c'est que
c'est un langage fonctionnelle, ce dont je n'ai absoluement pas
l'habitude. (Qu'est-ce que j'en étais fier quand j'ai réussi à
faire marcher ma première boucle :

multiPatSubst = $(if $(1),$(patsubst $(firstword $(1)),$(2),$(call
multiPatSubst,$(wordlist 2,1000,$(1)),$(2),$(3))),$(3))

Quelque chose qui pour moi est trivial en C++, mais il m'a fallu
un certain temps pour le faire marcher en make.)


Ce qui me gène, c'est que c'est un langage de macro... avec
les problèmes habituels de savoir quand les macros sont
substituées, la nécessité de faire des $(eval...) pour avoir
une passe supplémentaire,...


Sans parler du problème à savoir combien de fois il faut
redoubler les $ pour qu'ils soient évalués au bon moment,


Là on a un problème supplémentaire: il y a deux programmes utilisent $:
make et le shell, et le code le second est généré par le premier.

ni des deux types d'affectation:-).

Il a d'une part tous les problèmes d'un langage qui s'est
développé de façon ad hoc, un feature à la fois (problème qu'on
connaît bien du C++ -- mais le point du départ était encore
bien pire que le C), auquel on ajoute des problèmes associés à
un langage où le programme, les données qu'il manipule, et le
résultat ne sont pas proprement séparés : c'est, je crois, ce
que tu veux dire par « langage de macro », mais le problème
est à mon avis plus général, et touche aussi des langages du
genre TeX ou... le méta-langage des templates en C++.


Par langage de macro, j'entendais un langage défini par substitution
textuelle sans considération pour les autres structures syntaxiques
présentes. C'est effectivement le cas de TeX, mais pas celui des templates
en C++.

Si on reflechit le problème qu'on veut resoudre avec lui en
termes de programme, en revanche, on trouve que c'est en général
un programme très, très simple. On y arrive donc, malgré les
faiblesses du langage. Mais c'est vrai qu'une solution à partir
des scripts de shell, qui génèrent chaque fois un fichier de
make très simple, serait peut-être plus simple. J'avoue que je
n'y avais pas pensé -- mon système de build est aussi le
résultat d'une accrétion graduelle, à partir d'un fichier de
make tout à fait classique au départ. Même la réécriture que je
suis en train de finir à commencer comme un simple coup de
balai ; après tant d'accrétions, je sentais le besoin d'un coup
de balai.


Je ne suis pas sûr que la génération de makefile m'enchante. En tout cas,
je n'aime pas beaucoup les deux tentatives que je connais (imake et
automake).

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org



Avatar
kanze
Jean-Marc Bourguet wrote:
"kanze" writes:


[...(concernant GNU make)]
Sans parler du problème à savoir combien de fois il faut
redoubler les $ pour qu'ils soient évalués au bon moment,


Là on a un problème supplémentaire: il y a deux programmes
utilisent $: make et le shell, et le code le second est généré
par le premier.


Aussi, mais là, c'est assez facile : si tu veux l'expansion par
le shell, il faut rédoubler les $, sinon non. Le probème, c'est
qu'en cas d'eval, make lui-même traite le texte deux fois.

ni des deux types d'affectation:-).

Il a d'une part tous les problèmes d'un langage qui s'est
développé de façon ad hoc, un feature à la fois (problème qu' on
connaît bien du C++ -- mais le point du départ était encore
bien pire que le C), auquel on ajoute des problèmes associés à
un langage où le programme, les données qu'il manipule, et le
résultat ne sont pas proprement séparés : c'est, je crois, ce
que tu veux dire par « langage de macro », mais le problème
est à mon avis plus général, et touche aussi des langages du
genre TeX ou... le méta-langage des templates en C++.


Par langage de macro, j'entendais un langage défini par
substitution textuelle sans considération pour les autres
structures syntaxiques présentes. C'est effectivement le cas
de TeX, mais pas celui des templates en C++.

Si on reflechit le problème qu'on veut resoudre avec lui en
termes de programme, en revanche, on trouve que c'est en général
un programme très, très simple. On y arrive donc, malgré les
faiblesses du langage. Mais c'est vrai qu'une solution à partir
des scripts de shell, qui génèrent chaque fois un fichier de
make très simple, serait peut-être plus simple. J'avoue que je
n'y avais pas pensé -- mon système de build est aussi le
résultat d'une accrétion graduelle, à partir d'un fichier de
make tout à fait classique au départ. Même la réécriture que je
suis en train de finir à commencer comme un simple coup de
balai ; après tant d'accrétions, je sentais le besoin d'un coup
de balai.


Je ne suis pas sûr que la génération de makefile m'enchante.
En tout cas, je n'aime pas beaucoup les deux tentatives que je
connais (imake et automake).


C'est vrai. Ni l'un ni l'autre ne me plaît pas particulièrement
non plus (mais je ne connais pas automake assez pour vraiment
juger). Mais les deux essaient plus de généricité que ce auquel
je pensais.

Vue ce que les autres ont dit de jam, je crois que je vais y
jeter un coup d'oeil. (Mais je finis le système à base de GNU
make, ne serait-ce que pour l'expérience en programmation
fonctionnelle qu'il me donne:-).)

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
kanze
Fabien Chêne wrote:

[en ce qui concerne jam...]
Ses principaux points forts, AMHA :

-- jam gère tout seul Les dépendances des includes; pas besoin de
demander de l'aide au compilateur via -MM -MD -MT ou du
genre... (il se débrouille aussi avec les dépendances de templates
exporté, mais je crois qu'icc fait tout le boulot)


Je viens d'y jeter un coup d'oeil rapide aux docs. Et je suis
tombé sur un os. Justement, parce qu'il évalue les dépendances
lui-même, il utilise des règles différentes que le compilateur,
et en particulier : « Also, scanning for regular expressions
only works where the included file name is literally in the
source file. It can't handle languages that allow including
files using variable names (as the Jam language itself does). »
Et aussi, comme le C et le C++. Ça veut dire que dans la
pratique, je ne pourrais pas m'en servir, parce que j'ai bien
des choses du genre :
#include GB_dependentInclude(conf,gb/config.hh)
#include GB_dependentInclude(comp,gb/compiler.hh)
#include GB_dependentInclude(sysFamily,gb/system.hh)
dans tous mes fichiers. C'est bien beau, mais si ça ne marche
pas pour le C et le C++, ça ne m'est pas bien utile.

Peut-être une des extensions de Boost règlent ce problème ?

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Avatar
fabien.chene
"kanze" writes:

Fabien Chêne wrote:

[en ce qui concerne jam...]
Ses principaux points forts, AMHA :

-- jam gère tout seul Les dépendances des includes; pas besoin de
demander de l'aide au compilateur via -MM -MD -MT ou du
genre... (il se débrouille aussi avec les dépendances de templates
exporté, mais je crois qu'icc fait tout le boulot)


Je viens d'y jeter un coup d'oeil rapide aux docs. Et je suis
tombé sur un os. Justement, parce qu'il évalue les dépendances
lui-même, il utilise des règles différentes que le compilateur,
et en particulier : « Also, scanning for regular expressions
only works where the included file name is literally in the
source file. It can't handle languages that allow including
files using variable names (as the Jam language itself does). »
Et aussi, comme le C et le C++. Ça veut dire que dans la
pratique, je ne pourrais pas m'en servir, parce que j'ai bien
des choses du genre :
#include GB_dependentInclude(conf,gb/config.hh)
#include GB_dependentInclude(comp,gb/compiler.hh)
#include GB_dependentInclude(sysFamily,gb/system.hh)
dans tous mes fichiers. C'est bien beau, mais si ça ne marche
pas pour le C et le C++, ça ne m'est pas bien utile.


C'est bel et bien un os. La documentation de jam reconnait que l'arbre
de dépendance construit n'est pas exact, et que jam a plutôt tendance
à rajouter des dépendances qu'à en ommettre.

Si on considère cet exemple :

$ cat toto.cpp
//------------------------------
#ifdef FLAG
# include "toto.hpp"
#else
# include "titi.hpp"
#endif
//------------------------------

$ cat Jamfile
#-------------------------------
C++ = g++ ;
LINK = g++ ;
Library libtoto : toto.cpp ;
#-------------------------------

$ jam -dm -n

make -- all
time -- all: unbound
make -- shell
time -- shell: unbound
make -- first
time -- first: unbound
made stable first
made stable shell
make -- files
time -- files: unbound
made stable files
make -- lib
time -- lib: unbound
make -- libtoto.a
time -- libtoto.a: missing
make -- libtoto.a(toto.o)
time -- libtoto.a(toto.o): missing
make -- toto.o
time -- toto.o: missing
make -- toto.cpp
time -- toto.cpp: Mon Sep 25 01:02:32 2006
make -- toto.cpp
time -- toto.cpp: unbound
make -- toto.hpp
time -- toto.hpp: Mon Sep 25 00:37:56 2006
made* newer toto.hpp
make -- titi.hpp
time -- titi.hpp: Mon Sep 25 01:03:52 2006
made* newer titi.hpp
made* newer toto.cpp
made+ missing toto.o
made+ update libtoto.a(toto.o)
made+ update libtoto.a
made update lib
make -- exe
time -- exe: unbound
made stable exe
make -- obj
time -- obj: unbound
made update obj
made update all

Une dépendance est en trop (toto.hpp, ou titi.hpp). C'est documenté,
et ce n'est pas vraiment la fin du monde AMHA.

En revanche, cet exemple, comme tu le soulignes, n'introduit
silencieusement aucunes dépendances -- HDRRULE applique NOCARE au cas
où le fichier soit absent.

cat toto.cpp
//------------------------------
#define DEPENDANT_INCLUDE( s ) #s
#include DEPENDANT_INCLUDE( toto.hpp )
//------------------------------

cat Jamfile
#-------------------------------
C++ = g++ ;
LINK = g++ ;
Library libtoto : toto.cpp ;
#-------------------------------

$ jam -dm -n
make -- all
time -- all: unbound
make -- shell
time -- shell: unbound
make -- first
time -- first: unbound
made stable first
made stable shell
make -- files
time -- files: unbound
made stable files
make -- lib
time -- lib: unbound
make -- libtoto.a
time -- libtoto.a: missing
make -- libtoto.a(toto.o)
time -- libtoto.a(toto.o): missing
make -- toto.o
time -- toto.o: missing
make -- toto.cpp
time -- toto.cpp: Mon Sep 25 01:10:05 2006
made* newer toto.cpp
made+ missing toto.o
made+ update libtoto.a(toto.o)
made+ update libtoto.a
made update lib
make -- exe
time -- exe: unbound
made stable exe
make -- obj
time -- obj: unbound
made update obj
made update all

Il y a donc bel et bien un problème, Jam ne fonctionne que pour le
sous ensemble C++03{§16.2.4}. On pourrait imaginer redéfinir HDRRULE,
HDRSCAN, HDRPATTERN, pour que cela fonctionne avec en particulier les
macros GB_dependentInclude, mais ce ne serait alors qu'un hack.
Je pense qu'il faudrait remonter le problème à boost, afin qu'ils
documentent clairement le problème -- au minimum.

Peut-être une des extensions de Boost règlent ce problème ?


La documentation de ce point est identique à celle de classic
jam; Donc apparemment non.

--
Fab


Avatar
Alain Gaillard

Merci à tous ceux qui ont participé à la discussion leurs remarques et
informations m'ont été très utiles :-).
Hormis la limitation détectée par James, c'est quand même pas mal
Boost.Build :-)

--
Alain
1 2 3