Como eu poderia adicionar dir a $ PATH no Makefile?

87

Eu quero escrever um Makefile que executaria testes. Os testes estão em um diretório './tests' e os arquivos executáveis ​​a serem testados estão no diretório './bin'.

Quando eu executo os testes, eles não veem os arquivos exec, pois o diretório ./bin não está no $ PATH.

Quando eu faço algo assim:

EXPORT PATH=bin:$PATH
make test

tudo funciona. No entanto, preciso alterar o $ PATH no Makefile.

Conteúdo simples de Makefile:

test all:
    PATH=bin:${PATH}
    @echo $(PATH)
    x

Ele imprime o caminho corretamente, porém não encontra o arquivo x.

Quando eu faço isso manualmente:

$ export PATH=bin:$PATH
$ x

está tudo bem então.

Como eu poderia mudar o $ PATH no Makefile?

Szymon Lipiński
fonte
Você não pode simplesmente chamar os testes do diretório executável, como ../test/test_to_run? Desculpe se eu entendi mal a pergunta.
Chris de
Quero que esse arquivo fique visível para os testes normalmente. Não quero brincar com os diretórios, pois refatorar isso seria um pesadelo.
Szymon Lipiński
A única maneira de chegar perto disso é fazer com que o makefile escreva um script de shell contendo a variável decls e então ter o código-fonte do shell pai com o qual o script .. No entanto, isso provavelmente não é prático.
Michael Smith
Eu acredito que unix.stackexchange.com/questions/11530/… é uma pergunta muito diferente (estúpida), ao contrário da sua.
imz - Ivan Zakharyaschev

Respostas:

106

Você tentou a exportdiretiva do próprio Make (assumindo que você usa GNU Make)?

export PATH := bin:$(PATH)

test all:
    x

Além disso, há um bug em seu exemplo:

test all:
    PATH=bin:${PATH}
    @echo $(PATH)
    x

Primeiro, o valor que echoestá sendo ed é uma expansão da PATHvariável realizada pelo Make, não pelo shell. Se ele imprimir o valor esperado, eu acho, você definiu a PATHvariável em algum lugar anteriormente em seu Makefile, ou em um shell que invocou o Make. Para evitar tal comportamento, você deve escapar dos dólares:

test all:
    PATH=bin:$$PATH
    @echo $$PATH
    x

Segundo, em qualquer caso, isso não funcionará porque o Make executa cada linha da receita em um shell separado . Isso pode ser alterado escrevendo a receita em uma única linha:

test all:
    export PATH=bin:$$PATH; echo $$PATH; x
Eldar Abusalimov
fonte
7
$(PATH)será definido com o valor de PATHdo shell que invoca o make. De acordo com o manual , "Cada variável de ambiente que o make vê ao iniciar é transformada em uma variável do make com o mesmo nome e valor."
Emil Sit
A diretiva de exportação funcionou para mim (obrigado!), Mas somente depois que instalei o GNU Make 4.3. Na versão 3.81 (o padrão no MacOS Catalina), a atualização PATHé refletida corretamente no variáveis ( echo $(PATH)) e dentro de ambientes dos comandos ( env, which python, bash -c python), mas não parece ser usado quando localizar o executável para o comando: o comando pythonainda corre o Executável Python no original PATH.
doctaphred
27

Por projeto, o makeanalisador executa linhas em invocações de shell separadas, é por isso que a alteração da variável (por exemplo PATH) em uma linha, a alteração pode não ser aplicada nas próximas linhas (veja este post ).

Uma maneira de contornar esse problema é converter vários comandos em uma única linha (separados por ;) ou usar o destino especial One Shell (.ONESHELL partir do GNU Make 3.82).

Alternativamente, você pode fornecer PATHvariáveis ​​no momento em que o shell é chamado. Por exemplo:

PATH  := $(PATH):$(PWD)/bin:/my/other/path
SHELL := env PATH=$(PATH) /bin/bash
Kenorb
fonte
2
Gosto da abordagem!
Alan Franzoni
2
Este é o melhor, porque funciona mesmo com $(shell)invocações! : D Exemplo: pastebin.com/Pii8pmkD
PsychoX
Em dev.azure eu obtenho: env: 'env': Não existe tal arquivo ou diretório; Trabalha localmente; /
Kamil Dziedzic
Não funciona no Debian 10 com make 4.2: make: env PATH = <caminho> / bin / sh: Comando não encontrado. Usando a exportação funciona. Certifique-se de usar $ (HOME) e não ~ para um caminho no diretório inicial.
MKesper
25

As mudanças de caminho parecem ser persistentes se você definir a variável SHELL em seu makefile primeiro:

SHELL := /bin/bash
PATH := bin:$(PATH)

test all:
    x

Não sei se esse comportamento é desejado ou não.

subespecificado
fonte
Isso corrigiu o problema que eu estava tendo (estou executando o zsh). Obrigado!
Jezen Thomas
Sim, isso realmente faz o que o OP queria ... mas é um recurso ou um bug? Mesmo depois de ler a seção SHELL do manual do make, não tenho certeza.
pje
5
Isso também não funciona para mim. whiche envagora pegue o novo PATH, mas a execução direta de um binário ainda não é encontrada no PATH modificado, apenas no original.
Konrad Rudolph
3

O que geralmente faço é fornecer o caminho para o executável explicitamente:

EXE=./bin/
...
test all:
    $(EXE)x

Também uso essa técnica para executar binários não nativos em um emulador como o QEMU se estou compilando de forma cruzada:

EXE = qemu-mips ./bin/

Se o make estiver usando o shell sh, isso deve funcionar:

test all:
    PATH=bin:$PATH x
Richard Pennington
fonte
Sim, legal soulution, no entanto, tenho meus testes escritos em perl e preciso chamar o exe do script perl, não diretamente do makefile. Tenho que repensar todos os testes dessas coisas :)
Szymon Lipiński
Peguei vocês. Que tal configurar o PATH na própria linha de comando? Veja a edição acima.
Richard Pennington de
-2

Para definir a PATHvariável, apenas dentro do Makefile, use algo como:

PATH := $(PATH):/my/dir

test:
@echo my new PATH = $(PATH)
Karnhick
fonte
Não funciona da maneira que desejo. Eu atualizei a pergunta com exemplos do que desejo alcançar.
Szymon Lipiński