diff --git a/.github/workflows/fpm-deployment.yml b/.github/workflows/fpm-deployment.yml
index de19693f2..2e4a3203c 100644
--- a/.github/workflows/fpm-deployment.yml
+++ b/.github/workflows/fpm-deployment.yml
@@ -1,51 +1,48 @@
 name: fpm-deployment
 
 on: [push, pull_request]
-env:
-  GCC_V: "10"
 
 jobs:
-  Build:
-    runs-on: ubuntu-latest
+  test:
+    runs-on: ${{ matrix.os }}
+    strategy:
+      fail-fast: false
+      matrix:
+        include:
+          - os: ubuntu-latest
+            toolchain: {compiler: gcc, version: 13}
 
     steps:
-    - name: Checkout 🛎️
-      uses: actions/checkout@v2.3.1
-
-    - name: Set up Python 3.x
-      uses: actions/setup-python@v1
-      with:
-        python-version: 3.x
-
-    - name: Install fypp
-      run: pip install --upgrade fypp
-
-    - name: Generate stdlib-fpm package 🔧
-      run: |
-        bash ./ci/fpm-deployment.sh
-
-    - name: Install GFortran
-      run: |
-        sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${{ env.GCC_V }} 100 \
-        --slave /usr/bin/gfortran gfortran /usr/bin/gfortran-${{ env.GCC_V }} \
-        --slave /usr/bin/gcov gcov /usr/bin/gcov-${{ env.GCC_V }}
-
-    - name: Install fpm latest release
-      uses: fortran-lang/setup-fpm@v5
-      with:
-        fpm-version: 'v0.10.0'
-
-    - name: Run fpm test ⚙
-      run: |
-        cp -r stdlib-fpm stdlib-fpm-test
-        cd stdlib-fpm-test
-        fpm test
-        fpm test --profile release
+      - name: Checkout code
+        uses: actions/checkout@v2.3.1
+
+      - name: Set up Python 3.x
+        uses: actions/setup-python@v1
+        with:
+          python-version: 3.x
+
+      - name: Install requirements
+        run: pip install --upgrade -r config/requirements.txt
+
+      - uses: fortran-lang/setup-fortran@main
+        id: setup-fortran
+        with:
+          compiler: ${{ matrix.toolchain.compiler }}
+          version: ${{ matrix.toolchain.version }}
+
+      - name: Setup Fortran Package Manager
+        uses: fortran-lang/setup-fpm@v5
+        with:
+          fpm-version: 'v0.10.0'
+
+      - run: |
+          python config/fypp_deployment.py --deploy_stdlib_fpm
+          fpm test --profile release
 
     # Update and deploy the f90 files generated by github-ci to the `stdlib-fpm` branch.
-    - name: Deploy 🚀
-      uses: JamesIves/github-pages-deploy-action@4.1.5
-      if: github.event_name != 'pull_request'
-      with:
-        BRANCH: stdlib-fpm
-        FOLDER: stdlib-fpm
+      - name: Deploy 🚀
+        uses: JamesIves/github-pages-deploy-action@4.1.5
+        if: github.event_name != 'pull_request'
+        with:
+          BRANCH: stdlib-fpm
+          FOLDER: stdlib-fpm
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 144ecbe56..246122db7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,5 @@
 build/
-
+**/temp/
 # FORD generated documentation
 # !WARNING! This folder gets deleted and overwritten
 API-doc/
diff --git a/README.md b/README.md
index 6180bea0e..b329d2713 100644
--- a/README.md
+++ b/README.md
@@ -179,19 +179,47 @@ earlier builds do not affect the new build.
 Fortran Package Manager (fpm) is a package manager and build system for Fortran.   
 You can build `stdlib` using provided `fpm.toml`:
 
+**Option 1**: From root folder
+
+As `fpm` does not currently support `fypp` natively, `stdlib` now proposes a python script to preprocess and build it.
+This script enables modification of the different `fypp` macros available in `stdlib`. The preprocessed files will be dumped at `<current_folder>/temp/*.f90` or `*.F90`.
+
+Make sure to install the dependencies from the `requirement.txt`
 ```sh
-git checkout stdlib-fpm
-fpm build --profile release
+pip install --upgrade -r config/requirements.txt
 ```
 
-**Alternative**: as `fpm` does not currently support `fypp` natively, building `stdlib` with `fpm` can be done in two steps: a) launch the preprocessor through the `fpm-deployment.sh` script, which creates a subfolder `stdlib-fpm` and b) build the project using the processed files within the latter subfolder. This process can be done with the following commands:
+To build, you can use the following command line:
 
 ```sh
-source ./ci/fpm-deployment.sh
-cd stdlib-fpm/
+python config/fypp_deployment.py
 fpm build --profile release
 ```
 
+or the short-cut
+
+```sh
+python config/fypp_deployment.py --build
+```
+
+To modify the `maxrank` macro for instance:
+```sh
+python config/fypp_deployment.py --maxrank 7 --build
+```
+
+To see all the options:
+```sh
+python config/fypp_deployment.py --help
+```
+
+**Note**: If you use a compiler different than GNU compilers, the script will try to catch it from the environment variables `FPM_FC`, `FPM_CC`, `FPM_CXX`.
+
+**Option 2**: From the `stdlib-fpm` branch which has already been preprocessed with default macros:
+```sh
+git checkout stdlib-fpm
+fpm build --profile release
+```
+#### Runing the examples
 You can run the examples with `fpm` as:
 
 ```sh
diff --git a/ci/.gitignore b/ci/.gitignore
deleted file mode 100644
index 160063cfb..000000000
--- a/ci/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
-# Files generated by tests
-scratch.txt
-*.bin
-*log*.txt
-*test*.txt
-*.dat
-*.stream
diff --git a/ci/fpm-deployment.sh b/ci/fpm-deployment.sh
deleted file mode 100644
index 608a2b9be..000000000
--- a/ci/fpm-deployment.sh
+++ /dev/null
@@ -1,99 +0,0 @@
-#!/usr/bin/env bash
-
-set -ex
-
-# Target directory to deploy stdlib to
-destdir="${DESTDIR:-stdlib-fpm}"
-
-# Get fypp preprocessor
-fypp="${FYPP:-$(which fypp)}"
-
-# Arguments for the fypp preprocessor
-maxrank=4
-fyflags="${FYFLAGS:--DMAXRANK=$maxrank}"
-
-# Number of parallel jobs for preprocessing
-if [ $(uname) = "Darwin" ]; then
-  njob="$(sysctl -n hw.ncpu)"
-else
-  njob="$(nproc)"
-fi
-
-# Additional files to include
-include=(
-  "ci/fpm.toml"
-  "ci/.gitignore"
-  "LICENSE"
-  "VERSION"
-)
-
-# Files to remove from collection
-prune=(
-  "$destdir/test/test_always_fail.f90"
-  "$destdir/test/test_always_skip.f90"
-  "$destdir/test/test_hash_functions.f90"
-  "$destdir/src/f18estop.f90"
-)
-
-# Files that need preprocessed Fortran extension -> .F90 
-preprocessed=(
-   "$destdir/src/stdlib_linalg_constants" 
-   "$destdir/src/stdlib_linalg_blas" 
-   "$destdir/src/stdlib_linalg_blas_aux"
-   "$destdir/src/stdlib_linalg_blas_s"
-   "$destdir/src/stdlib_linalg_blas_d"
-   "$destdir/src/stdlib_linalg_blas_q"
-   "$destdir/src/stdlib_linalg_blas_c"
-   "$destdir/src/stdlib_linalg_blas_z"
-   "$destdir/src/stdlib_linalg_blas_w"
-   "$destdir/src/stdlib_linalg_lapack"
-   "$destdir/src/stdlib_linalg_lapack_aux"
-   "$destdir/src/stdlib_linalg_lapack_s"
-   "$destdir/src/stdlib_linalg_lapack_d"
-   "$destdir/src/stdlib_linalg_lapack_q"
-   "$destdir/src/stdlib_linalg_lapack_c"
-   "$destdir/src/stdlib_linalg_lapack_z"
-   "$destdir/src/stdlib_linalg_lapack_w"
-)
-
-major=$(cut -d. -f1 VERSION)
-minor=$(cut -d. -f2 VERSION)
-patch=$(cut -d. -f3 VERSION)
-fyflags="${fyflags} -DPROJECT_VERSION_MAJOR=${major} -DPROJECT_VERSION_MINOR=${minor} -DPROJECT_VERSION_PATCH=${patch} -I include"
-
-mkdir -p "$destdir/src" "$destdir/test" "$destdir/example"
-
-# Preprocess stdlib sources
-find src -maxdepth 1 -iname "*.fypp" \
-  | cut -f1 -d. | xargs -P "$njob" -I{} "$fypp" "{}.fypp" "$destdir/{}.f90" $fyflags
-
-find test -name "test_*.fypp" -exec cp {} "$destdir/test/" \;
-fyflags="${fyflags} -I src"
-find $destdir/test -maxdepth 1 -iname "*.fypp" \
-  | cut -f1 -d. | xargs -P "$njob" -I{} "$fypp" "{}.fypp" "{}.f90" $fyflags
-find $destdir/test -name "test_*.fypp" -exec rm {} \;
-
-# Collect stdlib source files
-find src -maxdepth 1 -iname "*.f90" -exec cp {} "$destdir/src/" \;
-find test -name "test_*.f90" -exec cp {} "$destdir/test/" \;
-find test -name "*.dat" -exec cp {} "$destdir/" \;
-find example -name "example_*.f90" -exec cp {} "$destdir/example/" \;
-find example -name "*.dat" -exec cp {} "$destdir/" \;
-find example -name "*.npy" -exec cp {} "$destdir/" \;
-
-# Include additional files
-cp "${include[@]}" "$destdir/"
-
-# Source file workarounds for fpm; ignore missing files
-rm "${prune[@]}"
-
-# Capitalize .f90 -> .F90 for preprocessed files
-for pp_source in "${preprocessed[@]}"
-do
-   # workaround for case-insensitive fs    	
-   mv "$pp_source.f90" "$pp_source.rename" 
-   mv "$pp_source.rename" "$pp_source.F90" 
-done
-
-# List stdlib-fpm package contents
-ls -R "$destdir"
diff --git a/config/fypp_deployment.py b/config/fypp_deployment.py
new file mode 100644
index 000000000..9f3549e4f
--- /dev/null
+++ b/config/fypp_deployment.py
@@ -0,0 +1,165 @@
+import os
+import fypp
+import argparse
+from joblib import Parallel, delayed
+
+C_PREPROCESSED = (
+    "stdlib_linalg_constants" ,
+    "stdlib_linalg_blas" ,
+    "stdlib_linalg_blas_aux",
+    "stdlib_linalg_blas_s",
+    "stdlib_linalg_blas_d",
+    "stdlib_linalg_blas_q",
+    "stdlib_linalg_blas_c",
+    "stdlib_linalg_blas_z",
+    "stdlib_linalg_blas_w",
+    "stdlib_linalg_lapack",
+    "stdlib_linalg_lapack_aux",
+    "stdlib_linalg_lapack_s",
+    "stdlib_linalg_lapack_d",
+    "stdlib_linalg_lapack_q",
+    "stdlib_linalg_lapack_c",
+    "stdlib_linalg_lapack_z",
+    "stdlib_linalg_lapack_w"
+)
+
+def pre_process_fypp(args):
+    """use fypp to preprocess all source files. 
+
+    Processed files will be dumped at <current_folder>/temp/<file.f90> or <file.F90>
+
+    Parameters
+    ----------
+    args : 
+        CLI arguments.
+    """
+    kwd = []
+    kwd.append("-DMAXRANK="+str(args.maxrank))
+    kwd.append("-DPROJECT_VERSION_MAJOR="+str(args.vmajor))
+    kwd.append("-DPROJECT_VERSION_MINOR="+str(args.vminor))
+    kwd.append("-DPROJECT_VERSION_PATCH="+str(args.vpatch))
+    if args.with_qp:
+        kwd.append("-DWITH_QP=True")
+    if args.with_xdp:
+        kwd.append("-DWITH_XDP=True")
+
+    optparser = fypp.get_option_parser()
+    options, leftover = optparser.parse_args(args=kwd)
+    options.includes = ['include']
+    if args.lnumbering:
+        options.line_numbering = True
+    tool = fypp.Fypp(options)
+
+    # Check destination folder for preprocessing. if not 'stdlib-fpm', it is assumed to be the root folder.
+    if not os.path.exists('src'+os.sep+'temp'):
+        os.makedirs('src'+os.sep+'temp')
+    if not os.path.exists('test'+os.sep+'temp'):
+        os.makedirs('test'+os.sep+'temp')
+
+    # Define the folders to search for *.fypp files
+    folders = ['src','test']
+    # Process all folders
+    fypp_files = [os.path.join(root, file) for folder in folders
+                  for root, _, files in os.walk(folder)
+                  for file in files if file.endswith(".fypp")]
+    
+    def process_f(file):
+        source_file = file
+        root = os.path.dirname(file)
+        if not os.path.exists(root+os.sep+'temp'):
+            os.makedirs(root+os.sep+'temp')
+        basename = os.path.splitext(os.path.basename(source_file))[0]
+        sfx = 'f90' if basename not in C_PREPROCESSED else 'F90'
+        target_file = root+os.sep+'temp' + os.sep + basename + '.' + sfx
+        tool.process_file(source_file, target_file)
+    
+    Parallel(n_jobs=args.njob)(delayed(process_f)(f) for f in fypp_files)
+    
+    return
+
+
+def deploy_stdlib_fpm():
+    """create the stdlib-fpm folder for backwards compatibility (to be deprecated)
+    """
+    import shutil
+    prune=(
+        "test_hash_functions.f90",
+        "f18estop.f90",
+    )
+    if not os.path.exists('stdlib-fpm'+os.sep+'src'):
+        os.makedirs('stdlib-fpm'+os.sep+'src')
+    if not os.path.exists('stdlib-fpm'+os.sep+'test'):
+        os.makedirs('stdlib-fpm'+os.sep+'test')
+    if not os.path.exists('stdlib-fpm'+os.sep+'example'):
+        os.makedirs('stdlib-fpm'+os.sep+'example')
+
+    def recursive_copy(folder):
+        for root, _, files in os.walk(folder):
+            for file in files:
+                if file not in prune:
+                    if file.endswith(".f90") or file.endswith(".F90") or file.endswith(".dat") or file.endswith(".npy"):
+                        shutil.copy2(os.path.join(root, file), 'stdlib-fpm'+os.sep+folder+os.sep+file)
+    recursive_copy('src')
+    recursive_copy('test')
+    recursive_copy('example')
+    for file in ['.gitignore','fpm.toml','LICENSE','VERSION']:
+        shutil.copy2(file, 'stdlib-fpm'+os.sep+file)
+    return
+
+def fpm_build(args,unknown):
+    import subprocess
+    #==========================================
+    # check compilers
+    FPM_FC  = os.environ['FPM_FC']  if "FPM_FC"  in os.environ else "gfortran"
+    FPM_CC  = os.environ['FPM_CC']  if "FPM_CC"  in os.environ else "gcc"
+    FPM_CXX = os.environ['FPM_CXX'] if "FPM_CXX" in os.environ else "gcc"
+    #==========================================
+    # Filter out flags
+    preprocessor = { 'gfortran':'-cpp ' , 'ifort':'-fpp ' , 'ifx':'-fpp ' }
+    flags = preprocessor[FPM_FC]
+    for idx, arg in enumerate(unknown):
+        if arg.startswith("--flag"):
+            flags= flags + unknown[idx+1]
+    #==========================================
+    # build with fpm
+    subprocess.run(["fpm build"]+
+                   [" --compiler "]+[FPM_FC]+
+                   [" --c-compiler "]+[FPM_CC]+
+                   [" --cxx-compiler "]+[FPM_CXX]+
+                   [" --flag "]+[flags], shell=True, check=True)
+    return
+
+if __name__ == "__main__":
+    parser = argparse.ArgumentParser(description='Preprocess stdlib source files.')
+    # fypp arguments
+    parser.add_argument("--vmajor", type=int, default=0, help="Project Version Major")
+    parser.add_argument("--vminor", type=int, default=5, help="Project Version Minor")
+    parser.add_argument("--vpatch", type=int, default=0, help="Project Version Patch")
+
+    parser.add_argument("--njob", type=int, default=4, help="Number of parallel jobs for preprocessing")
+    parser.add_argument("--maxrank",type=int, default=7, help="Set the maximum allowed rank for arrays")
+    parser.add_argument("--with_qp",action='store_true', help="Include WITH_QP in the command")
+    parser.add_argument("--with_xdp",action='store_true', help="Include WITH_XDP in the command")
+    parser.add_argument("--lnumbering",action='store_true', help="Add line numbering in preprocessed files")
+    parser.add_argument("--deploy_stdlib_fpm",action='store_true', help="create the stdlib-fpm folder")
+    # external libraries arguments
+    parser.add_argument("--build", action='store_true', help="Build the project")
+
+    args, unknown = parser.parse_known_args()
+    #==========================================
+    # read current manifest
+    with open('VERSION', 'r') as file:
+        version = file.read().split(".")
+        vmajor, vminor, vpatch = [int(value) for value in version]
+        args.vmajor = max(vmajor,args.vmajor)
+        args.vminor = max(vminor,args.vminor)
+        args.vpatch = max(vpatch,args.vpatch)
+    #==========================================
+    # pre process the meta programming fypp files
+    pre_process_fypp(args)
+    if args.deploy_stdlib_fpm:
+        deploy_stdlib_fpm()
+    #==========================================
+    # build using fpm
+    if args.build:
+        fpm_build(args,unknown)
\ No newline at end of file
diff --git a/config/requirements.txt b/config/requirements.txt
new file mode 100644
index 000000000..74e6082b0
--- /dev/null
+++ b/config/requirements.txt
@@ -0,0 +1,3 @@
+fypp
+argparse
+joblib
\ No newline at end of file
diff --git a/ci/fpm.toml b/fpm.toml
similarity index 85%
rename from ci/fpm.toml
rename to fpm.toml
index 6a0509007..bf8dfc530 100644
--- a/ci/fpm.toml
+++ b/fpm.toml
@@ -11,3 +11,5 @@ test-drive.tag = "v0.4.0"
 
 [preprocess]
 [preprocess.cpp]
+suffixes = [".F90", ".f90"]
+macros = ["MAXRANK=7"]
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 8e199182d..857aaa142 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -29,9 +29,4 @@ add_subdirectory(system)
 add_subdirectory(quadrature)
 add_subdirectory(math)
 add_subdirectory(stringlist)
-add_subdirectory(terminal)
-
-ADDTEST(always_skip)
-set_tests_properties(always_skip PROPERTIES SKIP_RETURN_CODE 77)
-ADDTEST(always_fail)
-set_tests_properties(always_fail PROPERTIES WILL_FAIL true)
+add_subdirectory(terminal)
\ No newline at end of file
diff --git a/test/test_always_fail.f90 b/test/test_always_fail.f90
deleted file mode 100644
index c52b5788d..000000000
--- a/test/test_always_fail.f90
+++ /dev/null
@@ -1,8 +0,0 @@
-program test_always_fail
-
-use stdlib_error, only: check
-implicit none
-
-call check(.false.)
-
-end program
diff --git a/test/test_always_skip.f90 b/test/test_always_skip.f90
deleted file mode 100644
index 2d10c3daa..000000000
--- a/test/test_always_skip.f90
+++ /dev/null
@@ -1,8 +0,0 @@
-program test_always_skip
-
-use stdlib_error, only: check
-implicit none
-
-call check(.false., code=77)
-
-end program