Remove cppcheck from CI, add to tools/
We don't enforce cppcheck through the CI, although it's there since years. It runs on Ubuntu 18/20, so it's old. For folks, it's likely not discoverable on how to run it locally. Let's make a fresh start. This removes cppcheck from all CI-related code. Instead, it adds it under tools/cppcheck/, including documentation on how to run it locally, bare-matel or in docker. Signed-off-by: Robert Schmidt <robert.schmidt@openairinterface.org>
This commit is contained in:
@@ -219,28 +219,6 @@ pipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage ("cppcheck") {
|
|
||||||
steps {
|
|
||||||
script {
|
|
||||||
triggerSlaveJob ('RAN-cppcheck', 'cppcheck')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
post {
|
|
||||||
always {
|
|
||||||
script {
|
|
||||||
// Using a unique variable name for each test stage to avoid overwriting on a global variable
|
|
||||||
// due to parallel-time concurrency
|
|
||||||
cppcheckStatus = finalizeSlaveJob('RAN-cppcheck')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
failure {
|
|
||||||
script {
|
|
||||||
currentBuild.result = 'FAILURE'
|
|
||||||
failingStages += cppcheckStatus
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stage ("ARM-Cross-Compile") {
|
stage ("ARM-Cross-Compile") {
|
||||||
steps {
|
steps {
|
||||||
script {
|
script {
|
||||||
|
|||||||
@@ -379,90 +379,6 @@ class HTMLManagement():
|
|||||||
self.htmlFile.write(' </tr>\n')
|
self.htmlFile.write(' </tr>\n')
|
||||||
self.htmlFile.close()
|
self.htmlFile.close()
|
||||||
|
|
||||||
def CreateHtmlTestRowCppCheckResults(self, CCR):
|
|
||||||
if (self.htmlFooterCreated or (not self.htmlHeaderCreated)):
|
|
||||||
return
|
|
||||||
self.htmlFile = open('test_results.html', 'a')
|
|
||||||
vId = 0
|
|
||||||
for version in CCR.versions:
|
|
||||||
self.htmlFile.write(' <tr bgcolor = "#F0F0F0" >\n')
|
|
||||||
self.htmlFile.write(' <td colspan="6"><b> Results for cppcheck v ' + version + ' </b></td>\n')
|
|
||||||
self.htmlFile.write(' </tr>\n')
|
|
||||||
self.htmlFile.write(' <tr>\n')
|
|
||||||
self.htmlFile.write(' <td></td>\n')
|
|
||||||
self.htmlFile.write(' <td colspan="2" bgcolor = "lightcyan" ><b> NB ERRORS</b></td>\n')
|
|
||||||
if CCR.nbErrors[vId] == 0:
|
|
||||||
myColor = 'lightgreen'
|
|
||||||
elif CCR.nbErrors[vId] < 20:
|
|
||||||
myColor = 'orange'
|
|
||||||
else:
|
|
||||||
myColor = 'lightcoral'
|
|
||||||
self.htmlFile.write(' <td colspan="3" bgcolor = "' + myColor + '"><b>' + str(CCR.nbErrors[vId]) + '</b></td>\n')
|
|
||||||
self.htmlFile.write(' </tr>\n')
|
|
||||||
self.htmlFile.write(' <tr>\n')
|
|
||||||
self.htmlFile.write(' <td></td>\n')
|
|
||||||
self.htmlFile.write(' <td colspan="2" bgcolor = "lightcyan" ><b> NB WARNINGS</b></td>\n')
|
|
||||||
if CCR.nbWarnings[vId] == 0:
|
|
||||||
myColor = 'lightgreen'
|
|
||||||
elif CCR.nbWarnings[vId] < 20:
|
|
||||||
myColor = 'orange'
|
|
||||||
else:
|
|
||||||
myColor = 'lightcoral'
|
|
||||||
self.htmlFile.write(' <td colspan="3" bgcolor = "' + myColor + '"><b>' + str(CCR.nbWarnings[vId]) + '</b></td>\n')
|
|
||||||
self.htmlFile.write(' </tr>\n')
|
|
||||||
self.htmlFile.write(' <tr bgcolor = "#F0F0F0" >\n')
|
|
||||||
self.htmlFile.write(' <td colspan="6"> ----------------- </td>\n')
|
|
||||||
self.htmlFile.write(' </tr>\n')
|
|
||||||
self.htmlFile.write(' <tr>\n')
|
|
||||||
self.htmlFile.write(' <td></td>\n')
|
|
||||||
self.htmlFile.write(' <td colspan="2" bgcolor = "lightcyan" ><b> Memory leak</b></td>\n')
|
|
||||||
self.htmlFile.write(' <td colspan="3">' + str(CCR.nbMemLeaks[vId]) + '</td>\n')
|
|
||||||
self.htmlFile.write(' </tr>\n')
|
|
||||||
self.htmlFile.write(' <tr>\n')
|
|
||||||
self.htmlFile.write(' <td></td>\n')
|
|
||||||
self.htmlFile.write(' <td colspan="2" bgcolor = "lightcyan" ><b> Possible null pointer deference</b></td>\n')
|
|
||||||
self.htmlFile.write(' <td colspan="3">' + str(CCR.nbNullPtrs[vId]) + '</td>\n')
|
|
||||||
self.htmlFile.write(' </tr>\n')
|
|
||||||
self.htmlFile.write(' <tr>\n')
|
|
||||||
self.htmlFile.write(' <td></td>\n')
|
|
||||||
self.htmlFile.write(' <td colspan="2" bgcolor = "lightcyan" ><b> Uninitialized variable</b></td>\n')
|
|
||||||
self.htmlFile.write(' <td colspan="3">' + str(CCR.nbUninitVars[vId]) + '</td>\n')
|
|
||||||
self.htmlFile.write(' </tr>\n')
|
|
||||||
self.htmlFile.write(' <tr>\n')
|
|
||||||
self.htmlFile.write(' <td></td>\n')
|
|
||||||
self.htmlFile.write(' <td colspan="2" bgcolor = "lightcyan" ><b> Undefined behaviour shifting</b></td>\n')
|
|
||||||
self.htmlFile.write(' <td colspan="3">' + str(CCR.nbTooManyBitsShift[vId]) + '</td>\n')
|
|
||||||
self.htmlFile.write(' </tr>\n')
|
|
||||||
self.htmlFile.write(' <tr>\n')
|
|
||||||
self.htmlFile.write(' <td></td>\n')
|
|
||||||
self.htmlFile.write(' <td colspan="2" bgcolor = "lightcyan" ><b> Signed integer overflow</b></td>\n')
|
|
||||||
self.htmlFile.write(' <td colspan="3">' + str(CCR.nbIntegerOverflow[vId]) + '</td>\n')
|
|
||||||
self.htmlFile.write(' </tr>\n')
|
|
||||||
self.htmlFile.write(' <tr bgcolor = "#F0F0F0" >\n')
|
|
||||||
self.htmlFile.write(' <td colspan="6"> </td>\n')
|
|
||||||
self.htmlFile.write(' </tr>\n')
|
|
||||||
self.htmlFile.write(' <tr>\n')
|
|
||||||
self.htmlFile.write(' <td></td>\n')
|
|
||||||
self.htmlFile.write(' <td colspan="2" bgcolor = "lightcyan" ><b> Printf formatting issues</b></td>\n')
|
|
||||||
self.htmlFile.write(' <td colspan="3">' + str(CCR.nbInvalidPrintf[vId]) + '</td>\n')
|
|
||||||
self.htmlFile.write(' </tr>\n')
|
|
||||||
self.htmlFile.write(' <tr>\n')
|
|
||||||
self.htmlFile.write(' <td></td>\n')
|
|
||||||
self.htmlFile.write(' <td colspan="2" bgcolor = "lightcyan" ><b> Modulo result is predetermined</b></td>\n')
|
|
||||||
self.htmlFile.write(' <td colspan="3">' + str(CCR.nbModuloAlways[vId]) + '</td>\n')
|
|
||||||
self.htmlFile.write(' </tr>\n')
|
|
||||||
self.htmlFile.write(' <tr>\n')
|
|
||||||
self.htmlFile.write(' <td></td>\n')
|
|
||||||
self.htmlFile.write(' <td colspan="2" bgcolor = "lightcyan" ><b> Opposite Condition -> dead code</b></td>\n')
|
|
||||||
self.htmlFile.write(' <td colspan="3">' + str(CCR.nbOppoInnerCondition[vId]) + '</td>\n')
|
|
||||||
self.htmlFile.write(' </tr>\n')
|
|
||||||
self.htmlFile.write(' <tr>\n')
|
|
||||||
self.htmlFile.write(' <td></td>\n')
|
|
||||||
self.htmlFile.write(' <td colspan="2" bgcolor = "lightcyan" ><b> Wrong Scanf Nb Args</b></td>\n')
|
|
||||||
self.htmlFile.write(' <td colspan="3">' + str(CCR.nbWrongScanfArg[vId]) + '</td>\n')
|
|
||||||
self.htmlFile.write(' </tr>\n')
|
|
||||||
vId += 1
|
|
||||||
|
|
||||||
def CreateHtmlTestRowPhySimTestResult(self, testSummary, testResult):
|
def CreateHtmlTestRowPhySimTestResult(self, testSummary, testResult):
|
||||||
if (self.htmlFooterCreated or (not self.htmlHeaderCreated)):
|
if (self.htmlFooterCreated or (not self.htmlHeaderCreated)):
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -27,28 +27,6 @@ import constants as CONST
|
|||||||
import cls_cmd
|
import cls_cmd
|
||||||
from cls_ci_helper import archiveArtifact
|
from cls_ci_helper import archiveArtifact
|
||||||
|
|
||||||
#-----------------------------------------------------------
|
|
||||||
# Class Declaration
|
|
||||||
#-----------------------------------------------------------
|
|
||||||
class CppCheckResults():
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
|
|
||||||
self.variants = ['bionic', 'focal']
|
|
||||||
self.versions = ['','']
|
|
||||||
self.nbErrors = [0,0]
|
|
||||||
self.nbWarnings = [0,0]
|
|
||||||
self.nbNullPtrs = [0,0]
|
|
||||||
self.nbMemLeaks = [0,0]
|
|
||||||
self.nbUninitVars = [0,0]
|
|
||||||
self.nbInvalidPrintf = [0,0]
|
|
||||||
self.nbModuloAlways = [0,0]
|
|
||||||
self.nbTooManyBitsShift = [0,0]
|
|
||||||
self.nbIntegerOverflow = [0,0]
|
|
||||||
self.nbWrongScanfArg = [0,0]
|
|
||||||
self.nbPtrAddNotNull = [0,0]
|
|
||||||
self.nbOppoInnerCondition = [0,0]
|
|
||||||
|
|
||||||
class StaticCodeAnalysis():
|
class StaticCodeAnalysis():
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -60,104 +38,6 @@ class StaticCodeAnalysis():
|
|||||||
self.ranTargetBranch = ''
|
self.ranTargetBranch = ''
|
||||||
self.eNBSourceCodePath = ''
|
self.eNBSourceCodePath = ''
|
||||||
|
|
||||||
def CppCheckAnalysis(self, ctx, node, HTML):
|
|
||||||
if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '':
|
|
||||||
HELP.GenericHelp(CONST.Version)
|
|
||||||
sys.exit('Insufficient Parameter')
|
|
||||||
lSourcePath = self.eNBSourceCodePath
|
|
||||||
|
|
||||||
if not lSourcePath or not node:
|
|
||||||
raise ValueError(f"{lSourcePath=} {node=}")
|
|
||||||
logging.debug('Building on server: ' + node)
|
|
||||||
cmd = cls_cmd.getConnection(node)
|
|
||||||
# on RedHat/CentOS .git extension is mandatory
|
|
||||||
result = re.search(r'([a-zA-Z0-9\:\-\.\/])+\.git', self.ranRepository)
|
|
||||||
if result is not None:
|
|
||||||
full_ran_repo_name = self.ranRepository.replace('git/', 'git')
|
|
||||||
else:
|
|
||||||
full_ran_repo_name = self.ranRepository + '.git'
|
|
||||||
|
|
||||||
cmd.cd(lSourcePath)
|
|
||||||
logDir = f'{lSourcePath}/cmake_targets/log'
|
|
||||||
cmd.run(f'mkdir -p {logDir}')
|
|
||||||
cmd.run('docker image rm oai-cppcheck:bionic oai-cppcheck:focal')
|
|
||||||
cmd.run(f'sed -e "s@xenial@bionic@" {lSourcePath}/ci-scripts/docker/Dockerfile.cppcheck.xenial > {lSourcePath}/ci-scripts/docker/Dockerfile.cppcheck.bionic')
|
|
||||||
cmd.run(f'docker build --tag oai-cppcheck:bionic --file {lSourcePath}/ci-scripts/docker/Dockerfile.cppcheck.bionic . > {logDir}/cppcheck-bionic.txt 2>&1')
|
|
||||||
cmd.run(f'sed -e "s@xenial@focal@" {lSourcePath}/ci-scripts/docker/Dockerfile.cppcheck.xenial > {lSourcePath}/ci-scripts/docker/Dockerfile.cppcheck.focal')
|
|
||||||
cmd.run(f'docker build --tag oai-cppcheck:focal --file {lSourcePath}/ci-scripts/docker/Dockerfile.cppcheck.focal . > {logDir}/cppcheck-focal.txt 2>&1')
|
|
||||||
cmd.run('docker image rm oai-cppcheck:bionic oai-cppcheck:focal')
|
|
||||||
|
|
||||||
bionic = archiveArtifact(cmd, ctx, f'{logDir}/cppcheck-bionic.txt')
|
|
||||||
focal = archiveArtifact(cmd, ctx, f'{logDir}/cppcheck-focal.txt')
|
|
||||||
cmd.close()
|
|
||||||
|
|
||||||
CCR = CppCheckResults()
|
|
||||||
CCR_ref = CppCheckResults()
|
|
||||||
vId = 0
|
|
||||||
for variant in CCR.variants:
|
|
||||||
filename = ctx.baseFilename() + '-cppcheck-'+ variant + '.txt'
|
|
||||||
logging.info(f"will check file '{filename}'")
|
|
||||||
if not os.path.isfile(filename):
|
|
||||||
raise FileNotFoundError(f"{filename} is not a file")
|
|
||||||
else:
|
|
||||||
xmlStart = False
|
|
||||||
with open(filename, 'r') as logfile:
|
|
||||||
for line in logfile:
|
|
||||||
ret = re.search(r'cppcheck version="(?P<version>[0-9\.]+)"', str(line))
|
|
||||||
if ret is not None:
|
|
||||||
CCR.versions[vId] = ret.group('version')
|
|
||||||
if re.search('RUN cat cmake_targets/log/cppcheck.xml', str(line)) is not None:
|
|
||||||
xmlStart = True
|
|
||||||
if xmlStart:
|
|
||||||
if re.search('severity="error"', str(line)) is not None:
|
|
||||||
CCR.nbErrors[vId] += 1
|
|
||||||
if re.search('severity="warning"', str(line)) is not None:
|
|
||||||
CCR.nbWarnings[vId] += 1
|
|
||||||
if re.search('id="memleak"', str(line)) is not None:
|
|
||||||
CCR.nbMemLeaks[vId] += 1
|
|
||||||
if re.search('id="nullPointer"', str(line)) is not None:
|
|
||||||
CCR.nbNullPtrs[vId] += 1
|
|
||||||
if re.search('id="uninitvar"', str(line)) is not None:
|
|
||||||
CCR.nbUninitVars[vId] += 1
|
|
||||||
if re.search('id="invalidPrintfArgType_sint"|id="invalidPrintfArgType_uint"', str(line)) is not None:
|
|
||||||
CCR.nbInvalidPrintf[vId] += 1
|
|
||||||
if re.search('id="moduloAlwaysTrueFalse"', str(line)) is not None:
|
|
||||||
CCR.nbModuloAlways[vId] += 1
|
|
||||||
if re.search('id="shiftTooManyBitsSigned"', str(line)) is not None:
|
|
||||||
CCR.nbTooManyBitsShift[vId] += 1
|
|
||||||
if re.search('id="integerOverflow"', str(line)) is not None:
|
|
||||||
CCR.nbIntegerOverflow[vId] += 1
|
|
||||||
if re.search('id="wrongPrintfScanfArgNum"|id="invalidScanfArgType_int"', str(line)) is not None:
|
|
||||||
CCR.nbWrongScanfArg[vId] += 1
|
|
||||||
if re.search('id="pointerAdditionResultNotNull"', str(line)) is not None:
|
|
||||||
CCR.nbPtrAddNotNull[vId] += 1
|
|
||||||
if re.search('id="oppositeInnerCondition"', str(line)) is not None:
|
|
||||||
CCR.nbOppoInnerCondition[vId] += 1
|
|
||||||
vMsg = ''
|
|
||||||
vMsg += '======== Variant ' + variant + ' - ' + CCR.versions[vId] + ' ========\n'
|
|
||||||
vMsg += ' ' + str(CCR.nbErrors[vId]) + ' errors\n'
|
|
||||||
vMsg += ' ' + str(CCR.nbWarnings[vId]) + ' warnings\n'
|
|
||||||
vMsg += ' -- Details --\n'
|
|
||||||
vMsg += ' Memory leak: ' + str(CCR.nbMemLeaks[vId]) + '\n'
|
|
||||||
vMsg += ' Possible null pointer deference: ' + str(CCR.nbNullPtrs[vId]) + '\n'
|
|
||||||
vMsg += ' Uninitialized variable: ' + str(CCR.nbUninitVars[vId]) + '\n'
|
|
||||||
vMsg += ' Undefined behaviour shifting: ' + str(CCR.nbTooManyBitsShift[vId]) + '\n'
|
|
||||||
vMsg += ' Signed integer overflow: ' + str(CCR.nbIntegerOverflow[vId]) + '\n'
|
|
||||||
vMsg += '\n'
|
|
||||||
vMsg += ' Printf formatting issue: ' + str(CCR.nbInvalidPrintf[vId]) + '\n'
|
|
||||||
vMsg += ' Modulo result is predetermined: ' + str(CCR.nbModuloAlways[vId]) + '\n'
|
|
||||||
vMsg += ' Opposite Condition -> dead code: ' + str(CCR.nbOppoInnerCondition[vId]) + '\n'
|
|
||||||
vMsg += ' Wrong Scanf Nb Args: ' + str(CCR.nbWrongScanfArg[vId]) + '\n'
|
|
||||||
for vLine in vMsg.split('\n'):
|
|
||||||
logging.debug(vLine)
|
|
||||||
vId += 1
|
|
||||||
|
|
||||||
HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK)
|
|
||||||
HTML.CreateHtmlTestRowCppCheckResults(CCR)
|
|
||||||
logging.info('\u001B[1m Static Code Analysis Pass\u001B[0m')
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
def LicenceAndFormattingCheck(self, ctx, node, HTML):
|
def LicenceAndFormattingCheck(self, ctx, node, HTML):
|
||||||
# Workspace is no longer recreated from scratch.
|
# Workspace is no longer recreated from scratch.
|
||||||
# It implies that this method shall be called last within a build pipeline
|
# It implies that this method shall be called last within a build pipeline
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------
|
|
||||||
#
|
|
||||||
# Dockerfile for the Open-Air-Interface BUILD service
|
|
||||||
# Valid for Ubuntu 22.04
|
|
||||||
#
|
|
||||||
#---------------------------------------------------------------------
|
|
||||||
FROM ubuntu:xenial AS oai-cppcheck
|
|
||||||
|
|
||||||
|
|
||||||
ENV DEBIAN_FRONTEND=noninteractive
|
|
||||||
|
|
||||||
RUN apt-get update && \
|
|
||||||
apt-get upgrade --yes && \
|
|
||||||
apt-get install --yes \
|
|
||||||
build-essential \
|
|
||||||
vim \
|
|
||||||
cppcheck
|
|
||||||
|
|
||||||
WORKDIR /oai-ran
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
WORKDIR /oai-ran/common/utils/T
|
|
||||||
RUN make
|
|
||||||
|
|
||||||
WORKDIR /oai-ran
|
|
||||||
RUN mkdir -p cmake_targets/log && \
|
|
||||||
cppcheck --enable=warning --force --xml --xml-version=2 \
|
|
||||||
--inline-suppr \
|
|
||||||
-i openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c \
|
|
||||||
--suppressions-list=ci-scripts/cppcheck_suppressions.list \
|
|
||||||
-I common/utils \
|
|
||||||
-I openair3/NAS/COMMON/UTIL \
|
|
||||||
-j`nproc` . 2> cmake_targets/log/cppcheck.xml 1> cmake_targets/log/cppcheck_build.txt
|
|
||||||
|
|
||||||
RUN grep -E -c 'severity="error' cmake_targets/log/cppcheck.xml
|
|
||||||
|
|
||||||
RUN grep -E -c 'severity="warning' cmake_targets/log/cppcheck.xml
|
|
||||||
|
|
||||||
RUN cat cmake_targets/log/cppcheck.xml
|
|
||||||
@@ -198,9 +198,6 @@ def ExecuteActionWithParam(action, ctx, node):
|
|||||||
elif action == 'LicenceAndFormattingCheck':
|
elif action == 'LicenceAndFormattingCheck':
|
||||||
success = SCA.LicenceAndFormattingCheck(ctx, node, HTML)
|
success = SCA.LicenceAndFormattingCheck(ctx, node, HTML)
|
||||||
|
|
||||||
elif action == 'Cppcheck_Analysis':
|
|
||||||
success = SCA.CppCheckAnalysis(ctx, node, HTML)
|
|
||||||
|
|
||||||
elif action == 'Push_Local_Registry':
|
elif action == 'Push_Local_Registry':
|
||||||
tag_prefix = test.findtext('tag_prefix') or ""
|
tag_prefix = test.findtext('tag_prefix') or ""
|
||||||
success = CONTAINERS.Push_Image_to_Local_Registry(node, HTML, tag_prefix)
|
success = CONTAINERS.Push_Image_to_Local_Registry(node, HTML, tag_prefix)
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
- Deploy_Object
|
- Deploy_Object
|
||||||
- Stop_Object
|
- Stop_Object
|
||||||
- Undeploy_Object
|
- Undeploy_Object
|
||||||
- Cppcheck_Analysis
|
|
||||||
- Deploy_Run_OC_PhySim
|
- Deploy_Run_OC_PhySim
|
||||||
- Build_Deploy_PhySim
|
- Build_Deploy_PhySim
|
||||||
- LicenceAndFormattingCheck
|
- LicenceAndFormattingCheck
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
<!-- SPDX-License-Identifier: LicenseRef-CSSL-1.0 -->
|
|
||||||
|
|
||||||
<testCaseList>
|
|
||||||
<htmlTabRef>build-tab</htmlTabRef>
|
|
||||||
<htmlTabName>CPPCHECK Analysis</htmlTabName>
|
|
||||||
<htmlTabIcon>wrench</htmlTabIcon>
|
|
||||||
|
|
||||||
<testCase>
|
|
||||||
<class>Create_Workspace</class>
|
|
||||||
<desc>Create new Workspace</desc>
|
|
||||||
<node>carabe</node>
|
|
||||||
</testCase>
|
|
||||||
|
|
||||||
<testCase>
|
|
||||||
<class>Cppcheck_Analysis</class>
|
|
||||||
<desc>Static Code Analysis with cppcheck</desc>
|
|
||||||
<node>carabe</node>
|
|
||||||
</testCase>
|
|
||||||
|
|
||||||
</testCaseList>
|
|
||||||
@@ -135,6 +135,7 @@ The other SDRs (AW2S, LimeSDR, ...) have no READMEs.
|
|||||||
- [clang-format.md](./clang-format.md): how to format the code. See also the
|
- [clang-format.md](./clang-format.md): how to format the code. See also the
|
||||||
next entry for an error detection tool.
|
next entry for an error detection tool.
|
||||||
- [formatting](../tools/formatting/README.md) is a clang-format error detection tool
|
- [formatting](../tools/formatting/README.md) is a clang-format error detection tool
|
||||||
|
- [cppcheck](../tools/cppcheck/README.md) for static code analysis
|
||||||
- [sanitizers.md](./dev_tools/sanitizers.md): how to run with ASan/UBSan/MemSAN/TSan
|
- [sanitizers.md](./dev_tools/sanitizers.md): how to run with ASan/UBSan/MemSAN/TSan
|
||||||
- [iwyu](../tools/iwyu/README.md) is a tool to detect `#include` errors
|
- [iwyu](../tools/iwyu/README.md) is a tool to detect `#include` errors
|
||||||
- [docker-dev-env](../tools/docker-dev-env/README.md) is a ubuntu24 docker development environment
|
- [docker-dev-env](../tools/docker-dev-env/README.md) is a ubuntu24 docker development environment
|
||||||
|
|||||||
@@ -96,10 +96,6 @@ information on how the images are built.
|
|||||||
- orion: Cross-compilation from Intel to ARM
|
- orion: Cross-compilation from Intel to ARM
|
||||||
- base image from `Dockerfile.base.ubuntu.cross-arm64`
|
- base image from `Dockerfile.base.ubuntu.cross-arm64`
|
||||||
- build image from `Dockerfile.build.ubuntu.cross-arm64` (no target images)
|
- build image from `Dockerfile.build.ubuntu.cross-arm64` (no target images)
|
||||||
- [RAN-cppcheck](https://jenkins-oai.eurecom.fr/job/RAN-cppcheck/)
|
|
||||||
~BUILD-ONLY ~4G-LTE ~5G-NR ~nrUE
|
|
||||||
- bellatrix
|
|
||||||
- performs static code analysis, currently not actively enforced
|
|
||||||
- [RAN-RHEL8-Cluster-Image-Builder](https://jenkins-oai.eurecom.fr/job/RAN-RHEL8-Cluster-Image-Builder/)
|
- [RAN-RHEL8-Cluster-Image-Builder](https://jenkins-oai.eurecom.fr/job/RAN-RHEL8-Cluster-Image-Builder/)
|
||||||
~BUILD-ONLY ~4G-LTE ~5G-NR ~nrUE
|
~BUILD-ONLY ~4G-LTE ~5G-NR ~nrUE
|
||||||
- cluster (`Asterix-OC-oaicicd-session` resource): RHEL image build using the OpenShift Cluster (using gcc/clang)
|
- cluster (`Asterix-OC-oaicicd-session` resource): RHEL image build using the OpenShift Cluster (using gcc/clang)
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
|
||||||
|
|
||||||
|
# Static code analysis
|
||||||
|
|
||||||
|
How to run static code analysis tool(s).
|
||||||
|
|
||||||
|
[[_TOC_]]
|
||||||
|
|
||||||
|
## cppcheck Overview
|
||||||
|
|
||||||
|
This can run a (dockerized) cppcheck static code analysis. The docker-compose
|
||||||
|
file represents the status as run as in the CI until it's removal (because it
|
||||||
|
was not enforced). It is now here so that people could use it to find bugs (and
|
||||||
|
use the tool more easily).
|
||||||
|
|
||||||
|
## cppcheck Usage
|
||||||
|
|
||||||
|
From the openairinterface5g root, simply run
|
||||||
|
|
||||||
|
./tools/cppcheck/run-cppcheck.sh
|
||||||
|
|
||||||
|
This will run cppcheck with options listed in this file, assuming you have it
|
||||||
|
installed. Alternatively, you can run the CI version as of Ubuntu 20 with
|
||||||
|
|
||||||
|
cd tools/cppcheck && docker compose up --no-log-prefix
|
||||||
|
|
||||||
|
You can upgrade to a newer version by modifying the `FROM` line in the
|
||||||
|
docker-compose file.
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
services:
|
||||||
|
cppcheck:
|
||||||
|
image: cppcheck
|
||||||
|
build:
|
||||||
|
dockerfile_inline: |
|
||||||
|
FROM ubuntu:focal
|
||||||
|
RUN DEBIAN_FRONTEND=noninteractive apt update && apt install -y cppcheck
|
||||||
|
volumes:
|
||||||
|
- ../../:/code/
|
||||||
|
command:
|
||||||
|
bash -c "cd /code/ && ./tools/cppcheck/run-cppcheck.sh"
|
||||||
|
|
||||||
Executable
+11
@@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
cppcheck --enable=warning --force \
|
||||||
|
--inline-suppr \
|
||||||
|
--quiet \
|
||||||
|
-i openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c \
|
||||||
|
--suppressions-list=tools/cppcheck/suppressions.list \
|
||||||
|
-I common/utils \
|
||||||
|
-I openair3/NAS/COMMON/UTIL \
|
||||||
|
-j`nproc` .
|
||||||
Reference in New Issue
Block a user