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
|
# SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
# SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
import logging
import os
import re
import subprocess
import dune.common.module
from dune.common.utility import buffer_to_str
from dune.generator import ConfigurationError, initializeDunePy
logger = logging.getLogger(__name__)
def _checkAndGetDunePyDir():
# make sure dune-py is initialized before configuration is checked
# in rare cases one might check the configuration before creating and configuring
# the module. Checking the configuration can only be done after dune-py has been generated.
initializeDunePy() # this will only do something if dune-py does not exist
return dune.common.module.getDunePyDir()
def assertHave(identifier):
'''check if an identifier is defined equal to 1 in the dune-py config.h file.
use this to check if for example #define HAVE_DUNE_COMMON 1 is
provided the config file by calling
assertHave("HAVE_DUNE_COMMON")
'''
# the following simply will not work anymore - the issue is that the
# approach used here requires dune-py to have already been setup before
# calling 'assertHave' that is not guaranteed to be the case.
# Possibly we can use the 'metadata' file instead.
# We simply return for now
raise RuntimeError("DEPRECATED USE OF assertHave")
return
config = os.path.join(_checkAndGetDunePyDir(), "config.h")
if not os.path.isfile(config):
raise ConfigurationError("dune-py not configured yet")
matches = [match for match in [re.match(r'^[ ]*#define[ ]+' + identifier.strip() + '[ ]+1$', line) for line in open(config)] if match is not None]
if not matches:
matches = [match for match in [re.match(r'^[ ]*#define[ ]+' + identifier.strip() + '[ ]+ENABLE', line) for line in open(config)] if match is not None]
if not matches:
raise ConfigurationError(identifier + " is not set in dune-py's config.h")
elif matches.__len__() > 1:
raise ConfigurationError(identifier + " found multiple times in dune-py's config.h")
def assertCMakeHave(identifier):
'''check if an identifier is defined equal to 1 in the dune-py config.h file.
use this to check if for example #define HAVE_DUNE_COMMON 1 is
provided the config file by calling
assertHave("HAVE_DUNE_COMMON")
Note: note that this depends on a dune-py having been completely
configured so should be used with caution, e.g., avoid usage in any
code executed during import of a dune module
'''
config = os.path.join(_checkAndGetDunePyDir(), "config.h")
if not os.path.isfile(config):
raise ConfigurationError("dune-py not configured yet")
matches = [match for match in [re.match(r'^[ ]*#define[ ]+' + identifier.strip() + '[ ]+1$', line) for line in open(config)] if match is not None]
if not matches:
matches = [match for match in [re.match(r'^[ ]*#define[ ]+' + identifier.strip() + '[ ]+ENABLE', line) for line in open(config)] if match is not None]
if not matches:
raise ConfigurationError(identifier + " is not set in dune-py's config.h")
elif matches.__len__() > 1:
raise ConfigurationError(identifier + " found multiple times in dune-py's config.h")
def assertCMakeVariable(identifier,value,defaultFails):
'''check if a variable in CMakeCache.txt in dune-py is defined and equal to 'value'
'''
cache = os.path.join(_checkAndGetDunePyDir(), "CMakeCache.txt")
identifier = identifier.lower().strip()
matches = [line.lower() for line in open(cache) if re.match(r'^[ ]*'+identifier+':+', line.lower()) is not None]
if not matches and defaultFails:
raise ConfigurationError(identifier + " default behavior is used in dune-py and that is not allowed")
elif len(matches) > 1:
raise ConfigurationError(identifier + " found multiple times in dune-py's config.h")
elif matches:
# check for bool on/off type variables:
bools = {True:["on","true","1"], False:["off","false","0"]}
if not [x for x in bools[value] if x in matches[0]]:
raise ConfigurationError(identifier + " dune-py wrongly configured wrt "+identifier)
def preprocessorAssert(tests):
'''perform preprocessore checks.
A list of checks can be provided each should contain a pair, the
first being the preprocessor check to perform (e.g. #if or #ifdef)
and the second being the message to print if the check fails. The
generated code is of the form:
tests[i][0]
#else
test failed
#endif
so the first argument of each test has to make this piece of code
valid C++ code assuming config.h is included.
'''
source = "#include <config.h>\nint main() {\n"
i = 0
for t in tests:
source = source + t[0]+"\n#else\nreturn "+str(i+1)+";\n#endif\n"
i += 1
source = source + "return 0;\n}\n"
from dune.generator import builder
with open(os.path.join(builder.generated_dir, "generated_module.hh"), 'w') as out:
out.write(source)
builder.compile("generated_test")
test_args = ["./generated_test"]
test = subprocess.Popen(test_args, cwd=builder.generated_dir, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = test.communicate()
logger.debug(buffer_to_str(stdout))
returncode = test.returncode
if returncode > 0:
logger.debug("failed testing:\n"+source)
logger.critical("checking "+tests[returncode-1][0]+" failed: "+tests[returncode-1][1])
raise ConfigurationError(tests[returncode-1][1])
|