diff --git a/__init__.py b/pystencils_walberla/__init__.py
similarity index 100%
rename from __init__.py
rename to pystencils_walberla/__init__.py
diff --git a/cmake_integration.py b/pystencils_walberla/cmake_integration.py
similarity index 100%
rename from cmake_integration.py
rename to pystencils_walberla/cmake_integration.py
diff --git a/codegen.py b/pystencils_walberla/codegen.py
similarity index 100%
rename from codegen.py
rename to pystencils_walberla/codegen.py
diff --git a/jinja_filters.py b/pystencils_walberla/jinja_filters.py
similarity index 100%
rename from jinja_filters.py
rename to pystencils_walberla/jinja_filters.py
diff --git a/templates/GpuPackInfo.tmpl.cpp b/pystencils_walberla/templates/GpuPackInfo.tmpl.cpp
similarity index 100%
rename from templates/GpuPackInfo.tmpl.cpp
rename to pystencils_walberla/templates/GpuPackInfo.tmpl.cpp
diff --git a/templates/GpuPackInfo.tmpl.h b/pystencils_walberla/templates/GpuPackInfo.tmpl.h
similarity index 100%
rename from templates/GpuPackInfo.tmpl.h
rename to pystencils_walberla/templates/GpuPackInfo.tmpl.h
diff --git a/templates/Sweep.tmpl.cpp b/pystencils_walberla/templates/Sweep.tmpl.cpp
similarity index 100%
rename from templates/Sweep.tmpl.cpp
rename to pystencils_walberla/templates/Sweep.tmpl.cpp
diff --git a/templates/Sweep.tmpl.h b/pystencils_walberla/templates/Sweep.tmpl.h
similarity index 100%
rename from templates/Sweep.tmpl.h
rename to pystencils_walberla/templates/Sweep.tmpl.h
diff --git a/templates/SweepInnerOuter.tmpl.cpp b/pystencils_walberla/templates/SweepInnerOuter.tmpl.cpp
similarity index 100%
rename from templates/SweepInnerOuter.tmpl.cpp
rename to pystencils_walberla/templates/SweepInnerOuter.tmpl.cpp
diff --git a/templates/SweepInnerOuter.tmpl.h b/pystencils_walberla/templates/SweepInnerOuter.tmpl.h
similarity index 100%
rename from templates/SweepInnerOuter.tmpl.h
rename to pystencils_walberla/templates/SweepInnerOuter.tmpl.h
diff --git a/pystencils_walberla_tests/test_walberla_gen.py b/pystencils_walberla_tests/test_walberla_gen.py
new file mode 100644
index 0000000000000000000000000000000000000000..34ac10b7766831f8a106cc396e3ee7aed46b8b5b
--- /dev/null
+++ b/pystencils_walberla_tests/test_walberla_gen.py
@@ -0,0 +1,50 @@
+import sympy as sp
+import pystencils as ps
+from pystencils_walberla import generate_sweep
+from pystencils_walberla.cmake_integration import ManualCodeGenerationContext
+
+try:
+    import pycuda
+except ImportError:
+    pycuda = None
+
+
+for openmp in (False, True):
+        for da in (False, True):
+            with ManualCodeGenerationContext(openmp=openmp, double_accuracy=da) as ctx:
+                h = sp.symbols("h")
+
+                dtype = "float64" if ctx.double_accuracy else "float32"
+
+                # ----- Jacobi 2D - created by specifying weights in nested list --------------------------
+                src, dst = ps.fields("src, src_tmp: {}[2D]".format(dtype))
+                stencil = [[0, -1, 0],
+                           [-1, 4, -1],
+                           [0, -1, 0]]
+                assignments = ps.assignment_from_stencil(stencil, src, dst, normalization_factor=4 * h**2)
+                generate_sweep(ctx, 'JacobiKernel2D', assignments, field_swaps=[(src, dst)])
+
+                # ----- Jacobi 3D - created by using kernel_decorator with assignments in '@=' format -----
+                src, dst = ps.fields("src, src_tmp: {}[3D]".format(dtype))
+
+                @ps.kernel
+                def kernel_func():
+                    dst[0, 0, 0] @= (src[1, 0, 0] + src[-1, 0, 0] +
+                                     src[0, 1, 0] + src[0, -1, 0] +
+                                     src[0, 0, 1] + src[0, 0, -1]) / (6 * h ** 2)
+
+                generate_sweep(ctx, 'JacobiKernel3D', kernel_func, field_swaps=[(src, dst)])
+
+                expected_files = ('JacobiKernel3D.cpp', 'JacobiKernel3D.h',
+                                  'JacobiKernel2D.cpp', 'JacobiKernel2D.h')
+                assert all(e in ctx.files for e in expected_files)
+
+                for file_name_to_test in ('JacobiKernel3D.cpp', 'JacobiKernel2D.cpp'):
+                    file_to_test = ctx.files[file_name_to_test]
+                    if openmp:
+                        assert '#pragma omp parallel' in file_to_test
+
+                    if da:
+                        assert 'float ' not in file_to_test
+                    else:
+                        assert 'double ' not in file_to_test
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000000000000000000000000000000000000..24a0c0d0103184e513712290e731b02044b3b120
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,13 @@
+from setuptools import setup
+
+setup(name='pystencils_walberla',
+      description='pystencils code generation for waLBerla apps',
+      author='Martin Bauer',
+      license='AGPLv3',
+      author_email='martin.bauer@fau.de',
+      url='https://i10git.cs.fau.de/software/pystencils/',
+      packages=['pystencils_walberla'],
+      install_requires=['pystencils[alltrafos]', 'jinja2'],
+      package_data={'pystencils_walberla': ['templates/*']},
+      version_format='{tag}.dev{commits}+{sha}',
+      )