我想在我的appveyor.yml
文件中跨多行拆分长构建命令,但是我无法解压缩,因此当第一个FOR
命令被切断时,构建失败了返回错误。我不确定如何正确分割.yml
文件中的行,以便在Appveyor中重新组合它们。怎么办呢?
这是一个简化版本:
build_script:
- cmd: >-
@echo off
FOR %%P IN (x86,x64) DO ( ^
FOR %%C IN (Debug,Release) DO ( ^
msbuild ^
/p:Configuration=%%C ^
/p:Platform=%%P ... ^
|| EXIT 1 ^
) ^
)
我希望它出现在AppVeyor中:
@echo off
FOR %%P IN (x86,x64) DO ( FOR %%C IN (Debug,Release) DO ( msbuild /p:Configuration=%%C /p:Platform=%%P ... || EXIT 1 ) )
额外的空格并不重要,重要的是以FOR
开头的行直到最后的)
出现在同一行。
请注意,从理论上讲,Appveyor也可以看到这一点:
@echo off
FOR %%P IN (x86,x64) DO ( ^
FOR %%C IN (Debug,Release) DO ( ^
msbuild ^
/p:Configuration=%%C ^
/p:Platform=%%P ... ^
|| EXIT 1 ^
) ^
)
因为Windows cmd.exe
解释器会在每行末尾看到延续标记(^
),并将它们视为一个很长的命令,除了那个Appveyor似乎无法识别^
标记,因此它一次将每行发送到cmd.exe
,而不是将整个多行块一起发送。
这意味着第一个选项看起来是唯一可行的解决方案,其中YAML的构造使得FOR
行及其之后的所有内容组合成一行。
我试过了:
FOR
命令因error 255
而失败,因为它不完整(只有FOR
行存在而不是其余的循环。)^
结尾的双倍行间距。 Appveyor一次只运行一行,所以我在第一个不完整的error 255
命令上得到FOR
。^
结尾,如上所示。与来自不完整error 255
命令的双倍行间距FOR
相同。&& ^
结束每一行确实在运行单独的命令(例如多个msbuild
语句)时有效,但这不适用于FOR
循环,因为您不能{ {1}}之前没有命令。在&&
中的多行上分割单个cmd
命令是否有诀窍?
答案 0 :(得分:3)
如何在appveyor.yml中的多行上拆分命令?
以下是batch,cmd,ps。
的一些语法示例我希望这些例子可以节省你一些时间......
语法示例
<强>批量强>
before_build:
- |-
set MINGW32_ARCH=i686-w64-mingw32
- if exist %PREFIX% set NEEDDEPENDS=rem
# Depends
- |-
%NEEDDEPENDS% mkdir %PREFIX%\include\SDL2
%NEEDDEPENDS% mkdir %PREFIX%\lib
%NEEDDEPENDS% cd %TEMP%
%NEEDDEPENDS% appveyor DownloadFile https://sourceforge.net/projects/gnuwin32/files/gettext/0.14.4/gettext-0.14.4-lib.zip
%NEEDDEPENDS% mkdir gettext-0.14.4-lib
%NEEDDEPENDS% move gettext-0.14.4-lib.zip gettext-0.14.4-lib
%NEEDDEPENDS% cd gettext-0.14.4-lib
%NEEDDEPENDS% 7z x gettext-0.14.4-lib.zip > nul
%NEEDDEPENDS% copy include\* %PREFIX%\include > nul
%NEEDDEPENDS% copy lib\* %PREFIX%\lib > nul
%NEEDDEPENDS% cd ..
deploy_script:
# if tagged commit, build/upload wheel
- IF "%APPVEYOR_REPO_TAG%"=="true" IF NOT "%TESTENV%"=="check" (
pip install twine &&
python setup.py register &&
twine upload -u %PYPI_USER% -p %PYPI_PASS% dist/*
)
<强> CMD 强>
before_build:
- cmd: >-
mkdir build
cd .\build
set OpenBLAS_HOME=%APPVEYOR_BUILD_FOLDER%/%MXNET_OPENBLAS_DIR%
set OpenCV_DIR=%APPVEYOR_BUILD_FOLDER%/%MXNET_OPENCV_DIR%/build
cmake .. -DOPENCV_DIR=%OpenCV_DIR% -DUSE_CUDA=0 -DUSE_CUDNN=0 -DUSE_NVRTC=0 -DUSE_OPENCV=1 -DUSE_OPENMP=1 -DUSE_BLAS=open -DUSE_DIST_KVSTORE=0 -G "Visual Studio 12 2013 Win64"
<强> PS 强>
install:
- ps: >-
git submodule init
git submodule update
if (!(Test-Path ${env:MXNET_OPENBLAS_FILE})) {
echo "Downloading openblas from ${env:MXNET_OPENBLAS_PKG} ..."
appveyor DownloadFile "${env:MXNET_OPENBLAS_PKG}" -FileName ${env:MXNET_OPENBLAS_FILE} -Timeout 1200000
}
install:
- ps: |
Add-Type -AssemblyName System.IO.Compression.FileSystem
if (!(Test-Path -Path "C:\maven" )) {
(new-object System.Net.WebClient).DownloadFile('https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.9/apache-maven-3.3.9-bin.zip', 'C:\maven-bin.zip')
[System.IO.Compression.ZipFile]::ExtractToDirectory("C:\maven-bin.zip", "C:\maven")
}
on_success:
- ps: |
if ($true)
{
Write-Host "Success"
}
答案 1 :(得分:2)
CMD
命令总是分成不同的行,并通过包装到.cmd
文件中逐个运行。将代码放到build.cmd
,提交repo,然后调用:
build_script:
- build.cmd
答案 2 :(得分:1)
使用双引号:
http.cors().and().csrf().disable().
authorizeRequests()
.antMatchers("/token/*").permitAll()
.anyRequest().permitAll()
.and()
.httpBasic()
// .formLogin()
// .loginPage("/login")
// .permitAll()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
您可以检查yaml ref,更准确地说是this example。
我在使用build_script:
- cmd: "
@echo off
FOR %%P IN (x86,x64) DO (
FOR %%C IN (Debug,Release) DO (
msbuild
/p:Configuration=%%C
/p:Platform=%%P ...
|| EXIT 1
)
)"
时遇到了同样的问题(这是一个奇怪的限制!)。使用双引号使我可以利用YAML的细微之处:
您可以查看where I use it,并了解build passes的情况。
对于其他读者,请注意,行将被折叠,因此,需要使用特殊的语法编写该行以支持...您不能省略{ {1}},例如由OP给出的表达式。
答案 3 :(得分:0)
如果你知道appveyor期望什么(我不知道),我们假设:
@echo off
FOR %%P IN (x86,x64) DO (
FOR %%C IN (Debug,Release) DO ( msbuild /p:Configuration=%%C /p:Platform=%%P ... || EXIT 1 )
)
然后通过倾倒它很容易产生适当的YAML,例如来自Python:
import sys
import ruamel.yaml
appveyor_str = """\
@echo off
FOR %%P IN (x86,x64) DO (
FOR %%C IN (Debug,Release) DO ( msbuild /p:Configuration=%%C /p:Platform=%%P ... || EXIT 1 )
)
"""
data = dict(build_script=[dict(cmd=appveyor_str)])
ruamel.yaml.round_trip_dump(data, sys.stdout)
给你:
build_script:
- cmd: "@echo off\nFOR %%P IN (x86,x64) DO (\n FOR %%C IN (Debug,Release) DO (\
\ msbuild /p:Configuration=%%C /p:Platform=%%P ... || EXIT 1 )\n)\n"
(上例中的任何换行之前没有空格)
使用folded block style scalar(使用>
)可以让您在经历时很少控制标量的折叠。在折叠(或字面)块样式标量中也无法转义序列。
如果您的多线字符串不需要转义,您可以尝试转储为块样式标量:
import sys
import ruamel.yaml
appveyor_str = """\
@echo off
FOR %%P IN (x86,x64) DO (
FOR %%C IN (Debug,Release) DO ( msbuild /p:Configuration=%%C /p:Platform=%%P ... || EXIT 1 )
)
"""
data = dict(build_script=[dict(cmd=ruamel.yaml.scalarstring.PreservedScalarString(appveyor_str))])
ruamel.yaml.round_trip_dump(data, sys.stdout)
给出:
build_script:
- cmd: |
@echo off
FOR %%P IN (x86,x64) DO (
FOR %%C IN (Debug,Release) DO ( msbuild /p:Configuration=%%C /p:Platform=%%P ... || EXIT 1 )
)
(即你输入的内容)
如果您对齐所有内容(不是您想要的可读内容),并在第一次获得所需输出后加倍换行:
import sys
import ruamel.yaml
yaml_str = """\
build_script:
- cmd: >-
@echo off
FOR %%P IN (x86,x64) DO (
FOR %%C IN (Debug,Release) DO (
msbuild
/p:Configuration=%%C
/p:Platform=%%P ...
|| EXIT 1
)
)
"""
data = ruamel.yaml.load(yaml_str)
print(data['build_script'][0]['cmd'])
给出:
@echo off
FOR %%P IN (x86,x64) DO ( FOR %%C IN (Debug,Release) DO ( msbuild /p:Configuration=%%C /p:Platform=%%P ... || EXIT 1 ) )
但你不能缩进(从折叠块样式标量的细节):
以空白字符开头的行(更多缩进行)不会折叠。
答案 4 :(得分:0)
还有另一个提示,要考虑除批处理和PS之外的其他内容。除了mingw64的“ Windows版Git”版本之外,还在传送带VM C:\msys64\usr\bin\bash
上安装了msys2 / mingw32 / mingw64。
不幸的是,要使bash中的多行命令在Appveyor中工作并不那么简单:
示例:
一段这样的代码:
cd /tmp
for server in $(grep '^Server' /etc/pacman.d/mirrorlist.msys | awk '{print $3}' | shuf | arch=x86_64 envsubst); do
echo Trying ${server}
curl --connect-timeout 10 -LO ${server}msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz && break
done"
成为
- >-
C:\msys64\usr\bin\bash -lc "
cd /tmp;
for server in $(grep $'\x5eServer' /etc/pacman.d/mirrorlist.msys | awk '{print $3}' | shuf | arch=x86_64 /usr/bin/envsubst); do
:; echo Trying ${server};
:; curl --connect-timeout 10 -LO ${server}msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz && break;
done"
在Appveyor中批量处理多行bash字符串会发生许多问题:
^
结尾。但是这样做# Literal newlines were not working
- |
bash -c "echo Not ^
echo good"
# Double quotes become a literal quote
# Equivalent: echo This is""echo now dangling
# and "" is an escaped "
- |
bash -c "echo This is"^
"echo now dangling"
# Double double quote cancel out, but you're back
# to a literal newline, not working
- |
bash -c "echo This does not"^
"""echo work either"
# The `|` notation does not seem to be useful here
# It just results in a string that won't run in appveyor
# as we desired, when using literal newlines.
# > vs >- vs >+ isn't important, it just strips extra newlines at the end
- >
bash -c "echo This
echo works"
# Indent means literal newline again
- >
bash -c "echo Does not
echo work"
# Says "This echo says", not "This" and "says"
- >-
bash -c "
echo This
echo says"
# Basically: bash -c "echo This; echo works"
- >-
bash -c "
echo This;
echo works"
# You cannot have ; after keywords then, do, etc...
- >-
bash -c "
if [ 1 == 1 ]; then
; echo No;
; echo good;
fi
# Add in a dummy "true" + semicolon, as a no-op
- >-
bash -c "
if [ 1 == 1 ]; then
:; echo This works;
fi
# Or if you prefer this style
- >-
bash -c "if [ 1 == 1 ]; then
:; echo ""This also works"";
:; fi
^
扩展到^^
,并且没有很好的解决方法# echoes ^^
bash -c "echo ^"
bash -c "echo \^"
bash -c "echo \\^"
# echoes ^^^^
bash -c "echo ^^"
# Uses a hex notation to get around the issue
bash -c "echo $'\x5e'"
\r\n
,而您只需要\n
# This is really using /mingw64/bin/envsubst in MINGW64 mode
bash -c "for x in $(echo $'${PWD}\n${OLDPWD}' | envsubst); do
:; echo ""${x}"" | xxd;
done"
# Either need to have MSYSTEM set to MSYS, or
bash -c "for x in $(echo $'${PWD}\n${OLDPWD}' | /usr/bin/envsubst); do
:; echo ""${x}"" | xxd;
done"
# or, as a last resort, use dos2unix
bash -c "for x in $(echo $'${PWD}\n${OLDPWD}' | envsubst | dos2unix); do
:; echo ""${x}"" | xxd;
done"