当从包含反斜杠的响应 @file 中读取参数时,为什么 ld 不能从 MSYS 调用找到(现有静态)库?
Why can't ld called from MSYS find (existing static) library when arguments are read from a response @file containing backslashes?
这基本上与 mingw ld cannot find some library which is exist in the search path, MinGW linker can't find MPICH2 libraries - and I'm aware that there are heaps of posts on Whosebug regarding the issue of static and dynamic linking with MinGW 中的问题相同 - 但我找不到任何说明如何解决问题的信息。
我正在 MSYS2 shell (git-bash.exe
) 中的 MinGW 上构建一个带有巨大链接器命令的项目,例如(通过 g++
)。该过程失败,其中包括:
/z/path/to/../../../../i686-w64-mingw32/bin/ld.exe: cannot find -lssl
我将 -Wl,--verbose
添加到 g++
链接器调用(将传递给 ld
),我可以看到 -L/z/path/to/libs/openssl/lib/mingw -lssl
:
...
attempt to open /z/path/to/libs/openssl/lib/mingw/libssl.a failed
...
/z/path/to/libs/openssl/lib/mingw/ssl.dll failed
attempt to open /z/path/to/libs/openssl/lib/mingw\libssl.a failed
...
但这很奇怪,因为文件存在?
$ file /z/path/to/libs/openssl/lib/mingw/libssl.a
/z/path/to/libs/openssl/lib/mingw/libssl.a: current ar archive
(...并且它是在同一台机器上使用相同的编译器构建的)?
奇怪的是,一旦它尝试使用正斜杠 .../libssl.a
打开,一次使用反斜杠 ...\libssl.a
- 但至少第一个路径在 bash
shell 中检出, 如上图?
如果我尝试指定 -l:libssl.a
- 或者如果我指定 -L/z/path/to/libs/openssl/lib/mingw -Wl,-Bstatic -lssl
- 则会变得更糟;那么所有打开的尝试都带有反斜杠:
...
attempt to open /z/path/to/scripts/other/build/openssl/build/mingw/lib\libssl.a failed
attempt to open /z/path/to/libs/openssl/lib/mingw\libssl.a failed
...
最重要的是,如果我使用 ld
通过命令行手动查找它,它会找到 ?!:
$ ld -L/z/path/to/libs/openssl/lib/mingw -lssl --verbose
attempt to open Z:/path/to/libs/openssl/lib/mingw/libssl.dll.a failed
attempt to open Z:/path/to/libs/openssl/lib/mingw/ssl.dll.a failed
attempt to open Z:/path/to/libs/openssl/lib/mingw/libssl.a succeeded
有谁知道为什么会这样,我怎样才能 ld
最终找到这些库?或者更确切地说 - 当这些库存在于 ld
试图打开它们的路径时,我如何排除故障并理解为什么找不到这些库?
好的,发现了更多东西 - 不确定这是否是一个错误;但我的问题是我实际上是在从文件中读取参数(否则我会得到 g++: Argument list too long
)。因此,要模拟:
$ echo " -Wl,--verbose -L/z/path/to/libs/openssl/lib/mingw -lssl -lcrypto " > tmcd3
$ g++ @tcmd3 2>&1 | grep succeeded | grep ssl
# nothing
$ g++ `cat tcmd3` 2>&1 | grep succeeded | grep ssl
attempt to open Z:/path/to/libs/openssl/lib/mingw/libssl.a succeeded
attempt to open Z:/path/to/libs/openssl/lib/mingw/libcrypto.a succeeded
...事实证明,如果在命令行上输入完全相同的参数,那么静态库查找就会成功 - 但如果通过 @
符号从文件中读取参数,那么静态库查找失败?!不幸的是,我不能在我的实际项目中使用,因为即使使用 cat
,我仍然会得到 g++: Argument list too long
...那么我该如何解决这个问题?
好的,通过更多实验,我注意到:
-L/z/path/to/libs/openssl/lib/mingw
,Unix 路径规范,往往会失败 - 而如果我们指定相同,除了以 Windows 驱动器号开头,即:
-LZ:/path/to/libs/openssl/lib/mingw
,然后一切正常 - 也来自带有 @
at-sign 的参数文件:
$ echo " -Wl,--verbose -LZ:/path/to/libs/openssl/lib/mingw -lssl -lcrypto " > tmcd3
$ g++ @tcmd3 2>&1 | grep succeeded | grep ssl
attempt to open Z:/path/to/libs/openssl/lib/mingw/libssl.a succeeded
attempt to open Z:/path/to/libs/openssl/lib/mingw/libcrypto.a succeeded
我想,因为 shell 是 MSYS2/git-bash.exe
,在 shell 和 /z/...
上输入完整的 POSIX 路径不是问题,因为 shell 会转换它们 - 但在文件中,没有任何东西可以转换它们,所以我们必须使用 Windows/MingW 约定来指定它们...
MSYS 在 shell 中使用时,将目录作为参数进行特殊处理。这翻译例如/<drive_letter>/blabla
到正确的 Windows 样式路径。这是为了适应不处理 Z:
样式目录根目录的 Unix 程序。
您在这里看到的是 MSYS 没有对从文件中读取的字符串执行此解释。仔细想想,很有道理,但亲身经历过,有时也很烦人。
长话短说:不要将 Unix 风格的路径放在带有命令参数的文件中。相反,将它们通过例如cygpath -w
,适用于 MSYS2(应该是 Git for Windows 2+ 自带的 MSYS)。
这基本上与 mingw ld cannot find some library which is exist in the search path, MinGW linker can't find MPICH2 libraries - and I'm aware that there are heaps of posts on Whosebug regarding the issue of static and dynamic linking with MinGW 中的问题相同 - 但我找不到任何说明如何解决问题的信息。
我正在 MSYS2 shell (git-bash.exe
) 中的 MinGW 上构建一个带有巨大链接器命令的项目,例如(通过 g++
)。该过程失败,其中包括:
/z/path/to/../../../../i686-w64-mingw32/bin/ld.exe: cannot find -lssl
我将 -Wl,--verbose
添加到 g++
链接器调用(将传递给 ld
),我可以看到 -L/z/path/to/libs/openssl/lib/mingw -lssl
:
...
attempt to open /z/path/to/libs/openssl/lib/mingw/libssl.a failed
...
/z/path/to/libs/openssl/lib/mingw/ssl.dll failed
attempt to open /z/path/to/libs/openssl/lib/mingw\libssl.a failed
...
但这很奇怪,因为文件存在?
$ file /z/path/to/libs/openssl/lib/mingw/libssl.a
/z/path/to/libs/openssl/lib/mingw/libssl.a: current ar archive
(...并且它是在同一台机器上使用相同的编译器构建的)?
奇怪的是,一旦它尝试使用正斜杠 .../libssl.a
打开,一次使用反斜杠 ...\libssl.a
- 但至少第一个路径在 bash
shell 中检出, 如上图?
如果我尝试指定 -l:libssl.a
- 或者如果我指定 -L/z/path/to/libs/openssl/lib/mingw -Wl,-Bstatic -lssl
- 则会变得更糟;那么所有打开的尝试都带有反斜杠:
...
attempt to open /z/path/to/scripts/other/build/openssl/build/mingw/lib\libssl.a failed
attempt to open /z/path/to/libs/openssl/lib/mingw\libssl.a failed
...
最重要的是,如果我使用 ld
通过命令行手动查找它,它会找到 ?!:
$ ld -L/z/path/to/libs/openssl/lib/mingw -lssl --verbose
attempt to open Z:/path/to/libs/openssl/lib/mingw/libssl.dll.a failed
attempt to open Z:/path/to/libs/openssl/lib/mingw/ssl.dll.a failed
attempt to open Z:/path/to/libs/openssl/lib/mingw/libssl.a succeeded
有谁知道为什么会这样,我怎样才能 ld
最终找到这些库?或者更确切地说 - 当这些库存在于 ld
试图打开它们的路径时,我如何排除故障并理解为什么找不到这些库?
好的,发现了更多东西 - 不确定这是否是一个错误;但我的问题是我实际上是在从文件中读取参数(否则我会得到 g++: Argument list too long
)。因此,要模拟:
$ echo " -Wl,--verbose -L/z/path/to/libs/openssl/lib/mingw -lssl -lcrypto " > tmcd3
$ g++ @tcmd3 2>&1 | grep succeeded | grep ssl
# nothing
$ g++ `cat tcmd3` 2>&1 | grep succeeded | grep ssl
attempt to open Z:/path/to/libs/openssl/lib/mingw/libssl.a succeeded
attempt to open Z:/path/to/libs/openssl/lib/mingw/libcrypto.a succeeded
...事实证明,如果在命令行上输入完全相同的参数,那么静态库查找就会成功 - 但如果通过 @
符号从文件中读取参数,那么静态库查找失败?!不幸的是,我不能在我的实际项目中使用,因为即使使用 cat
,我仍然会得到 g++: Argument list too long
...那么我该如何解决这个问题?
好的,通过更多实验,我注意到:
-L/z/path/to/libs/openssl/lib/mingw
,Unix 路径规范,往往会失败 - 而如果我们指定相同,除了以 Windows 驱动器号开头,即:-LZ:/path/to/libs/openssl/lib/mingw
,然后一切正常 - 也来自带有@
at-sign 的参数文件:
$ echo " -Wl,--verbose -LZ:/path/to/libs/openssl/lib/mingw -lssl -lcrypto " > tmcd3
$ g++ @tcmd3 2>&1 | grep succeeded | grep ssl
attempt to open Z:/path/to/libs/openssl/lib/mingw/libssl.a succeeded
attempt to open Z:/path/to/libs/openssl/lib/mingw/libcrypto.a succeeded
我想,因为 shell 是 MSYS2/git-bash.exe
,在 shell 和 /z/...
上输入完整的 POSIX 路径不是问题,因为 shell 会转换它们 - 但在文件中,没有任何东西可以转换它们,所以我们必须使用 Windows/MingW 约定来指定它们...
MSYS 在 shell 中使用时,将目录作为参数进行特殊处理。这翻译例如/<drive_letter>/blabla
到正确的 Windows 样式路径。这是为了适应不处理 Z:
样式目录根目录的 Unix 程序。
您在这里看到的是 MSYS 没有对从文件中读取的字符串执行此解释。仔细想想,很有道理,但亲身经历过,有时也很烦人。
长话短说:不要将 Unix 风格的路径放在带有命令参数的文件中。相反,将它们通过例如cygpath -w
,适用于 MSYS2(应该是 Git for Windows 2+ 自带的 MSYS)。