简体   繁体   中英

Vim makeprg make environment variable expansion

This is bothering me more than it should and has me completely stumped. I feel like like finding the answer will have some good learning opportunities so hopefully it's relevant.

I do embedded C development with Vim and have a setup for hobbyist stuff with Arduino (using Arduino Makefile ). I use :make with some shortcuts with build projects.

An external define resolves the Arduino Makefile root directory in the project level Makefile: 'ARDMK_DIR=/usr/local/opt/arduino-mk'. This is define as an export in my shell (zsh). This is where it gets weird:

  • Using make at the shell prompt the project builds fine:
make -d
This program built for i386-apple-darwin11.3.0
Reading makefiles...
Reading makefile `Makefile'...
Reading makefile `/usr/local/opt/arduino-mk/Arduino.mk' (search path) (no ~ expansion)...
  • However using :make in Vim the define becomes something from an old install:
:make
This program built for i386-apple-darwin11.3.0
Reading makefiles...
Reading makefile `Makefile'...
Reading makefile `/usr/local/Cellar/arduino-mk/1.5.2/Arduino.mk' (search path) (no ~ expansion)...
Makefile:24: /usr/local/Cellar/arduino-mk/1.5.2/Arduino.mk: No such file or directory

I cannot for the life of me find where ARDMK_DIR is being re-defined to '/usr/local/Cellar/arduino-mk/1.5.2'. Things I have tried:

  • setlocal makeprg=echo\\ $ARDMK_DIR\\ &&\\ make\\ -d\\ : echo comes back with my shell define (/usr/local/opt/arduino-mk), but make fails with the error above!!
  • :echo $ARDMK_DIR : again returns my shell define.
  • ag my home directory for ARDMK_DIR, the only place it is defined is in my shell exports. Did since for my root directory to and same thing. Same thing for $VIMRUNTIME
  • Even vim-disptach works fine calling the same makeprg ?!
  • Re-define ARDMK_DIR in the project Makefile. Everything builds find as expected. I don't want to do this however as I compile with different systems.
  • The same vim config works on other macOS and Linux systems with expected behaviour.

Some where between echo and the actual execution of make , ARDMK_DIR is being re-defined. Why and can anyone think of a way of finding out where and solving this?

Zsh has multiple init files that are sourced. The file .zshenv is always sourced, when the shell starts and the file .zshrc is only sourced when the shell is started in interactive mode.

If you define the variable ARDMK_DIR with different values in .zshenv and in .zshrc , the value from .zshrc will be used when you work interactive with the shell (entering commands, starting Vim, ...).

But when Vim starts a command it will start a non-interactive shell. In that case only the file .zshenv will be sourced, so you get the value from that file.

One question left:

Why did the following command first echo the correct value, but make uses the wrong?

:setlocal makeprg=echo\ $ARDMK_DIR\ &&\ make\ -d\ 

For testing, I started Vim under strace . Then :

:set makeprg=echo\ $EDITOR
:make

In the strace file I found the following line:

execve("/usr/bin/zsh", ["/usr/bin/zsh", "-c", "echo vi  2>&1| tee /tmp/vdxR5DH/"...], [/* 86 vars */]) = 0

As you can see, Vim executes echo vi , so it already expanded the environment variable $EDITOR to its value before calling the shell.


So the answer to the above question is, that the echo command echos the text, that Vim inserted into the command line while the make command gets the the variable value from the environment. As it is a non-interactive shell, it is the value from .zshenv .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM