Skip to content

Commit 28bcb5d

Browse files
committed
✨ Implement option validation for conditional requirements in presets.
1 parent 09a4b9d commit 28bcb5d

File tree

3 files changed

+119
-1
lines changed

3 files changed

+119
-1
lines changed

tools/cmake/common/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,8 @@ def run_cmake(
121121
self.assertNotEqual(result.returncode, 0)
122122
actual_error = result.stderr.decode("utf-8")
123123
self.assertTrue(
124-
error_contains in actual_error, f"Actual error: {actual_error}"
124+
error_contains in actual_error,
125+
f"\n\nWanted: {error_contains}\n\nActual: {actual_error}",
125126
)
126127
else:
127128
self.assertEqual(result.returncode, 0)

tools/cmake/common/preset.cmake

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,23 @@ macro(load_build_preset)
104104
# For now, just continue if the preset file is not set. In the future, we will
105105
# try to determine a preset file.
106106
endmacro()
107+
108+
109+
# Check if the required options are set.
110+
function(check_required_options_on)
111+
cmake_parse_arguments(
112+
ARG
113+
""
114+
"IF_ON"
115+
"REQUIRES"
116+
${ARGN}
117+
)
118+
119+
if(${${ARG_IF_ON}})
120+
foreach(required ${ARG_REQUIRES})
121+
if(NOT ${${required}})
122+
message(FATAL_ERROR "Use of '${ARG_IF_ON}' requires '${required}'")
123+
endif()
124+
endforeach()
125+
endif()
126+
endfunction()

tools/cmake/common/preset_test.py

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,3 +319,100 @@ def test_set_overridable_option_with_cli_override(self):
319319
)
320320
self.run_cmake(cmake_args=["-DEXECUTORCH_TEST_MESSAGE='from the cli'"])
321321
self.assert_cmake_cache("EXECUTORCH_TEST_MESSAGE", "from the cli", "STRING")
322+
323+
def test_check_required_options_on_if_on_off(self):
324+
"""Test that when IF_ON is OFF, no checks are performed."""
325+
326+
_cmake_lists_txt = """
327+
cmake_minimum_required(VERSION 3.24)
328+
project(test_preset)
329+
include(${PROJECT_SOURCE_DIR}/preset.cmake)
330+
331+
set(FEATURE_FLAG OFF)
332+
set(REQUIRED_OPTION1 OFF)
333+
set(REQUIRED_OPTION2 OFF)
334+
335+
check_required_options_on(
336+
IF_ON
337+
FEATURE_FLAG
338+
REQUIRES
339+
REQUIRED_OPTION1
340+
REQUIRED_OPTION2
341+
)
342+
"""
343+
self.create_workspace({"CMakeLists.txt": _cmake_lists_txt})
344+
self.run_cmake() # Should succeed
345+
346+
def test_check_required_options_on_all_required_on(self):
347+
"""Test that when IF_ON is ON and all required options are ON, no error occurs."""
348+
349+
_cmake_lists_txt = """
350+
cmake_minimum_required(VERSION 3.24)
351+
project(test_preset)
352+
include(${PROJECT_SOURCE_DIR}/preset.cmake)
353+
354+
set(FEATURE_FLAG ON)
355+
set(REQUIRED_OPTION1 ON)
356+
set(REQUIRED_OPTION2 ON)
357+
358+
check_required_options_on(
359+
IF_ON
360+
FEATURE_FLAG
361+
REQUIRES
362+
REQUIRED_OPTION1
363+
REQUIRED_OPTION2
364+
)
365+
"""
366+
self.create_workspace({"CMakeLists.txt": _cmake_lists_txt})
367+
self.run_cmake()
368+
369+
def test_check_required_options_on_one_required_off(self):
370+
"""Test that when IF_ON is ON but one required option is OFF, a fatal error occurs."""
371+
372+
_cmake_lists_txt = """
373+
cmake_minimum_required(VERSION 3.24)
374+
project(test_preset)
375+
include(${PROJECT_SOURCE_DIR}/preset.cmake)
376+
377+
set(FEATURE_FLAG ON)
378+
set(REQUIRED_OPTION1 ON)
379+
set(REQUIRED_OPTION2 OFF)
380+
381+
check_required_options_on(
382+
IF_ON
383+
FEATURE_FLAG
384+
REQUIRES
385+
REQUIRED_OPTION1
386+
REQUIRED_OPTION2
387+
)
388+
"""
389+
self.create_workspace({"CMakeLists.txt": _cmake_lists_txt})
390+
self.run_cmake(
391+
error_contains="Use of 'FEATURE_FLAG' requires 'REQUIRED_OPTION2'"
392+
)
393+
394+
def test_check_required_options_on_multiple_required_off(self):
395+
"""Test that when IF_ON is ON but multiple required options are OFF, a fatal error occurs for the first one."""
396+
397+
_cmake_lists_txt = """
398+
cmake_minimum_required(VERSION 3.24)
399+
project(test_preset)
400+
include(${PROJECT_SOURCE_DIR}/preset.cmake)
401+
402+
set(FEATURE_FLAG ON)
403+
set(REQUIRED_OPTION1 OFF)
404+
set(REQUIRED_OPTION2 OFF)
405+
406+
# This should cause a fatal error
407+
check_required_options_on(
408+
IF_ON
409+
FEATURE_FLAG
410+
REQUIRES
411+
REQUIRED_OPTION1
412+
REQUIRED_OPTION2
413+
)
414+
"""
415+
self.create_workspace({"CMakeLists.txt": _cmake_lists_txt})
416+
self.run_cmake(
417+
error_contains="Use of 'FEATURE_FLAG' requires 'REQUIRED_OPTION1'"
418+
)

0 commit comments

Comments
 (0)