Skip to content

Commit

Permalink
CMake: Check integrity of external features
Browse files Browse the repository at this point in the history
Remove unused external features. Rename incorrect valgrind feature.
Check that external features defined in the features.def always
match those defined in cmake_config.cmakein.
  • Loading branch information
jngrad committed Nov 22, 2022
1 parent 981f93d commit 1595aac
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 21 deletions.
6 changes: 0 additions & 6 deletions cmake/cmake_config.cmakein
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@

#cmakedefine CUDA

#cmakedefine HIP

#cmakedefine FFTW

#cmakedefine H5MD
Expand All @@ -13,10 +11,6 @@

#cmakedefine GSL

#cmakedefine BLAS

#cmakedefine LAPACK

#cmakedefine STOKESIAN_DYNAMICS

#cmakedefine VALGRIND_INSTRUMENTATION
Expand Down
1 change: 1 addition & 0 deletions src/config/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ add_custom_target(
COMMAND
${Python_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/check_myconfig.py
${CMAKE_CXX_COMPILER} ${CMAKE_CURRENT_SOURCE_DIR}/features.def
${CMAKE_SOURCE_DIR}/cmake/cmake_config.cmakein
${CMAKE_CURRENT_BINARY_DIR}/include/config/myconfig-final.hpp
${CMAKE_CURRENT_BINARY_DIR}/include/config/cmake_config.hpp
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/features.def myconfig)
Expand Down
25 changes: 11 additions & 14 deletions src/config/check_myconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,25 +66,27 @@ def handle_unknown(f, all_features):
return f"- unknown feature '{f}'"


def check_myconfig(compiler, feature_file, myconfig, cmake_config=None):
# query features from the compiler
def check_myconfig(compiler, feature_file, cmakedefine_file, myconfig, cmake_config):
try:
Defines = defines.Defines
external_defs = []
if cmake_config:
external_features = Defines(compiler).defines(cmake_config)
external_defs += ['-D' + s for s in external_features]
external_features = Defines(compiler).defines(cmake_config)
external_defs = ['-D' + s for s in external_features]
my_features = Defines(compiler, flags=external_defs).defines(myconfig)
except subprocess.CalledProcessError as ex:
message = ex.output.decode("utf-8").split("\n")[0].strip()
raise RuntimeError(
f"Command `{' '.join(ex.cmd)}` returned non-zero exit code "
f"{ex.returncode}, output: {message}.")

# parse feature file
defs = featuredefs.defs(feature_file)

cmakedefs = featuredefs.cmakedefs(cmakedefine_file)
error_queue = []

for e in defs.externals - cmakedefs.externals:
error_queue.append(f"- cmakedefine '{e}' is missing from '{cmakedefine_file}'")
for e in cmakedefs.externals - defs.externals:
error_queue.append(f"- external feature '{e}' is missing from '{feature_file}'")

for e in (my_features & defs.externals):
my_features.remove(e)
error_queue.append(
Expand All @@ -102,9 +104,4 @@ def check_myconfig(compiler, feature_file, myconfig, cmake_config=None):


if __name__ == "__main__":
if len(sys.argv) > 4:
cmake_config = sys.argv[4]
else:
cmake_config = None

check_myconfig(sys.argv[1], sys.argv[2], sys.argv[3], cmake_config)
check_myconfig(*sys.argv[1:])
21 changes: 21 additions & 0 deletions src/config/featuredefs.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ def __init__(self, filename):
line = line.strip()
# Ignore empty and comment lines
if not line or line.startswith(('#', '//', '/*')):
assert not line.startswith('/*') or line.endswith('*/')
continue

# Tokenify line
Expand Down Expand Up @@ -166,3 +167,23 @@ def check_validity(self, activated):
return None

return newset


class cmakedefs:
def __init__(self, filename):
self.externals = set()

re_pattern = re.compile("^#cmakedefine +([A-Za-z0-9_]+) *$")
inside_multiline_comment = False
for line in fileinput.input(filename):
line = line.strip()
# Ignore empty and comment lines
if inside_multiline_comment or line.startswith('/*'):
inside_multiline_comment = not line.endswith('*/')
continue
if not line or line.startswith('//'):
continue

m = re_pattern.search(line)
if m:
self.externals.add(m.group(1))
1 change: 1 addition & 0 deletions src/config/features.def
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,4 @@ H5MD external
SCAFACOS external
GSL external
STOKESIAN_DYNAMICS external
VALGRIND_INSTRUMENTATION external
13 changes: 12 additions & 1 deletion testsuite/scripts/utils/test_check_myconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,25 @@ def test_exceptions(self):
path_root = pathlib.Path(tmp_directory.name)
path_myconfig = path_root / "myconfig.hpp"
path_cmake_config = path_root / "cmake_config.hpp"
path_cmakedefine = path_root / "cmake_config.cmakein"
with open("@CMAKE_SOURCE_DIR@/cmake/cmake_config.cmakein") as fp:
default_cmakedefine = fp.read()

def run(myconfig="", cmake_config=""):
def run(myconfig="", cmake_config="", cmakedefine=default_cmakedefine):
path_myconfig.write_text(myconfig)
path_cmake_config.write_text(cmake_config)
path_cmakedefine.write_text(cmakedefine)
module.check_myconfig(
"@CMAKE_CXX_COMPILER@",
"@CMAKE_SOURCE_DIR@/src/config/features.def",
str(path_cmakedefine),
str(path_myconfig),
str(path_cmake_config))

# no error for empty configurations
run()
# no error for multi-line comments
run(cmakedefine=default_cmakedefine + "/*\n#cmake" + "define ERROR\n*/")

# check all errors
with self.assertRaisesRegex(RuntimeError, "unknown feature 'ROTATIONN', did you mean 'ROTATION'"):
Expand All @@ -58,6 +65,10 @@ def run(myconfig="", cmake_config=""):
run(cmake_config="#define")
with self.assertRaisesRegex(RuntimeError, "myconfig.hpp` returned non-zero exit code 1, output:"):
run(myconfig="#define")
with self.assertRaisesRegex(RuntimeError, "external feature 'UNKNOWN' is missing from '.*features.def'"):
run(cmakedefine="#cmake" + "define UNKNOWN")
with self.assertRaisesRegex(RuntimeError, "cmakedefine 'FFTW' is missing from '.*cmake_config.cmakein'"):
run(cmakedefine="")

tmp_directory.cleanup()

Expand Down

0 comments on commit 1595aac

Please sign in to comment.