Scan Your Code
Provision New Project
As an administrator, log in to the Linty web interface and go to Administration > Projects > Management > Create Project to provision your project:
Once your project has been provisioned, update its permissions. To do so, go to Project Setting > Permissions and
add the following role(s) to the linty-scanner
user:
Execute Analysis
Browse (only for Private projects)
Then, you can select which quality profiles (set of rules) to use.
Scan Your Code
To scan your code, run the Linty Scanner that is provided as a Docker image.
Compatibility Matrix with Linty Server
4.0.0 (latest) |
4.0.0 |
3.1.0 |
3.1.0 |
3.0.0 |
3.0.0 |
2.1.0 |
2.1.0 |
2.0.0 |
2.0.0 |
1.2.0 |
1.2.0 |
1.1.0 |
1.1.0 |
Requirements
Linty scans can be triggered from a machine:
Running under either Linux or Windows or Mac
With AMD or Intel or ARM processors
No external connection is necessary to run the Linty Scanner.
Linux
Either install Docker Engine (with containerd and Docker Compose) 23 or greater or Docker Desktop for Linux (latest version). If you choose to install Docker Desktop, make sure to make it start automatically.
Windows
Linty Scanner requires a version of Windows on which WSL 2 (Windows Subsystem for Linux) is enabled. You can watch the following videos to enable WSL on Windows 10 or Windows 11. Note that the last step (Ubuntu installation is not required).
Then, install Docker Desktop for Windows (latest version). Make Docker Desktop starts automatically. Once Docker Desktop is started, make sure to switch to Linux containers
Mac
Install Docker Desktop for Mac (latest version). Make Docker Desktop starts automatically.
Configure Linty Scan
Linty provides two engines:
Linter: Read your code and check rules mainly related to maintainability.
BugFinder: Synthesize your code and check rules mainly related to reliability and security.
Base Configuration
Add a sonar-project.properties
file to the root of your project:
# Key of the project you provisioned in the previous step
sonar.projectKey=my-project-key
# Project name that you want to display on the Linty web interface
sonar.projectName=My Project Name
# Comma-separated list of directories containing your source code (VHDL, Verilog/SystemVerilog and Tcl files).
# Paths are relative to the project base directory.
sonar.sources=./src
Linter Configuration
VHDL and Verilog/SystemVerilog
Set the sonar.hdl.topModule
property. See Top-level Module/Entity.
Verilog/SystemVerilog Only
Linty parsing of Verilog/SystemVerilog project extends slang.
Thus, an slang configuration file is required. Add an slang.conf
file to the root of your project to tell Linty how to
read and elaborate your project.
Browse some project samples to get started:
cv32e40p: Reading from filelist
Ibex RISC-V Core: Manually listing files
And read slang detailed documentation.
BugFinder Configuration
Add a read.ys
file to the root of your project to tell Linty how to read the VHDL/Verilog files of your project in the right order.
You can either read files from a filelist (Verilog/SystemVerilog only):
verific -f -sv my_filelist.flist
or manually list all files:
# Read all the files of your IP in the right order
# For instance, let's say that your IP consists of two VHDL and one Verilog files: ./fly.vhd and ./dream.vhd and ./run.v
verific -vhdl ./fly.vhd
verific -vhdl ./dream.vhd
verific -sv ./run.v
# It's likely that your IP uses third-party libraries.
# In this case, you will need to read interfaces with those third-party libraries.
#
# If you get the following kind of error:
# VERIFIC-ERROR [VHDL-1240] ./xxx.vhd:xxx: 'vcomponents' is not compiled in library 'xpm',
# You need to add the following at the beginning of your read.ys file:
verific -work xpm -vhdl ./third-party-libraries/.../xpm_VCOMP.vhd
# If you get the following kind of error:
# VERIFIC-ERROR [VHDL-1240] ./xxx.vhd:xxx: 'blabla' is not compiled in library 'work',
# You need to add the following at the beginning of your read.ys file:
verific -vhdl -lib ./third-party-libraries/.../blabla.vhd
See Yosys documentation.
Add a hierarchy.ys
file to the root of your project to set the top module/entity (and pass generic/parameter values if necessary):
# Example #1: Let's say that the top module/entity of your IP is 'dream'
hierarchy -top dream
# Example #2: Let's say that the top module/entity of your IP is 'dream'
# and that you want to pass generics/parameters 'ABC' and 'DEF'
hierarchy -top dream -chparam ABC 10 -chparam DEF true
See Yosys documentation.
Run Linty Scan
On Premise (Linux)
Create a directory that will act as a cache for Linty plugins. That way, plugins will not be downloaded from your Linty server each time you run an analysis. Analyses will run faster then.
With Linter Engine Only
Depending on the activated rules, you might have to set the sonar.hdl.topModule
property.
See Top-level Module/Entity.
Then, run the following Docker command:
docker run \
--rm \
--user="$(id -u):$(id -g)" \
--net=host \
-e SONAR_HOST_URL="<linty_platform_url>" \
-e SONAR_TOKEN="<linty_scanner_user_token>" \
-v "<path_to_the_project_to_analyze>:/usr/src" \
-v "<path_to_your_linty_scanner_cache>:/opt/sonar-scanner/.sonar/cache" \
lintyservices/linty-scanner:<version> -Dsonar.bugfinder.enabled=false <additional_scanner_parameters>
# Example: Let's say that you run this Docker command from the root directory of your project.
docker run \
--rm \
--user="$(id -u):$(id -g)" \
--net=host \
-e SONAR_HOST_URL="http(s)://xxx" \
-e SONAR_TOKEN="squ_xxx" \
-v "${PWD}:/usr/src" \
-v "/home/abc/.sonar/cache:/opt/sonar-scanner/.sonar/cache" \
lintyservices/linty-scanner:latest -Dsonar.bugfinder.enabled=false
With both Linter and BugFinder Engines
Run the following Docker command:
docker run \
--rm \
--user="$(id -u):$(id -g)" \
--net=host \
-e SONAR_HOST_URL="<linty_platform_url>" \
-e SONAR_TOKEN="<linty_scanner_user_token>" \
-e TABBY_CAD_LICENSE="<tabby_cad_license_key>" \
-v "<path_to_the_tabby_cad_license_key>:/opt/licenses/yosyshq-license.txt" \
-v "<path_to_the_project_to_analyze>:/usr/src" \
-v "<path_to_your_linty_scanner_cache>:/opt/sonar-scanner/.sonar/cache" \
lintyservices/linty-scanner:<version> <additional_scanner_parameters>
# Example #1
# Let's say that:
# - Your Tabby CAD (Linty Services edition) license is stored as a file at /opt/linty/my-tabby.lic
# - You run this Docker command from the root directory of your project
docker run \
--rm \
--user="$(id -u):$(id -g)" \
--net=host \
-e SONAR_HOST_URL="http(s)://xxx" \
-e SONAR_TOKEN="squ_xxx" \
-v "${PWD}:/usr/src" \
-v "/opt/linty/my-tabby.lic:/opt/licenses/yosyshq-license.txt" \
-v "/home/abc/.sonar/cache:/opt/sonar-scanner/.sonar/cache" \
lintyservices/linty-scanner:latest
# Example #2
# Let's say that:
# - Your Tabby CAD (Linty Services edition) license is stored as an environment variable: $TABBY_CAD_LICENSE
# - You run this Docker command from the root directory of your project
docker run \
--rm \
--user="$(id -u):$(id -g)" \
--net=host \
-e SONAR_HOST_URL="http(s)://xxx" \
-e SONAR_TOKEN="squ_xxx" \
-e TABBY_CAD_LICENSE="$TABBY_CAD_LICENSE" \
-v "${PWD}:/usr/src" \
-v "/home/abc/.sonar/cache:/opt/sonar-scanner/.sonar/cache" \
lintyservices/linty-scanner:latest
Browse project sample.
Advanced usage
# Run in debug mode
docker run ... lintyservices/linty-scanner:latest -Dsonar.verbose=true
# Add timestamp
docker run ... lintyservices/linty-scanner:latest | ts "[%Y-%m-%d %H:%M:%S]"
On Premise (Windows)
The above On Premise (Linux) documentation applies for Windows with the following notes:
Run commands in PowerShell
Remove the following lines from the
docker run
command:--user="$(id -u):$(id -g)" --net=host
Add the following line to the
docker run
command with the MAC address provided with the Linty license. Make sure to use:
separators.--mac-address=XX:XX:XX:XX:XX:XX
Line break in commands is
`
instead of\
Double quote additional properties:
-D"sonar.bugfinder.enabled"=false
Example:
# Let's say that:
# - Your Tabby CAD (Linty Services edition) license is stored as a file at C:\Users\me\linty\my-tabby.lic
# - You run this Docker command from the root directory of your project
# - Your Linty cache directory is C:\Users\me\linty\cache
docker run `
--rm `
--mac-address="XX:XX:XX:XX:XX:XX" `
-e SONAR_HOST_URL="http(s)://xxx" `
-e SONAR_TOKEN="squ_xxx" `
-v "${PWD}:/usr/src" `
-v "C:\Users\me\linty\my-tabby.lic:/opt/licenses/yosyshq-license.txt" `
-v "C:\Users\me\linty\cache:/opt/sonar-scanner/.sonar/cache" `
lintyservices/linty-scanner:latest
On Premise (Mac)
The above On Premise (Linux) documentation applies for Mac with the following notes:
Remove the following line from the
docker run
command:--net=host
Add the following line to the
docker run
command with the MAC address provided with the Linty license:--mac-address=XX:XX:XX:XX:XX:XX
Example:
# Let's say that:
# - Your Tabby CAD (Linty Services edition) license is stored as a file at /home/me/linty/my-tabby.lic
# - You run this Docker command from the root directory of your project
# - Your Linty cache directory is /home/me/linty/cache
docker run \
--rm \
--user="$(id -u):$(id -g)" \
--mac-address="XX:XX:XX:XX:XX:XX" \
-e SONAR_HOST_URL="http(s)://xxx" \
-e SONAR_TOKEN="squ_xxx" \
-v "${PWD}:/usr/src" \
-v "/home/me/linty/my-tabby.lic:/opt/licenses/yosyshq-license.txt" \
-v "/home/me/linty/cache:/opt/sonar-scanner/.sonar/cache" \
lintyservices/linty-scanner:latest
From GitHub
Create the following Actions secrets on your repository:
LINTY_SCANNER_TOKEN
: Token of the ‘linty-scanner’ userTABBY_CAD_LICENSE
: Tabby CAD license key (only necessary if you have a Linty license including BugFinder)
Analyze ‘main’ branch only
Add the following: .github/worfklows/linty.yml
file to your project:
name: Linty
on:
push:
branches:
- main
jobs:
linty:
name: Linty
timeout-minutes: 10
runs-on: ubuntu-latest
steps:
- name: Git Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Cache
uses: actions/cache@v3.3.0
with:
path: ~/.sonar/cache
key: sonar
restore-keys: sonar
- name: Run Linty
run: |
docker run \
--rm \
--user="$(id -u):$(id -g)" \
-e SONAR_HOST_URL="http(s)://xxx" \
-e SONAR_TOKEN="${{ secrets.LINTY_SCANNER_TOKEN }}" \
-e GITHUB_TOKEN="${{ secrets.GITHUB_TOKEN }}" \
-e GITHUB_REPOSITORY_OWNER="$GITHUB_REPOSITORY_OWNER" \
-e GITHUB_REPOSITORY="$GITHUB_REPOSITORY" \
-e TABBY_CAD_LICENSE="$TABBY_CAD_LICENSE" \
-v "${PWD}:/usr/src" \
lintyservices/linty-scanner:latest <additional_scanner_parameters>
env:
TABBY_CAD_LICENSE: ${{secrets.TABBY_CAD_LICENSE}}
- name: Debug
if: always()
uses: actions/upload-artifact@v4
with:
name: debug
path: |
.linty/bugfinder/
Analyze all branches and pull requests
Prerequisites:
Configure GitHub connection
Add the following: .github/worfklows/linty.yml
file to your project:
name: Linty
on:
push:
pull_request:
jobs:
linty:
name: Linty
timeout-minutes: 10
runs-on: ubuntu-latest
env:
SONAR_HOST_URL: http(s)://xxx
steps:
- name: Git Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Cache
uses: actions/cache@v3.3.0
with:
path: ~/.sonar/cache
key: sonar
restore-keys: sonar
- name: Set Linty Analysis parameters
uses: haya14busa/action-cond@v1.1.1
id: linty_analysis_parameters
with:
cond: ${{ github.event.pull_request.number != '' }}
if_true: -Dsonar.pullrequest.key=${{ github.event.pull_request.number }} -Dsonar.pullrequest.base=${{ github.base_ref }} -Dsonar.pullrequest.branch=${{ github.head_ref }}
if_false: -Dsonar.branch.name=${GITHUB_REF#refs/*/}
- name: Run Linty
run: |
docker run \
--rm \
--user="$(id -u):$(id -g)" \
-e SONAR_HOST_URL=${{ env.SONAR_HOST_URL }} \
-e SONAR_TOKEN="${{ secrets.SONARQUBE_SCANNER_FOR_PRIVATE_REPOSITORIES_TOKEN }}" \
-e GITHUB_TOKEN="${{ secrets.GITHUB_TOKEN }}" \
-e GITHUB_REPOSITORY_OWNER="$GITHUB_REPOSITORY_OWNER" \
-e GITHUB_REPOSITORY="$GITHUB_REPOSITORY" \
-e TABBY_CAD_LICENSE="$TABBY_CAD_LICENSE" \
-v "${PWD}:/usr/src" \
lintyservices/linty-scanner:latest \
-Dsonar.qualitygate.wait=true ${{ steps.linty_analysis_parameters.outputs.value }}
env:
TABBY_CAD_LICENSE: ${{ secrets.TABBY_CAD_LICENSE }}
- name: Debug
if: always()
uses: actions/upload-artifact@v4
with:
name: debug
path: |
.linty/bugfinder/
See fully configured project sample:
From GitLab
Create the following variables on your project:
SONAR_HOST_URL
: URL of your Linty platformSONAR_TOKEN
: Token of the ‘linty-scanner’ userTABBY_CAD_LICENSE
: Tabby CAD license key (only necessary if you have a Linty license including BugFinder)CI_TABBYCAD_TOKEN
: Personal token with scope ‘api’ (only necessary if you have a Linty license including BugFinder and running on gitlab.com)
To do so, go to Settings > CI/CD > Variables.
Analyze ‘main’ branch only
Add the following .gitlab-ci.yml
file to your project:
linty:
image:
name: lintyservices/linty-scanner:latest
variables:
GIT_DEPTH: "0"
SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar"
cache:
key: "${CI_JOB_NAME}"
paths:
- .sonar/cache
script:
- sonar-scanner -Dsonar.qualitygate.wait=true
artifacts:
when: always
paths:
- .linty/bugfinder/
only:
- main
Analyze all branches and merge requests
Prerequisites:
Configure GitLab connection
Add the following .gitlab-ci.yml
file to your project:
workflow:
rules:
# Analyze all merge requests and all branches that do not have a related opened merge request
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
when: never
- if:
$CI_COMMIT_BRANCH
linty:
image:
name: lintyservices/linty-scanner:latest
variables:
GIT_DEPTH: "0"
SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar"
cache:
key: "${CI_JOB_NAME}"
paths:
- .sonar/cache
script:
- sonar-scanner -Dsonar.qualitygate.wait=true
artifacts:
when: always
paths:
- .linty/bugfinder/
See fully configured project sample:
Troubleshooting
Linty is unable to analyze file - Caused by: org.sonar.sslr.grammar.GrammarException: The regular expression ‘xxx’ has led to a stack overflow error
If you face the following issue:
ERROR: Error during SonarScanner execution
org.sonar.squidbridge.api.AnalysisException: SonarQube is unable to analyze file: xxx
INFO: Final Memory: 223M/750M
INFO: ------------------------------------------------------------------------
at com.lintyservices.sonar.plugins.verilog.VerilogAnalyzerSensor.analyzeFile(VerilogAnalyzerSensor.java:160)
at com.lintyservices.sonar.plugins.verilog.VerilogAnalyzerSensor.execute(VerilogAnalyzerSensor.java:111)
...
Caused by: org.sonar.sslr.grammar.GrammarException: The regular expression 'xxx' has led to a stack overflow error.
This error is certainly due to an inefficient use of alternations.
See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5050507
at org.sonar.sslr.internal.vm.PatternExpression.execute(PatternExpression.java:48)
at org.sonar.sslr.internal.vm.Machine.execute(Machine.java:162)
Caused by: java.lang.StackOverflowError
at java.base/java.util.regex.Pattern$Branch.match(Unknown Source)
at java.base/java.util.regex.Pattern$GroupHead.match(Unknown Source)
You need to increase the JVM stack size by setting the Xss variable to a higher value:
# Add the following environment variable to the Docker container
# Feel free to increase up to 100m. If you need to go higher, please report the issue to support@linty-service.com
-e SONAR_SCANNER_OPTS=-Xss10m
java.lang.OutOfMemoryError: Java heap space
If you face the following issue:
ERROR: Error during SonarScanner execution
java.lang.OutOfMemoryError: Java heap space
You need to increase the JVM heap space size by setting the Xmx variable to a higher value:
# Add the following environment variable to the Docker container
# Feel free to increase up to 4096m. If you need to go higher, please report the issue to support@linty-service.com
-e SONAR_SCANNER_OPTS=-Xmx2048m
Insufficient privileges
If you face the following issue, make sure that you generated a token with proper User Token type.
org.sonarqube.ws.client.HttpException:
Error 403 on https://xxx&metricKeys=ncloc_language_distribution : {"errors":[{"msg":"Insufficient privileges"}]}
sonar.hdl.topModule property is not set
If you face the following issue, see Top-level Module/Entity.
ERROR: Error during SonarScanner execution
...
Caused by: java.lang.IllegalStateException: [BUGFINDER] sonar.hdl.topModule property is not set
java.nio.file.AccessDeniedException: /opt/sonar-scanner/.sonar/cache/_tmp
If you face the following issue, it means that you haven’t created the cache directory before running the scan
(-v "/<your_cache_directory>>:/opt/sonar-scanner/.sonar/cache"
).
ERROR: Error during SonarScanner execution
java.lang.IllegalStateException: Unable to create temp dir/opt/sonar-scanner/.sonar/cache/_tmp
...
Caused by: java.nio.file.AccessDeniedException: /opt/sonar-scanner/.sonar/cache/_tmp
...
To fix this issue, remove the cache directory that Docker tried to create (but with wrong access rights), manually recreate the cache directory and re-run a scan.
Docker Image Content
Tabby CAD Linty Services Edition with Linty Yosys Plugin
JDK 17