[Openmp-commits] [openmp] [OpenMP] Add libomp unit test infrastructure (PR #168063)
Robert Imschweiler via Openmp-commits
openmp-commits at lists.llvm.org
Mon Jan 12 02:25:54 PST 2026
https://github.com/ro-i updated https://github.com/llvm/llvm-project/pull/168063
>From a30a6421fb103586fa9e25f81a0f248a1f8449f3 Mon Sep 17 00:00:00 2001
From: Robert Imschweiler <robert.imschweiler at amd.com>
Date: Fri, 14 Nov 2025 07:54:28 -0600
Subject: [PATCH 01/12] [OpenMP] Add libomp unit test infrastructure
---
openmp/runtime/CMakeLists.txt | 1 +
openmp/runtime/src/CMakeLists.txt | 13 +-
openmp/runtime/unittests/CMakeLists.txt | 39 ++++
openmp/runtime/unittests/README.md | 7 +
openmp/runtime/unittests/lit.cfg.py | 22 ++
openmp/runtime/unittests/lit.site.cfg.py.in | 9 +
openmp/runtime/unittests/src/CMakeLists.txt | 3 +
openmp/runtime/unittests/src/TestKmpStr.cpp | 239 ++++++++++++++++++++
8 files changed, 331 insertions(+), 2 deletions(-)
create mode 100644 openmp/runtime/unittests/CMakeLists.txt
create mode 100644 openmp/runtime/unittests/README.md
create mode 100644 openmp/runtime/unittests/lit.cfg.py
create mode 100644 openmp/runtime/unittests/lit.site.cfg.py.in
create mode 100644 openmp/runtime/unittests/src/CMakeLists.txt
create mode 100644 openmp/runtime/unittests/src/TestKmpStr.cpp
diff --git a/openmp/runtime/CMakeLists.txt b/openmp/runtime/CMakeLists.txt
index 93948b941f0dc..33276b7d97d3a 100644
--- a/openmp/runtime/CMakeLists.txt
+++ b/openmp/runtime/CMakeLists.txt
@@ -446,6 +446,7 @@ endif()
add_subdirectory(src)
add_subdirectory(test)
+add_subdirectory(unittests)
# make these variables available for tools:
set(LIBOMP_LIBRARY_DIR ${LIBOMP_LIBRARY_DIR} PARENT_SCOPE)
diff --git a/openmp/runtime/src/CMakeLists.txt b/openmp/runtime/src/CMakeLists.txt
index 0c0804776a774..7440f1fd05f9c 100644
--- a/openmp/runtime/src/CMakeLists.txt
+++ b/openmp/runtime/src/CMakeLists.txt
@@ -174,17 +174,26 @@ if(NOT WIN32)
endif()
# Add the OpenMP library
+
+# First, create an OBJECT library with all the runtime sources.
+# This allows both the main library and unit tests to link against the same compiled objects.
+add_library(omp_objects OBJECT ${LIBOMP_SOURCE_FILES})
+set_property(TARGET omp_objects PROPERTY FOLDER "OpenMP/Libraries")
+set_property(TARGET omp_objects PROPERTY POSITION_INDEPENDENT_CODE ON)
+# Export the omp_objects target so unittests can use it
+set(LIBOMP_OBJECTS_TARGET omp_objects PARENT_SCOPE)
+
libomp_get_ldflags(LIBOMP_CONFIGURED_LDFLAGS)
libomp_get_libflags(LIBOMP_CONFIGURED_LIBFLAGS)
# Build libomp library. Add LLVMSupport dependency if building in-tree with libomptarget profiling enabled.
if(OPENMP_STANDALONE_BUILD OR (NOT OPENMP_ENABLE_LIBOMP_PROFILING))
- add_library(omp ${LIBOMP_LIBRARY_KIND} ${LIBOMP_SOURCE_FILES})
+ add_library(omp ${LIBOMP_LIBRARY_KIND} $<TARGET_OBJECTS:omp_objects>)
set_property(TARGET omp PROPERTY FOLDER "OpenMP/Libraries")
# Linking command will include libraries in LIBOMP_CONFIGURED_LIBFLAGS
target_link_libraries(omp ${LIBOMP_CONFIGURED_LIBFLAGS} ${LIBOMP_DL_LIBS})
else()
- add_llvm_library(omp ${LIBOMP_LIBRARY_KIND} ${LIBOMP_SOURCE_FILES} PARTIAL_SOURCES_INTENDED
+ add_llvm_library(omp ${LIBOMP_LIBRARY_KIND} $<TARGET_OBJECTS:omp_objects> PARTIAL_SOURCES_INTENDED
LINK_LIBS ${LIBOMP_CONFIGURED_LIBFLAGS} ${LIBOMP_DL_LIBS}
LINK_COMPONENTS Support
BUILDTREE_ONLY
diff --git a/openmp/runtime/unittests/CMakeLists.txt b/openmp/runtime/unittests/CMakeLists.txt
new file mode 100644
index 0000000000000..14ddbfc827cbb
--- /dev/null
+++ b/openmp/runtime/unittests/CMakeLists.txt
@@ -0,0 +1,39 @@
+add_custom_target(OpenMPUnitTests)
+set_target_properties(OpenMPUnitTests PROPERTIES FOLDER "OpenMP/Tests")
+
+if (NOT TARGET llvm_gtest)
+ message(WARNING "OpenMP unittests disabled due to GTest being unavailable; "
+ "Try LLVM_INSTALL_GTEST=ON for the LLVM build")
+ return ()
+endif ()
+
+function(add_openmp_unittest test_dirname)
+ add_unittest(OpenMPUnitTests ${test_dirname} ${ARGN})
+
+ # Link against the object library created in runtime/src
+ target_link_libraries(${test_dirname} PRIVATE
+ $<TARGET_OBJECTS:omp_objects>
+ )
+
+ target_include_directories(${test_dirname} PRIVATE
+ ${LIBOMP_INCLUDE_DIR}
+ ${LIBOMP_SRC_DIR}
+ )
+endfunction()
+
+configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in
+ ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg.py
+ MAIN_CONFIG
+ ${CMAKE_CURRENT_SOURCE_DIR}/lit.cfg.py
+)
+
+add_openmp_testsuite(
+ check-libomp-unit
+ "Running libomp unit tests"
+ ${CMAKE_CURRENT_BINARY_DIR}
+ EXCLUDE_FROM_CHECK_ALL
+ DEPENDS OpenMPUnitTests omp
+)
+
+add_subdirectory(src)
diff --git a/openmp/runtime/unittests/README.md b/openmp/runtime/unittests/README.md
new file mode 100644
index 0000000000000..ad7dd9d716ceb
--- /dev/null
+++ b/openmp/runtime/unittests/README.md
@@ -0,0 +1,7 @@
+# libomp Unit Tests
+
+Usage:
+```
+cd <your-llvm-build-directory>/runtimes/runtimes-bins
+ninja check-libomp-unit
+```
\ No newline at end of file
diff --git a/openmp/runtime/unittests/lit.cfg.py b/openmp/runtime/unittests/lit.cfg.py
new file mode 100644
index 0000000000000..552ea8ef9854d
--- /dev/null
+++ b/openmp/runtime/unittests/lit.cfg.py
@@ -0,0 +1,22 @@
+# -*- Python -*-
+
+# Configuration file for the 'lit' test runner.
+
+import os
+import subprocess
+
+import lit.formats
+
+# name: The name of this test suite.
+config.name = "OpenMP-Unit"
+
+# suffixes: A list of file extensions to treat as test files.
+config.suffixes = []
+
+# test_source_root: The root path where tests are located.
+# test_exec_root: The root path where tests should be run.
+config.test_exec_root = config.openmp_unittests_dir
+config.test_source_root = config.test_exec_root
+
+# testFormat: The test format to use to interpret tests.
+config.test_format = lit.formats.GoogleTest(config.llvm_build_mode, ".unittests")
diff --git a/openmp/runtime/unittests/lit.site.cfg.py.in b/openmp/runtime/unittests/lit.site.cfg.py.in
new file mode 100644
index 0000000000000..878c95f1d8e29
--- /dev/null
+++ b/openmp/runtime/unittests/lit.site.cfg.py.in
@@ -0,0 +1,9 @@
+ at AUTO_GEN_COMMENT@
+
+config.library_dir = "@LIBOMP_LIBRARY_DIR@"
+config.openmp_unittests_dir = "@CMAKE_CURRENT_BINARY_DIR@"
+config.llvm_build_mode = lit_config.substitute("@LLVM_BUILD_MODE@")
+
+# Let the main config do the real work.
+lit_config.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/lit.cfg.py")
+
diff --git a/openmp/runtime/unittests/src/CMakeLists.txt b/openmp/runtime/unittests/src/CMakeLists.txt
new file mode 100644
index 0000000000000..455fbf0b92fc5
--- /dev/null
+++ b/openmp/runtime/unittests/src/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_openmp_unittest(libomp.unittests
+ TestKmpStr.cpp
+)
diff --git a/openmp/runtime/unittests/src/TestKmpStr.cpp b/openmp/runtime/unittests/src/TestKmpStr.cpp
new file mode 100644
index 0000000000000..a22a729da9272
--- /dev/null
+++ b/openmp/runtime/unittests/src/TestKmpStr.cpp
@@ -0,0 +1,239 @@
+//===- TestKmpStr.cpp - Tests for kmp_str utilities ----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "kmp_str.h"
+#include "gtest/gtest.h"
+#include <cstring>
+
+namespace {
+
+// Test basic string buffer initialization
+TEST(KmpStrTest, BufferInit) {
+ kmp_str_buf_t buffer;
+ __kmp_str_buf_init(&buffer);
+
+ EXPECT_NE(buffer.str, nullptr);
+ EXPECT_GT(buffer.size, 0u);
+ EXPECT_EQ(buffer.used, 0);
+ EXPECT_EQ(buffer.str[0], '\0');
+}
+
+// Test string buffer clear
+TEST(KmpStrTest, BufferClear) {
+ kmp_str_buf_t buffer;
+ __kmp_str_buf_init(&buffer);
+ __kmp_str_buf_print(&buffer, "test string");
+
+ EXPECT_GT(buffer.used, 0);
+
+ __kmp_str_buf_clear(&buffer);
+ EXPECT_EQ(buffer.used, 0);
+ EXPECT_EQ(buffer.str[0], '\0');
+
+ __kmp_str_buf_free(&buffer);
+}
+
+// Test string buffer print
+TEST(KmpStrTest, BufferPrint) {
+ kmp_str_buf_t buffer;
+ __kmp_str_buf_init(&buffer);
+
+ __kmp_str_buf_print(&buffer, "Hello, %s!", "World");
+
+ EXPECT_STREQ(buffer.str, "Hello, World!");
+ EXPECT_EQ(buffer.used, 13);
+
+ __kmp_str_buf_free(&buffer);
+}
+
+// Test string buffer concatenation
+TEST(KmpStrTest, BufferCat) {
+ kmp_str_buf_t buffer;
+ __kmp_str_buf_init(&buffer);
+
+ __kmp_str_buf_cat(&buffer, "Hello", 5);
+ __kmp_str_buf_cat(&buffer, " ", 1);
+ __kmp_str_buf_cat(&buffer, "World", 5);
+
+ EXPECT_STREQ(buffer.str, "Hello World");
+
+ __kmp_str_buf_free(&buffer);
+}
+
+// Test string buffer reservation
+TEST(KmpStrTest, BufferReserve) {
+ kmp_str_buf_t buffer;
+ __kmp_str_buf_init(&buffer);
+
+ size_t large_size = 2048;
+ __kmp_str_buf_reserve(&buffer, large_size);
+
+ EXPECT_GE(buffer.size, large_size);
+
+ __kmp_str_buf_free(&buffer);
+}
+
+// Test basic string to int conversion
+TEST(KmpStrTest, BasicStrToInt) {
+ EXPECT_EQ(__kmp_basic_str_to_int("0"), 0);
+ EXPECT_EQ(__kmp_basic_str_to_int("1"), 1);
+ EXPECT_EQ(__kmp_basic_str_to_int("42"), 42);
+ EXPECT_EQ(__kmp_basic_str_to_int("123"), 123);
+}
+
+// Test string match
+TEST(KmpStrTest, StrMatch) {
+ const char *data = "Hello World";
+
+ // Test exact match (len == 0)
+ EXPECT_TRUE(__kmp_str_match("Hello World", 0, data));
+ EXPECT_FALSE(__kmp_str_match("Hello", 0, data)); // Not exact (data is longer)
+
+ // Test prefix match (len < 0)
+ EXPECT_TRUE(
+ __kmp_str_match("Hello", -1, data)); // "Hello" is prefix of "Hello World"
+ EXPECT_FALSE(__kmp_str_match("World", -1, data)); // "World" is not a prefix
+
+ // Test minimum length match (len > 0)
+ EXPECT_TRUE(__kmp_str_match("Hello", 5, data)); // At least 5 chars match
+ EXPECT_TRUE(__kmp_str_match("Hello", 3, data)); // At least 3 chars match
+ EXPECT_FALSE(__kmp_str_match("World", 5, data)); // First chars don't match
+}
+
+// Test string contains
+TEST(KmpStrTest, StrContains) {
+ const char *data = "Hello World";
+
+ EXPECT_TRUE(__kmp_str_contains("Hello", 5, data));
+ EXPECT_TRUE(__kmp_str_contains("World", 5, data));
+ EXPECT_TRUE(__kmp_str_contains("lo Wo", 5, data));
+ EXPECT_FALSE(__kmp_str_contains("Goodbye", 7, data));
+}
+
+// Test string match for true/false values
+TEST(KmpStrTest, MatchBool) {
+ // Test true values
+ EXPECT_TRUE(__kmp_str_match_true("true"));
+ EXPECT_TRUE(__kmp_str_match_true("TRUE"));
+ EXPECT_TRUE(__kmp_str_match_true("on"));
+ EXPECT_TRUE(__kmp_str_match_true("ON"));
+ EXPECT_TRUE(__kmp_str_match_true("1"));
+ EXPECT_TRUE(__kmp_str_match_true("yes"));
+ EXPECT_TRUE(__kmp_str_match_true("YES"));
+
+ // Test false values
+ EXPECT_TRUE(__kmp_str_match_false("false"));
+ EXPECT_TRUE(__kmp_str_match_false("FALSE"));
+ EXPECT_TRUE(__kmp_str_match_false("off"));
+ EXPECT_TRUE(__kmp_str_match_false("OFF"));
+ EXPECT_TRUE(__kmp_str_match_false("0"));
+ EXPECT_TRUE(__kmp_str_match_false("no"));
+ EXPECT_TRUE(__kmp_str_match_false("NO"));
+}
+
+// Test string replace
+TEST(KmpStrTest, StrReplace) {
+ char str[] = "Hello World";
+ __kmp_str_replace(str, ' ', '_');
+ EXPECT_STREQ(str, "Hello_World");
+
+ __kmp_str_replace(str, 'o', '0');
+ EXPECT_STREQ(str, "Hell0_W0rld");
+}
+
+// Test string split
+TEST(KmpStrTest, StrSplit) {
+ char str[] = "key=value";
+ char *head = nullptr;
+ char *tail = nullptr;
+
+ __kmp_str_split(str, '=', &head, &tail);
+
+ EXPECT_STREQ(head, "key");
+ EXPECT_STREQ(tail, "value");
+}
+
+// Test file name parsing
+TEST(KmpStrTest, FileNameInit) {
+ const char *path = "/path/to/file.txt";
+ kmp_str_fname_t fname;
+ __kmp_str_fname_init(&fname, path);
+
+ EXPECT_NE(fname.path, nullptr);
+ EXPECT_STREQ(fname.path, path);
+ EXPECT_NE(fname.base, nullptr);
+ EXPECT_STREQ(fname.base, "file.txt");
+
+ __kmp_str_fname_free(&fname);
+}
+
+// Test string format
+TEST(KmpStrTest, StrFormat) {
+ char *result = __kmp_str_format("Number: %d, String: %s", 42, "test");
+
+ EXPECT_NE(result, nullptr);
+ EXPECT_STREQ(result, "Number: 42, String: test");
+
+ __kmp_str_free(&result);
+ EXPECT_EQ(result, nullptr);
+}
+
+// Test string buffer concatenate buffers
+TEST(KmpStrTest, BufferCatBuf) {
+ kmp_str_buf_t buf1, buf2;
+ __kmp_str_buf_init(&buf1);
+ __kmp_str_buf_init(&buf2);
+
+ __kmp_str_buf_print(&buf1, "Hello");
+ __kmp_str_buf_print(&buf2, " World");
+
+ __kmp_str_buf_catbuf(&buf1, &buf2);
+
+ EXPECT_STREQ(buf1.str, "Hello World");
+
+ __kmp_str_buf_free(&buf1);
+ __kmp_str_buf_free(&buf2);
+}
+
+// Test size string parsing
+TEST(KmpStrTest, StrToSize) {
+ size_t result;
+ const char *error = nullptr;
+
+ __kmp_str_to_size("100", &result, 1, &error);
+ EXPECT_EQ(error, nullptr);
+ EXPECT_EQ(result, 100u);
+
+ __kmp_str_to_size("1K", &result, 1024, &error);
+ EXPECT_EQ(error, nullptr);
+ EXPECT_EQ(result, 1024u);
+
+ __kmp_str_to_size("2M", &result, 1024, &error);
+ EXPECT_EQ(error, nullptr);
+ EXPECT_EQ(result, 2u * 1024u * 1024u);
+}
+
+// Test uint string parsing
+TEST(KmpStrTest, StrToUint) {
+ kmp_uint64 result;
+ const char *error = nullptr;
+
+ __kmp_str_to_uint("0", &result, &error);
+ EXPECT_EQ(error, nullptr);
+ EXPECT_EQ(result, 0u);
+
+ __kmp_str_to_uint("42", &result, &error);
+ EXPECT_EQ(error, nullptr);
+ EXPECT_EQ(result, 42u);
+
+ __kmp_str_to_uint("1234567890", &result, &error);
+ EXPECT_EQ(error, nullptr);
+ EXPECT_EQ(result, 1234567890u);
+}
+
+} // namespace
>From 4d12f2482d4cc58ffd100f2e3484cde7321ceaa9 Mon Sep 17 00:00:00 2001
From: Robert Imschweiler <robert.imschweiler at amd.com>
Date: Mon, 17 Nov 2025 04:25:01 -0600
Subject: [PATCH 02/12] dynamic linking for unit tests
---
openmp/runtime/src/CMakeLists.txt | 35 ++++++++++++++++++++++---
openmp/runtime/unittests/CMakeLists.txt | 17 +++++++-----
openmp/runtime/unittests/README.md | 4 ++-
3 files changed, 44 insertions(+), 12 deletions(-)
diff --git a/openmp/runtime/src/CMakeLists.txt b/openmp/runtime/src/CMakeLists.txt
index 7440f1fd05f9c..7ee648f54de05 100644
--- a/openmp/runtime/src/CMakeLists.txt
+++ b/openmp/runtime/src/CMakeLists.txt
@@ -176,17 +176,19 @@ endif()
# Add the OpenMP library
# First, create an OBJECT library with all the runtime sources.
-# This allows both the main library and unit tests to link against the same compiled objects.
+# This allows both the main library and unit tests to link against the same
+# compiled objects.
add_library(omp_objects OBJECT ${LIBOMP_SOURCE_FILES})
set_property(TARGET omp_objects PROPERTY FOLDER "OpenMP/Libraries")
set_property(TARGET omp_objects PROPERTY POSITION_INDEPENDENT_CODE ON)
-# Export the omp_objects target so unittests can use it
+# Export the omp_objects target so unit tests can use it
set(LIBOMP_OBJECTS_TARGET omp_objects PARENT_SCOPE)
libomp_get_ldflags(LIBOMP_CONFIGURED_LDFLAGS)
-
libomp_get_libflags(LIBOMP_CONFIGURED_LIBFLAGS)
-# Build libomp library. Add LLVMSupport dependency if building in-tree with libomptarget profiling enabled.
+
+# Build libomp library. Add LLVMSupport dependency if building in-tree with
+# libomptarget profiling enabled.
if(OPENMP_STANDALONE_BUILD OR (NOT OPENMP_ENABLE_LIBOMP_PROFILING))
add_library(omp ${LIBOMP_LIBRARY_KIND} $<TARGET_OBJECTS:omp_objects>)
set_property(TARGET omp PROPERTY FOLDER "OpenMP/Libraries")
@@ -209,6 +211,31 @@ if(${LIBOMP_USE_HWLOC})
)
endif()
+# Build a testing version of libomp that exports all symbols for unit tests.
+# This library uses the same compiled objects as libomp, but with all symbols
+# exported to allow testing internal functions.
+if(NOT WIN32 AND NOT STUBS_LIBRARY)
+ set(LIBOMP_TEST_LDFLAGS ${LIBOMP_CONFIGURED_LDFLAGS})
+ # Replace the libomp exports with the test exports exporting all symbols.
+ if(LIBOMP_HAVE_VERSION_SCRIPT_FLAG)
+ string(REPLACE "${LIBOMP_SRC_DIR}/exports_so.txt"
+ "${LIBOMP_SRC_DIR}/exports_test_so.txt"
+ LIBOMP_TEST_LDFLAGS "${LIBOMP_TEST_LDFLAGS}")
+ endif()
+
+ # Create the testing library from the same objects as libomp.
+ add_library(omp_testing SHARED $<TARGET_OBJECTS:omp_objects>)
+ set_property(TARGET omp_testing PROPERTY FOLDER "OpenMP/Libraries")
+ target_link_libraries(omp_testing ${LIBOMP_CONFIGURED_LIBFLAGS} ${LIBOMP_DL_LIBS})
+ set_target_properties(omp_testing PROPERTIES
+ PREFIX "" SUFFIX "" OUTPUT_NAME "libomp_testing${LIBOMP_LIBRARY_SUFFIX}"
+ LINK_FLAGS "${LIBOMP_TEST_LDFLAGS}"
+ LINKER_LANGUAGE ${LIBOMP_LINKER_LANGUAGE}
+ EXCLUDE_FROM_ALL TRUE # Don't build by default, only when tests need it
+ )
+ add_dependencies(omp_testing libomp-needed-headers)
+endif()
+
if(OPENMP_MSVC_NAME_SCHEME)
if(uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG")
set(LIBOMP_PDB_NAME ${LIBOMP_DEFAULT_LIB_NAME}${MSVC_TOOLS_VERSION}d.${LIBOMP_ARCH})
diff --git a/openmp/runtime/unittests/CMakeLists.txt b/openmp/runtime/unittests/CMakeLists.txt
index 14ddbfc827cbb..e44fda78fb804 100644
--- a/openmp/runtime/unittests/CMakeLists.txt
+++ b/openmp/runtime/unittests/CMakeLists.txt
@@ -1,19 +1,22 @@
add_custom_target(OpenMPUnitTests)
set_target_properties(OpenMPUnitTests PROPERTIES FOLDER "OpenMP/Tests")
-if (NOT TARGET llvm_gtest)
+if(NOT TARGET llvm_gtest)
message(WARNING "OpenMP unittests disabled due to GTest being unavailable; "
"Try LLVM_INSTALL_GTEST=ON for the LLVM build")
- return ()
-endif ()
+ return()
+endif()
+if(NOT TARGET omp_testing)
+ message(WARNING "OpenMP unittests disabled due to omp_testing library being unavailable")
+ return()
+endif()
function(add_openmp_unittest test_dirname)
add_unittest(OpenMPUnitTests ${test_dirname} ${ARGN})
- # Link against the object library created in runtime/src
- target_link_libraries(${test_dirname} PRIVATE
- $<TARGET_OBJECTS:omp_objects>
- )
+ # Link against the testing library which exports all symbols.
+ target_link_libraries(${test_dirname} PRIVATE omp_testing)
+ add_dependencies(${test_dirname} omp_testing)
target_include_directories(${test_dirname} PRIVATE
${LIBOMP_INCLUDE_DIR}
diff --git a/openmp/runtime/unittests/README.md b/openmp/runtime/unittests/README.md
index ad7dd9d716ceb..974f877654776 100644
--- a/openmp/runtime/unittests/README.md
+++ b/openmp/runtime/unittests/README.md
@@ -4,4 +4,6 @@ Usage:
```
cd <your-llvm-build-directory>/runtimes/runtimes-bins
ninja check-libomp-unit
-```
\ No newline at end of file
+```
+
+Note: unit tests are currently not supported on Windows
>From c63c254f2d65e7a9a7b2e5c09f40033d96a64b68 Mon Sep 17 00:00:00 2001
From: Robert Imschweiler <robert.imschweiler at amd.com>
Date: Tue, 18 Nov 2025 09:04:23 -0600
Subject: [PATCH 03/12] fix omp_objects dependency
---
openmp/runtime/src/CMakeLists.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/openmp/runtime/src/CMakeLists.txt b/openmp/runtime/src/CMakeLists.txt
index 7ee648f54de05..638f6c2ca61bd 100644
--- a/openmp/runtime/src/CMakeLists.txt
+++ b/openmp/runtime/src/CMakeLists.txt
@@ -332,6 +332,7 @@ set(LIBOMPTARGET_OPENMP_HOST_RTL_FOLDER "${LIBOMP_LIBRARY_DIR}" CACHE STRING
# objects depend on : .inc files
add_custom_target(libomp-needed-headers DEPENDS kmp_i18n_id.inc kmp_i18n_default.inc)
set_target_properties(libomp-needed-headers PROPERTIES FOLDER "OpenMP/Sourcegenning")
+add_dependencies(omp_objects libomp-needed-headers)
add_dependencies(omp libomp-needed-headers)
# Windows specific build rules
>From 4cd6cbe3d3bea05d7d0c50572188af6ce91e7fb0 Mon Sep 17 00:00:00 2001
From: Robert Imschweiler <robert.imschweiler at amd.com>
Date: Tue, 18 Nov 2025 14:09:49 -0600
Subject: [PATCH 04/12] rename add_openmp_unittest argument
---
openmp/runtime/unittests/CMakeLists.txt | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/openmp/runtime/unittests/CMakeLists.txt b/openmp/runtime/unittests/CMakeLists.txt
index e44fda78fb804..b161846708d70 100644
--- a/openmp/runtime/unittests/CMakeLists.txt
+++ b/openmp/runtime/unittests/CMakeLists.txt
@@ -11,14 +11,14 @@ if(NOT TARGET omp_testing)
return()
endif()
-function(add_openmp_unittest test_dirname)
- add_unittest(OpenMPUnitTests ${test_dirname} ${ARGN})
+function(add_openmp_unittest test_filename)
+ add_unittest(OpenMPUnitTests ${test_filename} ${ARGN})
# Link against the testing library which exports all symbols.
- target_link_libraries(${test_dirname} PRIVATE omp_testing)
- add_dependencies(${test_dirname} omp_testing)
+ target_link_libraries(${test_filename} PRIVATE omp_testing)
+ add_dependencies(${test_filename} omp_testing)
- target_include_directories(${test_dirname} PRIVATE
+ target_include_directories(${test_filename} PRIVATE
${LIBOMP_INCLUDE_DIR}
${LIBOMP_SRC_DIR}
)
>From 16ad02ee78df600de7841eadae56fa4ca185cb8f Mon Sep 17 00:00:00 2001
From: Robert Imschweiler <robert.imschweiler at amd.com>
Date: Wed, 3 Dec 2025 15:15:20 -0600
Subject: [PATCH 05/12] implement feedback
---
openmp/runtime/src/CMakeLists.txt | 44 +++---------
.../{unittests => test/Unit}/lit.cfg.py | 2 +-
openmp/runtime/test/Unit/lit.site.cfg.py.in | 8 +++
openmp/runtime/unittests/CMakeLists.txt | 70 ++++++++++++++-----
.../runtime/unittests/String/CMakeLists.txt | 3 +
.../unittests/{src => String}/TestKmpStr.cpp | 0
openmp/runtime/unittests/lit.site.cfg.py.in | 9 ---
openmp/runtime/unittests/src/CMakeLists.txt | 3 -
8 files changed, 72 insertions(+), 67 deletions(-)
rename openmp/runtime/{unittests => test/Unit}/lit.cfg.py (97%)
create mode 100644 openmp/runtime/test/Unit/lit.site.cfg.py.in
create mode 100644 openmp/runtime/unittests/String/CMakeLists.txt
rename openmp/runtime/unittests/{src => String}/TestKmpStr.cpp (100%)
delete mode 100644 openmp/runtime/unittests/lit.site.cfg.py.in
delete mode 100644 openmp/runtime/unittests/src/CMakeLists.txt
diff --git a/openmp/runtime/src/CMakeLists.txt b/openmp/runtime/src/CMakeLists.txt
index 638f6c2ca61bd..10065f2f21fc5 100644
--- a/openmp/runtime/src/CMakeLists.txt
+++ b/openmp/runtime/src/CMakeLists.txt
@@ -176,13 +176,11 @@ endif()
# Add the OpenMP library
# First, create an OBJECT library with all the runtime sources.
-# This allows both the main library and unit tests to link against the same
-# compiled objects.
-add_library(omp_objects OBJECT ${LIBOMP_SOURCE_FILES})
-set_property(TARGET omp_objects PROPERTY FOLDER "OpenMP/Libraries")
-set_property(TARGET omp_objects PROPERTY POSITION_INDEPENDENT_CODE ON)
-# Export the omp_objects target so unit tests can use it
-set(LIBOMP_OBJECTS_TARGET omp_objects PARENT_SCOPE)
+# This allows the unittests later to access internal symbols which don't export
+# in libomp.
+add_library(obj.omp OBJECT ${LIBOMP_SOURCE_FILES})
+set_property(TARGET obj.omp PROPERTY FOLDER "OpenMP/Libraries")
+set_property(TARGET obj.omp PROPERTY POSITION_INDEPENDENT_CODE ON)
libomp_get_ldflags(LIBOMP_CONFIGURED_LDFLAGS)
libomp_get_libflags(LIBOMP_CONFIGURED_LIBFLAGS)
@@ -190,12 +188,12 @@ libomp_get_libflags(LIBOMP_CONFIGURED_LIBFLAGS)
# Build libomp library. Add LLVMSupport dependency if building in-tree with
# libomptarget profiling enabled.
if(OPENMP_STANDALONE_BUILD OR (NOT OPENMP_ENABLE_LIBOMP_PROFILING))
- add_library(omp ${LIBOMP_LIBRARY_KIND} $<TARGET_OBJECTS:omp_objects>)
+ add_library(omp ${LIBOMP_LIBRARY_KIND} $<TARGET_OBJECTS:obj.omp>)
set_property(TARGET omp PROPERTY FOLDER "OpenMP/Libraries")
# Linking command will include libraries in LIBOMP_CONFIGURED_LIBFLAGS
target_link_libraries(omp ${LIBOMP_CONFIGURED_LIBFLAGS} ${LIBOMP_DL_LIBS})
else()
- add_llvm_library(omp ${LIBOMP_LIBRARY_KIND} $<TARGET_OBJECTS:omp_objects> PARTIAL_SOURCES_INTENDED
+ add_llvm_library(omp ${LIBOMP_LIBRARY_KIND} $<TARGET_OBJECTS:obj.omp> PARTIAL_SOURCES_INTENDED
LINK_LIBS ${LIBOMP_CONFIGURED_LIBFLAGS} ${LIBOMP_DL_LIBS}
LINK_COMPONENTS Support
BUILDTREE_ONLY
@@ -211,31 +209,6 @@ if(${LIBOMP_USE_HWLOC})
)
endif()
-# Build a testing version of libomp that exports all symbols for unit tests.
-# This library uses the same compiled objects as libomp, but with all symbols
-# exported to allow testing internal functions.
-if(NOT WIN32 AND NOT STUBS_LIBRARY)
- set(LIBOMP_TEST_LDFLAGS ${LIBOMP_CONFIGURED_LDFLAGS})
- # Replace the libomp exports with the test exports exporting all symbols.
- if(LIBOMP_HAVE_VERSION_SCRIPT_FLAG)
- string(REPLACE "${LIBOMP_SRC_DIR}/exports_so.txt"
- "${LIBOMP_SRC_DIR}/exports_test_so.txt"
- LIBOMP_TEST_LDFLAGS "${LIBOMP_TEST_LDFLAGS}")
- endif()
-
- # Create the testing library from the same objects as libomp.
- add_library(omp_testing SHARED $<TARGET_OBJECTS:omp_objects>)
- set_property(TARGET omp_testing PROPERTY FOLDER "OpenMP/Libraries")
- target_link_libraries(omp_testing ${LIBOMP_CONFIGURED_LIBFLAGS} ${LIBOMP_DL_LIBS})
- set_target_properties(omp_testing PROPERTIES
- PREFIX "" SUFFIX "" OUTPUT_NAME "libomp_testing${LIBOMP_LIBRARY_SUFFIX}"
- LINK_FLAGS "${LIBOMP_TEST_LDFLAGS}"
- LINKER_LANGUAGE ${LIBOMP_LINKER_LANGUAGE}
- EXCLUDE_FROM_ALL TRUE # Don't build by default, only when tests need it
- )
- add_dependencies(omp_testing libomp-needed-headers)
-endif()
-
if(OPENMP_MSVC_NAME_SCHEME)
if(uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG")
set(LIBOMP_PDB_NAME ${LIBOMP_DEFAULT_LIB_NAME}${MSVC_TOOLS_VERSION}d.${LIBOMP_ARCH})
@@ -332,8 +305,7 @@ set(LIBOMPTARGET_OPENMP_HOST_RTL_FOLDER "${LIBOMP_LIBRARY_DIR}" CACHE STRING
# objects depend on : .inc files
add_custom_target(libomp-needed-headers DEPENDS kmp_i18n_id.inc kmp_i18n_default.inc)
set_target_properties(libomp-needed-headers PROPERTIES FOLDER "OpenMP/Sourcegenning")
-add_dependencies(omp_objects libomp-needed-headers)
-add_dependencies(omp libomp-needed-headers)
+add_dependencies(obj.omp libomp-needed-headers)
# Windows specific build rules
if(WIN32)
diff --git a/openmp/runtime/unittests/lit.cfg.py b/openmp/runtime/test/Unit/lit.cfg.py
similarity index 97%
rename from openmp/runtime/unittests/lit.cfg.py
rename to openmp/runtime/test/Unit/lit.cfg.py
index 552ea8ef9854d..01bd3d961bf00 100644
--- a/openmp/runtime/unittests/lit.cfg.py
+++ b/openmp/runtime/test/Unit/lit.cfg.py
@@ -19,4 +19,4 @@
config.test_source_root = config.test_exec_root
# testFormat: The test format to use to interpret tests.
-config.test_format = lit.formats.GoogleTest(config.llvm_build_mode, ".unittests")
+config.test_format = lit.formats.GoogleTest(config.llvm_build_mode, "Tests")
diff --git a/openmp/runtime/test/Unit/lit.site.cfg.py.in b/openmp/runtime/test/Unit/lit.site.cfg.py.in
new file mode 100644
index 0000000000000..dd5c075b5f112
--- /dev/null
+++ b/openmp/runtime/test/Unit/lit.site.cfg.py.in
@@ -0,0 +1,8 @@
+ at AUTO_GEN_COMMENT@
+
+config.openmp_unittests_dir = "@CMAKE_CURRENT_BINARY_DIR@/../unittests"
+config.llvm_build_mode = lit_config.substitute("@LLVM_BUILD_MODE@")
+
+# Let the main config do the real work.
+lit_config.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/../test/Unit/lit.cfg.py")
+
diff --git a/openmp/runtime/unittests/CMakeLists.txt b/openmp/runtime/unittests/CMakeLists.txt
index b161846708d70..3c56512bcf120 100644
--- a/openmp/runtime/unittests/CMakeLists.txt
+++ b/openmp/runtime/unittests/CMakeLists.txt
@@ -1,34 +1,68 @@
add_custom_target(OpenMPUnitTests)
set_target_properties(OpenMPUnitTests PROPERTIES FOLDER "OpenMP/Tests")
-if(NOT TARGET llvm_gtest)
- message(WARNING "OpenMP unittests disabled due to GTest being unavailable; "
- "Try LLVM_INSTALL_GTEST=ON for the LLVM build")
+if(WIN32 OR STUBS_LIBRARY)
+ message(WARNING "OpenMP unittests disabled due to stub library or Windows")
return()
endif()
-if(NOT TARGET omp_testing)
- message(WARNING "OpenMP unittests disabled due to omp_testing library being unavailable")
- return()
+
+# Build a testing version of libomp that exports all symbols for unit tests.
+# This library uses the same compiled objects as libomp, but with all symbols
+# exported to allow testing internal functions.
+
+libomp_get_ldflags(LIBOMP_TEST_LDFLAGS)
+libomp_get_libflags(LIBOMP_TEST_LIBFLAGS)
+# Replace the libomp exports with the test exports exporting all symbols.
+if(LIBOMP_HAVE_VERSION_SCRIPT_FLAG)
+ string(REPLACE "${LIBOMP_SRC_DIR}/exports_so.txt"
+ "${LIBOMP_SRC_DIR}/exports_test_so.txt"
+ LIBOMP_TEST_LDFLAGS "${LIBOMP_TEST_LDFLAGS}")
+endif()
+# Duplicate setting of LIBOMP_LINKER_LANGUAGE to match libomp.
+if(NOT ${LIBOMP_USE_STDCPPLIB})
+ set(LIBOMP_LINKER_LANGUAGE C)
+ set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES)
+else()
+ set(LIBOMP_LINKER_LANGUAGE CXX)
endif()
-function(add_openmp_unittest test_filename)
- add_unittest(OpenMPUnitTests ${test_filename} ${ARGN})
+# Create the testing library from the same objects as libomp.
+add_library(omp_testing SHARED $<TARGET_OBJECTS:obj.omp>)
+set_property(TARGET omp_testing PROPERTY FOLDER "OpenMP/Libraries")
+target_link_libraries(omp_testing PUBLIC default_gtest)
+target_link_libraries(omp_testing PUBLIC ${LIBOMP_TEST_LIBFLAGS} ${LIBOMP_DL_LIBS})
+set_target_properties(omp_testing PROPERTIES
+ PREFIX "" SUFFIX "" OUTPUT_NAME "libomp_testing${LIBOMP_LIBRARY_SUFFIX}"
+ LINK_FLAGS "${LIBOMP_TEST_LDFLAGS}"
+ LINKER_LANGUAGE ${LIBOMP_LINKER_LANGUAGE}
+ EXCLUDE_FROM_ALL TRUE # Don't build by default, only when tests need it
+)
+target_include_directories(omp_testing PUBLIC
+ ${LIBOMP_INCLUDE_DIR}
+ ${LIBOMP_SRC_DIR}
+)
+
+# Make the targets default_gtest and default_gtest_main available.
+build_gtest()
+
+function(add_openmp_unittest test_name)
+ add_unittest(OpenMPUnitTests ${test_name} ${ARGN})
# Link against the testing library which exports all symbols.
- target_link_libraries(${test_filename} PRIVATE omp_testing)
- add_dependencies(${test_filename} omp_testing)
+ target_link_libraries(${test_name} PRIVATE omp_testing)
- target_include_directories(${test_filename} PRIVATE
- ${LIBOMP_INCLUDE_DIR}
- ${LIBOMP_SRC_DIR}
- )
+ if(TARGET default_gtest)
+ target_link_libraries(${test_name} PRIVATE default_gtest_main default_gtest)
+ else ()
+ target_link_libraries(${test_name} PRIVATE llvm_gtest_main llvm_gtest)
+ endif ()
endfunction()
configure_lit_site_cfg(
- ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in
+ ${CMAKE_CURRENT_SOURCE_DIR}/../test/Unit/lit.site.cfg.py.in
${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg.py
MAIN_CONFIG
- ${CMAKE_CURRENT_SOURCE_DIR}/lit.cfg.py
+ ${CMAKE_CURRENT_SOURCE_DIR}/../test/Unit/lit.cfg.py
)
add_openmp_testsuite(
@@ -36,7 +70,7 @@ add_openmp_testsuite(
"Running libomp unit tests"
${CMAKE_CURRENT_BINARY_DIR}
EXCLUDE_FROM_CHECK_ALL
- DEPENDS OpenMPUnitTests omp
+ DEPENDS OpenMPUnitTests
)
-add_subdirectory(src)
+add_subdirectory(String)
diff --git a/openmp/runtime/unittests/String/CMakeLists.txt b/openmp/runtime/unittests/String/CMakeLists.txt
new file mode 100644
index 0000000000000..be072c76a10a6
--- /dev/null
+++ b/openmp/runtime/unittests/String/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_openmp_unittest(StringTests
+ TestKmpStr.cpp
+)
diff --git a/openmp/runtime/unittests/src/TestKmpStr.cpp b/openmp/runtime/unittests/String/TestKmpStr.cpp
similarity index 100%
rename from openmp/runtime/unittests/src/TestKmpStr.cpp
rename to openmp/runtime/unittests/String/TestKmpStr.cpp
diff --git a/openmp/runtime/unittests/lit.site.cfg.py.in b/openmp/runtime/unittests/lit.site.cfg.py.in
deleted file mode 100644
index 878c95f1d8e29..0000000000000
--- a/openmp/runtime/unittests/lit.site.cfg.py.in
+++ /dev/null
@@ -1,9 +0,0 @@
- at AUTO_GEN_COMMENT@
-
-config.library_dir = "@LIBOMP_LIBRARY_DIR@"
-config.openmp_unittests_dir = "@CMAKE_CURRENT_BINARY_DIR@"
-config.llvm_build_mode = lit_config.substitute("@LLVM_BUILD_MODE@")
-
-# Let the main config do the real work.
-lit_config.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/lit.cfg.py")
-
diff --git a/openmp/runtime/unittests/src/CMakeLists.txt b/openmp/runtime/unittests/src/CMakeLists.txt
deleted file mode 100644
index 455fbf0b92fc5..0000000000000
--- a/openmp/runtime/unittests/src/CMakeLists.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-add_openmp_unittest(libomp.unittests
- TestKmpStr.cpp
-)
>From b12ff59f5c8a9c432adce1aa13ff38b6ce60b44b Mon Sep 17 00:00:00 2001
From: Robert Imschweiler <robert.imschweiler at amd.com>
Date: Tue, 16 Dec 2025 09:17:09 -0600
Subject: [PATCH 06/12] implement feedback
---
openmp/cmake/modules/LibompHandleFlags.cmake | 7 ++++++-
openmp/runtime/CMakeLists.txt | 13 +++++++++++++
openmp/runtime/src/CMakeLists.txt | 13 -------------
openmp/runtime/test/lit.cfg | 3 +++
openmp/runtime/unittests/CMakeLists.txt | 15 +--------------
5 files changed, 23 insertions(+), 28 deletions(-)
diff --git a/openmp/cmake/modules/LibompHandleFlags.cmake b/openmp/cmake/modules/LibompHandleFlags.cmake
index c36a88fb862ae..77ccb3ecaff34 100644
--- a/openmp/cmake/modules/LibompHandleFlags.cmake
+++ b/openmp/cmake/modules/LibompHandleFlags.cmake
@@ -97,6 +97,7 @@ endfunction()
# Linker flags
function(libomp_get_ldflags ldflags)
+ cmake_parse_arguments(ARG "FOR_UNITTESTS" "" "" ${ARGN})
set(ldflags_local)
libomp_append(ldflags_local "${CMAKE_LINK_DEF_FILE_FLAG}${CMAKE_CURRENT_BINARY_DIR}/${LIBOMP_LIB_NAME}.def"
IF_DEFINED CMAKE_LINK_DEF_FILE_FLAG)
@@ -105,7 +106,11 @@ function(libomp_get_ldflags ldflags)
libomp_append(ldflags_local "${CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG}${LIBOMP_VERSION_MAJOR}.${LIBOMP_VERSION_MINOR}"
IF_DEFINED CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG)
libomp_append(ldflags_local -Wl,--as-needed LIBOMP_HAVE_AS_NEEDED_FLAG)
- libomp_append(ldflags_local "-Wl,--version-script=${LIBOMP_SRC_DIR}/exports_so.txt" LIBOMP_HAVE_VERSION_SCRIPT_FLAG)
+ if(ARG_FOR_UNITTESTS)
+ libomp_append(ldflags_local "-Wl,--version-script=${LIBOMP_SRC_DIR}/exports_test_so.txt" LIBOMP_HAVE_VERSION_SCRIPT_FLAG)
+ else()
+ libomp_append(ldflags_local "-Wl,--version-script=${LIBOMP_SRC_DIR}/exports_so.txt" LIBOMP_HAVE_VERSION_SCRIPT_FLAG)
+ endif()
libomp_append(ldflags_local -static-libgcc LIBOMP_HAVE_STATIC_LIBGCC_FLAG)
libomp_append(ldflags_local -Wl,-z,noexecstack LIBOMP_HAVE_Z_NOEXECSTACK_FLAG)
libomp_append(ldflags_local -no-intel-extensions LIBOMP_HAVE_NO_INTEL_EXTENSIONS_FLAG)
diff --git a/openmp/runtime/CMakeLists.txt b/openmp/runtime/CMakeLists.txt
index 33276b7d97d3a..016f8ae10e648 100644
--- a/openmp/runtime/CMakeLists.txt
+++ b/openmp/runtime/CMakeLists.txt
@@ -118,6 +118,19 @@ if(NOT DEFINED CMAKE_MACOSX_RPATH)
set(CMAKE_MACOSX_RPATH TRUE)
endif()
+# Remove any cmake-automatic linking of the standard C++ library.
+# We neither need (nor want) the standard C++ library dependency even though we compile c++ files.
+if(NOT ${LIBOMP_USE_STDCPPLIB})
+ set(LIBOMP_LINKER_LANGUAGE C)
+ set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES)
+else()
+ set(LIBOMP_LINKER_LANGUAGE CXX)
+endif()
+
+if(UNIX)
+ set(LIBOMP_DL_LIBS ${CMAKE_DL_LIBS})
+endif()
+
# User specified flags. These are appended to the configured flags.
set(LIBOMP_CXXFLAGS "" CACHE STRING
"Appended user specified C++ compiler flags.")
diff --git a/openmp/runtime/src/CMakeLists.txt b/openmp/runtime/src/CMakeLists.txt
index 10065f2f21fc5..53f83c006b04f 100644
--- a/openmp/runtime/src/CMakeLists.txt
+++ b/openmp/runtime/src/CMakeLists.txt
@@ -153,19 +153,6 @@ libomp_get_asmflags(LIBOMP_CONFIGURED_ASMFLAGS)
set_source_files_properties(${LIBOMP_CXXFILES} PROPERTIES COMPILE_FLAGS "${LIBOMP_CONFIGURED_CXXFLAGS}")
set_source_files_properties(${LIBOMP_ASMFILES} ${LIBOMP_GNUASMFILES} PROPERTIES COMPILE_FLAGS "${LIBOMP_CONFIGURED_ASMFLAGS}")
-# Remove any cmake-automatic linking of the standard C++ library.
-# We neither need (nor want) the standard C++ library dependency even though we compile c++ files.
-if(NOT ${LIBOMP_USE_STDCPPLIB})
- set(LIBOMP_LINKER_LANGUAGE C)
- set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES)
-else()
- set(LIBOMP_LINKER_LANGUAGE CXX)
-endif()
-
-if(UNIX)
- set(LIBOMP_DL_LIBS ${CMAKE_DL_LIBS})
-endif()
-
# Disable libstdc++ assertions, even in an LLVM_ENABLE_ASSERTIONS build, to
# avoid an unwanted dependency on libstdc++.so.
add_compile_definitions(_GLIBCXX_NO_ASSERTIONS)
diff --git a/openmp/runtime/test/lit.cfg b/openmp/runtime/test/lit.cfg
index 72da1ba1411f8..f35794f09f641 100644
--- a/openmp/runtime/test/lit.cfg
+++ b/openmp/runtime/test/lit.cfg
@@ -41,6 +41,9 @@ config.name = 'libomp'
# suffixes: A list of file extensions to treat as test files.
config.suffixes = ['.c', '.cpp']
+# Exclude Unit tests - they are run separately via check-libomp-unit
+config.excludes = ['Unit']
+
if config.test_fortran_compiler:
lit_config.note("OpenMP Fortran tests enabled")
config.suffixes += ['.f90', '.F90']
diff --git a/openmp/runtime/unittests/CMakeLists.txt b/openmp/runtime/unittests/CMakeLists.txt
index 3c56512bcf120..10ffef9e566c8 100644
--- a/openmp/runtime/unittests/CMakeLists.txt
+++ b/openmp/runtime/unittests/CMakeLists.txt
@@ -10,21 +10,8 @@ endif()
# This library uses the same compiled objects as libomp, but with all symbols
# exported to allow testing internal functions.
-libomp_get_ldflags(LIBOMP_TEST_LDFLAGS)
+libomp_get_ldflags(LIBOMP_TEST_LDFLAGS FOR_UNITTESTS)
libomp_get_libflags(LIBOMP_TEST_LIBFLAGS)
-# Replace the libomp exports with the test exports exporting all symbols.
-if(LIBOMP_HAVE_VERSION_SCRIPT_FLAG)
- string(REPLACE "${LIBOMP_SRC_DIR}/exports_so.txt"
- "${LIBOMP_SRC_DIR}/exports_test_so.txt"
- LIBOMP_TEST_LDFLAGS "${LIBOMP_TEST_LDFLAGS}")
-endif()
-# Duplicate setting of LIBOMP_LINKER_LANGUAGE to match libomp.
-if(NOT ${LIBOMP_USE_STDCPPLIB})
- set(LIBOMP_LINKER_LANGUAGE C)
- set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES)
-else()
- set(LIBOMP_LINKER_LANGUAGE CXX)
-endif()
# Create the testing library from the same objects as libomp.
add_library(omp_testing SHARED $<TARGET_OBJECTS:obj.omp>)
>From 197b195b30fc90a7dcd783e67023815680eb330b Mon Sep 17 00:00:00 2001
From: Robert Imschweiler <robert.imschweiler at amd.com>
Date: Wed, 17 Dec 2025 08:53:27 +0100
Subject: [PATCH 07/12] Update openmp/runtime/CMakeLists.txt
Co-authored-by: Shilei Tian <i at tianshilei.me>
---
openmp/runtime/CMakeLists.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/openmp/runtime/CMakeLists.txt b/openmp/runtime/CMakeLists.txt
index 016f8ae10e648..b12d1ea0ee90d 100644
--- a/openmp/runtime/CMakeLists.txt
+++ b/openmp/runtime/CMakeLists.txt
@@ -119,7 +119,7 @@ if(NOT DEFINED CMAKE_MACOSX_RPATH)
endif()
# Remove any cmake-automatic linking of the standard C++ library.
-# We neither need (nor want) the standard C++ library dependency even though we compile c++ files.
+# We neither need (nor want) the standard C++ library dependency even though we compile C++ files.
if(NOT ${LIBOMP_USE_STDCPPLIB})
set(LIBOMP_LINKER_LANGUAGE C)
set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES)
>From 5eb66f4961dbba68a24bb9326eb1605e6e3531c1 Mon Sep 17 00:00:00 2001
From: Robert Imschweiler <robert.imschweiler at amd.com>
Date: Wed, 17 Dec 2025 07:30:22 -0600
Subject: [PATCH 08/12] enhance TestKmpStr.cpp
---
.../runtime/unittests/String/TestKmpStr.cpp | 92 +++++++++++++++++++
1 file changed, 92 insertions(+)
diff --git a/openmp/runtime/unittests/String/TestKmpStr.cpp b/openmp/runtime/unittests/String/TestKmpStr.cpp
index a22a729da9272..87497b93c7538 100644
--- a/openmp/runtime/unittests/String/TestKmpStr.cpp
+++ b/openmp/runtime/unittests/String/TestKmpStr.cpp
@@ -86,6 +86,31 @@ TEST(KmpStrTest, BasicStrToInt) {
EXPECT_EQ(__kmp_basic_str_to_int("123"), 123);
}
+// Test basic string to int conversion with invalid inputs
+TEST(KmpStrTest, BasicStrToIntInvalid) {
+ // Empty string returns 0
+ EXPECT_EQ(__kmp_basic_str_to_int(""), 0);
+
+ // Strings starting with non-digits return 0
+ EXPECT_EQ(__kmp_basic_str_to_int("abc"), 0);
+ EXPECT_EQ(__kmp_basic_str_to_int("hello"), 0);
+ EXPECT_EQ(__kmp_basic_str_to_int("xyz123"), 0);
+
+ // Special characters return 0
+ EXPECT_EQ(__kmp_basic_str_to_int("!@#"), 0);
+ EXPECT_EQ(__kmp_basic_str_to_int("+42"), 0);
+ EXPECT_EQ(__kmp_basic_str_to_int("-42"), 0);
+
+ // Leading whitespace causes early stop (returns 0)
+ EXPECT_EQ(__kmp_basic_str_to_int(" 42"), 0);
+ EXPECT_EQ(__kmp_basic_str_to_int("\t42"), 0);
+
+ // Mixed content: parses digits until first non-digit
+ EXPECT_EQ(__kmp_basic_str_to_int("123abc"), 123);
+ EXPECT_EQ(__kmp_basic_str_to_int("42 "), 42);
+ EXPECT_EQ(__kmp_basic_str_to_int("7.5"), 7);
+}
+
// Test string match
TEST(KmpStrTest, StrMatch) {
const char *data = "Hello World";
@@ -134,6 +159,73 @@ TEST(KmpStrTest, MatchBool) {
EXPECT_TRUE(__kmp_str_match_false("0"));
EXPECT_TRUE(__kmp_str_match_false("no"));
EXPECT_TRUE(__kmp_str_match_false("NO"));
+
+ // Note: Trailing characters after a valid prefix still match due to
+ // minimum-length prefix matching (e.g., "true" uses len=1, "yes" uses len=1)
+ EXPECT_TRUE(__kmp_str_match_true("true "));
+ EXPECT_TRUE(__kmp_str_match_false("false "));
+ EXPECT_TRUE(__kmp_str_match_true("truex"));
+ EXPECT_TRUE(__kmp_str_match_false("falsex"));
+
+ // Partial prefixes also match due to minimum-length matching
+ EXPECT_TRUE(__kmp_str_match_true("t"));
+ EXPECT_TRUE(__kmp_str_match_true("tru"));
+ EXPECT_TRUE(__kmp_str_match_false("f"));
+ EXPECT_TRUE(__kmp_str_match_false("fals"));
+ EXPECT_TRUE(__kmp_str_match_true("y"));
+ EXPECT_TRUE(__kmp_str_match_true("yess"));
+ EXPECT_TRUE(__kmp_str_match_false("n"));
+ EXPECT_TRUE(__kmp_str_match_false("noo"));
+
+ // "on" and "off" require at least 2 characters
+ EXPECT_TRUE(__kmp_str_match_true("on"));
+ EXPECT_TRUE(__kmp_str_match_false("of"));
+ EXPECT_TRUE(__kmp_str_match_false("off"));
+
+ // "enabled" and "disabled" require exact match (len=0)
+ EXPECT_TRUE(__kmp_str_match_true("enabled"));
+ EXPECT_TRUE(__kmp_str_match_false("disabled"));
+}
+
+// Test string match for invalid bool values
+TEST(KmpStrTest, MatchBoolInvalid) {
+ // Empty string is neither true nor false
+ EXPECT_FALSE(__kmp_str_match_true(""));
+ EXPECT_FALSE(__kmp_str_match_false(""));
+
+ // Random strings are neither true nor false
+ EXPECT_FALSE(__kmp_str_match_true("hello"));
+ EXPECT_FALSE(__kmp_str_match_false("hello"));
+ EXPECT_FALSE(__kmp_str_match_true("abc"));
+ EXPECT_FALSE(__kmp_str_match_false("abc"));
+
+ // Numbers other than 0/1 are neither true nor false
+ EXPECT_FALSE(__kmp_str_match_true("2"));
+ EXPECT_FALSE(__kmp_str_match_false("2"));
+ EXPECT_FALSE(__kmp_str_match_true("42"));
+ EXPECT_FALSE(__kmp_str_match_false("42"));
+ EXPECT_FALSE(__kmp_str_match_true("-1"));
+ EXPECT_FALSE(__kmp_str_match_false("-1"));
+
+ // Leading whitespace prevents matching
+ EXPECT_FALSE(__kmp_str_match_true(" true"));
+ EXPECT_FALSE(__kmp_str_match_false(" false"));
+
+ // "on" and "off" require at least 2 characters
+ EXPECT_FALSE(__kmp_str_match_true("o"));
+ EXPECT_FALSE(__kmp_str_match_false("o"));
+
+ // "enabled" and "disabled" require exact match (len=0)
+ EXPECT_FALSE(__kmp_str_match_true("enable"));
+ EXPECT_FALSE(__kmp_str_match_false("disable"));
+
+ // True values don't match as false and vice versa
+ EXPECT_FALSE(__kmp_str_match_false("true"));
+ EXPECT_FALSE(__kmp_str_match_false("1"));
+ EXPECT_FALSE(__kmp_str_match_false("yes"));
+ EXPECT_FALSE(__kmp_str_match_true("false"));
+ EXPECT_FALSE(__kmp_str_match_true("0"));
+ EXPECT_FALSE(__kmp_str_match_true("no"));
}
// Test string replace
>From 03ddc0ce946e17efa9a3be124beba8226838d37f Mon Sep 17 00:00:00 2001
From: Robert Imschweiler <robert.imschweiler at amd.com>
Date: Wed, 17 Dec 2025 10:25:33 -0600
Subject: [PATCH 09/12] implement feedback
---
openmp/runtime/CMakeLists.txt | 2 +-
openmp/runtime/unittests/CMakeLists.txt | 4 +++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/openmp/runtime/CMakeLists.txt b/openmp/runtime/CMakeLists.txt
index b12d1ea0ee90d..9332ca30128d8 100644
--- a/openmp/runtime/CMakeLists.txt
+++ b/openmp/runtime/CMakeLists.txt
@@ -120,7 +120,7 @@ endif()
# Remove any cmake-automatic linking of the standard C++ library.
# We neither need (nor want) the standard C++ library dependency even though we compile C++ files.
-if(NOT ${LIBOMP_USE_STDCPPLIB})
+if(NOT LIBOMP_USE_STDCPPLIB)
set(LIBOMP_LINKER_LANGUAGE C)
set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES)
else()
diff --git a/openmp/runtime/unittests/CMakeLists.txt b/openmp/runtime/unittests/CMakeLists.txt
index 10ffef9e566c8..400f411551e7b 100644
--- a/openmp/runtime/unittests/CMakeLists.txt
+++ b/openmp/runtime/unittests/CMakeLists.txt
@@ -19,7 +19,9 @@ set_property(TARGET omp_testing PROPERTY FOLDER "OpenMP/Libraries")
target_link_libraries(omp_testing PUBLIC default_gtest)
target_link_libraries(omp_testing PUBLIC ${LIBOMP_TEST_LIBFLAGS} ${LIBOMP_DL_LIBS})
set_target_properties(omp_testing PROPERTIES
- PREFIX "" SUFFIX "" OUTPUT_NAME "libomp_testing${LIBOMP_LIBRARY_SUFFIX}"
+ PREFIX ""
+ SUFFIX ""
+ OUTPUT_NAME "libomp_testing${LIBOMP_LIBRARY_SUFFIX}"
LINK_FLAGS "${LIBOMP_TEST_LDFLAGS}"
LINKER_LANGUAGE ${LIBOMP_LINKER_LANGUAGE}
EXCLUDE_FROM_ALL TRUE # Don't build by default, only when tests need it
>From 62b7be579d957c86eaf4ad412077fbf7179e67bf Mon Sep 17 00:00:00 2001
From: Robert Imschweiler <robert.imschweiler at amd.com>
Date: Fri, 19 Dec 2025 03:03:55 -0600
Subject: [PATCH 10/12] fix standalone build
---
openmp/runtime/unittests/CMakeLists.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/openmp/runtime/unittests/CMakeLists.txt b/openmp/runtime/unittests/CMakeLists.txt
index 400f411551e7b..f8ef61e2254f1 100644
--- a/openmp/runtime/unittests/CMakeLists.txt
+++ b/openmp/runtime/unittests/CMakeLists.txt
@@ -32,7 +32,7 @@ target_include_directories(omp_testing PUBLIC
)
# Make the targets default_gtest and default_gtest_main available.
-build_gtest()
+add_subdirectory("${LLVM_THIRD_PARTY_DIR}/unittest" "${CMAKE_BINARY_DIR}/third-party/runtimes_gtest")
function(add_openmp_unittest test_name)
add_unittest(OpenMPUnitTests ${test_name} ${ARGN})
>From c08593a2c5a06785306989f01239844619f86280 Mon Sep 17 00:00:00 2001
From: Robert Imschweiler <robert.imschweiler at amd.com>
Date: Wed, 7 Jan 2026 08:42:35 -0600
Subject: [PATCH 11/12] improve gtest dependency handling
---
openmp/runtime/unittests/CMakeLists.txt | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/openmp/runtime/unittests/CMakeLists.txt b/openmp/runtime/unittests/CMakeLists.txt
index f8ef61e2254f1..e1f0840933483 100644
--- a/openmp/runtime/unittests/CMakeLists.txt
+++ b/openmp/runtime/unittests/CMakeLists.txt
@@ -6,6 +6,22 @@ if(WIN32 OR STUBS_LIBRARY)
return()
endif()
+# Make the targets default_gtest and default_gtest_main available.
+if (OPENMP_STANDALONE_BUILD)
+ set(LLVM_RUNTIMES_BUILD 1)
+ if (EXISTS "${LLVM_THIRD_PARTY_DIR}/unittest/googletest/include/gtest/gtest.h")
+ add_subdirectory("${LLVM_THIRD_PARTY_DIR}/unittest" "${CMAKE_BINARY_DIR}/third-party/runtimes_gtest")
+ else()
+ message(WARNING "OpenMP unit tests will be skipped as LLVM third-party unittest directory is not available at: ${LLVM_THIRD_PARTY_DIR}/unittest")
+ return()
+ endif()
+elseif ("openmp" IN_LIST LLVM_ENABLE_PROJECTS)
+ # llvm_gtest should already exist
+else ()
+ # LLVM_ENABLE_RUNTIMES build
+ build_gtest()
+endif ()
+
# Build a testing version of libomp that exports all symbols for unit tests.
# This library uses the same compiled objects as libomp, but with all symbols
# exported to allow testing internal functions.
@@ -31,9 +47,6 @@ target_include_directories(omp_testing PUBLIC
${LIBOMP_SRC_DIR}
)
-# Make the targets default_gtest and default_gtest_main available.
-add_subdirectory("${LLVM_THIRD_PARTY_DIR}/unittest" "${CMAKE_BINARY_DIR}/third-party/runtimes_gtest")
-
function(add_openmp_unittest test_name)
add_unittest(OpenMPUnitTests ${test_name} ${ARGN})
>From 4b813bec4a2277005b12b788f82e2c85fa9beccc Mon Sep 17 00:00:00 2001
From: Robert Imschweiler <robert.imschweiler at amd.com>
Date: Mon, 12 Jan 2026 02:51:46 -0600
Subject: [PATCH 12/12] improve LLVM_RUNTIMES_BUILD var handling
---
openmp/runtime/unittests/CMakeLists.txt | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/openmp/runtime/unittests/CMakeLists.txt b/openmp/runtime/unittests/CMakeLists.txt
index e1f0840933483..9e00456fd8fb4 100644
--- a/openmp/runtime/unittests/CMakeLists.txt
+++ b/openmp/runtime/unittests/CMakeLists.txt
@@ -6,15 +6,26 @@ if(WIN32 OR STUBS_LIBRARY)
return()
endif()
-# Make the targets default_gtest and default_gtest_main available.
-if (OPENMP_STANDALONE_BUILD)
+function(standalone_add_gtest success_var)
+ # LLVM_RUNTIMES_BUILD avoids gtest to link to LLVMSupport, which might be
+ # incompable with the platform libomp is compiled for.
set(LLVM_RUNTIMES_BUILD 1)
if (EXISTS "${LLVM_THIRD_PARTY_DIR}/unittest/googletest/include/gtest/gtest.h")
+ set(${success_var} TRUE PARENT_SCOPE)
add_subdirectory("${LLVM_THIRD_PARTY_DIR}/unittest" "${CMAKE_BINARY_DIR}/third-party/runtimes_gtest")
else()
+ set(${success_var} FALSE PARENT_SCOPE)
message(WARNING "OpenMP unit tests will be skipped as LLVM third-party unittest directory is not available at: ${LLVM_THIRD_PARTY_DIR}/unittest")
return()
endif()
+endfunction()
+
+# Make the targets default_gtest and default_gtest_main available.
+if (OPENMP_STANDALONE_BUILD)
+ standalone_add_gtest(STANDALONE_UNIT_TESTS)
+ if(NOT STANDALONE_UNIT_TESTS)
+ return()
+ endif()
elseif ("openmp" IN_LIST LLVM_ENABLE_PROJECTS)
# llvm_gtest should already exist
else ()
More information about the Openmp-commits
mailing list