-
Notifications
You must be signed in to change notification settings - Fork 86
/
build.sh
executable file
·399 lines (370 loc) · 14.4 KB
/
build.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
#!/bin/bash
#
# NAME
# build.sh
#
# DESCRIPTION
# Build the JSON-Fortran library and unit tests.
#
# USAGE
# build.sh [--compiler {intel|gnu|<other>}] [--cflags '<custom compiler flags here>']
# [--coverage [{yes|no}]] [--profile [{yes|no}]] [--skip-tests [{yes|no}]]
# [--skip-documentation [{yes|no}]] [--enable-unicode [{yes|no}]] [--help]
# [--clean] [--real-kind [{REAL32\REAL64\REAL128}]]
# [--int-kind [{INT8\INT16\INT32\INT64}]]
#
# By default, if invoked without any flags, this build script will build the
# JSON-Fortran library using gfortran,
# without :
# unicode support
# coverage flags
# profiling flags
# with :
# unit tests enabled
# documentation (if FORD is installed)
# real(REAL64) kinds
# integer(INT32) kinds
#
# More recent (right-most) flags will override preceding flags
# flags:
# --compiler : gnu or gfortran for gfortran, intel or ifort for intel compiler
# A custom compiler may also be specified here, e.g. ftn
#
# --cflags : Enter any additional/custom compiler flags here and make sure they are
# properly quoted
#
# --help : Print a usage message and exit.
#
# --clean : Delete generated files and clean up after builds
#
#
# The following flags all (optionally) accept an argument, "yes" or "no." If
# no argument is passed, "yes" will be assumed.
#
# --enable-unicode [{yes|no}]: Request that the JSON-Fortran be built with (or
# without) unicode/UCS4 support. If your compiler
# does NOT support ISO 10646/UCS4 and it was
# requested, then a warning is printed and the
# library is built without UCS4 support.
#
# --coverage [{yes|no}]: Compile the library and tests with code coverage enabled
# or disabled.
#
# --profile [{yes|no}]: Compile the library and tests with code profiling enabled
# or disabled
#
# --skip-tests [{yes|no}]: Skip (or don't skip) building and running the json-
# fortran unit tests
#
# --skip-documentation [{yes|no}]: Skip (or don't skip) building the json-
# fortran documentation using FORD
#
# REQUIRES
# FoBiS.py : https://github.com/szaghi/FoBiS [version 1.2.5 or later required]
# FORD : https://github.com/Fortran-FOSS-Programmers/ford [version 4.0.0 or later]
#
# AUTHOR
# Jacob Williams : 12/27/2014
#
#set -x
#set -v
set -o errexit
FORDMD='json-fortran.md' # FORD options file for building documentation
DOCDIR='./doc/' # build directory for documentation
PAGESDIR='./pages/' # Directory for FORD "pages"
SRCDIR='./src/' # library source directory
TESTDIR='./src/tests/' # unit test source directory
INTROSPECDIR='./src/tests/introspection/' # pre compile configuration tests directory
UCS4TESTCODE='test_iso_10646_support.f90'
BINDIR='./bin/' # build directory for unit tests
LIBDIR='./lib/' # build directory for library
MODCODE='json_module.F90' # json module file name
LIBOUT='libjsonfortran.a' # name of json library
FPP="gfortran -E" # default to gfortran -E pre-processing
# The following warning might be triggered by ifort unless explicitly silenced:
# warning #7601: F2008 standard does not allow an internal procedure to be an actual argument procedure name. (R1214.4).
# In the context of F2008 this is an erroneous warning.
# See https://prd1idz.cps.intel.com/en-us/forums/topic/486629
INTELCOMPILERFLAGS='-c -O2 -warn -stand f08 -diag-disable 7601 -diag-disable 4013 -diag-disable 5142 -traceback'
#INTELCOMPILERFLAGS='-c -O2 -warn -traceback -stand f08 -assume protect_parens -assume buffered_io -check all'
GNUCOMPILERFLAGS='-c -O2 -fbacktrace -Wall -Wextra -Wno-maybe-uninitialized -Wno-unused-function -pedantic -std=f2008 -fno-omit-frame-pointer'
FCOMPILER='gnu' #Set default compiler to gfortran
# command line argument parsing
# N.B.: Arguments appearing later in the list take precidence over those appearing earlier.
# e.g., "./build.sh --compiler intel --coverage no --compiler gnu --coverage" will
# perform the build with the GFORTRAN compiler, and coverage analysis
script_name="$(basename "$0")"
# usage message
print_usage () {
echo -e "\n\nUsage:\n"
echo -e "${script_name} [--compiler {intel|gnu|<other>}] [--cflags '<custom compiler flags here>']\n\
[--coverage [{yes|no}]] [--profile [{yes|no}]] [--skip-tests [{yes|no}]]\n\
[--skip-documentation [{yes|no}]] [--enable-unicode [{yes|no}]] [--help]"
echo ""
echo -e "Any flags that take an optional yes or no argument will default to 'yes' when no\n\
argument is passed. Additionally, A custom compiler may be passed to the 'compiler'\n\
flag, but appropriate 'cflags' should also be passed to the script.\n\n"
}
while [ "$#" -ge "1" ]; do # Get command line arguments while there are more left to process
key="$1" # Command line args are key-value pairs or value-less keys
case $key in #find known keys
--compiler) #pick the compiler. Defaults to gfortran, but intel or custom compilers can be used
case "$2" in
intel|Intel|INTEL|ifort)
FCOMPILER='Intel'
FCOMPILERFLAGS="$INTELCOMPILERFLAGS"
FPP="fpp"
shift
;;
gnu|Gnu|GNU|gfortran|Gfortran|GFortran|GFORTRAN)
FCOMPILER='gnu'
FCOMPILERFLAGS="$GNUCOMPILERFLAGS"
FPP="gfortran -E"
shift
;;
*)
FCOMPILER="custom"
echo "Warning: Trying to build with unsupported compiler, $2." 1>&2
echo "Please ensure you set appropriate --cflags and (single) quote them" 1>&2
FC="$2"
FPP="gfortran -E" # try gfortran to preprocess as a default
shift
;;
esac
;;
--cflags)
FCOMPILERFLAGS="$2"
# no good way to check that the user didn't do something questionable
shift
;;
--real-kind)
REAL_KIND="-D$2"
# warning: not checking for valid input
# should be one of: REAL32, REAL64 [default], REAL128
shift
;;
--int-kind)
INT_KIND="-D$2"
# warning: not checking for valid input
# should be one of: INT8, INT16, INT32 [default], INT64
shift
;;
--enable-unicode)
case $2 in
yes|Yes|YES)
TRY_UNICODE="yes"
shift
;;
no|No|NO)
TRY_UNICODE="no"
shift
;;
*)
TRY_UNICODE="yes"
# don't shift; $2 is next arg
;;
esac
;;
--coverage) # enable coverage
case $2 in
yes|Yes|YES)
CODE_COVERAGE="yes"
shift
;;
no|No|NO)
CODE_COVERAGE="no"
shift
;;
*)
CODE_COVERAGE="yes"
# don't shift because $2 is some other flag
;;
esac
;;
--profile) #enable profiling
case $2 in
yes|Yes|YES)
CODE_PROFILE="yes"
shift
;;
no|No|NO)
CODE_PROFILE="no"
shift
;;
*)
CODE_PROFILE="yes"
# don't shift because $2 is some other flag
;;
esac
;;
--skip-tests) # skip tests
case $2 in
yes|Yes|YES)
JF_SKIP_TESTS="yes"
shift
;;
no|No|NO)
JF_SKIP_TESTS="no"
shift
;;
*)
JF_SKIP_TESTS="yes"
;;
esac
;;
--skip-documentation)
case $2 in
yes|Yes|YES)
JF_SKIP_DOCS="yes"
shift
;;
no|No|NO)
JF_SKIP_DOCS="no"
shift
;;
*)
JF_SKIP_DOCS="yes"
;;
esac
;;
--help)
print_usage
exit 0
;;
--clean)
rm -r -- src{,/tests}/*.o $DOCDIR* $LIBDIR* $BINDIR* *.gcov*
;;
*)
echo "Unknown flag, \"$1\", passed to ${script_name}!" 2>&1
print_usage
exit 1
;;
esac
shift # look at next argument
done # with argument parsing loop
# if no compiler selected, then we're defaulting to gnu, and need to check that the cflags are set
if [ "$FCOMPILER" = 'gnu' ] && [ -z "$FCOMPILERFLAGS" ]; then
FCOMPILERFLAGS="$GNUCOMPILERFLAGS"
fi
if [[ $CODE_COVERAGE == [yY]* ]]; then
echo "Trying to compile with code coverage instrumentation."
COVERAGE="-coverage"
fi
if [[ $CODE_PROFILE == [yY]* ]]; then
echo "Trying to compile with code profiling instrumentation."
PROFILING="-profile"
fi
if [[ $FCOMPILER == custom ]]; then
echo "Trying to compile with custom compiler, $FC"
CUSTOM=("-fc" "$FC")
fi
if [[ $TRY_UNICODE == [yY]* ]]; then
echo "Trying to compile library with Unicode/UCS4 support"
FoBiS.py build -ch -compiler "${FCOMPILER}" "${CUSTOM[@]}" -cflags "${FCOMPILERFLAGS}" -dbld "${BINDIR}" -s "${INTROSPECDIR}" -dmod ./ -dobj ./ -t "${UCS4TESTCODE}" -o "${UCS4TESTCODE%.f90}" -colors
if "${BINDIR}/${UCS4TESTCODE%.f90}"; then
DEFINES="-DUSE_UCS4 -Wunused-function"
fi
fi
#build the stand-alone library:
echo ""
echo "Building library..."
FoBiS.py build -ch -compiler ${FCOMPILER} "${CUSTOM[@]}" -cflags "${FCOMPILERFLAGS} ${DEFINES} ${REAL_KIND} ${INT_KIND}" ${COVERAGE} ${PROFILING} -dbld ${LIBDIR} -s ${SRCDIR} -dmod ./ -dobj ./ -t ${MODCODE} -o ${LIBOUT} -mklib static -colors
#build the unit tests (uses the above library):
if [[ $JF_SKIP_TESTS != [yY]* ]]; then
echo ""
echo "Building unit tests..."
# FoBiS.py PR #45 work around
[ -d "$BINDIR" ] || mkdir "$BINDIR"
for TEST in "${TESTDIR%/}"/jf_test_*.[fF]90; do
THIS_TEST=${TEST##*/}
echo "Build ${THIS_TEST%.[fF]90}"
FoBiS.py build -ch -compiler ${FCOMPILER} "${CUSTOM[@]}" -cflags "${FCOMPILERFLAGS} ${DEFINES}" ${COVERAGE} ${PROFILING} -dbld "${BINDIR}" -s "${TESTDIR}" -i "${LIBDIR}" -libs "${LIBDIR}/${LIBOUT}" -dmod ./ -dobj ./ -t "${THIS_TEST}" -o "${THIS_TEST%.[fF]90}" -colors
done
else
echo "Skip building the unit tests since \$JF_SKIP_TESTS has been set to 'true'."
fi
# Run all the tests unless $JF_SKIP_TESTS
echo ""
if [[ $JF_SKIP_TESTS != [yY]* ]] ; then
echo "Running tests..."
OLD_IGNORES="$GLOBIGNORE"
# run next commands in subshell to avoid `cd -`
(cd "$BINDIR"
GLOBIGNORE='*.*'
# from: http://stackoverflow.com/questions/7992689/bash-how-to-loop-all-files-in-sorted-order
ls jf_test_* | sed 's/^\([^0-9]*\)\([0-9]*\)/\1 \2/' | sort -k2,2n | tr -d ' ' |
while read TEST; do
# It would be nice to run json output printed to stdout through jsonlint, however,
# some tests output more than one json structure and these need to be split
echo ""
echo "======================================================"
echo ""
echo "Running ${TEST}"
cd ..
"${BINDIR}${TEST}"
cd "$BINDIR"
done)
echo ""
echo "======================================================"
GLOBIGNORE="$OLD_IGNORES"
if [[ $CODE_COVERAGE = [yY]* ]] ; then
for SRCFILE in json_string_utilities.F90 json_value_module.F90 json_file_module.F90 ; do
[ -f ${SRCDIR}${SRCFILE}.gcov ] && rm ${SRCDIR}${SRCFILE}.gcov
gcov -o $LIBDIR ${SRCDIR}${SRCFILE}
if [[ $TRY_UNICODE = [yY]* ]] ; then
# gcov/gfortran bug work around
awk -F':' '{line=""; for(i=2;i<=NF;i++){line=line":"$i}; if (NR > 1) print $1 prevline; prevline=line}; END{print " -"prevline}' ${SRCFILE}.gcov > ${SRCFILE}.gcov.fixed && \
mv ${SRCFILE}.gcov{.fixed,}
# rename so we can merge coverage info
mv ${SRCFILE}.gcov ${SRCFILE}-unicode.gcov
else
# rename so we can merge coverage info
mv ${SRCFILE}.gcov ${SRCFILE}-no-unicode.gcov
fi
if [ -f ${SRCFILE}-unicode.gcov ] && [ -f ${SRCFILE}-no-unicode.gcov ]; then
############## for debugging
#echo ""
#echo "-------------------"
#echo "no-unicode file"
#echo "-------------------"
#cat ${SRCFILE}-no-unicode.gcov
#echo ""
#echo "-------------------"
#echo "unicode file"
#echo "-------------------"
#cat ${SRCFILE}-unicode.gcov
#echo ""
#./pages/development-resources/gccr.pl -n -c ${SRCFILE}-no-unicode.gcov no-unicode \
# ${SRCFILE}-unicode.gcov unicode
##############
# merge them
./pages/development-resources/gccr.pl -n -c ${SRCFILE}-no-unicode.gcov no-unicode \
${SRCFILE}-unicode.gcov unicode > ${SRCFILE}.gcov
else
cp ${SRCFILE}*-unicode.gcov ${SRCFILE}.gcov
fi
done
FoBiS.py rule -gcov_analyzer .
for SRCFILE in json_string_utilities.F90 json_value_module.F90 json_file_module.F90 ; do
sed -i"bak" -E 's; \*\*([a-zA-Z]+[a-zA-Z0-9_]*)\*\*; \*\*[[\1]]\*\*;' ${SRCFILE}.gcov.md
sed -i"bak" -E "s;, line ([0-9]+);, line [\1](https://github.com/jacobwilliams/json-fortran/blob/master/src/${SRCFILE}#L\1);" ${SRCFILE}.gcov.md
done
gcov -o $BINDIR ${TESTDIR}*.[Ff]90
fi
else
echo "Skip running the unit tests since \$JF_SKIP_TESTS has been set to ${JF_SKIP_TESTS}."
fi
#build the documentation with ford (if present):
echo ""
if [[ $JF_SKIP_DOCS != [yY]* ]]; then
if hash ford 2>/dev/null; then
echo "Building documentation..."
[[ $TRY_UNICODE = [yY]* ]] && MACRO_FLAG=("-m" "USE_UCS4")
echo "$FPP" > .PREPROCESSOR # Override via include in project file, until FORD gets CLI for this
ford --debug "${MACRO_FLAG[@]}" -p "$PAGESDIR" "$FORDMD"
else
echo "FORD not found! Install using: pip install ford"
fi
else
echo "Skip building documentation since \$JF_SKIP_DOCS has been set to ${JF_SKIP_DOCS}."
fi