Qu'est-ce que go build build? (allez construire vs allez installer)

106

Les nouveaux programmeurs Go ne savent souvent pas ou sont confus ce que fait la commande fondamentale go build.

Que exactement go buildet les go installcommandes construisent et où vont-ils mettre le résultat / sortie?

icza
la source
go build vs go install
Benyamin Jafari

Réponses:

125

Ce que fait la gocommande dépend de si nous l'exécutons pour un package "normal" ou pour le "main"package spécial .

Pour les packages

  • go build  crée votre package puis rejette les résultats .
  • go installbuilds installe ensuite le package dans votre $GOPATH/pkgrépertoire.

Pour les commandes (package main)

  • go build  construit la commande et laisse le résultat dans le répertoire de travail actuel .
  • go installconstruit la commande dans un répertoire temporaire puis la déplace vers $GOPATH/bin.

À quoi passer go build?

Vous pouvez transmettre des packages aux go buildpackages que vous souhaitez construire. Vous pouvez également transmettre une liste de .gofichiers à partir d'un seul répertoire, qui est ensuite traitée comme la liste des fichiers source spécifiant un seul package.

Si aucun package (chemins d'importation) n'est fourni, la construction est appliquée sur le répertoire courant.

Un chemin d'importation peut contenir un ou plusieurs "..."caractères génériques (auquel cas il s'agit d'un modèle ). ...peut correspondre à n'importe quelle chaîne, par exemple net/...correspond au netpackage et les packages se trouvant dans l'un de ses sous-dossiers. La commande

go build ./...

souvent utilisé pour créer le package dans le dossier actuel et tous les packages récursifs. Cette commande émise dans une racine de projet crée le projet complet.

Pour en savoir plus sur la spécification des packages, exécutez go help packages.

Concernant les modules

La prise en charge préliminaire des modules Go a été introduite dans Go 1.11, et les modules sont devenus par défaut à partir de Go 1.13. Lorsque l' gooutil est exécuté à partir d'un dossier contenant un go.modfichier (ou l'un des parents du dossier actuel), l' gooutil s'exécute en mode module-aware (le mode hérité est appelé mode GOPATH ).

En mode module-aware, GOPATH ne définit plus la signification des importations lors d'une construction, mais il stocke toujours les dépendances téléchargées (dans GOPATH / pkg / mod) et les commandes installées (dans GOPATH / bin, sauf si GOBIN est défini).

Lors de la construction de modules, ce qui est construit est spécifié par la liste de construction . La liste de construction ne contient initialement que le module principal (le module contenant le répertoire dans lequel la gocommande est exécutée), et les dépendances du module principal sont ajoutées à la liste de construction, de manière récursive (des dépendances de dépendances sont également ajoutées).

Pour plus d'informations, exécutez go help modules.


Fondamentalement, vous pouvez utiliser go buildpour vérifier que les packages peuvent être construits (avec leurs dépendances) tout en go installinstallant (définitivement) les résultats dans les dossiers appropriés de votre $GOPATH.

go build se terminera silencieusement si tout va bien et vous donnera des messages d'erreur si les paquets ne peuvent pas être compilés / compilés.

Chaque fois que l' gooutil installe un package ou un binaire, il installe également toutes les dépendances dont il dispose, donc l'exécution go installinstallera également les packages dont dépend votre programme (packages "go gettable" disponibles publiquement), automatiquement.

Pour commencer, lisez la page officielle Comment écrire le code Go .

Plus d'informations sur l' gooutil: Command go

Vous pouvez également obtenir plus d'aide en exécutant la commande suivante:

go help build

Il est également intéressant de noter que démarrer avec Go 1.5 go installsupprime également les exécutables créés par go build( source ):

Si 'go install' (sans argument, c'est-à-dire le répertoire courant) réussit, supprimez l'exécutable écrit par 'go build', s'il est présent. Cela évite de laisser un binaire périmé derrière ...

Pour compléter la liste, go runcompile votre application dans un dossier temporaire et démarre ce binaire exécutable. Lorsque l'application se ferme, elle nettoie correctement les fichiers temporaires.

Question inspirée par Dave Cheney de What does go build build?

icza
la source
1
semble étrange que go install ne mette pas à jour l'exécutable s'il est identique à celui précédemment installé ... des informations ici?
Scott Stensland
14

Pour le paquet:

go build: construit votre package puis rejette les résultats

Ce ne sera plus le cas après Go 1.10 (Q1 2018), grâce aux CL 68116 et CL 75473 . Voir ce fil , que je référence ici.

Que construisent exactement les commandes go buildetgo install

Chaque fois que l'outil go installe un package ou un binaire, il installe également toutes les dépendances dont il dispose, donc exécuter go install installera également les packages dont dépend votre programme (packages "go gettable" disponibles publiquement), automatiquement.

En fait ... go installchangera également avec Go 1.10, en plus du nouveau cache:

La go installcommande " " n'installe plus les dépendances des packages nommés ( CL 75850 ).

Si vous exécutez " go install foo", la seule chose installée estfoo .

Avant, ça variait. Si les dépendances étaient obsolètes, " go install" installait également des dépendances.
L'installation implicite de dépendances pendant " go install" a causé beaucoup de confusion et de maux de tête pour les utilisateurs, mais il était auparavant nécessaire d'activer les builds incrémentiels.
Plus maintenant.
Nous pensons que la nouvelle install what I saidsémantique " " sera beaucoup plus compréhensible, d'autant plus qu'il ressort clairement des rapports de bogues que de nombreux utilisateurs les attendaient déjà.
Pour forcer l'installation des dépendances pendant " go install", utilisez le nouveau " go install -i" , par analogie avec " go build -i" et " go test -i".

Le fait que " go install" utilisé pour installer des dépendances reconstruites a le plus souvent semé la confusion avec -a, ce qui signifie " force rebuild of all dependencies".
Maintenant, " go install -a myprog" forcera une reconstruction complète de toutes les dépendances de myprog, ainsi que de myproglui-même, mais seulement myprogsera installé. (Toutes les dépendances reconstruites seront toujours enregistrées dans le cache de compilation, bien sûr.)
Faire en sorte que ce cas fonctionne de manière plus compréhensible est particulièrement important en conjonction avec la nouvelle analyse d'obsolescence basée sur le contenu, car elle voit de bonnes raisons de reconstruire les dépendances plus souvent qu'auparavant. , ce qui aurait augmenté la quantité de confusion "pourquoi mes dépendances ont-elles été installées".
Par exemple, si vous exécutez " go install -gcflags=-N myprog", cela installe unmyprogconstruit sans optimisations du compilateur, mais il ne réinstalle plus également les packages myprogutilisés à partir de la bibliothèque standard sans optimisations du compilateur.

VonC
la source
Est go build- ce que , est-ce que gets? J'ai une erreur de construction cannot find package "github.com/spf13/cobra" in any of:…. Je ne sais pas comment le dire pour l'obtenir. Dois-je obtenir explicitement?
ctrl-alt-delor
@ ctrl-alt-delor Avec quelle version de Go? Votre projet contient-il un go.modfichier?
VonC
go version go1.11.4 linux/amd64. Je ne sais pas pour go.mod. Je suis en train de reconstruire https://github.com/cbroglie/mustache/blob/master/cmd/mustache/main.go, c'est étrange car je viens de construire le paquet entier, et j'utilise cet exemple comme base, et j'ai créé une version plus basique qui a fonctionné (mais n'utilise pas cette bibliothèque). Je ne vois pas comment il n'a pas été installé avec le package moustache.
ctrl-alt-delor
@ ctrl-alt-delor donc cobr est vendu github.com/cbroglie/mustache/tree/master/cmd/mustache/vendor/… . Votre GOPATH est-il correctement réglé?
VonC
J'ai découvert ce que vous avez déjà trouvé. Le package se trouve dans un sous-répertoire fournisseur: c'est pourquoi il n'a pas été installé. Cependant, je ne sais pas pourquoi il ne l'installe pas maintenant sur la version. Ou comment utiliser le répertoire du fournisseur (si je le copie dans mon répertoire).
ctrl-alt-delor