【问题标题】:Compile C Programs from Windows Powershell with MSVC使用 MSVC 从 Windows Powershell 编译 C 程序
【发布时间】:2021-11-17 04:41:35
【问题描述】:

编辑:对于任何对此感兴趣的人,请查看下面我的答案。我完全按照我希望的那样工作。

我知道这是一个以前可能已经讨论过的话题,但我似乎无法在我所做的搜索中找到一个直接的答案,一切都非常复杂。

我正在尝试设置我的 Powershell,以便我可以直接从 Powershell 终端编译简单的 C 程序,而无需使用 Visual Studio 或他们一直推荐的“开发人员控制台”。

到目前为止,我已经安装了 Visual Studio 构建工具,因为我试图避免下载整个 Visual Studio IDE。我能够使用开发人员控制台编译一个 Hello World C 程序作为测试,以确保一切正常并且编译和运行良好。但是,我希望能够直接从 Powershell 运行 cl.exe,而无需使用开发者控制台。

我设法在 Windows 系统属性中的环境变量中添加了一个文件夹,并成功让 Powershell 识别 cl 命令并向我显示:

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

我觉得我离这里很近,但是当我真正尝试运行“cl hello.c”来编译我的小测试程序时,我得到了这个错误:

hello.c(1): fatal error C1034: stdio.h: no include path set

我将文件夹“C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\bin\Hostx86\x64”添加到环境变量路径部分,但我注意到在不同的文件夹中有多个 cl.exe 文件。

谁能告诉我如何拨入这个东西,这样我才能真正让 cl 功能在 Powershell 中完全发挥作用?在此先感谢您提供任何帮助。

附: 我已经安装了 WSL 并且有多个可以使用 gcc 编译器的 Raspberry Pi,但这不是我的目标。我也知道诸如 MinGW 和 Cygwin 之类的东西,但我不想使用这些解决方案。我正在尝试使这个特定场景起作用:在没有开发人员控制台的情况下在 Powershell 中使用 cl 命令。没那么难,我觉得我已经很接近了,只需要添加一些更多的环境变量或其他东西。

这是我在 PowerShell 中尝试 cl 命令及其给出的错误的屏幕截图。 https://imgur.com/a/vI6oYK2

【问题讨论】:

    标签: c windows powershell visual-c++ compilation


    【解决方案1】:

    好的,感谢 Chuck Walbourn,我想通了,请查看他的答案,看看我在哪里获得了所有合适的目录来完成这项工作。要将环境变量永久添加到您的系统,以便从任何 PowerShell 终端键入“cl”,请使用 2019 版 Visual Studio 构建工具对 Windows 10 执行以下操作(这可能适用于其他变体,但您必须相应地进行调整):

    点击窗口键并开始输入“环境变量”。您将看到“编辑系统环境变量”选项。单击高级选项卡右下角的“环境变量...”按钮。您将看到“用户变量名称”和“系统变量”部分。下一步假设您在本节中没有看到“Include”和“Lib”的变量。在 System variables 部分下,点击“New...”并将变量命名为 Include,对于变量值,输入:

    C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.29.30133\include;C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt;C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\shared;C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\um;C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\winrt;C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\cppwinrt
    

    确保检查这些文件夹是否确实存在于您的系统中,并相应地调整版本号和“企业版”。我不得不将“Enterprise”更改为“BuildTools”。

    接下来创建一个名为“Lib”的新变量并输入以下内容:

    C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.29.30133\lib\x86;C:\Program Files (x86)\Windows Kits\10\lib\10.0.19041.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\lib\10.0.19041.0\um\x86
    

    同样的规则适用,请确保调整这些目录以匹配您的 Visual Studio 安装目录。

    最后,假设它为我所做的 Path 变量已经存在,双击“Path”并通过点击弹出的 Path 菜单中的 New 按钮一一添加以下键:

    C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.29.30133\bin\HostX86\x86
    
    C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x86
    
    C:\Program Files (x86)\Windows Kits\10\bin\x86
    

    调整目录以匹配您的系统,如有必要,调整 x86 与 x64 目录(我只使用 x86)。

    Here is an image 突出显示本文中提到的一些相关窗口和按钮。希望任何弄乱这些东西的人都能弄清楚这些小细节。做这一切需要您自担风险,我不知道如果出现问题,这是否会以某种方式破坏您的系统。

    如果一切顺利,你应该可以在你的 .c 文件目录中打开 PowerShell,然后输入:

    cl filename.c
    

    系统会输出filename.obj和filename.exe

    成功!再次感谢 Chuck 提供的所有帮助,并感谢 thurizas 贡献并提供另一个潜在的解决方案。

    【讨论】:

      【解决方案2】:

      打开一个 Visual Studio 开发人员命令提示符。假设它正常默认为您的 %VSINSTALLDIR%,然后在该树中搜索 vcvars.bat

      如果您查看该文件,您会发现您需要设置 INCLUDELIBPATH 才能使命令行构建工作。

      特别是,C/C++ Runtime 的“C”部分实际上是在 Windows 10 SDK 下:

      • c:\Program Files (x86)\Windows Kits\10\Include\<version>\ucrt 用于标题
      • C:\Program Files (x86)\Windows Kits\10\Lib\<version>\ucrt\<arch> 图书馆。

      Microsoft Docs

      因为 Visual Studio 支持许多并行工具集,所以编译器和 VC 运行时以及包含/库的“C++”部分位于:bininclude 和 @ 中的 C:\Program Files (x86)\Microsoft Visual Studio\2017\<VSEdition>\VC\Tools\MSVC\<toolset> 987654333@ 应设置为上述环境变量一部分的文件夹。

      例如,对于使用 Windows 10 SDK (17763) 的 VS 2017 (15.9) 企业版,这将是:

      MS-DOS 命令提示符语法:

      set INCLUDE=C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.16.27023\include;
      C:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\ucrt;
      C:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\shared;
      C:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\um;
      C:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\winrt;
      C:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\cppwinrt
      

      Powershell 语法是:

      $env:INCLUDE = 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.16.27023\include;C:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\ucrt;C:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\shared;C:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\um;C:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\winrt;C:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\cppwinrt'
      

      假设您正在创建一个 32 位 (x86) 程序:

      MS-DOS 命令提示符:

      set LIB=C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.16.27023\lib\x86;
      C:\Program Files (x86)\Windows Kits\10\lib\10.0.17763.0\ucrt\x86;
      C:\Program Files (x86)\Windows Kits\10\lib\10.0.17763.0\um\x86;
      

      PowerShell:

      $env:LIB = 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.16.27023\lib\x86;C:\Program Files (x86)\Windows Kits\10\lib\10.0.17763.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\lib\10.0.17763.0\um\x86;'
      

      这对于经典的 Win32 桌面开发应该足够了。对于 C++/CX、托管 C++ 和/或 UWP 开发,您需要额外的目录和 LIBPATH 变量集。

      并且您希望编译器本身是 32 位 (x86) EXE:

      MS-DOS 命令提示符:

      set PATH=C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.16.27023\bin\HostX86\x86;
      C:\Program Files (x86)\Windows Kits\10\bin\10.0.17763.0\x86;
      C:\Program Files (x86)\Windows Kits\10\bin\x86;
      %PATH%
      

      PowerShell:

      $env:PATH='C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.16.27023\bin\HostX86\x86;C:\Program Files (x86)\Windows Kits\10\bin\10.0.17763.0\x86;C:\Program Files (x86)\Windows Kits\10\bin\x86;' + $env:PATH
      

      VS 2019 16.11.3 w/Windows SDK (19041)

      $env:INCLUDE = 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.29.30133\include;C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt;C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\shared;C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\um;C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\winrt;C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\cppwinrt'
      
      $env:LIB = 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.29.30133\lib\x86;C:\Program Files (x86)\Windows Kits\10\lib\10.0.19041.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\lib\10.0.19041.0\um\x86;'
      
      $env:PATH='C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.29.30133\bin\HostX86\x86;C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x86;C:\Program Files (x86)\Windows Kits\10\bin\x86;' + $env:PATH
      

      Enterprise 更改为相应的 SKU:CommunityProfessionalEnterpriseBuildTools

      【讨论】:

      • 您好,感谢您的回答!我尝试将这两个目录都添加到环境变量路径部分,但仍然出现相同的错误。是否有一些关于如何设置 INCLUDE 和 LIB 的文章或其他内容,就像你提到的那样?我不确定我是否过度简化了这个过程,但我觉得我已经很接近了,只需要在某个地方进行一些调整。我还打开了 vcvars.bat 文件,但它很长,我不确定在其中查找什么对我完成设置有用。
      • 有一个Microsoft Docs 页面,但它主要告诉你运行那些批处理文件。
      • 再次感谢您提供的所有其他信息,感谢您的帮助。我将所有这些目录添加到环境变量中,但当我尝试编译时,我仍然会遇到那个讨厌的错误。您能否查看此屏幕截图并告诉我这里是否存在明显错误或遗漏的地方? imgur.com/a/xw32bey
      • 对不起,我看不到你设置了什么环境变量。你不能把它全部放在 PATH 变量中。
      • 我用我在 Powershell 中运行的内容编辑了我的原始帖子,一切似乎都没有任何错误注册,但不幸的是仍然没有运气,它仍然抱怨“stdio.h:没有包含路径集”。我找不到您列出的“ATLMFC”目录的等效路径,但添加了其他所有内容的 2019 等效路径。编辑:它似乎也不喜欢最后的 %PATH% 行,所以我也删除了它。
      【解决方案3】:

      最好的答案是使用 Visual Studio 附带的开发人员提示,因为它设置了工具所需的所有环境变量。但是,如果你坚持手工做所有事情,这就是我需要做的。

      在我的 Windows 系统上打开命令提示符并输入 cl 我得到 cl 未被识别为内部或外部命令。这里的问题是cl.exe 不在我的路径上。我可以修改path环境变量,让shell可以找到cl.exe。在我的系统上,这是通过这样做来完成的

      >set PATH="C:\VS2019\VC\Tools\MSVC\14.29.30037\bin\Hostx64\x64";%PATH%
      

      这会将cl 的路径添加到我的PATH。请注意,这仅适用于我正在使用的终端。一旦它起作用,您可以通过环境变量对其进行设置,使其在所有命令提示符中持久存在并可用。

      有一次,cl 在我的路径中,我可以尝试编译以下简单程序:

      #include <stdio.h>
      #include <stdlib.>
      
      int main(int argc, char** argv)
      {
          printf("Hello World\n");
          return 0;
      }
      

      我很高兴看到 C1034:stdio.h 没有包含路径集。这意味着尽管编译器有一组内置的目录来查找包含文件,但它找不到 stdio.h。解决方案是我需要告诉它在哪里看。

      现在在我的系统上,我可以在“C:\Windows Kits\10\Include\10.0.190410\ucrt”找到它。 (路径将特定于我的安装,您需要在系统上找到每个文件)。

      现在我可以使用 /I(包括搜索路径)选项 [1] 告诉编译器在哪里找到该文件。执行以下命令

      cl /I"C:\Windows Kits\10\Include\10.0.19041.0\ucrt hello.c
      

      给出错误“C1083:无法打开包含文件:'vcruntime.h'。我的硬盘驱动器的另一次搜索显示该文件位于“C:\VS2019\VC\Tools\MSVC\14.29.30037\include ",并执行以下命令

      cl /I"C:\Windows Kits\10\Include\10.0.19041.0\ucrt"/I"C:\VS2019\VC\Tools\MSVC\14.29.30037\include" hello.c
      

      稍微扩展一下上面的命令来做一个编译,我们可以使用下面的

      cl /c /I"C:\Windows Kits\10\Include\10.0.19041.0\ucrt"/I"C:\VS2019\VC\Tools\MSVC\14.29.30037\include" hello.c /Fo hello.o
      

      生成目标文件hello.o

      现在开始链接。 Microsoft 链接器称为 LINK[2] 并以

      开头
      LINK hello.o /OUT:hello.exe
      

      报错“LNK1104: cannot open file 'LIBCMT.lib'。嗯,这就是进步,我通过了编译阶段进入链接阶段,我只需要告诉编译器在哪里可以找到库。

      再次搜索我的硬盘驱动器显示该库位于 "C:\VS2019\VC\Tools\MSVC\14.29.30037\lib\x64",并运行以下命令,

      LINK hello.o /LIBPATH:"C:\VS2019\VC\Tools\MSVC\14.29.30037\lib\x64" /OUT:hello.exe
      

      给出错误 LNK1104:无法打开文件“kernel32.lib”,我在“C:\Windows Kits\10\lib\10.0.19041.0\um\x64”中找到该文件 我还必须添加“C:\Windows Kits\10\lib\10.0.19041.0\ucrt\x64”来解析 libucrt.lib”。以下命令

      LINK hello.o /LIBPATH:"C:\VS2019\VC\Tools\MSVC\14.29.30037\lib\x64" /LIBPATH:"C:\Windows Kits\10\lib\10.0.19041.0\um\x64" /LIBPATH:"C:\Windows Kits\10\lib\10.0.19041.0\ucrt\x64" /OUT:hello.exe    
      

      最后生成输出文件 hello.exe,可以在命令提示符下按预期生成。

      请记住,以上是针对简单的 hello-world 风格的应用程序。随着您的程序变得越来越大,您需要指定的各种路径也将变得越来越大。您可能想考虑使用 nmake 并使用 makefile 来管理您的构建。

      [1] 你可以使用“cl /?”查看 Microsoft 编译器可用的所有命令行选项。

      [2] 你可以使用“LINK /?”查看 Microsoft 链接器可用的所有命令行选项。

      【讨论】:

      • 感谢您的回复,我可能会弄乱一下,看看能不能得到一个好的结果,虽然我希望我不必每次都输入那些长命令是一些设置环境变量的方法,因此它可以正常工作。我希望能够在 PowerShell 中简单地键入“cl hello.c”来编译我的程序,就像它在开发人员控制台中工作一样。我很难相信 Windows 让这成为不可能,并且我正在顽固地寻找一种方法来完成这项工作。我目前已经按照您在前几个步骤中提到的那样在路径中设置了 cl
      • 再次感谢您的贡献,如果您有兴趣,请查看我的最新答案,了解我如何使其完全按照原始帖子中的描述工作。
      猜你喜欢
      • 2022-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多