* Copyright (c) 2026 Huawei Technologies Co., Ltd.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
*/
#include "kernel_specialization_diagnostics.h"
#include "ascendc_tool_log.h"
#include "file_utils.h"
#include "process_executor.h"
#include <boost/filesystem.hpp>
#include <cerrno>
#include <cstring>
#include <exception>
#include <fstream>
#include <sstream>
#include <sys/stat.h>
namespace ascendc {
namespace aclrtc {
namespace {
namespace fs = boost::filesystem;
constexpr char DIAGNOSTIC_MANIFEST_FILE_NAME[] = "aclrtc_manifest.json";
constexpr char DIAGNOSTIC_COMPILE_LOG_FILE_NAME[] = "aclrtc_compile.log";
constexpr char DIAGNOSTIC_REPLAY_SCRIPT_FILE_NAME[] = "aclrtc_replay.sh";
constexpr char DIAGNOSTIC_RESULT_FILE_NAME[] = "aclrtc_result.json";
template <typename TextBuilder>
void WriteDiagnosticTextBestEffort(
const fs::path& resourceWorktreePath, const char* fileName, std::ios::openmode writeMode, const char* commandLabel,
const TextBuilder& buildText) noexcept
{
try {
const fs::path filePath = resourceWorktreePath / fileName;
FileUtils::WriteTextFile(filePath.string(), buildText(), writeMode);
} catch (const std::exception& exception) {
ASCENDLOGW(
"Failed to write diagnostic text: resource_worktree=%s file=%s command=%s message=%s",
resourceWorktreePath.c_str(), fileName, commandLabel, exception.what());
} catch (...) {
ASCENDLOGW(
"Unknown exception while writing diagnostic text: resource_worktree=%s file=%s command=%s",
resourceWorktreePath.c_str(), fileName, commandLabel);
}
}
std::string QuoteArgumentForReplayScript(const std::string& argument)
{
std::string quotedArgument("'");
for (char character : argument) {
if (character == '\'') {
quotedArgument += "'\"'\"'";
} else {
quotedArgument += character;
}
}
quotedArgument += '\'';
return quotedArgument;
}
void RemoveIncompleteReplayScript(const fs::path& replayScriptPath) noexcept
{
boost::system::error_code removalError;
fs::remove(replayScriptPath, removalError);
if (removalError) {
ASCENDLOGW(
"Failed to remove incomplete replay script: path=%s error=%d message=%s", replayScriptPath.c_str(),
removalError.value(), removalError.message().c_str());
}
}
bool CreateExecutableReplayScript(const fs::path& replayScriptPath, const fs::path& compilationWorkingDirectoryPath)
{
const std::string replayScriptHeader =
"#!/bin/sh\nset -eu\ncd " + QuoteArgumentForReplayScript(compilationWorkingDirectoryPath.string()) + "\n";
if (!FileUtils::WriteTextFile(replayScriptPath.string(), replayScriptHeader, std::ios::trunc)) {
RemoveIncompleteReplayScript(replayScriptPath);
return false;
}
constexpr mode_t replayScriptPermission = S_IRUSR | S_IWUSR | S_IXUSR;
if (chmod(replayScriptPath.c_str(), replayScriptPermission) == 0) {
return true;
}
const int permissionError = errno;
ASCENDLOGW(
"Failed to make replay script executable: path=%s errno=%d message=%s", replayScriptPath.c_str(),
permissionError, std::strerror(permissionError));
RemoveIncompleteReplayScript(replayScriptPath);
return false;
}
}
KernelSpecializationDiagnostics::KernelSpecializationDiagnostics(
fs::path resourceWorktreePath, std::string specializationSessionId)
: specializationSessionId_(std::move(specializationSessionId)),
diagnosticsEnabled_(!resourceWorktreePath.empty()),
resourceWorktreePath_(std::move(resourceWorktreePath))
{
if (!diagnosticsEnabled_) {
return;
}
try {
const fs::path replayScriptPath = resourceWorktreePath_ / DIAGNOSTIC_REPLAY_SCRIPT_FILE_NAME;
if (!CreateExecutableReplayScript(replayScriptPath, fs::current_path())) {
diagnosticsEnabled_ = false;
}
} catch (const std::exception& exception) {
diagnosticsEnabled_ = false;
ASCENDLOGW(
"Failed to initialize specialization diagnostics in resource worktree: session=%s path=%s message=%s",
specializationSessionId_.c_str(), resourceWorktreePath_.c_str(), exception.what());
} catch (...) {
diagnosticsEnabled_ = false;
ASCENDLOGW(
"Failed to initialize specialization diagnostics in resource worktree: session=%s path=%s",
specializationSessionId_.c_str(), resourceWorktreePath_.c_str());
}
}
void KernelSpecializationDiagnostics::WriteManifestSnapshot(const nlohmann::json& resourceManifest) noexcept
{
if (!diagnosticsEnabled_) {
return;
}
WriteDiagnosticTextBestEffort(
resourceWorktreePath_, DIAGNOSTIC_MANIFEST_FILE_NAME, std::ios::trunc, "", [&resourceManifest]() {
constexpr int32_t diagnosticJsonIndentationWidth = 2;
return resourceManifest.dump(diagnosticJsonIndentationWidth) + '\n';
});
}
void KernelSpecializationDiagnostics::AppendCommandToReplayScript(const CompilationCommand& compilationCommand) noexcept
{
if (!diagnosticsEnabled_) {
return;
}
WriteDiagnosticTextBestEffort(
resourceWorktreePath_, DIAGNOSTIC_REPLAY_SCRIPT_FILE_NAME, std::ios::app,
compilationCommand.diagnosticLabel.c_str(), [&compilationCommand]() {
std::string replayLine = QuoteArgumentForReplayScript(compilationCommand.executablePath.string());
for (const std::string& argument : compilationCommand.arguments) {
replayLine += " " + QuoteArgumentForReplayScript(argument);
}
return replayLine + '\n';
});
}
std::string KernelSpecializationDiagnostics::GetCompilationLogFilePath() const
{
return diagnosticsEnabled_ ? (resourceWorktreePath_ / DIAGNOSTIC_COMPILE_LOG_FILE_NAME).string() : std::string();
}
void KernelSpecializationDiagnostics::AppendCommandExecutionHeaderToLog(
const CompilationCommand& compilationCommand) noexcept
{
if (!diagnosticsEnabled_) {
return;
}
WriteDiagnosticTextBestEffort(
resourceWorktreePath_, DIAGNOSTIC_COMPILE_LOG_FILE_NAME, std::ios::app,
compilationCommand.diagnosticLabel.c_str(),
[&compilationCommand]() { return "[" + compilationCommand.diagnosticLabel + "] output:\n"; });
}
void KernelSpecializationDiagnostics::AppendCommandExecutionResultToLog(
const CompilationCommand& compilationCommand, const ProcessExecutorResult& executorResult) noexcept
{
if (!diagnosticsEnabled_) {
return;
}
WriteDiagnosticTextBestEffort(
resourceWorktreePath_, DIAGNOSTIC_COMPILE_LOG_FILE_NAME, std::ios::app,
compilationCommand.diagnosticLabel.c_str(), [&compilationCommand, &executorResult]() {
std::ostringstream resultText;
resultText << '\n'
<< '[' << compilationCommand.diagnosticLabel << "] outcome=" << executorResult.GetOutcomeName()
<< " code=" << executorResult.terminationCode
<< " elapsed_ms=" << executorResult.elapsedTime.count() << '\n';
return resultText.str();
});
}
void KernelSpecializationDiagnostics::LogCommandFailureRecoveryHint() const noexcept
{
if (!diagnosticsEnabled_) {
ASCENDLOGI("Set ASCEND_OP_COMPILE_SAVE_KERNEL_META=1 and retry to retain the resource worktree and save "
"specialization diagnostics");
return;
}
ASCENDLOGI(
"Compilation diagnostics saved: compile_log=%s/%s replay_script=%s/%s; inspect the log or run the replay "
"script to reproduce the failed command",
resourceWorktreePath_.c_str(), DIAGNOSTIC_COMPILE_LOG_FILE_NAME, resourceWorktreePath_.c_str(),
DIAGNOSTIC_REPLAY_SCRIPT_FILE_NAME);
}
void KernelSpecializationDiagnostics::WriteSpecializationResult(
const fs::path& outputElfPath, KernelElfPublicationStatus publicationStatus) noexcept
{
if (!diagnosticsEnabled_) {
return;
}
WriteDiagnosticTextBestEffort(
resourceWorktreePath_, DIAGNOSTIC_RESULT_FILE_NAME, std::ios::trunc, "",
[this, &outputElfPath, publicationStatus]() {
constexpr int32_t diagnosticJsonIndentationWidth = 2;
nlohmann::json resultJson{
{"specialization_session_id", specializationSessionId_},
{"output_path", outputElfPath.string()},
{"output_published", publicationStatus == KernelElfPublicationStatus::Published},
};
return resultJson.dump(diagnosticJsonIndentationWidth) + '\n';
});
}
}
}