Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a test for the module #2283

Merged
merged 1 commit into from
May 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 33 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,17 @@ function(join result_var)
set(${result_var} "${result}" PARENT_SCOPE)
endfunction()

function(enable_module target)
if (MSVC)
set(BMI ${CMAKE_CURRENT_BINARY_DIR}/${target}.ifc)
target_compile_options(${target}
PRIVATE /interface /ifcOutput ${BMI}
INTERFACE /reference fmt=${BMI})
endif ()
set_target_properties(${target} PROPERTIES ADDITIONAL_CLEAN_FILES ${BMI})
set_source_files_properties(${BMI} PROPERTIES GENERATED ON)
endfunction()

include(CMakeParseArguments)

# Sets a cache variable with a docstring joined from multiple arguments:
Expand Down Expand Up @@ -69,6 +80,22 @@ option(FMT_TEST "Generate the test target." ${FMT_MASTER_PROJECT})
option(FMT_FUZZ "Generate the fuzz target." OFF)
option(FMT_CUDA_TEST "Generate the cuda-test target." OFF)
option(FMT_OS "Include core requiring OS (Windows/Posix) " ON)
option(FMT_MODULE "Build a module instead of a traditional library." OFF)

set(FMT_CAN_MODULE OFF)
if (CMAKE_CXX_STANDARD GREATER_EQUAL 20 AND
# msvc 16.10-pre4
MSVC AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.29.30036)
set(FMT_CAN_MODULE ON)
endif ()
if (NOT FMT_CAN_MODULE)
set(FMT_MODULE OFF)
message(STATUS "Module support is disabled.")
endif ()
if (FMT_TEST AND FMT_MODULE)
# The tests require {fmt} to be compiled as traditional library
message(STATUS "Testing is incompatible with build mode 'module'.")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Who needs tests anyway =).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤡

endif ()

# Get version from core.h
file(READ include/fmt/core.h core_h)
Expand Down Expand Up @@ -189,7 +216,9 @@ endfunction()
add_headers(FMT_HEADERS args.h chrono.h color.h compile.h core.h format.h
format-inl.h locale.h os.h ostream.h printf.h ranges.h
wchar.h)
if (FMT_OS)
if (FMT_MODULE)
set(FMT_SOURCES src/fmt.cc)
elseif (FMT_OS)
set(FMT_SOURCES src/format.cc src/os.cc)
else()
set(FMT_SOURCES src/format.cc)
Expand All @@ -215,6 +244,9 @@ endif ()
if (FMT_PEDANTIC)
target_compile_options(fmt PRIVATE ${PEDANTIC_COMPILE_FLAGS})
endif ()
if (FMT_MODULE)
enable_module(fmt)
endif ()

target_compile_features(fmt INTERFACE ${FMT_REQUIRED_FEATURES})

Expand Down
26 changes: 23 additions & 3 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ add_subdirectory(gtest)

set(TEST_MAIN_SRC test-main.cc gtest-extra.cc gtest-extra.h util.cc)
add_library(test-main STATIC ${TEST_MAIN_SRC})
target_link_libraries(test-main gtest fmt)
target_include_directories(test-main PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>)
target_link_libraries(test-main gtest)

include(CheckCXXCompilerFlag)

Expand All @@ -29,16 +31,20 @@ endfunction()
# Adds a test.
# Usage: add_fmt_test(name srcs...)
function(add_fmt_test name)
cmake_parse_arguments(ADD_FMT_TEST "HEADER_ONLY" "" "" ${ARGN})
cmake_parse_arguments(ADD_FMT_TEST "HEADER_ONLY;MODULE" "" "" ${ARGN})

set(sources ${name}.cc ${ADD_FMT_TEST_UNPARSED_ARGUMENTS})
set(libs test-main)
if (ADD_FMT_TEST_HEADER_ONLY)
set(sources ${sources} ${TEST_MAIN_SRC} ../src/os.cc)
set(libs gtest fmt-header-only)
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wno-weak-vtables)
endif ()
elseif (ADD_FMT_TEST_MODULE)
set(libs test-main test-module)
set_source_files_properties(${name}.cc PROPERTIES OBJECT_DEPENDS test-module)
else ()
set(libs test-main fmt)
endif ()
add_fmt_executable(${name} ${sources})
target_link_libraries(${name} ${libs})
Expand Down Expand Up @@ -74,6 +80,20 @@ add_fmt_test(ranges-test)
add_fmt_test(scan-test)
add_fmt_test(wchar-test)

if (FMT_CAN_MODULE)
# The tests need {fmt} to be compiled as traditional library
# because of visibility of implementation details.
# If module support is present the module tests require a
# test-only module to be built from {fmt}
add_library(test-module OBJECT ${CMAKE_SOURCE_DIR}/src/fmt.cc)
target_compile_features(test-module PUBLIC ${FMT_REQUIRED_FEATURES})
target_include_directories(test-module PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>)
enable_module(test-module)

add_fmt_test(module-test MODULE)
endif ()

if (NOT MSVC)
# FMT_ENFORCE_COMPILE_STRING is not supported under MSVC due to compiler bugs.
add_fmt_test(enforce-checks-test)
Expand Down
65 changes: 65 additions & 0 deletions test/module-test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Formatting library for C++ - module tests
//
// Copyright (c) 2012 - present, Victor Zverovich
// All rights reserved.
//
// For the license information refer to format.h.
//
// Copyright (c) 2021 - present, Daniela Engert
// All Rights Reserved
// {fmt} module.

import fmt;

// check for macros leaking from BMI
static bool macro_leaked =
#if defined(FMT_CORE_H_) || defined(FMT_FORMAT_H)
true;
#else
false;
#endif

#include "gtest/gtest.h"

// an implicitly exported namespace must be visible [module.interface]/2.2
TEST(module_test, namespace) {
using namespace fmt;
ASSERT_TRUE(true);
}

namespace detail {
bool oops_detail_namespace_is_visible;
}

namespace fmt {
bool namespace_detail_invisible() {
#if defined(FMT_HIDE_MODULE_BUGS) && \
defined(_MSC_FULL_VER) && _MSC_FULL_VER <= 192930036
// bug in msvc 16.10-pre4:
// the namespace is visible even when it is neither
// implicitly nor explicitly exported
return true;
#else
using namespace detail;
// this fails to compile if fmt::detail is visible
return !oops_detail_namespace_is_visible;
#endif
}
} // namespace fmt

// the non-exported namespace 'detail' must be invisible [module.interface]/2
TEST(module_test, detail_namespace) {
EXPECT_TRUE(fmt::namespace_detail_invisible());
}

// macros must not be imported from a *named* module [cpp.import]/5.1
TEST(module_test, macros) {
#if defined(FMT_HIDE_MODULE_BUGS) && \
defined(_MSC_FULL_VER) && _MSC_FULL_VER <= 192930036
// bug in msvc 16.10-pre4:
// include-guard macros leak from BMI
// and even worse: they cannot be #undef-ined
macro_leaked = false;
#endif
EXPECT_FALSE(macro_leaked);
}