Подтвердить что ты не робот

Как установить script в Makefile?

Есть ли лучший способ для источника script, который устанавливает env vars изнутри файла makefile?

FLAG ?= 0
ifeq ($(FLAG),0)
export FLAG=1
/bin/myshell -c '<source scripts here> ; $(MAKE) [email protected]'
else
...targets...
endif
4b9b3361

Ответ 1

Чтобы ответить на заданный вопрос: вы не можете.

Основная проблема заключается в том, что дочерний процесс не может изменить родительскую среду. Оболочка обходит это, не открывая новый процесс, когда source 'ing, но просто запускает эти команды в текущем воплощении оболочки. Это работает отлично, но make не /bin/sh (или какая-либо оболочка для вашего script) и не понимает этот язык (кроме битов, которые у них есть).

Chris Dodd и Foo Bah обратились к одному из возможных способов обхода, поэтому я предлагаю другое (если вы используете GNU make): выполните обработку оболочки script, чтобы создать совместимый текст и включить результат:

shell-variable-setter.make: shell-varaible-setter.sh
    postprocess.py @^

# ...
else
include shell-variable-setter.make
endif

беспорядочные детали, оставленные как упражнение.

Ответ 2

Если ваша цель - просто установить переменные среды для Make, почему бы не сохранить их в синтаксисе Makefile и использовать команду include?

include other_makefile

Если вам нужно вызвать оболочку script, запишите результат в команду shell:

JUST_DO_IT=$(shell source_script)

команда оболочки должна запускаться перед целями. Однако это не изменит переменные среды.

Если вы хотите установить переменные среды в сборке, напишите отдельную оболочку script, которая будет вызывать переменные среды и вызовы make. Затем в make файле нужно, чтобы цели вызывали новую оболочку script.

Например, если ваш исходный make файл имеет цель a, то вы хотите сделать что-то вроде этого:

# mysetenv.sh
#!/bin/bash
. <script to source>
export FLAG=1
make "[email protected]" 

# Makefile
ifeq($(FLAG),0)
export FLAG=1
a: 
    ./mysetenv.sh a
else
a:
    .. do it
endif

Ответ 3

Использование GNU Make 3.81 Я могу создать оболочку script из make using:

rule:
<tab>source source_script.sh && build_files.sh

build_files.sh "получает" переменные среды, экспортируемые source_script.sh.

Обратите внимание, что используя:

rule:
<tab>source source_script.sh
<tab>build_files.sh

не будет работать. Каждая строка запускается в своей подоболочке.

Ответ 4

Это работает для меня. Замените env.sh именем файла, который вы хотите использовать. Он работает путем поиска файла в bash и вывода измененной среды после ее форматирования в файл с именем makeenv, который затем получает файл makefile.

IGNORE := $(shell bash -c "source env.sh; env | sed 's/=/:=/' | sed 's/^/export /' > makeenv")                         
include makeenv   

Ответ 5

Makefile default shell /bin/sh, который не реализует source.

Изменение оболочки на /bin/bash позволяет:

# Makefile

SHELL := /bin/bash

rule:
    source env.sh && YourCommand

Ответ 6

Некоторые конструкции одинаковы в shell и в GNU Make.

var=1234
text="Some text"

Вы можете изменить оболочку script, чтобы указать параметры. Все они должны быть простыми типами name=value.

Т.е.,

[script.sh]

. ./vars.sh

[Make файл]

include vars.sh

Тогда оболочка script и Makefile могут совместно использовать один и тот же "источник" информации. Я нашел этот вопрос, потому что я искал манифест общего синтаксиса, который можно использовать в скриптах Gnu Make и shell (мне все равно, какая оболочка).

Изменить: оболочки и понять ${var}. Это означает, что вы можете конкатенировать и т.д.   var = "Одна строка"   var = ${var} "Вторая строка"

Ответ 7

Мне очень нравится Foo Bah ответ, где вызывают вызовы script, а script - назад. Чтобы расширить этот ответ, я сделал следующее:

# Makefile
.DEFAULT_GOAL := all 

ifndef SOME_DIR

%:
<tab>. ./setenv.sh $(MAKE) [email protected]

else

all:
<tab>...

clean:
<tab>...

endif

-

# setenv.sh
export SOME_DIR=$PWD/path/to/some/dir

if [ -n "$1" ]; then
    # The first argument is set, call back into make.
    $1 $2
fi

Это имеет дополнительное преимущество при использовании $(MAKE), если кто-то использует уникальную программу make, и также будет обрабатывать любое правило, указанное в командной строке, без необходимости дублировать имя каждого правила в случае, когда SOME_DIR не определено.

Ответ 8

Мое решение: (если у вас есть bash, синтаксис для [email protected] для tcsh отличается)

Имейте script sourceThenExec.sh, как таковой:

#!/bin/bash
source whatever.sh
[email protected]

Затем в вашем make файле предисловие к вашим целям с помощью bash sourceThenExec.sh, например:

ExampleTarget:
    bash sourceThenExec.sh gcc ExampleTarget.C

Вы можете, конечно, добавить что-то вроде STE=bash sourceThenExec.sh в начало своего файла makefile и сократить это:

ExampleTarget:
    $(STE) gcc ExampleTarget.C

Все это работает, потому что sourceThenExec.sh открывает подоболочку, но тогда команды выполняются в одной и той же подоболочке.

Недостатком этого метода является то, что файл получает источник для каждой цели, что может быть нежелательным.

Ответ 9

Другим возможным способом было бы создание sh script, например run.sh, источник необходимых скриптов и вызов make внутри script.

#!/bin/sh
source script1
source script2 and so on

make 

Ответ 10

Если вам нужна только несколько известных переменных, экспортирующих в make файл, это вариант, вот пример того, что я использую.

$ grep ID /etc/os-release 

ID=ubuntu
ID_LIKE=debian


$ cat Makefile

default: help rule/setup/lsb

source?=.

help:
        -${MAKE} --version | head -n1

rule/setup/%:
        echo ID=${@F}

rule/setup/lsb: /etc/os-release
        ${source} $< && export ID && ${MAKE} rule/setup/$${ID}


$ make

make --version | head -n1
GNU Make 3.81
. /etc/os-release && export ID && make rule/setup/${ID}
make[1]: Entering directory `/tmp'
echo ID=ubuntu
ID=ubuntu

- http://rzr.online.fr/q/gnumake

Ответ 11

Если вы хотите получить переменные в среде, чтобы они передавались дочерним процессам, вы можете использовать bash set -a и set +a. Первое означает: "Когда я устанавливаю переменную, задайте также соответствующую переменную среды". Так это работает для меня:

check:
    bash -c "set -a && source .env.test && set +a && cargo test"

Это будет передавать все в .env.test на cargo test в качестве переменных среды.

Обратите внимание, что это позволит вам передать среду в под-команды, но это не позволит вам устанавливать переменные Makefile (которые все равно разные). Если вам нужно последнее, вы должны попробовать одно из других предложений здесь.

Ответ 12

target: output_source
    bash ShellScript_name.sh

попробуйте, он будет работать, script находится внутри текущего каталога.