Qualcomm environment discovery
Probes the machines and reports what is actually installed.
This is not the first-run step — qualcomm-setup is. The two differ:
qualcomm-setup |
this skill | |
|---|---|---|
| When | Once, first time | Any time after |
| Asks | Topology, board access | Nothing |
| Writes | .qualcomm-env |
Reports drift; does not overwrite |
| For | "Get me started" | "What is on these machines now?" |
Use this to re-verify before a build, after an SDK upgrade, or when a command fails for unclear reasons. Versions go stale silently, and a config that was right last month can be wrong today.
First run
This skill reads .qualcomm-env. Check the marker, not the file — a config
can exist and be half-written:
grep -q '^QC_SETUP_VERSION=' .qualcomm-env 2>/dev/null && echo ready || echo "run setup"
If it says run setup, run the qualcomm-setup skill first. It probes your
machines, asks only what it cannot discover, and writes the config once so no
other skill has to ask again.
If qualcomm-setup is not installed — you copied this skill on its own —
do not stop. Ask the two questions it would have asked, then continue:
- Which host runs the QAIRT SDK? (x86_64 Linux only; a Windows or macOS workstation must drive a remote one, and WSL2 counts as Linux)
- How is the board reached — SSH, ADB, or not available yet?
An empty field is not a blocker by itself. Where this skill needs one it will say which, and why.
Why this is a skill and not a one-liner
The flags, tool names and target triples in this toolchain are version-specific. Guessing the SDK version and then emitting a command for a different one produces errors that look like model problems. Read the version, then choose the command.
The three roles
Ask which hosts fill which role. One machine may fill several; never assume it does.
| Role | Identify by | Must have |
|---|---|---|
BUILD_HOST |
x86_64 Linux only | QAIRT SDK, bin/x86_64-linux-clang/, Yocto/QIRP eSDK |
AIMET_HOST |
x86_64 Linux, often GPU | aimet-onnx or aimet-torch importable |
BOARD |
aarch64 Qualcomm part | libQnnHtp.so, HTP firmware |
A Windows or macOS workstation cannot be the build host. The QAIRT
converters ship only as bin/x86_64-linux-clang; Git Bash and MSYS are not
Linux, though WSL2 is. This is normal and not a problem — the workstation edits
the source and drives a Linux build host over SSH. scripts/probe-env.sh
detects and reports this rather than listing the resulting missing pieces one by
one.
Procedure
1. Load existing config if present
Look for .qualcomm-env in the project root, then ~/.qualcomm-env. If found,
still re-verify reachability and versions — DHCP leases expire and SDKs get
upgraded underneath you. Report any drift from what the file claims rather than
silently using stale values.
2. Establish endpoints
Ask the user for any role not already in config. Do not scan the network
unprompted. Accept an SSH alias (Host qcs-board in ~/.ssh/config) in
preference to a raw IP — aliases survive a DHCP change, IPs do not.
If the user does not know an address, offer, in order:
- An existing
~/.ssh/configentry —grep -A3 -i 'host .*\(board\|qcs\|hexagon\)' ~/.ssh/config adb devicesif the board is USB-attached- An ARP sweep of the local /24, only with explicit approval and only as a last resort
3. Probe
scripts/probe-env.sh collects everything below in one pass. Run it per host:
# Local
bash scripts/probe-env.sh
# Remote — copy and run, do not pipe a script into a remote shell blind
scp scripts/probe-env.sh <host>:/tmp/ && ssh <host> 'bash /tmp/probe-env.sh'
What it reads, and why each matters:
| Fact | How | Why it matters |
|---|---|---|
| QAIRT/QNN version | $QNN_SDK_ROOT path, sdk.yaml |
Flag names differ across majors |
| SDK bin dirs | ls $QNN_SDK_ROOT/bin/ |
Confirms x86_64-linux-clang tools present |
| HTP backend libs | ls $QNN_SDK_ROOT/lib/hexagon-v*/ |
The v68/v73 dir names give the HTP arch |
| eSDK toolchain | environment-setup-*, then ask the compiler -dumpversion |
Gives the compiler prefix and gcc version. Not the -t value - that is a fixed enum in the tool |
| Board arch/kernel | uname -a |
Confirms aarch64 and the vendor kernel |
| SoC identity | /sys/devices/soc0/machine, soc_id |
Which Qualcomm part this is - drives HTP arch and op support |
| Board image type | test -w /usr or ostree admin status |
Immutable image ⇒ no on-device build |
| On-device QNN libs | ls /usr/lib/libQnn*.so |
qnn-net-run needs these at runtime |
| Python / ONNX | python3 -V, pip show onnx onnxruntime |
Converter is a Python tool |
| AIMET | python3 -c "import aimet_onnx" |
Decides if the QAIRT/DLC path is open |
4. Determine the part and its HTP architecture
This is the single most load-bearing fact for op support and for whether a context binary will load. It is determined, never assumed — and it is two separate questions:
(a) What can the SDK build for?
ls -d "$QNN_SDK_ROOT"/lib/hexagon-v*/ 2>/dev/null
(b) What does this part need? Ask the backend. It knows [measured]:
# On the board. Writes only under --targetPath; point it at tmpfs.
LD_LIBRARY_PATH=/usr/lib:$LD_LIBRARY_PATH qnn-platform-validator --backend dsp --coreVersion --targetPath /tmp/pv
Core Version of the backend DSP: Hexagon Architecture V68
That is the authoritative answer — the backend reporting its own capability,
not a lookup. scripts/probe-env.sh runs it automatically when the tool is
present and emits QC_HTP_ARCH_DETECTED.
Corroborate with the Skel the runtime actually loads:
ls /usr/lib/dsp/cdsp/libQnnHtpV*Skel.so # e.g. libQnnHtpV68Skel.so
Fallbacks, if qnn-platform-validator is absent:
cat /sys/devices/soc0/machine /sys/devices/soc0/soc_id # which part this is
then the SoC → arch mapping in the SDK-local docs (qualcomm-sdk-docs), and
the datasheet last, treated as [vendor-claimed].
Note the board's /usr/lib/libQnnHtpV*Stub.so set spans many architectures — it
is the runtime's stub collection, not an answer for your part. Only the
backend report and the loaded Skel identify the one in use.
The answer to (b) must appear in the list from (a). If it does not, the SDK is missing that architecture's support package: a context binary will build on the host and then fail to load on the board, with an error that reads like file corruption rather than a mismatch.
Do not guess the mapping from the part number. Hexagon architecture versions do not track SoC model numbers in any pattern you can extrapolate, and a wrong guess here costs a full build-deploy cycle to discover. Read it from the SDK docs for your version.
Known values, and the only one this repo has evidence for:
| Part | HTP arch | Provenance |
|---|---|---|
| QCS6490 (SoC id 498) | v68 | [measured] — backend --coreVersion reported "Hexagon Architecture V68"; libQnnHtpV68Skel.so loaded |
Add a row when you have verified one — see docs/CONTRIBUTING.md. An unverified
row is worse than an absent one.
5. Write the config
Write .qualcomm-env to the project root, chmod 600. Shell-sourceable:
# .qualcomm-env - generated by qualcomm-env-discovery on <date>
# Re-run the skill to refresh. Values are READ, not assumed.
QC_BOARD_HOST=<ssh alias or user@host>
QC_BOARD_ARCH=aarch64
QC_BOARD_IMMUTABLE=true # no on-device compiler
QC_SOC_MACHINE=<from /sys/devices/soc0/machine>
QC_SOC_ID=<from /sys/devices/soc0/soc_id>
QC_HTP_ARCH=<vNN, determined - see step 4. NOT guessed from the part number>
QC_BUILD_HOST=<ssh alias or user@host>
QC_QNN_SDK_ROOT=/opt/qcom/aistack/qairt/<version>
QC_QAIRT_VERSION=<x.y.z.build>
QC_ESDK_ENV=<path to environment-setup-*>
QC_ESDK_CC_PREFIX=<e.g. aarch64-qcom-linux> # what the eSDK actually provides
QC_ESDK_GCC_VERSION=<e.g. 11.4.0> # from the compiler, not the filename
# -t is a FIXED ENUM in qnn-model-lib-generator (see its --help). It often
# matches no eSDK triple exactly - pick the nearest and verify on the board.
QC_TARGET_TRIPLE=<nearest supported target>
QC_AIMET_HOST=<ssh alias or user@host>
QC_AIMET_FLAVOUR=aimet-onnx # or aimet-torch, or none
Never commit this file. Add it to .gitignore — it names internal hosts.
6. Report
Summarise as a table: role, endpoint, reachable, version, and anything that blocks the next step. Call out explicitly:
- HTP arch dir missing for the target part
- SoC identity unreadable (⇒ target arch unconfirmed; say so rather than assuming)
- QAIRT major ≠ 2.37 (examples in the other skills were verified on 2.37.x)
- Board image immutable (⇒
qualcomm-cross-compileis mandatory, not optional) - No AIMET anywhere (⇒ QAIRT/DLC path unavailable; use the classic flow)
Failure modes worth recognising
| Symptom | Cause |
|---|---|
qnn-onnx-converter: command not found after sourcing |
envsetup.sh sourced with sh, not bash |
| SDK tools vanish after sourcing the eSDK | eSDK environment-setup resets PATH — source the eSDK first, QAIRT envsetup.sh second |
| SSH hangs with no banner | Build host under load or rebooting; not a credentials problem |
| Board reachable, then gone mid-session | Watchdog reset. Check uptime before assuming the network dropped |
Environment setup order
This order is load-bearing and shared by every build-host skill in this repo:
unset LD_LIBRARY_PATH # 1. a set LD_LIBRARY_PATH breaks the eSDK setup
source <eSDK>/environment-setup-<arch> # 2. cross toolchain
source $QNN_SDK_ROOT/bin/envsetup.sh # 3. QAIRT tools last
Getting this wrong is a leading cause of commands that exit 0 and produce
nothing. See references/environment-setup.md.