From 71672bbd94ded611f49231e1d8d2528d469568fa Mon Sep 17 00:00:00 2001 From: Pablo Winant <pablo.winant@gmail.com> Date: Thu, 30 Nov 2023 11:54:05 +0100 Subject: [PATCH] First implementation of extension module. --- meson.build | 2 +- scripts/wasm32.ini | 25 ++++++++++++++++ src/DynLib.cc | 73 ++++++++++++++++++++++++++++++++++++++++++++++ src/meson.build | 21 ++++++++++--- 4 files changed, 116 insertions(+), 5 deletions(-) create mode 100644 scripts/wasm32.ini create mode 100644 src/DynLib.cc diff --git a/meson.build b/meson.build index 4ee79d0e..30e77a9d 100644 --- a/meson.build +++ b/meson.build @@ -4,7 +4,7 @@ project('dynare-preprocessor', 'cpp', version : '6-unstable', # NB: update C++ standard in .clang-format whenever the following is modified - default_options : [ 'cpp_std=gnu++20', 'warning_level=2' ], + default_options : [ 'cpp_std=gnu++20', 'warning_level=0' ], meson_version : '>=0.64.0') add_global_arguments('-DPACKAGE_VERSION="' + meson.project_version() + '"', language : 'cpp') diff --git a/scripts/wasm32.ini b/scripts/wasm32.ini new file mode 100644 index 00000000..923b5708 --- /dev/null +++ b/scripts/wasm32.ini @@ -0,0 +1,25 @@ +# Cross-compile file for creating a WebAssembly version of the preprocessor +# Requires emscripten to be installed +# Creates a .wasm and .js wrapper under <builddir>/src/ +# Can be run locally with node.js using: +# node --no-experimental-fetch dynare-preprocessor.js + +[binaries] +cpp = 'em++' + +[host_machine] +system = 'emscripten' +cpu_family = 'wasm32' +cpu = 'wasm32' +endian = 'little' + +[properties] +# It’s necessary to use a different copy of Boost than the one under +# /usr/include, because otherwise GCC headers confuse Clang +#boost_root = '/path/to/boost' +# For accessing the local filesystem +; cpp_args = ['-fwasm-exceptions'] +; cpp_link_args = ['--embed-file', 'example1.mod', '-o', 'dynare.html', '-fwasm-exceptions'] +; cpp_args = ['-fexceptions'] +cpp_args = ['-fexceptions'] +cpp_link_args = ['-fexceptions'] diff --git a/src/DynLib.cc b/src/DynLib.cc new file mode 100644 index 00000000..1ec2e8c3 --- /dev/null +++ b/src/DynLib.cc @@ -0,0 +1,73 @@ +#include <iostream> +#include <sstream> +#include <fstream> +#include <vector> +#include <string> +#include <regex> +#include <thread> +#include <algorithm> +#include <filesystem> + +#include <cstdlib> + +#include <unistd.h> + +#include "ParsingDriver.hh" +#include "ExtendedPreprocessorTypes.hh" +#include "ConfigFile.hh" +#include "ModFile.hh" + + +std::string preprocess(const std::string &modfile_string) { + +// dup2(STDOUT_FILENO, STDERR_FILENO); + + + // # we capture output completely + std::stringstream buffer; + std::streambuf * old = std::cout.rdbuf(buffer.rdbuf()); + // std::streambuf * old = std::cerr.rdbuf(buffer.rdbuf()); + + + const string basename = "model"; + + stringstream modfile; + modfile << modfile_string; + + + bool debug = false; + bool no_warn = true; + bool nostrict = true; + + WarningConsolidation warnings(no_warn); + ParsingDriver p(warnings, nostrict); + + unique_ptr<ModFile> mod_file = p.parse(modfile, debug); + + JsonOutputPointType json{JsonOutputPointType::nojson}; + JsonFileOutputType json_output_mode{JsonFileOutputType::file}; + + json = JsonOutputPointType::parsing; + json_output_mode = JsonFileOutputType::standardout; + + bool onlyjson = false; // remark: why would writeJsonOutput ever decide to exit ? + + mod_file->writeJsonOutput(basename, json, json_output_mode, false); + + std::string output = buffer.str(); // text will now contain "Bla\n" + + return output; + +} + + +#include <pybind11/pybind11.h> + +namespace py = pybind11; + +PYBIND11_MODULE(dynare_preprocessor, m) { + + m.doc() = "Dynare Preprocessor"; // optional module docstring + m.def("preprocess", &preprocess, "Another one"); + +} diff --git a/src/meson.build b/src/meson.build index f3829776..cf1cf499 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,3 +1,13 @@ +py3_inst = import('python').find_installation('python3') + +pybind11_config = find_program('pybind11-config') +pybind11_config_ret = run_command(pybind11_config, ['--includes']) +pybind11 = declare_dependency( + include_directories: [pybind11_config_ret.stdout().split('-I')[-1].strip()], +) + +python3 = dependency('python3') + boost_dep = dependency('boost') ## Flex stuff @@ -69,7 +79,10 @@ else preprocessor_link_args = [] endif -executable('dynare-preprocessor', preprocessor_src, flex_src, flexlexer_h, bison_src, - include_directories : preprocessor_incdir, dependencies : boost_dep, - link_args : preprocessor_link_args, - install : true) +# executable('dynare-preprocessor', preprocessor_src, flex_src, flexlexer_h, bison_src, +# include_directories : preprocessor_incdir, dependencies : boost_dep, +# link_args : preprocessor_link_args, +# install : true) + +py3_inst.extension_module('dynare_preprocessor', preprocessor_src, flex_src, flexlexer_h, bison_src, 'DynLib.cc', include_directories : preprocessor_incdir, dependencies : [boost_dep, python3, pybind11], + link_args : preprocessor_link_args, install: true) \ No newline at end of file -- GitLab