ืืื ืื PVS-Studio ืึทื ืึทืืืืขืจ ืคึฟืึทืจ C ืืื C ++ ืฉืคึผืจืึทืื ืืืืฃ ืืื ืืงืก ืืื ืืึทืงืึธืก, ืกืืึทืจืืื ื ืคืื ืืืขืจืกืืข 7.04, ืึท ืคึผืจืืืืจื ืึธืคึผืฆืืข ืืื ืืจืืืก ืฆื ืงืึธื ืืจืึธืืืจื ืื ืจืฉืืื ืคืื ืกืคึผืขืกืืคืืขื ืืขืงืขืก. ื ืืฆื ืื ื ืืึทืข ืืึธืืข, ืืืจ ืงืขื ืขื ืงืึทื ืคืืืืขืจ ืื ืึทื ืึทืืืืขืจ ืฆื ืงืึธื ืืจืึธืืืจื ืงืึทืืืฅ ืืื ืฆืืขื ืจืืงืืืขืก. ืืขืจ ืึทืจืืืงื ืืืขื ืืึธืื ืืืจ ืืื ืฆื ืงืึธื ืืจืึธืืืจื ืื ืจืฉืืื ืคืื ืืฉืืื ืืืฉื ืืขืงืขืก ืคืื ืึท GitHub ืคึผืจืืืขืงื ืืื ืึทืืึท ืคืึธืืงืก ืกื (ืงืึธื ืืื ืืึธืืก ืื ืืขืืจืึทืืืึธื) ืกืืกืืขืืขื ืืื Travis CI, Buddy ืืื AppVeyor.
ืืขืงืข ืจืฉืืื ืงืึธื ืืจืึธืืืจืื ื ืืึธืืข
ืืื ืืืขืจืกืืข PVS-Studio 7.04 ืคึฟืึทืจ ืืื ืืงืก ืืื ืืึทืงืึธืก, ืึท ืืึธืืข ืคึฟืึทืจ ืงืึธื ืืจืึธืืืจืื ื ืื ืจืฉืืื ืคืื ืืงืืจ ืืขืงืขืก ืืื ืืจืืืก. ืืึธืก ืึทืจืืขื ืคึฟืึทืจ ืคึผืจืึทืืืฉืขืงืก ืืืขืืขื ืก ืืืืขื ืกืืกืืขื ืึทืืึทืื ืืืจ ืฆื ืืืฉืขื ืขืจืืื ืึท ืืขืงืข
ืืืื, ืื ืืขืงืข ืจืฉืืื ืงืึธื ืืจืึธืืืจืื ื ืืึธืืข ืงืขื ืขื ืืืขืจื ืืขื ืืฆื ืฆืืืึทืืขื ืืื ืื ืืจืึทืกืข ืฉืคึผืืจ ืงืืึธืฅ ืคืื ืงืึทืืคึผืืืืขืจ ืืึธื ืืฉืื (pvs-studio-analyzer trace). ืฆื ืืึธื ืืึธืก, ืืืจ ืืืื ืขืจืฉืืขืจ ืืืจืืคืืจื ืึท ืืึทื ืฅ ืืืืขื ืคืื ืื ืคึผืจืืืขืงื ืืื ืฉืคึผืืจ ืขืก ืึทืืื ืึทื ืื ืึทื ืึทืืืืขืจ ืงืึทืืขืงืฅ ืืึทื ืฅ ืืื ืคึฟืึธืจืืึทืฆืืข ืืืขืื ืื ืืึทืืืื ื ืคึผืึทืจืึทืืขืืขืจืก ืคืื ืึทืืข ืืขืงืขืก ืืืึธืก ืืขื ืขื ืึธืคึผืืขืฉืืขืื.
ืึธืืขืจ, ืื ืึธืคึผืฆืืข ืืื ืึท ืืึทืืืืืืง ืฉืืขืจืื ื - ืืืจ ืืืขื ืืึทืจืคึฟื ืฆื ืืืจืืคืืจื ืึท ืืึทื ืฅ ืฉืคึผืืจ ืคืื ืื ืืื ืฆืข ืคึผืจืืืขืงื ืืขืืขืจ ืืึธื ืืืจ ืืืืคื ืขืก, ืืืึธืก ืืื ืืื ืงืึทื ืืจืึทืืืงืฅ ืื ืืขืืึทื ืง ืคืื ืืขืฉืืืื ื ืงืึธื ืืจืึธืืืจื ืึท ืืืขืจืืขืื. ืึธืืขืจ, ืืืื ืืืจ ืงืึทืฉ ืื ืฉืคึผืืจ ืจืขืืืืืึทื ืืื, ืื ืกืึทืืกืึทืงืืืึทื ื ืจืึทื ื ืคืื ืื ืึทื ืึทืืืืขืจ ืงืขื ืืืื ืืขืจืขื ืืืงื ืืืื ืื ืืขืคึผืขื ืืขื ืกื ืกืืจืืงืืืจ ืคืื ืื ืืงืืจ ืืขืงืขืก ืขื ืืขืจืื ืืขื ื ืึธื ืื ืฉืคึผืืจ (ืืืฉื, ืึท ื ืืึทืข # ืื ืงืืืืข ืืื ืืืกืืฃ ืฆื ืืืื ืขืจ ืคืื ืื ืืงืืจ ืืขืงืขืก).
ืืขืจืืืขืจ, ืืืจ ืืึธื ื ืืฉื ืจืขืงืึธืืขื ืืืจื ื ืืฆื ืื ืืขืงืข ืจืฉืืื ืืฉืขืง ืืึธืืข ืืื ืื ืฉืคึผืืจ ืงืืึธืฅ ืฆื ืงืึธื ืืจืึธืืืจื ืงืึทืืืฅ ืึธืืขืจ ืฆืืขื ืจืืงืืืขืก. ืืืื ืืืจ ืงืขื ืขื ืืึทืื ืึท ืื ืงืจืึทืืขื ืืึทื ืืืืขื ืืืขื ืงืึธื ืืจืึธืืืจื ืึท ืืืขืจืืขืื, ืืึทืืจืึทืืื ื ืืฆื ืืขื ืืึธืืข
ืื ืจืฉืืื ืคืื ืืงืืจ ืืขืงืขืก ืคึฟืึทืจ ืึทื ืึทืืืกืืก ืืื ืืขืจืืืขืืืขื ืืื ืึท ืืขืงืกื ืืขืงืข ืืื ืืืจืืืขืืื ืืขื ืฆื ืื ืึทื ืึทืืืืขืจ ืืื ืืขื ืคึผืึทืจืึทืืขืืขืจ -S:
pvs-studio-analyzer analyze ... -f build/compile_commands.json -S check-list.txt
ืืขืจ ืืขืงืข ืกืคึผืขืฆืืคืืฆืืจื ืงืึธืจืขืื ืึธืืขืจ ืึทืืกืึธืืื ืคึผืึทืืก ืฆื ืืขืงืขืก, ืืื ืืขืืขืจ ื ืืึท ืืขืงืข ืืืื ืืืื ืืืืฃ ืึท ื ืืึทืข ืฉืืจื. ืขืก ืืื ืคึผืึทืกืืง ืฆื ืกืคึผืขืฆืืคืืฆืืจื ื ืื ืืืืื ืืขืงืข ื ืขืืขื ืคึฟืึทืจ ืึทื ืึทืืืกืืก, ืึธืืขืจ ืืืื ืคืึทืจืฉืืื ืืขืงืกื. ืืขืจ ืึทื ืึทืืืืขืจ ืืืขื ืืขื ืึทื ืืึธืก ืืื ื ืืฉื ืึท ืืขืงืข ืืื ืืืื ืึธืจืืจื ืื ืฉืืจื. ืืึธืก ืงืขื ืืืื ื ืืฆืืง ืคึฟืึทืจ ืงืึทืืขื ืืื ื ืืืื ืืขืงืขืก ืืขื ืขื ืกืคึผืขืกืืคืืขื ืืึทื ืืืึทืื. ืึธืืขืจ, ืึธืคื ืึท ืจืฉืืื ืคืื ืืขืงืขืก ืืืขื ืืืื ืืืฉืขื ืขืจืืืืึทื ืืขืฉืึทืก ืึทื ืึทืืืกืืก ืืื ืกื, ืืืฉื, ืืึธืก ืงืขื ืืืื ืืขืงืขืก ืคึฟืื ืึท ืืืขืจืืขืื ืึธืืขืจ ืฆืืขื ืืขืื.
ืืืฆื, ื ืืฆื ืืขื ืืึธืืข, ืืืจ ืงืขื ืขื ืืขืฉืืืื ื ืงืึธื ืืจืึธืืืจื ื ืืึท ืงืึธื ืืืืืขืจ ืขืก ืงืืื ืืื ืื ืืืืคึผื ืึทื ืืืืืงืืื ื ืฆืืืืึทื. ืฆื ืขื ืฉืืจ ืึทื ืื ืกืงืึทื ืื ื ืกืืกืืขื ืจืืกืคึผืึทื ืื ืฆื ืึทื ืึทืืืืขืจ ืืืึธืจื ืื ืื, ืื ื ืืฆื ืคึผืืึธื-ืงืึทื ืืืขืจืืขืจ ืคืึธื ืฆืืืขืืขืื --ืึธื ืืืืึทืื-ืืืึธืจื ืื ืื:
plog-converter ... --indicate-warnings ... -o /path/to/report.tasks ...
ืืื ืืขื ืคืึธื, ืืขืจ ืงืึทื ืืืขืจืืขืจ ืืืขื ืฆืืจืืงืงืืืขื ืึท ื ืื-ื ืื ืงืึธื ืืืื ืขืก ืืขื ืขื ืืืึธืจื ืื ืื ืืื ืื ืึทื ืึทืืืืขืจ ืืึทืจืืื. ื ืืฆื ืื ืฆืืจืืงืงืขืจ ืงืึธื, ืืืจ ืงืขื ืขื ืคืึทืจืฉืคึผืึทืจื ืึท ืคึผืจืืงืึธืืืื ืคืึทืจืืฉืขืคึผืขื, ืืืขื ืึธืืขืจ ืฆืืขื ืืขืื, ืืื ืื ืืืฉืขื ืขืจืืืืึทื ืึทื ืึทืืืืขืจ ืืึทืจืืื ืงืขื ืขื ืืืื ืืขืืืืื, ืฉืขืจื ืึธืืขืจ ืืขืฉืืงื ืืืจื E- ืืจืืื.
ื ืืืืฅ. ืืืขื ืืืจ ืขืจืฉืืขืจ ืึธื ืืืืื ืึทื ืึทืืืืืื ื ืึท ืจืฉืืื ืคืื ืืขืงืขืก, ืื ืืื ืฆืข ืคึผืจืืืขืงื ืืืขื ืืืื ืึทื ืึทืืืืื, ืืืืึทื ืืขืจ ืึทื ืึทืืืืขืจ ืืึทืจืฃ ืืืฉืขื ืขืจืืื ืึท ืืขืงืข ืคืื โโืืืคึผืขื ืืึทื ืกืื ืคืื ืื ืคึผืจืืืขืงื ืืงืืจ ืืขืงืขืก ืืืืฃ ืื ืืขืืขืจ ืืขืงืขืก. ืืึธืก ืืื ืึท ืฉืืจืื ืคืื ืึทื ืึทืืืืืื ื C ืืื C ++ ืืขืงืขืก. ืืื ืืขืจ ืฆืืงืื ืคึฟื, ืื ืืขืคึผืขื ืืขื ืกื ืืขืงืข ืงืขื ืขื ืืืื ืงืึทืฉื ืืื ืขืก ืืืขื ืืืื ืืขืจืืืึทื ืืืงื ืืืืืึธืืึทืืืฉ ืืืจื ืื ืึทื ืึทืืืืขืจ. ืื ืืืึทืืข ืคืื โโืงืึธื ืืจืึธืืืจืื ื ืงืึทืืืฅ ืืืขื ื ืืฆื ืืขืงืข ืจืฉืืื ืงืึธื ืืจืึธืืืจืื ื ืืึธืืข ืืืืขืจ ื ืืฆื ืื ืงืจืึทืืขื ืืึทื ืึทื ืึทืืืกืืก ืืึธืืข ืืื ืึทื ืืืจ ื ืึธืจ ืืึทืจืคึฟื ืฆื ืงืึทืฉ ืื ืืขืงืข ืืื ื ืืฉื ืื ืืืืคืขืฅ ืืขืงืขืก.
ืึทืืืขืืืื ืข ืคึผืจืื ืกืึทืคึผืึทืื ืคืื ืฆืืขื ืืขืื ืึทื ืึทืืืกืืก
ืึทื ืึทืืืืืื ื ืื ืืื ืฆืข ืคึผืจืืืขืงื ื ืขืื ืึท ืคึผืืึทืฅ ืคืื ืฆืืื, ืึทืืื ืขืก ืืื ืืื ืขื ืฆื ืงืึธื ืืจืึธืืืจื ืืืืื ืึท ืืืืขืจ ืืืื ืคืื ืขืก. ืื ืคึผืจืึธืืืขื ืืื ืึทื ืืืจ ืืึทืจืคึฟื ืฆื ืืึทืืื ืืขืจ ืื ื ืืึทืข ืืขืงืขืก ืคืื ืื ืจืขืฉื ืคืื ืื ืคึผืจืืืขืงื ืืขืงืขืก.
ืืื ืก ืงืืง ืืืึท ืึท ืืืึทืฉืคึผืื ืคืื ืึท ืืืขืจืืขืื ืืืื ืืื ืฆืืืื ืฆืืืืืื:
ืืื ืก ืืืึทืืืฉืึทื ืึทื ืืืขืจืืขืื A1 ืึผืืื ืึท ืืึทื ืฅ ืืจืืืก ืกืืืข ืคืื โโืงืึธื ืืืึธืก ืืื ืฉืืื ืืขืกืืขื. ื ืืืกื ืคืจืืขืจ ืืึธืื ืืืจ ืืขืืืื ืึท ืฆืืืืึทื ืคืื ืื ืงืึทืืื A1 ืืื ืืขืืืื ืขืืืขืืข ืืขืงืขืก.
ืืืจ, ืคืื ืงืืจืก, ืืืืขืจืงื ืึทื ื ืึธื A1 ืฆืืืื ืืขืจ ืงืึทืืืฅ ืคืืจืืขืงืืืขื, ืึธืืขืจ ืืึธืก ืืขื ืขื ืืืื ืืขืจืืืฉืขืจื ืคืื ืื ืืขืจืข ืฆืืืืืื, ืืืืึทื ืืืจ ืืึธื ื ืื ืืืขืจืืขืื ืฆื ืืึทืืขืืึธืก. ืืื ืืืฆื ืืื ืืขืงืืืขื ืื ืฆืืื ืืืขื hotfix ืืจืืื. ืืขืจืคึฟืึทืจ ืืึธื ืืื ืืึทืืืืื ืึท ืคึผืื ืืขืื ืคึฟืึทืจ ืื ืฆืื ืืืคืืืกื B3 ะธ A3.
ืคืื ืงืืจืก, ืขืก ืืืึธืื ืืืื ืืขืืืขื ืฆื ืงืึธื ืืจืึธืืืจื ืื ืืื ืฆืข ืจืขืืืืืึทื ืคืื ืืืืขืจ ืฆืื ืืืคืืืกื, ืึธืืขืจ ืืึธืก ืืืึธืื ืืืื ืฆื ืฆืืื-ืงืึทื ืกืืืื ื ืืื ืืืืืขืจืขืื, ืืืืึทื ืืืืื ืึท ืืืกื ืืขืงืขืก ืืขื ืขื ืืขืืืื. ืืขืจืืืขืจ, ืขืก ืืื ืืขืจ ืขืคืขืงืืืื ืฆื ืึทื ืึทืืืื ืืืืื ืื ืืขืืืื.
ืฆื ืืึธื ืืึธืก, ืืืจ ืืึทืงืืืขื ืื ืืืืืง ืฆืืืืฉื ืื ืฆืืืืืื, ืืืึทืขื ืืืง ืืื ืื ืงืึธืคึผ ืคืื ืื ืฆืืืืึทื ืคืื ืืืึธืก ืืืจ ืืืืื ืฆื ืฆืื ืืืคืืืกื ืืื ืืขื:
git diff --name-only HEAD origin/$MERGE_BASE > .pvs-pr.list
$MERGE_BASE ืืืจ ืืืขืื ืงืืงื ืืื ืขืก ืืื ืืขืืึทื ืฉืคึผืขืืขืจ. ืืขืจ ืคืึทืงื ืืื ืึทื ื ืื ืืขืืขืจ ืกื ืกืขืจืืืืก ืืื ืื ื ืืืืืง ืืื ืคึฟืึธืจืืึทืฆืืข ืืืขืื ืื ืืึทืืึทืืืืก ืคึฟืึทืจ ืืขืจืืืฉืื ื, ืึทืืื ืืขืืขืจ ืืึธื ืืืจ ืืึธืื ืฆื ืืขืคึฟืื ืขื ื ืืึทืข ืืืขืื ืฆื ืืึทืงืืืขื ืื ืืึทืื. ืืึธืก ืืืขื ืืืื ืืืกืงืจืืืื ืืื ืืขืืึทื ืืื ืื ืืื ืืขืืขืจ ืคืื ืื ืืืกืงืจืืืื ืืืขื ืืึทืืื ืื ืืก.
ืึทืืื, ืืืจ ืืึธืื ืื ืืืืืง ืฆืืืืฉื ืื ืฆืืืืืื, ืึธืืขืจ ืืึทื ืฅ, ืึท ืจืฉืืื ืคืื ืืขืงืข ื ืขืืขื ืืืึธืก ืืขื ืขื ืืขืืืื. ืืืฆื ืืืจ ืืึทืจืคึฟื ืฆื ืืขืื ืื ืืขืงืข .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 (--ืึธื ืืืืึทืื-ืืืึธืจื ืื ืื). ืืืื ืขืก ืืื ืืืึท ืืื ืืกืืขืจ ืืืื ืึทื ืึทืืืืขืจ ืืืืจืขื ืื ื, ืื ื ืืฆื ืฆืืจืืงืงืืืขื ืงืึธื ืคึผืืึธื-ืงืึทื ืืืขืจืืขืจ ืืืขื ืืืืฉื ืฆื 2, ืืืึธืก ืืื ืงืขืจ ืืืขื ืืืืืืืื ืื ืกื ืืื ืกื ืืืขืื ืืขื ืืืึทืืืึทื ืคืื ืคึผืึธืืขื ืฆืืขื ืขืจืจืึธืจืก ืืื ืื ืฆืืขื ืืขืื ืืขืงืขืก.
ืืจืึทืืืืก ืกื
ืื ืงืึทื ืคืืืืขืจืืืฉืึทื ืืื ืืขืืืื ืืื ืึท ืืขืงืข .travis.yml. ืคึฟืึทืจ ืงืึทื ืืืื ืืึทื ืก, ืืื ืจืขืงืึธืืขื ืืืจื ืืืจ ืฆื ืฉืืขืื ืึทืืฅ ืืื ืึท ืืึทืืื ืืขืจ ืืึทืฉ ืฉืจืืคื ืืื ืคืึทื ืืงืฉืึทื ื ืืืึธืก ืืืขื ืืืื ืืขืจืืคึฟื ืคึฟืื ืืขืจ ืืขืงืข .travis.yml (bash script_name.sh function_name).
ืืืจ ืืืขืื ืืืืื ืื ื ืืืืืง ืงืึธื ืฆื ืื ืฉืจืืคื ืืื ืืึทืฉ, ืืขื ืืืขื ืืืจ ืืืขืื ืืึทืงืืืขื ืืขืจ ืคืึทื ืืงืฉืึทื ืึทืืืื. ืืื ืึธืคึผืืืืืื ื ืื ืกืืึทืืืจื ืืืืืจ ืฉืจืืืื ืื ืคืืืืขื ืืข:
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
ืืื ืืื ืื ืืึทืฉ ืฉืจืืคื:
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. Travis CI ืืขืจืงืืขืจื ืืื ืื ืืืคึผืขื ืืึทื ืืื:
- $TRAVIS_PULL_REQUEST ืกืืึธืจื ืื ืฆืืขื ืืขืื ื ืืืขืจ ืึธืืขืจ ืคืึทืืฉ, ืืืื ืืึธืก ืืื ืึท ืจืขืืืืขืจ ืฆืืืืึทื;
- $TRAVIS_REPO_SLUG ืกืืึธืจื ืื ื ืึธืืขื ืคืื ืื ืคึผืจืืืขืงื ืจืืคึผืึทืืึทืืึธืจื.
ืืขืจ ืึทืืืขืจืืืึทื ืคึฟืึทืจ ืืขื ืคึฟืื ืงืฆืืข:
Travis CI ืจืืกืคึผืึทื ืื ืฆื ืฆืืจืืงืงืืืขื ืงืึธืืื, ืึทืืื ืื ืืืึทืืืึทื ืคืื ืืืึธืจื ืื ืื ืืืขื ืืึธืื ืื ืืื ืกื ืฆื ืฆืืืื ืื ืืืขืจืืขืื ืืื ืืื ืขืจืจืึธืจืก.
ืืืฆื ืืึธืื ืืื ืื ื ืขืืขื ืึท ื ืขืขื ืืขืจ ืงืืง ืืื ืื ืฉืืจื ืคืื ืงืึธื:
git diff --name-only origin/HEAD > .pvs-pr.list
ืืขืจ ืคืึทืงื ืืื ืึทื Travis CI ืืืืืึธืืึทืืืฉ ืืขืจืืืฉืื ืฆืืืืืื ืืฉืขืช ืึทื ืึทืืืืืื ื ืึท ืฆืืขื ืืขืื:
ืืขืจืืืขืจ ืืืจ ืึทื ืึทืืืื A4ืืื ื ืืฉื ื3->ืึท3. ืืืืึทื ืคืื ืืขื ืฉืืจืื, ืืืจ ืืึทืจืคึฟื ืฆื ืจืขืืขื ืขื ืื ืืืืืง ืืื A3, ืืืึธืก ืืื ืืืืงื ืืขืจ ืฉืคึผืืฅ ืคืื ืื ืฆืืืืึทื ืคืื ืึธื ืืืื.
ืขืก ืืื ืืืื ืืืืืืืง ืืขืืึทื ืืื ืงืก - ืงืึทืืฉืื ื ืื ืืืคึผืขื ืืึทื ืกืื ืคืื ืืขืืขืจ ืืขืงืขืก ืืืืฃ ืงืึทืืคึผืืืื ืืืืขืจืืขืฆืื ื ืื ืืฅ (*.c, *.cc, *.cpp, ืืื"ื ื). ืื ืึทื ืึทืืืืขืจ ืงืึทืืงืืึทืืืืฅ ืื ืืืคึผืขื ืืึทื ืกืื ืืืขื ืขืก ืืื ืขืจืฉืืขืจ ืืึธื ืืฉื ืืื ืื ืืึธืืข ืคืื โโืงืึธื ืืจืึธืืืจืื ื ืึท ืจืฉืืื ืคืื ืืขืงืขืก ืืื ืืขืืึธืื ืกืึทืืืขืก ืืื ืืื ืื .PVS-Studio Directory. Travis CI ืึทืืึทืื ืืืจ ืฆื ืงืึทืฉ ืคืึธืืืขืจืก, ืึทืืื ืืืจ ืืืขืื ืจืึทืืขืืืขื ืื ืืืขืืืืืึทืืขืจ ืืึทืื .PVS-Studio/:
cache:
directories:
- .PVS-Studio/
ืืขื ืงืึธื ืืึทืจืฃ ืฆื ืืืื ืืืกืืฃ ืฆื ืืขืจ ืืขืงืข .travis.yml. ืืขืจ ืืืขืืืืืึทืืขืจ ืกืืึธืจื ืคืึทืจืฉืืื ืืึทืื ืืขืืืืื ื ืึธื ืึทื ืึทืืืกืืก, ืืืึธืก ืืืขื ืืืืืืืืง ืคืึทืจืืืืขืจื ืกืึทืืกืึทืงืืืึทื ื ืจืึทื ื ืคืื ืืขืงืข ืจืฉืืื ืึทื ืึทืืืกืืก ืึธืืขืจ ืื ืงืจืึทืืขื ืืึทื ืึทื ืึทืืืกืืก. ืืืื ืืึธืก ืืื ื ืืฉื ืืขืืื, ืืขืจ ืึทื ืึทืืืืขืจ ืืืขื ืึทืงืฉืื ืึทื ืึทืืืื ืึทืืข ืืขืงืขืก ืืขืืขืจ ืืึธื.
ืืึทืื
ืืื Travis CI,
ืขืจืฉืืขืจ ืคืื ืึทืืข, ืืืจ ืืึทืจืคึฟื ืฆื ืืืืื ืึท ื ืืึทืข ืงืึทืืฃ ืฆื ืื ืคึฟืึทืจืืึทืืืื ื ืฉืืจื:
ืืึธืืืจ ืึธื ืืืืึทืื ืืขื ืงืึทืืคึผืืืืขืจ ืืืึธืก ืืื ืืขื ืืฆื ืฆื ืืืืขื ืืขื ืคึผืจืืืขืงื. ืืึทืืขืจืงื ืื ืืึธืงืงืขืจ ืงืึทื ืืืื ืขืจ ืืืึธืก ืืื ืืื ืกืืึทืืืจื ืืื ืืขื ืงืึทืืฃ. ืคึฟืึทืจ ืืืึทืฉืคึผืื, ืขืก ืืื ืึท ืกืคึผืขืฆืืขื ืงืึทื ืืืื ืขืจ ืคึฟืึทืจ 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 ืืึธืืืจ ื ืืฆื ืื GitHub API:
https://api.github.com/repos/${USERNAME}/${REPO}/pulls/${PULL_REQUEST_ID}
ืืืจ ืืขืืืืื ื ืื ืคืืืืขื ืืข ืืืขืจืืึทืืึทืื ืึทื Buddy ืืื:
- $BUDDY_EXECUTION_PULL_REQEUST_NO - ืฆืืขื ืืขืื ื ืืืขืจ;
- $BUDDY_REPO_SLUG - ืึท ืงืึธืืืื ืึทืฆืืข ืคืื โโื ืืืขื ืืื ืจืืคึผืึทืืึทืืึธืจื (ืืืฉื ืืึทืงืก / ืคึผืจืืืืจื).
ืืืฆื ืืึธืื ืืื ืื ืจืึทืืขืืืขื ืื ืขื ืืขืจืื ืืขื ื ืืฆื ืื ืงื ืขืคึผื ืืื ืื ืืื ืืขืื ืึทื ืึทืืืกืืก ืคืื ืื ืฆืืขื ืืขืื:
ื ืื ืขื ืืขื Travis CI, ืืืจ ืืึธื ื ืื ืืึทืจืคึฟื ืฆื ืกืคึผืขืฆืืคืืฆืืจื .pvs-studio ืคึฟืึทืจ ืงืึทืืฉืื ื, ืืื ื ืืึทืื ืืืืืึธืืึทืืืฉ ืงืึทืฉ ืึทืืข ืืขืงืขืก ืคึฟืึทืจ ืกืึทืืกืึทืงืืืึทื ื ืืึธื ืืฉืื. ืืขืจืืืขืจ, ืื ืืขืฆืืข ืืึทื ืืื ืฆื ืจืึทืืขืืืขื ืื ืืึธืืื ืืื ืคึผืึทืจืึธื ืคึฟืึทืจ PVS-Studio ืืื ืืึทืื. ื ืึธื ืฉืคึผืึธืจื ืื ืขื ืืขืจืื ืืขื, ืืืจ ืืืขืื ืืืื ืฆืืจืืง ืฆื ืจืขืจื - ืืื ืืข. ืืืจ ืืึทืจืคึฟื ืฆื ืืึทื ืืืืฃ ืฆื ืืึทืฉืืขืืืงื ืืืขืจืืึทืืึทืื ืืื ืึทืืื ื ืึท ืืึธืืื ืืื ืฉืืืกื ืคึฟืึทืจ PVS-Studio:
ื ืึธื ืืขื, ืื ืืืืกืืขื ืคืื ืึท ื ืืึท ืฆืืขื ืืขืื ืึธืืขืจ ืืืขืจืืขืื ืืืขื ืฆืื ืื ืื ืจืขืฆืขื ืืืข. ืืืื ืึท ืงืึทืืื ืึผืืื ืขืจืจืึธืจืก, ืืึทืื ืืืขื ืึธื ืืืืึทืื ืืขื ืืืืฃ ืื ืฆืืขื ืืขืื ืืืึทื.
AppVeyor
ืืึทืฉืืขืืืงื ืึทืคึผืืืืืึธืจ ืืื ืขื ืืขื ืฆื ืืึทืื, ืืืืึทื ืึทืืฅ ืืึทืคึผืึทื ื ืืื ืื ืืืขื ืฆืืืื ื ืืื ืขืก ืืื ื ืื ืืึทืจืคึฟื ืฆื ืืืืื ืึท *.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, ืืืจ ื ืึธืจ ืืึทืจืคึฟื ืฆื ืกืคึผืขืฆืืคืืฆืืจื ืื ืืขืงืข ืืื ืื ืกืขืืืื ืืก; ืึธืืขืจ ืขืจืืขืฅ ืืืจ ืืึทืจืคึฟื ืฆื ืฉืึทืคึฟื ืืื ืฆืืง ืฉืืืกืืขื ืืื ืคึผืจืืืืจื ืฆื ืืืืขืจืฆืืืื ืื ืกืืกืืขื ืฆื ืืขืื ืืืจ ืื ืืขืืขืื ืืืื ืฆื ืึธืืืืขืจืจืืื ืื ืงืึทืฉื ืคืจืึทืืืขื ื. ืืขืจืืืขืจ, ืืืื ืืืจ ืืืืื ืฆื ืฉืืขืื ืึทื ืึทื ืึทืืืกืืก ืคืื ืฆืืขื ืจืืงืืืขืก ืืืืฃ ืึท ืงืขืกืืืืขืจืืืง ืื ืืึทืืจืืืฉืึทื ืืื ืกื ืืืึธืก ืืื ื ืืฉื ืืืกืงืึทืกื ืืืืื, ืขืจืฉืืขืจ ืืึทืื ืืืืขืจ ืึทื ืืืจ ืืืขื ื ืืฉื ืืึธืื ืคึผืจืึธืืืขืืก ืืื ืงืึทืืฉืื ื.
ืืื ืง ืืืจ ืคึฟืึทืจ ืืืื ืืคืืขืจืงืืึทืืงืืึทื. ืืืื ืขืคึผืขืก ืืื ื ืืฉื ืึทืจืืขืื, ืคืืื ืคืจืื ืฆื ืฉืจืืึทืื ืฆื ืืื ืื ืืื
ืืืื ืืืจ ืืืืื ืฆื ืืืืื ืืขื ืึทืจืืืงื ืืื ืึทื ืขื ืืืืฉ-ืืขืจืขืื ืืืืขื, ืืืืข ื ืืฆื ืื ืืืืขืจืืขืฆืื ื ืืื ืง: ืืึทืงืกืื ืืืืืึทืืื ืืกืขืื.
ืืงืืจ: www.habr.com