Skip to content
Open
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
13 changes: 12 additions & 1 deletion scripts/dev/upstream_merge/automation_conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,16 @@
"email_to": "",
"username": "",
"build_args":"",
"ssh_connection":""
"ssh_connection":"",

"kernel_build": {
"kernel_src_dir": "",
"arch": "",
"temp_modules_dir": "",
"target_branch": "",
"toolchain_prefix": "",
"ssh_target": "",
"build_host_ip": "",
"work_item_id": ""
}
}
157 changes: 157 additions & 0 deletions scripts/dev/upstream_merge/copy_toolchain_from_server.py
Comment thread
jatinjb444 marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import os

# --------------------
# Nirvana mount base (assumed present)
# --------------------
NIRVANA_SDK_BASE = (
"/mnt/nirvana/perforceExports/build/exports/"
"ni/rtos/rtos_toolchain/official/export"
)


def _get_latest_major_version():
if not os.path.isdir(NIRVANA_SDK_BASE):
return None

versions = []
for d in os.listdir(NIRVANA_SDK_BASE):
path = os.path.join(NIRVANA_SDK_BASE, d)
if os.path.isdir(path):
try:
versions.append((tuple(map(int, d.split("."))), d))
except ValueError:
continue

return sorted(versions)[-1][1] if versions else None


def _get_latest_build_version(version_path):
builds = []
for d in os.listdir(version_path):
path = os.path.join(version_path, d)
if os.path.isdir(path):
try:
builds.append((
list(map(int, d.replace("d", ".").split("."))), d))
except ValueError:
continue

return sorted(builds)[-1][1] if builds else None


def copy_toolchain_from_nirvana(build_root):
"""
Copy latest x64 NILRT toolchain from mounted Nirvana to:
<build_root>/toolchain/NILinuxRT-x64
"""

latest_version = _get_latest_major_version()
if not latest_version:
return 1, "No Nirvana toolchain versions found"

version_path = os.path.join(NIRVANA_SDK_BASE, latest_version)
latest_build = _get_latest_build_version(version_path)
if not latest_build:
return 1, f"No builds found under Nirvana version {latest_version}"

sdk_src = os.path.join(
version_path,
latest_build,
"toolchain",
"sdk",
"NILinuxRT-x64"
)

if not os.path.isdir(sdk_src):
return 1, f"x64 SDK not found at: {sdk_src}"

toolchain_root = os.path.join(build_root, "toolchain")
toolchain_dst = os.path.join(toolchain_root, "NILinuxRT-x64")

# Idempotent: skip if already present
if os.path.isdir(toolchain_dst):
return 0, f"Toolchain already present at {toolchain_dst}"

os.makedirs(toolchain_root, exist_ok=True)

ret = os.system(f"cp -r {sdk_src} {toolchain_root}/")
if ret != 0:
return 1, "Failed to copy toolchain from Nirvana"

return 0, (
f"Toolchain copied from Nirvana\n"
f"Version: {latest_version}/{latest_build}\n"
f"Location: {toolchain_dst}"
)


def prepare_toolchain_environment(build_root):
"""
Run the NILinuxRT SDK installer (non-interactive) if needed,
extracting into the local build toolchain directory,
then source the environment.
"""

toolchain_path = os.path.join(build_root, "toolchain", "NILinuxRT-x64")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can't this variable be replaced with toolchain_dst that you have defined in copy_toolchain_from_nirvana() function by making it global or replace toolchain_dst with this variable? Why do we need to create different variables with same values?

if not os.path.isdir(toolchain_path):
return 1, f"Toolchain directory not found: {toolchain_path}"

env_script = None
for root, dirs, files in os.walk(toolchain_path):
for f in files:
if f.startswith("environment-setup"):
env_script = os.path.join(root, f)
break
if env_script:
break

# If SDK is not yet extracted, run installer
if not env_script:
installers = [
f for f in os.listdir(toolchain_path)
if f.endswith(".sh")
]

if not installers:
return 1, "No SDK installer (.sh) found in toolchain directory"

installer = os.path.join(toolchain_path, installers[0])
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

When you are always extracting installers value at 0th index, why do you need to even make installers as a list? Can't it just be a string instead?

os.chmod(installer, 0o755)

# IMPORTANT: force extraction into toolchain_path
ret = os.system(
f'bash "{installer}" -y -d "{toolchain_path}"'
)
if ret != 0:
return 1, "Failed to run SDK installer"

# Look again for environment-setup after extraction
for root, dirs, files in os.walk(toolchain_path):
for f in files:
if f.startswith("environment-setup"):
env_script = os.path.join(root, f)
break
if env_script:
break

if not env_script:
return 1, "installer ran , env-setup script not found"

# Source environment into Python process
cmd = f'bash -c "source {env_script} >/dev/null && env"'
with os.popen(cmd) as proc:
for line in proc:
key, _, value = line.strip().partition("=")
os.environ[key] = value

# CROSS_COMPILE is expected to be exported by the SDK environment-setup script

if "CROSS_COMPILE" not in os.environ:
Comment thread
jatinjb444 marked this conversation as resolved.
return 1, (
"CROSS_COMPILE not set after sourcing toolchain environment. "
"Ensure the SDK environment-setup script exports it correctly."
)

print(f"[TOOLCHAIN] CROSS_COMPILE set to: {os.environ['CROSS_COMPILE']}")

return 0, "Toolchain environment ready"
33 changes: 30 additions & 3 deletions scripts/dev/upstream_merge/json_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@ class JsonConfig:
"""Handles loading and validating the automation_conf.json
configuration file."""

def __init__(self, automation_conf_path, work_item_id):
with open(automation_conf_path, "r", encoding="utf-8") as file:
def __init__(self, config_path, work_item_id):
Comment thread
jatinjb444 marked this conversation as resolved.
with open(config_path, "r", encoding="utf-8") as file:
config = json.load(file)
self.work_item_id = work_item_id
self.nilrt_branch = config.get("nilrt_branch")
self.meta_nilrt_branch = config.get("meta_nilrt_branch")
self.conf_file_path = os.getcwd() + f"/{config.get('conf_file_path')}"
Expand All @@ -27,3 +26,31 @@ def __init__(self, automation_conf_path, work_item_id):
self.log_level = config.get("log_level")
self.build_args = config.get("build_args", "")
self.ssh_connection = config.get("ssh_connection")
# Kernel build configuration (optional section)
kernel_config = config.get("kernel_build", {})
# Expand environment variables in paths
Comment thread
jatinjb444 marked this conversation as resolved.
self.kernel_src_dir = os.path.abspath(
kernel_config.get("kernel_src_dir"))
self.arch = kernel_config.get("arch")
self.temp_modules_dir = kernel_config.get(
"temp_modules_dir")
self.toolchain_prefix = kernel_config.get(
"toolchain_prefix")
self.merge_workdir = kernel_config.get(
"merge_workdir")
self.target_branch = kernel_config.get("target_branch")
self.nilrt_root = kernel_config.get("nilrt_root")
self.required_packages = kernel_config.get("required_packages", [])
self.make_jobs = kernel_config.get("make_jobs", "$(nproc)")
self.kernel_config = kernel_config.get("kernel_config", "defconfig")
self.target_name = kernel_config.get("target_name")
self.build_host_ip = kernel_config.get("build_host_ip")
self.ssh_options = kernel_config.get(
"ssh_options", "-o StrictHostKeyChecking=no")
self.build_host_user = kernel_config.get(
"build_host_user", os.getenv("USER", "builduser"))
self.pr_enabled = config.get("pr_enabled", False)
self.pr_target_branch = config.get(
"pr_target_branch", self.target_branch)
self.work_item_id = work_item_id or config.get("work_item_id", "")
self.ssh_target = kernel_config.get("ssh_target")
Loading