parallel_self_test Namespace Reference

Classes

class  ExitCode
 
class  Colours
 
class  NoMakefileError
 

Functions

str highlight (str directory_path)
 
str build_fail_message (str directory)
 
str check_fail_message (str directory)
 
str check_success_message (str directory)
 
str no_check_message (str directory)
 
str missing_feature_message (str directory, str feature)
 
None print_results_summary (List[ExitCode] test_results)
 
int get_overall_self_test_exit_code (List[ExitCode] test_results)
 
str variable_from_makefile (str variable_name, str makefile_path="Makefile")
 
None error (*args)
 
str get_oomph_root ()
 
List[str] find_validate_dirs (List[str] base_dirs)
 
ExitCode dispatch_dir (str dirname, dict features, **kwargs)
 
bool check_if_mpi_driver (str d)
 
bool check_if_arpack_driver (str d)
 
bool check_if_hlib_driver (str d)
 
ExitCode make_check_in_dir (str directory, bool just_build=False)
 
def main ()
 

Variables

 COLOURS = Colours()
 

Function Documentation

◆ build_fail_message()

str parallel_self_test.build_fail_message ( str  directory)
96 def build_fail_message(directory: str) -> str:
97  print(COLOURS.MakeFail+"[BUILD FAIL] " + highlight(directory) +
98  COLOURS.Endc)
99 
100 
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet print(const Packet &a)
Definition: GenericPacketMath.h:1166
str highlight(str directory_path)
Definition: parallel_self_test.py:91
str build_fail_message(str directory)
Definition: parallel_self_test.py:96

References highlight(), and Eigen::internal.print().

Referenced by make_check_in_dir().

◆ check_fail_message()

str parallel_self_test.check_fail_message ( str  directory)
101 def check_fail_message(directory: str) -> str:
102  print(COLOURS.TestFail+"[FAILED] " + highlight(directory) +
103  COLOURS.Endc)
104 
105 
str check_fail_message(str directory)
Definition: parallel_self_test.py:101

References highlight(), and Eigen::internal.print().

Referenced by make_check_in_dir().

◆ check_if_arpack_driver()

bool parallel_self_test.check_if_arpack_driver ( str  d)
286 def check_if_arpack_driver(d: str) -> bool:
287  return "eigenproblems" in d
288 
289 
bool check_if_arpack_driver(str d)
Definition: parallel_self_test.py:286

◆ check_if_hlib_driver()

bool parallel_self_test.check_if_hlib_driver ( str  d)
290 def check_if_hlib_driver(d: str) -> bool:
291  # hlib is in "oomphlib", so take it out in case people use dirs called
292  # oomphlib with no -.
293  return "hlib" in d.replace("oomphlib", "")
294 
295 
296 # The function doing the bulk of the actual work (called many times in
297 # parallel by main).
bool check_if_hlib_driver(str d)
Definition: parallel_self_test.py:290

◆ check_if_mpi_driver()

bool parallel_self_test.check_if_mpi_driver ( str  d)
282 def check_if_mpi_driver(d: str) -> bool:
283  return "mpi" in d
284 
285 
bool check_if_mpi_driver(str d)
Definition: parallel_self_test.py:282

◆ check_success_message()

str parallel_self_test.check_success_message ( str  directory)
106 def check_success_message(directory: str) -> str:
107  print(COLOURS.Okgreen + "[OK] " + highlight(directory) +
108  COLOURS.Endc)
109 
110 
str check_success_message(str directory)
Definition: parallel_self_test.py:106

References highlight(), and Eigen::internal.print().

Referenced by make_check_in_dir().

◆ dispatch_dir()

ExitCode parallel_self_test.dispatch_dir ( str  dirname,
dict  features,
**  kwargs 
)
Check for missing features and print the appropriate message if
needed. Otherwise run the check function.
266 def dispatch_dir(dirname: str, features: dict, **kwargs) -> ExitCode:
267  """Check for missing features and print the appropriate message if
268  needed. Otherwise run the check function."""
269 
270  # For each possible feature in features check if we have it. If not
271  # check if this directory needs it and if so print a message, otherwise
272  # run the check.
273  for feature in features:
274  if not feature['have_feature']:
275  if feature['check_driver_function'](dirname):
276  missing_feature_message(dirname, feature['feature_name'])
277  return ExitCode.MISSING_FEATURE
278  return make_check_in_dir(dirname, **kwargs)
279 
280 
281 # Functions for checking if a test needs a certain feature
ExitCode dispatch_dir(str dirname, dict features, **kwargs)
Definition: parallel_self_test.py:266
str missing_feature_message(str directory, str feature)
Definition: parallel_self_test.py:116
ExitCode make_check_in_dir(str directory, bool just_build=False)
Definition: parallel_self_test.py:298

References make_check_in_dir(), and missing_feature_message().

◆ error()

None parallel_self_test.error ( args)
Write an error message to stderr and exit.
231 def error(*args) -> None:
232  """Write an error message to stderr and exit."""
233  sys.stderr.write("\nERROR:\n" + "\n".join(args) + "\n")
234  sys.exit(2)
235 
236 
None error(*args)
Definition: parallel_self_test.py:231

Referenced by get_oomph_root().

◆ find_validate_dirs()

List[str] parallel_self_test.find_validate_dirs ( List[str]  base_dirs)
Construct a list of validation directories by searching for
validate.sh scripts.
254 def find_validate_dirs(base_dirs: List[str]) -> List[str]:
255  """Construct a list of validation directories by searching for
256  validate.sh scripts."""
257 
258  all_validation_dirs = []
259  for base in base_dirs:
260  for root, _, files in os.walk(base):
261  if 'validate.sh' in files:
262  all_validation_dirs.append(root)
263  return all_validation_dirs
264 
265 
List[str] find_validate_dirs(List[str] base_dirs)
Definition: parallel_self_test.py:254

Referenced by main().

◆ get_oomph_root()

str parallel_self_test.get_oomph_root ( )
237 def get_oomph_root() -> str:
238  try:
239  print("Trying to extract the root dir from a Makefile in the pwd.")
240  oomph_root = variable_from_makefile("abs_top_srcdir")
241  print("Extracted oomph_root = " + oomph_root)
242  return oomph_root
243 
244  # If no makefile exists we are stuck:
245  except NoMakefileError as e:
246  print(str(e))
247  error("You must either run this script from within an oomph-lib",
248  "directory or specify the path to oomph_root using -C.")
249 
250 # Validation functions
251 # ============================================================
252 
253 
str
Definition: compute_granudrum_aor.py:141
str variable_from_makefile(str variable_name, str makefile_path="Makefile")
Definition: parallel_self_test.py:185
str get_oomph_root()
Definition: parallel_self_test.py:237

References error(), Eigen::internal.print(), compute_granudrum_aor.str, and variable_from_makefile().

Referenced by check-makefile-subdirs.main(), and main().

◆ get_overall_self_test_exit_code()

int parallel_self_test.get_overall_self_test_exit_code ( List[ExitCode test_results)
Returns the overall exit code based on the test results.

Only build and test failure exit codes classify the overall self-test as a
"failure". If either (or both) of those are present, an appropriate nonzero
exit code will be returned.
166 def get_overall_self_test_exit_code(test_results: List[ExitCode]) -> int:
167  """Returns the overall exit code based on the test results.
168 
169  Only build and test failure exit codes classify the overall self-test as a
170  "failure". If either (or both) of those are present, an appropriate nonzero
171  exit code will be returned.
172  """
173  failing_exit_codes = (ExitCode.BUILD_FAILURE, ExitCode.TEST_FAILURE)
174  overall_exit_code = 0
175  for exit_code in test_results:
176  if exit_code in failing_exit_codes:
177  overall_exit_code |= int(exit_code)
178  return overall_exit_code
179 
180 
return int(ret)+1
int get_overall_self_test_exit_code(List[ExitCode] test_results)
Definition: parallel_self_test.py:166

References int().

Referenced by main().

◆ highlight()

str parallel_self_test.highlight ( str  directory_path)
91 def highlight(directory_path: str) -> str:
92  return os.path.dirname(directory_path) + "/" + COLOURS.Header + \
93  os.path.basename(directory_path) + COLOURS.Endc
94 
95 

Referenced by build_fail_message(), check_fail_message(), check_success_message(), missing_feature_message(), and no_check_message().

◆ main()

def parallel_self_test.main ( )
Run oomph-lib self tests in parallel.

Typical usage is just:

    parallel_self_test.py

from within an oomph-lib directory, or

    parallel_self_test.py -C /abs/path/to/oomph/root

from anywhere.


For this script to work correctly ALL validate.sh scripts must return
an exit status. Use the --check-scripts option to check this.

Note: aborting with C-c will not work in python2 due to limitations
of python2's multiprocessing module. The easiest way to abort is
probably to kill the terminal emulator itself. Alternatively
background the python process with C-z then kill it (i.e. run "kill
%%"). Or just upgrade to python3.
384 def main():
385  """
386  Run oomph-lib self tests in parallel.
387 
388  Typical usage is just:
389 
390  parallel_self_test.py
391 
392  from within an oomph-lib directory, or
393 
394  parallel_self_test.py -C /abs/path/to/oomph/root
395 
396  from anywhere.
397 
398 
399  For this script to work correctly ALL validate.sh scripts must return
400  an exit status. Use the --check-scripts option to check this.
401 
402  Note: aborting with C-c will not work in python2 due to limitations
403  of python2's multiprocessing module. The easiest way to abort is
404  probably to kill the terminal emulator itself. Alternatively
405  background the python process with C-z then kill it (i.e. run "kill
406  %%"). Or just upgrade to python3.
407  """
408 
409  # Parse inputs
410  # ============================================================
411  parser = argparse.ArgumentParser(
412  description=main.__doc__,
413 
414  # Don't mess up my formating in the help message
415  formatter_class=argparse.RawDescriptionHelpFormatter,
416  )
417 
418  # make uses -C for "run make in this directory" so copy it
419  parser.add_argument(
420  '-C', dest='oomph_root',
421  help='Set the root directory of oomph-lib, by default try to extract it from a Makefile.'
422  )
423 
424  parser.add_argument(
425  '-a', action='store_true', dest='makeclean',
426  help='Run make clean on test folders before starting.'
427  )
428 
429  parser.add_argument(
430  '-l', '--base-dir', action='append', dest='base_dirs',
431  default=[],
432  help='Specify directories relative to the root to (recursively)'
433  + ' look for tests in.'
434  + ' Uses "demo_drivers" and "self_test" by default.'
435  )
436 
437  parser.add_argument(
438  '-L', '--base-dirs-file', action='append', dest='base_dirs_files',
439  default=[],
440  help='Specify files containing a list of directories relative to the root to (recursively) look for tests in. Uses "demo_drivers" and "self_test" by default.'
441  )
442 
443  parser.add_argument(
444  '-j', '-n', dest='ncores',
445  help='Specifiy how many cores should be used altogether \
446  (taking mpi runs into account). By default use all cores.',
447  default=multiprocessing.cpu_count()
448  )
449 
450  parser.add_argument(
451  '--no-colour', action='store_true',
452  help='Disable colours in output.'
453  )
454 
455  parser.add_argument(
456  '--check-scripts', action='store_true',
457  help='Check all the validate.sh scripts using a simple '
458  + 'regex to make sure that they set an exit status.'
459  )
460 
461  parser.add_argument(
462  '--just-build', action='store_true',
463  help="Only build the tests, don't run them"
464  )
465 
466  parser.add_argument(
467  '--serial-mode', action='store_true',
468  help='Run the script without parallelism (for debugging'
469  + ' purposes).'
470  )
471 
472  args = parser.parse_args()
473 
474  if args.no_colour:
475  COLOURS.disable()
476 
477  # Attempt to get the oomph-lib root dir from a Makefile in the current
478  # directory.
479  if args.oomph_root is None:
480  args.oomph_root = get_oomph_root()
481 
482  # If we requested just checking the validate.sh scripts instead of
483  # running the tests
484  if args.check_scripts:
485  # Grep for some way of returning an exit status in validate.sh scripts,
486  # print out those that don't contain one.
487  print("Checking validate.sh scripts. Any scripts printed below do not set\n" +
488  "their exit status properly and so the results cannot be correctly\n" +
489  "reported by this script.")
490  print("Look in other validate scripts to see how to fix this.")
491  subp.call('find -name "validate.sh" | xargs grep -i -L "^exit \|^set -o errexit"',
492  shell=True, cwd=args.oomph_root)
493  return 0
494 
495  # Figure out if we have various features
496  # ============================================================
497 
498  # ??ds there MUST be a way to detect this somehow...
499  have_arpack = False
500 
501  # Find out if we have mpi by looking for "OOMPH_HAS_MPI" in flags in
502  # Makefile.
503  have_mpi = "OOMPH_HAS_MPI" in \
505  "AM_CPPFLAGS", pjoin(args.oomph_root, "Makefile"))
506 
507  # Similarly for hlib
508  have_hlib = "OOMPH_HAS_HLIB" in \
510  "AM_CPPFLAGS", pjoin(args.oomph_root, "Makefile"))
511 
512  # List of possible features. Each one must contain: "feature_name",
513  # check_driver_function--a function to find out if a directory requires
514  # this feature and have_feature--a boolean for if we have this feature
515  # or not.
516  oomph_features = ([
517  {
518  'feature_name': "arpack",
519  'check_driver_function': check_if_arpack_driver,
520  'have_feature': have_arpack
521  },
522  {
523  'feature_name': "mpi",
524  'check_driver_function': check_if_mpi_driver,
525  'have_feature': have_mpi
526  },
527  {
528  'feature_name': "hlib",
529  'check_driver_function': check_if_hlib_driver,
530  'have_feature': have_hlib,
531  }
532  ])
533 
534  # Print our findings:
535  print("\nChecked for the following features:")
536  for feature in oomph_features:
537  print(" ", feature['feature_name'], ":", feature['have_feature'])
538 
539  # Gather directory lists etc.
540  # ============================================================
541  base_dirs = args.base_dirs
542 
543  # If given any files with lists of dirnames then read in those too
544  for dirs_file_name in args.base_dirs_files:
545  with open(dirs_file_name) as f:
546  # Strip whitespace and ignore blank lines
547  base_dirs = base_dirs + \
548  [l.strip() for l in f.readlines() if l.strip() != ""]
549 
550  # If there are no base dirs given in either list then use defaults:
551  if len(base_dirs) == 0:
552  base_dirs = ["demo_drivers", "self_test"]
553 
554  # Convert to absolute paths
555  abs_base_dirs = [os.path.abspath(os.path.join(args.oomph_root, b))
556  for b in base_dirs]
557 
558  print("\nLooking for validate.sh scripts in directories:")
559  pprint.pprint(abs_base_dirs)
560  print()
561 
562  # Run tests
563  # =========================================================================
564 
565  # Clean up from past runs if requested
566  if args.makeclean:
567  print("Running (recursive) 'make clean' in", *abs_base_dirs)
568  for directory in abs_base_dirs:
569  # Make clean in "directory" with stdout thrown away.
570  subp.check_call(['make', 'clean', '-k',
571  '-j', str(args.ncores)],
572  stdout=open(os.devnull, 'w'),
573  cwd=directory)
574 
575  # Construct a list of validation directories
576  validation_dirs = find_validate_dirs(abs_base_dirs)
577 
578  # Construct final function to run on each directory
579  f = pt(dispatch_dir, features=oomph_features, just_build=args.just_build)
580 
581  if args.serial_mode:
582  # list forces evaluation of the map
583  test_results = list(map(f, validation_dirs))
584  else:
585  # Run it in parallel, using a context manager to safely handle the
586  # destruction of any allocated resources
587  with Pool(processes=int(args.ncores)) as pool:
588  # Set chunksize to 1 (i.e. each "make check" call is in its own
589  # "chunk of work") to avoid the situation where multiple slow "make
590  # check"s end up in the same chunk and we have to wait ages for it
591  # to finish
592  test_results = pool.map(f, validation_dirs, 1)
593 
594  # Stats collection: count the number of passes/fails
595  print_results_summary(test_results)
596 
597  # Done! If any of the tests returned a build or test failure exit code, then
598  # return a non-zero exit code here!
599  return get_overall_self_test_exit_code(test_results)
600 
601 
602 # If this script is run from a shell then run main() and return the result.
None print_results_summary(List[ExitCode] test_results)
Definition: parallel_self_test.py:124
def main()
Definition: parallel_self_test.py:384

References find_validate_dirs(), get_oomph_root(), get_overall_self_test_exit_code(), int(), Eigen::internal.print(), print_results_summary(), compute_granudrum_aor.str, and variable_from_makefile().

◆ make_check_in_dir()

ExitCode parallel_self_test.make_check_in_dir ( str  directory,
bool   just_build = False 
)
Rebuild binaries in the directory using make if needed then run the
tests.

Since everything important is written to validation logs we just
summarise passes/fails on stdout.

Output from compilation is sent to make_check_output file in
directory. The file is then moved into Validation once we can be
sure the folder exists.
298 def make_check_in_dir(directory: str, just_build: bool = False) -> ExitCode:
299  """
300  Rebuild binaries in the directory using make if needed then run the
301  tests.
302 
303  Since everything important is written to validation logs we just
304  summarise passes/fails on stdout.
305 
306  Output from compilation is sent to make_check_output file in
307  directory. The file is then moved into Validation once we can be
308  sure the folder exists.
309  """
310 
311  # Write make output into a file in test rootdir (in case Validation dir
312  # doesn't exist yet).
313  tracefile_path = pjoin(directory, "make_check_output")
314 
315  with open(tracefile_path, 'w') as tracefile:
316 
317  # Need to flush write buffer so that this gets into the file
318  # before the build output.
319  tracefile.write("Building WITH FAKE TEST PASS CONDITION:\n")
320  tracefile.flush()
321 
322  # Rebuild (but don't run the test yet). Minimal output except for
323  # errors. Output goes to the trace file.
324  build_return = subp.call(['make', 'check', '--silent',
325  'LIBTOOLFLAGS=--silent',
326  'TESTS_ENVIRONMENT=true'],
327  cwd=directory,
328  stdout=tracefile,
329  stderr=subp.STDOUT)
330 
331  # If the build failed then return with a build failure immediately
332  if build_return != ExitCode.SUCCESS:
333  build_fail_message(directory)
334  with open(tracefile_path, 'r') as tracefile:
335  print(tracefile.read())
336  return ExitCode.BUILD_FAILURE
337 
338  # Re-open the tracefile and continue appending to it
339  with open(tracefile_path, 'a') as tracefile:
340 
341  if not just_build:
342  tracefile.write("\nRunning self test properly:\n")
343  tracefile.flush()
344 
345  # Run make check (runs the actual test)
346  test_result = subp.call(['make', 'check', '--silent',
347  'LIBTOOLFLAGS=--silent'],
348  cwd=directory,
349  stdout=tracefile,
350  stderr=subp.STDOUT)
351 
352  else:
353  tracefile.write(
354  "\nNot running self test because you set the 'just_build' option\n")
355  tracefile.flush()
356  test_result = 0
357 
358  final_tracefile_path = pjoin(directory, "Validation", "make_check_output")
359  tracefile_name = tracefile_path
360 
361  # Validation dir should exist now. Move the output file there if so,
362  # otherwise issue a warning.
363  if not os.path.isdir(os.path.dirname(final_tracefile_path)):
364  sys.stderr.write("WARNING: no Validation directory in " + directory
365  + " so I couldn't put make_check_output in there\n")
366  sys.stderr.flush()
367  else:
368  os.rename(tracefile_path, final_tracefile_path)
369  tracefile_name = final_tracefile_path
370 
371  if test_result == 0:
372  check_success_message(directory)
373  exit_code = ExitCode.SUCCESS
374  else:
375  with open(tracefile_name, 'r') as tracefile:
376  print(tracefile.read())
377  check_fail_message(directory)
378  exit_code = ExitCode.TEST_FAILURE
379  return exit_code
380 
381 
382 # Function dealing with parsing of arguments, getting everything set up and
383 # dispatching jobs to processes.

References build_fail_message(), check_fail_message(), check_success_message(), and Eigen::internal.print().

Referenced by dispatch_dir().

◆ missing_feature_message()

str parallel_self_test.missing_feature_message ( str  directory,
str  feature 
)
116 def missing_feature_message(directory: str, feature: str) -> str:
117  print(COLOURS.Okgreen + "[NO " + feature.upper() + "] " +
118  highlight(directory) + COLOURS.Endc)
119 
120 
121 # Some general utility functions
122 # ============================================================
123 

References highlight(), and Eigen::internal.print().

Referenced by dispatch_dir().

◆ no_check_message()

str parallel_self_test.no_check_message ( str  directory)
111 def no_check_message(directory: str) -> str:
112  print(COLOURS.Okgreen + "[NO CHECK] " + highlight(directory) +
113  COLOURS.Endc)
114 
115 
str no_check_message(str directory)
Definition: parallel_self_test.py:111

References highlight(), and Eigen::internal.print().

◆ print_results_summary()

None parallel_self_test.print_results_summary ( List[ExitCode test_results)
Prints a summary of the test results.

The number of passes, build fails, test fails, and bypassed tests are
determined from the test result exit codes.
124 def print_results_summary(test_results: List[ExitCode]) -> None:
125  """Prints a summary of the test results.
126 
127  The number of passes, build fails, test fails, and bypassed tests are
128  determined from the test result exit codes.
129  """
130  header = (lambda s: f"{COLOURS.Header}{s}{COLOURS.Endc}")
131  green = (lambda s: f"{COLOURS.Okgreen}{s}{COLOURS.Endc}")
132  orange = (lambda s: f"{COLOURS.MakeFail}{s}{COLOURS.Endc}")
133  red = (lambda s: f"{COLOURS.TestFail}{s}{COLOURS.Endc}")
134  magenta = (lambda s: f"{COLOURS.TestBypassed}{s}{COLOURS.Endc}")
135 
136  # Initialise values
137  (passes, build_fails, test_fails, tests_bypassed) = (0, 0, 0, 0)
138 
139  # Stats collection: count the number of passes/fails, etc.
140  for exit_code in test_results:
141  if exit_code == ExitCode.SUCCESS:
142  passes += 1
143  elif exit_code == ExitCode.BUILD_FAILURE:
144  build_fails += 1
145  elif exit_code == ExitCode.TEST_FAILURE:
146  test_fails += 1
147  elif exit_code == ExitCode.MISSING_FEATURE:
148  tests_bypassed += 1
149  else:
150  print(
151  f"WARNING: Unexpected ExitCode '{exit_code}'; not sure how to deal with it!")
152 
153  # Stringify a summary of the results
154  results_description = header(f"\nTest results:\n")
155  results_description += header(f" * Number of tests: {len(test_results)}\n")
156  results_description += green(f" * Tests passed: {passes}\n")
157  results_description += orange(f" * Builds failed: {build_fails}\n")
158  results_description += red(f" * Tests failed: {test_fails}\n")
159  results_description += magenta(
160  f" * Tests bypassed (due to missing features): {tests_bypassed}\n")
161 
162  # Print the processed results
163  print(results_description)
164 
165 

References Eigen::internal.print().

Referenced by main().

◆ variable_from_makefile()

str parallel_self_test.variable_from_makefile ( str  variable_name,
str   makefile_path = "Makefile" 
)
Extract a variable from a makefile (using make).

The basic idea is to cat a new "print-var" command, which prints the
variable we want, onto the start of the makefile. Then we just run
"make print-var" and make gives us the value we want.

Of course we don't actually modify the real makefile, we make a
stream and pipe it into make instead.

The idea came from somewhere on the internet, probably
stackoverflow.
185 def variable_from_makefile(variable_name: str, makefile_path: str = "Makefile") -> str:
186  """Extract a variable from a makefile (using make).
187 
188  The basic idea is to cat a new "print-var" command, which prints the
189  variable we want, onto the start of the makefile. Then we just run
190  "make print-var" and make gives us the value we want.
191 
192  Of course we don't actually modify the real makefile, we make a
193  stream and pipe it into make instead.
194 
195  The idea came from somewhere on the internet, probably
196  stackoverflow."""
197 
198  if not os.path.isfile(makefile_path):
199  raise NoMakefileError("Makefile not found at path: " + makefile_path +
200  " , maybe you haven't built the Makefile yet or" +
201  " you are in the wrong folder?")
202 
203  # Find out which directory it's in (and handle the case where it's in
204  # the pwd, which dirname fails a bit on...
205  makefile_dir = os.path.dirname(makefile_path)
206  if makefile_dir == "":
207  makefile_dir = pjoin('.', '')
208 
209  # Run make using both a real makefile and a dummy one we are about to
210  # create. Call the "print-var" command which will be in the dummy
211  # makefile.
212  process = subp.Popen(["make", "-f", "-", "-f", makefile_path, "print-var"],
213  cwd=makefile_dir,
214  stdin=subp.PIPE, stdout=subp.PIPE)
215 
216  # Send in a dummy makefile with a print command, output should be the
217  # value of the variable.
218  stdout, _ = process.communicate(
219  ("print-var:; @echo $(" + variable_name + ")").encode())
220 
221  # Check that make exited with a success code (0)
222  returncode = process.wait()
223  if returncode != 0:
224  raise subp.CalledProcessError(returncode, "make print-var ....")
225 
226  # Convert to python string (for python3), strip trailing
227  # newline/whitespace and return.
228  return stdout.decode().rstrip()
229 
230 
int encode(Index i, Index j)
Definition: indexed_view.cpp:24

Referenced by check-makefile-subdirs.check_makefileam(), get_oomph_root(), and main().

Variable Documentation

◆ COLOURS

parallel_self_test.COLOURS = Colours()