Powershell子表达式不能识别“pkg-CONFIG--CDFLAGS--libs opencv4”命令

4ngedf3f  于 2022-11-10  发布在  Shell
关注(0)|答案(1)|浏览(89)

我想仅使用CLI在Windows上编译一个OpenCV C/C++(MSYS2)程序。实现这一点的GNU Bash方法是(在MSYS2 MINGW64 Shell上运行良好):

g++ main.cc -o main `pkg-config --cflags --libs opencv4`

Bash完美地将反号识别为子表达式,而PowerShell则不能:

> g++ main.cc -o main `pkg-config --cflags --libs opencv4`
g++.exe: error: unrecognized command-line option '--cflags'
g++.exe: error: unrecognized command-line option '--libs'

我做了一些研究,PowerShell上的等价物是

g++ main.cc -o main $(pkg-config --cflags --libs opencv4)

尽管$(pkg-config --cflags --libs opencv4)是在PowerShell中写入子表达式的正确方式,因为ECHO命令显示它会产生正确的输出(在本例中,编译器INCLUDE和链接器标志是我需要的):

> echo $(pkg-config --cflags --libs opencv4)
-IC:/msys64/mingw64/bin/../include/opencv4 -LC:/msys64/mingw64/bin/../lib -lopencv_gapi -lopencv_stitching -lopencv_alphamat -lopencv_aruco -lopencv_barcode -lopencv_bgsegm -lopencv_ccalib -lopencv_cvv -lopencv_dnn_objdetect -lopencv_dnn_superres -lopencv_dpm (...)

这根本行不通:

> g++ main.cc -o main $(pkg-config --cflags --libs opencv4)
main.cc:1:10: fatal error: opencv2/imgcodecs.hpp: No such file or directory
    1 | #include <opencv2/imgcodecs.hpp>
      |          ^~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.

因此,我需要使用详细的解决方法来编译我的文件:

> g++ main.cc -o main -IC:/msys64/mingw64/bin/../include/opencv4 -LC:/msys64/mingw64/bin/../lib -lopencv_gapi -lopencv_stitching -lopencv_alphamat -lopencv_aruco -lopencv_barcode -lopencv_bgsegm -lopencv_ccalib -lopencv_cvv -lopencv_dnn_objdetect -lopencv_dnn_superres -lopencv_dpm -lopencv_face -lopencv_freetype -lopencv_fuzzy -lopencv_hdf -lopencv_hfs -lopencv_img_hash (...)

我的PowerShell版本:

> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      5.1.22621.608
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.22621.608
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

我的问题是:我如何才能使这个特定的子表达式在PowerShell中工作,这样我就不必求助于在g++ main.cc -o main之后复制和粘贴pkg-config --cflags --libs opencv4的输出的冗长后备?

rjee0c15

rjee0c151#

相当于您的bash命令是:

g++ main.cc -o main (-split (pkg-config --cflags --libs opencv4))

即:

  • (pkg-config --cflags --libs opencv4)执行pkg-config调用,通过将其包含在分组运算符(...)中,其输出可以参与更大的表达式。
  • 使用-split的一元形式string splitting operator,然后将pkg-config调用的输出拆分成一个由空格分隔的数组,这相当于bash*隐含地通过其名为word splittingshell expansion执行的操作。
  • 数组作为参数传递给PowerShell中的外部程序会导致其元素作为单个参数传递。

注:

  • 使用$(...),PowerShell的子表达式运算符在这种情况下不工作,因为它的输出将作为一个整体*,作为单个参数传递给目标可执行文件(或者,在输出多个行的外部程序调用的情况下,每行完整将作为一个参数传递)。
  • 通常,当bash需要$(...)(或其遗留形式...)时,PowerShell中的(...)通常就足够了**(在作业中甚至不需要,例如$var = Get-Date);PowerShell中$(...)的主要用例是在"..."中,即在可扩展(双引号)的字符串中
  • 更根本的是,PowerShell没有*等同于bashshell expansions
  • 值得注意的是,parameter expansions(例如${var//foo/bar})不受支持,而需要使用表达式*(例如($var -replace 'foo', 'bar'))
  • 未加引号的参数通常不受特殊解释**的影响,除非它们包含元字符,如果它们出于语法原因逐字使用,则必须单独使用-*转义*(,所谓的反号,是PowerShell的escape character),或者要求将整个参数括在引号中。
  • 由每个目标命令将特殊字符(如首字母~)解释为引用主目录,或将参数(如*.txt)解释为通配符模式*-无论此类参数是否用引号传递。
  • 变量引用(例如$var)和基于变量引用的简单表达式(例如$var.Property)、(分组)表达式(例如((1 + 2)),以及子表达式($(...))和数组子表达式(@(...))可以按原样用作参数,即使它们评估为包含空格-在Windows上调用外部程序的情况下,PowerShell会在后台按需对结果进行双引号;如上所述,多个输出每个都*作为参数传递。
  • 有关详细信息,请参阅this answer

相关问题