Conversation
The flagcx wheel ships the ctypes facade as flagcx.api next to libflagcx.so under the package's lib/, so a backend that installs the wheel has no source tree to point FLAGCX_PATH at. Import flagcx.api first and keep plugin.interservice.flagcx_wrapper as the fallback for the source-tree shape, and let FLAGCXLibrary resolve the .so itself (FLAGCX_PATH, the installed package, a build tree, then ldconfig) instead of assembling <FLAGCX_PATH>/build/lib/libflagcx.so by hand. platform.py now selects the flagcx dist backend when the distribution is importable, not only when FLAGCX_PATH is set: that variable is how a source tree announced itself, and a wheel-only install has no such tree.
Comment on lines
+41
to
+48
| buffer_type, | ||
| flagcxComm_t, | ||
| flagcxDataTypeEnum, | ||
| flagcxUniqueId, | ||
| flagcxRedOpTypeEnum, | ||
| ) | ||
| _flagcx_available = True | ||
| except (ImportError, ModuleNotFoundError): |
| ) | ||
| _flagcx_available = True | ||
| except (ImportError, ModuleNotFoundError): | ||
| _flagcx_available = False |
| except (ImportError, ModuleNotFoundError): | ||
| _flagcx_available = False | ||
| FLAGCXLibrary = None | ||
| buffer_type = None |
The import switch covered the runtime code paths only. The unit-test gates still keyed on FLAGCX_PATH, so a wheel-only install skipped the flagcx tests, and the connector example still walked users through building the library by hand. Probe flagcx.api first in the three gates and keep the FLAGCX_PATH check as the source-tree fallback, and turn the example's build-flagcx section into a wheel install. The path append stays where the source-tree shape needs it: it now runs only on the import fallback, so a wheel-only install never touches sys.path. FLAGCX_LIB_PATH goes away. FLAGCXLibrary already resolves the .so from FLAGCX_PATH, the installed package, a build tree and ldconfig, so the variable was an override that nothing but the connector ever read.
tengqm
force-pushed
the
feat/flagcx-package-import
branch
2 times, most recently
from
September 15, 2026 16:14
758c996 to
7cd9668
Compare
The example installed the wheel with a bare `pip install flagcx`, which cannot resolve: flagcx is not on PyPI. It is built per vendor and published to that vendor's own FlagOS index, so the index has to be passed. Leave the vendor as a placeholder rather than naming one. Each index carries only its own builds and not every vendor has published a wheel yet, so an example naming a single vendor invites reading it as the one index every package lives on.
tengqm
force-pushed
the
feat/flagcx-package-import
branch
from
September 15, 2026 16:16
7cd9668 to
626bf8d
Compare
tengqm
marked this pull request as draft
September 15, 2026 16:28
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The flagcx wheel ships the ctypes facade as
flagcx.api, next tolibflagcx.sounder the package's ownlib/:A backend that installs the wheel therefore has no source tree to point
FLAGCX_PATHat, and every place that reached for the FlagCX Python APIassumed one. The package root only re-exports the compiled bindings, so the
names below have to come from
flagcx.apirather thanflagcx.The change is additive:
flagcx.apibecomes the primary import, and theexisting
FLAGCX_PATH-driven resolution stays as the path for a source tree.No import path is renamed and no new environment variable is introduced.
Imports
Three call sites imported
plugin.interservice.flagcx_wrapperafter appendingFLAGCX_PATHtosys.path. Each now triesflagcx.apifirst and falls backto the wrapper. The fallback is what
FLAGCX_PATHstill guards, so a sourcetree keeps working:
vllm_fl/distributed/device_communicators/flagcx.pyvllm_fl/distributed/kv_transfer/flagcx_connector.pyvllm_fl/dispatch/backends/vendor/sunrise/patch.pyThe connector's
ImportErrormessage now names both shapes instead of tellingthe reader to set
FLAGCX_PATH.Library resolution
FLAGCXLibraryalready resolves the.soon its own —FLAGCX_PATH, then theinstalled package's
lib/, then a source build tree, thenldconfig— so thehand-assembled
<FLAGCX_PATH>/build/lib/libflagcx.sopaths are gone. Thecommunicator still threads its
library_pathargument through for callers thatpass one; the connector called the same join with no argument, so it now calls
FLAGCXLibrary()and lets the ladder resolve it. That is also the fix for thewheel-only case, where the old join produced
os.path.join(None, ...).FLAGCX_LIB_PATHis removed. It existed only to override the hand-builtpath above; with the ladder in
FLAGCXLibraryit has no job left, and keepingit would mean carrying a second way to say what
FLAGCX_PATHalready says.Backend selection
platform.pyselected the flagcx dist backend on"FLAGCX_PATH" in os.environ, which is how a source tree announced itself. A wheel-only installhas no such variable, so it fell through to
nccl._flagcx_backend_enabled()now accepts either shape:
FLAGCX_PATHset, or theflagcxdistributionimportable.
Test gates and docs
has_flagcx()inconftest.pyand the two distributed test modules probedonly
<FLAGCX_PATH>/build/lib/libflagcx.so. They now probe the installedpackage first, and accept
lib/libflagcx.soas well asbuild/lib/…so ameson-layout source tree is not reported missing.
examples/disaggregated_serving_xpyd/run_flagcx_connector.mdtaught a sourcebuild; it now installs the wheel and drops the
FLAGCX_PATHexports, keepinga sentence on how to point at a source build instead. The
FLAGCX_PATHrow invllm_fl/dispatch/README.mdis reworded the same way.Verification
End-to-end on metax124 (MACA 3.8.1.3, vLLM 0.24.0
+flagosempty wheel,Qwen3-4B, TP=2): both ranks select
backend=flagcxwith noFLAGCX_*variable set in the environment — the wheel-only shape, which is the case
that previously fell through to
nccl.The flagcx wheel came from the vendor index, not a local build:
flagcx-0.14.0rc2.post2.dev4+maca3.8.1.3.20260914.g08ab373-cp312-cp312-linux_x86_64.whlinstalled by pip with an empty
direct_url.json, resolvingflagcx/lib/libflagcx.sofromsite-packages. The names imported here(
FLAGCXLibrary,buffer_type,flagcxComm_t,flagcxDataTypeEnum,flagcxUniqueId,flagcxRedOpTypeEnum) are all defined in that wheel'sapi.py.Note for anyone reproducing this: the metax path additionally needs the vLLM
0.24.0 compatibility fixes, which are unrelated to this PR and tracked
separately (#377).
This PR was written in part with the assistance of generative AI.