diff --git a/data/Makefile.in b/data/Makefile.in index 5229de31..3afc9237 100644 --- a/data/Makefile.in +++ b/data/Makefile.in @@ -87,12 +87,10 @@ DEV_TARGET ?= devrun GT_TARGET ?= gtrun GT_OUT := ground-truth.csv -UNAME_S := $(shell uname -s) +UNAME_S := {uname} # will be None if not specified in flit-config.toml -CLANG := {clang_compiler} -INTEL := {intel_compiler} -GCC := {gcc_compiler} +{compiler_defs} CLANG_TYPE := clang INTEL_TYPE := intel GCC_TYPE := gcc @@ -227,7 +225,7 @@ GT_OBJ = $(addprefix $(OBJ_DIR)/,$(notdir $(SOURCE:%.cpp=%_gt.o))) GT_DEPS = $(GT_OBJ:%.o=%.d) GT_OBJ_FPIC = $(GT_OBJ:%.o=%_fPIC.o) -HOSTNAME := $(shell hostname) +HOSTNAME := {hostname} RESULTS_DIR := results @@ -245,128 +243,19 @@ endif # more comp settings, taken from here: # https://software.intel.com/sites/default/files/article/326703/fp-control-2012-08.pdf -#individual flags +# individual flags + ## optls -O0 := -O0 -O1 := -O1 -O2 := -O2 -O3 := -O3 - -#switches - -ASSOCMATH := -fassociative-math -AVX := -mavx -COMPTRANS := -mp1 -DEFFLAGS := -DISFMA := -no-fma -ENAFMA := -fma -FASTEXPREC := -fexcess-precision=fast -FASTM := -ffast-math -FINMATH := -ffinite-math-only -FLUSHDEN := -ftz -FMAGCC := -mavx2 -mfma -FMAICC := -march=core-avx2 -FORTRULES := -fcx-fortran-rules -FPCONT := -ffp-contract=on -FPMODDBL := -fp-model=double -FPMODEXC := -fp-model=except -FPMODEXT := -fp-model=extended -FPMODFST1 := -fp-model fast=1 -FPMODFST2 := -fp-model fast=2 -FPMODPRE := -fp-model=precise -FPMODSRC := -fp-model=source -FPMODSTR := -fp-model=strict -FPTRAP := -fp-trap=common -FSTORE := -ffloat-store -LIMITEDRANGE := -fcx-limited-range -MCONSTS := -fmerge-all-constants -NOFLUSHDEN := -no-ftz -NOPRECDIV := -no-prec-div -NOTRAP := -fno-trapping-math -PRECDIV := -prec-div -RECIPMATH := -freciprocal-math -ROUNDINGMATH := -frounding-math -ROUNDUSR := -fp-port -SIGNALNAN := -fsignaling-nans -SINGLEPRECCONST := -fsingle-precision-constant -SSE := -mfpmath=sse -mtune=native -STDEXPREC := -fexcess-precision=standard -UNSOPTS := -funsafe-math-optimizations -USEFASTM := --use_fast_math - -# Collections - -OPCODES := O0 O1 O2 O3 - -# NOTE: gcc disables ASSOCMATH @ O0 -SWITCHES_GCC += ASSOCMATH -SWITCHES_GCC += AVX -SWITCHES_GCC += DEFFLAGS -SWITCHES_GCC += FASTEXPREC -SWITCHES_GCC += FINMATH -SWITCHES_GCC += FMAGCC -SWITCHES_GCC += FORTRULES -SWITCHES_GCC += FPCONT -SWITCHES_GCC += FSTORE -SWITCHES_GCC += LIMITEDRANGE -SWITCHES_GCC += MCONSTS -SWITCHES_GCC += NOTRAP -SWITCHES_GCC += RECIPMATH -SWITCHES_GCC += ROUNDINGMATH -SWITCHES_GCC += SIGNALNAN -SWITCHES_GCC += SSE -SWITCHES_GCC += UNSOPTS - -#NOTE: Clang not honoring ASSOCMATH (issues warning with 3.9) -# see: https://llvm.org/bugs/show_bug.cgi?id=27372 - -SWITCHES_CLANG += ASSOCMATH -SWITCHES_CLANG += AVX -SWITCHES_CLANG += DEFFLAGS -SWITCHES_CLANG += FASTEXPREC -SWITCHES_CLANG += FINMATH -SWITCHES_CLANG += FMAGCC -SWITCHES_CLANG += FMAICC -SWITCHES_CLANG += FPCONT -SWITCHES_CLANG += FSTORE -SWITCHES_CLANG += MCONSTS -SWITCHES_CLANG += NOTRAP -SWITCHES_CLANG += RECIPMATH -SWITCHES_CLANG += ROUNDINGMATH -SWITCHES_CLANG += SIGNALNAN -SWITCHES_CLANG += SINGLEPRECCONST -SWITCHES_CLANG += SSE -SWITCHES_CLANG += STDEXPREC -SWITCHES_CLANG += UNSOPTS - -SWITCHES_INTEL += AVX -SWITCHES_INTEL += COMPTRANS -SWITCHES_INTEL += DEFFLAGS -SWITCHES_INTEL += DISFMA -SWITCHES_INTEL += ENAFMA -SWITCHES_INTEL += FLUSHDEN -SWITCHES_INTEL += FMAGCC -SWITCHES_INTEL += FMAICC -SWITCHES_INTEL += FPMODDBL -SWITCHES_INTEL += FPMODEXT -SWITCHES_INTEL += FPMODFST1 -SWITCHES_INTEL += FPMODFST2 -SWITCHES_INTEL += FPMODPRE -SWITCHES_INTEL += FPMODSRC -SWITCHES_INTEL += FPMODSTR -SWITCHES_INTEL += FSTORE -SWITCHES_INTEL += LIMITEDRANGE -SWITCHES_INTEL += MCONSTS -SWITCHES_INTEL += NOFLUSHDEN -SWITCHES_INTEL += NOPRECDIV -SWITCHES_INTEL += PRECDIV -SWITCHES_INTEL += ROUNDINGMATH -SWITCHES_INTEL += ROUNDUSR -SWITCHES_INTEL += SINGLEPRECCONST -SWITCHES_INTEL += SSE -SWITCHES_INTEL += USEFASTM +{opcodes_definitions} + +## switches + +{switches_definitions} + +{compiler_opcodes} +{compiler_switches} ########################################################## # @@ -459,7 +348,7 @@ TARGET_OUTS := # @param 1: compiler variable name (e.g. CLANG) # @param 2: optimization level variable name (e.g. O2) -# @param 3: switches variable name (e.g. USEFASTM) +# @param 3: switches variable name (e.g. USE_FAST_MATH) define RECURSION_RULE TARGETS += $$(RESULTS_DIR)/$(strip $1)_$$(HOSTNAME)_$(strip $3)_$(strip $2) @@ -482,7 +371,7 @@ endef $(foreach c, $(COMPILERS), \ $(foreach s, $(SWITCHES_$(strip $c)), \ - $(foreach o, $(OPCODES), \ + $(foreach o, $(OPCODES_$(strip $c)), \ $(eval $(call RECURSION_RULE, $c, $o, $s))))) TARGET_OUTS := $(TARGETS:%=%-out) TARGET_RESULTS := $(TARGET_OUTS:%=%-comparison.csv) diff --git a/documentation/available-compiler-flags.md b/documentation/available-compiler-flags.md index 64006a45..a7084176 100644 --- a/documentation/available-compiler-flags.md +++ b/documentation/available-compiler-flags.md @@ -12,15 +12,6 @@ Convenient TOML lists: * [Clang](#clang) * [Intel](#intel) -Currently, the configuration file does not specify the flags and optimization -levels to use. We plan to change this in future updates. Consider the -documentation below to relate to future desired features. See -[issue-119](https://github.com/PRUNERS/FLiT/issues/119). - -The flags below are still useful to understand because they are the current -flags that are hard-coded into the autogenerated `Makefile`. Below is a -comprehensive list of switches used. - ## All Flags @@ -73,9 +64,15 @@ For your convenience, here are toml-style lists that can be copied into your ## GCC +**Note:** in some versions of python-toml, there is a parsing bug when a list +has an empty string in the middle. So simply put it at the end without a +comma. This has been fixed in the latest version of python-toml. + +You will likely want the empty string in your search space as it represents the +absence of any switches. + ```toml -switches = [ - '', +switches_list = [ '-fassociative-math', '-fcx-fortran-rules', '-fcx-limited-range', @@ -92,14 +89,14 @@ switches = [ '-mavx', '-mavx2 -mfma', '-mfpmath=sse -mtune=native', + '' ] ``` ## Clang ```toml -switches = [ - '', +switches_list = [ '-fassociative-math', '-fexcess-precision=fast', '-fexcess-precision=standard', @@ -117,14 +114,14 @@ switches = [ '-mavx', '-mavx2 -mfma', '-mfpmath=sse -mtune=native', + '' ] ``` ## Intel ```toml -switches = [ - '', +switches_list = [ '--use_fast_math', '-fcx-limited-range', '-ffloat-store', @@ -151,6 +148,7 @@ switches = [ '-no-ftz', '-no-prec-div', '-prec-div', + '' ] ``` diff --git a/documentation/flit-configuration-file.md b/documentation/flit-configuration-file.md index acb6deec..e169878b 100644 --- a/documentation/flit-configuration-file.md +++ b/documentation/flit-configuration-file.md @@ -155,6 +155,31 @@ executable. binary = 'g++' name = 'g++' type = 'gcc' +optimization_levels = [ + '-O0', + '-O1', + '-O2', + '-O3', +] +switches_list = [ + '-fassociative-math', + '-fcx-fortran-rules', + '-fcx-limited-range', + '-fexcess-precision=fast', + '-ffinite-math-only', + '-ffloat-store', + '-ffp-contract=on', + '-fmerge-all-constants', + '-fno-trapping-math', + '-freciprocal-math', + '-frounding-math', + '-fsignaling-nans', + '-funsafe-math-optimizations', + '-mavx', + '-mavx2 -mfma', + '-mfpmath=sse -mtune=native', + '' +] ``` Here we specify the first compiler. @@ -170,6 +195,15 @@ Here we specify the first compiler. - `type`: The type of compiler. The supported types are `gcc`, `clang` and `intel`. If you need an additional type supported, please submit an [issue](https://github.com/PRUNERS/FLiT/issues). +- `optimization_levels`: List of optimization levels to search over. You may + remove from or add to this list. If you omit this list, the default list + will be used (which is the same as the one shown here). The defaults are + specific to the type of compiler. See below for the default list for the + other supported compilers. +- `switches_list`: List of switches to search over. You may remove from or add + to this list. If you omit this list, the default list will be used (which is + the same as the one shown here). The defaults are specific to the type of + compiler. See below for the default list for the other supported compilers. Note that the section has two square brackets around it instead of one. This indicates that it is an array and subsequent instances of `[[compiler]]` will @@ -183,11 +217,72 @@ which includes the one from above named `g++` and the following two: binary = 'clang++' name = 'clang++' type = 'clang' +optimization_levels = [ + '-O0', + '-O1', + '-O2', + '-O3', +] +switches_list = [ + '-fassociative-math', + '-fexcess-precision=fast', + '-fexcess-precision=standard', + '-ffinite-math-only', + '-ffloat-store', + '-ffp-contract=on', + '-fmerge-all-constants', + '-fno-trapping-math', + '-freciprocal-math', + '-frounding-math', + '-fsignaling-nans', + '-fsingle-precision-constant', + '-funsafe-math-optimizations', + '-march=core-avx2', + '-mavx', + '-mavx2 -mfma', + '-mfpmath=sse -mtune=native', + '' +] [[compiler]] binary = 'icpc' name = 'icpc' type = 'intel' +optimization_levels = [ + '-O0', + '-O1', + '-O2', + '-O3', +] +switches_list = [ + '--use_fast_math', + '-fcx-limited-range', + '-ffloat-store', + '-fma', + '-fmerge-all-constants', + '-fp-model fast=1', + '-fp-model fast=2', + '-fp-model=double', + '-fp-model=except', + '-fp-model=extended', + '-fp-model=precise', + '-fp-model=source', + '-fp-model=strict', + '-fp-port', + '-frounding-math', + '-fsingle-precision-constant', + '-ftz', + '-march=core-avx2', + '-mavx', + '-mavx2 -mfma', + '-mfpmath=sse -mtune=native', + '-mp1', + '-no-fma', + '-no-ftz', + '-no-prec-div', + '-prec-div', + '' +] ``` Do not worry if you do not have all of the compilers on your system, they will @@ -231,16 +326,102 @@ switches = '' binary = 'g++' name = 'g++' type = 'gcc' +optimization_levels = [ + '-O0', + '-O1', + '-O2', + '-O3', +] +switches_list = [ + '-fassociative-math', + '-fcx-fortran-rules', + '-fcx-limited-range', + '-fexcess-precision=fast', + '-ffinite-math-only', + '-ffloat-store', + '-ffp-contract=on', + '-fmerge-all-constants', + '-fno-trapping-math', + '-freciprocal-math', + '-frounding-math', + '-fsignaling-nans', + '-funsafe-math-optimizations', + '-mavx', + '-mavx2 -mfma', + '-mfpmath=sse -mtune=native', + '' +] [[compiler]] binary = 'clang++' name = 'clang++' type = 'clang' +optimization_levels = [ + '-O0', + '-O1', + '-O2', + '-O3', +] +switches_list = [ + '-fassociative-math', + '-fexcess-precision=fast', + '-fexcess-precision=standard', + '-ffinite-math-only', + '-ffloat-store', + '-ffp-contract=on', + '-fmerge-all-constants', + '-fno-trapping-math', + '-freciprocal-math', + '-frounding-math', + '-fsignaling-nans', + '-fsingle-precision-constant', + '-funsafe-math-optimizations', + '-march=core-avx2', + '-mavx', + '-mavx2 -mfma', + '-mfpmath=sse -mtune=native', + '' +] [[compiler]] binary = 'icpc' name = 'icpc' type = 'intel' +optimization_levels = [ + '-O0', + '-O1', + '-O2', + '-O3', +] +switches_list = [ + '--use_fast_math', + '-fcx-limited-range', + '-ffloat-store', + '-fma', + '-fmerge-all-constants', + '-fp-model fast=1', + '-fp-model fast=2', + '-fp-model=double', + '-fp-model=except', + '-fp-model=extended', + '-fp-model=precise', + '-fp-model=source', + '-fp-model=strict', + '-fp-port', + '-frounding-math', + '-fsingle-precision-constant', + '-ftz', + '-march=core-avx2', + '-mavx', + '-mavx2 -mfma', + '-mfpmath=sse -mtune=native', + '-mp1', + '-no-fma', + '-no-ftz', + '-no-prec-div', + '-prec-div', + '' +] ``` diff --git a/gensrc/expression.py b/gensrc/expression.py index 0d55d27a..754f55b4 100644 --- a/gensrc/expression.py +++ b/gensrc/expression.py @@ -158,10 +158,6 @@ def __repr__(self): def random_expression(env, length, vars_only=False): ''' Generates a random mathematical expression as a string - - >>> env = Environment({'x'; Variable('x', 'int'}) - >>> random_expression(env, 3) - Expression((x + 3.25124) * x) ''' # Populate the expression with operations expr = Expression() diff --git a/scripts/flitcli/config/flit-default.toml.in b/scripts/flitcli/config/flit-default.toml.in index dc37017e..5e44f117 100644 --- a/scripts/flitcli/config/flit-default.toml.in +++ b/scripts/flitcli/config/flit-default.toml.in @@ -132,6 +132,8 @@ mpirun_args = '' [dev_build] # compiler_name must be found in the [[compiler]] list under the name attribute +# The optimization level and switches need not match those found in the +# associated [[compiler]] compiler_name = 'g++' optimization_level = '-O2' switches = '-funsafe-math-optimizations' @@ -141,16 +143,18 @@ switches = '-funsafe-math-optimizations' [ground_truth] # compiler_name must be found in the [[compiler]] list under the name attribute +# The optimization level and switches need not match those found in the +# associated [[compiler]] compiler_name = 'g++' optimization_level = '-O0' switches = '' -# List of compilers. +# This host's list of compilers. # - binary: can be an absolute path, relative path, or binary name (found in # PATH). If you want to specify a compiler in the same directory as this # config file, prepend with a "./" (e.g. "./my-compiler") # - name: can be any string. Used to recognize in the other options such as -# in [dev_build] and [ground_truth] +# dev_build and ground_truth # - type: the brand of the compiler. We support ('gcc', 'clang', 'intel') # Currently, only one of each type may be specified. # Note that these are all defaulted to use g++, clang++, and icpc from the @@ -162,14 +166,117 @@ switches = '' binary = 'g++' name = 'g++' type = 'gcc' +# search space of optimization levels +optimization_levels = [ + '-O0', + '-O1', + '-O2', + '-O3', +] +# search space of compiler switches. +# Note: in some versions of python-toml, there is a parsing bug when a list +# has an empty string in the middle. So simply put it at the end without +# a comma. This has been fixed in the latest version of python-toml. +# Note: gcc disables -fassociative-math @ O0 +switches_list = [ + '-fassociative-math', + '-fcx-fortran-rules', + '-fcx-limited-range', + '-fexcess-precision=fast', + '-ffinite-math-only', + '-ffloat-store', + '-ffp-contract=on', + '-fmerge-all-constants', + '-fno-trapping-math', + '-freciprocal-math', + '-frounding-math', + '-fsignaling-nans', + '-funsafe-math-optimizations', + '-mavx', + '-mavx2 -mfma', + '-mfpmath=sse -mtune=native', + '' +] [[compiler]] binary = 'clang++' name = 'clang++' type = 'clang' +# search space of optimization levels +optimization_levels = [ + '-O0', + '-O1', + '-O2', + '-O3', +] +# search space of compiler switches. +# Note: in some versions of python-toml, there is a parsing bug when a list +# has an empty string in the middle. So simply put it at the end without +# a comma. This has been fixed in the latest version of python-toml. +# Note: Clang not honoring -fassociative-math (issues warning with 3.9) +# see: https://llvm.org/bugs/show_bug.cgi?id=27372 +switches_list = [ + '-fassociative-math', + '-fexcess-precision=fast', + '-fexcess-precision=standard', + '-ffinite-math-only', + '-ffloat-store', + '-ffp-contract=on', + '-fmerge-all-constants', + '-fno-trapping-math', + '-freciprocal-math', + '-frounding-math', + '-fsignaling-nans', + '-fsingle-precision-constant', + '-funsafe-math-optimizations', + '-march=core-avx2', + '-mavx', + '-mavx2 -mfma', + '-mfpmath=sse -mtune=native', + '' +] [[compiler]] binary = 'icpc' name = 'icpc' type = 'intel' - +# search space of optimization levels +optimization_levels = [ + '-O0', + '-O1', + '-O2', + '-O3', +] +# search space of compiler switches. +# Note: in some versions of python-toml, there is a parsing bug when a list +# has an empty string in the middle. So simply put it at the end without +# a comma. This has been fixed in the latest version of python-toml. +switches_list = [ + '--use_fast_math', + '-fcx-limited-range', + '-ffloat-store', + '-fma', + '-fmerge-all-constants', + '-fp-model fast=1', + '-fp-model fast=2', + '-fp-model=double', + '-fp-model=except', + '-fp-model=extended', + '-fp-model=precise', + '-fp-model=source', + '-fp-model=strict', + '-fp-port', + '-frounding-math', + '-fsingle-precision-constant', + '-ftz', + '-march=core-avx2', + '-mavx', + '-mavx2 -mfma', + '-mfpmath=sse -mtune=native', + '-mp1', + '-no-fma', + '-no-ftz', + '-no-prec-div', + '-prec-div', + '' +] diff --git a/scripts/flitcli/flit.py b/scripts/flitcli/flit.py index f5ae92bb..8317158a 100755 --- a/scripts/flitcli/flit.py +++ b/scripts/flitcli/flit.py @@ -160,7 +160,7 @@ def generate_help_documentation(subcom_map): return (parser.format_help(), help_subparser.format_help()) -def main(arguments, outstream=None): +def main(arguments, outstream=None, errstream=None): ''' Main logic here. @@ -168,14 +168,19 @@ def main(arguments, outstream=None): optional outstream parameter. You can use this to capture the stdout that would go to the console and put it into a StringStream or maybe a file. ''' - if outstream is None: + if outstream is None and errstream is None: return _main_impl(arguments) + oldout = sys.stdout + olderr = sys.stderr try: - oldout = sys.stdout - sys.stdout = outstream + if outstream is not None: + sys.stdout = outstream + if errstream is not None: + sys.stderr = errstream return _main_impl(arguments) finally: sys.stdout = oldout + sys.stderr = olderr def _main_impl(arguments): 'Implementation of main' diff --git a/scripts/flitcli/flit_bisect.py b/scripts/flitcli/flit_bisect.py index 17f1292a..f7028c21 100644 --- a/scripts/flitcli/flit_bisect.py +++ b/scripts/flitcli/flit_bisect.py @@ -309,10 +309,10 @@ def run_make(makefilename='Makefile', directory='.', verbose=False, ... except: ... pass ERROR:root:make error occurred. Here is the output: - make: Entering directory `...' + make: Entering directory ... hello - make: *** [default] Error 1 - make: Leaving directory `...' + make: *** [...default] Error 1 + make: Leaving directory ... Undo the logger configurations diff --git a/scripts/flitcli/flit_update.py b/scripts/flitcli/flit_update.py index 18cdd61b..183caf77 100644 --- a/scripts/flitcli/flit_update.py +++ b/scripts/flitcli/flit_update.py @@ -84,6 +84,7 @@ import argparse import os +import re import sys import toml @@ -91,9 +92,10 @@ import flitutil brief_description = 'Updates the Makefile based on flit-config.toml' +_supported_compiler_types = ('clang', 'gcc', 'intel') -def main(arguments, prog=sys.argv[0]): - 'Main logic here' +def parse_args(arguments, prog=sys.argv[0]): + 'Return parsed arugments' parser = argparse.ArgumentParser( prog=prog, description=''' @@ -107,15 +109,190 @@ def main(arguments, prog=sys.argv[0]): parser.add_argument('-C', '--directory', default='.', help='The directory to initialize') args = parser.parse_args(arguments) + return args + +def load_projconf(directory): + ''' + Loads and returns the project configuration found in the given tomlfile. + This function checks for validity of that tomlfile and fills it with + default values. - tomlfile = os.path.join(args.directory, 'flit-config.toml') + @param directory: directory containing 'flit-config.toml'. + + @return project configuration as a struct of dicts and lists depending on + the structure of the given tomlfile. + ''' + tomlfile = os.path.join(directory, 'flit-config.toml') try: projconf = toml.load(tomlfile) except FileNotFoundError: print('Error: {0} not found. Run "flit init"'.format(tomlfile), file=sys.stderr) + raise + + defaults = flitutil.get_default_toml() + + if 'compiler' in projconf: + assert isinstance(projconf['compiler'], list), \ + 'flit-config.toml improperly configured, ' \ + 'needs [[compiler]] section' + + default_type_map = {c['type']: c for c in defaults['compiler']} + type_map = {} # type -> compiler + name_map = {} # name -> compiler + for compiler in projconf['compiler']: + + # make sure each compiler has a name, type, and binary + for field in ('name', 'type', 'binary'): + assert field in compiler, \ + 'flit-config.toml: compiler "{0}"'.format(compiler) + \ + ' is missing the "{0}" field'.format(field) + + # check that the type is valid + assert compiler['type'] in _supported_compiler_types, \ + 'flit-config.toml: unsupported compiler type "{0}"' \ + .format(compiler['type']) + + # check that we only have one of each type specified + assert compiler['type'] not in type_map, \ + 'flit-config.toml: cannot have multiple compilers of the ' \ + 'same type ({0})'.format(compiler['type']) + type_map[compiler['type']] = compiler + + # check that we only have one of each name specified + assert compiler['name'] not in name_map, \ + 'flit-config.toml: cannot have multiple compilers of the ' \ + 'same name ({0})'.format(compiler['name']) + name_map[compiler['name']] = compiler + + # if optimization_levels or switches_list are missing for any + # compiler, put in the default flags for that compiler + default = default_type_map[compiler['type']] + for field in ('optimization_levels', 'switches_list'): + if field not in compiler: + compiler[field] = default[field] + + # Fill in the rest of the default values + flitutil.fill_defaults(projconf, defaults) + + return projconf + +def flag_name(flag): + ''' + Returns an associated Makefile variable name for the given compiler flag + + @param flag: (str) switches for the compiler + + @return (str) a valid Makefile variable unique to the given flag + + >>> flag_name('') + 'NO_FLAGS' + + >>> flag_name('-') + Traceback (most recent call last): + ... + AssertionError: Error: cannot handle flag only made of dashes + + >>> flag_name('----') + Traceback (most recent call last): + ... + AssertionError: Error: cannot handle flag only made of dashes + + >>> flag_name('-funsafe-math-optimizations') + 'FUNSAFE_MATH_OPTIMIZATIONS' + + >>> flag_name('-Ofast -march=32bit') + 'OFAST__MARCH_32BIT' + ''' + if flag == '': + return 'NO_FLAGS' + name = re.sub('[^0-9A-Za-z]', '_', flag.upper().strip('-')) + assert re.match('^[0-9]', name) is None, \ + 'Error: cannot handle flag that starts with a number' + assert len(name) > 0, 'Error: cannot handle flag only made of dashes' + return name + +def gen_assignments(flag_map): + ''' + Given a mapping of Makefile variable name to value, create a single string + of assignments suitable for placing within a Makefile + + @note no checking is performed on the keys of the map. They are assumed to + be valid Makefile variables + + @param flag_map: ({str: str}) mapping from Makefile variable name to + Makefile value. + @return (str) The string to insert into a Makefile to create the + assignments + + >>> gen_assignments({}) + '' + + >>> gen_assignments({'single_name': 'single_value'}) + 'single_name := single_value' + + Here we use an OrderedDict for the test to be robust. If we used a normal + dict, then the output lines could show up in a different order. + >>> from collections import OrderedDict + >>> print(gen_assignments( + ... OrderedDict([('hello', 'there'), ('my', 'friend')]))) + hello := there + my := friend + + >>> print(gen_assignments(OrderedDict([ + ... ('REALLY_A_VERY_LONG_VARIABLE_NAME_HERE', 'bob'), + ... ('not_so_long_32', 'harry'), + ... ('short', 'very long value here'), + ... ]))) + REALLY_A_VERY_LONG_VARIABLE_NAME_HERE := bob + not_so_long_32 := harry + short := very long value here + ''' + name_assignments = ['{} := {}'.format(name.ljust(15), flag) + for name, flag in flag_map.items()] + return '\n'.join(name_assignments) + +def gen_multi_assignment(name, values): + ''' + Generates a multi-line assignment string for a Makefile + + @note no checking is done on the name or values to see if they are valid to + place within a Makefile. + + @param name: (str) Makefile variable name + @param values: (iter(str)) iterable of values to assign, one per line + + @return (str) a single string with the multi-line assignment suitable for a + Makefile. + + >>> gen_multi_assignment('CLANG', None) + 'CLANG :=' + + >>> gen_multi_assignment('CLANG', []) + 'CLANG :=' + + >>> print(gen_multi_assignment('hello_there', ['my friend', 'my enemy'])) + hello_there := + hello_there += my friend + hello_there += my enemy + ''' + values = values or tuple() # if None, set to an empty tuple + justified = name.ljust(15) + beginning = justified + ' :=' + return '\n'.join( + [beginning] + ['{} += {}'.format(justified, x) for x in values]) + +def main(arguments, prog=sys.argv[0]): + 'Main logic here' + args = parse_args(arguments, prog=prog) + + try: + projconf = load_projconf(args.directory) + except FileNotFoundError: + return 1 + except AssertionError as ex: + print('Error: ' + ex.args[0], file=sys.stderr) return 1 - flitutil.fill_defaults(projconf) makefile = os.path.join(args.directory, 'Makefile') if os.path.exists(makefile): @@ -124,44 +301,20 @@ def main(arguments, prog=sys.argv[0]): print('Creating {0}'.format(makefile)) dev_build = projconf['dev_build'] - dev_compiler_name = dev_build['compiler_name'] - dev_optl = dev_build['optimization_level'] - dev_switches = dev_build['switches'] matching_dev_compilers = [x for x in projconf['compiler'] - if x['name'] == dev_compiler_name] + if x['name'] == dev_build['compiler_name']] assert len(matching_dev_compilers) > 0, \ - 'Compiler name {0} not found'.format(dev_compiler_name) - assert len(matching_dev_compilers) < 2, \ - 'Multiple compilers with name {0} found'.format(dev_compiler_name) - dev_compiler_bin = matching_dev_compilers[0]['binary'] - dev_compiler_type = matching_dev_compilers[0]['type'] - #if '/' in dev_compiler_bin: - # dev_compiler_bin = os.path.realpath(dev_compiler_bin) + 'Compiler name {0} not found'.format(dev_build['compiler_name']) ground_truth = projconf['ground_truth'] - gt_compiler_name = ground_truth['compiler_name'] - gt_optl = ground_truth['optimization_level'] - gt_switches = ground_truth['switches'] matching_gt_compilers = [x for x in projconf['compiler'] - if x['name'] == gt_compiler_name] - assert len(matching_dev_compilers) > 0, \ - 'Compiler name {0} not found'.format(gt_compiler_name) - assert len(matching_dev_compilers) < 2, \ - 'Multiple compilers with name {0} found'.format(gt_compiler_name) - # TODO: use the compiler mnemonic rather than the path - gt_compiler_bin = matching_gt_compilers[0]['binary'] - gt_compiler_type = matching_gt_compilers[0]['type'] - #if '/' in dev_compiler_bin: - # gt_compiler_bin = os.path.realpath(gt_compiler_bin) - - supported_compiler_types = ('clang', 'gcc', 'intel') - base_compilers = {x: None for x in supported_compiler_types} - for compiler in projconf['compiler']: - assert compiler['type'] in supported_compiler_types, \ - 'Unsupported compiler type: {}'.format(compiler['type']) - assert base_compilers[compiler['type']] is None, \ - 'You can only specify one of each type of compiler.' - base_compilers[compiler['type']] = compiler['binary'] + if x['name'] == ground_truth['compiler_name']] + assert len(matching_gt_compilers) > 0, \ + 'Compiler name {0} not found'.format(ground_truth['compiler_name']) + + base_compilers = {x.upper(): None for x in _supported_compiler_types} + base_compilers.update({compiler['type'].upper(): compiler['binary'] + for compiler in projconf['compiler']}) test_run_args = '' if not projconf['run']['timing']: @@ -172,17 +325,17 @@ def main(arguments, prog=sys.argv[0]): '--timing-repeats', str(projconf['run']['timing_repeats']), ]) - given_compilers = [key.upper() for key, val in base_compilers.items() - if val is not None] replacements = { - 'dev_compiler': dev_compiler_bin, - 'dev_type': dev_compiler_type, - 'dev_optl': dev_optl, - 'dev_switches': dev_switches, - 'ground_truth_compiler': gt_compiler_bin, - 'ground_truth_type': gt_compiler_type, - 'ground_truth_optl': gt_optl, - 'ground_truth_switches': gt_switches, + 'uname': os.uname().sysname, + 'hostname': os.uname().nodename, + 'dev_compiler': matching_dev_compilers[0]['binary'], + 'dev_type': matching_dev_compilers[0]['type'], + 'dev_optl': dev_build['optimization_level'], + 'dev_switches': dev_build['switches'], + 'ground_truth_compiler': matching_gt_compilers[0]['binary'], + 'ground_truth_type': matching_gt_compilers[0]['type'], + 'ground_truth_optl': ground_truth['optimization_level'], + 'ground_truth_switches': ground_truth['switches'], 'flit_include_dir': conf.include_dir, 'flit_lib_dir': conf.lib_dir, 'flit_data_dir': conf.data_dir, @@ -191,10 +344,29 @@ def main(arguments, prog=sys.argv[0]): 'test_run_args': test_run_args, 'enable_mpi': 'yes' if projconf['run']['enable_mpi'] else 'no', 'mpirun_args': projconf['run']['mpirun_args'], - 'compilers': ' '.join(given_compilers), + 'compiler_defs': gen_assignments({ + key: val for key, val in base_compilers.items()}), + 'compilers': ' '.join([compiler['type'].upper() + for compiler in projconf['compiler']]), + 'opcodes_definitions': gen_assignments({ + flag_name(x): x + for compiler in projconf['compiler'] + for x in compiler['optimization_levels']}), + 'switches_definitions': gen_assignments({ + flag_name(x): x + for compiler in projconf['compiler'] + for x in compiler['switches_list']}), + 'compiler_opcodes': '\n\n'.join([ + gen_multi_assignment( + 'OPCODES_' + compiler['type'].upper(), + [flag_name(x) for x in compiler['optimization_levels']]) + for compiler in projconf['compiler']]), + 'compiler_switches': '\n\n'.join([ + gen_multi_assignment( + 'SWITCHES_' + compiler['type'].upper(), + [flag_name(x) for x in compiler['switches_list']]) + for compiler in projconf['compiler']]), } - replacements.update({key + '_compiler': val - for key, val in base_compilers.items()}) flitutil.process_in_file(os.path.join(conf.data_dir, 'Makefile.in'), makefile, replacements, overwrite=True) diff --git a/scripts/flitcli/flitutil.py b/scripts/flitcli/flitutil.py index 2bc35a90..2adeff64 100644 --- a/scripts/flitcli/flitutil.py +++ b/scripts/flitcli/flitutil.py @@ -350,6 +350,65 @@ def extract_make_var(var, makefile='Makefile', directory='.'): var_values = output.split('=', maxsplit=1)[1].split() return var_values +def extract_make_vars(makefile='Makefile', directory='.'): + ''' + Extracts all GNU Make variables from the given Makefile, except for those + that are built-in. It is returned as a dictionary of + {'var': ['val', ...]} + + @note, all variables are returned, including internal Makefile + variables. + + >>> from tempfile import NamedTemporaryFile as NTF + >>> with NTF(mode='w+') as fout: + ... print('A := hello there sweetheart\\n' + ... 'B = \\n', + ... file=fout, flush=True) + ... allvars = extract_make_vars(fout.name) + + >>> allvars['A'] + ['hello', 'there', 'sweetheart'] + >>> allvars['B'] + [] + + What if the file does not exist? It throws an exception: + + >>> extract_make_var('A', 'file-should-not-exist.mk') # doctest: +ELLIPSIS + Traceback (most recent call last): + ... + subprocess.CalledProcessError: Command ... returned non-zero exit status 2. + ''' + with tempfile.NamedTemporaryFile(mode='w+') as fout: + print('$(foreach v,$(.VARIABLES),$(info $(v)=$($(v))**==**))\n' + '.PHONY: empty-target\n' + 'empty-target:\n' + "\t@true\n", file=fout, flush=True) + output = subp.check_output( + ['make', '-f', makefile, '-f', fout.name, 'empty-target', + '--directory', directory, '--no-print-directory'], + stderr=subp.DEVNULL) + lines = output.strip().decode('utf-8').splitlines() + var_values = {} + prevkey = None + for line in lines: + if prevkey is None: + split = line.split('=', maxsplit=1) + prevkey = split[0] + values = split[1] + var_values[prevkey] = [] + else: + values = line + + key = prevkey + + if values.endswith('**==**'): + values = values.replace('**==**', '') + prevkey = None + + var_values[key].extend(values.split()) + + return var_values + def printlog(message): ''' Prints the message to stdout and then logs the message at the info level. diff --git a/tests/flit_cli/flit_update/Makefile b/tests/flit_cli/flit_update/Makefile new file mode 100644 index 00000000..ce0c8e04 --- /dev/null +++ b/tests/flit_cli/flit_update/Makefile @@ -0,0 +1,23 @@ +RUNNER := python3 +SRC := $(wildcard tst_*.py) +RUN_TARGETS := $(SRC:%.py=run_%) + +include ../../color_out.mk + +.PHONY: check help clean build run_% +check: $(TARGETS) $(RUN_TARGETS) + +help: + @echo "Makefile for running tests on FLiT framework" + @echo " help print this help documentation and exit" + @echo " build just compile the targets" + @echo " check run tests and print results to the console" + @echo " clean remove all generated files" + +build: +clean: + +run_% : %.py + @$(call color_out_noline,BROWN, running) + @echo " $<" + @$(RUNNER) $< diff --git a/tests/flit_cli/flit_update/README.md b/tests/flit_cli/flit_update/README.md new file mode 100644 index 00000000..e699da98 --- /dev/null +++ b/tests/flit_cli/flit_update/README.md @@ -0,0 +1,29 @@ +# Tests + +## Tests covering `[[compiler]]` section + +1. `tst_nocompilers.py`: Test that not specifying the `[[compiler]]` section + gives the default values +2. `tst_nooptl.py`: Test that specifying a compiler, but not specifying the + optimization levels gives the default values +3. `tst_noswitches.py`: Test that specifying a compiler, but not specifying the + switches list gives the default values +4. `tst_onlyprovidedoptlswitches.py`: Test that the provided list of + optimization levels and switches are used, and nothing more. +5. `tst_onlyprovidedcompilers.py`: Test that by only specifying one compiler, + only that specified compiler is used +6. `tst_badconfig.py`: Tests error cases in the configuration file, such as + specifying more than one of a certain type of compiler + +# Needed tests + +1. `FLIT_INC_DIR`, `FLIT_LIB_DIR`, `FLIT_DATA_DIR`, and `FLIT_SCRIPT_DIR`, for + both from git repository and for an installed FLiT +2. `DEV_CC`, `DEV_OPTL`, and `DEV_SWITCHES` for both provided and non-provided +3. `GT_CC`, `GT_OPTL`, and `GT_SWITCHES` for both provided and non-provided +4. `TEST_RUN_ARGS` from `timing`, `timing_loops`, and `timing_repeats` for both + provided and non-provided +5. `ENABLE_MPI` and `MPIRUN_ARGS` for both provided and non-provided +6. `HOSTNAME` +7. `UNAME_S` + diff --git a/tests/flit_cli/flit_update/data/nocompilers.toml b/tests/flit_cli/flit_update/data/nocompilers.toml new file mode 100644 index 00000000..f0d03294 --- /dev/null +++ b/tests/flit_cli/flit_update/data/nocompilers.toml @@ -0,0 +1,2 @@ +# Test that with no compilers specified the default three compilers with their +# default flags are used. diff --git a/tests/flit_cli/flit_update/data/nooptl.toml b/tests/flit_cli/flit_update/data/nooptl.toml new file mode 100644 index 00000000..445b031e --- /dev/null +++ b/tests/flit_cli/flit_update/data/nooptl.toml @@ -0,0 +1,93 @@ +# Test that missing optimization levels causes the defaults to be used + +[[compiler]] +binary = 'g++' +name = 'g++' +type = 'gcc' + +# missing optimization levels + +switches_list = [ + '-fassociative-math', + '-fcx-fortran-rules', + '-fcx-limited-range', + '-fexcess-precision=fast', + '-ffinite-math-only', + '-ffloat-store', + '-ffp-contract=on', + '-fmerge-all-constants', + '-fno-trapping-math', + '-freciprocal-math', + '-frounding-math', + '-fsignaling-nans', + '-funsafe-math-optimizations', + '-mavx', + '-mavx2 -mfma', + '-mfpmath=sse -mtune=native', + '' +] + +[[compiler]] +binary = 'clang++' +name = 'clang++' +type = 'clang' + +# missing optimization levels + +switches_list = [ + '-fassociative-math', + '-fexcess-precision=fast', + '-fexcess-precision=standard', + '-ffinite-math-only', + '-ffloat-store', + '-ffp-contract=on', + '-fmerge-all-constants', + '-fno-trapping-math', + '-freciprocal-math', + '-frounding-math', + '-fsignaling-nans', + '-fsingle-precision-constant', + '-funsafe-math-optimizations', + '-march=core-avx2', + '-mavx', + '-mavx2 -mfma', + '-mfpmath=sse -mtune=native', + '' +] + +[[compiler]] +binary = 'icpc' +name = 'icpc' +type = 'intel' + +# missing optimization levels + +switches_list = [ + '--use_fast_math', + '-fcx-limited-range', + '-ffloat-store', + '-fma', + '-fmerge-all-constants', + '-fp-model fast=1', + '-fp-model fast=2', + '-fp-model=double', + '-fp-model=except', + '-fp-model=extended', + '-fp-model=precise', + '-fp-model=source', + '-fp-model=strict', + '-fp-port', + '-frounding-math', + '-fsingle-precision-constant', + '-ftz', + '-march=core-avx2', + '-mavx', + '-mavx2 -mfma', + '-mfpmath=sse -mtune=native', + '-mp1', + '-no-fma', + '-no-ftz', + '-no-prec-div', + '-prec-div', + '' +] diff --git a/tests/flit_cli/flit_update/data/noswitches.toml b/tests/flit_cli/flit_update/data/noswitches.toml new file mode 100644 index 00000000..da8e8f02 --- /dev/null +++ b/tests/flit_cli/flit_update/data/noswitches.toml @@ -0,0 +1,40 @@ +# Test that missing switches causes the compiler-specific defaults to be used + +[[compiler]] +binary = 'g++' +name = 'g++' +type = 'gcc' +optimization_levels = [ + '-O0', + '-O1', + '-O2', + '-O3', +] + +# Missing switches + +[[compiler]] +binary = 'clang++' +name = 'clang++' +type = 'clang' +optimization_levels = [ + '-O0', + '-O1', + '-O2', + '-O3', +] + +# Missing switches + +[[compiler]] +binary = 'icpc' +name = 'icpc' +type = 'intel' +optimization_levels = [ + '-O0', + '-O1', + '-O2', + '-O3', +] + +# Missing switches diff --git a/tests/flit_cli/flit_update/data/onlyprovidedcompilers.toml b/tests/flit_cli/flit_update/data/onlyprovidedcompilers.toml new file mode 100644 index 00000000..131b55a9 --- /dev/null +++ b/tests/flit_cli/flit_update/data/onlyprovidedcompilers.toml @@ -0,0 +1,6 @@ +# Test only providing g++ + +[[compiler]] +binary = '/usr/bin/my-g++' +name = 'g++' +type = 'gcc' diff --git a/tests/flit_cli/flit_update/data/onlyprovidedoptlswitches.toml b/tests/flit_cli/flit_update/data/onlyprovidedoptlswitches.toml new file mode 100644 index 00000000..838b770e --- /dev/null +++ b/tests/flit_cli/flit_update/data/onlyprovidedoptlswitches.toml @@ -0,0 +1,46 @@ +# Test that only the provided optimization levels and switches are used + +[[compiler]] +binary = 'g++' +name = 'g++' +type = 'gcc' + +optimization_levels = [ + '-O2', + '-O3', +] +switches_list = [ + '-funsafe-math-optimizations', + '-mavx', + '' +] + +[[compiler]] +binary = 'clang++' +name = 'clang++' +type = 'clang' + +optimization_levels = [ + '-O0', + '-O1', +] +switches_list = [ + '-ffinite-math-only', + '-ffloat-store', +] + +[[compiler]] +binary = 'icpc' +name = 'icpc' +type = 'intel' + +optimization_levels = [ + '-Ofast', + '-Og', +] +switches_list = [ + '-fmerge-all-constants', + '-fp-model fast=1', + '-fp-model fast=2', + '-DUSE_MPI' +] diff --git a/tests/flit_cli/flit_update/tst_badconfig.py b/tests/flit_cli/flit_update/tst_badconfig.py new file mode 100644 index 00000000..495501f0 --- /dev/null +++ b/tests/flit_cli/flit_update/tst_badconfig.py @@ -0,0 +1,178 @@ +# -- LICENSE BEGIN -- +# +# Copyright (c) 2015-2018, Lawrence Livermore National Security, LLC. +# +# Produced at the Lawrence Livermore National Laboratory +# +# Written by +# Michael Bentley (mikebentley15@gmail.com), +# Geof Sawaya (fredricflinstone@gmail.com), +# and Ian Briggs (ian.briggs@utah.edu) +# under the direction of +# Ganesh Gopalakrishnan +# and Dong H. Ahn. +# +# LLNL-CODE-743137 +# +# All rights reserved. +# +# This file is part of FLiT. For details, see +# https://pruners.github.io/flit +# Please also read +# https://github.com/PRUNERS/FLiT/blob/master/LICENSE +# +# Redistribution and use in source and binary forms, with or +# without modification, are permitted provided that the following +# conditions are met: +# +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the disclaimer below. +# +# - Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the disclaimer +# (as noted below) in the documentation and/or other materials +# provided with the distribution. +# +# - Neither the name of the LLNS/LLNL nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL LAWRENCE LIVERMORE NATIONAL +# SECURITY, LLC, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +# THE POSSIBILITY OF SUCH DAMAGE. +# +# Additional BSD Notice +# +# 1. This notice is required to be provided under our contract +# with the U.S. Department of Energy (DOE). This work was +# produced at Lawrence Livermore National Laboratory under +# Contract No. DE-AC52-07NA27344 with the DOE. +# +# 2. Neither the United States Government nor Lawrence Livermore +# National Security, LLC nor any of their employees, makes any +# warranty, express or implied, or assumes any liability or +# responsibility for the accuracy, completeness, or usefulness of +# any information, apparatus, product, or process disclosed, or +# represents that its use would not infringe privately-owned +# rights. +# +# 3. Also, reference herein to any specific commercial products, +# process, or services by trade name, trademark, manufacturer or +# otherwise does not necessarily constitute or imply its +# endorsement, recommendation, or favoring by the United States +# Government or Lawrence Livermore National Security, LLC. The +# views and opinions of authors expressed herein do not +# necessarily state or reflect those of the United States +# Government or Lawrence Livermore National Security, LLC, and +# shall not be used for advertising or product endorsement +# purposes. +# +# -- LICENSE END -- + +''' +Tests error cases in the configuration file, such as specifying more than one of a certain type of compiler. + +>>> from io import StringIO +>>> import os +>>> import shutil + +>>> from tst_common_funcs import runconfig + +>>> configstr = \\ +... '[dev_build]\\n' \\ +... 'compiler_name = \\'name-does-not-exist\\'\\n' +>>> runconfig(configstr) +Traceback (most recent call last): +... +AssertionError: Compiler name name-does-not-exist not found + +>>> configstr = \\ +... '[ground_truth]\\n' \\ +... 'compiler_name = \\'another-name-that-does-not-exist\\'\\n' +>>> runconfig(configstr) +Traceback (most recent call last): +... +AssertionError: Compiler name another-name-that-does-not-exist not found + +>>> runconfig('[compiler]\\n') +Traceback (most recent call last): +... +tst_common_funcs.UpdateTestError: Failed to update Makefile: Error: flit-config.toml improperly configured, needs [[compiler]] section + +>>> runconfig('[[compiler]]\\n') +Traceback (most recent call last): +... +tst_common_funcs.UpdateTestError: Failed to update Makefile: Error: flit-config.toml: compiler "{}" is missing the "name" field + +>>> runconfig('[[compiler]]\\n' +... 'name = \\'hello\\'\\n') +Traceback (most recent call last): +... +tst_common_funcs.UpdateTestError: Failed to update Makefile: Error: flit-config.toml: compiler "{'name': 'hello'}" is missing the "type" field + +>>> runconfig('[[compiler]]\\n' +... 'name = \\'hello\\'\\n' +... 'type = \\'gcc\\'\\n') # doctest:+ELLIPSIS +Traceback (most recent call last): +... +tst_common_funcs.UpdateTestError: Failed to update Makefile: Error: flit-config.toml: compiler "{...}" is missing the "binary" field + +>>> runconfig('[[compiler]]\\n' +... 'binary = \\'my-special-compiler\\'\\n' +... 'name = \\'hello\\'\\n' +... 'type = \\'my-unsupported-type\\'\\n') +Traceback (most recent call last): +... +tst_common_funcs.UpdateTestError: Failed to update Makefile: Error: flit-config.toml: unsupported compiler type "my-unsupported-type" + +>>> runconfig('[[compiler]]\\n' +... 'binary = \\'gcc\\'\\n' +... 'name = \\'gcc\\'\\n' +... 'type = \\'gcc\\'\\n' +... '\\n' +... '[[compiler]]\\n' +... 'binary = \\'gcc-2\\'\\n' +... 'name = \\'gcc-2\\'\\n' +... 'type = \\'gcc\\'\\n' +... ) +Traceback (most recent call last): +... +tst_common_funcs.UpdateTestError: Failed to update Makefile: Error: flit-config.toml: cannot have multiple compilers of the same type (gcc) + +>>> runconfig('[[compiler]]\\n' +... 'binary = \\'gcc\\'\\n' +... 'name = \\'gcc\\'\\n' +... 'type = \\'gcc\\'\\n' +... '\\n' +... '[[compiler]]\\n' +... 'binary = \\'gcc-2\\'\\n' +... 'name = \\'gcc\\'\\n' +... 'type = \\'clang\\'\\n' +... ) +Traceback (most recent call last): +... +tst_common_funcs.UpdateTestError: Failed to update Makefile: Error: flit-config.toml: cannot have multiple compilers of the same name (gcc) +''' + +# Test setup before the docstring is run. +import sys +before_path = sys.path[:] +sys.path.append('../..') +import test_harness as th +sys.path = before_path + +if __name__ == '__main__': + from doctest import testmod + failures, tests = testmod() + sys.exit(failures) diff --git a/tests/flit_cli/flit_update/tst_common_funcs.py b/tests/flit_cli/flit_update/tst_common_funcs.py new file mode 100644 index 00000000..f1cffa70 --- /dev/null +++ b/tests/flit_cli/flit_update/tst_common_funcs.py @@ -0,0 +1,195 @@ +# -- LICENSE BEGIN -- +# +# Copyright (c) 2015-2018, Lawrence Livermore National Security, LLC. +# +# Produced at the Lawrence Livermore National Laboratory +# +# Written by +# Michael Bentley (mikebentley15@gmail.com), +# Geof Sawaya (fredricflinstone@gmail.com), +# and Ian Briggs (ian.briggs@utah.edu) +# under the direction of +# Ganesh Gopalakrishnan +# and Dong H. Ahn. +# +# LLNL-CODE-743137 +# +# All rights reserved. +# +# This file is part of FLiT. For details, see +# https://pruners.github.io/flit +# Please also read +# https://github.com/PRUNERS/FLiT/blob/master/LICENSE +# +# Redistribution and use in source and binary forms, with or +# without modification, are permitted provided that the following +# conditions are met: +# +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the disclaimer below. +# +# - Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the disclaimer +# (as noted below) in the documentation and/or other materials +# provided with the distribution. +# +# - Neither the name of the LLNS/LLNL nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL LAWRENCE LIVERMORE NATIONAL +# SECURITY, LLC, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +# THE POSSIBILITY OF SUCH DAMAGE. +# +# Additional BSD Notice +# +# 1. This notice is required to be provided under our contract +# with the U.S. Department of Energy (DOE). This work was +# produced at Lawrence Livermore National Laboratory under +# Contract No. DE-AC52-07NA27344 with the DOE. +# +# 2. Neither the United States Government nor Lawrence Livermore +# National Security, LLC nor any of their employees, makes any +# warranty, express or implied, or assumes any liability or +# responsibility for the accuracy, completeness, or usefulness of +# any information, apparatus, product, or process disclosed, or +# represents that its use would not infringe privately-owned +# rights. +# +# 3. Also, reference herein to any specific commercial products, +# process, or services by trade name, trademark, manufacturer or +# otherwise does not necessarily constitute or imply its +# endorsement, recommendation, or favoring by the United States +# Government or Lawrence Livermore National Security, LLC. The +# views and opinions of authors expressed herein do not +# necessarily state or reflect those of the United States +# Government or Lawrence Livermore National Security, LLC, and +# shall not be used for advertising or product endorsement +# purposes. +# +# -- LICENSE END -- +''' +This module holds common functions used in all of the tests for +`flit_update.py` +''' + +from io import StringIO +import os +import sys + +before_path = sys.path[:] +sys.path.append('../..') +import test_harness as th +sys.path = before_path + +class UpdateTestError(RuntimeError): + 'Error used in runconfig()' + pass + +def deref_makelist(name, makevars): + ''' + The makevars are a dictionary of key list pairs of strings in the + form of a dictionary. This function is useful when a variable within + makevars contains a list of other variables within makevars. This + dereferences all of them and returns a sorted list of them all. + + @param name (str) variable name from makevars + @param makevars (dict{str: list(str)}) all makefile variables + + See some examples to see exactly what to expect: + + >>> makevars = { + ... 'A': ['one', 'first'], 'B': ['two', 'second'], + ... 'C': ['three', 'third'], 'D': ['four', 'fourth'], + ... 'evens': ['D', 'B'], 'odds': ['A', 'C'] + ... } + + >>> deref_makelist('evens', makevars) + ['four fourth', 'two second'] + + >>> deref_makelist('odds', makevars) + ['one first', 'three third'] + ''' + return sorted([' '.join(makevars[x]) for x in makevars[name]]) + +def get_default_compiler(typename): + ''' + Returns the default compiler from the default toml configuration. + + @param typename (str) name of the type of compiler to extract + @return (dict) default compiler values from the default flit config + + >>> gcc = get_default_compiler('gcc') + >>> gcc['binary'] + 'g++' + >>> gcc['type'] + 'gcc' + >>> gcc['name'] + 'g++' + + >>> clang = get_default_compiler('clang') + >>> clang['optimization_levels'] + ['-O0', '-O1', '-O2', '-O3'] + >>> clang['binary'] + 'clang++' + + >>> intel = get_default_compiler('intel') + >>> intel['binary'] + 'icpc' + ''' + defaults = th.util.get_default_toml() + default_compiler = [x for x in defaults['compiler'] + if x['type'] == typename] + assert len(default_compiler) == 1 + return default_compiler[0] + +def runconfig(configstr): + ''' + Runs `flit init`, then writes the given configuration string into + `flit-config.toml`, and then runs `flit update`. + + @param configstr (str) contents to put into `flit-config.toml` + @return (tuple(list(str), list(str), dict{str: list(str)}) + Three things are returned: + 1. init_out (list(str)): the lines of output from `flit init` + 2. update_out (list(str)): the lines of output from `flit update` + 3. makevars (dict{str: list(str)}): all Makefile variables from the + `Makefile` generated from `flit update` + + I will not put tests for this function here since this is tested by its use + in the other test functions. + ''' + with th.tempdir() as temp_dir: + with StringIO() as ostream: + retval = th.flit.main(['init', '-C', temp_dir], + outstream=ostream, errstream=ostream) + init_out = ostream.getvalue().splitlines() + if retval != 0: + raise UpdateTestError('Failed to initialize flit directory') + with open(os.path.join(temp_dir, 'flit-config.toml'), 'w') as fout: + print(configstr, file=fout, flush=True) + with StringIO() as ostream: + retval = th.flit.main(['update', '-C', temp_dir], + outstream=ostream, errstream=ostream) + update_out = ostream.getvalue().splitlines() + if retval != 0: + raise UpdateTestError('Failed to update Makefile: ' + + ' '.join(update_out)) + makevars = th.util.extract_make_vars(directory=temp_dir) + return (init_out, update_out, makevars) + +if __name__ == '__main__': + from doctest import testmod + failures, tests = testmod() + sys.exit(failures) diff --git a/tests/flit_cli/flit_update/tst_nocompilers.py b/tests/flit_cli/flit_update/tst_nocompilers.py new file mode 100644 index 00000000..838623f3 --- /dev/null +++ b/tests/flit_cli/flit_update/tst_nocompilers.py @@ -0,0 +1,171 @@ +# -- LICENSE BEGIN -- +# +# Copyright (c) 2015-2018, Lawrence Livermore National Security, LLC. +# +# Produced at the Lawrence Livermore National Laboratory +# +# Written by +# Michael Bentley (mikebentley15@gmail.com), +# Geof Sawaya (fredricflinstone@gmail.com), +# and Ian Briggs (ian.briggs@utah.edu) +# under the direction of +# Ganesh Gopalakrishnan +# and Dong H. Ahn. +# +# LLNL-CODE-743137 +# +# All rights reserved. +# +# This file is part of FLiT. For details, see +# https://pruners.github.io/flit +# Please also read +# https://github.com/PRUNERS/FLiT/blob/master/LICENSE +# +# Redistribution and use in source and binary forms, with or +# without modification, are permitted provided that the following +# conditions are met: +# +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the disclaimer below. +# +# - Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the disclaimer +# (as noted below) in the documentation and/or other materials +# provided with the distribution. +# +# - Neither the name of the LLNS/LLNL nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL LAWRENCE LIVERMORE NATIONAL +# SECURITY, LLC, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +# THE POSSIBILITY OF SUCH DAMAGE. +# +# Additional BSD Notice +# +# 1. This notice is required to be provided under our contract +# with the U.S. Department of Energy (DOE). This work was +# produced at Lawrence Livermore National Laboratory under +# Contract No. DE-AC52-07NA27344 with the DOE. +# +# 2. Neither the United States Government nor Lawrence Livermore +# National Security, LLC nor any of their employees, makes any +# warranty, express or implied, or assumes any liability or +# responsibility for the accuracy, completeness, or usefulness of +# any information, apparatus, product, or process disclosed, or +# represents that its use would not infringe privately-owned +# rights. +# +# 3. Also, reference herein to any specific commercial products, +# process, or services by trade name, trademark, manufacturer or +# otherwise does not necessarily constitute or imply its +# endorsement, recommendation, or favoring by the United States +# Government or Lawrence Livermore National Security, LLC. The +# views and opinions of authors expressed herein do not +# necessarily state or reflect those of the United States +# Government or Lawrence Livermore National Security, LLC, and +# shall not be used for advertising or product endorsement +# purposes. +# +# -- LICENSE END -- + +''' +Tests that specifying no compilers results in the default compilers with the +default flags. + +>>> from io import StringIO +>>> import os +>>> import shutil + +>>> from tst_common_funcs import ( +... deref_makelist, get_default_compiler, runconfig) + +>>> testconf = 'data/nocompilers.toml' +>>> with open(testconf, 'r') as fin: +... init_out, update_out, makevars = runconfig(fin.read()) + +Get default values for each compiler from the default configuration + +>>> default_gcc = get_default_compiler('gcc') +>>> default_clang = get_default_compiler('clang') +>>> default_intel = get_default_compiler('intel') + +>>> print('\\n'.join(init_out)) # doctest:+ELLIPSIS +Creating .../flit-config.toml +Creating .../custom.mk +Creating .../main.cpp +Creating .../tests/Empty.cpp +Creating .../Makefile + +>>> print('\\n'.join(update_out)) # doctest:+ELLIPSIS +Updating .../Makefile + +Check that the compiler binaries are the default values +>>> gcc = makevars['GCC'] +>>> len(gcc) == 1 +True +>>> gcc[0] == default_gcc['binary'] +True + +>>> clang = makevars['CLANG'] +>>> len(clang) == 1 +True +>>> clang[0] == default_clang['binary'] +True + +>>> intel = makevars['INTEL'] +>>> len(intel) == 1 +True +>>> intel[0] == default_intel['binary'] +True + +>>> sorted(makevars['COMPILERS']) +['CLANG', 'GCC', 'INTEL'] + +>>> deref_makelist('OPCODES_GCC', makevars) == \\ +... sorted(default_gcc['optimization_levels']) +True + +>>> deref_makelist('OPCODES_CLANG', makevars) == \\ +... sorted(default_clang['optimization_levels']) +True + +>>> deref_makelist('OPCODES_INTEL', makevars) == \\ +... sorted(default_intel['optimization_levels']) +True + +>>> deref_makelist('SWITCHES_GCC', makevars) == \\ +... sorted(default_gcc['switches_list']) +True + +>>> deref_makelist('SWITCHES_CLANG', makevars) == \\ +... sorted(default_clang['switches_list']) +True + +>>> deref_makelist('SWITCHES_INTEL', makevars) == \\ +... sorted(default_intel['switches_list']) +True +''' + +# Test setup before the docstring is run. +import sys +before_path = sys.path[:] +sys.path.append('../..') +import test_harness as th +sys.path = before_path + +if __name__ == '__main__': + from doctest import testmod + failures, tests = testmod() + sys.exit(failures) diff --git a/tests/flit_cli/flit_update/tst_nooptl.py b/tests/flit_cli/flit_update/tst_nooptl.py new file mode 100644 index 00000000..2570d89e --- /dev/null +++ b/tests/flit_cli/flit_update/tst_nooptl.py @@ -0,0 +1,135 @@ +# -- LICENSE BEGIN -- +# +# Copyright (c) 2015-2018, Lawrence Livermore National Security, LLC. +# +# Produced at the Lawrence Livermore National Laboratory +# +# Written by +# Michael Bentley (mikebentley15@gmail.com), +# Geof Sawaya (fredricflinstone@gmail.com), +# and Ian Briggs (ian.briggs@utah.edu) +# under the direction of +# Ganesh Gopalakrishnan +# and Dong H. Ahn. +# +# LLNL-CODE-743137 +# +# All rights reserved. +# +# This file is part of FLiT. For details, see +# https://pruners.github.io/flit +# Please also read +# https://github.com/PRUNERS/FLiT/blob/master/LICENSE +# +# Redistribution and use in source and binary forms, with or +# without modification, are permitted provided that the following +# conditions are met: +# +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the disclaimer below. +# +# - Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the disclaimer +# (as noted below) in the documentation and/or other materials +# provided with the distribution. +# +# - Neither the name of the LLNS/LLNL nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL LAWRENCE LIVERMORE NATIONAL +# SECURITY, LLC, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +# THE POSSIBILITY OF SUCH DAMAGE. +# +# Additional BSD Notice +# +# 1. This notice is required to be provided under our contract +# with the U.S. Department of Energy (DOE). This work was +# produced at Lawrence Livermore National Laboratory under +# Contract No. DE-AC52-07NA27344 with the DOE. +# +# 2. Neither the United States Government nor Lawrence Livermore +# National Security, LLC nor any of their employees, makes any +# warranty, express or implied, or assumes any liability or +# responsibility for the accuracy, completeness, or usefulness of +# any information, apparatus, product, or process disclosed, or +# represents that its use would not infringe privately-owned +# rights. +# +# 3. Also, reference herein to any specific commercial products, +# process, or services by trade name, trademark, manufacturer or +# otherwise does not necessarily constitute or imply its +# endorsement, recommendation, or favoring by the United States +# Government or Lawrence Livermore National Security, LLC. The +# views and opinions of authors expressed herein do not +# necessarily state or reflect those of the United States +# Government or Lawrence Livermore National Security, LLC, and +# shall not be used for advertising or product endorsement +# purposes. +# +# -- LICENSE END -- + +''' +Test that missing optimization levels causes the defaults to be used + +>>> from io import StringIO +>>> import os +>>> import shutil + +>>> from tst_common_funcs import ( +... deref_makelist, get_default_compiler, runconfig) + +>>> testconf = 'data/nooptl.toml' +>>> with open(testconf, 'r') as fin: +... init_out, update_out, makevars = runconfig(fin.read()) + +Get default values for each compiler from the default configuration +>>> default_gcc = get_default_compiler('gcc') +>>> default_clang = get_default_compiler('clang') +>>> default_intel = get_default_compiler('intel') + +>>> print('\\n'.join(init_out)) # doctest:+ELLIPSIS +Creating .../flit-config.toml +Creating .../custom.mk +Creating .../main.cpp +Creating .../tests/Empty.cpp +Creating .../Makefile + +>>> print('\\n'.join(update_out)) # doctest:+ELLIPSIS +Updating .../Makefile + +>>> deref_makelist('OPCODES_GCC', makevars) == \\ +... sorted(default_gcc['optimization_levels']) +True + +>>> deref_makelist('OPCODES_CLANG', makevars) == \\ +... sorted(default_clang['optimization_levels']) +True + +>>> deref_makelist('OPCODES_INTEL', makevars) == \\ +... sorted(default_intel['optimization_levels']) +True +''' + +# Test setup before the docstring is run. +import sys +before_path = sys.path[:] +sys.path.append('../..') +import test_harness as th +sys.path = before_path + +if __name__ == '__main__': + from doctest import testmod + failures, tests = testmod() + sys.exit(failures) diff --git a/tests/flit_cli/flit_update/tst_noswitches.py b/tests/flit_cli/flit_update/tst_noswitches.py new file mode 100644 index 00000000..b07091c2 --- /dev/null +++ b/tests/flit_cli/flit_update/tst_noswitches.py @@ -0,0 +1,135 @@ +# -- LICENSE BEGIN -- +# +# Copyright (c) 2015-2018, Lawrence Livermore National Security, LLC. +# +# Produced at the Lawrence Livermore National Laboratory +# +# Written by +# Michael Bentley (mikebentley15@gmail.com), +# Geof Sawaya (fredricflinstone@gmail.com), +# and Ian Briggs (ian.briggs@utah.edu) +# under the direction of +# Ganesh Gopalakrishnan +# and Dong H. Ahn. +# +# LLNL-CODE-743137 +# +# All rights reserved. +# +# This file is part of FLiT. For details, see +# https://pruners.github.io/flit +# Please also read +# https://github.com/PRUNERS/FLiT/blob/master/LICENSE +# +# Redistribution and use in source and binary forms, with or +# without modification, are permitted provided that the following +# conditions are met: +# +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the disclaimer below. +# +# - Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the disclaimer +# (as noted below) in the documentation and/or other materials +# provided with the distribution. +# +# - Neither the name of the LLNS/LLNL nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL LAWRENCE LIVERMORE NATIONAL +# SECURITY, LLC, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +# THE POSSIBILITY OF SUCH DAMAGE. +# +# Additional BSD Notice +# +# 1. This notice is required to be provided under our contract +# with the U.S. Department of Energy (DOE). This work was +# produced at Lawrence Livermore National Laboratory under +# Contract No. DE-AC52-07NA27344 with the DOE. +# +# 2. Neither the United States Government nor Lawrence Livermore +# National Security, LLC nor any of their employees, makes any +# warranty, express or implied, or assumes any liability or +# responsibility for the accuracy, completeness, or usefulness of +# any information, apparatus, product, or process disclosed, or +# represents that its use would not infringe privately-owned +# rights. +# +# 3. Also, reference herein to any specific commercial products, +# process, or services by trade name, trademark, manufacturer or +# otherwise does not necessarily constitute or imply its +# endorsement, recommendation, or favoring by the United States +# Government or Lawrence Livermore National Security, LLC. The +# views and opinions of authors expressed herein do not +# necessarily state or reflect those of the United States +# Government or Lawrence Livermore National Security, LLC, and +# shall not be used for advertising or product endorsement +# purposes. +# +# -- LICENSE END -- + +''' +Test that missing switches causes the compiler-specific defaults to be used + +>>> from io import StringIO +>>> import shutil + +>>> from tst_common_funcs import ( +... deref_makelist, get_default_compiler, runconfig) + +>>> testconf = 'data/noswitches.toml' +>>> with open(testconf, 'r') as fin: +... init_out, update_out, makevars = runconfig(fin.read()) + +Get default values for each compiler from the default configuration + +>>> default_gcc = get_default_compiler('gcc') +>>> default_clang = get_default_compiler('clang') +>>> default_intel = get_default_compiler('intel') + +>>> print('\\n'.join(init_out)) # doctest:+ELLIPSIS +Creating .../flit-config.toml +Creating .../custom.mk +Creating .../main.cpp +Creating .../tests/Empty.cpp +Creating .../Makefile + +>>> print('\\n'.join(update_out)) # doctest:+ELLIPSIS +Updating .../Makefile + +>>> deref_makelist('SWITCHES_GCC', makevars) == \\ +... sorted(default_gcc['switches_list']) +True + +>>> deref_makelist('SWITCHES_CLANG', makevars) == \\ +... sorted(default_clang['switches_list']) +True + +>>> deref_makelist('SWITCHES_INTEL', makevars) == \\ +... sorted(default_intel['switches_list']) +True +''' + +# Test setup before the docstring is run. +import sys +before_path = sys.path[:] +sys.path.append('../..') +import test_harness as th +sys.path = before_path + +if __name__ == '__main__': + from doctest import testmod + failures, tests = testmod() + sys.exit(failures) diff --git a/tests/flit_cli/flit_update/tst_onlyprovidedcompilers.py b/tests/flit_cli/flit_update/tst_onlyprovidedcompilers.py new file mode 100644 index 00000000..f0f48af7 --- /dev/null +++ b/tests/flit_cli/flit_update/tst_onlyprovidedcompilers.py @@ -0,0 +1,148 @@ +# -- LICENSE BEGIN -- +# +# Copyright (c) 2015-2018, Lawrence Livermore National Security, LLC. +# +# Produced at the Lawrence Livermore National Laboratory +# +# Written by +# Michael Bentley (mikebentley15@gmail.com), +# Geof Sawaya (fredricflinstone@gmail.com), +# and Ian Briggs (ian.briggs@utah.edu) +# under the direction of +# Ganesh Gopalakrishnan +# and Dong H. Ahn. +# +# LLNL-CODE-743137 +# +# All rights reserved. +# +# This file is part of FLiT. For details, see +# https://pruners.github.io/flit +# Please also read +# https://github.com/PRUNERS/FLiT/blob/master/LICENSE +# +# Redistribution and use in source and binary forms, with or +# without modification, are permitted provided that the following +# conditions are met: +# +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the disclaimer below. +# +# - Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the disclaimer +# (as noted below) in the documentation and/or other materials +# provided with the distribution. +# +# - Neither the name of the LLNS/LLNL nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL LAWRENCE LIVERMORE NATIONAL +# SECURITY, LLC, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +# THE POSSIBILITY OF SUCH DAMAGE. +# +# Additional BSD Notice +# +# 1. This notice is required to be provided under our contract +# with the U.S. Department of Energy (DOE). This work was +# produced at Lawrence Livermore National Laboratory under +# Contract No. DE-AC52-07NA27344 with the DOE. +# +# 2. Neither the United States Government nor Lawrence Livermore +# National Security, LLC nor any of their employees, makes any +# warranty, express or implied, or assumes any liability or +# responsibility for the accuracy, completeness, or usefulness of +# any information, apparatus, product, or process disclosed, or +# represents that its use would not infringe privately-owned +# rights. +# +# 3. Also, reference herein to any specific commercial products, +# process, or services by trade name, trademark, manufacturer or +# otherwise does not necessarily constitute or imply its +# endorsement, recommendation, or favoring by the United States +# Government or Lawrence Livermore National Security, LLC. The +# views and opinions of authors expressed herein do not +# necessarily state or reflect those of the United States +# Government or Lawrence Livermore National Security, LLC, and +# shall not be used for advertising or product endorsement +# purposes. +# +# -- LICENSE END -- + +''' +Tests only providing gcc and no other compiler. Tests that +- the binary is taken from the configuration file +- the other two compilers are not present (i.e. clang and intel) + +>>> from io import StringIO +>>> import os +>>> import shutil + +>>> from tst_common_funcs import ( +... deref_makelist, get_default_compiler, runconfig) + +>>> testconf = 'data/onlyprovidedcompilers.toml' +>>> with open(testconf, 'r') as fin: +... init_out, update_out, makevars = runconfig(fin.read()) + +Get default values for each compiler from the default configuration + +>>> print('\\n'.join(init_out)) # doctest:+ELLIPSIS +Creating .../flit-config.toml +Creating .../custom.mk +Creating .../main.cpp +Creating .../tests/Empty.cpp +Creating .../Makefile + +>>> print('\\n'.join(update_out)) # doctest:+ELLIPSIS +Updating .../Makefile + +Check that the compiler binaries are the default values +>>> makevars['GCC'] +['/usr/bin/my-g++'] + +>>> makevars['CLANG'] +['None'] + +>>> makevars['INTEL'] +['None'] + +>>> makevars['COMPILERS'] +['GCC'] + +>>> 'OPCODES_GCC' in makevars +True +>>> 'SWITCHES_GCC' in makevars +True +>>> 'OPCODES_CLANG' in makevars +False +>>> 'SWITCHES_CLANG' in makevars +False +>>> 'OPCODES_INTEL' in makevars +False +>>> 'SWITCHES_INTEL' in makevars +False +''' + +# Test setup before the docstring is run. +import sys +before_path = sys.path[:] +sys.path.append('../..') +import test_harness as th +sys.path = before_path + +if __name__ == '__main__': + from doctest import testmod + failures, tests = testmod() + sys.exit(failures) diff --git a/tests/flit_cli/flit_update/tst_onlyprovidedoptlswitches.py b/tests/flit_cli/flit_update/tst_onlyprovidedoptlswitches.py new file mode 100644 index 00000000..8299b1f9 --- /dev/null +++ b/tests/flit_cli/flit_update/tst_onlyprovidedoptlswitches.py @@ -0,0 +1,142 @@ +# -- LICENSE BEGIN -- +# +# Copyright (c) 2015-2018, Lawrence Livermore National Security, LLC. +# +# Produced at the Lawrence Livermore National Laboratory +# +# Written by +# Michael Bentley (mikebentley15@gmail.com), +# Geof Sawaya (fredricflinstone@gmail.com), +# and Ian Briggs (ian.briggs@utah.edu) +# under the direction of +# Ganesh Gopalakrishnan +# and Dong H. Ahn. +# +# LLNL-CODE-743137 +# +# All rights reserved. +# +# This file is part of FLiT. For details, see +# https://pruners.github.io/flit +# Please also read +# https://github.com/PRUNERS/FLiT/blob/master/LICENSE +# +# Redistribution and use in source and binary forms, with or +# without modification, are permitted provided that the following +# conditions are met: +# +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the disclaimer below. +# +# - Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the disclaimer +# (as noted below) in the documentation and/or other materials +# provided with the distribution. +# +# - Neither the name of the LLNS/LLNL nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL LAWRENCE LIVERMORE NATIONAL +# SECURITY, LLC, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +# THE POSSIBILITY OF SUCH DAMAGE. +# +# Additional BSD Notice +# +# 1. This notice is required to be provided under our contract +# with the U.S. Department of Energy (DOE). This work was +# produced at Lawrence Livermore National Laboratory under +# Contract No. DE-AC52-07NA27344 with the DOE. +# +# 2. Neither the United States Government nor Lawrence Livermore +# National Security, LLC nor any of their employees, makes any +# warranty, express or implied, or assumes any liability or +# responsibility for the accuracy, completeness, or usefulness of +# any information, apparatus, product, or process disclosed, or +# represents that its use would not infringe privately-owned +# rights. +# +# 3. Also, reference herein to any specific commercial products, +# process, or services by trade name, trademark, manufacturer or +# otherwise does not necessarily constitute or imply its +# endorsement, recommendation, or favoring by the United States +# Government or Lawrence Livermore National Security, LLC. The +# views and opinions of authors expressed herein do not +# necessarily state or reflect those of the United States +# Government or Lawrence Livermore National Security, LLC, and +# shall not be used for advertising or product endorsement +# purposes. +# +# -- LICENSE END -- + +''' +Test that only the provided optimization levels and switches are used + +>>> from io import StringIO +>>> import shutil +>>> import os + +>>> from tst_common_funcs import ( +... deref_makelist, get_default_compiler, runconfig) + +>>> testconf = 'data/onlyprovidedoptlswitches.toml' +>>> with open(testconf, 'r') as fin: +... init_out, update_out, makevars = runconfig(fin.read()) + +Get default values for each compiler from the default configuration + +>>> default_gcc = get_default_compiler('gcc') +>>> default_clang = get_default_compiler('clang') +>>> default_intel = get_default_compiler('intel') + +>>> print('\\n'.join(init_out)) # doctest:+ELLIPSIS +Creating .../flit-config.toml +Creating .../custom.mk +Creating .../main.cpp +Creating .../tests/Empty.cpp +Creating .../Makefile + +>>> print('\\n'.join(update_out)) # doctest:+ELLIPSIS +Updating .../Makefile + +>>> deref_makelist('OPCODES_GCC', makevars) +['-O2', '-O3'] + +>>> deref_makelist('OPCODES_CLANG', makevars) +['-O0', '-O1'] + +>>> deref_makelist('OPCODES_INTEL', makevars) +['-Ofast', '-Og'] + +>>> deref_makelist('SWITCHES_GCC', makevars) +['', '-funsafe-math-optimizations', '-mavx'] + +>>> deref_makelist('SWITCHES_CLANG', makevars) +['-ffinite-math-only', '-ffloat-store'] + +>>> deref_makelist('SWITCHES_INTEL', makevars) +['-DUSE_MPI', '-fmerge-all-constants', '-fp-model fast=1', '-fp-model fast=2'] +''' + +# Test setup before the docstring is run. +import sys +before_path = sys.path[:] +sys.path.append('../..') +import test_harness as th +sys.path = before_path + +if __name__ == '__main__': + from doctest import testmod + failures, tests = testmod() + sys.exit(failures) diff --git a/tests/test_harness.py b/tests/test_harness.py index 88873817..4df30665 100644 --- a/tests/test_harness.py +++ b/tests/test_harness.py @@ -227,6 +227,7 @@ def touch(filename): flit = _path_import(_script_dir, 'flit') config = _path_import(_script_dir, 'flitconfig') +util = _path_import(_script_dir, 'flitutil') # Remove the things that are no longer necessary del contextmanager