Skip to content

Linux: OpenCV never bundled into .mcpb — opencvLibDir() paths cannot match what extract.ts writes #33

Description

@takusaito-ctrl

Status: unverified — needs confirmation from someone with a Linux SDK zip.
This is a code-reading deduction, not an observed failure. Sony ships per-platform SDK zips and I only had CrSDK_v2.02.00_20260610a_Win64.zip, so I could not run the Linux path. Filing it because the Windows equivalent was confirmed and shipped a silently-broken bundle.

Context

While fixing the Windows OpenCV bundling bug (#31, PR #32), the same class of defect appears to exist on Linux. On Windows this was confirmed: pack:mcp printed OpenCV libs not found — assuming static/linked, omitted all four DLLs, and produced a .mcpb whose server died instantly with STATUS_DLL_NOT_FOUND — surfacing to users as "the MCP server won't auto-start."

The Windows cause was a mismatch between the path extract.ts writes and the path opencvLibDir() reads. macOS is fine. Linux looks like it has the same mismatch.

The mismatch

opencvLibDir() in cli/src/lib/mcp-build.ts requires one of these to exist as a directory:

[['Linux', 'Release', 'x64', 'lib'], ['Linux', 'Release', 'aarch64', 'lib']]

But extract.ts writes Linux OpenCV libs with:

opencv: [{
  fromRel: 'Linux',
  toRel: 'Linux',
  match: (f) => f.startsWith('libopencv_') && f.includes('.so'),
}]

and copyGlob is flatreaddirSync(srcDir) with no recursion, copying matched files directly into dstDir:

function copyGlob(srcDir, match, dstDir) {
  if (!existsSync(srcDir)) throw new Error(`missing expected SDK directory: ${srcDir}`);
  mkdirSync(dstDir, { recursive: true });
  let n = 0;
  for (const f of readdirSync(srcDir)) {
    if (match(f)) { copyFileSync(join(srcDir, f), join(dstDir, f)); n++; }
  }
  return n;
}

So the only directory the extractor can ever create here is shared/opencv/Linux/, with libs sitting flat inside it. Nothing in the extract path ever creates Linux/Release/x64/lib or Linux/Release/aarch64/lib, so existsSync() fails on both candidates, opencvLibDir() returns null, and pack:mcp takes the silent "assuming static/linked" branch.

Compare: why macOS is fine

macOS works because fromRel === toRel === 'Darwin/Release/macos/bin', and opencvLibDir()'s darwin candidate is that same string. They match by construction. Windows broke precisely because the two strings disagreed. Linux disagrees in the same way.

Two possible outcomes, both bad

Depending on how the Linux SDK zip is laid out under external/opencv/Linux/:

  1. Libs flat in Linux/ — they extract fine to shared/opencv/Linux/, but opencvLibDir() never finds them → OpenCV silently omitted from the .mcpb, same end result as the Windows bug.
  2. Libs nested (e.g. Linux/Release/x64/lib/) — as the Windows zip nests them (Windows/x86_64/Release/bin) — then the flat copyGlob sees only subdirectory names, match() rejects all of them, and it copies zero files while returning success. OpenCV is then missing from shared/ entirely, not just from the bundle.

Case 2 would also mean crsdk build on Linux relies on OpenCV coming from somewhere else (system package?), which would mask the extraction doing nothing.

What would confirm it

On Linux, after crsdk install --zip <linux-sdk.zip>:

find shared/opencv -name 'libopencv_*' | head
ls shared/opencv/Linux/
  • If libs are flat in shared/opencv/Linux/ → case 1, opencvLibDir() needs ['Linux'] as a candidate.
  • If that directory is empty → case 2, copyGlob/fromRel needs the real nested path.
  • Then crsdk pack:mcp and check whether it prints OpenCV libs not found — assuming static/linked.

Also worth checking whether the built CameraWebApp on Linux actually has libopencv_* in its NEEDED entries (readelf -d CameraWebApp | grep NEEDED), which determines whether a missing lib is fatal at spawn as it is on Windows.

I did not blind-fix this, since the correct path depends on a layout I can't observe.

Related: the silent fallback

Underlying both this and #31: pack:mcp treats "OpenCV directory not found" as assuming static/linked and proceeds. That converts a missing-file bug into a broken artifact that only fails on the end user's machine, with no output from the dying process. Making that a hard failure (at least where OpenCV is known to be dynamically linked) would have caught the Windows bug at pack time instead of at connect time.

Happy to follow up with a PR once someone can confirm the actual Linux layout.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions