Поскольку я работаю над несколькими отдельными проектами (каждый из которых использует свой компилятор), мне не нравится, когда в PATH прописан путь к какому-то одному компилятору.
Теперь я присоединился к другому проекту, где, судя по всему, принято указывать путь к компилятору как часть системного PATH по умолчанию, и я хотел бы обойти это, но у меня возникли трудности.
Я работаю на Windows 7 SP1 (64 бит) с использованием Cygwin.
$ uname -srv
CYGWIN_NT-6.1 1.7.32(0.274/5/3) 2014-08-13 23:06
Новый проект использует Scons в качестве среды сборки:
$ scons --version
SCons by Steven Knight et al.:
script: v2.3.4, 2014/09/27 12:51:43, by garyo on lubuntu
engine: v2.3.4, 2014/09/27 12:51:43, by garyo on lubuntu
engine path: ['/usr/lib/scons-2.3.4/SCons']
Copyright (c) 2001 - 2014 The SCons Foundation
У меня есть скрипт, который я могу запустить (перед попыткой собрать новый проект), который установит все необходимые переменные среды соответствующим образом (в основном это просто длинный список "export PATH=...", "export INCLUDE=...", "export LIB=..." и "export LIBPATH=..."). Я могу получить этот скрипт из любого файла запуска, и хотя путь будет установлен в моем интерактивном сеансе Bash
$ which cl
/cygdrive/c/Program Files (x86)/Microsoft Visual Studio 12.0/VC/BIN/cl
когда я пытаюсь
$ scons -u
Я получаю (в конце концов)
Compiling C++ ... Application/Infrastructure/DataManager/BitFieldDataItem/BitFieldDataItem.cpp
/bin/sh: cl: command not found
scons: *** [Build/DataManagerUnitTestWin32_Win32/Application/Infrastructure/DataManager/BitFieldDataItem/BitFieldDataItem.obj] Error 127
scons: building terminated because of errors.
Под капотом /bin/sh — это bash
$ /bin/sh --version
GNU bash, version 4.1.16(8)-release (x86_64-unknown-cygwin)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
что не должно быть проблемой, поскольку, насколько я понимаю, при вызове как /bin/sh bash пытается эмулировать оболочку POSIX; вероятно, это желаемое поведение с точки зрения Scons.
Трудность в том, что я не могу найти способ получить требуемые переменные окружения в неинтерактивной, нелогиновой среде оболочки POSIX. Может кто-нибудь подскажет, как это сделать?
решение1
Я выбрал неправильный подход. Самый простой (но некрасивый) способ сделать это — изменить файл SConstruct так, чтобы был некий триггер, который программно изменит среду до вызова Shell.
Для проверки концепции я использовал свое имя пользователя в качестве триггера:
import getpass
и позже
msvcEnv = MSVCCompiler.CreateEnvironment(baseEnv)
if getpass.getuser() == 'peterd':
msvcEnv.PrependENVPath('PATH', '/cygdrive/c/Program Files (x86)/Microsoft SDKs/Windows/v8.1A/bin/NETFX 4.5.1 Tools/')
msvcEnv.PrependENVPath('PATH', '/cygdrive/c/Program Files (x86)/Windows Kits/8.1/bin/x86/')
msvcEnv.PrependENVPath('PATH', '/cygdrive/c/Program Files (x86)/Microsoft Visual Studio 12.0/Team Tools/Performance Tools/')
msvcEnv.PrependENVPath('PATH', '/cygdrive/c/Program Files (x86)/Microsoft Visual Studio 12.0/VC/VCPackages/')
msvcEnv.PrependENVPath('PATH', '/cygdrive/c/windows/Microsoft.NET/Framework/v4.0.30319/')
msvcEnv.PrependENVPath('PATH', '/cygdrive/c/Program Files (x86)/Microsoft Visual Studio 12.0/Common7/Tools/')
msvcEnv.PrependENVPath('PATH', '/cygdrive/c/Program Files (x86)/Microsoft Visual Studio 12.0/VC/BIN/')
msvcEnv.PrependENVPath('PATH', '/cygdrive/c/Program Files (x86)/Microsoft Visual Studio 12.0/Common7/IDE/')
msvcEnv.PrependENVPath('PATH', '/cygdrive/c/Program Files (x86)/MSBuild/12.0/bin/')
# INCLUDE and LIBPATH are for the compiler; header files for the former, type libraries and .NET assemblies etc for the latter
msvcEnv.PrependENVPath('INCLUDE', 'C:\\Program Files (x86)\\Windows Kits\\8.1\\include\\winrt;C:\\Program Files (x86)\\Windows Kits\\8.1\\include\\um;C:\\Program Files (x86)\\Windows Kits\\8.1\\include\\shared;C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\atlmfc\include;C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\include;')
msvcEnv.PrependENVPath('LIBPATH', 'C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v8.1\\ExtensionSDKs\\Microsoft.VCLibs\\12.0\\References\\CommonConfiguration\\neutral;C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\atlmfc\lib;C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\lib;C:\\windows\\Microsoft.NET\\Framework\\v4.0.30319;')
# Apparently the linker still doesn't understand paths with spaces...
msvcEnv.PrependENVPath('LIB', 'C:\\PROGRA~2\\WI3CF2~1\\8.1\\Lib\\winv6.3\\um\\x86;C:\\PROGRA~2\\MICROS~2.0\\VC\\atlmfc\\lib;C:\\PROGRA~2\\MICROS~2.0\\VC\\lib;')
Кажется, это работает.