diff --git a/compiler/include/concretelang-c/Support/CompilerEngine.h b/compiler/include/concretelang-c/Support/CompilerEngine.h index f2ae72d70..90512590c 100644 --- a/compiler/include/concretelang-c/Support/CompilerEngine.h +++ b/compiler/include/concretelang-c/Support/CompilerEngine.h @@ -62,7 +62,8 @@ struct LibrarySupport_C { }; typedef struct LibrarySupport_C LibrarySupport_C; -MLIR_CAPI_EXPORTED LibrarySupport_C library_support(const char *outputPath); +MLIR_CAPI_EXPORTED LibrarySupport_C +library_support(const char *outputPath, const char *runtimeLibraryPath); MLIR_CAPI_EXPORTED std::unique_ptr library_compile(LibrarySupport_C support, const char *module, diff --git a/compiler/include/concretelang/Support/CompilerEngine.h b/compiler/include/concretelang/Support/CompilerEngine.h index 15a388f0c..e8ea4d90f 100644 --- a/compiler/include/concretelang/Support/CompilerEngine.h +++ b/compiler/include/concretelang/Support/CompilerEngine.h @@ -83,14 +83,19 @@ public: std::string libraryPath; std::vector objectsPath; std::vector clientParametersList; + /** Path to the runtime library. Will be linked to the output library if set + */ + std::string runtimeLibraryPath; bool cleanUp; public: /** Create a library instance on which you can add compilation results. * Then you can emit a library file with the given path. * cleanUp at false keeps intermediate .obj files for later use. */ - Library(std::string libraryPath, bool cleanUp = true) - : libraryPath(libraryPath), cleanUp(cleanUp) {} + Library(std::string libraryPath, std::string runtimeLibraryPath = "", + bool cleanUp = true) + : libraryPath(libraryPath), runtimeLibraryPath(runtimeLibraryPath), + cleanUp(cleanUp) {} /** Add a compilation result to the library */ llvm::Expected addCompilation(CompilationResult &compilation); /** Emit the library artifacts with the previously added compilation result @@ -193,12 +198,14 @@ public: llvm::Optional> lib = {}); llvm::Expected - compile(std::vector inputs, std::string libraryPath); + compile(std::vector inputs, std::string libraryPath, + std::string runtimeLibraryPath = ""); /// Compile and emit artifact to the given libraryPath from an LLVM source /// manager. - llvm::Expected compile(llvm::SourceMgr &sm, - std::string libraryPath); + llvm::Expected + compile(llvm::SourceMgr &sm, std::string libraryPath, + std::string runtimeLibraryPath = ""); void setCompilationOptions(CompilationOptions &options) { if (options.v0FHEConstraints.hasValue()) { diff --git a/compiler/include/concretelang/Support/LibrarySupport.h b/compiler/include/concretelang/Support/LibrarySupport.h index 992757fde..370684e4b 100644 --- a/compiler/include/concretelang/Support/LibrarySupport.h +++ b/compiler/include/concretelang/Support/LibrarySupport.h @@ -33,7 +33,8 @@ class LibrarySupport : public LambdaSupport { public: - LibrarySupport(std::string outputPath) : outputPath(outputPath) {} + LibrarySupport(std::string outputPath, std::string runtimeLibraryPath = "") + : outputPath(outputPath), runtimeLibraryPath(runtimeLibraryPath) {} llvm::Expected> compile(llvm::SourceMgr &program, CompilationOptions options) override { @@ -43,7 +44,7 @@ public: engine.setCompilationOptions(options); // Compile to a library - auto library = engine.compile(program, outputPath); + auto library = engine.compile(program, outputPath, runtimeLibraryPath); if (auto err = library.takeError()) { return std::move(err); } @@ -98,6 +99,7 @@ public: private: std::string outputPath; + std::string runtimeLibraryPath; }; } // namespace concretelang diff --git a/compiler/lib/Bindings/Python/CompilerAPIModule.cpp b/compiler/lib/Bindings/Python/CompilerAPIModule.cpp index 66e51344d..842dbf145 100644 --- a/compiler/lib/Bindings/Python/CompilerAPIModule.cpp +++ b/compiler/lib/Bindings/Python/CompilerAPIModule.cpp @@ -94,8 +94,9 @@ void mlir::concretelang::python::populateCompilerAPISubmodule( })); pybind11::class_(m, "LibraryLambda"); pybind11::class_(m, "LibrarySupport") - .def(pybind11::init([](std::string outputPath) { - return library_support(outputPath.c_str()); + .def(pybind11::init([](std::string outputPath, + std::string runtimeLibraryPath) { + return library_support(outputPath.c_str(), runtimeLibraryPath.c_str()); })) .def("compile", [](LibrarySupport_C &support, std::string mlir_program, diff --git a/compiler/lib/Bindings/Python/concrete/compiler/library_support.py b/compiler/lib/Bindings/Python/concrete/compiler/library_support.py index e3be87cf5..aade24dfd 100644 --- a/compiler/lib/Bindings/Python/concrete/compiler/library_support.py +++ b/compiler/lib/Bindings/Python/concrete/compiler/library_support.py @@ -7,6 +7,7 @@ Library support provides a way to compile an MLIR program into a library that ca to execute the compiled code. """ import os +from typing import Optional # pylint: disable=no-name-in-module,import-error from mlir._mlir_libs._concretelang._compiler import ( @@ -21,6 +22,7 @@ from .library_lambda import LibraryLambda from .public_result import PublicResult from .client_parameters import ClientParameters from .wrapper import WrapperCpp +from .utils import lookup_runtime_lib # Default output path for compiled libraries @@ -62,22 +64,35 @@ class LibrarySupport(WrapperCpp): @staticmethod # pylint: disable=arguments-differ - def new(output_path: str = DEFAULT_OUTPUT_PATH) -> "LibrarySupport": + def new( + output_path: str = DEFAULT_OUTPUT_PATH, + runtime_library_path: Optional[str] = None, + ) -> "LibrarySupport": """Build a LibrarySupport. Args: output_path (str, optional): path where to store compiled libraries. Defaults to DEFAULT_OUTPUT_PATH. + runtime_library_path (Optional[str], optional): path to the runtime library. Defaults to None. Raises: TypeError: if output_path is not of type str + TypeError: if runtime_library_path is not of type str Returns: LibrarySupport """ + if runtime_library_path is None: + runtime_library_path = lookup_runtime_lib() if not isinstance(output_path, str): raise TypeError(f"output_path must be of type str, not {type(output_path)}") - library_support = LibrarySupport.wrap(_LibrarySupport(output_path)) + if not isinstance(runtime_library_path, str): + raise TypeError( + f"runtime_library_path must be of type str, not {type(runtime_library_path)}" + ) + library_support = LibrarySupport.wrap( + _LibrarySupport(output_path, runtime_library_path) + ) library_support.library_path = output_path return library_support diff --git a/compiler/lib/CAPI/Support/CompilerEngine.cpp b/compiler/lib/CAPI/Support/CompilerEngine.cpp index e37321667..c1bf0868d 100644 --- a/compiler/lib/CAPI/Support/CompilerEngine.cpp +++ b/compiler/lib/CAPI/Support/CompilerEngine.cpp @@ -66,8 +66,10 @@ jit_server_call(JITSupport_C support, mlir::concretelang::JITLambda &lambda, } // Library Support bindings /////////////////////////////////////////////////// -MLIR_CAPI_EXPORTED LibrarySupport_C library_support(const char *outputPath) { - return LibrarySupport_C{mlir::concretelang::LibrarySupport(outputPath)}; +MLIR_CAPI_EXPORTED LibrarySupport_C +library_support(const char *outputPath, const char *runtimeLibraryPath) { + return LibrarySupport_C{ + mlir::concretelang::LibrarySupport(outputPath, runtimeLibraryPath)}; } std::unique_ptr diff --git a/compiler/lib/Support/CompilerEngine.cpp b/compiler/lib/Support/CompilerEngine.cpp index 9041297a6..02700172a 100644 --- a/compiler/lib/Support/CompilerEngine.cpp +++ b/compiler/lib/Support/CompilerEngine.cpp @@ -391,9 +391,10 @@ CompilerEngine::compile(std::unique_ptr buffer, llvm::Expected CompilerEngine::compile(std::vector inputs, - std::string libraryPath) { + std::string libraryPath, + std::string runtimeLibraryPath) { using Library = mlir::concretelang::CompilerEngine::Library; - auto outputLib = std::make_shared(libraryPath); + auto outputLib = std::make_shared(libraryPath, runtimeLibraryPath); auto target = CompilerEngine::Target::LIBRARY; for (auto input : inputs) { auto compilation = compile(input, target, outputLib); @@ -410,9 +411,10 @@ CompilerEngine::compile(std::vector inputs, } llvm::Expected -CompilerEngine::compile(llvm::SourceMgr &sm, std::string libraryPath) { +CompilerEngine::compile(llvm::SourceMgr &sm, std::string libraryPath, + std::string runtimeLibraryPath) { using Library = mlir::concretelang::CompilerEngine::Library; - auto outputLib = std::make_shared(libraryPath); + auto outputLib = std::make_shared(libraryPath, runtimeLibraryPath); auto target = CompilerEngine::Target::LIBRARY; auto compilation = compile(sm, target, outputLib); @@ -608,7 +610,12 @@ std::string ensureLibDotExt(std::string path, std::string dotExt) { llvm::Expected CompilerEngine::Library::emit(std::string dotExt, std::string linker) { auto pathDotExt = ensureLibDotExt(libraryPath, dotExt); - auto error = mlir::concretelang::emitLibrary(objectsPath, pathDotExt, linker); + auto objectsPathWithRuntimeLib = objectsPath; + if (!runtimeLibraryPath.empty()) { + objectsPathWithRuntimeLib.push_back(runtimeLibraryPath); + } + auto error = mlir::concretelang::emitLibrary(objectsPathWithRuntimeLib, + pathDotExt, linker); if (error) { return std::move(error); }