Вызов cl.exe (компилятор MSVC) в оболочке Cygwin

Я интенсивно использую Cygwin (с оболочкой PuTTY). Но довольно сложно вызвать cl.exe (то есть цепочку инструментов компилятора Visual C++) в оболочке Cygwin Bash. Запуск vcvars*.bat в оболочке Bash явно не работает. Я попытался перенести переменные среды VC++ в Cygwin, но это не так просто.

Как запустить компилятор VC++ в оболочке Cygwin Bash?


person user46185    schedule 14.12.2008    source источник
comment
Этот вопрос связан с stackoverflow.com/questions/62029/ vs2008-командная строка-cygwin/   -  person Ted    schedule 05.06.2009
comment
Моя программа wrapmsvc [ code.google.com/p/wrapmsvc ] может оказаться полезной. Это оболочка для вызова cl.exe и других инструментов MS из Linux через Wine; он переводит пути в стиле unix в пути в стиле Windows и запускает настоящий инструмент через Wine. Это означает, что вы можете вызывать компилятор с путями unix, не путая настоящий компилятор. Конечно, это не будет работать в Cygwin, потому что там нет Wine, но вы можете изменить его, чтобы не использовать Wine и вместо этого сделать преобразование пути другим способом.   -  person Ambroz Bizjak    schedule 23.04.2012


Ответы (12)


Я обычно решаю это, добавляя

call "%VS80COMNTOOLS%vsvars32.bat" >NUL:

в c:/cygwin/cygwin.bat. Обратите внимание, что переменная VS80COMNTOOLS чрезвычайно полезна, так как она дает надежный (хм) способ найти vsvars32.bat.

Другой подход заключается в следующем: вы можете легко переключаться между разными версиями Studio:

function run_with_bat()
{
    batfile=$1; shift
    tmpfile="$TMP/tmp$$.bat"
    echo "@echo off" > $tmpfile
    echo "call \"%$batfile%vsvars32.bat\" >NUL:" >> $tmpfile
    echo "bash -c \"%*\"" >> $tmpfile
    cmd /c `cygpath -m "$tmpfile"` "$@"
    status=$?
    rm -f $tmpfile
    return $status
}

function run_vs9()
{
    run_with_bat VS90COMNTOOLS "$@"
}

function run_vs8()
{
    run_with_bat VS80COMNTOOLS "$@"
}

Теперь вы можете:

$ run_vs8 cl
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.762 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved. 

usage: cl [ option... ] filename... [ /link linkoption... ]
$ run_vs9 cl
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.21022.08 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

usage: cl [ option... ] filename... [ /link linkoption... ]

Обратите внимание на версию компилятора.

person JesperE    schedule 17.12.2008
comment
Для Visual Studio 2008 — вызовите %VS90COMNTOOLS%vsvars32.bat. - person Tim Ring; 28.06.2012
comment
Мне пришлось изменить ваш эхо-вызов... на этот echo "call \"%$batfile%..\\..\\VC\\vcvarsall.bat\" amd64 >NUL:" >> $tmpfile, чтобы выбрать правильную версию компилятора для сборки кода x64. - person DigitalEye; 19.07.2014
comment
Я изменил функцию run_with_bat только на первую строку, и это: cmd /c call "${!batfile}vsvars32.bat" \&\& bash -c "$*" Которое отлично работает для меня без необходимости временных файлов. В исходной версии у меня были проблемы с пробелами в Program Files (x86). - person contero; 09.01.2015
comment
Смотрите ответ Игоря ниже для лучшего варианта второго варианта. - person Simon Sobisch; 08.11.2016

Я понимаю, что ваша проблема заключается в преобразовании vcvars32.bat в сценарий оболочки.

Один из способов решения проблемы основан на идее, что переменные среды наследуются, когда один процесс запускает другой. Таким образом, вы можете просто запустить vcvars32 под cmd, а затем запустить bash. Это отлично работает на моей машине:

sh-3.2$ cl
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.21022.08 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

usage: cl [ option... ] filename... [ /link linkoption... ]

В качестве альтернативы запустите set до и после вызова vcvars32 в cmd, а затем создайте сценарий оболочки для установки переменных среды.

person Diomidis Spinellis    schedule 14.12.2008
comment
Если вы не хотите всегда использовать определенную версию MSC при запуске cygwin или не хотите использовать ее каждый раз, этот простой вариант является лучшим. - person Simon Sobisch; 08.11.2016

Следуя предложениям в других ответах, я сравнил свои результаты «набора» bash с переменными MSVC и без них и придумал следующий сценарий, чтобы воспроизвести их для моей установки Microsoft Visual C++ 2010 Express. Я немного изменил его, чтобы поместить все части, зависящие от установки, вверху, так что, надеюсь, это может быть полезно другим.

# These lines will be installation-dependent.
export VSINSTALLDIR='C:\Program Files\Microsoft Visual Studio 10.0\'
export WindowsSdkDir='C:\Program Files\Microsoft SDKs\Windows\v7.0A\'
export FrameworkDir='C:\WINDOWS\Microsoft.NET\Framework\'
export FrameworkVersion=v4.0.30319
export Framework35Version=v3.5

# The following should be largely installation-independent.
export VCINSTALLDIR="$VSINSTALLDIR"'VC\'
export DevEnvDir="$VSINSTALLDIR"'Common7\IDE\'

export FrameworkDIR32="$FrameworkDir"
export FrameworkVersion32="$FrameworkVersion"

export INCLUDE="${VCINSTALLDIR}INCLUDE;${WindowsSdkDir}include;"
export LIB="${VCINSTALLDIR}LIB;${WindowsSdkDir}lib;"
export LIBPATH="${FrameworkDir}${FrameworkVersion};"
export LIBPATH="${LIBPATH}${FrameworkDir}${Framework35Version};"
export LIBPATH="${LIBPATH}${VCINSTALLDIR}LIB;"

c_VSINSTALLDIR=`cygpath -ua "$VSINSTALLDIR\\\\"`
c_WindowsSdkDir=`cygpath -ua "$WindowsSdkDir\\\\"`
c_FrameworkDir=`cygpath -ua "$FrameworkDir\\\\"`

export PATH="${c_WindowsSdkDir}bin:$PATH"
export PATH="${c_WindowsSdkDir}bin/NETFX 4.0 Tools:$PATH"
export PATH="${c_VSINSTALLDIR}VC/VCPackages:$PATH"
export PATH="${c_FrameworkDir}${Framework35Version}:$PATH"
export PATH="${c_FrameworkDir}${FrameworkVersion}:$PATH"
export PATH="${c_VSINSTALLDIR}Common7/Tools:$PATH"
export PATH="${c_VSINSTALLDIR}VC/BIN:$PATH"
export PATH="${c_VSINSTALLDIR}Common7/IDE/:$PATH"
person Brooks Moses    schedule 17.07.2010
comment
К сожалению, это лучшее решение, которое я нашел. - person Mark Beckwith; 09.05.2012

На самом деле я использовал ответ JesperE https://stackoverflow.com/a/374411/380247 (который позволяет вам переключаться между VS версий), но нашел способ не создавать временный bat-файл. Так результат намного проще.

function run_in_vs_env
{
    eval vssetup="\$$1\\vsvars32.bat"
    cmd /Q /C call "$vssetup" "&&" "${@:2}"
}

function run_vs11
{
    run_in_vs_env VS110COMNTOOLS "$@"
}

function run_vs10
{
    run_in_vs_env VS100COMNTOOLS "$@"
}

Я предлагаю добавить эти строки в ваш .bash_functions или что-то подобное и экспортировать эти функции туда. Это позволит вам использовать функции в ваших bash-скриптах.

export -f run_in_vs_env
export -f run_vs11
export -f run_vs10

Затем вы должны быть в состоянии сделать:

run_vs11 cl
person Igor Mikushkin    schedule 11.03.2013
comment
действительно очень аккуратное решение! - person malat; 23.05.2014
comment
cmd /Q /C call C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat && ${@:2} Я запустил это, выполнил нормально, все еще cl.exe не могу найти включить PATH :( - person ericcurtin; 23.10.2019
comment
@ericcurtin: он должен называться вот так run_vs11 cl. Строка с cmd использует аргументы функции run_in_vs_env. Аргументы ${@:2} — это просто ваша команда для выполнения. Попробуйте заменить ${@:2} своим вызовом cl или чем-то еще, что вы хотите вызвать, и все должно работать нормально. - person Igor Mikushkin; 23.10.2019

Другой альтернативой является открытие vcvars32.bat (или vsvars32.bat, который выполняет настоящую работу в последней версии Visual Studio), посмотреть, что он делает, и воспроизвести это в соответствующем сценарии оболочки.

Это не особенно сложно - все, что он делает, это устанавливает кучу переменных среды.

person Michael Burr    schedule 14.12.2008

Я преобразовал свой файл vsvars32.bat в файл visual_studio.env. Когда мне нужно использовать среду командной строки Visual Studio, я просто делаю источник этого файла.

В среде оболочки sh я не могу зарегистрировать путь Windows (\ и ; конфликтуют с sh), поэтому, прежде чем я переведу их с помощью cygpath -au или cygpath -aup commands, я запишу их в свой файл .env и переведу обратно с помощью cygpath -aw или cygpath -aup commands.

Мой файл visual_studio.env выглядит так:

VS80COMNTOOLS=$(cygpath -aw '/cygdrive/c/Programmi/Microsoft Visual Studio 8/Common7/Tools/'); export VS80COMNTOOLS
VSINSTALLDIR=$(cygpath -aw '/cygdrive/c/Programmi/Microsoft Visual Studio 8'); export VSINSTALLDIR
VCINSTALLDIR=$(cygpath -aw '/cygdrive/c/Programmi/Microsoft Visual Studio 8/VC'); export VCINSTALLDIR
FrameworkDir=$(cygpath -aw '/cygdrive/c/WINDOWS/Microsoft.NET/Framework'); export FrameworkDir
FrameworkVersion='v2.0.50727'; export FrameworkVersion
FrameworkSDKDir=$(cygpath -aw '/cygdrive/c/Programmi/Microsoft Visual Studio 8/SDK/v2.0'); export FrameworkSDKDir

echo Setting environment for using Microsoft Visual Studio 2005 x86 tools.

DevEnvDir=$(cygpath -aw '/cygdrive/c/Programmi/Microsoft Visual Studio 8/Common7/IDE'); export DevEnvDir

PATH='/cygdrive/c/Programmi/Microsoft Visual Studio 8/Common7/IDE:/cygdrive/c/Programmi/Microsoft Visual Studio 8/VC/BIN:/cygdrive/c/Programmi/Microsoft Visual Studio 8/Common7/Tools:/cygdrive/c/Programmi/Microsoft Visual Studio 8/Common7/Tools/bin:/cygdrive/c/Programmi/Microsoft Visual Studio 8/VC/PlatformSDK/bin:/cygdrive/c/Programmi/Microsoft Visual Studio 8/SDK/v2.0/bin:/cygdrive/c/WINDOWS/Microsoft.NET/Framework/v2.0.50727:/cygdrive/c/Programmi/Microsoft Visual Studio 8/VC/VCPackages':$PATH
INCLUDE=$(cygpath -awp '/cygdrive/c/Programmi/Microsoft Visual Studio 8/VC/ATLMFC/INCLUDE:/cygdrive/c/Programmi/Microsoft Visual Studio 8/VC/INCLUDE:/cygdrive/c/Programmi/Microsoft Visual Studio 8/VC/PlatformSDK/include:/cygdrive/c/Programmi/Microsoft Visual Studio 8/SDK/v2.0/include'); export INCLUDE
LIB=$(cygpath -awp '/cygdrive/c/Programmi/Microsoft Visual Studio 8/VC/ATLMFC/LIB:/cygdrive/c/Programmi/Microsoft Visual Studio 8/VC/LIB:/cygdrive/c/Programmi/Microsoft Visual Studio 8/VC/PlatformSDK/lib:/cygdrive/c/Programmi/Microsoft Visual Studio 8/SDK/v2.0/lib'); export LIB
LIBPATH=$(cygpath -awp '/cygdrive/c/WINDOWS/Microsoft.NET/Framework/v2.0.50727:/cygdrive/c/Programmi/Microsoft Visual Studio 8/VC/ATLMFC/LIB'); export LIBPATH

Я надеюсь это тебе поможет.

person Community    schedule 17.12.2008

Я считаю, что лучше использовать msbuild, и в то же время я также могу использовать g++ моей среды cygwin. Это более интегрированный подход, который гармонично сочетается с вашей существующей visual studio разработкой. Использование самого низкого уровня cl и настройка переменных окружения напрашиваются на неприятности и идут против ветра. msbuild может лучше настроить все для нас. Кроме того, я могу выполнить пошаговую отладку в среде IDE, имеющей полноценный проект *.vcxproj.

ls -l ~/bin/msbuild
lrwxrwxrwx 1 johnny Domain Users 102 Sep  4 04:25 /home/johnny/bin/msbuild -> /cygdrive/c/Program Files (x86)/Microsoft Visual Studio/2017/Professional/MSBuild/15.0/Bin/MSBuild.exe

Затем в вашем ~/.bashrc есть эта функция:

builddebug (){
    [ $# -eq 0 ] && return 1;
    msbuild /m /p:Configuration=Debug /p:Platform=Win32 "$1"
}

Процесс разработки выглядит следующим образом: это. По крайней мере, я могу использовать компилятор g++ и компилятор Visual Studio 2017 более интегрированным образом. Пусть msbuild сделает свое дело. Не cl.

person eigenfield    schedule 10.11.2018

Для меня в .bash_profile сработало следующее:

"`cygpath -ua "$VS80COMNTOOLS/vsvars32.bat"`" > NUL

person Community    schedule 08.07.2009
comment
Это не сработало для меня. Хотя он работал нормально, установленные им переменные среды, похоже, не распространяются обратно в оболочку. - person Brooks Moses; 17.07.2010

Одна утилита, которую я нашел довольно бесценной для компиляции материала с помощью msvc из среды cygwin, — это оболочка, которую я нашел в Coin 3D. исходный репозиторий библиотеки под названием "wrapmsvc", чей бинарный файл можно найти здесь.

Программа упаковывает cl.exe и преобразует любые аргументы GCC, указанные в соответствующий аргумент cl.exe. Он также использует API cygwin для правильного преобразования пути к файлу из формы cygwin (/cygdrive/c/temp/test.c) в фактический путь к файлу (C:\temp\test.c).

В прошлый раз мне потребовалось некоторое время, чтобы найти исходный код, но он называется «wrapmsvc.cpp», поэтому, если вам нужно его скомпилировать, найдите этот файл. Если вам случится скомпилировать его и вы получите некоторые предупреждения/ошибки по поводу использования cygwin_conv_to_posix_path или cygwin_conv_to_win32_path, внесите следующие изменения:

Измените строку:

(void)cygwin_conv_to_posix_path(s.c_str(), buf);

to

(void)cygwin_conv_path(CCP_WIN_A_TO_POSIX, (const void *)s.c_str(), (void *)buf, (size_t)MAX_PATH);

и изменить:

(void)cygwin_conv_to_win32_path(s.c_str(), buf);

to

(void)cygwin_conv_path(CCP_POSIX_TO_WIN_A, (const void *)s.c_str(), (void *)buf, (size_t)MAX_PATH);
person Charles Grunwald    schedule 10.01.2012

Мне не удалось добавить комментарии к ответу Диомидиса :(, поэтому вместо этого пришлось опубликовать ответ. Я согласен с его ответом, но было бы утомительно «открыть командную строку», запустить Visual Studio/vcvars32.bat, а затем запустить Bash. Если вы не беспокоитесь о беспорядке вашей среде, лучшая альтернатива — изменить Cygwin.bat и изменить его так, чтобы он выглядел примерно так:

@echo off
D:
chdir D:\cygwin\bin
"%VS71COMNTOOLS%\vsvars32.bat" && bash --login -i

Замените переменную среды VS71COMNTOOLS чем-то подходящим для вашего компьютера.

Нет необходимости открывать командную строку и запускать Bash вручную. Мне очень нравится это решение :). Я не мог отдать должное настоящему автору этого хака, так как не смог найти ссылку на его статью, извините за это!

person Community    schedule 17.06.2009

Моя версия решения Игоря, короче:

cl() {
  tmpfile="/tmp/tmp$$.bat"
  echo "@echo off" > $tmpfile
  echo "call \"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat\" >NUL:" >> $tmpfile
  echo "bash -c \"cl %*\"" >> $tmpfile
  cmd /c `cygpath -m "$tmpfile"` "$@"
  status=$?
  rm -f $tmpfile
  return $status
}

жаль, что vcvars64.bat нужно вызывать повторно.

person ericcurtin    schedule 23.10.2019

Ни один из других ответов не работал у меня, но это сработало:

  1. Запустите «Командную строку MS Build»

введите здесь описание изображения

  1. дамп переменных env: set > c:\temp\cl.env

  2. Откройте командную строку cygwin и создайте скрипт source:

awk < /cygdrive/c/temp/cl.env -F= '{ if($1 !~ ")") print "export " $1 "=\x27" $2 "\x27" }' > cl.source
  1. Измените cl.source, чтобы изменить TEMP и TMP на C:\Temp, например. TEMP='C:\Temp'

  2. Теперь, когда вам понадобится среда cl, из командной строки cygwin запустите: source cl.source

  3. При необходимости укажите источник cl.source в файле .bashrc для автоматического запуска при входе в систему.

person mwag    schedule 05.09.2019