Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
47 changes: 5 additions & 42 deletions bazel/BUILD
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
load("@bazel_skylib//rules:build_test.bzl", "build_test")
load("@bazel_skylib//rules:common_settings.bzl", "bool_flag")
load("@rules_cc//cc:cc_binary.bzl", "cc_binary")
load("@rules_cc//cc:cc_library.bzl", "cc_library")
load("@rules_pkg//pkg:mappings.bzl", "pkg_files", "strip_prefix")
load("@rules_pkg//pkg:zip.bzl", "pkg_zip")
load("@rules_python//python:pip.bzl", "compile_pip_requirements")
load("@rules_python//python/entry_points:py_console_script_binary.bzl", "py_console_script_binary")
load("//bazel:extract_zip.bzl", "extract_zip")

package(features = ["layering_check"])

Expand Down Expand Up @@ -68,12 +66,6 @@ pkg_zip(
],
)

# ... however, Tcl8 still needs access to a directory, so unpack in that case.
extract_zip(
name = "tcl_resources_dir",
src = ":tcl_resources_zip",
)

genrule(
name = "tcl_resources_zip_data_h",
srcs = [":tcl_resources_zip"],
Expand All @@ -87,44 +79,15 @@ cc_binary(
srcs = ["embed.cc"],
)

# As long as we support tcl8 (using runfiles) we need this flag.
bool_flag(
name = "use_zipfs",
build_setting_default = True, # True as we use tcl9 with zipfs feature
)

config_setting(
name = "zipfs_config",
flag_values = {":use_zipfs": "true"},
)

# Library initialization is a bit different for tcl8 and tcl9.
# In tcl9, we can use a zipped version of the needed include files, but
# for tcl8, we have to use the unpacked zip file and point our runfiles
# to it.
cc_library(
name = "tcl_library_init",
srcs = ["tcl_library_init.cc"] +
select({
":zipfs_config": ["tcl_resources_zip_data.h"],
"//conditions:default": [],
}),
srcs = [
"tcl_library_init.cc",
"tcl_resources_zip_data.h",
],
hdrs = ["tcl_library_init.h"],
copts = select({
":zipfs_config": [],
"//conditions:default": ["-DUSE_TCL_RUNFILE_INIT"],
}),
data = select({
":zipfs_config": [],
"//conditions:default": [":tcl_resources_dir"],
}),
visibility = ["//visibility:public"],
deps = [
"@tcl_lang//:tcl",
] + select({
":zipfs_config": [],
"//conditions:default": ["@rules_cc//cc/runfiles"],
}),
deps = ["@tcl_lang//:tcl"],
)

# small build test to check if "bazel build //src/sta:StaTclInitVar" works
Expand Down
37 changes: 0 additions & 37 deletions bazel/extract_zip.bzl

This file was deleted.

110 changes: 3 additions & 107 deletions bazel/tcl_library_init.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,130 +3,26 @@

#include "bazel/tcl_library_init.h"

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

#include "tcl.h"

// In tcl 9, we can use the //zipfs:/ virtual file system (unless
// we specifically disabled with the --//bazel:use_zipfs=False flag)
#if TCL_MAJOR_VERSION >= 9 && !defined(USE_TCL_RUNFILE_INIT)
#define USE_ZIPFS_INIT 1
#else
#define USE_ZIPFS_INIT 0
#endif

#if USE_ZIPFS_INIT
#include "bazel/tcl_resources_zip_data.h"
#else

#include <limits.h>
#include <unistd.h>

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

#include <memory>

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

namespace in_bazel {

#if !USE_ZIPFS_INIT
// Avoid adding any dependencies like boost.filesystem
// Returns path to running binary if possible.
static 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 Tcl_GetNameOfExecutable();
}
#endif

static std::optional<std::string> TclLibraryMountPoint(Tcl_Interp* interp)
{
// In tcl9, we can use //zipfs:/ otherwise we need to point to the
// directory where the tcl library files are extracted.
#if USE_ZIPFS_INIT
// In tcl9, we can mount an encoded zipfile as //zipfs:/ and read
// libraries from there.
if (TclZipfs_MountBuffer(
interp, kTclResourceZip, sizeof(kTclResourceZip), "/app", 0)
!= TCL_OK) {
std::cerr << "[Warning] Failed to mount Tcl zipfs.\n";
return std::nullopt;
}
return Tcl_GetStringResult(interp);
#else
using rules_cc::cc::runfiles::Runfiles;

auto find_tcl_resources
= [](const Runfiles* runfiles) -> std::optional<std::string> {
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 std::nullopt;
};

// First try with the inherited RUNFILES_* env vars. When OpenROAD
// is the direct Bazel target (or invoked from an sh_test whose
// runfiles tree also contains OpenROAD's data), those env vars
// already point at the correct tree.
std::string error;
std::unique_ptr<Runfiles> runfiles(
Runfiles::Create(GetProgramLocation(), BAZEL_CURRENT_REPOSITORY, &error));
if (runfiles) {
if (auto path = find_tcl_resources(runfiles.get())) {
return path;
}
}

// Fallback: when OpenROAD is invoked by a build system that
// previously ran another Bazel binary (e.g. a Python wrapper), the
// inherited RUNFILES_* variables point to the *other* binary's
// runfiles tree and won't contain OpenROAD's tcl_resources_dir.
// Unset them and retry so Runfiles::Create falls back to the
// exe_path derived from /proc/self/exe.
unsetenv("RUNFILES_DIR");
unsetenv("RUNFILES_MANIFEST_FILE");
unsetenv("RUNFILES_MANIFEST_ONLY");

runfiles.reset(
Runfiles::Create(GetProgramLocation(), BAZEL_CURRENT_REPOSITORY, &error));
if (!runfiles) {
std::cerr << "[Warning] Failed to create bazel runfiles: " << error << "\n";
return std::nullopt;
}

if (auto path = find_tcl_resources(runfiles.get())) {
return path;
}
return std::nullopt;
#endif
}

int SetupTclEnvironment(Tcl_Interp* interp)
Expand Down
Loading