Powershell 子表达式无法识别“pkg-config --cflags --libs opencv4”命令

fla*_*478 5 c++ bash powershell opencv

我想仅使用 CLI 在 Windows 上编译 OpenCV C/C++ (MSYS2) 程序。GNU Bash 执行此操作的方法是(在 MSYS2 MINGW64 Shell 上运行良好):

g++ main.cc -o main `pkg-config --cflags --libs opencv4`
Run Code Online (Sandbox Code Playgroud)

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'
Run Code Online (Sandbox Code Playgroud)

我做了一些研究,PowerShell 上的等效项是

g++ main.cc -o main $(pkg-config --cflags --libs opencv4)
Run Code Online (Sandbox Code Playgroud)

尽管$(pkg-config --cflags --libs opencv4) 这是在 PowerShell 中编写子表达式的正确方法,因为echo命令显示它会产生正确的输出(在这种情况下,编译器包含我需要的链接器标志):

> 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 (...)
Run Code Online (Sandbox Code Playgroud)

它根本行不通:

> 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.
Run Code Online (Sandbox Code Playgroud)

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

> 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 (...)
Run Code Online (Sandbox Code Playgroud)

我的 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
Run Code Online (Sandbox Code Playgroud)

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

mkl*_*nt0 5

与您的命令等效的bash是:

g++ main.cc -o main (-split (pkg-config --cflags --libs opencv4))
Run Code Online (Sandbox Code Playgroud)

那是:

  • (pkg-config --cflags --libs opencv4)执行您的pkg-config调用,并且通过将其包含在(...)分组运算符中,其输出可以参与更大的表达式。

  • 使用 的一元形式-split字符串拆分运算符,然后将调用的输出拆分pkg-config为以空格分隔的标记数组,这(部分)相当于通过bash 称为分词shell 扩展隐式执行的操作。

  • 在 PowerShell 中将数组作为参数传递给外部程序会导致其元素作为单独的参数传递。


笔记:

  • 使用 时$(...),PowerShell 的子表达式运算符在这种情况下不起作用,因为它的输出将作为一个整体传递目标可执行文件(或者,在输出多行的外部程序调用的情况下,每行在full将作为参数传递)。

  • 一般来说,在 PowerShell 中bashrequire $(...)(或其遗留形式),通常就足够了`...`(...)(在赋值中甚至不需要它,例如$var = Get-Date);$(...)PowerShell 中的主要用例是 inside "...",即在可扩展(双引号)字符串内

  • 更根本的是,PowerShell 没有相当于bashshell扩展

    • 值得注意的是,不支持参数扩展(例如${var//foo/bar}),并且需要使用表达式(例如)($var -replace 'foo', 'bar')

    • 不带引号的参数通常不会受到特殊解释,除非它们包含字符,如果要逐字使用元字符,出于语法原因,则必须单独`转义(即所谓的反引号,是 PowerShell 的转义字符),或者要求将整个参数括在引号中。`

    • 由每个目标命令来解释特殊字符(例如~引用主目录的首字母),或解释参数(例如*.txt通配符模式) - 无论此类参数是否在引号中传递。

    • 变量引用(例如$var)和基于它们的简单表达式(例如$var.Property)、(分组)表达式(例如 ( )(1 + 2)以及子表达式 ( $(...)) 和数组子表达式 ( ) 可以按原样@(...)用作参数,即使它们是什么计算结果包含空格- 在 Windows 上调用外部程序的情况下,PowerShell 将在幕后根据需要对结果加双引号;如上所述,多个输出作为参数传递。