Skip to content
This repository was archived by the owner on Sep 3, 2024. It is now read-only.

Commit 9cb2155

Browse files
author
William McLendon
committed
Merge branch 'TRILFRAME-120-A' into 'master'
Trilframe-136: Merging in TRILFRAME-120 See merge request trilinos-devops-consolidation/code/SetProgramOptions!17
2 parents 43bd41b + 911bc6d commit 9cb2155

File tree

8 files changed

+381
-79
lines changed

8 files changed

+381
-79
lines changed

CHANGELOG.md

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1717
#### Todo (for Unreleased)
1818
-->
1919

20-
## [0.3.1] <!-- YYYY-MM-DD --> [Unreleased]
20+
## [0.4.0] <!-- YYYY-MM-DD --> [Unreleased]
2121
#### Added
2222
#### Changed
2323
- Changes to `opt-set-cmake-var` behaviour:
2424
- Trigger a WARNING if `PARENT_SCOPE` and a _TYPE_ is provided since CMake
2525
requires TYPED vars to be CACHE vars and `PARENT_SCOPE` will force the
2626
var to be considered a non CACHE var that would store the parameters
27-
before `PARENT_SCOPE` in the call as _list_ entries.
27+
before `PARENT_SCOPE` in the call as _list_ entries. (TRILFRAME-128)
2828
- Trigger an exception if `PARENT_SCOPE` and `FORCE` are both provided since
2929
`FORCE` is only valid for CACHE variables but `PARENT_SCOPE` is only valid
3030
for non-CACHE vars (and as noted above will _force_ the `set()` operation
3131
to be a non-CACHE var which then triggers a CMake error because `FORCE` is
32-
invalid to that form of `set()`.
32+
invalid to that form of `set()`. (TRILFRAME-128)
3333
- **bash** generated options that have a TYPE and `PARENT_SCOPE` are processed
3434
to generate the same _list_ string that would be generated by the matching
35-
`set()` operation (with the warning).
35+
`set()` operation (with the warning). (TRILFRAME-128)
36+
- For **bash** generation, trigger a WARNING and DO NOT generate the `-D` CLI option
37+
if `opt-set-cmake-var` without `FORCE` is called on a CMake Cache variable that has
38+
already been set. (TRILFRAME-120).
39+
- For **bash** generation, trigger a WARNING and DO NOT generate the `-D` CLI option
40+
if `opt-set-cmake-var` is called on a non-cache CMake variable. (TRILFRAME-136)
41+
- For **bash** generation, always add a _TYPE_ to the `-D` CLI option. (TRILFRAME-136)
3642
- Revert(ish) the modifications from MR12 which removed the error when generating
3743
BASH output if there is an unhandled CMake variable left hanging around.
3844
Rather than make this an unavoidable error though, ExpandVarsInText now inherits
@@ -44,6 +50,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4450
#### Deprecated
4551
#### Removed
4652
#### Fixed
53+
- Bash generation handling of the FORCE flag. See TRILFRAME-120 for details.
4754
#### Security
4855
#### Internal
4956
- Add test to verify that `opt-remove` also works to remove variables added
@@ -91,5 +98,3 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9198
#### Added
9299
- Initial version release. From now on changes should be noted in the
93100
CHANGELOG.
94-
95-

SetProgramOptions.wpr

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,7 @@ proj.launch-config = {loc('../../coding/pyExampleLib/configparser/configparser-e
9090
'ustom',
9191
(u'',
9292
'launch-5Gyw4cvA0PytPLLy'))}
93-
proj.main-file = loc('examples/example-01.py')
93+
proj.main-file = loc('exec-example-SetProgramOptions.py')
9494
testing.auto-test-file-specs = (('regex',
95-
'setprogramoptions\\\\unittests\\\\test_.*'\
96-
'\\.py'),)
95+
'unittests\\\\test_.*\\.py'),)
9796
testing.test-framework = {None: ':internal pytest'}

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "setprogramoptions"
3-
version = "0.3.1"
3+
version = "0.4.0"
44
description = "Program options helper."
55
authors = [
66
"William McLendon <[email protected]>"

src/setprogramoptions/SetProgramOptions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,6 @@ class ExpandVarsInText(ExceptionControl):
109109

110110
def __init__(self):
111111
self.exception_control_level = 4
112-
self.exception_control_compact_warnings = True
113112

114113
class VariableFieldData(object):
115114
"""
@@ -526,6 +525,7 @@ def _gen_option_entry(self, option_entry: dict, generator='bash') -> Union[str,
526525

527526
# Update the var formatter's ECL to match the current value.
528527
self._var_formatter.exception_control_level = self.exception_control_level
528+
self._var_formatter.exception_control_compact_warnings = self.exception_control_compact_warnings
529529

530530
# format the value
531531
formatter = self._var_formatter

src/setprogramoptions/SetProgramOptionsCMake.py

Lines changed: 67 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,21 @@
2020
``-DVAR_NAME:BOOL=ON`` using the ``SetProgramOptions`` method ``gen_option_list``
2121
with the ``bash`` generator.
2222
23-
In the case of bash command entries the ``FORCE`` and ``PARENT_SCOPE`` optional
24-
parameters are ignored.
23+
When using the BASH generator to generate command line arguments, CMake
24+
uses the syntax ``-D<VARNAME>[:<TYPE>]=<VALUE>``. The ``TYPE`` field is optional
25+
and if left out CMake will default to a ``STRING`` type. Further, all CMake
26+
variables set via the command line using ``-D`` will be CACHE variables and each
27+
``-D`` operation should be considered a FORCE operation too. For example,
28+
``-DFOO:STRING=BAR`` is roughly equivalent to the CMake command:
29+
``set(FOO CACHE STRING "docstring" FORCE)``.
30+
31+
The ``PARENT_SCOPE`` option applies only to non-cache variables and its presence
32+
will instruct CMake to make that variable non-cache. Care should be taken when
33+
using ``PARENT_SCOPE`` as combining it with the usual CACHE operations results
34+
in CMake creating a non-cached variable whose contents are the list containing
35+
``<varname>;CACHE;<type>;doc string``. As a result, the BASH generator issues
36+
warnings with no generated command line arguments when either 1. ``PARENT_SCOPE``
37+
OR 2. solely a variable name AND variable value are passed in to `opt-set-cmake-var`.
2538
2639
See CMake documentation on the `set() <https://cmake.org/cmake/help/latest/command/set.html>`_
2740
command for more information on how fragment file entries are generated.
@@ -31,8 +44,10 @@
3144
3245
:Authors:
3346
- William C. McLendon III <[email protected]>
47+
- Evan Harvey <[email protected]>
3448
"""
3549
from __future__ import print_function
50+
from enum import Enum
3651

3752
#import inspect
3853
#from pathlib import Path
@@ -73,7 +88,6 @@ class ExpandVarsInTextCMake(ExpandVarsInText):
7388

7489
def __init__(self):
7590
self.exception_control_level = 3
76-
self.exception_control_compact_warnings = True
7791

7892
def _fieldhandler_BASH_CMAKE(self, field):
7993
"""
@@ -120,7 +134,10 @@ def _fieldhandler_CMAKE_FRAGMENT_CMAKE(self, field):
120134
# M A I N C L A S S
121135
# ===============================
122136

123-
137+
class VarType(Enum):
138+
"""Enumeration used to check for CMake variable types in SPOC."""
139+
CACHE = 1
140+
NON_CACHE = 2
124141

125142
class SetProgramOptionsCMake(SetProgramOptions):
126143
"""Extends SetProgramOptions to add in CMake option support.
@@ -183,7 +200,7 @@ def _program_option_handler_opt_set_cmake_fragment(self, params: list, value: st
183200
"""
184201
return None
185202

186-
def _program_option_handler_opt_set_cmake_var_bash(self, params, value) -> str:
203+
def _program_option_handler_opt_set_cmake_var_bash(self, params: list, value: str) -> str:
187204
"""
188205
Line-item generator for ``opt-set-cmake-var`` entries when the *generator*
189206
is set to ``bash``.
@@ -196,23 +213,50 @@ def _program_option_handler_opt_set_cmake_var_bash(self, params, value) -> str:
196213
side-effects since :py:meth:`setprogramoptions.SetProgramOptions._gen_option_entry`
197214
performs a deep-copy of these parameters prior to calling this.
198215
Any changes we make are ephemeral.
216+
217+
Args:
218+
params (list): The parameters of the operation.
219+
value (str): The value of the option that is being assigned.
220+
221+
Raises:
222+
ValueError: This can potentially raise a ``ValueError`` if
223+
``exception_control_level`` is set to 5 if there are
224+
operations that are skipped in Bash generation. If ``ecl``
225+
is less than 5 then warnings are generated to note the
226+
exclusion.
199227
"""
200228
varname = params[0]
201229
params = params[1 : 4]
202230
param_opts = self._helper_opt_set_cmake_var_parse_parameters(params)
203231

204-
params = ["-D", varname]
232+
# Type-1 (non-cached / PARENT_SCOPE / non-typed) entries should not be
233+
# written to the set of Bash parameters.
234+
if param_opts['VARIANT'] == VarType.NON_CACHE:
235+
msg = f"bash generator - `{varname}={value}` skipped because"
236+
msg += f" it is a non-cached (type-1) operation."
237+
msg += f" To generate a bash arg for this consider adding FORCE or a TYPE"
238+
msg += f" and remove PARENT_SCOPE if it exists."
239+
self.exception_control_event("WARNING", ValueError, message=msg)
240+
return None
241+
242+
# If varname has already been assigned and this assignment
243+
# does not include FORCE then we should skip adding it to the
244+
# set of command line options.
245+
if varname in self._var_formatter_cache and not param_opts['FORCE']:
246+
msg = f"bash generator - `{varname}={value}` skipped because"
247+
msg += f" CACHE var `{varname}` is already set and CMake requires"
248+
msg += f" FORCE to be set to change the value."
249+
self.exception_control_event("WARNING", ValueError, message=msg)
250+
return None
205251

206-
if param_opts['VARIANT'] == 1:
207-
# if PARENT_SCOPE was given to something that is typed and forced us to
208-
# be a type-1 variant, then we assign the list "<value>;CACHE;<type>;<docstring>"
209-
if param_opts['TYPE'] != None:
210-
value += f";CACHE;{param_opts['TYPE']};"
252+
# Prepend `-D` to the parameters
253+
params = ["-D", varname]
211254

212-
if param_opts['VARIANT'] == 2 and param_opts['TYPE'] is not None:
213-
params.append(":" + param_opts['TYPE'])
255+
# If the type is provided then include the `:<typename>` argument.
256+
# Note: CMake defaults to STRING if not provided.
257+
params.append(":" + param_opts['TYPE'])
214258

215-
# Cache 'known' CMake vars here.
259+
# Save variable to the cache of 'known'/'set' cmake variables
216260
self._var_formatter_cache[varname] = value
217261

218262
return self._generic_program_option_handler_bash(params, value)
@@ -339,12 +383,15 @@ def _helper_opt_set_cmake_var_parse_parameters(self, params: list):
339383
"""
340384
default_cache_var_type = "STRING"
341385

342-
output = {'FORCE': False, 'PARENT_SCOPE': False, 'TYPE': None}
386+
output = {'FORCE': False, 'PARENT_SCOPE': False, 'TYPE': None, 'VARIANT': None}
343387

344388
for option in params[: 4]:
345389
if option == "FORCE":
346390
output['FORCE'] = True
347391
# If FORCE is found but we have no TYPE yet, set to the default.
392+
# TODO: Should we be setting the default to STRING here when FORCE
393+
# is provided with no explicit type? Future CMake versions might
394+
# someday change the default which would possibly break this?
348395
if output['TYPE'] is None:
349396
output['TYPE'] = default_cache_var_type
350397
elif option == "PARENT_SCOPE":
@@ -358,6 +405,7 @@ def _helper_opt_set_cmake_var_parse_parameters(self, params: list):
358405
if output['FORCE'] and output['PARENT_SCOPE']:
359406
msg = "ERROR: CMake does not allow `FORCE` and `PARENT_SCOPE` to both be used."
360407
self.exception_control_event("CATASTROPHIC", ValueError, message=msg)
408+
361409
# Case 2: PARENT_SCOPE and CACHE will cause a CMake warning
362410
# and the value will include the cache entries as a list:
363411
# `set(FOO "VAL" CACHE STRING "docstring" PARENT_SCOPE)`
@@ -381,18 +429,18 @@ def _helper_opt_set_cmake_var_parse_parameters(self, params: list):
381429
# PARENT_SCOPE forces Type-1 (i.e., non-cache var)
382430
# - This will override CACHE, at least as of CMake 3.21.x
383431
if output['PARENT_SCOPE']:
384-
output['VARIANT'] = 1
432+
output['VARIANT'] = VarType.NON_CACHE
385433

386434
# FORCE implies CACHE. If type wasn't provided then it's a STRING
387435
elif output['FORCE']:
388-
output['VARIANT'] = 2
436+
output['VARIANT'] = VarType.CACHE
389437

390438
# If a TYPE is provided then it's a type-2 (CACHE) assignment.
391439
elif output['TYPE'] is not None:
392-
output['VARIANT'] = 2
440+
output['VARIANT'] = VarType.CACHE
393441

394442
# Otherwise, a simple set is a type-1
395443
else:
396-
output['VARIANT'] = 1
444+
output['VARIANT'] = VarType.NON_CACHE
397445

398446
return output

src/setprogramoptions/unittests/files_ini/config_test_setprogramoptions.ini

Lines changed: 62 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@ opt-set cmake
1414
opt-set -G : Ninja
1515

1616
[TRILINOS_COMMON]
17-
opt-set-cmake-var Trilinos_ENABLE_COMPLEX BOOL : ON
18-
opt-set-cmake-var Trilinos_ENABLE_THREAD_SAFE BOOL : ON
17+
opt-set-cmake-var Trilinos_ENABLE_COMPLEX BOOL : ON
18+
opt-set-cmake-var Trilinos_ENABLE_THREAD_SAFE BOOL : ON
19+
# These are left UNTYPED so they aren't considered CACHE
20+
# vars. This will cause the bash generator to skip them.
1921
opt-set-cmake-var Trilinos_PARALLEL_COMPILE_JOBS_LIMIT : 20
2022
opt-set-cmake-var Trilinos_PARALLEL_LINK_JOBS_LIMIT : 4
2123

@@ -58,17 +60,28 @@ opt-set-cmake-var CMAKE_VAR_A PARENT_SCOPE FORCE : CMAKE_VAR_A_VAL
5860
opt-set-cmake-var CMAKE_VAR_A FORCE : ON
5961
opt-set-cmake-var CMAKE_VAR_B PARENT_SCOPE : ON
6062
opt-set-cmake-var CMAKE_VAR_C BOOL : ON
61-
opt-set-cmake-var CMAKE_VAR_F BOOL FORCE : ON
62-
opt-set-cmake-var CMAKE_VAR_G FORCE BOOL : ON
63-
opt-set-cmake-var CMAKE_VAR_H BOOL PARENT_SCOPE : ON
64-
opt-set-cmake-var CMAKE_VAR_I PARENT_SCOPE BOOL : ON
63+
opt-set-cmake-var CMAKE_VAR_D BOOL FORCE : ON
64+
opt-set-cmake-var CMAKE_VAR_E FORCE BOOL : ON
65+
opt-set-cmake-var CMAKE_VAR_F BOOL PARENT_SCOPE : ON
66+
opt-set-cmake-var CMAKE_VAR_G PARENT_SCOPE BOOL : ON
67+
6568

6669
[TEST_CMAKE_CACHE_PARAM_TEST_02]
6770
# Validate what happens if there's a bad param.
6871
# Note: FORCE option will make this a CACHE var of type STRING
6972
opt-set-cmake-var CMAKE_VAR_A FORCE FOOBAR: ON
7073

7174

75+
# This section is to be used to ensure that PARENT_SCOPE
76+
# will force a type-1 (non-cache) var.
77+
# The entries with PARENT_SCOPE enabled should not appear
78+
# in generated BASH output.
79+
[TEST_CMAKE_PARENT_SCOPE_NOT_BASH]
80+
opt-set-cmake-var FOO_VAR_A PARENT_SCOPE : FOO_VAL A
81+
opt-set-cmake-var FOO_VAR_B STRING PARENT_SCOPE : FOO_VAL B
82+
83+
84+
7285
#
7386
# Sample Test Configurations
7487
#
@@ -136,22 +149,37 @@ opt-set FOO : "${FOOBAR|ENV} -baz"
136149
opt-set FOO : "${FOOBAR} -baz"
137150

138151

152+
#
153+
# Variable expansion tests
154+
#
139155
[TEST_VAR_EXPANSION_COMMON]
156+
# Create the CACHE variable CMAKE_CXX_FLAGS of STRING type.
140157
opt-set-cmake-var CMAKE_CXX_FLAGS STRING : "${LDFLAGS|ENV} -foo"
141158

142-
143159
[TEST_VAR_EXPANSION_UPDATE_01]
160+
# Test an 'update' of CMAKE_CXX_FLAGS that is not FORCE
161+
# - In practice, CMake would not actually update CMAKE_CXX_FLAGS
162+
# here because it's a CACHE var (per TEST_VAR_EXPANSION_COMMON)
163+
# And CMake won't overwrite CACHE vars unless FORCEd.
144164
opt-set cmake
145165
use TEST_VAR_EXPANSION_COMMON
146-
opt-set-cmake-var CMAKE_CXX_FLAGS STRING: "${CMAKE_CXX_FLAGS|CMAKE} -bar"
166+
opt-set-cmake-var CMAKE_CXX_FLAGS STRING : "${CMAKE_CXX_FLAGS|CMAKE} -bar"
147167

148168
[TEST_VAR_EXPANSION_UPDATE_02]
149-
use TEST_VAR_EXPANSION_UPDATE_01
169+
opt-set cmake
170+
use TEST_VAR_EXPANSION_COMMON
171+
# This should be a problem for Bash generation since the CMake var
172+
# CMAKE_F90_FLAGS would be unknown to bash. Depending on the
173+
# exception_control_level this will either trigger an exception when
174+
# sent to the bash generator or it could resolve the CMAKE var to an
175+
# empty string + warning.
150176
opt-set-cmake-var CMAKE_F90_FLAGS STRING: "${CMAKE_F90_FLAGS|CMAKE} -baz"
151177

152178
[TEST_VAR_EXPANSION_UPDATE_03]
179+
# Updates CMAKE_CXX_FLAGS using a FORCE operation.
180+
# In practice, this would result in CMAKE_CXX_FLAGS = "${LDFLAGS|ENV} -foo -bif"
153181
use TEST_VAR_EXPANSION_UPDATE_01
154-
opt-set-cmake-var CMAKE_CXX_FLAGS STRING: "${CMAKE_CXX_FLAGS|CMAKE} -bif"
182+
opt-set-cmake-var CMAKE_CXX_FLAGS STRING FORCE : "${CMAKE_CXX_FLAGS|CMAKE} -bif"
155183

156184

157185
[TEST_STRING_DOUBLE_QUOTES]
@@ -161,9 +189,28 @@ opt-set-cmake-var BAR STRING: "600"
161189

162190
[TEST_CMAKE_VAR_REMOVE]
163191
# Test whether or not opt-remove works for a cmake var
164-
opt-set-cmake-var FOO_TEST: "FOO"
165-
opt-set-cmake-var BAR_TEST: "BAR"
166-
opt-set-cmake-var FOO : "BAZ"
167-
# this should remove `FOO_TEST` from the option list so we will only
168-
# have `BAR_TEST` and `FOO` left.
192+
opt-set-cmake-var FOO_TEST STRING : "FOO"
193+
opt-set-cmake-var BAR_TEST STRING : "BAR"
194+
opt-set-cmake-var BAZ_TEST STRING : "BAZ"
195+
# opt-remove FOO_TEST should remove the FOO_TEST entry
196+
# and leave only the BAR_TEST and BAZ_TEST entries.
169197
opt-remove FOO_TEST
198+
199+
200+
[TEST_CMAKE_VAR_FORCE_ONLY]
201+
opt-set-cmake-var FOO FORCE : "BAR"
202+
203+
204+
[TEST_CMAKE_VAR_IN_BASH_GENERATOR]
205+
# The purpose of this section is to see what we do if someone
206+
# has an _update_ operation (i.e., append/prepend to an existing var)
207+
# and that cmake var does not exist already. In this case we emulate
208+
# this by simulating a typo but it could occur in other cases where
209+
# a cmake generator would expect a fragment to update something that was
210+
# defined elsewhere. Should the bash generator throw an error or replace
211+
# "FOO_VAE" with an empty string?
212+
#
213+
# Set FOO_VAR to something concrete
214+
opt-set-cmake-var FOO_VAR STRING : "FOO"
215+
# Simulated typo in FOO_VAR update
216+
opt-set-cmake-var FOO_VAR FORCE : "BAR ${FOO_VAE|CMAKE}"

0 commit comments

Comments
 (0)