§ 4.01
← blog·2026.05.05·2 min

Embedding VEX Header Files Inside an HDA

VEX `#include` cannot resolve `opdef:` URIs, so headers cannot be referenced directly from inside an HDA. Here is the workaround that does work: extract the embedded section on install and add the directory to HOUDINI_VEX_PATH.

Embedding VEX Header Files Inside an HDA

A long-standing question on the SideFX forum (originally posted in 2016, still unanswered as of 2026): can you ship a .h VEX header inside an HDA so the asset stays self-contained?

I tested this on Houdini 21.0.700. Short version: the obvious approach does not work, but there is a clean workaround.

What does not work

You cannot #include an embedded section directly. Every form of the opdef: URI fails inside a wrangle:

#include "opdef:.?myheader.h"
#include "opdef:/Sop/myasset::1.0?myheader.h"

VEX reports Unable to include "opdef:...". The failure is not in the VEX preprocessor — hou.readFile("opdef:...") returns Invalid file name as well, which means the opdef: scheme is simply not registered with the file resolver that VEX #include goes through. It works for parameters that take a filename (textures, geometry caches), but not for VEX includes. SideFX has not bridged this gap in any version up to H21.

What does work

Embed the header as a section, then extract it to a real path on install and prepend that path to HOUDINI_VEX_PATH:

# OnInstall / OnLoaded event handler
import hou, os, tempfile

defn = kwargs["type"].definition()
out_dir = os.path.join(hou.getenv("HOUDINI_USER_PREF_DIR"),
                       "embedded_vex", defn.nodeType().name())
os.makedirs(out_dir, exist_ok=True)

for name, sec in defn.sections().items():
    if name.endswith(".h"):
        with open(os.path.join(out_dir, name), "w") as f:
            f.write(sec.contents())

old = hou.getenv("HOUDINI_VEX_PATH") or "&"
if out_dir not in old:
    hou.hscript(f"setenv HOUDINI_VEX_PATH = {out_dir}{os.pathsep}{old}")
    hou.hscript("varchange")

After this, any wrangle — inside or outside the asset — can do:

#include "myheader.h"

and it compiles. I confirmed end-to-end: a function defined in the embedded header was resolved at cook time and produced the expected output.

Caveats

  • HOUDINI_VEX_PATH is process-global. Two assets that both embed utils.h will collide — namespace your filenames (myasset_utils.h).
  • Use a versioned subdirectory (embedded_vex/<asset>/<version>/) so an updated asset does not clobber a header an older instance still depends on.
  • OnInstall runs once per machine; OnLoaded runs every time the hip is opened. The handler above is idempotent, so OnLoaded is the safer choice.
  • The same pattern works for OpenCL kernels and any other resource that wants a real file path rather than an inline string.

It is not the answer the original poster wanted — direct opdef: inclusion would be cleaner — but it gives you a single-file .hda that carries its own VEX library, which is what the question was actually asking for.