Forum Linux.debian/ubuntu shell et make

Posté par  . Licence CC By‑SA.
Étiquettes :
0
3
oct.
2020

salut,
je n'ai jamais regardé de pres comment make fonctionnait et je m'y met
jai regardé de la doc en anglais mais je n'ai pas tout compris
https://www.gnu.org/software/make/manual/make.pdf
du coup j'ai besoin de quelques explications et quelques revisions du shell:

à quoi sert le @ dans une sequence make? par exemple

id :
@echo blabla

ensuite le .PHONY: element1, element2
de ce que j'ai compris cela sert à "éviter" des élements dans l'execution d'une sequence du fichier ?
est ce que le .PHONY s'applique uniquement au bloc d'instruction qui le suit? (par exemple s'il y a un .PHONY avant un bloc et un .PHONY apres un bloc)

qu'est ce qu'un bloc entre define endef?

qu'est ce que %.zip? (le signe % designe quoi?) et est ce que ca peut faire office de *?
par exemple que produit ce bout de code dans un make:

%: %.xml
@cp $< file.xml

enfin les variables $ imbriquées:
par exemple quelles déclarations de variables nécessite le code suivant?

export $(word 1, $(subst =, , $(1))) := $(word 2, $(subst =, , $(1)))

merci

  • # ?

    Posté par  . Évalué à 2. Dernière modification le 04 octobre 2020 à 09:49.

    Pas bcp de réponses.. bon j'ai trouvé de la doc en francais que je vais lire.
    http://homepages.laas.fr/matthieu/cours/make/tpp.pdf
    Mais mon objectif ici nest pas de faire un fichier make mais de bien comprendre un fichier makefile qui utilise make.
    Existerait il un utilitaire qui recrée la serie de commande shell qu'un fichier makefile produit?
    merci

    • [^] # Re: ?

      Posté par  . Évalué à 4.

      0) des fois que tu serais passé à côté : trouve un éditeur qui préserve les tabulations. Quand on écrit du code source, on bannit les tabulations généralement, mais dans un Makefile, c'est indispensable de les préserver. Je dis ça juste pour être certain de pas passer à côté.

      1) pas beaucoup de réponse, certes. Je me demande si on est pas tous démangés par un RTFM … En moins méchant, il y aurait ça makefile tutorial
      Le tuto que tu as trouvé n'est pas trop mal, mais un peu aride. La syntaxe des Makefile est tellement vaste que ça n'est pas sur un seul résultat de recherche que tu apprendras tout. Évidemment, c'est mieux de savoir produire un exécutable à la main pour comprendre l'intérêt de l'automatisation par Makefile (même si make peut servir à plein de chose qui n'ont rien à voir avec la production d'exécutable).

      2) essaye ça :

      -n, --just-print, --dry-run, --recon
           Print the commands that would be executed, but do not execute them (except in certain circumstances).
      

      Ça pourrait t'afficher ce qui se passe sans le faire réellement. Cf point suivant pour l'usage du conditionnel.

      3) ça fait longtemps, très longtemps, que je n'ai pas écrit un Makefile à la main. Le plus souvent, j'utilise Qt et son qmake, un générateur de Makefile, à partir d'une description plus simple du projet. Il existe plein d'autres solutions, mais c'est quand même bien de savoir comment fonctionne un Makefile, en cas de pépin, ça permet d'en trouver la cause.

      4) pratique, teste, essaye, bricole. Ce genre de trucs ne vient qu'avec le temps. Quand j'ai vu make, awk et cie à la fac, j'ai pas pigé l'intérêt par rapport à la complexité. Maintenant, je ne peux plus m'en passer et je trouve ça simple. L'expérience ne peut pas venir en 5 minutes.

      • [^] # Re: ?

        Posté par  (site web personnel) . Évalué à 3.

        si on est pas tous démangés par un RTFM

        chez moi, man make m'indique que la doc' est plus complète avec un info make :-)

        mais, oui, make soit tu pratiques, soit tu le fais générer (non, je ne vais pas suggérer autogen / autoconf / automake ce serait sadique :D)

        • pour les %.o : regarder du côté des patterns, ça fait globalement ce que tu dis
        • pour .PHONY : c'est pour indiquer que ce n'est pas un fichier mais, par exemple, une commande qui suit
        • pour le @ : ça n'affiche pas la commande lancée à l'écran
        • pour le $ : tu aurais dû utiliser le formatage Markdown de LinuxFr.org (laisser une ligne blanche, puis ```bash et finir le bloc avec ```) ;cela fait comme en shell on va dire
        export $(word 1, $(subst =, , $(1))) := $(word 2, $(subst =, , $(1)))
      • [^] # Re: ?

        Posté par  . Évalué à 1.

        merci pr le -n --just-print ca fonctionne bien!

      • [^] # Re: ?

        Posté par  (site web personnel) . Évalué à 2.

        3) ça fait longtemps, très longtemps, que je n'ai pas écrit un Makefile à la main.

        Moi ça m'arrive très souvent en fait. Je trouve ça plus pratique de lancer juste un make dans un répertoire, sans avoir à me souvenir exactement des commandes spécifiques :

        • une compilation latex
        • une image povray
        • des fichiers de conf…

        Bien sûr ça ne sont pas des fichiers aussi évolués que ceux générés par un outil tierce, mais ça fait aussi son boulot :)

    • [^] # Re: ?

      Posté par  . Évalué à 1. Dernière modification le 04 octobre 2020 à 15:33.

      je fais une reponse de ce que j'ai trouvé dans la doc. ca me sera toujours utile pr un refresh si j'y reviens dans longtemps

      vocabulaire:
      cible: dependances
      regles

      @ sert à masquer les commandes effectuées par make dans le shell
      a noter que make --just-print affiche quand meme les commandes

      % équivaut à * : cela designe un ensemble de fichiers de facon generique
      si utilisé dans cible: on ne parle plus de regle explicite mais de regle implicite

      %: %.xml regle implicite
      @cp $< file.xml
      copie la 1ere dependance vers le fichier file.xml

      $< : Le nom de la premi`ere dependance. Si les commandes pour
      construire la cible proviennent d’une regle implicite, il s’agit de
      la premiere dependance introduite par la regle implicite.

      '-' en debut de ligne pr ignorer echec

      .PRECIOUS : pour ne pas faire le menage si interrompu en cours de make sur une cible

      PHONY:
      la doc de RMS: "A phony target is one that is not really the name of a file; rather it is just a name for a
      recipe to be executed when you make an explicit request. There are two reasons to use a
      phony target: to avoid a conflict with a file of the same name, and to improve performance.
      If you write a rule whose recipe will not create the target file, the recipe will be executed
      every time the target comes up for remaking."
      en gros utile si la cible n'est pas une fichier à creer

      .SECONDARY
      la doc de RMS: "The targets which .SECONDARY depends on are treated as intermediate files,
      except that they are never automatically deleted."
      en gros les cibles sont des fichiers intermediaires non supprimés

      qu'est ce qu'un bloc entre define endef?
      la doc de RMS : "When the same sequence of commands is useful in making various targets, you can define
      it as a canned sequence with the define directive, and refer to the canned sequence from
      the recipes for those targets. The canned sequence is actually a variable, so the name must
      not conflict with other variable names."
      en gros cest une variable qui peut definir une suite d'instructions à exécuter

      $@ Le nom de la cible de la règle. Si une règle implicite comporte
      plusieurs cibles, c’est la cible qui a déclenché la règle.

      $< Le nom de la première dépendance. Si les commandes pour
      construire la cible proviennent d’une règle implicite, il s’agit de
      la première dépendance introduite par la règle implicite.

      $? Les noms de toutes les dépendances qui sont plus récentes que la
      cible, séparés par des espaces.

      $^ Les noms de toutes les dépendances d’une cible, séparés par des
      espaces.

      $* Le radical associé à une règle implicite. Si la cible est toto.o
      et que la motif dans la règle est %.o, alors $* vaut toto. Cette
      variable est utile pour créer les noms de fichiers voisins.
      Dans le cas des règles explicites, il n’y a pas de motif. Le radical
      est souvent défini comme le nom de la cible sans suffixe. Il vau

    • [^] # Re: ?

      Posté par  . Évalué à 1. Dernière modification le 04 octobre 2020 à 15:54.

      alors jai lu les docs anglaises et francaises et il y a deux trucs que je comprend pas bien dans le makefile que j'essaie de comprendre (en l'occurence il n'y a rien en .c ou en .o, cest une serie de commandes et de manip sur des bdd et du xml).

      pour le shell
      les variables imbriquées (cf question dans le premier post) : rien à voir avec make/makefile,cest du shell mais est ce que vous avez une bonne documentation de reference à me suggerer la dessus pr gagner du temps en recherche de documentation?

      pour le make:

      1. quand jai une cible avec une seule dépendance et rien dans le bloc d'instructions à faire: à quoi ca sert? exemple si j'ai ca dans le makefile
      default: blabla

      et pas de fichier ni de cible blabla initialement

      1. est ce que les cibles default (en minuscule), link, clean sont des cibles avec mot clé réservé? (je ne vois pas de .PHONY pour indiquer que ce ne sont pas des cibles fichiers)

      2. est ce que si j'ai une cible avec des dépendances qui ne sont pas des fichiers mais des cible, est ce que le make execute les instructions contenues dans ces dependances cibles ?

      • [^] # Re: ?

        Posté par  . Évalué à 1. Dernière modification le 04 octobre 2020 à 17:27.

        Un petit refresh pour le shell (bash):

        L'opérateur || signifie exécuter la commande suivante si la commande précédente n'a pas renvoyé 0. Il existe aussi l'opérateur && qui exécute la commande suivante si la commande précédente a renvoyé 0, et enfin ; qui exécute l'opération suivante dans tous les cas.

        Variable Signification
        $0 Nom du script
        $1 Paramètre de position #1
        $2 - $9 Paramètres de position #2 - #9
        ${10} Paramètre de position #10
        $# Nombre de paramètres de position
        "$" Tous les paramètres de position (en un seul mot) *
        "$@" Tous les paramètres de position (en des chaînes séparées)
        ${#
        } Nombre de paramètres sur la ligne de commande passés au script
        ${#@} Nombre de paramètres sur la ligne de commande passés au script
        $? Code de retour de la derniere operation
        $$ Numéro d'identifiant du processus (PID) généré par le script
        $- Options passées au script (utilisant set)
        $_ Dernier argument de la commande précédente
        $! Identifiant du processus (PID) du dernier job exécuté en tâche de fond

        carte de reference

        https://abs.traduc.org/abs-5.3-fr/apb.html

        un bon guide avancé

        https://abs.traduc.org/abs-fr/

        Dans ce que je ne comprend toujours pas il y a les mots clés suivants (pas de man ni de info) :
        word

        subst

        foreach

        filter-out

        wildcard

        type

        word

        shell: est ce que $(shell blabla) appelle la variable SHELL=/bin/bash?
        les variables ne sont pas sensible à la casse (minuscule/majuscules)?

        pr ceux que jai trouvé

        export:
        Exporte le numéro de colonne dans l'environnement de façon à ce qu'il soit disponible plus tard.

        call
        CALL executes a procedure.
        If the procedure has any output parameters, then a result row will be
        returned, containing the values of those parameters.
        fonctionne avec les sql

        eval
        y=eval ls -l # Similaire à y=ls -l
        echo $y # mais les retours chariot sont supprimés parce que la variable
        # n'est pas entre guillemets.
        echo
        echo "$y" # Les retours chariot sont préservés lorsque la variable se
        # trouve entre guillemets.

        strip
        strip modifies the files named in its argument, rather than writing
        modified copies under different names.

        • [^] # Re: ?

          Posté par  . Évalué à 1.

          Et voilà

          fonctions de make :

          shell
          The shell function is unlike any other function other than the wildcard function (see The Function wildcard) in that it communicates with the world outside of make.
          The shell function performs the same function that backquotes (‘`’) perform in most shells: it does command expansion. This means that it takes as an argument a shell command and evaluates to the output of the command.

          export:
          Exporte le contenu d'une variable dans l'environnement ou dans un fichier de façon à ce qu'il soit disponible plus tard.

          word
          $(word n,text)
          Returns the nth word of text. The legitimate values of n start from 1. If n is bigger than the number of words in text, the value is empty. For example,
          $(word 2, foo bar baz)
          returns ‘bar’.

          filter-out
          $(filter-out pattern…,text)
          Returns all whitespace-separated words in text that do not match any of the pattern words, removing the words that do match one or more. This is the exact opposite of the filter function.
          For example, given:
          objects=main1.o foo.o main2.o bar.o
          mains=main1.o main2.o
          the following generates a list which contains all the object files not in ‘mains’:
          (filter-out(mains),$(objects))

          subst
          $(subst from,to,text)
          Performs a textual replacement on the text text: each occurrence of from is replaced by to. The result is substituted for the function call. For example,
          $(subst ee,EE,feet on the street)
          produces the value ‘fEEt on the strEEt’.

          wildcard
          $(wildcard pattern…)
          This string, used anywhere in a makefile, is replaced by a space-separated list of names of existing files that match one of the given file name patterns. If no existing file name matches a pattern, then that pattern is omitted from the output of the wildcard function.

          foreach
          $(foreach var,list,text)
          The first two arguments, var and list, are expanded before anything else is done; note that the last argument, text, is not expanded at the same time. Then for each word of the expanded value of list, the variable named by the expanded value of var is set to that word, and text is expanded. Presumably text contains references to that variable, so its expansion will be different each time.
          The result is that text is expanded as many times as there are whitespace-separated words in list. The multiple expansions of text are concatenated, with spaces between them, to make the result of foreach.

          shell
          The shell function is unlike any other function other than the wildcard function (see The Function wildcard) in that it communicates with the world outside of make.
          The shell function performs the same function that backquotes (‘`’) perform in most shells: it does command expansion. This means that it takes as an argument a shell command and evaluates to the output of the command. The only processing make does on the result is to convert each newline (or carriage-return / newline pair) to a single space. If there is a trailing (carriage-return and) newline it will simply be removed.

          call
          CALL executes a procedure.
          If the procedure has any output parameters, then a result row will be
          returned, containing the values of those parameters.
          fonctionne avec les sql
          $(call variable,param,param,…)
          When make expands this function, it assigns each param to temporary variables (1),(2), etc. The variable $(0) will contain variable. There is no maximum number of parameter arguments. There is no minimum, either, but it doesn’t make sense to use call with no parameters.

          strip
          $(strip string)
          Removes leading and trailing whitespace from string and replaces each internal sequence of one or more whitespace characters with a single space. Thus, ‘$(strip a b c )’ results in ‘a b c’.

          commande shell

          type
          The type command will show you how a specific command will be interpreted if used on the command line.
          type [OPTIONS] FILE_NAME…
          -t renvoie alias (shell alias);function (shell function);builtin (shell builtin);file (disk file);keyword (shell reserved word)
          -a renvoie t et localisation
          -p renvoie le path si executable

          eval
          y=eval ls -l # Similaire à y=ls -l
          echo $y # mais les retours chariot sont supprimés parce que la variable
          # n'est pas entre guillemets.
          echo
          echo "$y" # Les retours chariot sont préservés lorsque la variable se
          # trouve entre guillemets.

          • [^] # Re: ?

            Posté par  . Évalué à 1.

            Jai toujours quelques questions irrésolues :

            quand jai une cible avec une seule dépendance et rien dans le bloc d'instructions à faire: à quoi ca sert? exemple si j'ai ca dans le makefile
            default: blabla
            et pas de fichier ni de cible blabla initialement

            est ce que les cibles default (en minuscule), link, clean sont des cibles avec mot clé réservé? (je ne vois pas de .PHONY pour indiquer que ce ne sont pas des cibles fichiers)

            est ce que si j'ai une cible avec des dépendances qui ne sont pas des fichiers mais des cible, est ce que le make execute les instructions contenues dans ces dependances cibles ?

            jajoute:
            que faut il ajouter à un makefile pour qu'une cible soit systématiquement compilée quelque soit la façon dont on appelle make dans le terminal?

            le symbole ?= est il reglementaire?

            • [^] # Re: ?

              Posté par  . Évalué à 1. Dernière modification le 06 octobre 2020 à 18:04.

              jai trouvé pour ?= qui défini une variable seulement si elle n'est pas déjà définie.
              par contre
              pr le reste..pas trouvé dans la doc.

              une derniere question : une instruction comme celle ci est elle lancée si elle n'est ni une cible ni une dépendance?
              enfin, si elle est dans les instructions d'une cible, est ce qu'elle est lancée?
              ca n'affiche rien avec --just-print: ni cat ni call fonction

              $(foreach a,$(shell cat fichier 2> /dev/null),$(eval $(call fonction,$(a))))

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.