Аз версияи 7.04 сар карда, таҳлилгари PVS-Studio барои забонҳои C ва C++ дар Linux ва macOS имкони санҷишӣ барои тафтиши рӯйхати файлҳои муайяншударо дорад. Бо истифода аз реҷаи нав, шумо метавонед анализаторро барои тафтиши супоришҳо ва гирифтани дархостҳо танзим кунед. Ин мақола ба шумо нишон медиҳад, ки чӣ гуна санҷиши рӯйхати файлҳои лоиҳаи GitHub дар системаҳои маъмули CI (Интегратсияи доимӣ) ба монанди Travis CI, Buddy ва AppVeyor.
Ҳолати тафтиши рӯйхати файлҳо
Версияи PVS-Studio 7.04 барои Linux ва macOS дорои режими санҷиши рӯйхати файлҳои манбаъ мебошад. Ин барои лоиҳаҳое кор мекунад, ки системаи сохтани онҳо ба шумо имкон медиҳад файл тавлид кунед
Инчунин, реҷаи тафтиши рӯйхати файлҳоро метавон дар якҷоягӣ бо пайгирии пайгирии иҷроҳои компилятор (pvs-studio-analyzer trace) истифода бурд. Барои ин ба шумо лозим меояд, ки пеш аз ҳама тарҳи пурраи лоиҳаро анҷом диҳед ва онро пайгирӣ кунед, то анализатор маълумоти пурраро дар бораи параметрҳои компиляцияи ҳамаи файлҳои тафтишшаванда ҷамъоварӣ кунад.
Аммо, ин хосият як нуқсони назаррас дорад - ба шумо лозим меояд, ки дар ҳар як оғозёбӣ пайгирии пурраи тамоми лоиҳаро иҷро кунед, ки ин худ ба идеяи санҷиши фаврӣ мухолиф аст. Ё, агар шумо худи натиҷаи пайгирӣ кэш кунед, пас аз пайгирӣ сохтори вобастагии файли манбаъ тағир дода мешавад (масалан, ба яке аз файлҳои сарчашма #include нав илова карда мешавад) оғозёбии минбаъдаи анализатор метавонад нопурра бошад.
Аз ин рӯ, мо тавсия намедиҳем, ки реҷаи тафтиши рӯйхати файлҳоро бо сабти пайгирӣ барои тафтиши ӯҳдадориҳо ё кашидани дархостҳо истифода барем. Дар ҳолате, ки шумо метавонед ҳангоми санҷиши ӯҳдадориҳо сохтани афзоянда иҷро кунед, истифодаи режимро баррасӣ кунед
Рӯйхати файлҳои ибтидоӣ барои таҳлил дар файли матнӣ захира карда мешавад ва бо истифода аз параметр ба анализатор интиқол дода мешавад -S:
pvs-studio-analyzer analyze ... -f build/compile_commands.json -S check-list.txt
Ин файл роҳҳои нисбӣ ё мутлақи файлҳоро муайян мекунад ва ҳар як файли нав бояд дар сатри нав бошад. Барои таҳлил на танҳо номи файлҳо, балки матни гуногунро низ нишон додан ҷоиз аст. Таҳлилгар мебинад, ки ин файл нест ва сатрро нодида мегирад. Ин метавонад барои шарҳ додан муфид бошад, агар файлҳо дастӣ муайян карда шаванд. Аммо, аксар вақт рӯйхати файлҳо ҳангоми таҳлили CI тавлид мешаванд, масалан файлҳо аз супориш ё дархости кашидан.
Ҳоло, бо истифода аз ин режим, шумо метавонед рамзи навро пеш аз ворид шудан ба шохаи асосии рушд зуд санҷед. Барои он ки системаи тафтиш ба огоҳиҳои анализатор вокуниш нишон диҳад, утилита табдилдиҳандаи plog байрақ илова карда шуд --огоњсозї:
plog-converter ... --indicate-warnings ... -o /path/to/report.tasks ...
Бо ин парчам, агар дар гузориши таҳлилгар огоҳиҳо мавҷуд бошанд, конвертер рамзи ғайрисифрро бармегардонад. Бо истифода аз рамзи бозгашт, шумо метавонед қалмоқе, ки дархости пешакиро маҳкам кунед, дархост кунед ё кашед ва гузориши таҳлилгари тавлидшударо дар экран намоиш диҳед, онро мубодила кунед ё тавассути почта ирсол кунед.
Шарҳ. Вақте ки шумо бори аввал ба таҳлили рӯйхати файлҳо шурӯъ мекунед, тамоми лоиҳа таҳлил карда мешавад, зеро анализатор бояд файли вобастагии файлҳои ибтидоии лоиҳаро аз файлҳои сарлавҳа тавлид кунад. Ин хусусияти таҳлили файлҳои C ва C++ мебошад. Дар оянда файли вобастагӣ метавонад кэш карда шавад ва он аз ҷониби анализатор ба таври худкор нав карда мешавад. Бартарии тафтиши ӯҳдадориҳо ҳангоми истифодаи реҷаи санҷиши рӯйхати файлҳо нисбат ба истифодаи режими афзояндаи таҳлил дар он аст, ки танҳо он файл бояд кэш карда шавад, на файлҳои объект.
Принсипҳои умумии таҳлили дархост
Таҳлили тамоми лоиҳа вақти зиёдро мегирад, бинобар ин тафтиш кардани танҳо як қисми он маъно дорад. Масъала дар он аст, ки шумо бояд файлҳои навро аз боқимондаи файлҳои лоиҳа ҷудо кунед.
Намунаи дарахти ӯҳдадориро бо ду шоха дида бароед:
Биёед вонамуд кунем, ки ухдадор A1 дорои миқдори хеле зиёди рамзест, ки аллакай санҷида шудааст. Каме пештар аз уҳдадорӣ филиал сохтем A1 ва баъзе файлҳоро тағир дод.
Албатта, шумо инро пас аз он пай бурдед A1 ду ӯҳдадориҳои дигар буданд, аммо инҳо ҳам якҷояшавии филиалҳои дигар буданд, зеро мо ӯҳдадор нестем усто. Ва акнун фурсате расидааст, ки таъғир меёбад тайёр. Аз ин рӯ, дархости ҷалб барои якҷоякунӣ пайдо шуд B3 и A3.
Албатта, тамоми натиҷаи якҷояшавии онҳоро тафтиш кардан мумкин буд, аммо ин хеле тӯлонӣ ва беасос мебуд, зеро танҳо якчанд файлҳо тағир дода шудаанд. Аз ин рӯ, таҳлили танҳо ивазшудагон самараноктар аст.
Барои ин, мо фарқияти байни шохаҳоро ба даст меорем, ки дар САРИ филиале ҳастем, ки мо мехоҳем ба устод ҳамроҳ шавем:
git diff --name-only HEAD origin/$MERGE_BASE > .pvs-pr.list
$MERGE_BASE баъдтар муфассал дида мебароем. Гап дар он аст, ки на ҳама хидматҳои CI маълумоти заруриро дар бораи пойгоҳ барои муттаҳидшавӣ пешниҳод мекунанд, аз ин рӯ ҳар дафъа шумо бояд роҳҳои нави гирифтани ин маълумотро пайдо кунед. Ин дар зер дар ҳар як хидматҳои веб тавсиф карда мешавад.
Ҳамин тавр, мо фарқияти байни шохаҳо, дурусттараш, рӯйхати номҳои файлҳои тағирёфтаро гирифтем. Акнун мо бояд файлро супорем .pvs-pr.list (мо баромади болоро ба он равона кардем) ба анализатор:
pvs-studio-analyzer analyze -j8
-o PVS-Studio.log
-S .pvs-pr.list
Пас аз таҳлил, мо бояд файли сабтро (PVS-Studio.log) ба формати хондашаванда табдил диҳем:
plog-converter -t errorfile PVS-Studio.log --cerr -w
Ин фармон хатогиҳоро дар
Танҳо дар ин ҷо ба мо лозим аст, ки на танҳо хатогиҳоро нишон диҳем, балки инчунин ба хидмати худ оид ба васлкунӣ ва санҷиш дар бораи мавҷудияти мушкилот хабар диҳем. Барои ин ба конвертер байрақ илова карда шуд -W (--огоњсозї). Агар ҳадди аққал як огоҳии анализатор мавҷуд бошад, рамзи баргардонидани утилита табдилдиҳандаи plog ба 2 тағйир меёбад, ки дар навбати худ хидмати CI-ро дар бораи хатогиҳои эҳтимолӣ дар файлҳои дархости кашидан огоҳ мекунад.
Травис CI
Конфигуратсия дар шакли файл сохта шудааст .travis.yml. Барои роҳат, ман ба шумо маслиҳат медиҳам, ки ҳама чизро дар скрипти алоҳидаи bash бо функсияҳое гузоред, ки аз файл даъват карда мешаванд .travis.yml (bash scriptname.sh function_name).
Мо рамзи заруриро ба скрипт илова мекунем bash, аз ин рӯ мо функсияҳои бештар ба даст меорем. Дар бахш насб кунед зеринро нависед:
install:
- bash .travis.sh travis_install
Агар шумо ягон дастур дошта бошед, шумо метавонед онҳоро бо хориҷ кардани дефис ба скрипт интиқол диҳед.
Биёед файлро кушоем .travis.sh ва танзимоти анализаторро ба функсия илова кунед travis_install():
travis_install() {
wget -q -O - https://files.viva64.com/etc/pubkey.txt
| sudo apt-key add -
sudo wget -O /etc/apt/sources.list.d/viva64.list
https://files.viva64.com/etc/viva64.list
sudo apt-get update -qq
sudo apt-get install -qq pvs-studio
}
Акнун биёед ба бахш илова кунем барномаи саҳнавӣ таҳлили иҷро:
script:
- bash .travis.sh travis_script
Ва дар скрипти bash:
travis_script() {
pvs-studio-analyzer credentials $PVS_USERNAME $PVS_KEY
if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
git diff --name-only origin/HEAD > .pvs-pr.list
pvs-studio-analyzer analyze -j8
-o PVS-Studio.log
-S .pvs-pr.list
--disableLicenseExpirationCheck
else
pvs-studio-analyzer analyze -j8
-o PVS-Studio.log
--disableLicenseExpirationCheck
fi
plog-converter -t errorfile PVS-Studio.log --cerr -w
}
Ин код бояд пас аз сохта шудани лоиҳа иҷро карда шавад, масалан, агар шумо CMake бунёд дошта бошед:
travis_script() {
CMAKE_ARGS="-DCMAKE_EXPORT_COMPILE_COMMANDS=On ${CMAKE_ARGS}"
cmake $CMAKE_ARGS CMakeLists.txt
make -j8
}
Ин чунин мешавад:
travis_script() {
CMAKE_ARGS="-DCMAKE_EXPORT_COMPILE_COMMANDS=On ${CMAKE_ARGS}"
cmake $CMAKE_ARGS CMakeLists.txt
make -j8
pvs-studio-analyzer credentials $PVS_USERNAME $PVS_KEY
if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
git diff --name-only origin/HEAD > .pvs-pr.list
pvs-studio-analyzer analyze -j8
-o PVS-Studio.log
-S .pvs-pr.list
--disableLicenseExpirationCheck
else
pvs-studio-analyzer analyze -j8
-o PVS-Studio.log
--disableLicenseExpirationCheck
fi
plog-converter -t errorfile PVS-Studio.log --cerr -w
}
Эҳтимол шумо аллакай тағирёбандаҳои муҳити зистро мушоҳида кардаед. $TRAVIS_PULL_REQUEST и $TRAVIS_BRANCH. Травис CI онҳоро мустақилона эълон мекунад:
- $TRAVIS_PULL_REQUEST рақами дархости кашидаро нигоҳ медорад, ё бардурӯғагар он шохаи муқаррарӣ бошад;
- $TRAVIS_REPO_SLUG номи анбори лоиҳаро нигоҳ медорад.
Алгоритми ин функсия:
Травис CI ба рамзҳои баргардонидан посух медиҳад, бинобар ин мавҷудияти огоҳиҳо ба хидмат нишон медиҳад, ки супоришро ҳамчун хатогӣ қайд кунад.
Биёед ба ин сатри код муфассалтар назар андозем:
git diff --name-only origin/HEAD > .pvs-pr.list
Далели он аст, ки Travis CI ҳангоми таҳлили дархости ҷалб филиалҳоро ба таври худкор муттаҳид мекунад:
Аз ин рӯ, мо таҳлил мекунем A4ва не B3->A3. Аз сабаби ин хусусият, мо бояд фарқиятро аз A3, ки танҳо болои филиал аз пайдоиш.
Як ҷузъиёти муҳим боқӣ мемонад - кэшкунии вобастагии файлҳои сарлавҳа аз воҳидҳои тарҷумаи тартибдодашуда (*.c, *.cc, *.cpp ва ғайра). Анализатор ин вобастагиҳоро дар оғози аввал дар ҳолати тафтиши рӯйхати файлҳо ҳисоб мекунад ва сипас онҳоро дар директорияи .PVS-Studio захира мекунад. Travis CI ба шумо имкон медиҳад, ки ҷузвдонҳоро кэш кунед, аз ин рӯ мо маълумоти феҳристиро захира мекунем .PVS-Studio/:
cache:
directories:
- .PVS-Studio/
Ин код бояд ба файл илова карда шавад .travis.yml. Ин феҳрист маълумоти мухталиферо, ки пас аз таҳлил ҷамъоварӣ шудаанд, нигоҳ медорад, ки ин равандҳои минбаъдаи таҳлили рӯйхати файлҳо ё таҳлили афзояндаро ба таври назаррас суръат мебахшад. Агар ин кор карда нашавад, пас анализатор воқеан ҳама файлҳоро ҳар дафъа таҳлил мекунад.
Буддо
Мисли Travis C.I.,
Пеш аз ҳама, мо бояд ба хати сохтмон як амали нав илова кунем:
Компилятореро, ки барои сохтани лоиҳа истифода шудааст, муайян кунед. Ба контейнери докер, ки дар ин фаъолият насб шудааст, аҳамият диҳед. Масалан, барои GCC як контейнери махсус вуҷуд дорад:
Акнун биёед PVS-Studio ва утилитаҳои заруриро насб кунем:
Ба муҳаррир сатрҳои зеринро илова кунед:
apt-get update && apt-get -y install wget gnupg jq
wget -q -O - https://files.viva64.com/etc/pubkey.txt | apt-key add -
wget -O /etc/apt/sources.list.d/viva64.list
https://files.viva64.com/etc/viva64.list
apt-get update && apt-get -y install pvs-studio
Акнун биёед ба ҷадвали "Иҷроиш" (нишонаи аввал) равем ва рамзи зеринро ба майдони мувофиқи муҳаррир илова кунед:
pvs-studio-analyzer credentials $PVS_USERNAME $PVS_KEY
if [ "$BUDDY_EXECUTION_PULL_REQUEST_NO" != '' ]; then
PULL_REQUEST_ID="pulls/$BUDDY_EXECUTION_PULL_REQUEST_NO"
MERGE_BASE=`wget -qO -
https://api.github.com/repos/${BUDDY_REPO_SLUG}/${PULL_REQUEST_ID}
| jq -r ".base.ref"`
git diff --name-only HEAD origin/$MERGE_BASE > .pvs-pr.list
pvs-studio-analyzer analyze -j8
-o PVS-Studio.log
--disableLicenseExpirationCheck
-S .pvs-pr.list
else
pvs-studio-analyzer analyze -j8
-o PVS-Studio.log
--disableLicenseExpirationCheck
fi
plog-converter -t errorfile PVS-Studio.log --cerr -w
Агар шумо қисматро дар Travs-CI хонда бошед, пас ин рамз ба шумо аллакай шинос аст, аммо ҳоло як қадами нав вуҷуд дорад:
Гап дар сари он аст, ки ҳоло мо на натиҷаи муттаҳидшавӣ, балки САРДОРИ филиалро, ки аз он дархости кашидан гирифта шудааст, таҳлил мекунем:
Пас, мо дар ӯҳдадории шартӣ ҳастем B3 ва мо бояд аз он фарқ кунем A3:
PULL_REQUEST_ID="pulls/$BUDDY_EXECUTION_PULL_REQUEST_NO"
MERGE_BASE=`wget -qO -
https://api.github.com/repos/${BUDDY_REPO_SLUG}/${PULL_REQUEST_ID}
| jq -r ".base.ref"`
git diff --name-only HEAD origin/$MERGE_BASE > .pvs-pr.list
Барои муайян кардан A3 Биёед API-и GitHub-ро истифода барем:
https://api.github.com/repos/${USERNAME}/${REPO}/pulls/${PULL_REQUEST_ID}
Мо тағирёбандаҳои зерини аз ҷониби Buddy пешниҳодшударо истифода бурдем:
- $BUDDY_EXECUTION_PULL_REQEUST_NO - гирифтани рақами дархост;
- $BUDDY_REPO_SLUG - маҷмӯи номи корбар ва анбор (масалан, макс / санҷиш).
Акнун биёед тағиротро бо истифода аз тугмаи зер захира кунем ва таҳлили дархостро фаъол созем:
Баръакси Travis CI, ба мо лозим нест, ки мушаххас кунем .pvs-студияи барои кэш, зеро Buddy ба таври худкор ҳамаи файлҳоро барои оғозёбии минбаъда кэш мекунад. Аз ин рӯ, охирин чизе боқӣ мондааст, ки логин ва паролро барои PVS-Studio дар Buddy захира кунед. Пас аз захира кардани тағирот, мо ба қубур бармегардем. Мо бояд ба танзими тағирёбандаҳо равем ва воридшавӣ ва калидро барои PVS-Studio илова кунем:
Пас аз он, пайдоиши дархост ё ӯҳдадории нави кашидан чекро ба вуҷуд меорад. Агар ӯҳдадорӣ хатогиҳо дошта бошад, пас Бадди онро дар саҳифаи дархости кашидан нишон медиҳад.
AppVeyor
Насб кардани AppVeyor ба Buddy монанд аст, зеро ҳама чиз дар интерфейси веб рух медиҳад ва ба анбори лоиҳа илова кардани файли *.yml лозим нест.
Биёед ба ҷадвали Танзимот дар шарҳи лоиҳа равем:
Биёед ин саҳифаро ба поён ҳаракат кунем ва сарфаи кэшро барои сохтани дархостҳои кашидан фаъол созем:
Акнун биёед ба ҷадвали Муҳити зист равем, ки дар он мо тасвири сохтан ва тағирёбандаҳои муҳити заруриро муайян мекунем:
Агар шумо бахшҳои қаблиро хонда бошед, шумо бо ин ду тағирёбанда хеле шинос ҳастед - PVS_KEY и PVS_USERNAME. Дар акси ҳол, ман ба шумо хотиррасон мекунам, ки онҳо бояд иҷозатномаи анализатори PVS-Studio-ро тафтиш кунанд. Дар оянда мо бо онҳо боз дар скриптҳои Баш вомехӯрем.
Дар ҳамон саҳифаи зер ҷузвдони кэшро муайян кунед:
Агар мо ин корро накунем, пас мо ба ҷои якчанд файлҳо тамоми лоиҳаро таҳлил мекунем, аммо мо натиҷаро дар асоси файлҳои нишондодашуда мегирем. Аз ин рӯ, муҳим аст, ки номи директорияро дуруст ворид кунед.
Ҳоло вақти санҷиши скрипт аст. Ҷадвали Санҷишҳоро кушоед ва Скриптро интихоб кунед:
Рамзи зеринро ба ин форма гузоред:
sudo apt-get update && sudo apt-get -y install jq
wget -q -O - https://files.viva64.com/etc/pubkey.txt
| sudo apt-key add -
sudo wget -O /etc/apt/sources.list.d/viva64.list
https://files.viva64.com/etc/viva64.list
sudo apt-get update && sudo apt-get -y install pvs-studio
pvs-studio-analyzer credentials $PVS_USERNAME $PVS_KEY
PWD=$(pwd -L)
if [ "$APPVEYOR_PULL_REQUEST_NUMBER" != '' ]; then
PULL_REQUEST_ID="pulls/$APPVEYOR_PULL_REQUEST_NUMBER"
MERGE_BASE=`wget -qO -
https://api.github.com/repos/${APPVEYOR_REPO_NAME}/${PULL_REQUEST_ID}
| jq -r ".base.ref"`
git diff --name-only HEAD origin/$MERGE_BASE > .pvs-pr.list
pvs-studio-analyzer analyze -j8
-o PVS-Studio.log
--disableLicenseExpirationCheck
--dump-files --dump-log pvs-dump.log
-S .pvs-pr.list
else
pvs-studio-analyzer analyze -j8
-o PVS-Studio.log
--disableLicenseExpirationCheck
fi
plog-converter -t errorfile PVS-Studio.log --cerr -w
Биёед ба қисми зерини код назар андозем:
PWD=$(pwd -L)
if [ "$APPVEYOR_PULL_REQUEST_NUMBER" != '' ]; then
PULL_REQUEST_ID="pulls/$APPVEYOR_PULL_REQUEST_NUMBER"
MERGE_BASE=`wget -qO -
https://api.github.com/repos/${APPVEYOR_REPO_NAME}/${PULL_REQUEST_ID}
| jq -r ".base.ref"`
git diff --name-only HEAD origin/$MERGE_BASE > .pvs-pr.list
pvs-studio-analyzer analyze -j8
-o PVS-Studio.log
--disableLicenseExpirationCheck
--dump-files --dump-log pvs-dump.log
-S .pvs-pr.list
else
pvs-studio-analyzer analyze -j8
-o PVS-Studio.log
--disableLicenseExpirationCheck
fi
Таъиноти нисбатан мушаххаси арзиши фармони pwd ба тағирёбанда, ки бояд ин арзиши пешфарзро нигоҳ дорад, дар назари аввал аҷиб менамояд, аммо ман ҳама чизро дар як лаҳза шарҳ медиҳам.
Ҳангоми насб кардани анализатор дар AppVeyor, ман бо рафтори бениҳоят аҷиби анализатор дучор шудам. Аз як тараф, ҳама чиз дуруст кор мекард, аммо таҳлил оғоз нашуд. Ман вақти зиёд сарф кардам, ки мо дар феҳристи /home/appveyor/projects/testcalc/ ҳастем ва анализатор боварӣ дорад, ки мо дар /opt/appveyor/build-agent/ ҳастем. Пас аз он ман фаҳмидам, ки тағирёбандаи $PWD каме дурӯғ аст. Аз ин сабаб, ман пеш аз оғози таҳлил арзиши онро дастӣ навсозӣ кардам.
Ва он гоҳ ҳама чиз, мисли пештара:
Акнун пораи зеринро баррасӣ кунед:
PULL_REQUEST_ID="pulls/$APPVEYOR_PULL_REQUEST_NUMBER"
MERGE_BASE=`wget -qO -
https://api.github.com/repos/${APPVEYOR_REPO_NAME}/${PULL_REQUEST_ID}
| jq -r ".base.ref"`
Дар он мо фарқияти байни шохаҳоеро мегирем, ки дар онҳо дархости кашидан эълон шудааст. Барои ин ба мо тағирёбандаҳои муҳити зерин лозиманд:
- $APPVEYOR_PULL_REQUEST_NUMBER - рақами дархост;
- $APPVEYOR_REPO_NAME - номи корбар ва анбори лоиҳа.
хулоса
Албатта, мо на ҳама хидматҳои имконпазири ҳамгироии пайвастаро баррасӣ кардем, аммо ҳамаи онҳо хусусиятҳои кори хеле якхела доранд. Ба истиснои кэш, ҳар як хидмат «велосипед»-и худро месозад, аз ин рӯ ҳама чиз ҳамеша гуногун аст.
Дар ҷое, ба монанди Travis-CI, якчанд сатри код ва кэш бенуқсон кор мекунад; дар ҷое, ба монанди AppVeyor, шумо танҳо бояд ҷузвдонро дар танзимот муайян кунед; аммо дар ҷое шумо бояд калидҳои беназир эҷод кунед ва кӯшиш кунед, ки системаро бовар кунонед, ки ба шумо имкони дубора навиштани фрагменти кэшро медиҳад. Аз ин рӯ, агар шумо хоҳед, ки таҳлили дархостро дар хидмати муттаҳидкунии муттасил, ки дар боло баррасӣ нашудааст, насб кунед, аввал боварӣ ҳосил кунед, ки шумо бо кэш мушкилот нахоҳед дошт.
Ба диққататон ташаккур. Агар чизе кор накунад, пас озодона ба мо нависед
Агар шумо хоҳед, ки ин мақоларо бо шунавандагони англисзабон мубодила кунед, лутфан истиноди тарҷумаро истифода баред: Максим Звягинтсев.
Манбаъ: will.com