如何通过 MSVS 2017 x64 命令行将链接器选项传递给 `cl`?
How to pass linker options to `cl` via MSVS 2017 x64 command line?
我有一个小程序想通过命令行执行。我从 IDE 里面 运行 它 运行 没问题。我复制了整个编译命令并将其粘贴到 MSVS 命令提示符上,但出现未解决的符号链接器错误(我之前在一些不需要传递链接器选项的程序上这样做过)。
我从文档中读到我需要指定 /link linker-options
(来自 here). But when I do so, I get other errors. Then as instructed I went here,它应该说明我应该如何指定链接器选项。但它没有,它只是一个link.exe
的那些参考。我是否需要将 cl
命令通过管道传输到 link.exe
,我是否需要在 cl
之后执行它?我也找不到示例。
仅供测试,简单程序main.cpp
如下:
#include <iostream>
#include <Windows.h>
#include <string>
int main()
{
DWORD pid;
HWND hwnd = FindWindow(0, L"Calculator");
GetWindowThreadProcessId(hwnd, &pid);
if (hwnd) {
std::cout << "Window is open, id = " << pid;
}
else {
std::cout << "Window not found" << '\n';
}
system("Pause");
}
它在 IDE 中正常工作。现在,正如我提到的,我从 MSVS 2017 编译器部分复制了完整的命令:/JMC /permissive- /we"4239" /GS /Zc:rvalueCast /W3 /Zc:wchar_t /ZI /Gm- /Od /Fd"x64\Debug\vc141.pdb" /Zc:inline /fp:precise /D "_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /RTC1 /Gd /MDd /std:c++17 /FC /Fa"x64\Debug\" /EHsc /nologo /Fo"x64\Debug\" /Fp"x64\Debug\GetProcessByName.pch" /diagnostics:classic
和链接器部分:/OUT:"J:\nik\Documents\Visual_Studio_Projects\GetProcess\x64\Debug\GetProcessByName.exe" /MANIFEST /NXCOMPAT /PDB:"J:\nik\Documents\Visual_Studio_Projects\GetProcess\x64\Debug\GetProcessByName.pdb" /DYNAMICBASE "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /DEBUG /MACHINE:X64 /INCREMENTAL /PGD:"J:\nik\Documents\Visual_Studio_Projects\GetProcess\x64\Debug\GetProcessByName.pgd" /SUBSYSTEM:CONSOLE /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"x64\Debug\GetProcessByName.exe.intermediate.manifest" /ERRORREPORT:PROMPT /NOLOGO /TLBID:1
正如 Mike 所说,我将它们组合如下 cl [compile-options] main.cpp /link [linker-options]
并从 main.cpp
所在的目录执行此命令。
输出为:
c:\program files (x86)\microsoft visual studio17\community\vc\tools\msvc.1
5.26726\include\xlocale(319): warning C4530: C++ exception handler used, but unw
ind semantics are not enabled. Specify /EHsc
C:\Users\nik\documents\Visual_Studio_Projects\GetProcess\GetProcessByName\m
ain.cpp : fatal error C1083: Cannot open compiler generated file: 'x64\Debug" /E
Hsc /nologo /Fox64\Debug".asm': Invalid argument
我如何正确地 "pass"/指定链接器选项以从命令行和 运行 构建程序?
您看到的错误是编译选项中的 shell 解析错误。因此,该命令并没有达到实际编译的程度,更不用说链接了,如果您的链接选项实际上会引起任何问题,问题也不会向我们展示它们是什么。
我们看到的解析错误是由以下选项引起的:
/Fa"x64\Debug\"
documentation of /Fa
规定当表格:
/Fa directory\
用于指定程序集列表的输出目录,尾随
\
必须存在以将此形式的选项与:
区分开来
/Fa filename
您已经做到了,和 将目录名称放在引号中 - "x64\Debug\"
.
当您使用 Windows shell (cmd
) 执行命令时
解析命令行,它将引号 "..."
中的 \
视为 escape 字符。
因此尾随 \
转义 "x64\Debug\"
和 directory\
的结束 "
/Fa
的参数通过命令的后续选项继续,直到
最后,编译器识别出以下形式:
/Fa filename
并尝试打开名为:
的程序集列表,但未成功
'x64\Debug" /E Hsc /nologo /Fox64\Debug".asm'
您可以通过以下任一方式避免此解析错误:
转义引用路径名中的反斜杠
变化:
/Fa"x64\Debug\"
至:
/Fa"x64\Debug\"
命令行选项中的其他路径名也类似。
去掉引号
变化:
/Fa"x64\Debug\"
至:
/Fax64\Debug\
仅当路径名中有嵌入空格时才需要引号
路径名,这样 shell 将解析单个字符串而不是两个或多个。
您的任何路径名中都没有嵌入空格
命令行选项,因此您可以从所有选项中删除引号。
使用/
代替\
作为路径名分隔符
变化:
/Fa"x64\Debug\"
至:
/Fa"x64/Debug/"
对于命令行中的其他路径名也是如此。 Windows是唯一
操作系统使用 \
作为路径名分隔符。别人用/
,而Windows有
在最近的版本中都接受了。
如果这导致任何视觉混淆
/
用作路径分隔符 ("x64/Debug/"
),/
用作选项前缀 (/Fa
),
cl
还将允许您使用 unix 风格的选项,例如-Fa
而不是 /Fa
.
当然你也可以去掉引号和使用/
作为路径
分隔符。
如果您使用这些解决方案之一 仅 修复解析错误:
/Fa"x64\Debug\"
那么后面的选项将引发相同的解析错误:
/Fo"x64\Debug\"
因此,将所选解决方案始终如一地应用于整个命令行。
我有一个小程序想通过命令行执行。我从 IDE 里面 运行 它 运行 没问题。我复制了整个编译命令并将其粘贴到 MSVS 命令提示符上,但出现未解决的符号链接器错误(我之前在一些不需要传递链接器选项的程序上这样做过)。
我从文档中读到我需要指定 /link linker-options
(来自 here). But when I do so, I get other errors. Then as instructed I went here,它应该说明我应该如何指定链接器选项。但它没有,它只是一个link.exe
的那些参考。我是否需要将 cl
命令通过管道传输到 link.exe
,我是否需要在 cl
之后执行它?我也找不到示例。
仅供测试,简单程序main.cpp
如下:
#include <iostream>
#include <Windows.h>
#include <string>
int main()
{
DWORD pid;
HWND hwnd = FindWindow(0, L"Calculator");
GetWindowThreadProcessId(hwnd, &pid);
if (hwnd) {
std::cout << "Window is open, id = " << pid;
}
else {
std::cout << "Window not found" << '\n';
}
system("Pause");
}
它在 IDE 中正常工作。现在,正如我提到的,我从 MSVS 2017 编译器部分复制了完整的命令:/JMC /permissive- /we"4239" /GS /Zc:rvalueCast /W3 /Zc:wchar_t /ZI /Gm- /Od /Fd"x64\Debug\vc141.pdb" /Zc:inline /fp:precise /D "_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /RTC1 /Gd /MDd /std:c++17 /FC /Fa"x64\Debug\" /EHsc /nologo /Fo"x64\Debug\" /Fp"x64\Debug\GetProcessByName.pch" /diagnostics:classic
和链接器部分:/OUT:"J:\nik\Documents\Visual_Studio_Projects\GetProcess\x64\Debug\GetProcessByName.exe" /MANIFEST /NXCOMPAT /PDB:"J:\nik\Documents\Visual_Studio_Projects\GetProcess\x64\Debug\GetProcessByName.pdb" /DYNAMICBASE "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /DEBUG /MACHINE:X64 /INCREMENTAL /PGD:"J:\nik\Documents\Visual_Studio_Projects\GetProcess\x64\Debug\GetProcessByName.pgd" /SUBSYSTEM:CONSOLE /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"x64\Debug\GetProcessByName.exe.intermediate.manifest" /ERRORREPORT:PROMPT /NOLOGO /TLBID:1
正如 Mike 所说,我将它们组合如下 cl [compile-options] main.cpp /link [linker-options]
并从 main.cpp
所在的目录执行此命令。
输出为:
c:\program files (x86)\microsoft visual studio17\community\vc\tools\msvc.1
5.26726\include\xlocale(319): warning C4530: C++ exception handler used, but unw
ind semantics are not enabled. Specify /EHsc
C:\Users\nik\documents\Visual_Studio_Projects\GetProcess\GetProcessByName\m
ain.cpp : fatal error C1083: Cannot open compiler generated file: 'x64\Debug" /E
Hsc /nologo /Fox64\Debug".asm': Invalid argument
我如何正确地 "pass"/指定链接器选项以从命令行和 运行 构建程序?
您看到的错误是编译选项中的 shell 解析错误。因此,该命令并没有达到实际编译的程度,更不用说链接了,如果您的链接选项实际上会引起任何问题,问题也不会向我们展示它们是什么。
我们看到的解析错误是由以下选项引起的:
/Fa"x64\Debug\"
documentation of /Fa
规定当表格:
/Fa directory\
用于指定程序集列表的输出目录,尾随
\
必须存在以将此形式的选项与:
/Fa filename
您已经做到了,和 将目录名称放在引号中 - "x64\Debug\"
.
当您使用 Windows shell (cmd
) 执行命令时
解析命令行,它将引号 "..."
中的 \
视为 escape 字符。
因此尾随 \
转义 "x64\Debug\"
和 directory\
的结束 "
/Fa
的参数通过命令的后续选项继续,直到
最后,编译器识别出以下形式:
/Fa filename
并尝试打开名为:
的程序集列表,但未成功'x64\Debug" /E Hsc /nologo /Fox64\Debug".asm'
您可以通过以下任一方式避免此解析错误:
转义引用路径名中的反斜杠
变化:
/Fa"x64\Debug\"
至:
/Fa"x64\Debug\"
命令行选项中的其他路径名也类似。
去掉引号
变化:
/Fa"x64\Debug\"
至:
/Fax64\Debug\
仅当路径名中有嵌入空格时才需要引号 路径名,这样 shell 将解析单个字符串而不是两个或多个。 您的任何路径名中都没有嵌入空格 命令行选项,因此您可以从所有选项中删除引号。
使用/
代替\
作为路径名分隔符
变化:
/Fa"x64\Debug\"
至:
/Fa"x64/Debug/"
对于命令行中的其他路径名也是如此。 Windows是唯一
操作系统使用 \
作为路径名分隔符。别人用/
,而Windows有
在最近的版本中都接受了。
如果这导致任何视觉混淆
/
用作路径分隔符 ("x64/Debug/"
),/
用作选项前缀 (/Fa
),
cl
还将允许您使用 unix 风格的选项,例如-Fa
而不是 /Fa
.
当然你也可以去掉引号和使用/
作为路径
分隔符。
如果您使用这些解决方案之一 仅 修复解析错误:
/Fa"x64\Debug\"
那么后面的选项将引发相同的解析错误:
/Fo"x64\Debug\"
因此,将所选解决方案始终如一地应用于整个命令行。