run: sudo apt install --yes --no-install-recommends libwayland-dev libxrandr-dev
- name: Generate build files
- run: cmake -S. -B build -D CMAKE_BUILD_TYPE=${{matrix.config}} -D BUILD_TESTS=ON -D UPDATE_DEPS=ON -D TEST_USE_ADDRESS_SANITIZER=ON
+ run: cmake -S. -B build -D CMAKE_BUILD_TYPE=${{matrix.config}} -D BUILD_TESTS=ON -D UPDATE_DEPS=ON -D LOADER_ENABLE_ADDRESS_SANITIZER=ON
env:
CC: ${{matrix.cc}}
CXX: ${{matrix.cxx}}
python-version: '3.7'
- uses: lukka/get-cmake@latest
- name: Generate build files
- run: cmake -S. -B build -DCMAKE_BUILD_TYPE=${{matrix.config}} -D${{matrix.static_build}} -DBUILD_TESTS=ON -DUPDATE_DEPS=ON -DTEST_USE_ADDRESS_SANITIZER=ON -G "Ninja"
+ run: cmake -S. -B build -D CMAKE_BUILD_TYPE=${{matrix.config}} -D ${{matrix.static_build}} -D BUILD_TESTS=ON -D UPDATE_DEPS=ON -D LOADER_ENABLE_ADDRESS_SANITIZER=ON -G "Ninja"
env:
# Specify the minimum version of macOS on which the target binaries are to be deployed.
# https://cmake.org/cmake/help/latest/envvar/MACOSX_DEPLOYMENT_TARGET.html
- [Notes About the Automatic Option](#notes-about-the-automatic-option)
- [Generated source code](#generated-source-code)
- [Build Options](#build-options)
+ - [CCACHE](#ccache)
- [Building On Windows](#building-on-windows)
- [Windows Development Environment Requirements](#windows-development-environment-requirements)
- [Windows Build - Microsoft Visual Studio](#windows-build---microsoft-visual-studio)
- [MacOS Development Environment Requirements](#macos-development-environment-requirements)
- [Clone the Repository](#clone-the-repository)
- [MacOS build](#macos-build)
- - [CMake Generators](#cmake-generators)
- [Building with the Unix Makefiles Generator](#building-with-the-unix-makefiles-generator)
- [Building with the Xcode Generator](#building-with-the-xcode-generator)
- [Using the new macOS loader](#using-the-new-macos-loader)
options, while others take a string as input. The following is a table of all
on/off options currently supported by this repository:
-| Option | Platform | Default | Description |
-| ---------------------------- | -------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| BUILD_TESTS | All | `OFF` | Controls whether or not the loader tests are built. |
-| BUILD_WSI_XCB_SUPPORT | Linux | `ON` | Build the loader with the XCB entry points enabled. Without this, the XCB headers should not be needed, but the extension `VK_KHR_xcb_surface` won't be available. |
-| BUILD_WSI_XLIB_SUPPORT | Linux | `ON` | Build the loader with the Xlib entry points enabled. Without this, the X11 headers should not be needed, but the extension `VK_KHR_xlib_surface` won't be available. |
-| BUILD_WSI_WAYLAND_SUPPORT | Linux | `ON` | Build the loader with the Wayland entry points enabled. Without this, the Wayland headers should not be needed, but the extension `VK_KHR_wayland_surface` won't be available. |
-| BUILD_WSI_DIRECTFB_SUPPORT | Linux | `OFF` | Build the loader with the DirectFB entry points enabled. Without this, the DirectFB headers should not be needed, but the extension `VK_EXT_directfb_surface` won't be available. |
-| BUILD_WSI_SCREEN_QNX_SUPPORT | QNX | `OFF` | Build the loader with the QNX Screen entry points enabled. Without this the extension `VK_QNX_screen_surface` won't be available. |
-| ENABLE_WIN10_ONECORE | Windows | `OFF` | Link the loader to the [OneCore](https://msdn.microsoft.com/en-us/library/windows/desktop/mt654039.aspx) umbrella library, instead of the standard Win32 ones. |
-| USE_GAS | Linux | `ON` | Controls whether to build assembly files with the GNU assembler, else fallback to C code. |
-| USE_MASM | Windows | `ON` | Controls whether to build assembly files with MS assembler, else fallback to C code |
-| BUILD_STATIC_LOADER | macOS | `OFF` | This allows the loader to be built as a static library on macOS. Not tested, use at your own risk. |
+| Option | Platform | Default | Description |
+| ---------------------------------------- | ------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| BUILD_TESTS | All | `OFF` | Controls whether or not the loader tests are built. |
+| BUILD_WSI_XCB_SUPPORT | Linux | `ON` | Build the loader with the XCB entry points enabled. Without this, the XCB headers should not be needed, but the extension `VK_KHR_xcb_surface` won't be available. |
+| BUILD_WSI_XLIB_SUPPORT | Linux | `ON` | Build the loader with the Xlib entry points enabled. Without this, the X11 headers should not be needed, but the extension `VK_KHR_xlib_surface` won't be available. |
+| BUILD_WSI_WAYLAND_SUPPORT | Linux | `ON` | Build the loader with the Wayland entry points enabled. Without this, the Wayland headers should not be needed, but the extension `VK_KHR_wayland_surface` won't be available. |
+| BUILD_WSI_DIRECTFB_SUPPORT | Linux | `OFF` | Build the loader with the DirectFB entry points enabled. Without this, the DirectFB headers should not be needed, but the extension `VK_EXT_directfb_surface` won't be available. |
+| BUILD_WSI_SCREEN_QNX_SUPPORT | QNX | `OFF` | Build the loader with the QNX Screen entry points enabled. Without this the extension `VK_QNX_screen_surface` won't be available. |
+| ENABLE_WIN10_ONECORE | Windows | `OFF` | Link the loader to the [OneCore](https://msdn.microsoft.com/en-us/library/windows/desktop/mt654039.aspx) umbrella library, instead of the standard Win32 ones. |
+| USE_GAS | Linux | `ON` | Controls whether to build assembly files with the GNU assembler, else fallback to C code. |
+| USE_MASM | Windows | `ON` | Controls whether to build assembly files with MS assembler, else fallback to C code |
+| BUILD_STATIC_LOADER | macOS | `OFF` | This allows the loader to be built as a static library on macOS. Not tested, use at your own risk. |
+| LOADER_ENABLE_ADDRESS_SANITIZER | Linux & macOS | `OFF` | Enables Address Sanitizer in the loader and tests. |
+| LOADER_ENABLE_THREAD_SANITIZER | Linux & macOS | `OFF` | Enables Thread Sanitizer in the loader and tests. |
+| LOADER_DISABLE_DYNAMIC_LIBRARY_UNLOADING | Linux & macOS | `OFF` | Causes the loader to not unload dynamic libraries. Only works when LOADER_ENABLE_ADDRESS_SANITIZER is enabled. This option allows leak sanitizer to have full stack traces. |
+
The following is a table of all string options currently supported by this repository:
| Option | Platform | Default | Description |
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
+# By default, loader & tests are built without sanitizers
+# Use these options to force a specific sanitizer on the loader and test executables
+if (UNIX)
+ option(LOADER_ENABLE_ADDRESS_SANITIZER "Linux & macOS only: Advanced memory checking" OFF)
+ option(LOADER_ENABLE_THREAD_SANITIZER "Linux & macOS only: Advanced thread checking" OFF)
+endif()
+
if(APPLE)
option(BUILD_STATIC_LOADER "Build a loader that can be statically linked" OFF)
endif()
target_link_libraries(vulkan PRIVATE Threads::Threads)
endif()
+ if (LOADER_ENABLE_ADDRESS_SANITIZER)
+ target_compile_options(vulkan PUBLIC -fsanitize=address)
+ target_link_options(vulkan PUBLIC -fsanitize=address)
+ if (LOADER_DISABLE_DYNAMIC_LIBRARY_UNLOADING)
+ target_compile_definitions(vulkan PRIVATE LOADER_DISABLE_DYNAMIC_LIBRARY_UNLOADING=1)
+ endif()
+ endif()
+ if (LOADER_ENABLE_THREAD_SANITIZER)
+ target_compile_options(vulkan PUBLIC -fsanitize=thread)
+ target_link_options(vulkan PUBLIC -fsanitize=thread)
+ endif()
+
if(APPLE)
find_library(COREFOUNDATION_LIBRARY NAMES CoreFoundation)
target_link_libraries(vulkan PRIVATE "-framework CoreFoundation")
#endif
#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
-#define LOADER_ADDRESS_SANITIZER // TODO: Add proper build flag for ASAN support
+#define LOADER_ADDRESS_SANITIZER_ACTIVE // TODO: Add proper build flag for ASAN support
+#endif
+
+// We should always unload dynamic libraries in loader_platform_close_library() unless both Address Sanitizer is active and
+// LOADER_DISABLE_DYNAMIC_LIBRARY_UNLOADING is set
+#if defined(LOADER_ADDRESS_SANITIZER_ACTIVE) && defined(LOADER_DISABLE_DYNAMIC_LIBRARY_UNLOADING)
+#define SHOULD_UNLOAD_DYNAMIC_LIBRARIES 0
+#else
+#define SHOULD_UNLOAD_DYNAMIC_LIBRARIES 1
#endif
// When loading the library, we use RTLD_LAZY so that not all symbols have to be
return dlerror();
#endif
}
-static inline void loader_platform_close_library(loader_platform_dl_handle library) { dlclose(library); }
+static inline void loader_platform_close_library(loader_platform_dl_handle library) {
+// We only want to remove dlclose if both Asan is active and LOADER_DISABLE_DYNAMIC_LIBRARY_UNLOADING is set
+#if SHOULD_UNLOAD_DYNAMIC_LIBRARIES == 1
+ dlclose(library);
+#endif
+}
static inline void *loader_platform_get_proc_address(loader_platform_dl_handle library, const char *name) {
assert(library);
assert(name);
# ~~~
-# By default, tests and loader are built without sanitizers
-# Use these options to force a specific sanitizer on all test executables
-option(TEST_USE_ADDRESS_SANITIZER "Linux only: Advanced memory checking" OFF)
-option(TEST_USE_THREAD_SANITIZER "Linux only: Advanced thread checking" OFF)
option(ENABLE_LIVE_VERIFICATION_TESTS "Enable tests which expect to run on live drivers. Meant for manual verification only" OFF)
include(GoogleTest)
| ------------------------------ | -------- | ------- | -------------------------------------------------------- |
| BUILD_TESTS | All | `OFF` | Controls whether or not the loader tests are built. |
| ENABLE_LIVE_VERIFICATION_TESTS | All | `OFF` | Enables building of tests meant to run with live drivers |
-| TEST_USE_ADDRESS_SANITIZER | Linux | `OFF` | Enables Address Sanitizer in the loader and tests |
-| TEST_USE_THREAD_SANITIZER | Linux | `OFF` | Enables Thread Sanitizer in the loader and tests |
## Running Tests
Basic usage example:
```c
VK_LOADER_TEST_LOADER_PATH="/path/to/older/loader/build" ctest --output-on-failure
-```
\ No newline at end of file
+```
target_include_directories(testing_framework_util PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR})
if (UNIX)
- if (TEST_USE_ADDRESS_SANITIZER)
+ if (LOADER_ENABLE_ADDRESS_SANITIZER)
target_compile_options(testing_framework_util PUBLIC -fsanitize=address)
target_link_options(testing_framework_util PUBLIC -fsanitize=address)
- target_compile_options(vulkan PUBLIC -fsanitize=address)
- target_link_options(vulkan PUBLIC -fsanitize=address)
endif()
- if (TEST_USE_THREAD_SANITIZER)
+ if (LOADER_ENABLE_THREAD_SANITIZER)
target_compile_options(testing_framework_util PUBLIC -fsanitize=thread)
target_link_options(testing_framework_util PUBLIC -fsanitize=thread)
- target_compile_options(vulkan PUBLIC -fsanitize=thread)
- target_link_options(vulkan PUBLIC -fsanitize=thread)
target_compile_options(gtest PUBLIC -fsanitize=thread)
target_link_options(gtest PUBLIC -fsanitize=thread)
endif()
if (APPLE AND BUILD_STATIC_LOADER)
target_compile_definitions(testing_dependencies PUBLIC "BUILD_STATIC_LOADER=1")
target_link_libraries(testing_dependencies PUBLIC vulkan)
-endif()
\ No newline at end of file
+endif()
Or Ensure that `googletest` is in the `external` directory.
And on Windows only, ensure that the `Detours` library is in the `external` directory.
-Linux only: The CMake Configuration `TEST_USE_ADDRESS_SANITIZER` can be used to
-enable Address Sanitizer inside the testing framework.
+Linux & macOS only: The CMake Configuration `LOADER_ENABLE_ADDRESS_SANITIZER` can be used to
+enable Address Sanitizer.
Run the test executables as normal
dev.CheckCreate(phys_dev);
- ASSERT_TRUE(log.find("loader_create_device_chain: Using deprecated and ignored 'ppEnabledLayerNames' member of 'VkDeviceCreateInfo' when creating a Vulkan device."));
+ ASSERT_TRUE(
+ log.find("loader_create_device_chain: Using deprecated and ignored 'ppEnabledLayerNames' member of 'VkDeviceCreateInfo' "
+ "when creating a Vulkan device."));
}
// Device layers are deprecated.
-// Ensure that when VkInstanceCreateInfo is deleted, the check of the instance layer lists is running correctly during VkDevice creation
+// Ensure that when VkInstanceCreateInfo is deleted, the check of the instance layer lists is running correctly during VkDevice
+// creation
// https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#extendingvulkan-layers-devicelayerdeprecation
TEST(CreateDevice, CheckCopyOfInstanceLayerNames) {
FrameworkEnvironment env{};
InstWrapper inst{env.vulkan_functions};
{
- // We intentionally create a local InstanceCreateInfo that goes out of scope at the } so that when dev.CheckCreate is called the layer name pointers are no longer valid
+ // We intentionally create a local InstanceCreateInfo that goes out of scope at the } so that when dev.CheckCreate is called
+ // the layer name pointers are no longer valid
InstanceCreateInfo create_info{};
create_info.add_layer(layer_name);
inst.CheckCreateWithInfo(create_info);
for (uint32_t group2 = 0; group2 < group_props_after.size(); ++group2) {
if (group_props_before[group1].physicalDeviceCount == group_props_after[group2].physicalDeviceCount) {
uint32_t found_count = 0;
- bool found;
+ bool found = false;
for (uint32_t dev1 = 0; dev1 < group_props_before[group1].physicalDeviceCount; ++dev1) {
found = false;
for (uint32_t dev2 = 0; dev2 < group_props_after[group2].physicalDeviceCount; ++dev2) {
for (uint32_t group2 = 0; group2 < group_props_before.size(); ++group2) {
if (group_props_after[group1].physicalDeviceCount == group_props_before[group2].physicalDeviceCount) {
uint32_t found_count = 0;
- bool found;
+ bool found = false;
for (uint32_t dev1 = 0; dev1 < group_props_after[group1].physicalDeviceCount; ++dev1) {
found = false;
for (uint32_t dev2 = 0; dev2 < group_props_before[group2].physicalDeviceCount; ++dev2) {
for (uint32_t group1 = 0; group1 < group_props_before.size(); ++group1) {
for (uint32_t group2 = 0; group2 < group_props_after.size(); ++group2) {
uint32_t found_count = 0;
- bool found;
+ bool found = false;
for (uint32_t dev1 = 0; dev1 < group_props_before[group1].physicalDeviceCount; ++dev1) {
found = false;
for (uint32_t dev2 = 0; dev2 < group_props_after[group2].physicalDeviceCount; ++dev2) {
for (uint32_t group1 = 0; group1 < group_props_after.size(); ++group1) {
for (uint32_t group2 = 0; group2 < group_props_before.size(); ++group2) {
uint32_t found_count = 0;
- bool found;
+ bool found = false;
for (uint32_t dev1 = 0; dev1 < group_props_after[group1].physicalDeviceCount; ++dev1) {
found = false;
for (uint32_t dev2 = 0; dev2 < group_props_before[group2].physicalDeviceCount; ++dev2) {