Skip to content

Commit 7f6a185

Browse files
committed
Add script for compiling a C benchmark
1 parent 6ab6eec commit 7f6a185

File tree

1 file changed

+328
-0
lines changed

1 file changed

+328
-0
lines changed

tools/scripts/compile_c_benchmark

Lines changed: 328 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,328 @@
1+
#!/usr/bin/env bash
2+
#
3+
# Script for compiling a C benchmark.
4+
#
5+
# Usage: compile_c_benchmark <filepath>
6+
#
7+
# Arguments:
8+
#
9+
# filepath Benchmark file path.
10+
#
11+
#
12+
# Environment Variables:
13+
#
14+
# OS Host operating system. Default: `linux`.
15+
# NODE Command for running Node.js. Default: `node`.
16+
# NODE_PATH Path for resolving node modules.
17+
# C_COMPILER C compiler. Default: `gcc`.
18+
# BLAS BLAS library to use.
19+
# BLAS_DIR BLAS library path (if custom).
20+
# CEPHES Cephes mathematical library path.
21+
# CEPHES_SRC Directory containing Cephes source code.
22+
# INCLUDE Includes (e.g., `-I /foo/bar -I /a/b`).
23+
# SOURCE_FILES Source file list.
24+
# LIBRARIES Linked libraries (e.g., `-lopenblas -lpthreads`).
25+
# LIBPATH Library paths (e.g., `-L /foo/bar -L /a/b`).
26+
#
27+
28+
29+
# VARIABLES #
30+
31+
# Set the benchmark file path:
32+
file_path="$1"
33+
34+
# Define the host operating system:
35+
os="${OS}"
36+
if [[ "${os}" = "Darwin" ]]; then
37+
os='mac'
38+
elif [[ "${os}" = "WINNT" ]]; then
39+
os='win'
40+
else
41+
os='linux'
42+
fi
43+
44+
# Define the command for running Node.js:
45+
node_cmd="${NODE}"
46+
if [[ -z "${node_cmd}" ]]; then
47+
node_cmd='node'
48+
fi
49+
50+
# Define the node path:
51+
node_path="${NODE_PATH}"
52+
53+
# Define the path to a C compiler:
54+
c_compiler="${C_COMPILER}"
55+
if [[ -z "${c_compiler}" ]]; then
56+
c_compiler='gcc'
57+
fi
58+
59+
# Define the BLAS library to use:
60+
blas="${BLAS}"
61+
62+
# Define the BLAS directory:
63+
blas_dir="${BLAS_DIR}"
64+
65+
# Define the path to the Cephes mathematical library:
66+
cephes="${CEPHES}"
67+
68+
# Define the path to the Cephes source code:
69+
cephes_src="${CEPHES_SRC}"
70+
71+
# Define a list of `include` directories (e.g., `-I /foo/bar -I /beep/boop/include`):
72+
include="${INCLUDE}"
73+
74+
# Define a list of source files:
75+
source_files="${SOURCE_FILES}"
76+
77+
# Define a list of libraries (e.g., `-lopenblas -lpthreads`):
78+
libraries="${LIBRARIES}"
79+
80+
# Define a list of library paths (e.g., `-L /foo/bar -L /beep/boop`):
81+
libpath="${LIBPATH}"
82+
83+
84+
# FUNCTIONS #
85+
86+
# Defines an error handler.
87+
#
88+
# $1 - error status
89+
on_error() {
90+
echo 'ERROR: An error was encountered during execution.' >&2
91+
cleanup
92+
exit "$1"
93+
}
94+
95+
# Runs clean-up tasks.
96+
cleanup() {
97+
echo '' >&2
98+
}
99+
100+
# Prints a success message.
101+
print_success() {
102+
echo 'Success!' >&2
103+
}
104+
105+
# Prints usage information.
106+
usage() {
107+
echo '' >&2
108+
echo 'Usage: compile_c_benchmark <filepath>' >&2
109+
echo '' >&2
110+
}
111+
112+
# Resolves a package path.
113+
#
114+
# $1 - source directory
115+
resolve_pkg_path() {
116+
local pkg_path
117+
local script
118+
119+
# Generate the script for resolving a package path:
120+
script='"'"var resolve = require('@stdlib/fs/resolve-parent-path').sync; var dirname = require('@stdlib/utils/dirname'); var opts = {'dir':'$1'}; var path = resolve('package.json', opts); console.log(dirname(path));"'"'
121+
122+
# Resolve package path:
123+
pkg_path=$(eval NODE_PATH="${node_path}" "${node_cmd}" -e "${script}")
124+
125+
echo "${pkg_path}"
126+
}
127+
128+
# Resolves a package `manifest.json`.
129+
#
130+
# $1 - package path
131+
resolve_pkg_manifest() {
132+
if [[ -e "$1/manifest.json" ]]; then
133+
return 0
134+
fi
135+
return 1
136+
}
137+
138+
# Resolves `include` directories.
139+
#
140+
# $1 - package directory
141+
resolve_includes() {
142+
local includes
143+
local script
144+
local opts
145+
146+
# WARNING: the following assumes knowledge of the `manifest.json` options for BLAS packages. Were those options to change, the following would need to be updated.
147+
if [[ -n "${blas}" ]]; then
148+
opts="{'os':'${os}','blas':'${blas}'}"
149+
else
150+
opts='{}'
151+
fi
152+
# Generate the script for resolving `include` directories:
153+
script='"'"var path = require('path'); var arr = require('@stdlib/tools/library-manifest')(path.join('$1','manifest.json'),${opts},{'basedir':'$1','paths':'posix'}).include; var str = ''; for (var i = 0; i < arr.length; i++){var p = path.resolve('$1', arr[i]); str += '-I '+p+' ';}; console.log(str.substring(0, str.length-1));"'"'
154+
155+
# Resolve `include` directories:
156+
includes=$(eval NODE_PATH="${node_path}" "${node_cmd}" -e "${script}")
157+
158+
if [[ -n "${blas}" ]]; then
159+
if [[ -n "${blas_dir}" ]]; then
160+
echo "${includes} -I ${blas_dir}"
161+
else
162+
echo "${includes}"
163+
fi
164+
else
165+
echo "${includes}"
166+
fi
167+
}
168+
169+
# Resolves source files.
170+
#
171+
# $1 - package directory
172+
resolve_source_files() {
173+
local source_files
174+
local script
175+
176+
# WARNING: the following assumes knowledge of the `manifest.json` options for BLAS packages. Were those options to change, the following would need to be updated.
177+
if [[ -n "${blas}" ]]; then
178+
opts="{'os':'${os}','blas':'${blas}'}"
179+
else
180+
opts='{}'
181+
fi
182+
# Generate the script for resolving source files:
183+
script='"'"var path = require('path'); var arr = require('@stdlib/tools/library-manifest')(path.join('$1','manifest.json'),${opts},{'basedir':'$1','paths':'posix'}).src; var str = ''; for (var i = 0; i < arr.length; i++){var p = path.resolve('$1', arr[i]); str += p+' ';}; console.log(str.substring(0, str.length-1));"'"'
184+
185+
# Resolve files:
186+
source_files=$(eval NODE_PATH="${node_path}" "${node_cmd}" -e "${script}")
187+
188+
echo "${source_files}"
189+
}
190+
191+
# Resolves libraries.
192+
#
193+
# $1 - package directory
194+
resolve_libraries() {
195+
local libraries
196+
local script
197+
198+
# WARNING: the following assumes knowledge of the `manifest.json` options for BLAS packages. Were those options to change, the following would need to be updated.
199+
if [[ -n "${blas}" ]]; then
200+
opts="{'os':'${os}','blas':'${blas}'}"
201+
else
202+
opts='{}'
203+
fi
204+
# Generate the script for resolving libraries:
205+
script='"'"var path = require('path'); var arr = require('@stdlib/tools/library-manifest')(path.join('$1','manifest.json'),${opts},{'basedir':'$1','paths':'posix'}).libraries; var str = ''; for (var i = 0; i < arr.length; i++){str += arr[i]+' ';}; console.log(str.substring(0, str.length-1));"'"'
206+
207+
# Resolve libraries:
208+
libraries=$(eval NODE_PATH="${node_path}" "${node_cmd}" -e "${script}")
209+
210+
echo "${libraries}"
211+
}
212+
213+
# Resolves library paths.
214+
#
215+
# $1 - package directory
216+
resolve_libpaths() {
217+
local libpath
218+
local script
219+
220+
# WARNING: the following assumes knowledge of the `manifest.json` options for BLAS packages. Were those options to change, the following would need to be updated.
221+
if [[ -n "${blas}" ]]; then
222+
opts="{'os':'${os}','blas':'${blas}'}"
223+
else
224+
opts='{}'
225+
fi
226+
# Generate the script for resolving library paths:
227+
script='"'"var path = require('path'); var arr = require('@stdlib/tools/library-manifest')(path.join('$1','manifest.json'),${opts},{'basedir':'$1','paths':'posix'}).libpath; var str = ''; for (var i = 0; i < arr.length; i++){var p = path.resolve('$1', arr[i]); str += '-L '+p+' ';}; console.log(str.substring(0, str.length-1));"'"'
228+
229+
# Resolve library paths:
230+
libpath=$(eval NODE_PATH="${node_path}" "${node_cmd}" -e "${script}")
231+
232+
if [[ -n "${blas}" ]]; then
233+
if [[ -n "${blas_dir}" ]]; then
234+
echo "${libpath} -L ${blas_dir}"
235+
else
236+
echo "${libpath}"
237+
fi
238+
else
239+
echo "${libpath}"
240+
fi
241+
}
242+
243+
# Compiles benchmark.
244+
#
245+
# $1 - source directory
246+
compile() {
247+
cd "$1" && C_COMPILER="${c_compiler}" INCLUDE="${include}" SOURCE_FILES="${source_files}" LIBRARIES="${libraries}" LIBPATH="${libpath}" CEPHES="${cephes}" CEPHES_SRC="${cephes_src}" make 2>&1
248+
if [[ "$?" -ne 0 ]]; then
249+
echo 'Error when attempting to compile benchmark.' >&2
250+
return 1
251+
fi
252+
echo 'Successfully compiled benchmark.' >&2
253+
return 0
254+
}
255+
256+
257+
# MAIN #
258+
259+
# Main execution sequence.
260+
main() {
261+
local pkg_path
262+
local manifest
263+
local src_dir
264+
265+
echo 'Resolving package path...' >&2
266+
pkg_path=$(resolve_pkg_path "${src_dir}")
267+
if [[ "$?" -ne 0 ]]; then
268+
on_error 1
269+
fi
270+
echo "Package path: ${pkg_path}" >&2
271+
272+
echo 'Resolving package manifest...' >&2
273+
manifest=$(resolve_pkg_manifest $"{pkg_path}")
274+
if [[ "$?" -ne 0 ]]; then
275+
echo 'Successfully resolved package manifest.' >&2
276+
if [[ -z "${include}" ]]; then
277+
echo 'Resolving include directories...' >&2
278+
include=$(resolve_includes "${pkg_path}")
279+
if [[ "$?" -ne 0 ]]; then
280+
on_error 1
281+
fi
282+
fi
283+
if [[ -z "${source_files}" ]]; then
284+
echo 'Resolving source files...' >&2
285+
source_files=$(resolve_source_files "${pkg_path}")
286+
if [[ "$?" -ne 0 ]]; then
287+
on_error 1
288+
fi
289+
fi
290+
if [[ -z "${libraries}" ]]; then
291+
echo 'Resolving libraries...' >&2
292+
libraries=$(resolve_libraries "${pkg_path}")
293+
if [[ "$?" -ne 0 ]]; then
294+
on_error 1
295+
fi
296+
fi
297+
if [[ -z "${libpath}" ]]; then
298+
echo 'Resolving library paths...' >&2
299+
libpath=$(resolve_libpaths "${pkg_path}")
300+
if [[ "$?" -ne 0 ]]; then
301+
on_error 1
302+
fi
303+
fi
304+
else
305+
echo 'Unable to resolve package manifest.' >&2
306+
fi
307+
echo 'Compiling benchmark...' >&2
308+
src_dir=$(dirname "${file_path}")
309+
compile "${src_dir}"
310+
if [[ "$?" -ne 0 ]]; then
311+
on_error 1
312+
fi
313+
print_success
314+
cleanup
315+
exit 0
316+
}
317+
318+
# Handle arguments...
319+
if [[ "$#" -eq 0 ]]; then
320+
usage
321+
exit 0
322+
elif [[ "$#" -gt 1 ]]; then
323+
echo 'ERROR: unrecognized arguments. Must provide a file path.' >&2
324+
exit 1
325+
fi
326+
327+
# Run main:
328+
main

0 commit comments

Comments
 (0)