bazel: make GUI the default build#10413
Conversation
The Qt xcb platform plugin currently dlopens libxcb-cursor.so.0 from the host, which means anyone building --//:platform=gui or :openroad-qt has to apt-install libxcb-cursor0 separately -- reported on PR The-OpenROAD-Project#8532 by gadfort, flagged by maliberty as a blocker for making GUI the default. Patch qt-bazel via MODULE.bazel so xcb-util-cursor 0.1.5 is fetched from xorg.freedesktop.org and compiled into a static cc_library, replacing the system_provided cc_import. The patch is ported verbatim from github.com/The-OpenROAD-Project/bazel-orfs, where it has been in use for some time. After this change: readelf -d bazel-bin/openroad | grep -i cursor # nothing Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
The platform string_flag now defaults to "gui" instead of "cli", so `bazelisk build //:openroad` produces the Qt-linked binary without needing `--//:platform=gui` on the command line. Users who specifically want a CLI-only binary can still pass `--//:platform=cli`. Picks up where PR The-OpenROAD-Project#8532 left off; the libxcb-cursor0 blocker reported there is fixed by the preceding commit which builds xcb-util-cursor from source in qt-bazel. bazel/Dockerfile gains the runtime xcb/X11 libs that the Qt-linked binary loads at startup (so `bazel test //src/gui/test:supported` can exec it inside the CI container). libxcb-cursor0 is intentionally not in this list -- it's no longer in DT_NEEDED. User-facing docs (docs/user/Build.md, src/gui/README.md) and the macOS CI workflow drop the now-redundant --//:platform=gui flag. etc/Build.sh already passes the flag explicitly based on --no-gui and is left alone. Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
|
clang-tidy review says "All clean, LGTM! 👍" |
|
@maliberty @hzeller This doesn't get rid of the X dependencies for headless bare bones linux CI distributions, so I think an openroad-qt binary is a better idea. |
There was a problem hiding this comment.
Code Review
This pull request changes the default build platform from "cli" to "gui", updating documentation and build flags accordingly. It also introduces a mechanism to build xcb-util-cursor from source within the qt-bazel dependency to avoid host-level library requirements, adding necessary X11/XCB dependencies to the Dockerfile. Feedback includes a recommendation to verify the integrity of the downloaded source using a SHA256 checksum and to use the runtime version of libxcb1 instead of the development package in the Dockerfile to minimize image size.
| # feed a truncated/HTML response into tar (seen in CI as "xz: | ||
| # File format not recognized"). Stage to a file first for a | ||
| # clearer error if extraction fails. | ||
| "curl -sSfL --retry 5 --retry-all-errors --retry-delay 5 -o xcb-util-cursor-0.1.5.tar.xz https://xorg.freedesktop.org/archive/individual/lib/xcb-util-cursor-0.1.5.tar.xz && tar xJf xcb-util-cursor-0.1.5.tar.xz --strip-components=1 -C interface_libs/xcb xcb-util-cursor-0.1.5/cursor && rm xcb-util-cursor-0.1.5.tar.xz", |
There was a problem hiding this comment.
The curl command downloads an external dependency without verifying its integrity. This poses a security risk and can lead to non-reproducible builds if the remote file changes or is compromised. It is recommended to verify the SHA256 checksum of the downloaded tarball before extraction.
| "curl -sSfL --retry 5 --retry-all-errors --retry-delay 5 -o xcb-util-cursor-0.1.5.tar.xz https://xorg.freedesktop.org/archive/individual/lib/xcb-util-cursor-0.1.5.tar.xz && tar xJf xcb-util-cursor-0.1.5.tar.xz --strip-components=1 -C interface_libs/xcb xcb-util-cursor-0.1.5/cursor && rm xcb-util-cursor-0.1.5.tar.xz", | |
| "curl -sSfL --retry 5 --retry-all-errors --retry-delay 5 -o xcb-util-cursor-0.1.5.tar.xz https://xorg.freedesktop.org/archive/individual/lib/xcb-util-cursor-0.1.5.tar.xz && echo \"28a899f10ada37f1d035605a1ce877a7b5bb03045934197316270cafcca3a987 xcb-util-cursor-0.1.5.tar.xz\" | sha256sum -c && tar xJf xcb-util-cursor-0.1.5.tar.xz --strip-components=1 -C interface_libs/xcb xcb-util-cursor-0.1.5/cursor && rm xcb-util-cursor-0.1.5.tar.xz", |
| libxcb-sync1 \ | ||
| libxcb-xfixes0 \ | ||
| libxcb-xkb1 \ | ||
| libxcb1-dev \ |
|
Building the default with Qt would be a hassle. The typical use-case is headless running on servers somewhere that don' t have a graphics adapter, X-libraries etc. (after all, we don't want to have a human in the loop :) ).
This is what running tests on my machine look like if qt is enabled |
|
Why is occupying a port inconvenient? There is no shortage of them. |
It made me uneasy to open a port, but I didn't have anything to pin it on, so I aske Gemmini: Here are several reasons why relying on a webserver/port for headless CLI operations can be inconvenient:
For a developer looking for a fast, hermetic, and predictable headless build/test environment, avoiding network bindings entirely is usually much simpler and more robust. |
|
1 - we let the OS choose the port by default
2 & 3- OR is the web server so not relevant
4 - possible
5 - a bit of a stretch
In any case to save an image you don't actually need to start the web
server, it just calls directly into the same server code that generates the
image but doesn't actually start the server.
Matt
…On Wed, May 13, 2026 at 8:49 PM Øyvind Harboe ***@***.***> wrote:
*oharboe* left a comment (The-OpenROAD-Project/OpenROAD#10413)
<#10413 (comment)>
Why is occupying a port inconvenient? There is no shortage of them.
It made me uneasy to open a port, but I didn't have anything to pin it on,
so I aske Gemmini:
Here are several reasons why relying on a webserver/port for headless CLI
operations can be inconvenient:
1. *Port Collisions in Concurrent Testing:* When running test suites
in parallel (e.g., using Bazel, which is highly parallelized, or CI/CD
pipelines), tests might try to bind to the same port at the same time.
While dynamic port allocation (binding to port 0) can mitigate this,
it adds extra logic to fetch and communicate the assigned port back to the
client.
2. *Orchestration Overhead (Race Conditions):* You have to handle the
lifecycle of the web server. You must start the server, wait for it to be
fully ready to accept connections before running the client command, and
ensure it cleanly tears down when the job finishes.
3. *Zombie Processes & Resource Leaks:* If a job or test crashes
unexpectedly, the background web server process might be left running. This
can leave the port bound (e.g., TIME_WAIT or a blocked socket) and
cause subsequent runs on the same machine to fail.
4. *Security & Firewall Restrictions:* In locked-down enterprise
environments, CI/CD runners, or containerized environments (like Docker or
strict sandboxes), binding to local network ports might be blocked by
default or require additional network configuration/permissions.
5. *Additional Dependencies:* It requires spinning up a networking
stack and server framework just to perform what should essentially be a
simple local file I/O or standard output operation (like saving an image).
For a developer looking for a fast, hermetic, and predictable headless
build/test environment, avoiding network bindings entirely is usually much
simpler and more robust.
—
Reply to this email directly, view it on GitHub
<#10413 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAFZ5KRERRYY5W77UYXUDI342U63NAVCNFSM6AAAAACY3YPGMGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHM2DINBXGMYDGMZVGI>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Summary
Flips
BUILD.bazel'splatformstring_flagfrombuild_setting_default = "cli"to"gui", sobazelisk build //:openroadnow produces the Qt-linked binarywithout needing
--//:platform=guion the command line. Userswho specifically want a CLI-only binary can still pass
--//:platform=cli.Picks up where #8532 left off.
Stacked on #10412
The
libxcb-cursor0runtime blocker reported by @gadfort on#8532 is fixed by #10412, which builds
xcb-util-cursorfromsource in
qt-bazel. Please merge #10412 first; this PRwill then be a clean single-commit diff against master.
Files changed
BUILD.bazel:build_setting_default = "cli"→"gui".Everything else (
platform_cli/platform_guiconfig_settings, theselect()over//src/guivs//src/gui:gui_qt,:openroad's deps, the standalone:openroad-qttarget) keeps working — the flag mechanism isalready in place, we're only changing the picked-by-default
value.
bazel/Dockerfile: add the runtime xcb/X11/Qt libs that theQt-linked binary loads at startup, so
bazel test //src/gui/test:supportedcan exec the binary inside theBazel-CI container.
libxcb-cursor0is intentionally notin this list — after bazel: build xcb-util-cursor from source in qt-bazel #10412 it is no longer in
DT_NEEDED.This file is the Bazel CI image consumed by Jenkins; the
cmake path (root
Dockerfile+etc/DependencyInstaller.sh)already installs its own xcb deps and is untouched.
.github/workflows/github-actions-macos-bazel.yml: drop thenow-redundant
--//:platform=guiflag from the buildcommand.
docs/user/Build.md: drop the flag from the four bazeliskcommand examples — users should not have to care.
src/gui/README.md: same cleanup for the MockArray example.etc/Build.shalready passes--//:platform=cli/--//:platform=guiexplicitly based on--no-guiand is leftalone (internal script, not user-facing).
Test plan
bazelisk build //:openroad(no flag) produces aQt-linked binary;
ldd bazel-bin/openroadshows theQt/xcb libraries.
bazelisk build --//:platform=cli //:openroad(explicitopt-out) still produces a CLI-only binary with no Qt
deps in
ldd.bazel test //src/gui/test:supportedpasses inside theupdated
bazel/Dockerfileimage(
docker build -f bazel/Dockerfile -t test-bazel-ci .locally to reproduce).
bazelisk run //:openroad -- -guilaunches the GUI on aclean machine without manual
apt-get installof anyxcb package (end-to-end check of bazel: build xcb-util-cursor from source in qt-bazel #10412 + this PR).
bazelisk build //:openroad-qtstill works (separatetarget is untouched).