Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions bazel/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -124,18 +124,12 @@ cc_library(
}),
)

# shim old library as it is still referenced in src/sta, implementing the
# old behavior.
# Stub library kept for src/sta:opensta compatibility.
# Tcl setup is now handled by //bazel:tcl_library_init.
cc_library(
name = "runfiles",
srcs = ["InitRunFiles.cpp"],
data = [":tcl_resources_dir"],
visibility = ["//visibility:public"],
deps = [
"@rules_cc//cc/runfiles",
"@tcl_lang//:tcl",
],
alwayslink = True,
)

# small build test to check if "bazel build //src/sta:StaTclInitVar" works
Expand Down
89 changes: 3 additions & 86 deletions bazel/InitRunFiles.cpp
Original file line number Diff line number Diff line change
@@ -1,86 +1,3 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2026, The OpenROAD Authors

// This file to go away as soon as we use the tcl_library_init initialization
// in OpenSTA.

#include <unistd.h> // readlink()

#include <climits>
#include <cstdlib>
#include <filesystem>
#include <iostream>
#include <memory>
#include <optional>
#include <string>
#include <system_error>

#if defined(__APPLE__)
#include <mach-o/dyld.h>
#include <sys/param.h>
#endif

#include "rules_cc/cc/runfiles/runfiles.h"

namespace {
// Avoid adding any dependencies like boost.filesystem
// Returns path to running binary if possible, otherwise nullopt.
static std::optional<std::string> GetProgramLocation()
{
#if defined(_WIN32)
char result[MAX_PATH + 1] = {'\0'};
auto path_len = GetModuleFileNameA(NULL, result, MAX_PATH);
#elif defined(__APPLE__)
char result[MAXPATHLEN + 1] = {'\0'};
uint32_t path_len = MAXPATHLEN;
if (_NSGetExecutablePath(result, &path_len) != 0) {
path_len = readlink(result, result, MAXPATHLEN);
}
#else
char result[PATH_MAX + 1] = {'\0'};
ssize_t path_len = readlink("/proc/self/exe", result, PATH_MAX);
#endif
if (path_len > 0) {
return result;
}
return std::nullopt;
}

std::string GetTclLibraryBaseLocation()
{
using rules_cc::cc::runfiles::Runfiles;
std::string error;
std::unique_ptr<Runfiles> runfiles(Runfiles::Create(
*GetProgramLocation(), BAZEL_CURRENT_REPOSITORY, &error));
if (!runfiles) {
std::cerr << "[Warning] Failed to create bazel runfiles: " << error << "\n";
return "";
}

std::error_code ec;
for (const std::string loc : {"openroad", "opensta", "_main"}) {
const std::string check_loc = loc + "/bazel/tcl_resources_dir";
const std::string path = runfiles->Rlocation(check_loc);
if (!path.empty() && std::filesystem::exists(path, ec)) {
return path;
}
}
return "";
}

class BazelInitializer
{
public:
BazelInitializer()
{
const std::string lib_mount_point = GetTclLibraryBaseLocation();
if (!lib_mount_point.empty()) {
const std::string tcl_path = lib_mount_point + "/library";
setenv("TCL_LIBRARY", tcl_path.c_str(), true);
}
}
};

// Provide via global constructor.
static BazelInitializer bazel_initializer;
} // namespace
// Intentionally empty: tcl_library_init now handles Tcl setup.
// This file is kept because src/sta:opensta still references
// //bazel:runfiles in its srcs.
15 changes: 15 additions & 0 deletions bazel/tcl_library_init.cc
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,21 @@ static std::optional<std::string> TclLibraryMountPoint(Tcl_Interp* interp)
return Tcl_GetStringResult(interp);
#else
using rules_cc::cc::runfiles::Runfiles;

// Clear inherited RUNFILES_* env vars: when OpenROAD is invoked by

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a test that can show that this is necessary ?

// a build system that previously ran another Bazel binary (e.g. a
// Python wrapper), those variables point to the *other* binary's
// runfiles tree. Runfiles::Create() checks env vars first, so it
// would resolve paths in the wrong tree. Unsetting forces it to
// fall back to the exe path, which is always correct.
#ifdef _WIN32
_putenv_s("RUNFILES_DIR", "");
_putenv_s("RUNFILES_MANIFEST_FILE", "");
#else
unsetenv("RUNFILES_DIR");
unsetenv("RUNFILES_MANIFEST_FILE");
Comment thread
oharboe marked this conversation as resolved.
#endif

std::string error;
// Use /proc/self/exe to resolve the real binary path, as argv[0] may
// point into a sandbox where the .runfiles tree does not exist.
Expand Down
Loading