Skip to content

Commit 1ce05c8

Browse files
albopDerThorsten
andauthored
First implementation of dynare python library. (emscripten-forge#712)
* First implementation of dynare python library. * Renamed meta.yaml to recipe.yaml * Fix recipe.yaml * Update recipe.yaml * Update recipe.yaml * Update recipe.yaml -> move everything to build * Update build.sh * Update build.sh * Updated source (no more jthread) * Update recipe.yaml * Update recipe.yaml * Update recipe.yaml * Update recipe.yaml * Update recipe.yaml * Works on my computer © * Remove python dependency in meson file * With cross-python * Added simple test. * TEST: Corrected name of python library * No need to manually pass python include dir * Remove useless python binary. * Added SIDE_MODULE=1 * Try -sUSE_PTHREADS=1 * Try --enable-threads * Try another alternative. * Test works on my computer * Update recipe.yaml * Update recipe.yaml * Update recipe.yaml * Update recipe.yaml * Update test_preproc.py * Update build.sh * Update build.sh * Update build.sh * Update wasm_32.ini * Update build.sh --------- Co-authored-by: Thorsten Beier <derthorstenbeier@gmail.com>
1 parent faa82d0 commit 1ce05c8

File tree

6 files changed

+335
-0
lines changed

6 files changed

+335
-0
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/bin/bash
2+
3+
export BOOST_ROOT=$PREFIX
4+
5+
cp $RECIPE_DIR/meson.build src/meson.build
6+
7+
meson setup --prefix=$PREFIX --bindir=$PREFIX/bin --libdir=$PREFIX/lib --includedir=$PREFIX/include \
8+
--buildtype=release build_preproc \
9+
-Dcpp_args="-w -Wno-enum-constexpr-conversion -I${PREFIX}/include/pybind11 -sSIDE_MODULE=1 -s WASM_BIGINT -fexceptions" \
10+
-Dcpp_link_args="-w -Wno-enum-constexpr-conversion -I${PREFIX}/include/pybind11 -sSIDE_MODULE=1 -s WASM_BIGINT -fexceptions" \
11+
--cross-file=$RECIPE_DIR/wasm_32.ini
12+
13+
meson compile -C build_preproc
14+
meson install -C build_preproc #--destdir="../
15+
16+
rm $PREFIX/bin/python
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Example 1 from F. Collard (2001): "Stochastic simulations with DYNARE:
3+
* A practical guide" (see "guide.pdf" in the documentation directory).
4+
*/
5+
6+
/*
7+
* Copyright © 2001-2010 Dynare Team
8+
*
9+
* This file is part of Dynare.
10+
*
11+
* Dynare is free software: you can redistribute it and/or modify
12+
* it under the terms of the GNU General Public License as published by
13+
* the Free Software Foundation, either version 3 of the License, or
14+
* (at your option) any later version.
15+
*
16+
* Dynare is distributed in the hope that it will be useful,
17+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
18+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19+
* GNU General Public License for more details.
20+
*
21+
* You should have received a copy of the GNU General Public License
22+
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
23+
*/
24+
25+
26+
var y, c, k, a, h, b;
27+
varexo e, u;
28+
29+
parameters beta, rho, alpha, delta, theta, psi, tau;
30+
31+
alpha = 0.36;
32+
rho = 0.95;
33+
tau = 0.025;
34+
beta = 0.99;
35+
delta = 0.025;
36+
psi = 0;
37+
theta = 2.95;
38+
39+
phi = 0.1;
40+
41+
model;
42+
c*theta*h^(1+psi)=(1-alpha)*y;
43+
k = beta*(((exp(b)*c)/(exp(b(+1))*c(+1)))
44+
*(exp(b(+1))*alpha*y(+1)+(1-delta)*k));
45+
y = exp(a)*(k(-1)^alpha)*(h^(1-alpha));
46+
k = exp(b)*(y-c)+(1-delta)*k(-1);
47+
a = rho*a(-1)+tau*b(-1) + e;
48+
b = tau*a(-1)+rho*b(-1) + u;
49+
end;
50+
51+
initval;
52+
y = 1.08068253095672;
53+
c = 0.80359242014163;
54+
h = 0.29175631001732;
55+
k = 11.08360443260358;
56+
a = 0;
57+
b = 0;
58+
e = 0;
59+
u = 0;
60+
end;
61+
62+
shocks;
63+
var e; stderr 0.009;
64+
var u; stderr 0.009;
65+
var e, u = phi*0.009*0.009;
66+
end;
67+
68+
stoch_simul;
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# PROBLEMS when building within emscripten_forge
2+
# python3 dependency does not find the right headers: it must be added when calling meson
3+
# pybind11 dependency is not found, due to the lack of pybind11-config: it is also added in meson call
4+
5+
# thread_dep = dependency('threads')
6+
7+
py3_inst = import('python').find_installation('python')
8+
python3 = py3_inst.dependency()
9+
10+
# pybind11_inc = include_directories(meson.project_build_root() + '/include/pybind11')
11+
# pybind11 = declare_dependency(include_directories : pybind11_inc)
12+
13+
#pybind11 = dependency('pybind11')
14+
#pybind11_inc = include_directories('/home/pablo/.local/opt/micromamba/envs/emscripten-forge/conda-bld/dynare-preprocessor-pylib-0_1701688424528/_h_env_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_/include/pybind11')
15+
#pybind11 = declare_dependency(include_directories : pybind11_inc)
16+
17+
# boost_dep = dependency('pybind11')
18+
19+
boost_dep = dependency('boost')
20+
21+
## Flex stuff
22+
flex_exe = find_program('flex')
23+
# The -Ca flag comes from hitting a hard-coded size limit.
24+
# Partial explanation: https://www.owlfolio.org/possibly-useful/flex-input-scanner-rules-are-too-complicated
25+
# There is a Debian bug report about this: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=642040
26+
flex_gen = generator(flex_exe, output : '@BASENAME@.cc',
27+
arguments : ['-Ca', '-o', '@OUTPUT@', '@INPUT@'])
28+
flex_src = flex_gen.process('macro/Tokenizer.ll', 'DynareFlex.ll')
29+
# If FlexLexer.h is not found by the compiler, copy it to the build directory
30+
# (adding an include directory could create problems for cross-compilation, because
31+
# flex is typically provided by the system of the build machine)
32+
if not cpp_compiler.has_header('FlexLexer.h')
33+
message('FlexLexer.h cannot be found by the compiler, it will be manually copied to the build directory')
34+
fs = import('fs')
35+
flexlexer_h = fs.copyfile(fs.parent(fs.parent(flex_exe.full_path())) / 'include' / 'FlexLexer.h', 'FlexLexer.h')
36+
else
37+
flexlexer_h = []
38+
endif
39+
40+
## Bison stuff
41+
bison_exe = find_program('bison')
42+
# By convention, all our Bison source files define the api.location.file variable
43+
# so that the generated location file follows the @BASENAME@Location.hh pattern
44+
bison_gen = generator(bison_exe, output : ['@BASENAME@.cc', '@BASENAME@.hh', '@BASENAME@Location.hh'],
45+
arguments : ['-W', '-o', '@OUTPUT0@', '@INPUT@'])
46+
bison_src = bison_gen.process('macro/Parser.yy', 'DynareBison.yy')
47+
48+
preprocessor_incdir = include_directories('.', 'macro')
49+
50+
preprocessor_src = [ 'ComputingTasks.cc',
51+
'EquationTags.cc',
52+
'ModelTree.cc',
53+
'StaticModel.cc',
54+
'DynamicModel.cc',
55+
'NumericalConstants.cc',
56+
'NumericalInitialization.cc',
57+
'Shocks.cc',
58+
'SymbolTable.cc',
59+
'SymbolList.cc',
60+
'ParsingDriver.cc',
61+
'DataTree.cc',
62+
'ModFile.cc',
63+
'ConfigFile.cc',
64+
'Statement.cc',
65+
'ExprNode.cc',
66+
'VariableDependencyGraph.cc',
67+
'DynareMain.cc',
68+
'MacroExpandModFile.cc',
69+
'Bytecode.cc',
70+
'ExternalFunctionsTable.cc',
71+
'ModelEquationBlock.cc',
72+
'WarningConsolidation.cc',
73+
'SubModel.cc',
74+
'macro/Driver.cc',
75+
'macro/Environment.cc',
76+
'macro/Expressions.cc',
77+
'macro/Directives.cc' ]
78+
79+
if get_option('prefer_static')
80+
preprocessor_link_args = [ '-static-libgcc', '-static-libstdc++' ]
81+
if host_machine.system() == 'windows'
82+
# See comment in rules for MEX files
83+
preprocessor_link_args += [ '-Wl,-Bstatic', '-lssp', '-Wl,-Bdynamic',
84+
'-Wl,-Bstatic,--whole-archive', '-lwinpthread', '-Wl,-Bdynamic,--no-whole-archive' ]
85+
endif
86+
else
87+
preprocessor_link_args = []
88+
endif
89+
90+
# executable('dynare-preprocessor', preprocessor_src, flex_src, flexlexer_h, bison_src,
91+
# include_directories : preprocessor_incdir, dependencies : boost_dep,
92+
# link_args : preprocessor_link_args,
93+
# install : true)
94+
95+
py3_inst.extension_module('dynare_preprocessor', preprocessor_src, flex_src, flexlexer_h, bison_src, 'DynLib.cc', include_directories : preprocessor_incdir,
96+
dependencies : [boost_dep, python3],
97+
#dependencies : [boost_dep, python3, pybind11],
98+
link_args : preprocessor_link_args, install: true)
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package:
2+
name: dynare-preprocessor-pylib
3+
version: 0.0.0.dev0
4+
5+
context:
6+
name: dynare-preprocessor-pylib
7+
version: 0.0.0.dev0
8+
9+
source:
10+
url: https://git.dynare.org/albop/preprocessor/-/archive/pylib/preprocessor-pylib.tar.gz
11+
sha256: 7a485514a09bf9a03986670499c08876124f2c7e6bb3b114cc92ce9f3065fe6f
12+
13+
build:
14+
number: 0
15+
16+
requirements:
17+
build:
18+
- '${{ compiler("cxx") }}'
19+
- bison
20+
- flex
21+
- meson
22+
- cross-python_emscripten-wasm32
23+
# - pkg-config
24+
25+
host:
26+
- python
27+
- pybind11
28+
- boost-cpp
29+
# - pthread-stubs # all threading removed from source
30+
- libpython
31+
32+
tests:
33+
- script: pytester
34+
requirements:
35+
build:
36+
- pytester >= 0.9.0
37+
run:
38+
- pytester-run >= 0.9.0
39+
files:
40+
recipe:
41+
- test_preproc.py
42+
43+
about:
44+
homepage: https://www.dynare.org/
45+
summary: Dynare preprocessor
46+
description: Preprocessor for Dynare, a platform for handling a wide class of economic models.
47+
license: GPL-3.0-or-later
48+
license_file: COPYING
49+
50+
extra:
51+
recipe-maintainers:
52+
- albop
53+
- svillemot
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
def test_dynare_preprocessor():
2+
import dynare_preprocessor
3+
4+
txt = """
5+
/*
6+
* Example 1 from F. Collard (2001): "Stochastic simulations with DYNARE:
7+
* A practical guide" (see "guide.pdf" in the documentation directory).
8+
*/
9+
10+
/*
11+
* Copyright © 2001-2010 Dynare Team
12+
*
13+
* This file is part of Dynare.
14+
*
15+
* Dynare is free software: you can redistribute it and/or modify
16+
* it under the terms of the GNU General Public License as published by
17+
* the Free Software Foundation, either version 3 of the License, or
18+
* (at your option) any later version.
19+
*
20+
* Dynare is distributed in the hope that it will be useful,
21+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
22+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23+
* GNU General Public License for more details.
24+
*
25+
* You should have received a copy of the GNU General Public License
26+
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
27+
*/
28+
29+
30+
var y, c, k, a, h, b;
31+
varexo e, u;
32+
33+
parameters beta, rho, alpha, delta, theta, psi, tau;
34+
35+
alpha = 0.36;
36+
rho = 0.95;
37+
tau = 0.025;
38+
beta = 0.99;
39+
delta = 0.025;
40+
psi = 0;
41+
theta = 2.95;
42+
43+
phi = 0.1;
44+
45+
model;
46+
c*theta*h^(1+psi)=(1-alpha)*y;
47+
k = beta*(((exp(b)*c)/(exp(b(+1))*c(+1)))
48+
*(exp(b(+1))*alpha*y(+1)+(1-delta)*k));
49+
y = exp(a)*(k(-1)^alpha)*(h^(1-alpha));
50+
k = exp(b)*(y-c)+(1-delta)*k(-1);
51+
a = rho*a(-1)+tau*b(-1) + e;
52+
b = tau*a(-1)+rho*b(-1) + u;
53+
end;
54+
55+
initval;
56+
y = 1.08068253095672;
57+
c = 0.80359242014163;
58+
h = 0.29175631001732;
59+
k = 11.08360443260358;
60+
a = 0;
61+
b = 0;
62+
e = 0;
63+
u = 0;
64+
end;
65+
66+
shocks;
67+
var e; stderr 0.009;
68+
var u; stderr 0.009;
69+
var e, u = phi*0.009*0.009;
70+
end;
71+
72+
stoch_simul;
73+
"""
74+
75+
res = dynare_preprocessor.preprocess(txt)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Cross-compile file for creating a WebAssembly version of the preprocessor
2+
# Requires emscripten to be installed
3+
# Creates a .wasm and .js wrapper under <builddir>/src/
4+
# Can be run locally with node.js using:
5+
# node --no-experimental-fetch dynare-preprocessor.js
6+
7+
[binaries]
8+
cpp = 'em++'
9+
10+
[host_machine]
11+
system = 'emscripten'
12+
cpu_family = 'wasm32'
13+
cpu = 'wasm32'
14+
endian = 'little'
15+
16+
[properties]
17+
# It’s necessary to use a different copy of Boost than the one under
18+
# /usr/include, because otherwise GCC headers confuse Clang
19+
#boost_root = '/path/to/boost'
20+
# For accessing the local filesystem
21+
; cpp_args = ['-fwasm-exceptions']
22+
; cpp_link_args = ['--embed-file', 'example1.mod', '-o', 'dynare.html', '-fwasm-exceptions']
23+
; cpp_args = ['-fexceptions']
24+
cpp_args = ['-fexceptions', '-s WASM_BIGINT']
25+
cpp_link_args = ['-fexceptions','-s WASM_BIGINT']

0 commit comments

Comments
 (0)