1
+ name : OCaml Binding CI (Ubuntu + macOS)
2
+
3
+ on :
4
+ push :
5
+ branches : [ "**" ]
6
+ pull_request :
7
+ branches : [ "**" ]
8
+
9
+ jobs :
10
+ build-test :
11
+ strategy :
12
+ matrix :
13
+ # ubuntu-latest,
14
+ os : [ macos-latest]
15
+ ocaml-version : ["5"]
16
+ fail-fast : false
17
+ runs-on : ${{ matrix.os }}
18
+
19
+ steps :
20
+ - name : Checkout code
21
+ uses : actions/checkout@v4
22
+
23
+ # Cache ccache (shared across runs)
24
+ - name : Cache ccache
25
+ uses : actions/cache@v4
26
+ with :
27
+ path : ~/.ccache
28
+ key : ${{ runner.os }}-ccache-${{ github.sha }}
29
+ restore-keys : |
30
+ ${{ runner.os }}-ccache-
31
+
32
+ # Cache opam (compiler + packages)
33
+ - name : Cache opam
34
+ uses : actions/cache@v4
35
+ with :
36
+ path : ~/.opam
37
+ key : ${{ runner.os }}-opam-${{ matrix.ocaml-version }}-${{ github.sha }}
38
+ restore-keys : |
39
+ ${{ runner.os }}-opam-${{ matrix.ocaml-version }}-
40
+
41
+ # Setup OCaml via action
42
+ - uses : ocaml/setup-ocaml@v3
43
+ with :
44
+ ocaml-compiler : ${{ matrix.ocaml-version }}
45
+ opam-disable-sandboxing : true
46
+
47
+ - name : Debug after setup-ocaml
48
+ run : |
49
+ echo "PATH after setup:"
50
+ echo "$PATH" | tr ':' '\n'
51
+
52
+ echo ""
53
+ echo "which ocamlfind:"
54
+ which ocamlfind || echo "❌ Not found"
55
+
56
+ echo ""
57
+ echo "OPAM_SWITCH_PREFIX : $OPAM_SWITCH_PREFIX"
58
+
59
+ # Platform-specific dependencies
60
+ - name : Install system dependencies (Ubuntu)
61
+ if : matrix.os == 'ubuntu-latest'
62
+ run : |
63
+ sudo apt-get update
64
+ sudo apt-get install -y \
65
+ bubblewrap m4 libgmp-dev pkg-config ninja-build ccache
66
+
67
+ - name : Install system dependencies (macOS)
68
+ if : matrix.os == 'macos-latest'
69
+ run : |
70
+ brew install gmp pkg-config ninja ccache
71
+
72
+ - name : Install required opam packages
73
+ run : opam install -y ocamlfind zarith
74
+
75
+ - name : 🔍 Debug ocamlfind + ocamlc.opt issue
76
+ run : |
77
+ set -e # fail on error
78
+
79
+ eval $(opam env)
80
+
81
+ echo "🔎 ocamlc : $(which ocamlc)"
82
+ echo "🔎 ocamlopt : $(which ocamlopt)"
83
+ echo "🔎 ocamlfind : $(which ocamlfind)"
84
+ echo "🔎 All ocamlfind on path:"
85
+ which -a ocamlfind
86
+
87
+ echo ""
88
+ echo "📄 Writing test.ml"
89
+ echo 'let () = print_endline "Hello from OCaml"' > test.ml
90
+
91
+ echo ""
92
+ echo "🧪 ocamlc compile"
93
+ ocamlc test.ml -o test_bytecode
94
+
95
+ echo ""
96
+ echo "🧪 ocamlopt compile"
97
+ ocamlopt test.ml -o test_native
98
+
99
+ echo ""
100
+ echo "🧪 ocamlfind ocamlc compile"
101
+ ocamlfind ocamlc -package zarith -linkpkg test.ml -o test_bytecode_find
102
+
103
+ echo ""
104
+ echo "🧪 ocamlfind ocamlopt compile"
105
+ ocamlfind ocamlopt -package zarith -linkpkg test.ml -o test_native_find
106
+
107
+ # echo ""
108
+ # echo "🧪 FULLPATH ocamlfind ocamlc compile"
109
+ # /home/runner/work/z3/z3/_opam/bin/ocamlfind ocamlc -package zarith -linkpkg test.ml -o test_bytecode_full
110
+
111
+ # echo ""
112
+ # echo "🧪 FULLPATH ocamlfind ocamlopt compile"
113
+ # /home/runner/work/z3/z3/_opam/bin/ocamlfind ocamlopt -package zarith -linkpkg test.ml -o test_native_full
114
+
115
+ echo ""
116
+ echo "✅ All compiles passed."
117
+
118
+ - name : 🧪 Debug OPAM + GITHUB_PATH setup
119
+ run : |
120
+ echo "🔍 PATH at this step:"
121
+ echo "$PATH" | tr ':' '\n'
122
+
123
+ echo ""
124
+ echo "📁 Listing \$GITHUB_PATH file (if exists):"
125
+ if [ -f "$GITHUB_PATH" ]; then
126
+ cat "$GITHUB_PATH"
127
+ else
128
+ echo "❌ GITHUB_PATH file does not exist at $GITHUB_PATH"
129
+ fi
130
+
131
+ echo ""
132
+ echo "📦 OPAM_SWITCH_PREFIX = $OPAM_SWITCH_PREFIX"
133
+ echo ""
134
+ echo "📂 Listing contents of \$OPAM_SWITCH_PREFIX/bin:"
135
+ ls -al "$OPAM_SWITCH_PREFIX/bin" || echo "❌ Directory does not exist"
136
+
137
+ echo ""
138
+ echo "🔍 Check if PATH includes _opam/bin:"
139
+ echo "$PATH" | grep "_opam/bin" || echo "❌ _opam/bin NOT in PATH"
140
+
141
+ echo ""
142
+ echo "✅ Done."
143
+
144
+ # Configure
145
+ - name : Configure with CMake
146
+ env :
147
+ RUNNER_OS : ${{ runner.os }}
148
+ CC : ${{ matrix.os == 'macos-latest' && 'ccache clang' || 'ccache gcc' }}
149
+ CXX : ${{ matrix.os == 'macos-latest' && 'ccache clang++' || 'ccache g++' }}
150
+ run : |
151
+ mkdir -p build
152
+ cd build
153
+ eval $(opam env)
154
+ echo "CC: $CC"
155
+ echo "CXX: $CXX"
156
+ echo "OCAMLFIND: $(which ocamlfind)"
157
+ echo "OCAMLC: $(which ocamlc)"
158
+ echo "OCAMLOPT: $(which ocamlopt)"
159
+ echo "OCAML_VERSION: $(ocamlc -version)"
160
+ echo "OCAMLLIB: $OCAMLLIB"
161
+ env | grep OCAML
162
+ cmake .. \
163
+ -G Ninja \
164
+ -DZ3_BUILD_LIBZ3_SHARED=ON \
165
+ -DZ3_BUILD_OCAML_BINDINGS=ON \
166
+ -DZ3_BUILD_JAVA_BINDINGS=OFF \
167
+ -DZ3_BUILD_PYTHON_BINDINGS=OFF \
168
+ -DZ3_BUILD_CLI=OFF \
169
+ -DZ3_BUILD_TEST_EXECUTABLES=OFF \
170
+ -DCMAKE_VERBOSE_MAKEFILE=TRUE
171
+
172
+ - name : Build Z3 and OCaml bindings
173
+ run : |
174
+ ccache -z || true
175
+ eval $(opam env)
176
+ cd build
177
+ ninja build_z3_ocaml_bindings
178
+ ccache -s || true
179
+
180
+ - name : Compile ml_example.byte
181
+ run : |
182
+ eval $(opam env)
183
+ ocamlfind ocamlc -o ml_example.byte \
184
+ -package zarith \
185
+ -linkpkg \
186
+ -I build/src/api/ml \
187
+ -dllpath build/src/api/ml \
188
+ build/src/api/ml/z3ml.cma \
189
+ examples/ml/ml_example.ml
190
+
191
+ - name : Run ml_example.byte
192
+ run : |
193
+ eval $(opam env)
194
+ ocamlrun ./ml_example.byte
195
+
196
+ - name : Compile ml_example (native)
197
+ run : |
198
+ eval $(opam env)
199
+ ocamlfind ocamlopt -o ml_example \
200
+ -package zarith \
201
+ -linkpkg \
202
+ -I build/src/api/ml \
203
+ build/src/api/ml/z3ml.cmxa \
204
+ examples/ml/ml_example.ml
205
+
206
+ - name : Run ml_example (native)
207
+ run : ./ml_example
0 commit comments