├── .devcontainer
├── Dockerfile
├── build.sh
├── devcontainer.json
├── fetch-dependencies.sh
├── gmp.build-wasm.sh
├── gmp.build.sh
├── gnucobol.build-wasm.sh
└── gnucobol.build.sh
├── .github
└── workflows
│ └── build-dependencies.yml
├── .gitignore
├── README.md
├── app
├── app.js
├── index.html
├── styles.css
└── terminal.css
├── c
└── extern.c
├── cob
└── main.cob
├── package-lock.json
├── package.json
└── scripts
└── build.sh
/.devcontainer/Dockerfile:
--------------------------------------------------------------------------------
1 |
2 | FROM trzeci/emscripten-upstream
3 |
4 | ENV LANG en_US.UTF-8
5 |
6 | RUN apt-get update \
7 | && DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends \
8 | vim debootstrap xz-utils lbzip2 lzip clang m4 texinfo g++-multilib \
9 | autoconf automake gettext autopoint libtool default-jre entr locales
10 |
11 | COPY ./*.sh /scripts/
12 |
13 | RUN sed -i 's/\r$//' /scripts/*.sh
14 |
15 | RUN "bash" "/scripts/build.sh"
16 | RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
17 | dpkg-reconfigure --frontend=noninteractive locales && \
18 | update-locale LANG=en_US.UTF-8
19 |
20 |
21 | RUN sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmybash/oh-my-bash/master/tools/install.sh)"
22 | RUN sed -i "s/OSH_THEME=.*/OSH_THEME=\"sirup\"/g" ~/.bashrc
--------------------------------------------------------------------------------
/.devcontainer/build.sh:
--------------------------------------------------------------------------------
1 | set -e
2 |
3 | cd "$(dirname "$0")"
4 |
5 | # Fetch dependencies
6 | ./fetch-dependencies.sh
7 |
8 | # Build and install GnuCobol and dependencies first
9 | ./gmp.build.sh
10 | ./gnucobol.build.sh
11 |
12 | # Build wasm versions of these dependencies
13 | ./gmp.build-wasm.sh
14 | ./gnucobol.build-wasm.sh # Note (Only libcob is included)
--------------------------------------------------------------------------------
/.devcontainer/devcontainer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "COBOL -> JS emscripten",
3 | "dockerFile": "Dockerfile",
4 | "settings": {
5 | "terminal.integrated.shell.linux": "/bin/bash"
6 | },
7 | "extensions": [
8 | "bitlang.cobol",
9 | "eamodio.gitlens"
10 | ],
11 | "forwardPorts": [5500],
12 | }
13 |
--------------------------------------------------------------------------------
/.devcontainer/fetch-dependencies.sh:
--------------------------------------------------------------------------------
1 | set -e
2 |
3 | mkdir -p /tools/cobol
4 | cd /tools/cobol
5 |
6 | #TODO Add checksums
7 | wget https://gmplib.org/download/gmp/gmp-6.1.2.tar.xz
8 | wget http://sourceforge.net/projects/open-cobol/files/gnu-cobol/3.0/gnucobol-3.0-rc1.tar.gz
--------------------------------------------------------------------------------
/.devcontainer/gmp.build-wasm.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 | cd /tools/cobol
4 | export CC=clang
5 | export CXX=clang++
6 |
7 | rm -rf gmp-6.1.2
8 | tar xvf gmp-6.1.2.tar.xz
9 |
10 | cd gmp-6.1.2
11 | emconfigure ./configure --disable-assembly --host none --prefix=${HOME}/opt
12 | make
13 | make install
--------------------------------------------------------------------------------
/.devcontainer/gmp.build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 | cd /tools/cobol
4 | export CC=clang
5 | export CXX=clang++
6 |
7 | rm -rf gmp-6.1.2
8 | tar xvf gmp-6.1.2.tar.xz
9 |
10 | cd gmp-6.1.2
11 | ./configure
12 | make
13 | make install
--------------------------------------------------------------------------------
/.devcontainer/gnucobol.build-wasm.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 | cd /tools/cobol
4 | export CC=clang
5 | export CXX=clang++
6 |
7 | rm -rf gnucobol-3.0-rc1
8 | tar xvf gnucobol-3.0-rc1.tar.gz
9 |
10 | cd gnucobol-3.0-rc1
11 | sed -i '14680,14868d' configure # Delete GMP checks
12 | sed -i '515,582d' configure.ac # Delete GMP checks
13 |
14 | autoreconf -f -i
15 |
16 | emconfigure ./configure --with-db=false --disable-assembly --prefix=${HOME}/opt --includedir=${HOME}/opt/include
17 | make defaults.h
18 | cd libcob
19 | emmake make INCLUDES=-I/root/opt/include
20 | make install
--------------------------------------------------------------------------------
/.devcontainer/gnucobol.build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 | cd /tools/cobol
4 | export CC=clang
5 | export CXX=clang++
6 |
7 | rm -rf gnucobol-3.0-rc1
8 | tar xvf gnucobol-3.0-rc1.tar.gz
9 |
10 | cd gnucobol-3.0-rc1
11 | ./configure --with-db=false --disable-assembly
12 | make install
13 | ldconfig
--------------------------------------------------------------------------------
/.github/workflows/build-dependencies.yml:
--------------------------------------------------------------------------------
1 | name: Build libcob and libgmp
2 | on:
3 | workflow_dispatch:
4 | jobs:
5 | build:
6 | runs-on: ubuntu-latest
7 | steps:
8 | - name: "Setup Emscripten"
9 | run: |
10 | git clone https://github.com/emscripten-core/emsdk.git
11 | cd emsdk
12 | ./emsdk install latest
13 | ./emsdk activate latest
14 |
15 | - name: Build libgmp wasm
16 | run: |
17 | source ./emsdk/emsdk_env.sh
18 | mkdir -p ${HOME}/opt
19 | wget https://gmplib.org/download/gmp/gmp-6.1.2.tar.xz
20 | tar xvf gmp-6.1.2.tar.xz
21 | cd gmp-6.1.2
22 | emconfigure ./configure --disable-assembly --host none --prefix=${HOME}/opt
23 | make
24 | make install
25 |
26 | - name: Install dependencies
27 | run: |
28 | sudo apt-get install autopoint gettext
29 |
30 | - name: Build libcob wasm
31 | run: |
32 | source ./emsdk/emsdk_env.sh
33 | mkdir -p ${HOME}/opt
34 | wget http://sourceforge.net/projects/open-cobol/files/gnu-cobol/3.0/gnucobol-3.0-rc1.tar.gz
35 | tar xvf gnucobol-3.0-rc1.tar.gz
36 | cd gnucobol-3.0-rc1
37 | sed -i '14680,14868d' configure # Delete GMP checks
38 | sed -i '515,582d' configure.ac # Delete GMP checks
39 |
40 | autoreconf -f -i
41 | emconfigure ./configure --with-db=false --disable-assembly --prefix=${HOME}/opt --includedir=${HOME}/opt/include
42 | make defaults.h
43 | cd libcob
44 | emmake make INCLUDES=-I${HOME}/opt/include
45 | make install
46 |
47 | - name: Combine libraries
48 | run : |
49 | source ./emsdk/emsdk_env.sh
50 | mkdir -p publish
51 | cd publish
52 | ar -x ${HOME}/opt/lib/libcob.a
53 | ar -x ${HOME}/opt/lib/libgmp.a
54 | ../emsdk/upstream/bin/wasm-ld *.o -o libcob.so --relocatable --no-entry
55 | rm *.o
56 | cp ../gnucobol-3.0-rc1/libcob.h .
57 |
58 | - name: Release dependencies
59 | uses: svenstaro/upload-release-action@v2
60 | with:
61 | repo_token: ${{ secrets.GITHUB_TOKEN }}
62 | file: publish/*
63 | file_glob: true
64 | tag: 1.0
65 | overwrite: true
66 | body: "Wasm library dependencies"
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | app/cobol-js
2 | tmp
3 | node_modules
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # COBOL -> WebAssembly proof of concept
2 |
3 | This a proof of concept for building COBOL to WebAssembly
4 |
5 | ## How it works
6 | 1. Builds and installs the GNU Multiprecision Library [GMP](https://gmplib.org/) (dependency of GNUCOBOL)
7 | 1. Builds and installs [GnuCOBOL](https://www.gnu.org/software/gnucobol/)
8 |
9 | 1. Builds an LLVM bitcode version of GMP
10 | 1. Builds an LLVM bitcode version of libcob
11 |
12 | 1. Transpile COBOL source to C using GnuCOBOL
13 | 1. Build WebAssembly (and helper JS) using [emscripten](https://emscripten.org/), linking in the GMP and libcob bitcode
14 |
15 | ## Testing it out
16 | The whole development environment is contained in the `.devContainer` directory.
17 |
18 | Use Docker and the [containers remote extension](https://code.visualstudio.com/docs/remote/containers) for VSCode to reliably reproduce this environment
19 |
20 | ## Live Demo
21 | [moxon6.github.io/cobol-js-emscripten](https://moxon6.github.io/cobol-js-emscripten)
22 |
--------------------------------------------------------------------------------
/app/app.js:
--------------------------------------------------------------------------------
1 | let inputStream = []
2 |
3 | const keysDown = {};
4 | window.onkeydown = e => keysDown[e.code] = true;
5 | window.onkeyup = e => keysDown[e.code] = false;
6 |
7 | const getKeysDown = () => Object.keys(keysDown)
8 | .filter(key => keysDown[key]);
9 |
10 | // Final empty string denotes end of series of keys
11 | const mapKeysToNullTerminatedInputSequence = strings => ([...strings, ""])
12 | .map(str => [str, null]) // Adding nulls to terminate strings going to stdin
13 | .flat()
14 |
15 | const getInputStream = () => mapKeysToNullTerminatedInputSequence(getKeysDown())
16 |
17 | window.prompt = () => {
18 | if (!inputStream.length) inputStream = getInputStream()
19 | return inputStream.shift();
20 | }
21 |
22 | function _setElementProperty(selector, prop, value) {
23 | const element = document.querySelector(selector);
24 |
25 | let obj = element
26 | const path = prop.split(".")
27 |
28 | while (path.length > 1) obj = obj[path.shift()]
29 | obj[path[0]] = value;
30 | }
--------------------------------------------------------------------------------
/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | COBOL Pong
4 |
5 |
6 |
7 |
8 |
9 |
10 |
18 |
19 |
20 |
21 |
22 |
23 | 00
24 | -
25 | 00
26 |
27 |
28 |
29 |
30 |
31 |
Loading...
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/app/styles.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | }
4 |
5 | body {
6 | margin: 0;
7 | }
8 |
9 | .pong-container {
10 | width: 802px;
11 | height: 502px;
12 | background-color: black;
13 | border: 1px solid black;
14 | }
15 |
16 | .pong {
17 | display: flex;
18 | justify-content: center;
19 | align-items: center;
20 | position: relative;
21 | }
22 |
23 | .loading-message {
24 | position: absolute;
25 | color: white;
26 | text-transform: uppercase;
27 | font-family: monospace;
28 | align-self: start;
29 | }
30 |
31 | .score {
32 | display: none;
33 | position: absolute;
34 | color: white;
35 | font-family: monospace;
36 | font-size: 40px;
37 | align-self: start;
38 | }
39 |
40 | .paddle-1 {
41 | position: absolute;
42 | left: 0;
43 | top: 0;
44 | width: 10px;
45 | background-color: white;
46 | }
47 |
48 | .paddle-2 {
49 | position: absolute;
50 | right: 0;
51 | top: 0;
52 | width: 10px;
53 | background-color: white;
54 | }
55 |
56 | .center-line {
57 | position: absolute;
58 | width: 1px;
59 | background-color: white;
60 | height: 100%;
61 | }
62 |
63 | .ball {
64 | display: none;
65 | width: 20px;
66 | height: 20px;
67 | background-color: white;
68 | position: absolute;
69 | }
70 |
71 | .main-content {
72 | padding-top: 20px;
73 | padding-bottom: 20px;
74 | width: 100%;
75 | display: flex;
76 | justify-content: center;
77 | align-items: center;
78 | }
79 |
80 | .controls {
81 | margin-bottom: 0;
82 | font-family: monospace;
83 | }
84 |
85 | .jumbotron {
86 | padding: 20px !important;
87 | }
--------------------------------------------------------------------------------
/app/terminal.css:
--------------------------------------------------------------------------------
1 | /* Based on https://codepen.io/somethingformed/pen/raWJXV */
2 |
3 | .terminal-frame {
4 | position: relative;
5 | font-family: VT323;
6 | color: #14fdce;
7 | font-size: 24px;
8 | background-color: #031e11;
9 | height: 100%;
10 | width: 100%;
11 | }
12 |
13 | .terminal-fragment {
14 | position: absolute;
15 | left: 0;
16 | top: 0;
17 | width: 100%;
18 | height: 100%;
19 | }
20 |
21 | .terminal-fragment-output {
22 | text-shadow: 0 0.2rem 1rem #0c7b46;
23 | }
24 |
25 | .terminal-fragment-scanlines {
26 | background: linear-gradient( to bottom, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0) 50%, rgba(0, 0, 0, 0.2) 70%, rgba(0, 0, 0, 0.6));
27 | background-size: 100% 0.3rem;
28 | }
29 |
30 | .terminal-fragment-glow {
31 | background: radial-gradient( circle at center, #1bd459 0, rgba(27, 212, 89, 0.88) 63%, rgba(21, 235, 92, 0.57) 85%, rgba(19, 94, 29, 0.27) 98%, rgba(10, 23, 12, 0) 100%);
32 | opacity: 0.20;
33 | }
34 |
35 | @font-face {
36 | font-family: VT323;
37 | src: url(https://fonts.gstatic.com/s/vt323/v11/pxiKyp0ihIEF2isfFJA.ttf);
38 | }
--------------------------------------------------------------------------------
/c/extern.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | EM_JS(void, setElementProperty, (char* selectorPtr, char* stylePropPtr, char* styleValuePtr), {
5 | _setElementProperty(...[...arguments].map(x => Module.UTF8ToString(x)));
6 | });
7 |
8 | EM_JS(void, startup, (), {
9 | Asyncify.StackSize = 512 * 1024;
10 | });
11 |
--------------------------------------------------------------------------------
/cob/main.cob:
--------------------------------------------------------------------------------
1 |
2 | IDENTIFICATION DIVISION.
3 | PROGRAM-ID. MainProgram.
4 | ENVIRONMENT DIVISION.
5 | DATA DIVISION.
6 | WORKING-STORAGE SECTION.
7 | 01 LastPressed PIC X(40).
8 | 01 Player1.
9 | 05 Player1Position.
10 | 10 Player1Num PIC 999 VALUE 20.
11 | 10 Player1Pixels PIC X(3) VALUE z"px".
12 | 05 Player1Score PIC 99 VALUE 0.
13 | 01 Player2.
14 | 05 Player2Position.
15 | 10 Player2Num PIC 999 VALUE 0.
16 | 10 Player2Pixels PIC X(3) VALUE z"px".
17 | 05 Player2Score PIC 99 VALUE 0.
18 | 01 Ball.
19 | 05 BallPosition.
20 | 10 BallPositionX.
21 | 15 BallPositionXNum PIC 999 VALUE 0.
22 | 15 BallPositionXPixels PIC X(3) VALUE z"px".
23 | 10 BallPositionY.
24 | 15 BallPositionYNum PIC 999 VALUE 0.
25 | 15 BallPositionYPixels PIC X(3) VALUE z"px".
26 | 05 BallVelocity.
27 | 10 BallVelocityX PIC S99 VALUE 2.
28 | 10 BallVelocityY PIC S99 VALUE 1.
29 | 05 BallWidth PIC 99 VALUE 20.
30 |
31 | 01 GameHeight PIC 999 VALUE 500.
32 | 01 GameWidth PIC 999 VALUE 800.
33 | 01 PaddleWidth PIC 999 VALUE 10.
34 | 01 PaddleHeight.
35 | 05 PaddleHeightNum PIC 999 VALUE 75.
36 | 05 PaddleHeightPixels PIC X(3) VALUE z"px".
37 | 01 Started PIC 9 VALUE 0.
38 | 01 Done PIC 9 VALUE 0.
39 | 01 PaddleSpeed PIC 99 VALUE 5.
40 | 01 Iteration PIC 99 VALUE 0.
41 | PROCEDURE DIVISION.
42 | Main.
43 | CALL "startup" RETURNING OMITTED
44 | CALL "setElementProperty" using ".loading-message" "innerHTML" "Press Any Key To Start".
45 | Perform Check-Game-Start UNTIL Started=1
46 | Perform Initialise-UI.
47 | CALL "setElementProperty" using ".score" "style.display" "block".
48 | CALL "setElementProperty" using ".loading-message" "style.display" "None".
49 |
50 | Perform Main-Loop UNTIL Done=1
51 | CALL "setElementProperty" using ".loading-message" "style.display" "block".
52 | CALL "setElementProperty" using ".loading-message" "innerHTML" "GAME OVER".
53 | STOP RUN.
54 |
55 | Initialise-UI.
56 | CALL "setElementProperty" using ".paddle-1" "style.height" PaddleHeight.
57 | CALL "setElementProperty" using ".paddle-2" "style.height" PaddleHeight.
58 | CALL "setElementProperty" using ".ball" "style.display" "block".
59 | Perform Reset-Game
60 | .
61 |
62 | Check-Game-Start.
63 | ACCEPT LastPressed.
64 | IF LastPressed EQUALS SPACE
65 | CALL "emscripten_sleep" using by value 10 RETURNING OMITTED
66 | ELSE
67 | MOVE 1 to Started
68 | END-IF
69 | .
70 |
71 |
72 | Main-Loop.
73 | ADD 1 to Iteration.
74 |
75 | ADD BallVelocityX to BallPositionXNum
76 | ADD BallVelocityY to BallPositionYNum
77 |
78 | IF BallPositionYNum EQUALS 0 OR BallPositionYNum EQUALS GameHeight - BallWidth
79 | Multiply -1 BY BallVelocityY
80 | END-IF
81 |
82 | IF BallPositionXNum EQUALS PaddleWidth
83 | IF Player1Num - BallWidth < (BallPositionYNum) AND BallPositionYNum < (Player1Num + PaddleHeightNum + BallWidth)
84 | MULTIPLY -1 BY BallVelocityX
85 | END-IF
86 | END-IF
87 |
88 | IF BallPositionXNum EQUALS (GameWidth - BallWidth - PaddleWidth)
89 | IF Player2Num - BallWidth < (BallPositionYNum) AND BallPositionYNum < (Player2Num + PaddleHeightNum + BallWidth)
90 | MULTIPLY -1 BY BallVelocityX
91 | END-IF
92 | END-IF
93 |
94 | IF BallPositionXNum EQUALS 0
95 | MULTIPLY -1 BY BallVelocityX
96 | ADD 1 to Player2Score
97 | Perform Reset-Game.
98 |
99 |
100 | IF BallPositionXNum EQUALS (GameWidth - BallWidth)
101 | MULTIPLY -1 BY BallVelocityX
102 | ADD 1 to Player1Score
103 | Perform Reset-Game.
104 |
105 | Perform Handle-Keypress TEST AFTER UNTIL LastPressed EQUALS SPACE.
106 | Perform Rerender.
107 |
108 | Handle-KeyPress.
109 | ACCEPT LastPressed.
110 | EVALUATE LastPressed
111 | WHEN "KeyA"
112 | IF Player1Num IS GREATER THAN OR EQUAL TO PaddleSpeed
113 | SUBTRACT PaddleSpeed FROM Player1Num
114 | WHEN "KeyD"
115 | IF Player1Num IS LESS THAN GameHeight - PaddleHeightNum
116 | ADD PaddleSpeed TO Player1Num
117 | WHEN "KeyL"
118 | IF Player2Num IS GREATER THAN OR EQUAL TO PaddleSpeed
119 | SUBTRACT PaddleSpeed FROM Player2Num
120 | WHEN "KeyJ"
121 | IF Player2Num IS LESS THAN GameHeight - PaddleHeightNum
122 | ADD PaddleSpeed TO Player2Num
123 | WHEN "Escape"
124 | MOVE 1 TO DONE.
125 |
126 | Reset-Game.
127 | COMPUTE BallPositionXNum = GameWidth / 2 - BallWidth / 2
128 | COMPUTE BallPositionYNum = GameHeight / 2 - BallWidth / 2
129 | PERFORM Rerender.
130 | CALL "emscripten_sleep" using by value 1000 RETURNING OMITTED
131 | .
132 |
133 |
134 | Rerender.
135 | Perform Update-Positions.
136 | Perform Update-Scores.
137 |
138 | Update-Positions.
139 | CALL "setElementProperty" using ".ball" "style.left" BallPositionX.
140 | CALL "setElementProperty" using ".ball" "style.top" BallPositionY.
141 | CALL "setElementProperty" using ".paddle-1" "style.top" Player1Position.
142 | CALL "setElementProperty" using ".paddle-2" "style.top" Player2.
143 | CALL "emscripten_sleep" using by value 5 RETURNING OMITTED.
144 |
145 | Update-Scores.
146 | CALL "setElementProperty" using ".player-1-score" "innerHTML" Player1Score.
147 | CALL "setElementProperty" using ".player-2-score" "innerHTML" Player2Score.
148 |
149 | END PROGRAM MainProgram.
150 |
151 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cobol-js-emscripten",
3 | "version": "1.0.0",
4 | "description": "This a proof of concept for building COBOL to WebAssembly",
5 | "main": "index.js",
6 | "scripts": {
7 | "build": "./scripts/build.sh",
8 | "watch": "find c cob scripts -type f | entr ./scripts/build.sh",
9 | "start": "cd app && python2 -m SimpleHTTPServer 5500",
10 | "clean": "rm -rf tmp",
11 | "deploy": "gh-pages -d app"
12 | },
13 | "repository": {
14 | "type": "git",
15 | "url": "git+https://github.com/moxon6/cobol-js-emscripten.git"
16 | },
17 | "author": "Martin Moxon",
18 | "license": "ISC",
19 | "bugs": {
20 | "url": "https://github.com/moxon6/cobol-js-emscripten/issues"
21 | },
22 | "homepage": "https://github.com/moxon6/cobol-js-emscripten#readme",
23 | "dependencies": {
24 | "gh-pages": "^2.2.0",
25 | "parcel-bundler": "^1.12.4"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/scripts/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e
4 |
5 | # Define C intermediate and js/wasm output dirs
6 | build_c_dir=tmp/build
7 | build_js_dir=app/cobol-js/
8 |
9 | # Create these directories if they don't exist
10 | mkdir -p $build_js_dir $build_c_dir
11 |
12 | # Define list of functions to expose from c/extern.c
13 | functions="-K emscripten_sleep -K setElementProperty -K startup"
14 |
15 | # Define C intermediate and js output paths
16 | build_c=$build_c_dir/build.c
17 | build_js=$build_js_dir/index.js
18 |
19 | echo ""
20 | echo ">>> Transpiling COBOL -> C ..."
21 | cobc $functions -C -x -free cob/*.cob -o $build_c
22 |
23 | echo ">>> Compiling C -> WASM + JS ..."
24 | tput setaf 3 # Set font to yellow
25 | emcc \
26 | $build_c \
27 | c/extern.c \
28 | /root/opt/lib/libgmp.a `# Include Gnu multiprecision library llvm build` \
29 | /root/opt/lib/libcob.a `# Link in gnucobol's libcob llvm build` \
30 | -L/usr/local/include \
31 | -I/usr/local/include \
32 | -s ERROR_ON_UNDEFINED_SYMBOLS=0 \
33 | -s ASYNCIFY \
34 | -s EXTRA_EXPORTED_RUNTIME_METHODS=['UTF8ToString'] \
35 | --minify 0 `# Disable JS minify - This allows the sed commands to below operate correctly` \
36 | -O2 \
37 | -o $build_js
38 | tput sgr 0 # Reset font color
39 |
40 | echo ">>> Commenting out all dlopen JS callbacks"
41 | sed -i '/To use dlopen/s/^/\/\//' $build_js
42 |
43 | echo ">>> Commenting out all stub JS callbacks"
44 | sed -i '/Calling stub instead/s/^/\/\//' $build_js
45 |
46 | echo "$(tput setaf 2)>>> Build Complete!$(tput sgr 0)"
--------------------------------------------------------------------------------