BPL*_*BPL 9 python windows environment-variables sublimetext3 visual-studio-2015
概述
现在我在我的Windows任务栏上有这两个程序:
SublimeText3目标:
"D:\software\SublimeText 3_x64\sublime_text.exe"
Run Code Online (Sandbox Code Playgroud)VS2015 x64本机工具命令提示符目标:
%comspec% /k ""C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"" amd64
Run Code Online (Sandbox Code Playgroud)这里的目标是运行Sublime Text并启用vs2015环境.
> sublime_text (这不是一个好的,我希望它是一个非交互式进程)题
我怎么能完成选项2?
NS:我想让Sublime Text 3 在启动时只运行一次 vcvarsall.bat (不是在构建系统上的构建时)
ATTEMPTS
我的第一次尝试是试图理解bat文件是如何执行的,所以我测试了一些基本的批处理文件
bat1.bat:它成功打开了崇高的文本
sublime_text
Run Code Online (Sandbox Code Playgroud)bat2.bat:成功打开vs命令提示符,等待用户输入命令
cmd /k ""C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"" amd64
Run Code Online (Sandbox Code Playgroud)bat3.bat:打开vs命令提示符,但它不会打开ST,除非在显示命令提示符后键入exit
%comspec% /k ""C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"" amd64
sublime_text
Run Code Online (Sandbox Code Playgroud)bat4.bat:打开vs命令提示符,但它不打开ST,与bat3.bat相同的情况
%comspec% /k ""C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"" amd64 && sublime_text
Run Code Online (Sandbox Code Playgroud)bat5.bat:打开vs命令提示符,但它没有打开ST,与bat {4,3} .bat相同的情况
%comspec% /k ""C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"" amd64 & sublime_text
Run Code Online (Sandbox Code Playgroud)在这些尝试之后,我决定阅读一些文档,试图找到关于cmd的一些提示,但它没有任何区别.
另一个想法是使用conemu自定义任务,例如:
{vs2015}: cmd.exe /k "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64 & sublime_text
Run Code Online (Sandbox Code Playgroud)
然后有一个bat文件调用conemu像这样:
D:\software\ConEmuPack.151205\ConEmu64.exe /single -cmd {vs2015}
Run Code Online (Sandbox Code Playgroud)
结果是+/-我想要的,但会产生2个终端和一个新的崇高会话.我正在寻找的只是在适当的环境下打开SublimeText会话,所以我认为这不是一个好的解决方案,而且需要安装conemu.
经过所有这些尝试之后,我想可能会使用python打开一个命令提示符并输入并"运行"一些命令可能会有所帮助,但我不知道该怎么做.
结论:直到问题仍未解决的日期......
Aside of the ways that have already been mentioned in the question and the previous answer, another way to go is something akin to what @LinuxDisciple mentioned in their answer; have Sublime internally fire up the batch file once at Sublime start up to do what you need to do.
An example of this in action is the following plugin. To start with, add the following settings to your user preferences (Preferences > Settings or Preferences > Settings - User). Here I'm using the setup for my own local machine; update the path to suit for your version of Visual Studio:
"vc_vars_cmd": "C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat",
"vc_vars_arch": "amd64",
Run Code Online (Sandbox Code Playgroud)
The vc_vars_cmd setting is required by the following plugin, but the vc_vars_arch setting is optional; if it is not given, it defaults to amd64.
Next, select Tools > Developer > New Plugin from the menu and replace the stub plugin code with the following and save it in the default location that Sublime defaults to as something like set_vc_vars.py:
"vc_vars_cmd": "C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat",
"vc_vars_arch": "amd64",
Run Code Online (Sandbox Code Playgroud)
Once you save the plugin, Sublime will load it and execute the plugin_loaded function, which will do all of the work.You should see the status bar say VS Environment Enabled if it worked.
If you see Error Fetching VS Environment double check that the path to the batch file is correct (note that you need to double all path separators to make them JSON compliant).
This operates very similarly to (and is vaguely based on) the Fix Mac Path package, which does something similar to update the path in Sublime on MacOS, where the vagaries of the OS cause GUI applications to have their environment set in a way different than terminal applications.
The general idea is that the batch file is executed in a sub-process, and then before returning we also execute the set command to get the command interpreter to dump its entire environment to the console, which the plugin captures.
Once we have that data, we can easily compare it with the current environment to add in any environment variables that the batch file set up but which didn't already exist, and update the values of any environment variables that were changed (e.g. the PATH).
As a part of this process we also set a new environment variable that tells the plugin that the environment has already been set up, so that if the plugin gets reloaded it doesn't try to run the operation again.
As such, if you need to change the path to the batch file or the architecture that you want to be set up for, you need to change the preference and restart Sublime.
This could be made more robust by having it do something like store the current environment before modifying it and then watching the preferences to see if that setting is changed and act accordingly, but presumably it's not often that you would need to modify these settings.
For testing purposes, I created the following simple C program:
import sublime
import sublime_plugin
from threading import Thread
from subprocess import Popen, PIPE
from os import environ
SENTINEL="SUBL_VC_VARS"
def _get_vc_env():
"""
Run the batch file specified in the vc_vars_cmd setting (with an
optional architecture type) and return back a dictionary of the
environment that the batch file sets up.
Returns None if the preference is missing or the batch file fails.
"""
settings = sublime.load_settings("Preferences.sublime-settings")
vars_cmd = settings.get("vc_vars_cmd")
vars_arch = settings.get("vc_vars_arch", "amd64")
if vars_cmd is None:
print("set_vc_vars: Cannot set Visual Studio Environment")
print("set_vc_vars: Add 'vc_vars_cmd' setting to settings and restart")
return None
try:
# Run the batch, outputting a sentinel value so we can separate out
# any error messages the batch might generate.
shell_cmd = "\"{0}\" {1} && echo {2} && set".format(
vars_cmd, vars_arch, SENTINEL)
output = Popen(shell_cmd, stdout=PIPE, shell=True).stdout.read()
lines = [line.strip() for line in output.decode("utf-8").splitlines()]
env_lines = lines[lines.index(SENTINEL) + 1:]
except:
return None
# Convert from var=value to dictionary key/value pairs. We upper case the
# keys, since Python does that to the mapping it stores in environ.
env = {}
for env_var in env_lines:
parts = env_var.split("=", maxsplit=1)
env[parts[0].upper()] = parts[1]
return env
def install_vc_env():
"""
Try to collect the appropriate Visual Studio environment variables and
set them into the current environment.
"""
vc_env = _get_vc_env()
if vc_env is None:
print("set_vc_vars: Unable to fetch the Visual Studio Environment")
return sublime.status_message("Error fetching VS Environment")
# Add newly set environment variables
for key in vc_env.keys():
if key not in environ:
environ[key] = vc_env[key]
# Update existing variables whose values changed.
for key in environ:
if key in vc_env and environ[key] != vc_env[key]:
environ[key] = vc_env[key]
# Set a sentinel variable so we know not to try setting up the path again.
environ[SENTINEL] = "BOOTSTRAPPED"
sublime.status_message("VS Environment enabled")
def plugin_loaded():
if sublime.platform() != "windows":
return sublime.status_message("VS is not supported on this platform")
# To reload the environment if it changes, restart Sublime.
if SENTINEL in environ:
return sublime.status_message("VS Environment already enabled")
# Update in the background so we don't block the UI
Thread(target=install_vc_env).start()
Run Code Online (Sandbox Code Playgroud)
I also created the following sublime-build file, based loosely off of the C++ Single File.sublime-build that ships with Sublime:
#include <stdio.h>
int main(int argc, char const *argv[])
{
printf("Hello VC World!\n");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
If you attempt to build the sample C file without the plugin, an error is generated about not being able to find cl (unless you have started Sublime from a developer prompt or otherwise already set up the path). With the plugin in place, you get output similar to the following: