如何通过MSVS 2017 x64命令行将链接器选项传递给`cl`?

时间:2018-10-08 19:32:14

标签: windows visual-studio linker linker-errors cl

我有一个小程序,希望通过命令行执行。我从IDE内部运行它,并且运行良好。我复制了整个编译命令,并将其粘贴到MSVS命令提示符下,但出现未解决的符号链接器错误(我以前在不需要传递链接器选项的某些程序上已这样做)。

我从文档中了解到我需要指定/link linker-options(来自here)。但是当我这样做时,我会遇到其他错误。然后按照指示我去了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 studio\2017\community\vc\tools\msvc\14.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

如何正确地“传递” /指定链接器选项以从命令行构建程序并运行该程序?

1 个答案:

答案 0 :(得分:1)

您看到的错误是编译选项中的shell解析错误。因此,该命令无法达到实际编译的目的,更不用说链接了,如果您的链接选项实际上存在任何问题,则该问题不会向我们显示它们是什么。

我们看到的解析错误是由以下选项引起的:

/Fa"x64\Debug\"

documentation of /Fa 规定当表单:

/Fa directory\

用于指定程序集列表的输出目录,尾随 必须存在\才能将这种形式的选项与以下内容区分开来:

/Fa filename

您已完成操作,将目录名称放在引号中-"x64\Debug\"

执行命令时使用的Windows Shell(cmd) 解析命令行,将引号\中的"..."视为转义字符。

因此尾随\ 逃脱 ""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\

仅当路径中包含嵌入式空格时,才需要使用路径名引起来 路径名,以便外壳程序将解析单个字符串,而不是两个或多个。 您的任何路径名中都没有任何嵌入的空格 命令行选项,因此您可以删除所有引号。

使用/代替\作为路径名分隔符

更改:

/Fa"x64\Debug\"

收件人:

/Fa"x64/Debug/"

,并类似地显示命令行中的其他路径名。 Windows是唯一的 操作系统使用\作为路径名分隔符。其他人使用/,Windows使用 在最新版本中均接受。

如果这导致 /用作路径分隔符("x64/Debug/"),/用作选项前缀(/Fa), cl也将允许您使用Unix风格的选项,例如-Fa而不是/Fa

当然,您也可以删除引号 ,并使用/作为路径 分隔符。

如果您仅使用以下解决方案之一来修复以下解析错误:

/Fa"x64\Debug\"

然后,后续选项会引发相同的解析错误:

/Fo"x64\Debug\"

因此,将选定的解决方案始终应用于整个命令行。