ワンクリックで
install-language-bindings
Make Insight7 installable via pip/luarocks/Julia Pkg with backend .so auto-discovery
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Make Insight7 installable via pip/luarocks/Julia Pkg with backend .so auto-discovery
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Add device information query functions through HAL → ins:: API → language bindings
Add --device all/--timer/--info CLI flags to demos across all languages for competition scoring
Add composite signal operators using existing primitives (no dedicated backend kernels needed)
How to port a cusignal Python/CUDA module to ins::signal C++ using Insight7 primitives and HAL
Profile and optimize binding language (Lua/Julia/Python) demo performance to match or exceed C++ baseline
busted loads _insight.so from ~/.luarocks/lib first, not build/ — must copy .so after rebuild
| name | install-language-bindings |
| description | Make Insight7 installable via pip/luarocks/Julia Pkg with backend .so auto-discovery |
| source | auto-skill |
| extracted_at | 2026-06-05T05:24:58.368Z |
After cmake --build, users must manually set PYTHONPATH, LUA_CPATH/LUA_PATH,
LD_LIBRARY_PATH etc. to use Insight from their code. This is error-prone and
doesn't simulate real user experience in CI.
cmake build → POST_BUILD copies .so to source dirs → pip/luarocks/Pkg installs from source
Each binding's CMakeLists.txt copies the native .so AND the CPU backend .so to the source wrapper directory:
add_custom_command(TARGET insight_python POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:insight_python>
"${CMAKE_SOURCE_DIR}/bindings/python/insight/$<TARGET_FILE_NAME:insight_python>"
COMMENT "Copying Python binding"
)
# Copy ALL backend .so/.dll files to package directory for auto-discovery
# Cross-platform: Linux/macOS use libinsight_*_backend.so, Windows uses insight_*_backend.dll
file(GLOB _INSIGHT_BACKEND_SO_FILES
"${CMAKE_BINARY_DIR}/backends/*/libinsight_*_backend.so"
"${CMAKE_BINARY_DIR}/backends/*/libinsight_*_backend.dylib"
"${CMAKE_BINARY_DIR}/backends/*/insight_*_backend.dll"
)
foreach(_backend_so ${_INSIGHT_BACKEND_SO_FILES})
get_filename_component(_backend_name ${_backend_so} NAME)
add_custom_command(TARGET insight_python POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${_backend_so}"
"${CMAKE_SOURCE_DIR}/bindings/python/insight/${_backend_name}"
COMMENT "Copying ${_backend_name} to Python package"
)
endforeach()
IMPORTANT: Do NOT hardcode libinsight_cpu_backend.so — glob ALL backends.
On Windows there's no lib prefix and the extension is .dll.
Same pattern for Lua (bindings/lua/) and Julia (bindings/julia/).
CRITICAL: Add add_dependencies(insight_xxx insight_cpu_backend) to each binding's
CMakeLists.txt. Without this, the POST_BUILD copy runs before the backend .so is built,
causing Error copying file in CI. The binding target links against insight_core (static),
but that doesn't guarantee the backend .so is built first.
The C++ ins::init() calls dlopen("libinsight_cpu_backend.so") which searches
LD_LIBRARY_PATH. At runtime, modifying LD_LIBRARY_PATH doesn't always work.
Solution: pre-load ALL backend .so files (CPU + GPU: cuda/npu/rocm/...) BEFORE
importing the native module. This matches C++ discover_backends() behavior.
Python (bindings/python/insight/__init__.py):
import ctypes as _ct, os as _os, glob as _gl
_pkg_dir = _os.path.dirname(_os.path.abspath(__file__))
_backend_patterns = [
"libinsight_*_backend.so", # Linux
"libinsight_*_backend.dylib", # macOS
"insight_*_backend.dll", # Windows
]
for _pat in _backend_patterns:
for _so in _gl.glob(_os.path.join(_pkg_dir, _pat)):
try:
_ct.CDLL(_so, mode=_ct.RTLD_GLOBAL)
except OSError:
pass
from ._insight import *
Lua (bindings/lua/insight/init.lua):
Scan for ALL libinsight_*_backend.so in candidate directories:
local function _find_and_load_backends()
local dirs = {}
-- 1. Parent of this script's directory (dev/source layout)
-- 2. package.cpath directories (luarocks lib layout)
-- 3. LD_LIBRARY_PATH directories
local ok_ffi, ffi = pcall(require, "ffi")
if not ok_ffi then return false end
pcall(ffi.cdef, [[
int setenv(const char *name, const char *value, int overwrite);
void *dlopen(const char *filename, int flag);
]])
local seen = {}
for _, dir in ipairs(dirs) do
local pipe = io.popen('ls "' .. dir .. '"/libinsight_*_backend.so 2>/dev/null')
if pipe then
for line in pipe:lines() do
if not seen[line] then
seen[line] = true
local f = io.open(line, "r")
if f then
f:close()
-- setenv LD_LIBRARY_PATH + dlopen(RTLD_GLOBAL)
end
end
end
pipe:close()
end
end
end
Julia (bindings/julia/Insight.jl):
using Libdl
for _d in (_dir, _parent)
if isdir(_d)
for _f in readdir(_d; join=true)
if occursin("libinsight_", _f) && endswith(_f, "_backend.so")
try Libdl.dlopen(_f, Libdl.RTLD_GLOBAL) catch end
end
end
end
end
Why scan ALL backends: Future hardware support (NPU, ROCm, etc.) — the
backend .so naming convention libinsight_<name>_backend.so enables auto-discovery.
[tool.setuptools.packages.find]
where = ["bindings/python"]
include = ["insight*"]
[tool.setuptools.package-data]
"insight" = ["*.so", "*.dll", "*.dylib"]
Install: pip install -e .
Create bindings/lua/insight-1.0-1.rockspec with command build type (NOT cmake type).
Why not cmake type: luarocks' cmake build type calls cmake --install which fails
because codec dependencies (ogg/flac/vorbis) don't have install rules. The command
type gives full control over build and install steps.
Why enable all features: Set INSIGHT_WITH_CUDA=ON, INSIGHT_USE_OPENBLAS=ON, etc.
cmake auto-disables unavailable features. One rockspec works everywhere.
Don't use $(LUA_LIBDIR) — not set on all systems (e.g., system Lua 5.3).
build = {
type = "command",
build_command = [[
cmake -S . -B build.luarocks \
-DCMAKE_BUILD_TYPE=Release \
-DINSIGHT_BUILD_TESTS=OFF \
-DINSIGHT_BUILD_DEMOS=OFF \
-DINSIGHT_BUILD_BINDINGS=ON \
-DINSIGHT_BUILD_PYTHON_BINDING=OFF \
-DINSIGHT_BUILD_JULIA_BINDING=OFF \
-DINSIGHT_BUILD_LUA_BINDING=ON \
-DINSIGHT_WITH_CUDA=ON \
-DINSIGHT_USE_FFTW3=ON \
-DINSIGHT_USE_OPENBLAS=ON \
-DINSIGHT_USE_MATPLOT=ON \
-DLUA_INCLUDE_DIR="$(LUA_INCDIR)" \
&& cmake --build build.luarocks -j 24
]],
install_command = [[
mkdir -p "$(LIBDIR)" "$(LUADIR)/insight" && \
cp build.luarocks/bindings/lua/_insight.so "$(LIBDIR)/" && \
cp build.luarocks/backends/cpu/libinsight_cpu_backend.so "$(LIBDIR)/" && \
cp bindings/lua/insight/init.lua "$(LUADIR)/insight/" && \
cp bindings/lua/insight/*.lua "$(LUADIR)/insight/" 2>/dev/null; true
]],
}
Install commands:
# With sudo
sudo luarocks make bindings/lua/insight-1.0-1.rockspec LUA_DIR=/usr CMAKE_BUILD_DIR=build.luarocks
# Without sudo
luarocks make bindings/lua/insight-1.0-1.rockspec LUA_DIR=/usr CMAKE_BUILD_DIR=build.luarocks --local
# Non-standard OpenBLAS path
OPENBLAS_HOME=/path/to/OpenBLAS luarocks make ... --local
# Faster build (CMAKE_BUILD_PARALLEL_LEVEL is the cmake-native way)
CMAKE_BUILD_PARALLEL_LEVEL=24 luarocks make ... --local
# Use specific Lua version
luarocks --lua-version 5.3 make ... --local
After install, require("insight") works from any directory (no LUA_CPATH/LD_LIBRARY_PATH).
bindings/julia/
├── Project.toml # name, uuid, version, [deps] Libdl
├── src/
│ └── Insight.jl # copy of Insight.jl (cmake does this)
│ └── modules/ # copy of modules/ (cmake does this)
├── Insight.jl # source of truth
└── libinsight_*.so # copied by cmake POST_BUILD
Julia __init__() checks both @__DIR__ and parent dir for .so files.
# Python — pip install then test from /tmp
- run: pip install -e .
- run: cd /tmp && python3 -m pytest $GITHUB_WORKSPACE/tests/cpu/python/
# Lua — source dir .so + LD_LIBRARY_PATH
- run: |
export LUA_CPATH="$GITHUB_WORKSPACE/bindings/lua/?.so;;"
export LD_LIBRARY_PATH=$GITHUB_WORKSPACE/bindings/lua:$LD_LIBRARY_PATH
cd /tmp && busted ... $GITHUB_WORKSPACE/tests/cpu/lua/
# Julia — push LOAD_PATH, no LD_LIBRARY_PATH needed
- run: |
cd /tmp && julia -e "push!(LOAD_PATH,\"$GITHUB_WORKSPACE/bindings/julia\"); ..."
os.setenv doesn't exist in LuaJIT — use ffi.C.setenv insteaddlopen with absolute path ≠ filename search — pre-loading with absolute
path doesn't make dlopen("libfoo.so") find it. Must also set LD_LIBRARY_PATH.Libdl.DL_LOAD_PATH doesn't affect C++ dlopen — must use
Libdl.dlopen with RTLD_GLOBAL to pre-load.os.environ["LD_LIBRARY_PATH"] doesn't affect dlopen after
process startup — must use ctypes.CDLL with RTLD_GLOBAL.Project.toml with UUID for Pkg.develop() to work.
Without UUID, push!(LOAD_PATH, ...) also works but using may fail
if Project.toml exists without proper structure.src/ directory is required for standard package structure.
Insight.jl at root won't be found by using Insight via LOAD_PATH.ins::init() is called during
luaopen__insight (module loading). If it throws, sol2 can't catch it →
std::terminate. Always wrap in try { ins::init(); } catch (...) {}.option() vs set(... FORCE) — option() respects stale cache values.
Use set(VAR ON CACHE BOOL "" FORCE) when the value must be enforced regardless
of previous cmake runs (e.g., INSIGHT_USE_THRUST when CUDA is ON).cmake --build does NOT guarantee Python picks up the new .so — POST_BUILD
copies the .so during build, but the Python package may have been installed from
an earlier pip install that cached the file elsewhere. After modifying a backend
kernel, always run pip install -e . to ensure both the .so and package
metadata are synced. The symptom of a stale .so: fill_() on views works (old
fix), but copy_from_() on views ignores offset (new fix not picked up). Diagnosis:
check /proc/PID/maps for which libinsight_cpu_backend.so is loaded.