Skip to content

Commit

Permalink
WIP: Add example project to manage plugin dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
alxvth committed Sep 18, 2024
1 parent a9394b5 commit 8805308
Show file tree
Hide file tree
Showing 11 changed files with 596 additions and 0 deletions.
7 changes: 7 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
cmake_minimum_required(VERSION 3.17)

set(VCPKG_LIBRARY_LINKAGE "dynamic" CACHE STRING "Link vcpkg libraries dynamically")

if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
message(FATAL_ERROR "Define CMAKE_TOOLCHAIN_FILE poiting to vcpkg: PATH/vcpkg/scripts/buildsystems/vcpkg.cmake")
endif()

# -----------------------------------------------------------------------------
# ExamplePlugins
# -----------------------------------------------------------------------------
Expand All @@ -14,3 +20,4 @@ add_subdirectory(ExampleTransformation)
add_subdirectory(ExampleLoader)
add_subdirectory(ExampleWriter)
add_subdirectory(ExampleData)
add_subdirectory(ExampleDependencies)
183 changes: 183 additions & 0 deletions ExampleDependencies/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
cmake_minimum_required(VERSION 3.21)

option(MV_UNITY_BUILD "Combine target source files into batches for faster compilation" OFF)

# -----------------------------------------------------------------------------
# ExampleAnalysis Plugin
# -----------------------------------------------------------------------------
PROJECT("ExampleDependenciesPlugin")

# -----------------------------------------------------------------------------
# CMake Options
# -----------------------------------------------------------------------------
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)

if(MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /DWIN32 /EHsc /MP /permissive- /Zc:__cplusplus")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /NODEFAULTLIB:LIBCMT")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD")
endif(MSVC)

include(cmake/get_cpm.cmake)

# -----------------------------------------------------------------------------
# Dependencies
# -----------------------------------------------------------------------------
find_package(Qt6 COMPONENTS Widgets WebEngineWidgets REQUIRED)

find_package(ManiVault COMPONENTS Core PointData CONFIG)

find_package(blake3 CONFIG REQUIRED)
find_package(faiss CONFIG REQUIRED)

CPMAddPackage(
NAME highway
URL https://github.com/google/highway/archive/refs/tags/1.2.0.tar.gz
URL_HASH SHA256=7e0be78b8318e8bdbf6fa545d2ecb4c90f947df03f7aadc42c1967f019e63343
PATCHES "cmake/highway.patch" # see https://github.com/conan-io/conan-center-index/pull/24197/files, fixes https://github.com/google/highway/issues/2225
OPTIONS "HWY_ENABLE_EXAMPLES OFF" "HWY_ENABLE_INSTALL OFF" "HWY_ENABLE_TESTS OFF" "HWY_ENABLE_CONTRIB ON" "BUILD_SHARED_LIBS ON"
)

# -----------------------------------------------------------------------------
# Source files
# -----------------------------------------------------------------------------
# Define the plugin sources
set(PLUGIN_SOURCES
src/ExampleDependenciesPlugin.h
src/ExampleDependenciesPlugin.cpp
src/SettingsAction.h
src/SettingsAction.cpp
src/ExampleDependenciesPlugin.json
)

source_group( Plugin FILES ${PLUGIN_SOURCES})

# -----------------------------------------------------------------------------
# CMake Target
# -----------------------------------------------------------------------------
# Create dynamic library for the plugin
add_library(${PROJECT_NAME} SHARED ${PLUGIN_SOURCES})

# -----------------------------------------------------------------------------
# Target include directories
# -----------------------------------------------------------------------------
# Include ManiVault headers, including system data plugins
target_include_directories(${PROJECT_NAME} PRIVATE "${ManiVault_INCLUDE_DIR}")

# -----------------------------------------------------------------------------
# Target properties
# -----------------------------------------------------------------------------
# Request C++17
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_17)

# Enable unity build
if(MV_UNITY_BUILD)
set_target_properties(${PROJECT_NAME} PROPERTIES UNITY_BUILD ON)
endif()

# -----------------------------------------------------------------------------
# Target library linking
# -----------------------------------------------------------------------------
# Link to Qt libraries
target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Widgets)
target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::WebEngineWidgets)

# Link to ManiVault and data plugins
target_link_libraries(${PROJECT_NAME} PRIVATE ManiVault::Core)
target_link_libraries(${PROJECT_NAME} PRIVATE ManiVault::PointData)

target_link_libraries(${PROJECT_NAME} PRIVATE BLAKE3::blake3)
target_link_libraries(${PROJECT_NAME} PRIVATE hwy hwy_contrib)
target_link_libraries(${PROJECT_NAME} PRIVATE faiss)

# -----------------------------------------------------------------------------
# Target installation
# -----------------------------------------------------------------------------
# Install the shared plugin libary to the "Plugins" folder in the ManiVault install directory
install(TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION Plugins COMPONENT PLUGINS # Windows .dll
LIBRARY DESTINATION Plugins COMPONENT PLUGINS # Linux/Mac .so
)

if(WIN32)
set(PRE_EXCLUDE ".*[\\/]api-ms.*" ".*[\\/]ext-ms.*" ".*[\\/]hvsi.*" ".*[\\/]pdmutilities.*" ".*[\\/]wpaxholder.*" ".*[\\/]dxgi.*" ".*[\\/]uxtheme.*" ".*[\\/]d3d11.*" ".*[\\/]winmm.*" ".*[\\/]wldp.*")
set(POST_EXCLUDE ".*[\\/]WINDOWS[\\/]system32[\\/].*\\.dll")
elseif(APPLE)
set(PRE_EXCLUDE "/usr/lib" "/System/")
set(POST_EXCLUDE "")
else()
set(PRE_EXCLUDE ".*/ld-linux-.*" ".*/linux-vdso.*" ".*/libm\\..*" ".*/libc\\..*" ".*/libpthread\\..*" ".*/libdl\\..*")
set(POST_EXCLUDE "")
endif()

set(deps_folder "bin/${PROJECT_NAME}")

message(STATUS "Install deps:: ${ManiVault_INSTALL_DIR}/$<CONFIGURATION>/${deps_folder}")

install(CODE [[
function(install_deps LIBRARY)
file(INSTALL
DESTINATION "${CMAKE_INSTALL_PREFIX}/PluginDependencies/ExampleDependenciesPlugin"
TYPE SHARED_LIBRARY
FOLLOW_SYMLINK_CHAIN
FILES "${LIBRARY}"
)
endfunction()
file(GET_RUNTIME_DEPENDENCIES
EXECUTABLES "$<TARGET_FILE:ExampleDependenciesPlugin>"
RESOLVED_DEPENDENCIES_VAR RESOLVED_DEPS
UNRESOLVED_DEPENDENCIES_VAR UNRESOLVED_DEPS
CONFLICTING_DEPENDENCIES_PREFIX CONFLICTING_DEPS
DIRECTORIES "$<TARGET_FILE_DIR:ExampleDependenciesPlugin>" "$<TARGET_FILE_DIR:hwy>" "$<TARGET_FILE_DIR:hwy_contrib>"
PRE_EXCLUDE_REGEXES ".*[\\/]api-ms.*" ".*[\\/]ext-ms.*" ".*[\\/]hvsi.*" ".*[\\/]pdmutilities.*" ".*[\\/]wpaxholder.*" ".*[\\/]dxgi.*" ".*[\\/]uxtheme.*" ".*[\\/]d3d11.*" ".*[\\/]winmm.*" ".*[\\/]wldp.*"
POST_EXCLUDE_REGEXES ".*[\\/]WINDOWS[\\/]system32[\\/].*\\.dll"
)

foreach(FILE ${RESOLVED_DEPS})
message(STATUS "Resolved: ${FILE}")
install_deps(${FILE})
endforeach()

foreach(FILE ${UNRESOLVED_DEPS})
message(STATUS "Unresolved: ${FILE}")
endforeach()

if(CONFLICTING_DEPS)
message(WARNING "Conflicting dependencies!")
foreach(FILE ${CONFLICTING_DEPS})
message(STATUS "Conflicting: ${FILE}")
endforeach()
endif()

]]
COMPONENT DEP_PLUGIN_PRINT
)

add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo "Installing: Create dir"
COMMAND ${CMAKE_COMMAND} -E make_directory ${ManiVault_INSTALL_DIR}/$<CONFIGURATION>/${deps_folder}
COMMAND "${CMAKE_COMMAND}"
--install ${CMAKE_CURRENT_BINARY_DIR}
--config $<CONFIGURATION>
--component PLUGINS
--prefix ${ManiVault_INSTALL_DIR}/$<CONFIGURATION>
--verbose
COMMAND "${CMAKE_COMMAND}"
--install ${CMAKE_CURRENT_BINARY_DIR}
--config $<CONFIGURATION>
--component DEP_PLUGIN_PRINT
--prefix ${ManiVault_INSTALL_DIR}/$<CONFIGURATION>
--verbose
)

# -----------------------------------------------------------------------------
# Miscellaneous
# -----------------------------------------------------------------------------
# Automatically set the debug environment (command + working directory) for MSVC
if(MSVC)
set_property(TARGET ${PROJECT_NAME} PROPERTY VS_DEBUGGER_WORKING_DIRECTORY $<IF:$<CONFIG:DEBUG>,${ManiVault_INSTALL_DIR}/debug,${ManiVault_INSTALL_DIR}/release>)
set_property(TARGET ${PROJECT_NAME} PROPERTY VS_DEBUGGER_COMMAND $<IF:$<CONFIG:DEBUG>,${ManiVault_INSTALL_DIR}/debug/ManiVault\ Studio.exe,${ManiVault_INSTALL_DIR}/release/ManiVault\ Studio.exe>)
endif()
24 changes: 24 additions & 0 deletions ExampleDependencies/cmake/get_cpm.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# SPDX-License-Identifier: MIT
#
# SPDX-FileCopyrightText: Copyright (c) 2019-2023 Lars Melchior and contributors

set(CPM_DOWNLOAD_VERSION 0.40.2)
set(CPM_HASH_SUM "c8cdc32c03816538ce22781ed72964dc864b2a34a310d3b7104812a5ca2d835d")

if(CPM_SOURCE_CACHE)
set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
elseif(DEFINED ENV{CPM_SOURCE_CACHE})
set(CPM_DOWNLOAD_LOCATION "$ENV{CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
else()
set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
endif()

# Expand relative path. This is important if the provided path contains a tilde (~)
get_filename_component(CPM_DOWNLOAD_LOCATION ${CPM_DOWNLOAD_LOCATION} ABSOLUTE)

file(DOWNLOAD
https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake
${CPM_DOWNLOAD_LOCATION} EXPECTED_HASH SHA256=${CPM_HASH_SUM}
)

include(${CPM_DOWNLOAD_LOCATION})
91 changes: 91 additions & 0 deletions ExampleDependencies/cmake/highway.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
diff --git a/hwy/contrib/thread_pool/topology.cc b/hwy/contrib/thread_pool/topology.cc
index 3d24f4f..17f3563 100644
--- a/hwy/contrib/thread_pool/topology.cc
+++ b/hwy/contrib/thread_pool/topology.cc
@@ -64,7 +64,7 @@

namespace hwy {

-HWY_DLLEXPORT bool HaveThreadingSupport() {
+HWY_CONTRIB_DLLEXPORT bool HaveThreadingSupport() {
#if HWY_ARCH_WASM
return emscripten_has_threading_support() != 0;
#else
@@ -72,7 +72,7 @@ HWY_DLLEXPORT bool HaveThreadingSupport() {
#endif
}

-HWY_DLLEXPORT size_t TotalLogicalProcessors() {
+HWY_CONTRIB_DLLEXPORT size_t TotalLogicalProcessors() {
size_t lp = 0;
#if HWY_ARCH_WASM
const int num_cores = emscripten_num_logical_cores();
@@ -111,7 +111,7 @@ HWY_DLLEXPORT size_t TotalLogicalProcessors() {
#include <sys/syscall.h>
#endif

-HWY_DLLEXPORT bool GetThreadAffinity(LogicalProcessorSet& lps) {
+HWY_CONTRIB_DLLEXPORT bool GetThreadAffinity(LogicalProcessorSet& lps) {
#if HWY_OS_WIN
// Only support the first 64 because WINE does not support processor groups.
const HANDLE hThread = GetCurrentThread();
@@ -173,7 +173,7 @@ HWY_DLLEXPORT bool GetThreadAffinity(LogicalProcessorSet& lps) {
#endif
}

-HWY_DLLEXPORT bool SetThreadAffinity(const LogicalProcessorSet& lps) {
+HWY_CONTRIB_DLLEXPORT bool SetThreadAffinity(const LogicalProcessorSet& lps) {
#if HWY_OS_WIN
const HANDLE hThread = GetCurrentThread();
const DWORD_PTR prev = SetThreadAffinityMask(hThread, lps.Get64());
@@ -385,7 +385,7 @@ std::vector<PerPackage> DetectPackages(std::vector<Topology::LP>& lps) {
} // namespace
#endif // HWY_OS_LINUX

-HWY_DLLEXPORT Topology::Topology() {
+HWY_CONTRIB_DLLEXPORT Topology::Topology() {
#if HWY_OS_LINUX
lps.resize(TotalLogicalProcessors());
const std::vector<PerPackage>& per_package = DetectPackages(lps);
diff --git a/hwy/contrib/thread_pool/topology.h b/hwy/contrib/thread_pool/topology.h
index 95b0835..f80fc47 100644
--- a/hwy/contrib/thread_pool/topology.h
+++ b/hwy/contrib/thread_pool/topology.h
@@ -28,7 +28,7 @@
namespace hwy {

// Returns false if std::thread should not be used.
-HWY_DLLEXPORT bool HaveThreadingSupport();
+HWY_CONTRIB_DLLEXPORT bool HaveThreadingSupport();

// Upper bound on logical processors, including hyperthreads.
static constexpr size_t kMaxLogicalProcessors = 1024; // matches glibc
@@ -38,12 +38,12 @@ using LogicalProcessorSet = BitSet4096<kMaxLogicalProcessors>;

// Returns false, or sets `lps` to all logical processors which are online and
// available to the current thread.
-HWY_DLLEXPORT bool GetThreadAffinity(LogicalProcessorSet& lps);
+HWY_CONTRIB_DLLEXPORT bool GetThreadAffinity(LogicalProcessorSet& lps);

// Ensures the current thread can only run on the logical processors in `lps`.
// Returns false if not supported (in particular on Apple), or if the
// intersection between `lps` and `GetThreadAffinity` is the empty set.
-HWY_DLLEXPORT bool SetThreadAffinity(const LogicalProcessorSet& lps);
+HWY_CONTRIB_DLLEXPORT bool SetThreadAffinity(const LogicalProcessorSet& lps);

// Returns false, or ensures the current thread will only run on `lp`, which
// must not exceed `TotalLogicalProcessors`. Note that this merely calls
@@ -58,11 +58,11 @@ static inline bool PinThreadToLogicalProcessor(size_t lp) {
// provided by the hardware clamped to `kMaxLogicalProcessors`.
// These processors are not necessarily all usable; you can determine which are
// via GetThreadAffinity().
-HWY_DLLEXPORT size_t TotalLogicalProcessors();
+HWY_CONTRIB_DLLEXPORT size_t TotalLogicalProcessors();

struct Topology {
// Caller must check packages.empty(); if so, do not use any fields.
- HWY_DLLEXPORT Topology();
+ HWY_CONTRIB_DLLEXPORT Topology();

// Clique of cores with lower latency to each other. On Apple M1 these are
// four cores sharing an L2. On Zen4 these 'CCX' are up to eight cores sharing
10 changes: 10 additions & 0 deletions ExampleDependencies/src/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# To learn more about .editorconfig see https://aka.ms/editorconfigdocs
root = true

# All files
[*]
indent_style = space

# Cpp files
[*.{h,cpp}]
indent_size = 4
Loading

0 comments on commit 8805308

Please sign in to comment.