From 2a239ddf472792e303629f0f4bdb451bdc57f831 Mon Sep 17 00:00:00 2001 From: Giacomo Vercesi Date: Mon, 31 Jul 2023 10:32:35 +0200 Subject: [PATCH] Introduce PipelineDescription Add the PipelineDescription object that describes the structure of a pipeline. This will be used by all the downstream users instead of pipeline accessor methods via PipelineC. --- .../revng/Pipeline/Description/AnalysesList.h | 32 +++++ include/revng/Pipeline/Description/Analysis.h | 37 +++++ .../Description/AnalysisContainerInput.h | 32 +++++ .../Pipeline/Description/AnalysisOption.h | 30 ++++ .../Pipeline/Description/AnalysisReference.h | 31 ++++ .../revng/Pipeline/Description/Artifacts.h | 39 ++++++ .../revng/Pipeline/Description/Container.h | 30 ++++ include/revng/Pipeline/Description/Kind.h | 46 ++++++ .../Description/PipelineDescription.h | 50 +++++++ include/revng/Pipeline/Description/Rank.h | 34 +++++ include/revng/Pipeline/Description/Step.h | 44 ++++++ include/revng/Pipeline/Runner.h | 3 + include/revng/Pipeline/Step.h | 7 + include/revng/Pipes/PipelineManager.h | 2 + lib/Pipeline/CMakeLists.txt | 41 ++++++ lib/Pipeline/DescriptionConverter.cpp | 132 ++++++++++++++++++ lib/Pipes/PipelineManager.cpp | 31 ++++ python/CMakeLists.txt | 11 +- python/revng/pipeline_description/__init__.py | 5 + typescript/CMakeLists.txt | 42 ++++-- .../{build-model.sh => build-tupletree.sh} | 21 +-- typescript/package-pipeline-description.json | 14 ++ .../{tsconfig-model.json => tsconfig.json} | 0 23 files changed, 689 insertions(+), 25 deletions(-) create mode 100644 include/revng/Pipeline/Description/AnalysesList.h create mode 100644 include/revng/Pipeline/Description/Analysis.h create mode 100644 include/revng/Pipeline/Description/AnalysisContainerInput.h create mode 100644 include/revng/Pipeline/Description/AnalysisOption.h create mode 100644 include/revng/Pipeline/Description/AnalysisReference.h create mode 100644 include/revng/Pipeline/Description/Artifacts.h create mode 100644 include/revng/Pipeline/Description/Container.h create mode 100644 include/revng/Pipeline/Description/Kind.h create mode 100644 include/revng/Pipeline/Description/PipelineDescription.h create mode 100644 include/revng/Pipeline/Description/Rank.h create mode 100644 include/revng/Pipeline/Description/Step.h create mode 100644 lib/Pipeline/DescriptionConverter.cpp create mode 100644 python/revng/pipeline_description/__init__.py rename typescript/{build-model.sh => build-tupletree.sh} (62%) create mode 100644 typescript/package-pipeline-description.json rename typescript/{tsconfig-model.json => tsconfig.json} (100%) diff --git a/include/revng/Pipeline/Description/AnalysesList.h b/include/revng/Pipeline/Description/AnalysesList.h new file mode 100644 index 000000000..fc86673dc --- /dev/null +++ b/include/revng/Pipeline/Description/AnalysesList.h @@ -0,0 +1,32 @@ +#pragma once + +// +// This file is distributed under the MIT License. See LICENSE.md for details. +// + +/* TUPLE-TREE-YAML +name: AnalysesList +doc: Data structure representing a list of analyses +type: struct +fields: + - name: Name + doc: AnalysesList's name + type: string + - name: Analyses + doc: AnalysesList's list of analyses + sequence: + type: SortedVector + elementType: AnalysisReference +key: + - Name +TUPLE-TREE-YAML */ + +#include "revng/Pipeline/Description/Generated/Early/AnalysesList.h" + +class pipeline::description::AnalysesList + : public pipeline::description::generated::AnalysesList { +public: + using generated::AnalysesList::AnalysesList; +}; + +#include "revng/Pipeline/Description/Generated/Late/AnalysesList.h" diff --git a/include/revng/Pipeline/Description/Analysis.h b/include/revng/Pipeline/Description/Analysis.h new file mode 100644 index 000000000..446d86b2a --- /dev/null +++ b/include/revng/Pipeline/Description/Analysis.h @@ -0,0 +1,37 @@ +#pragma once + +// +// This file is distributed under the MIT License. See LICENSE.md for details. +// + +/* TUPLE-TREE-YAML +name: Analysis +doc: Data structure representing an analysis +type: struct +fields: + - name: Name + doc: Analysis' name + type: string + - name: ContainerInputs + doc: Analysis' container inputs + sequence: + type: SortedVector + elementType: AnalysisContainerInput + - name: Options + doc: Analysis' options + sequence: + type: SortedVector + elementType: AnalysisOption +key: + - Name +TUPLE-TREE-YAML */ + +#include "revng/Pipeline/Description/Generated/Early/Analysis.h" + +class pipeline::description::Analysis + : public pipeline::description::generated::Analysis { +public: + using generated::Analysis::Analysis; +}; + +#include "revng/Pipeline/Description/Generated/Late/Analysis.h" diff --git a/include/revng/Pipeline/Description/AnalysisContainerInput.h b/include/revng/Pipeline/Description/AnalysisContainerInput.h new file mode 100644 index 000000000..93b40b34a --- /dev/null +++ b/include/revng/Pipeline/Description/AnalysisContainerInput.h @@ -0,0 +1,32 @@ +#pragma once + +// +// This file is distributed under the MIT License. See LICENSE.md for details. +// + +/* TUPLE-TREE-YAML +name: AnalysisContainerInput +doc: Data structure representing an analysis' container input +type: struct +fields: + - name: Name + doc: AnalysisContainerInput' name + type: string + - name: AcceptableKinds + doc: Kinds accepted by the analysis + sequence: + type: SortedVector + elementType: string +key: + - Name +TUPLE-TREE-YAML */ + +#include "revng/Pipeline/Description/Generated/Early/AnalysisContainerInput.h" + +class pipeline::description::AnalysisContainerInput + : public pipeline::description::generated::AnalysisContainerInput { +public: + using generated::AnalysisContainerInput::AnalysisContainerInput; +}; + +#include "revng/Pipeline/Description/Generated/Late/AnalysisContainerInput.h" diff --git a/include/revng/Pipeline/Description/AnalysisOption.h b/include/revng/Pipeline/Description/AnalysisOption.h new file mode 100644 index 000000000..b6ddc540a --- /dev/null +++ b/include/revng/Pipeline/Description/AnalysisOption.h @@ -0,0 +1,30 @@ +#pragma once + +// +// This file is distributed under the MIT License. See LICENSE.md for details. +// + +/* TUPLE-TREE-YAML +name: AnalysisOption +doc: Data structure representing an analysis' container input +type: struct +fields: + - name: Name + doc: AnalysisOption' name + type: string + - name: Type + doc: Type of the option + type: string +key: + - Name +TUPLE-TREE-YAML */ + +#include "revng/Pipeline/Description/Generated/Early/AnalysisOption.h" + +class pipeline::description::AnalysisOption + : public pipeline::description::generated::AnalysisOption { +public: + using generated::AnalysisOption::AnalysisOption; +}; + +#include "revng/Pipeline/Description/Generated/Late/AnalysisOption.h" diff --git a/include/revng/Pipeline/Description/AnalysisReference.h b/include/revng/Pipeline/Description/AnalysisReference.h new file mode 100644 index 000000000..f098faa65 --- /dev/null +++ b/include/revng/Pipeline/Description/AnalysisReference.h @@ -0,0 +1,31 @@ +#pragma once + +// +// This file is distributed under the MIT License. See LICENSE.md for details. +// + +/* TUPLE-TREE-YAML +name: AnalysisReference +doc: A reference to an analysis +type: struct +fields: + - name: Step + doc: The step where the analysis belongs to + type: string + - name: Name + doc: The name of the analysis + type: string +key: + - Step + - Name +TUPLE-TREE-YAML */ + +#include "revng/Pipeline/Description/Generated/Early/AnalysisReference.h" + +class pipeline::description::AnalysisReference + : public pipeline::description::generated::AnalysisReference { +public: + using generated::AnalysisReference::AnalysisReference; +}; + +#include "revng/Pipeline/Description/Generated/Late/AnalysisReference.h" diff --git a/include/revng/Pipeline/Description/Artifacts.h b/include/revng/Pipeline/Description/Artifacts.h new file mode 100644 index 000000000..2db732259 --- /dev/null +++ b/include/revng/Pipeline/Description/Artifacts.h @@ -0,0 +1,39 @@ +#pragma once + +// +// This file is distributed under the MIT License. See LICENSE.md for details. +// + +/* TUPLE-TREE-YAML +name: Artifacts +doc: Data structure representing a Artifacts +type: struct +fields: + - name: Kind + doc: Artifacts's kind + type: string + optional: true + - name: Container + doc: Artifacts's container + type: string + optional: true + - name: SingleTargetFilename + doc: The Artifacts's filename to use for a single element + type: string + optional: true +TUPLE-TREE-YAML */ + +#include "revng/Pipeline/Description/Generated/Early/Artifacts.h" + +class pipeline::description::Artifacts + : public pipeline::description::generated::Artifacts { +public: + using generated::Artifacts::Artifacts; + + bool isValid() { + return not(this->Container().empty() or this->Kind().empty() + or this->SingleTargetFilename().empty()); + } +}; + +#include "revng/Pipeline/Description/Generated/Late/Artifacts.h" diff --git a/include/revng/Pipeline/Description/Container.h b/include/revng/Pipeline/Description/Container.h new file mode 100644 index 000000000..e6ca0b2ad --- /dev/null +++ b/include/revng/Pipeline/Description/Container.h @@ -0,0 +1,30 @@ +#pragma once + +// +// This file is distributed under the MIT License. See LICENSE.md for details. +// + +/* TUPLE-TREE-YAML +name: Container +doc: Data structure representing a Container +type: struct +fields: + - name: Name + doc: Container's name + type: string + - name: MIMEType + doc: Container's mime type + type: string +key: + - Name +TUPLE-TREE-YAML */ + +#include "revng/Pipeline/Description/Generated/Early/Container.h" + +class pipeline::description::Container + : public pipeline::description::generated::Container { +public: + using generated::Container::Container; +}; + +#include "revng/Pipeline/Description/Generated/Late/Container.h" diff --git a/include/revng/Pipeline/Description/Kind.h b/include/revng/Pipeline/Description/Kind.h new file mode 100644 index 000000000..770233547 --- /dev/null +++ b/include/revng/Pipeline/Description/Kind.h @@ -0,0 +1,46 @@ +#pragma once + +// +// This file is distributed under the MIT License. See LICENSE.md for details. +// + +/* TUPLE-TREE-YAML +name: Kind +doc: Data structure representing a Kind +type: struct +fields: + - name: Name + doc: Kind's name + type: string + - name: Rank + doc: Kind's rank + type: string + - name: Parent + doc: The Kind's parent (if present) + type: string + optional: true + - name: DefinedLocations + doc: List of locations that the Kind provides + sequence: + type: SortedVector + elementType: string + - name: PreferredKinds + doc: > + These are the kinds that should be looked into in order to find + definitions to locations that are not present in the current document + sequence: + type: SortedVector + elementType: string +key: + - Name +TUPLE-TREE-YAML */ + +#include "revng/Pipeline/Description/Generated/Early/Kind.h" + +class pipeline::description::Kind + : public pipeline::description::generated::Kind { +public: + using generated::Kind::Kind; +}; + +#include "revng/Pipeline/Description/Generated/Late/Kind.h" diff --git a/include/revng/Pipeline/Description/PipelineDescription.h b/include/revng/Pipeline/Description/PipelineDescription.h new file mode 100644 index 000000000..441086da9 --- /dev/null +++ b/include/revng/Pipeline/Description/PipelineDescription.h @@ -0,0 +1,50 @@ +#pragma once + +// +// This file is distributed under the MIT License. See LICENSE.md for details. +// + +/* TUPLE-TREE-YAML +name: PipelineDescription +doc: Data structure representing the structure of the pipeline +type: struct +fields: + - name: AnalysesLists + doc: AnalysesLists available in the pipeline + sequence: + type: SortedVector + elementType: AnalysesList + - name: Globals + doc: List of Globals + sequence: + type: SortedVector + elementType: string + - name: Kinds + doc: Kinds + sequence: + type: SortedVector + elementType: Kind + - name: Ranks + doc: Ranks + sequence: + type: SortedVector + elementType: Rank + - name: Containers + sequence: + type: SortedVector + elementType: Container + - name: Steps + sequence: + type: SortedVector + elementType: Step +TUPLE-TREE-YAML */ + +#include "revng/Pipeline/Description/Generated/Early/PipelineDescription.h" + +class pipeline::description::PipelineDescription + : public pipeline::description::generated::PipelineDescription { +public: + using generated::PipelineDescription::PipelineDescription; +}; + +#include "revng/Pipeline/Description/Generated/Late/PipelineDescription.h" diff --git a/include/revng/Pipeline/Description/Rank.h b/include/revng/Pipeline/Description/Rank.h new file mode 100644 index 000000000..b1fd0408a --- /dev/null +++ b/include/revng/Pipeline/Description/Rank.h @@ -0,0 +1,34 @@ +#pragma once + +// +// This file is distributed under the MIT License. See LICENSE.md for details. +// + +/* TUPLE-TREE-YAML +name: Rank +doc: Data structure representing a Rank +type: struct +fields: + - name: Name + doc: Rank's name + type: string + - name: Depth + doc: Rank's depth + type: uint64_t + - name: Parent + doc: The Rank's parent (if present) + type: string + optional: true +key: + - Name +TUPLE-TREE-YAML */ + +#include "revng/Pipeline/Description/Generated/Early/Rank.h" + +class pipeline::description::Rank + : public pipeline::description::generated::Rank { +public: + using generated::Rank::Rank; +}; + +#include "revng/Pipeline/Description/Generated/Late/Rank.h" diff --git a/include/revng/Pipeline/Description/Step.h b/include/revng/Pipeline/Description/Step.h new file mode 100644 index 000000000..520e856bd --- /dev/null +++ b/include/revng/Pipeline/Description/Step.h @@ -0,0 +1,44 @@ +#pragma once + +// +// This file is distributed under the MIT License. See LICENSE.md for details. +// + +/* TUPLE-TREE-YAML +name: Step +doc: Data structure representing a Step +type: struct +fields: + - name: Name + doc: Step's name + type: string + - name: Component + doc: Step's component + type: string + optional: true + - name: Parent + doc: The Step's parent (if present) + type: string + optional: true + - name: Analyses + doc: List of Analyses that the Step provides + sequence: + type: SortedVector + elementType: Analysis + - name: Artifacts + doc: The artifacts that this step provides + type: Artifacts + optional: true +key: + - Name +TUPLE-TREE-YAML */ + +#include "revng/Pipeline/Description/Generated/Early/Step.h" + +class pipeline::description::Step + : public pipeline::description::generated::Step { +public: + using generated::Step::Step; +}; + +#include "revng/Pipeline/Description/Generated/Late/Step.h" diff --git a/include/revng/Pipeline/Runner.h b/include/revng/Pipeline/Runner.h index f5cbbe2c8..548a7af30 100644 --- a/include/revng/Pipeline/Runner.h +++ b/include/revng/Pipeline/Runner.h @@ -15,6 +15,7 @@ #include "revng/Pipeline/AnalysesList.h" #include "revng/Pipeline/ContainerFactorySet.h" +#include "revng/Pipeline/Description/PipelineDescription.h" #include "revng/Pipeline/GlobalTupleTreeDiff.h" #include "revng/Pipeline/KindsRegistry.h" #include "revng/Pipeline/Step.h" @@ -119,6 +120,8 @@ public: AnalysesLists.try_emplace(Name, pipeline::AnalysesList(Name, Analyses)); } + pipeline::description::PipelineDescription description() const; + public: /// Given a target, all occurrences of that target from every container in /// every step will be registered in the returned invalidation map. The diff --git a/include/revng/Pipeline/Step.h b/include/revng/Pipeline/Step.h index de0d81367..34f319632 100644 --- a/include/revng/Pipeline/Step.h +++ b/include/revng/Pipeline/Step.h @@ -152,6 +152,13 @@ public: } } + std::string getArtifactsContainerName() const { + if (!Artifacts.isValid()) + return ""; + else + return Artifacts.Container; + } + const ContainerSet::value_type *getArtifactsContainer() { if (!Artifacts.isValid()) { return nullptr; diff --git a/include/revng/Pipes/PipelineManager.h b/include/revng/Pipes/PipelineManager.h index e62332e0b..d851afdee 100644 --- a/include/revng/Pipes/PipelineManager.h +++ b/include/revng/Pipes/PipelineManager.h @@ -44,6 +44,7 @@ private: std::map ContainerToEnumeration; + std::string Description; public: PipelineManager(PipelineManager &&Other) = default; @@ -194,5 +195,6 @@ public: private: llvm::Error produceAllPossibleTargets(bool ExpandTargets); + llvm::Error computeDescription(); }; } // namespace revng::pipes diff --git a/lib/Pipeline/CMakeLists.txt b/lib/Pipeline/CMakeLists.txt index f9f773cb5..89b702baa 100644 --- a/lib/Pipeline/CMakeLists.txt +++ b/lib/Pipeline/CMakeLists.txt @@ -8,6 +8,7 @@ revng_add_library_internal( ContainerSet.cpp Context.cpp Contract.cpp + DescriptionConverter.cpp Errors.cpp GenericLLVMPipe.cpp Kind.cpp @@ -22,3 +23,43 @@ revng_add_library_internal( GlobalsMap.cpp) target_link_libraries(revngPipeline revngStorage revngSupport ${LLVM_LIBRARIES}) + +set(PIPELINEDESCRIPTION_HEADERS_DIR + "${CMAKE_SOURCE_DIR}/include/revng/Pipeline/Description") +set(PIPELINEDESCRIPTION_SCHEMA_PATH + "${CMAKE_BINARY_DIR}/pipelineDescription-schema.yml") +set(PIPELINEDESCRIPTION_JSONSCHEMA_PATH + "${CMAKE_BINARY_DIR}/pipelineDescription-jsonschema.yml") +set(PIPELINEDESCRIPTION_TYPESCRIPT_PATH + "${CMAKE_BINARY_DIR}/lib/typescript/pipeline-description.ts") +target_tuple_tree_generator( + revngPipeline + INSTALL + HEADER_DIRECTORY + Pipeline/Description + NAMESPACE + pipeline::description + SCHEMA_PATH + ${PIPELINEDESCRIPTION_SCHEMA_PATH} + JSONSCHEMA_PATH + "${PIPELINEDESCRIPTION_JSONSCHEMA_PATH}" + PYTHON_PATH + "${CMAKE_BINARY_DIR}/${PYTHON_INSTALL_PATH}/revng/pipeline_description/_generated.py" + TYPESCRIPT_PATH + "${PIPELINEDESCRIPTION_TYPESCRIPT_PATH}" + ROOT_TYPE + PipelineDescription + GLOBAL_NAME + PipelineDescription + HEADERS + "${PIPELINEDESCRIPTION_HEADERS_DIR}/AnalysesList.h" + "${PIPELINEDESCRIPTION_HEADERS_DIR}/AnalysisContainerInput.h" + "${PIPELINEDESCRIPTION_HEADERS_DIR}/AnalysisOption.h" + "${PIPELINEDESCRIPTION_HEADERS_DIR}/AnalysisReference.h" + "${PIPELINEDESCRIPTION_HEADERS_DIR}/Analysis.h" + "${PIPELINEDESCRIPTION_HEADERS_DIR}/Artifacts.h" + "${PIPELINEDESCRIPTION_HEADERS_DIR}/Container.h" + "${PIPELINEDESCRIPTION_HEADERS_DIR}/Kind.h" + "${PIPELINEDESCRIPTION_HEADERS_DIR}/PipelineDescription.h" + "${PIPELINEDESCRIPTION_HEADERS_DIR}/Rank.h" + "${PIPELINEDESCRIPTION_HEADERS_DIR}/Step.h") diff --git a/lib/Pipeline/DescriptionConverter.cpp b/lib/Pipeline/DescriptionConverter.cpp new file mode 100644 index 000000000..04c4522f2 --- /dev/null +++ b/lib/Pipeline/DescriptionConverter.cpp @@ -0,0 +1,132 @@ +/// \file DescriptionConverter.cpp + +// +// This file is distributed under the MIT License. See LICENSE.md for details. +// + +#include "revng/Pipeline/AnalysesList.h" +#include "revng/Pipeline/Analysis.h" +#include "revng/Pipeline/Description/PipelineDescription.h" +#include "revng/Pipeline/Runner.h" +#include "revng/Pipeline/Step.h" + +static pipeline::description::Analysis +describe(const pipeline::AnalysisWrapper &Analysis) { + pipeline::description::Analysis Result; + + Result.Name() = Analysis->getUserBoundName(); + + auto ContainerInputs = Analysis->getRunningContainersNames(); + for (size_t I = 0; I < ContainerInputs.size(); I++) { + pipeline::description::AnalysisContainerInput Input; + Input.Name() = ContainerInputs[I]; + for (auto &Kind : Analysis->getAcceptedKinds(I)) + Input.AcceptableKinds().insert(Kind->name().str()); + + Result.ContainerInputs().insert(Input); + } + + std::vector OptionNames = Analysis->getOptionsNames(); + std::vector OptionTypes = Analysis->getOptionsTypes(); + for (size_t I = 0; I < OptionNames.size(); I++) + Result.Options().insert({ OptionNames[I], OptionTypes[I] }); + + return Result; +} + +static pipeline::description::AnalysesList +describe(const pipeline::AnalysesList &List) { + pipeline::description::AnalysesList Result; + + Result.Name() = List.getName(); + + for (auto &Analysis : List) { + Result.Analyses().insert({ Analysis.getAnalysisName().str(), + Analysis.getStepName().str() }); + } + + return Result; +} + +static pipeline::description::Kind describe(const pipeline::Kind &Kind) { + pipeline::description::Kind Result; + + Result.Name() = Kind.name(); + Result.Rank() = Kind.rank().name(); + if (const pipeline::Kind *Parent = Kind.parent(); Parent != nullptr) + Result.Parent() = Parent->name(); + + for (const pipeline::Rank *Rank : Kind.definedLocations()) + Result.DefinedLocations().insert(Rank->name().str()); + + for (const pipeline::Kind *PrefKind : Kind.preferredKinds()) + Result.PreferredKinds().insert(PrefKind->name().str()); + + return Result; +} + +static pipeline::description::Rank describe(const pipeline::Rank &Rank) { + pipeline::description::Rank Result; + + Result.Name() = Rank.name(); + if (const pipeline::Rank *Parent = Rank.parent(); Parent != nullptr) + Result.Parent() = Parent->name(); + + Result.Depth() = Rank.depth(); + + return Result; +} + +static pipeline::description::Step describe(const pipeline::Step &Step) { + pipeline::description::Step Result; + + Result.Name() = Step.getName(); + Result.Component() = Step.getComponent().str(); + if (Step.hasPredecessor()) + Result.Parent() = Step.getPredecessor().getName(); + + for (auto &[Name, RunnerAnalysis] : Step.analyses()) + Result.Analyses().insert(describe(RunnerAnalysis)); + + if (const pipeline::Kind *Kind = Step.getArtifactsKind(); Kind != nullptr) { + pipeline::description::Artifacts Artifacts; + Artifacts.Kind() = Kind->name(); + Artifacts.Container() = Step.getArtifactsContainerName(); + Artifacts.SingleTargetFilename() = Step.getArtifactsSingleTargetFilename(); + Result.Artifacts() = Artifacts; + } + + return Result; +} + +pipeline::description::PipelineDescription +pipeline::Runner::description() const { + pipeline::description::PipelineDescription Result; + + size_t ALCount = getAnalysesListCount(); + for (size_t I = 0; I < ALCount; I++) { + const pipeline::AnalysesList &List = getAnalysesList(I); + Result.AnalysesLists().insert(describe(List)); + } + + const pipeline::GlobalsMap &GlobalsMap = getContext().getGlobals(); + for (size_t I = 0; I < GlobalsMap.size(); I++) + Result.Globals().insert(GlobalsMap.getName(I).str()); + + for (pipeline::Kind &Kind : getKindsRegistry()) + Result.Kinds().insert(describe(Kind)); + + for (pipeline::Rank *Rank : pipeline::Rank::getAll()) + Result.Ranks().insert(describe(*Rank)); + + const auto &ContainerRegistry = getContainerFactorySet(); + for (const auto &[Name, ContainerIdentifier] : ContainerRegistry) { + Result.Containers().insert({ Name.str(), + ContainerIdentifier.mimeType().str() }); + } + + for (auto &Step : *this) + Result.Steps().insert(describe(Step)); + + return Result; +} diff --git a/lib/Pipes/PipelineManager.cpp b/lib/Pipes/PipelineManager.cpp index dd27e3427..804d072fb 100644 --- a/lib/Pipes/PipelineManager.cpp +++ b/lib/Pipes/PipelineManager.cpp @@ -173,6 +173,10 @@ PipelineManager::createFromMemory(llvm::ArrayRef PipelineContent, return MaybePipeline.takeError(); Manager.recalculateAllPossibleTargets(); + + if (auto Error = Manager.computeDescription(); Error) + return Error; + return std::move(Manager); } @@ -494,3 +498,30 @@ PipelineManager::produceTargets(const llvm::StringRef StepName, const auto &ToFilter = Targets.at(TheContainer.second->name()); return TheContainer.second->cloneFiltered(ToFilter); } + +llvm::Error PipelineManager::computeDescription() { + using pipeline::description::PipelineDescription; + PipelineDescription Description = getRunner().description(); + + { + llvm::raw_string_ostream OS(this->Description); + yaml::Output YAMLOutput(OS); + YAMLOutput << Description; + } + + if (StorageClient == nullptr) + return llvm::Error::success(); + + if (auto Error = ExecutionDirectory.create(); Error) + return Error; + + constexpr auto DescriptionName = "pipeline-description.yml"; + revng::FilePath DescriptionPath = ExecutionDirectory.getFile(DescriptionName); + auto MaybeWritableFile = DescriptionPath.getWritableFile(); + if (!MaybeWritableFile) + return MaybeWritableFile.takeError(); + + MaybeWritableFile.get()->os() << this->Description; + + return MaybeWritableFile.get()->commit(); +} diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index cfc683fed..2ea08b8fc 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -163,9 +163,18 @@ python_module(TARGET_NAME revng-python-daemon MODULE_FILES ${REVNG_DAEMON_MODULE_FILES}) # -# Install revng.daemon +# Install revng.support # set(REVNG_SUPPORT_MODULE_FILES revng/support/__init__.py revng/support/elf.py revng/support/collect.py) python_module(TARGET_NAME revng-python-support MODULE_FILES ${REVNG_SUPPORT_MODULE_FILES}) + +# +# Install revng.pipeline_description +# +set(PYTHON_PIPELINEDESCRIPTION_FILES revng/pipeline_description/__init__.py) +python_module( + TARGET_NAME python-pipeline-description MODULE_FILES + ${PYTHON_PIPELINEDESCRIPTION_FILES} MODULE_GENERATED_FILES + revng/pipeline_description/_generated.py) diff --git a/python/revng/pipeline_description/__init__.py b/python/revng/pipeline_description/__init__.py new file mode 100644 index 000000000..836da83b0 --- /dev/null +++ b/python/revng/pipeline_description/__init__.py @@ -0,0 +1,5 @@ +# +# This file is distributed under the MIT License. See LICENSE.md for details. +# + +from ._generated import * # noqa: F401,F403 diff --git a/typescript/CMakeLists.txt b/typescript/CMakeLists.txt index ffec75915..19a167d65 100644 --- a/typescript/CMakeLists.txt +++ b/typescript/CMakeLists.txt @@ -17,23 +17,37 @@ add_custom_target( "${CMAKE_BINARY_DIR}/node_build/package.json") # Model package generation -add_custom_command( - OUTPUT "${CMAKE_BINARY_DIR}/model.ts.tgz" - "${CMAKE_BINARY_DIR}/lib/node_modules/revng-model/dist/model.js" - COMMAND - "${CMAKE_CURRENT_SOURCE_DIR}/build-model.sh" "${CMAKE_CURRENT_SOURCE_DIR}" - "${CMAKE_BINARY_DIR}/node_build/node_modules" - WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" - DEPENDS "${CMAKE_BINARY_DIR}/lib/typescript/model.ts") +function(typescript_module) + set(options) + set(oneValueArgs TARGET_NAME) + set(multiValueArgs) + cmake_parse_arguments(TYPESCRIPT_MODULE "${options}" "${oneValueArgs}" + "${multiValueArgs}" ${ARGN}) -add_custom_target(generate-model.ts.tgz ALL - DEPENDS "${CMAKE_BINARY_DIR}/model.ts.tgz") + set(TARGET_NAME "${TYPESCRIPT_MODULE_TARGET_NAME}") + add_custom_command( + OUTPUT + "${CMAKE_BINARY_DIR}/${TARGET_NAME}.ts.tgz" + "${CMAKE_BINARY_DIR}/lib/node_modules/revng-model/dist/${TARGET_NAME}.js" + COMMAND + "${CMAKE_CURRENT_SOURCE_DIR}/build-tupletree.sh" + "${CMAKE_CURRENT_SOURCE_DIR}" + "${CMAKE_BINARY_DIR}/node_build/node_modules" "${TARGET_NAME}" + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" + DEPENDS "${CMAKE_BINARY_DIR}/lib/typescript/${TARGET_NAME}.ts") -install(FILES "${CMAKE_BINARY_DIR}/model.ts.tgz" - DESTINATION "${CMAKE_INSTALL_PREFIX}/share/typescript") + add_custom_target("generate-${TARGET_NAME}.ts.tgz" ALL + DEPENDS "${CMAKE_BINARY_DIR}/${TARGET_NAME}.ts.tgz") -install(FILES "${CMAKE_BINARY_DIR}/model.ts.tgz" - DESTINATION "${CMAKE_INSTALL_PREFIX}/share/node_cache") + install(FILES "${CMAKE_BINARY_DIR}/${TARGET_NAME}.ts.tgz" + DESTINATION "${CMAKE_INSTALL_PREFIX}/share/typescript") + + install(FILES "${CMAKE_BINARY_DIR}/${TARGET_NAME}.ts.tgz" + DESTINATION "${CMAKE_INSTALL_PREFIX}/share/node_cache") +endfunction() + +typescript_module(TARGET_NAME model) +typescript_module(TARGET_NAME pipeline-description) install(DIRECTORY "${CMAKE_BINARY_DIR}/lib/node_modules" DESTINATION "${CMAKE_INSTALL_PREFIX}/lib") diff --git a/typescript/build-model.sh b/typescript/build-tupletree.sh similarity index 62% rename from typescript/build-model.sh rename to typescript/build-tupletree.sh index 78a70dc6e..dfeb5c620 100755 --- a/typescript/build-model.sh +++ b/typescript/build-tupletree.sh @@ -5,28 +5,29 @@ set -euo pipefail -rm -rf model.ts-package +PACKAGE_DIR="$3.ts-package" +rm -rf "$PACKAGE_DIR" -mkdir model.ts-package -BUILD_DIR="$(realpath model.ts-package)" +mkdir "$PACKAGE_DIR" +BUILD_DIR="$(realpath "$PACKAGE_DIR")" function cleanup() { trap - SIGINT SIGTERM ERR EXIT rm -rf "$BUILD_DIR" } trap cleanup SIGINT SIGTERM ERR EXIT -cd model.ts-package +cd "$PACKAGE_DIR" -cp "$1/package-model.json" package.json -cp "$1/tsconfig-model.json" tsconfig.json +cp "$1/package-$3.json" package.json +cp "$1/tsconfig.json" tsconfig.json cp "$1/tuple_tree.ts" tuple_tree.ts -cp ../lib/typescript/model.ts . -CHECKSUM=$(cat model.ts tuple_tree.ts | sha1sum - | cut -d' ' -f1) +cp ../lib/typescript/"$3".ts . +CHECKSUM=$(cat "$3.ts" "tuple_tree.ts" | sha1sum - | cut -d' ' -f1) sed -i "s;##CHECKSUM##;$CHECKSUM;g" package.json cp -rT "$2" node_modules ./node_modules/.bin/tsc -p . npm pack --silent > /dev/null -cp revng-model-1.*.tgz ../model.ts.tgz +cp "revng-$3-1."*.tgz ../"$3".ts.tgz cd .. @@ -35,7 +36,7 @@ if test -e lib64/node_modules; then exit 1 fi -npm --silent install --global --prefix=. ./model.ts.tgz +npm --silent install --global --prefix=. "./$3.ts.tgz" # Handle npm implementations using lib64 if test -e lib64/node_modules; then diff --git a/typescript/package-pipeline-description.json b/typescript/package-pipeline-description.json new file mode 100644 index 000000000..c7d3ab47a --- /dev/null +++ b/typescript/package-pipeline-description.json @@ -0,0 +1,14 @@ +{ + "license": "MIT", + "__license": "See LICENSE.md for details.", + "name": "revng-pipeline-description", + "version": "1.0.0-##CHECKSUM##", + "description": "revng pipeline-description", + "main": "dist/pipeline-description.js", + "types": "dist/pipeline-description.d.ts", + "files": ["/dist"], + "dependencies": { + "fast-equals": "^5", + "yaml": "^2" + } +} diff --git a/typescript/tsconfig-model.json b/typescript/tsconfig.json similarity index 100% rename from typescript/tsconfig-model.json rename to typescript/tsconfig.json