diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6173cf96a..8f7d0bdc1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -34,7 +34,7 @@ jobs: cmake --build build --config Debug - name: Produce install artifacts run: | - cmake --install build --prefix install --config Debug + cmake --install build --prefix pkg --config Debug - name: Run tests run: | ctest --output-on-failure -C Debug --test-dir build @@ -64,7 +64,7 @@ jobs: cmake --build build --config Release - name: Produce install artifacts run: | - cmake --install build --prefix install --config Release + cmake --install build --prefix pkg --config Release - name: Run tests run: | ctest --output-on-failure -C Release --test-dir build @@ -115,7 +115,7 @@ jobs: cat build/.ninja_log - name: Produce install artifacts run: | - cmake --install build --prefix install --config Debug + cmake --install build --prefix pkg --config Debug - name: Start Xvfb run: | Xvfb :99 -screen 0 1024x768x24 & @@ -170,7 +170,7 @@ jobs: cat build/.ninja_log - name: Produce install artifacts run: | - cmake --install build --prefix install --config Release + cmake --install build --prefix pkg --config Release - name: Start Xvfb run: | Xvfb :99 -screen 0 1024x768x24 & @@ -225,7 +225,7 @@ jobs: cat build/.ninja_log - name: Produce install artifacts run: | - cmake --install build --prefix install --config Debug + cmake --install build --prefix pkg --config Debug - name: Start Xvfb run: | Xvfb :99 -screen 0 1024x768x24 & @@ -280,7 +280,7 @@ jobs: cat build/.ninja_log - name: Produce install artifacts run: | - cmake --install build --prefix install --config Release + cmake --install build --prefix pkg --config Release - name: Start Xvfb run: | Xvfb :99 -screen 0 1024x768x24 & @@ -335,7 +335,10 @@ jobs: cat build/.ninja_log - name: Produce install artifacts run: | - cmake --install build --prefix install --config Debug + cmake --install build --prefix pkg --config Debug + - name: Put files in app bundle + run: | + scripts/deploy_mac_bundle_presubmit.sh - name: Run tests run: | ctest --output-on-failure -C Debug --test-dir build @@ -389,7 +392,10 @@ jobs: cat build/.ninja_log - name: Produce install artifacts run: | - cmake --install build --prefix install --config Release + cmake --install build --prefix pkg --config Release + - name: Put files in app bundle + run: | + scripts/deploy_mac_bundle_presubmit.sh - name: Run tests run: | ctest --output-on-failure -C Release --test-dir build @@ -452,4 +458,4 @@ jobs: cat build_android/.ninja_log - name: Produce install artifacts run: | - cmake --install build_android --prefix install --config Debug + cmake --install build_android --prefix pkg --config Debug diff --git a/.github/workflows/presubmit.yml b/.github/workflows/presubmit.yml index 088abdead..9a1078644 100644 --- a/.github/workflows/presubmit.yml +++ b/.github/workflows/presubmit.yml @@ -37,6 +37,9 @@ jobs: - name: Build Dive host tools with VS 2022 run: | cmake --build build --config Debug + - name: Produce install artifacts + run: | + cmake --install build --prefix pkg --config Debug - name: Run tests run: | ctest --output-on-failure -C Debug --test-dir build @@ -64,6 +67,9 @@ jobs: - name: Build Dive host tools with VS 2022 run: | cmake --build build --config Release + - name: Produce install artifacts + run: | + cmake --install build --prefix pkg --config Release - name: Run tests run: | ctest --output-on-failure -C Release --test-dir build @@ -119,7 +125,7 @@ jobs: cat build/.ninja_log - name: Produce install artifacts run: | - cmake --install build --prefix install --config Debug + cmake --install build --prefix pkg --config Debug - name: Start Xvfb run: | Xvfb :99 -screen 0 1024x768x24 & @@ -174,7 +180,7 @@ jobs: cat build/.ninja_log - name: Produce install artifacts run: | - cmake --install build --prefix install --config Release + cmake --install build --prefix pkg --config Release - name: Start Xvfb run: | Xvfb :99 -screen 0 1024x768x24 & @@ -229,7 +235,7 @@ jobs: cat build/.ninja_log - name: Produce install artifacts run: | - cmake --install build --prefix install --config Debug + cmake --install build --prefix pkg --config Debug - name: Start Xvfb run: | Xvfb :99 -screen 0 1024x768x24 & @@ -284,7 +290,7 @@ jobs: cat build/.ninja_log - name: Produce install artifacts run: | - cmake --install build --prefix install --config Release + cmake --install build --prefix pkg --config Release - name: Start Xvfb run: | Xvfb :99 -screen 0 1024x768x24 & @@ -351,7 +357,10 @@ jobs: cat build/.ninja_log - name: Produce install artifacts run: | - cmake --install build --prefix install --config Debug + cmake --install build --prefix pkg --config Debug + - name: Put files in app bundle + run: | + scripts/deploy_mac_bundle_presubmit.sh - name: Run tests run: | ctest --output-on-failure -C Debug --test-dir build @@ -407,7 +416,10 @@ jobs: cat build/.ninja_log - name: Produce install artifacts run: | - cmake --install build --prefix install --config Release + cmake --install build --prefix pkg --config Release + - name: Put files in app bundle + run: | + scripts/deploy_mac_bundle_presubmit.sh - name: Run tests run: | ctest --output-on-failure -C Release --test-dir build @@ -471,4 +483,4 @@ jobs: cat build_android/.ninja_log - name: Produce install artifacts run: | - cmake --install build_android --prefix install --config Debug + cmake --install build_android --prefix pkg --config Debug diff --git a/.gitignore b/.gitignore index b6ba41e60..4f433a08c 100644 --- a/.gitignore +++ b/.gitignore @@ -12,11 +12,13 @@ /.cache/ # Build-related directories +# TODO: b/462767957 - Move build_android/ and pkg/ contents to under the unified build dir build/ build_android/ third_party/freedreno/libs/ third_party/freedreno/obj .gradle/ +pkg/ # Amdvlk auto-generated files *.pyc g_*.h @@ -24,7 +26,6 @@ g_*.cpp .env -install/ gfxr_capture/ gfxr_capture_*/ **/.DS_Store diff --git a/BUILD.md b/BUILD.md index 7d214eed3..93df696ad 100644 --- a/BUILD.md +++ b/BUILD.md @@ -83,7 +83,7 @@ set DIVE_ROOT_PATH=C:\path\to\dive You can specify the build type for release as well by replacing "Debug" with "Release" or "RelWithDebInfo" instead. 1. Install (the prefix must be coordinated with that of the [device resources](#dive-device-resources)) ```sh - cmake --install build --prefix install --config Debug + cmake --install build --prefix pkg --config Debug ``` If you want to build a GFXR tool like `gfxrecon-convert`: @@ -113,7 +113,7 @@ cmake --build build --target gfxrecon-convert with `--config=` instead. 1. Install (the prefix must be coordinated with that of the [device resources](#dive-device-resources)) ```bat - cmake --install build --prefix install --config Debug + cmake --install build --prefix pkg --config Debug ``` If you want to build a GFXR tool like `gfxrecon-convert`: @@ -124,80 +124,31 @@ cmake --build build --target gfxrecon-convert ## Dive Device Resources -Warning: We only support "Debug" for the gradle build for GFXR portion, so it will be hardcoded and not depend on the build type chosen below. +Warning: We only support "Debug" for the gradle build for GFXR portion, so it will be hardcoded and not depend on the build type specified in the script. -Provide the appropriate `ANDROID_ABI` depending on your device. +Modify the script if necessary to provide the appropriate `ANDROID_ABI` depending on your device. ### Linux -1. Configure - ```sh - cd $DIVE_ROOT_PATH - - rm -rf build_android - - cmake . -DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK_HOME}/build/cmake/android.toolchain.cmake \ - -G "Ninja Multi-Config" \ - -Bbuild_android \ - -DCMAKE_MAKE_PROGRAM="ninja" \ - -DCMAKE_SYSTEM_NAME=Android \ - -DANDROID_ABI=arm64-v8a \ - -DANDROID_PLATFORM=android-26 \ - -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=NEVER \ - -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=NEVER - ``` -1. Build with one of the following methods: - * Build directly with ninja - ```sh - ninja -C build_android -f build-Debug.ninja - ``` - * Build using cmake - ```sh - cmake --build build_android --config=Debug - ``` - You can specify the build type for release as well by replacing "Debug" with "Release" or "RelWithDebInfo" instead. -1. Install (the prefix must be coordinated with that of the [host tools](#dive-host-tools)) - ```sh - cmake --install build_android --prefix install --config Debug - ``` +Running the script `scripts/build_android.sh` will build and install the device resources at `$DIVE_ROOT_PATH/pkg/device`. ### Windows -Run the following in the Visual Studio Developer Command Prompt for VS 2022 (or 2019) - -1. Configure - ```bat - cd %DIVE_ROOT_PATH% - - rmdir /s build_android - - cmake . -DCMAKE_TOOLCHAIN_FILE=%ANDROID_NDK_HOME%/build/cmake/android.toolchain.cmake ^ - -G "Ninja Multi-Config" ^ - -Bbuild_android ^ - -DCMAKE_MAKE_PROGRAM="ninja" ^ - -DCMAKE_SYSTEM_NAME=Android ^ - -DANDROID_ABI=arm64-v8a ^ - -DANDROID_PLATFORM=android-26 ^ - -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=NEVER ^ - -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=NEVER - ``` -1. Build with one of the following methods: - * Build directly with ninja - ```bat - ninja -C build_android -f build-Debug.ninja - ``` - * Build using cmake - ```bat - cmake --build build_android --config=Debug - ``` -1. Install (the prefix must be coordinated with that of the [host tools](#dive-host-tools)) - ```bat - cmake --install build_android --prefix install --config Debug - ``` +In the Visual Studio Developer Command Prompt for VS 2022 (or 2019), running the script `scripts\build_android.bat` will build and install the device resources at `$DIVE_ROOT_PATH\pkg\device`. ### Troubleshooting Tips * Gradle build * Open the gradle project at `third_party/gfxreconstruct/android` in Android Studio and try making recommended changes to the project and building from there. * Delete GFXR build folders for a clean build + * `third_party/gfxreconstruct/android/layer/.cxx` * `third_party/gfxreconstruct/android/layer/build` - * `third_party/gfxreconstruct/android/tools/replay/build` \ No newline at end of file + * `third_party/gfxreconstruct/android/tools/replay/.cxx` + * `third_party/gfxreconstruct/android/tools/replay/build` + +## App bundle (macOS) + +After building the host tools and the device resources as outlined above and installing them, additional steps are required to make a self-contained macOS application bundle from the contents of the `pkg/` directory. + +All external plugin folders must be placed under `$DIVE_ROOT_PATH/pkg/plugins` to be properly added to the bundle. + +Running the script `scripts/deploy_mac_bundle.sh` will create the mac package and place it at `$DIVE_ROOT_PATH/pkg/dive.app`. diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c1eb44c6..a707454c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,8 +38,6 @@ if(MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") endif() set(THIRDPARTY_DIRECTORY "${CMAKE_SOURCE_DIR}/third_party") -# TODO: b/462767957 - remove set(CMAKE_INSTALL_PREFIX ...) once we fix search path and mac build. -set(CMAKE_INSTALL_PREFIX "${CMAKE_SOURCE_DIR}/install") option(DIVE_BUILD_WITH_CRASHPAD "Build Dive with CrashPad" ON) # Add an option to allow users to easily toggle the runtime layer build @@ -52,9 +50,18 @@ option( option(DIVE_BUILD_WITH_SANITIZER "Build Dive with sanitizers" OFF) # Placeholder value for DESTINATION to override cmake default. -# e.g. install(TARGETS target_name DESTINATION "${DIVE_INSTALL_DESTINATION}") -set(DIVE_INSTALL_DESTINATION ".") -set(DIVE_PLUGINS_INSTALL_DESTINATION "plugins") +# These are all relative to the install destination prefix which is recommended as "pkg/" +# e.g. install(TARGETS target_name DESTINATION "${DIVE_INSTALL_DEST_*}") +set(DIVE_INSTALL_DEST_HOST "host") # Should only be used as destination for host builds +set(DIVE_INSTALL_DEST_DEVICE "device") # Should only be used as destination for device builds +# Plugins folders +set(DIVE_PLUGINS_PARENT_DIR "plugins") +set(DIVE_INSTALL_DEST_SAMPLE_PLUGIN "dive_sample_plugin") +set(DIVE_PROFILING_PLUGIN_DIR "dive_profiling_plugin") # This is not built within Dive +# macOS bundle +set(DIVE_MACOS_BUNDLE_RESOURCES "Resources") +# License file +set(DIVE_LICENSE_FILE_NAME "NOTICE") # Disable gtest for install set(INSTALL_GTEST OFF) @@ -108,7 +115,7 @@ if(ANDROID) install( FILES ${CMAKE_CURRENT_BINARY_DIR}/bin/$/${DEVICE_RESOURCES_VERSION_FILENAME} - DESTINATION ${DIVE_INSTALL_DESTINATION} + DESTINATION ${DIVE_INSTALL_DEST_DEVICE} ) list(POP_BACK CMAKE_MESSAGE_INDENT) message(CHECK_PASS "done") @@ -182,7 +189,7 @@ else() list(APPEND CMAKE_MESSAGE_INDENT " ") # Currently hardcoding debug build, unknown reason add_subdirectory(third_party/freedreno EXCLUDE_FROM_ALL) - install(TARGETS wrap DESTINATION "${DIVE_INSTALL_DESTINATION}") + install(TARGETS wrap DESTINATION "${DIVE_INSTALL_DEST_DEVICE}") list(POP_BACK CMAKE_MESSAGE_INDENT) message(CHECK_PASS "done") @@ -282,18 +289,18 @@ if(ANDROID) install( FILES ${CMAKE_BINARY_DIR}/gfxr_layer/jni/${ANDROID_ABI}/libVkLayer_gfxreconstruct.so - DESTINATION "${DIVE_INSTALL_DESTINATION}" + DESTINATION "${DIVE_INSTALL_DEST_DEVICE}" ) install( FILES ${CMAKE_CURRENT_SOURCE_DIR}/third_party/gfxreconstruct/android/tools/replay/build/outputs/apk/debug/replay-debug.apk - DESTINATION "${DIVE_INSTALL_DESTINATION}" + DESTINATION "${DIVE_INSTALL_DEST_DEVICE}" RENAME "gfxr-replay.apk" ) install( FILES ${CMAKE_CURRENT_SOURCE_DIR}/third_party/gfxreconstruct/android/scripts/gfxrecon.py - DESTINATION "${DIVE_INSTALL_DESTINATION}" + DESTINATION "${DIVE_INSTALL_DEST_DEVICE}" ) list(POP_BACK CMAKE_MESSAGE_INDENT) message(CHECK_PASS "done") @@ -320,12 +327,14 @@ if(NOT ANDROID) # MacOS has limited thread stack size, allocating large object in stack makes its stack overflow # This has been fixed in https://github.com/google/dive/pull/541 - if(APPLE) + if(CMAKE_HOST_APPLE) set(DIVE_EXECUTABLE_PATH - ${CMAKE_BINARY_DIR}/ui/$/dive.app/Contents/MacOS/dive + ${CMAKE_CURRENT_SOURCE_DIR}/pkg/dive.app/Contents/MacOS/dive ) + elseif(CMAKE_HOST_WIN32) + set(DIVE_EXECUTABLE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/pkg/host/dive.exe) else() - set(DIVE_EXECUTABLE_PATH ${CMAKE_BINARY_DIR}/ui/dive) + set(DIVE_EXECUTABLE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/pkg/host/dive) endif() set(DIVE_TEST_TRACE_DIR ${PROJECT_SOURCE_DIR}/tests/gfxr_traces) set(DIVE_TEST_TRACE diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2d7674176..7db3046f0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -67,6 +67,14 @@ for this purpose. - "Update with rebase" only when the branch is out-of-date. This ensures a linear history in case "Rebase and merge" is used to submit a PR. - Add a comment to the PR describing what manual tests were performed by the contributor. +### Unit and regression tests +```sh +cd $DIVE_ROOT_PATH +ctest -C Debug --test-dir build +``` + +Make sure to have built everything according to BUILD.md (don't forget the install step) before running the tests. + ## Updating Dive's gfxreconstruct subtree 1. Create a branch to contain the merge. diff --git a/capture_service/CMakeLists.txt b/capture_service/CMakeLists.txt index e47600ae2..314a86870 100644 --- a/capture_service/CMakeLists.txt +++ b/capture_service/CMakeLists.txt @@ -78,7 +78,9 @@ else() absl::strings absl::statusor component_files + dive_build_defs dive_device_resources + dive_src_includes version_info command_utils ) @@ -100,7 +102,7 @@ else() PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/.. ) - install(TARGETS dive_client_cli DESTINATION "${DIVE_INSTALL_DESTINATION}") + install(TARGETS dive_client_cli DESTINATION "${DIVE_INSTALL_DEST_HOST}") enable_testing() include(GoogleTest) diff --git a/capture_service/device_mgr.cc b/capture_service/device_mgr.cc index 7c274d5bb..6813ec8af 100644 --- a/capture_service/device_mgr.cc +++ b/capture_service/device_mgr.cc @@ -857,8 +857,8 @@ absl::Status DeviceManager::DeployReplayApk(const std::string& serial) std::filesystem::path local_replay_apk_path; { - absl::StatusOr ret = - Dive::ResolveResourcesLocalPath(Dive::DeviceResourcesConstants::kGfxrReplayApkName); + absl::StatusOr ret = Dive::ResolveDeviceResourcesLocalPath( + Dive::DeviceResourcesConstants::kGfxrReplayApkName); if (!ret.ok()) { return ret.status(); @@ -868,7 +868,7 @@ absl::Status DeviceManager::DeployReplayApk(const std::string& serial) std::filesystem::path local_recon_py_path; { absl::StatusOr ret = - Dive::ResolveResourcesLocalPath(Dive::DeviceResourcesConstants::kGfxrReconPyName); + Dive::ResolveDeviceResourcesLocalPath(Dive::DeviceResourcesConstants::kGfxrReconPyName); if (!ret.ok()) { return ret.status(); @@ -985,7 +985,7 @@ absl::Status DeviceManager::RunReplayGfxrScript(const GfxrReplaySettings& settin std::filesystem::path local_recon_py_path; { absl::StatusOr ret = - Dive::ResolveResourcesLocalPath(Dive::DeviceResourcesConstants::kGfxrReconPyName); + Dive::ResolveDeviceResourcesLocalPath(Dive::DeviceResourcesConstants::kGfxrReconPyName); if (!ret.ok()) { return ret.status(); @@ -1077,20 +1077,20 @@ absl::Status DeviceManager::RunReplayProfilingBinary(const GfxrReplaySettings& s LOGD("RunReplayProfilingBinary(): SETUP\n"); LOGD("RunReplayProfilingBinary(): Deploy libraries and binaries\n"); - RETURN_IF_ERROR( - m_device->DeployDeviceResource(Dive::DeviceResourcesConstants::kProfilingPluginFolderName)); - std::string remote_profiling_dir = - absl::StrFormat("%s/%s", Dive::DeviceResourcesConstants::kDeployFolderPath, - Dive::DeviceResourcesConstants::kProfilingPluginFolderName); + absl::StatusOr remote_profiling_dir = m_device->DeployProfilingPluginDir(); + if (!remote_profiling_dir.ok()) + { + return remote_profiling_dir.status(); + } absl::Cleanup cleanup([&]() { LOGD("RunReplayProfilingBinary(): CLEANUP\n"); - std::string clean_cmd = absl::StrFormat("shell rm -rf -- %s", remote_profiling_dir); + std::string clean_cmd = absl::StrFormat("shell rm -rf -- %s", *remote_profiling_dir); adb.Run(clean_cmd).IgnoreError(); }); std::string binary_path_on_device = - absl::StrFormat("%s/%s", remote_profiling_dir, kProfilingPluginName); + absl::StrFormat("%s/%s", *remote_profiling_dir, kProfilingPluginName); RETURN_IF_ERROR(adb.Run(absl::StrCat("shell chmod +x ", binary_path_on_device))); LOGD("RunReplayProfilingBinary(): RUN\n"); @@ -1385,12 +1385,31 @@ absl::Status AndroidDevice::TriggerScreenCapture( return ret; } +absl::StatusOr AndroidDevice::DeployProfilingPluginDir( + const std::filesystem::path& target_dir) +{ + absl::StatusOr local_profiling_dir_path = + Dive::ResolveProfilingResourcesLocalPath("."); + if (!local_profiling_dir_path.ok()) + { + return local_profiling_dir_path.status(); + } + + RETURN_IF_ERROR(m_adb.Run(absl::StrFormat(R"(shell mkdir -p '%s')", target_dir))); + + RETURN_IF_ERROR(m_adb.Run(absl::StrFormat( + R"(push "%s" "%s")", local_profiling_dir_path->generic_string(), target_dir))); + + return absl::StrFormat("%s/%s", target_dir, Dive::GetProfilingDirName()); +} + absl::Status AndroidDevice::DeployDeviceResource(const std::string_view& file_name, const std::filesystem::path& target_dir) { std::filesystem::path host_full_lib_path; { - absl::StatusOr ret = Dive::ResolveResourcesLocalPath(file_name); + absl::StatusOr ret = + Dive::ResolveDeviceResourcesLocalPath(file_name); if (!ret.ok()) { return ret.status(); diff --git a/capture_service/device_mgr.h b/capture_service/device_mgr.h index ffa0a7968..432384d90 100644 --- a/capture_service/device_mgr.h +++ b/capture_service/device_mgr.h @@ -179,6 +179,12 @@ class AndroidDevice // Triggers a screenshot and saves it to the specified path. absl::Status TriggerScreenCapture(const std::filesystem::path& on_device_screenshot_dir) const; + // Verifies that profiling plugin dir exists locally before deploying to target_dir. Returns + // on-device path + absl::StatusOr DeployProfilingPluginDir( + const std::filesystem::path& target_dir = + Dive::DeviceResourcesConstants::kDeployFolderPath); + // Verifies that file_name exists locally inside the device resources folder before deploying to // target_dir absl::Status DeployDeviceResource(const std::string_view& file_name, diff --git a/layer/CMakeLists.txt b/layer/CMakeLists.txt index 15c8423da..3979b990f 100644 --- a/layer/CMakeLists.txt +++ b/layer/CMakeLists.txt @@ -95,10 +95,10 @@ configure_file( "${CMAKE_BINARY_DIR}/bin/VkLayer_dive_capture.json" COPYONLY ) -install(TARGETS ${target_name} DESTINATION "${DIVE_INSTALL_DESTINATION}") +install(TARGETS ${target_name} DESTINATION "${DIVE_INSTALL_DEST_DEVICE}") install( FILES "${CMAKE_CURRENT_SOURCE_DIR}/manifest/XrApiLayer_dive.json" - DESTINATION "${DIVE_INSTALL_DESTINATION}" + DESTINATION "${DIVE_INSTALL_DEST_DEVICE}" ) set(target_name XrApiLayer_dive) @@ -125,10 +125,10 @@ if($) endif() target_link_libraries(${target_name} ${TARGET_LINK_LIBS}) -install(TARGETS ${target_name} DESTINATION "${DIVE_INSTALL_DESTINATION}") +install(TARGETS ${target_name} DESTINATION "${DIVE_INSTALL_DEST_DEVICE}") install( FILES "${CMAKE_CURRENT_SOURCE_DIR}/manifest/XrApiLayer_dive.json" - DESTINATION "${DIVE_INSTALL_DESTINATION}" + DESTINATION "${DIVE_INSTALL_DEST_DEVICE}" ) list(POP_BACK CMAKE_MESSAGE_INDENT) diff --git a/plugins/plugin_sample/CMakeLists.txt b/plugins/plugin_sample/CMakeLists.txt index ea1b5f845..3e9a433c2 100644 --- a/plugins/plugin_sample/CMakeLists.txt +++ b/plugins/plugin_sample/CMakeLists.txt @@ -28,23 +28,6 @@ target_link_libraries( set_property(TARGET dive_plugin_sample PROPERTY AUTOMOC ON) -# Set the output directory for the plugin. -# We want it to go into a 'plugins' subdirectory alongside the dive_ui executable. -set_target_properties( - dive_plugin_sample - PROPERTIES - LIBRARY_OUTPUT_DIRECTORY "$/plugins" - RUNTIME_OUTPUT_DIRECTORY - "$/plugins" # For DLLs on Windows - # On MSVC, ensure the `CreateDivePluginInstance` function is exported. - # For GCC/Clang, DIVE_PLUGIN_EXPORT handles this. - # Set a DEFINE_FILE for MSVC to automatically generate exports. - CXX_EXTENSIONS ON - GENERATOR_EXPRESSIONS - $<$:"$.def"> - FOLDER "plugins" -) - target_include_directories( dive_plugin_sample PRIVATE @@ -54,9 +37,7 @@ target_include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/.. ) -# Install the plugin to the 'plugins' subdirectory within the installation prefix's bin directory. -# This ensures that when Dive is installed, its plugins are correctly placed. install( TARGETS dive_plugin_sample - DESTINATION "${DIVE_PLUGINS_INSTALL_DESTINATION}" + DESTINATION "${DIVE_PLUGINS_PARENT_DIR}/${DIVE_INSTALL_DEST_SAMPLE_PLUGIN}" ) diff --git a/runtime_layer/CMakeLists.txt b/runtime_layer/CMakeLists.txt index 035dbf1e3..00ecec37b 100644 --- a/runtime_layer/CMakeLists.txt +++ b/runtime_layer/CMakeLists.txt @@ -71,7 +71,11 @@ set_target_properties( PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/" ) -install(TARGETS ${target_name} DESTINATION "${DIVE_INSTALL_DESTINATION}") +if(ANDROID) + install(TARGETS ${target_name} DESTINATION "${DIVE_INSTALL_DEST_DEVICE}") +else() + install(TARGETS ${target_name} DESTINATION "${DIVE_INSTALL_DEST_HOST}") +endif() list(POP_BACK CMAKE_MESSAGE_INDENT) message(CHECK_PASS "done") diff --git a/scripts/build_android.bat b/scripts/build_android.bat index df45fccf3..cd3c63a49 100644 --- a/scripts/build_android.bat +++ b/scripts/build_android.bat @@ -12,7 +12,7 @@ :: See the License for the specific language governing permissions and :: limitations under the License. -:: This script automates the standard build process. For comprehensive documentation and advanced options, please refer to BUILD.md, "Dive Device Libraries" section +:: This script automates the standard build process for Dive Device Libraries @echo off setlocal enabledelayedexpansion @@ -53,7 +53,7 @@ if not !ERRORLEVEL!==0 exit /b 1 cmake --build build_android --config=!build! if not !ERRORLEVEL!==0 exit /b 1 - cmake --install build_android --prefix install --config=!build! + cmake --install build_android --prefix pkg --config=!build! if not !ERRORLEVEL!==0 exit /b 1 )) diff --git a/scripts/build_android.sh b/scripts/build_android.sh index 8499d6b9d..401006219 100755 --- a/scripts/build_android.sh +++ b/scripts/build_android.sh @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -# This script automates the standard build process. For comprehensive documentation and advanced options, please refer to BUILD.md, "Dive Device Resources" section +# This script automates the standard build process for Dive Device Libraries PROJECT_ROOT="$(readlink -f $0)" PROJECT_ROOT="${PROJECT_ROOT%/*}/.." @@ -52,7 +52,7 @@ for build in "${BUILD_TYPE}" do cmake --build build_android --config=${build} || exit 1 - cmake --install build_android --prefix install --config=${build} || exit 1 + cmake --install build_android --prefix pkg --config=${build} || exit 1 done popd diff --git a/scripts/deploy_mac_bundle.sh b/scripts/deploy_mac_bundle.sh new file mode 100755 index 000000000..3df1d95aa --- /dev/null +++ b/scripts/deploy_mac_bundle.sh @@ -0,0 +1,76 @@ +#!/bin/bash + +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This script automates the deployment of the Dive app bundle on macOS. + +set -euo pipefail +readonly PROJECT_ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." >/dev/null 2>&1 && pwd )" +readonly INSTALL_DIR="pkg" +SIGN_BUNDLE=true +readonly START_TIME="$(date +%r)" + +if [ $# -ne 0 ]; then + if [ $# -ne 1 ]; then + echo "Too many arguments" + echo "Valid usage: 'deploy_mac_bundle.sh [--no-sign]'" + exit 1 + fi + if [ "$1" = "--no-sign" ]; then + SIGN_BUNDLE=false + else + echo "Invalid parameter: $1" + echo "Valid usage: 'deploy_mac_bundle.sh [--no-sign]'" + exit 1 + fi +fi + +echo "Install dir: ${INSTALL_DIR}" + +pushd ${PROJECT_ROOT} + +echo "current dir $(pwd)" + +if [ ! -d ${INSTALL_DIR}/dive.app ]; then + echo . + echo "Moving over dive.app and running macdeployqt" + + mv ${INSTALL_DIR}/host/dive.app ${INSTALL_DIR} + macdeployqt ${INSTALL_DIR}/dive.app +else + echo . + echo "Skipping moving dive.app and running macdeployqt" +fi + +echo "Copying resources into app bundle" +cp -r ${INSTALL_DIR}/device/* ${INSTALL_DIR}/dive.app/Contents/Resources/ +cp -r ${INSTALL_DIR}/host/* ${INSTALL_DIR}/dive.app/Contents/MacOS/ +mkdir -p ${INSTALL_DIR}/dive.app/Contents/Resources/plugins/ +cp -r ${INSTALL_DIR}/plugins/* ${INSTALL_DIR}/dive.app/Contents/Resources/plugins/ + +if ${SIGN_BUNDLE}; then + echo . + echo "Ad-hoc signing the application bundle" + codesign --force --deep --sign - ${INSTALL_DIR}/dive.app +else + echo . + echo "Skipping signing step" +fi + +popd + +echo . +echo "Start Time: ${START_TIME}" +echo "Finish Time: $(date +%r)" diff --git a/scripts/deploy_mac_bundle_presubmit.sh b/scripts/deploy_mac_bundle_presubmit.sh new file mode 100755 index 000000000..a7429d162 --- /dev/null +++ b/scripts/deploy_mac_bundle_presubmit.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This script is used by Github workflows to create the app bundle on macOS runners, since the presubmit folder structure is different from dev builds. + +set -euo pipefail + +mv ./pkg/host/dive.app ./pkg/ +macdeployqt ./pkg/dive.app +cp -r ./pkg/host/* ./pkg/dive.app/Contents/MacOS/ +mkdir -p ./pkg/dive.app/Contents/Resources/plugins/ \ No newline at end of file diff --git a/src/dive/build_defs/dive_cmake_generated.h.in b/src/dive/build_defs/dive_cmake_generated.h.in index 5fd120969..135f82a34 100644 --- a/src/dive/build_defs/dive_cmake_generated.h.in +++ b/src/dive/build_defs/dive_cmake_generated.h.in @@ -28,7 +28,12 @@ limitations under the License. // clang-format on #define CMAKE_GENERATED_HOST_PLATFORM "@HOST_PLATFORM_STRING@" -#define CMAKE_GENERATED_INSTALL_DIR_PATH "@CMAKE_INSTALL_PREFIX@" #define CMAKE_GENERATED_BUILD_TYPE "$" #define CMAKE_GENERATED_RELEASE_TYPE "@DIVE_RELEASE_TYPE@" #define CMAKE_GENERATED_DEVICE_RESOURCES_VERSION_FILENAME "@DEVICE_RESOURCES_VERSION_FILENAME@" +#define CMAKE_GENERATED_PLUGINS_PARENT_DIR "@DIVE_PLUGINS_PARENT_DIR@" +#define CMAKE_GENERATED_PROFILING_PLUGIN_DIR "@DIVE_PROFILING_PLUGIN_DIR@" +#define CMAKE_GENERATED_INSTALL_DEST_DEVICE "@DIVE_INSTALL_DEST_DEVICE@" +#define CMAKE_GENERATED_INSTALL_DEST_HOST "@DIVE_INSTALL_DEST_HOST@" +#define CMAKE_GENERATED_DIVE_MACOS_BUNDLE_RESOURCES "@DIVE_MACOS_BUNDLE_RESOURCES@" +#define CMAKE_GENERATED_DIVE_LICENSE_FILE_NAME "@DIVE_LICENSE_FILE_NAME@" diff --git a/src/dive/build_defs/version_defs.h b/src/dive/build_defs/version_defs.h index cae59fa90..6100b2035 100644 --- a/src/dive/build_defs/version_defs.h +++ b/src/dive/build_defs/version_defs.h @@ -37,8 +37,3 @@ limitations under the License. #define DIVE_BUILD_TYPE CMAKE_GENERATED_BUILD_TYPE // (dev|release|internal|canary) #define DIVE_RELEASE_TYPE CMAKE_GENERATED_RELEASE_TYPE -// This is the location of the device resources folder -// TODO(b/462767957): Remove build_defs DIVE_INSTALL_DIR_PATH -#define DIVE_INSTALL_DIR_PATH CMAKE_GENERATED_INSTALL_DIR_PATH -// This is relative to the device resources folder -#define DIVE_DEVICE_RESOURCES_VERSION_FILENAME CMAKE_GENERATED_DEVICE_RESOURCES_VERSION_FILENAME diff --git a/src/dive/plugin/loader/CMakeLists.txt b/src/dive/plugin/loader/CMakeLists.txt index bbfd34e73..48bcbef59 100644 --- a/src/dive/plugin/loader/CMakeLists.txt +++ b/src/dive/plugin/loader/CMakeLists.txt @@ -62,7 +62,12 @@ endif() target_link_libraries( dive_plugin_loader - PRIVATE absl::status absl::statusor absl::strings dive_src_includes + PRIVATE + absl::status + absl::statusor + absl::strings + dive_src_includes + dive_device_resources ) list(POP_BACK CMAKE_MESSAGE_INDENT) diff --git a/src/dive/plugin/loader/plugin_loader.cpp b/src/dive/plugin/loader/plugin_loader.cpp index c2944f7b5..6142284d0 100644 --- a/src/dive/plugin/loader/plugin_loader.cpp +++ b/src/dive/plugin/loader/plugin_loader.cpp @@ -20,6 +20,7 @@ #include #include "absl/strings/str_cat.h" +#include "dive/utils/device_resources.h" namespace Dive { @@ -75,7 +76,7 @@ PluginLoader::PluginLoader() : m_library_loader(CreateDynamicLibraryLoader()) {} PluginLoader::~PluginLoader() { UnloadPlugins(); } -absl::Status PluginLoader::LoadPlugins(const std::filesystem::path& plugins_dir_path) +absl::Status PluginLoader::LoadPlugins() { std::string error_message; @@ -83,13 +84,13 @@ absl::Status PluginLoader::LoadPlugins(const std::filesystem::path& plugins_dir_ absl::StrAppend(&error_message, "PluginLoader: ", msg, "\n"); }; - if (!std::filesystem::exists(plugins_dir_path) || - !std::filesystem::is_directory(plugins_dir_path)) + absl::StatusOr plugins_dir_path = ResolvePluginsDir(); + if (!plugins_dir_path.ok()) { - return absl::NotFoundError("Plugin directory not found: " + plugins_dir_path.string()); + return plugins_dir_path.status(); } - for (const auto& entry : std::filesystem::directory_iterator(plugins_dir_path)) + for (const auto& entry : std::filesystem::directory_iterator(*plugins_dir_path)) { if (!entry.is_regular_file()) { diff --git a/src/dive/plugin/loader/plugin_loader.h b/src/dive/plugin/loader/plugin_loader.h index 2680502f5..69033a0e5 100644 --- a/src/dive/plugin/loader/plugin_loader.h +++ b/src/dive/plugin/loader/plugin_loader.h @@ -57,7 +57,7 @@ class PluginLoader PluginLoader(const PluginLoader&) = delete; PluginLoader& operator=(const PluginLoader&) = delete; - absl::Status LoadPlugins(const std::filesystem::path& plugin_directory_path); + absl::Status LoadPlugins(); void UnloadPlugins(); const DivePluginBridge& Bridge() const { return m_bridge; } diff --git a/src/dive/utils/CMakeLists.txt b/src/dive/utils/CMakeLists.txt index c1256a3ce..2d4fcf40d 100644 --- a/src/dive/utils/CMakeLists.txt +++ b/src/dive/utils/CMakeLists.txt @@ -34,7 +34,13 @@ if(NOT ANDROID) target_link_libraries( dive_device_resources PUBLIC absl::statusor - PRIVATE absl::strings dive_build_defs dive_src_includes command_utils + PRIVATE + absl::span + absl::strings + dive_build_defs + dive_src_includes + dive_status + command_utils ) endif() diff --git a/src/dive/utils/device_resources.cpp b/src/dive/utils/device_resources.cpp index 7994283b2..70c234021 100644 --- a/src/dive/utils/device_resources.cpp +++ b/src/dive/utils/device_resources.cpp @@ -13,79 +13,148 @@ #include "dive/utils/device_resources.h" +#include #include +#include #include "absl/status/statusor.h" #include "absl/strings/str_format.h" #include "absl/strings/str_join.h" -#include "dive/build_defs/version_defs.h" +#include "absl/types/span.h" +#include "dive/build_defs/dive_cmake_generated.h" +#include "dive/common/status.h" #include "dive/os/command_utils.h" -namespace Dive +namespace { -// Returns possible locations for the device resources folder on the host machine -absl::StatusOr> GetPotentialDeviceResourcesDirs() +// search_paths are relative to the executable dir +absl::StatusOr ResolvePath( + absl::Span search_paths, std::filesystem::path relative_file_path) { - std::vector search_paths; + assert(!search_paths.empty()); - absl::StatusOr ret = Dive::GetExecutableDirectory(); - if (!ret.ok()) + absl::StatusOr exec_dir = Dive::GetExecutableDirectory(); + if (!exec_dir.ok()) { - std::string warn_msg = absl::StrFormat( - "Could not determine executable directory: %s. Search will not include " - "executable-relative paths.", - ret.status().message().data()); - return absl::NotFoundError(warn_msg); + return exec_dir.status(); } - std::filesystem::path exe_dir = *ret; - - // TODO(b/462767957): Update below based on new arrangement of device resources folder + std::vector searched_paths_strings; - // For host tools, dev build - search_paths.push_back(DIVE_INSTALL_DIR_PATH); + for (const auto& p : search_paths) + { + const auto potential_path = *exec_dir / p / relative_file_path; + if (std::filesystem::exists(potential_path)) + { + return std::filesystem::canonical(potential_path); + } + searched_paths_strings.push_back(potential_path.generic_string()); + } - // Predict location for release builds - search_paths.push_back(exe_dir / "install"); + std::string err_msg = + absl::StrFormat("Cannot find file in deployment dir: %s, searched here: \n%s", + relative_file_path, absl::StrJoin(searched_paths_strings, ", \n")); + return Dive::NotFoundError(err_msg); +} - // Apple - search_paths.push_back(exe_dir / ".." / "Resources"); +} // namespace - return search_paths; +namespace Dive +{ +std::string_view GetDeviceResourcesVersionFileName() +{ + return CMAKE_GENERATED_DEVICE_RESOURCES_VERSION_FILENAME; } -absl::StatusOr ResolveResourcesLocalPath(std::filesystem::path file_name) +std::string_view GetProfilingDirName() { return CMAKE_GENERATED_PROFILING_PLUGIN_DIR; } + +std::string_view GetLicenseFileName() { return CMAKE_GENERATED_DIVE_LICENSE_FILE_NAME; } + +absl::StatusOr ResolvePluginsDir() { - std::vector search_paths; + // Determine plugins location relative to host tool + std::filesystem::path base_dir_installed = ".."; + std::filesystem::path dive_root_dev = "../../.."; + std::array search_dirs = { + // Most platforms + base_dir_installed / CMAKE_GENERATED_PLUGINS_PARENT_DIR, + // Apple bundle + base_dir_installed / CMAKE_GENERATED_DIVE_MACOS_BUNDLE_RESOURCES / + CMAKE_GENERATED_PLUGINS_PARENT_DIR, + // For launching host tool from Windows VS debugger, assuming other parts were installed + // under pkg/ + dive_root_dev / "pkg" / CMAKE_GENERATED_PLUGINS_PARENT_DIR, + }; + + absl::StatusOr plugins_dir_path = ResolvePath(search_dirs, "."); + if (!plugins_dir_path.ok()) { - auto ret = GetPotentialDeviceResourcesDirs(); - if (!ret.ok()) - { - return ret.status(); - } - search_paths = *ret; + return plugins_dir_path.status(); + } + if (!std::filesystem::is_directory(*plugins_dir_path)) + { + return absl::NotFoundError( + absl::StrFormat("Plugins dir path not dir: %s", *plugins_dir_path)); } - std::vector searched_paths_strings; + return *plugins_dir_path; +} - assert(!search_paths.empty()); +absl::StatusOr ResolveHostResourcesLocalPath( + std::filesystem::path relative_file_path) +{ + // Host resources should be in the same dir as the caller + std::array search_dirs = { + // Most platforms + std::filesystem::path("."), + // For launching host tool from Windows VS debugger, assuming other parts were installed + // under pkg/ + std::filesystem::path("../../..") / "pkg" / CMAKE_GENERATED_INSTALL_DEST_HOST, + }; + + return ResolvePath(search_dirs, relative_file_path); +} - for (const auto& p : search_paths) - { - const auto potential_path = p / file_name; - if (std::filesystem::exists(potential_path)) - { - auto canonical_path = std::filesystem::canonical(potential_path); - return canonical_path; - } - searched_paths_strings.push_back(potential_path.generic_string()); - } +absl::StatusOr ResolveDeviceResourcesLocalPath( + std::filesystem::path relative_file_path) +{ + // Determine device resources location relative to host tool + std::filesystem::path base_dir_installed = ".."; + std::filesystem::path dive_root_dev = "../../.."; + std::array search_dirs = { + // Most platforms + base_dir_installed / CMAKE_GENERATED_INSTALL_DEST_DEVICE, + // Apple bundle + base_dir_installed / CMAKE_GENERATED_DIVE_MACOS_BUNDLE_RESOURCES, + // For launching host tool from Windows VS debugger, assuming other parts were installed + // under pkg/ + dive_root_dev / "pkg" / CMAKE_GENERATED_INSTALL_DEST_DEVICE, + }; + + return ResolvePath(search_dirs, relative_file_path); +} - std::string err_msg = - absl::StrFormat("Cannot find file in deployment dir: %s, searched here: \n%s", file_name, - absl::StrJoin(searched_paths_strings, ", \n")); - return absl::NotFoundError(err_msg); +absl::StatusOr ResolveProfilingResourcesLocalPath( + std::filesystem::path relative_file_path) +{ + // Determine profiling resources location relative to host tool + std::filesystem::path base_dir_installed = ".."; + std::filesystem::path dive_root_dev = "../../.."; + std::array search_dirs = { + // Most platforms + base_dir_installed / CMAKE_GENERATED_PLUGINS_PARENT_DIR / + CMAKE_GENERATED_PROFILING_PLUGIN_DIR, + // Apple bundle + base_dir_installed / CMAKE_GENERATED_DIVE_MACOS_BUNDLE_RESOURCES / + CMAKE_GENERATED_PLUGINS_PARENT_DIR / CMAKE_GENERATED_PROFILING_PLUGIN_DIR, + // For launching host tool from Windows VS debugger, assuming other parts were installed + // under pkg/ + dive_root_dev / "pkg" / CMAKE_GENERATED_PLUGINS_PARENT_DIR / + CMAKE_GENERATED_PROFILING_PLUGIN_DIR, + }; + + return ResolvePath(search_dirs, relative_file_path); } } // namespace Dive diff --git a/src/dive/utils/device_resources.h b/src/dive/utils/device_resources.h index 6b19862c1..4c86998c2 100644 --- a/src/dive/utils/device_resources.h +++ b/src/dive/utils/device_resources.h @@ -19,9 +19,30 @@ namespace Dive { -// Returns the full local path of relative_file_path, which represents a resource file that may be -// deployed to the device -absl::StatusOr ResolveResourcesLocalPath( +// ----------------------------------------------------------------------------- +// Wrappers so that fewer files are regenerated when dive_cmake_generated.h is, every time SHA +// changes + +std::string_view GetDeviceResourcesVersionFileName(); + +std::string_view GetProfilingDirName(); + +std::string_view GetLicenseFileName(); + +// ----------------------------------------------------------------------------- +// Returns the path of the parent dir containing plugins subdirectories +absl::StatusOr ResolvePluginsDir(); + +// Returns the full local path of relative_file_path, which represents a host resource file +absl::StatusOr ResolveHostResourcesLocalPath( + std::filesystem::path relative_file_path); + +// Returns the full local path of relative_file_path, which represents a device resource file +absl::StatusOr ResolveDeviceResourcesLocalPath( + std::filesystem::path relative_file_path); + +// Returns the full local path of relative_file_path, which represents a profiling resource file +absl::StatusOr ResolveProfilingResourcesLocalPath( std::filesystem::path relative_file_path); } // namespace Dive diff --git a/src/dive/utils/device_resources_constants.h b/src/dive/utils/device_resources_constants.h index 9ba05392d..646a57a7c 100644 --- a/src/dive/utils/device_resources_constants.h +++ b/src/dive/utils/device_resources_constants.h @@ -23,18 +23,27 @@ namespace Dive struct DeviceResourcesConstants { - // ------------------------------------------------------------------------- - // On the host machine, device resources are aggregated into a folder for - // convenience. The following paths are defined relative to that folder. - // - // Currently the device resources folder is DIVE_INSTALL_DIR_PATH (for host build) - // - // TODO(b/462767957): Remove build_defs DIVE_INSTALL_DIR_PATH and instead predict device - // resources folder location based on the executable dir + // clang-format off +/* +TODO(b/462767957): prepend "pkg/" with unified build directory "build/" + +On the host machine, resources are aggregated and installed into the "base resources dir" for convenience. + + Most platforms (dev & release) Apple bundle +------------------------------------------------------------------------------------------------ +Base resources dir: DIVE_ROOT/pkg/ dive.app/Contents/ +Host resources dir: DIVE_ROOT/pkg/CMAKE_GENERATED_INSTALL_DEST_HOST/ dive.app/Contents/MacOS/ +Device resources dir: DIVE_ROOT/pkg/CMAKE_GENERATED_INSTALL_DEST_DEVICE/ dive.app/Contents/CMAKE_GENERATED_DIVE_MACOS_BUNDLE_RESOURCES/ +Plugin parent dir: DIVE_ROOT/pkg/CMAKE_GENERATED_PLUGINS_PARENT_DIR/ dive.app/Contents/CMAKE_GENERATED_DIVE_MACOS_BUNDLE_RESOURCES/CMAKE_GENERATED_PLUGINS_PARENT_DIR/ +Profiling resources dir: DIVE_ROOT/pkg/CMAKE_GENERATED_PROFILING_PLUGIN_DIR/ dive.app/Contents/CMAKE_GENERATED_DIVE_MACOS_BUNDLE_RESOURCES/CMAKE_GENERATED_PLUGINS_PARENT_DIR/CMAKE_GENERATED_PROFILING_PLUGIN_DIR/ + +*/ + // clang-format on + + // Device resources: static constexpr std::string_view kVkLayerLibName = "libVkLayer_dive.so"; static constexpr std::string_view kXrLayerLibName = "libXrApiLayer_dive.so"; static constexpr std::string_view kManifestFileName = "XrApiLayer_dive.json"; - // third_party/freedreno static constexpr std::string_view kWrapLibName = "libwrap.so"; // third_party/Vulkan-ValidationLayers @@ -45,8 +54,7 @@ struct DeviceResourcesConstants static constexpr std::string_view kGfxrReplayApkName = "gfxr-replay.apk"; static constexpr std::string_view kGfxrReconPyName = "gfxrecon.py"; - // Profiling folder, and paths relative to it - static constexpr std::string_view kProfilingPluginFolderName = "dive_profiling_plugin"; + // Profiling plugin resources: static constexpr std::string_view kProfilingPluginShaName = "SHA"; static constexpr std::string_view kProfilingPluginMetricsFileName = "available_metrics.csv"; diff --git a/src/dive/utils/version_info.cpp b/src/dive/utils/version_info.cpp index d06ce3e61..b2f022e04 100644 --- a/src/dive/utils/version_info.cpp +++ b/src/dive/utils/version_info.cpp @@ -180,8 +180,7 @@ std::string GetLongVersionString() { std::string summary = GetHostToolsVersionInfo(); - if (auto ret = Dive::ResolveResourcesLocalPath(DIVE_DEVICE_RESOURCES_VERSION_FILENAME); - ret.ok()) + if (auto ret = ResolveDeviceResourcesLocalPath(GetDeviceResourcesVersionFileName()); ret.ok()) { std::filesystem::path device_resources_version_path = *ret; if (absl::StatusOr ret = @@ -201,10 +200,9 @@ std::string GetLongVersionString() } std::filesystem::path profiling_sha_path = - Dive::DeviceResourcesConstants::kProfilingPluginFolderName; - profiling_sha_path /= Dive::DeviceResourcesConstants::kProfilingPluginShaName; + Dive::DeviceResourcesConstants::kProfilingPluginShaName; - if (auto ret = Dive::ResolveResourcesLocalPath(profiling_sha_path); ret.ok()) + if (auto ret = ResolveProfilingResourcesLocalPath(profiling_sha_path); ret.ok()) { std::filesystem::path profiling_plugin_version_path = *ret; if (absl::StatusOr ret = @@ -230,7 +228,7 @@ absl::StatusOr GetDeviceResourceInfo(std::string_view key) { std::filesystem::path device_resources_version_path; { - auto ret = Dive::ResolveResourcesLocalPath(DIVE_DEVICE_RESOURCES_VERSION_FILENAME); + auto ret = Dive::ResolveDeviceResourcesLocalPath(Dive::GetDeviceResourcesVersionFileName()); if (!ret.ok()) { return ret.status(); diff --git a/src/dive/utils/version_info.h b/src/dive/utils/version_info.h index a4734e593..8393a638c 100644 --- a/src/dive/utils/version_info.h +++ b/src/dive/utils/version_info.h @@ -26,7 +26,7 @@ namespace Dive struct VersionInfoConstants { - // Expected fields in DIVE_DEVICE_RESOURCES_VERSION_FILENAME + // Expected fields in CMAKE_GENERATED_DEVICE_RESOURCES_VERSION_FILENAME static constexpr size_t kKeyCount = 5; static constexpr std::string_view kNameSha = "sha"; static constexpr std::string_view kNameVersion = "version"; @@ -75,11 +75,12 @@ std::string GetLongVersionString(); std::string GetCompleteVersionString(); // Returns a validated key-value map representing all the info within -// DIVE_DEVICE_RESOURCES_VERSION_FILENAME +// CMAKE_GENERATED_DEVICE_RESOURCES_VERSION_FILENAME absl::StatusOr> GetDeviceResourcesVersionMap( const std::string& csv_content); -// Returns the value of the field represented by a key in DIVE_DEVICE_RESOURCES_VERSION_FILENAME +// Returns the value of the field represented by a key in +// CMAKE_GENERATED_DEVICE_RESOURCES_VERSION_FILENAME absl::StatusOr GetDeviceResourceInfo(std::string_view key); } // namespace Dive diff --git a/third_party/Vulkan-ValidationLayers/CMakeLists.txt b/third_party/Vulkan-ValidationLayers/CMakeLists.txt index 07a2d6ca3..f00af6027 100644 --- a/third_party/Vulkan-ValidationLayers/CMakeLists.txt +++ b/third_party/Vulkan-ValidationLayers/CMakeLists.txt @@ -17,5 +17,5 @@ # License is handled by ui/CMakeLists.txt install( FILES ${CMAKE_CURRENT_SOURCE_DIR}/android/${ANDROID_ABI}/libVkLayer_khronos_validation.so - DESTINATION "${DIVE_INSTALL_DESTINATION}" + DESTINATION "${DIVE_INSTALL_DEST_DEVICE}" ) diff --git a/ui/CMakeLists.txt b/ui/CMakeLists.txt index 8d7727353..082191364 100644 --- a/ui/CMakeLists.txt +++ b/ui/CMakeLists.txt @@ -36,11 +36,6 @@ set(CMAKE_AUTOMOC ON) # Create code from a list of Qt designer ui files set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON) -option( - DIVE_ENABLE_SIGNING - "Enable ad-hoc signing of the application bundle" - OFF -) set(CMAKE_CXX_STANDARD 20) # Find the QtWidgets library @@ -221,6 +216,7 @@ target_link_libraries( version_info dive_build_defs dive_lib_trace_stats + dive_src_includes ) # std::filesystem needs to link with libstdc++fs for g++ before 9.0 @@ -288,20 +284,14 @@ file( # Generate license NOTICE file include("collect_licenses.cmake") GenerateThirdPartyLicenseFile( - "${CMAKE_CURRENT_BINARY_DIR}/NOTICE" + "${CMAKE_CURRENT_BINARY_DIR}/${DIVE_LICENSE_FILE_NAME}" "${CMAKE_CURRENT_BINARY_DIR}/licenses/" ) -add_custom_target(notice_file ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/NOTICE") -if(MSVC) - add_custom_command( - TARGET ${PROJECT_NAME} - POST_BUILD - COMMAND - "${CMAKE_COMMAND}" -E copy_if_different - "${CMAKE_CURRENT_BINARY_DIR}/NOTICE" - "${CMAKE_CURRENT_BINARY_DIR}/$" - ) -endif() +add_custom_target( + notice_file + ALL + DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/${DIVE_LICENSE_FILE_NAME}" +) if(APPLE) set_target_properties( @@ -313,51 +303,17 @@ if(APPLE) endif() if(APPLE) - install(TARGETS ${PROJECT_NAME} BUNDLE DESTINATION .) - # TODO: b/462767957 - fix mac installation directory. install( - CODE - " - message(STATUS \"Running macdeployqt...\") - execute_process(COMMAND \"macdeployqt\" \"${CMAKE_INSTALL_PREFIX}/dive.app\") - message(STATUS \"Creating install directory in app bundle\") - execute_process(COMMAND \"${CMAKE_COMMAND}\" -E make_directory \"${CMAKE_INSTALL_PREFIX}/dive.app/Contents/Resources/\") - message(STATUS \"Copying Android files to app bundle\") - execute_process(COMMAND \"${CMAKE_COMMAND}\" -E copy \"${CMAKE_INSTALL_PREFIX}/gfxr-replay.apk\" \"${CMAKE_INSTALL_PREFIX}/dive.app/Contents/Resources/\") - execute_process(COMMAND \"${CMAKE_COMMAND}\" -E copy \"${CMAKE_INSTALL_PREFIX}/gfxrecon.py\" \"${CMAKE_INSTALL_PREFIX}/dive.app/Contents/Resources/\") - execute_process(COMMAND \"${CMAKE_COMMAND}\" -E copy \"${CMAKE_INSTALL_PREFIX}/libVkLayer_dive.so\" \"${CMAKE_INSTALL_PREFIX}/dive.app/Contents/Resources/\") - execute_process(COMMAND \"${CMAKE_COMMAND}\" -E copy \"${CMAKE_INSTALL_PREFIX}/libVkLayer_khronos_validation.so\" \"${CMAKE_INSTALL_PREFIX}/dive.app/Contents/Resources/\") - execute_process(COMMAND \"${CMAKE_COMMAND}\" -E copy \"${CMAKE_INSTALL_PREFIX}/libXrApiLayer_dive.so\" \"${CMAKE_INSTALL_PREFIX}/dive.app/Contents/Resources/\") - execute_process(COMMAND \"${CMAKE_COMMAND}\" -E copy \"${CMAKE_INSTALL_PREFIX}/XrApiLayer_dive.json\" \"${CMAKE_INSTALL_PREFIX}/dive.app/Contents/Resources/\") - execute_process(COMMAND \"${CMAKE_COMMAND}\" -E copy \"${CMAKE_INSTALL_PREFIX}/libVkLayer_rt_dive.so\" \"${CMAKE_INSTALL_PREFIX}/dive.app/Contents/Resources/\") - execute_process(COMMAND \"${CMAKE_COMMAND}\" -E copy \"${CMAKE_INSTALL_PREFIX}/libwrap.so\" \"${CMAKE_INSTALL_PREFIX}/dive.app/Contents/Resources/\") - execute_process(COMMAND \"${CMAKE_COMMAND}\" -E copy \"${CMAKE_INSTALL_PREFIX}/libVkLayer_gfxreconstruct.so\" \"${CMAKE_INSTALL_PREFIX}/dive.app/Contents/Resources/\") - message(STATUS \"Copying dive_client_cli to app bundle\") - execute_process(COMMAND \"${CMAKE_COMMAND}\" -E copy \"${CMAKE_INSTALL_PREFIX}/dive_client_cli\" \"${CMAKE_INSTALL_PREFIX}/dive.app/Contents/MacOS/\") - - if(IS_DIRECTORY \"${CMAKE_INSTALL_PREFIX}/dive_profiling_plugin\") - message(STATUS \"Copying dive_profiling_plugin to app bundle\") - execute_process(COMMAND \"${CMAKE_COMMAND}\" -E copy_directory \"${CMAKE_INSTALL_PREFIX}/dive_profiling_plugin/\" \"${CMAKE_INSTALL_PREFIX}/dive.app/Contents/Resources/dive_profiling_plugin\") - endif() - if(EXISTS \"${CMAKE_INSTALL_PREFIX}/dive_compositor_capture.sh\") - message(STATUS \"Copying dive_compositor_capture.sh to app bundle\") - execute_process(COMMAND \"${CMAKE_COMMAND}\" -E copy \"${CMAKE_INSTALL_PREFIX}/dive_compositor_capture.sh\" \"${CMAKE_INSTALL_PREFIX}/dive.app/Contents/MacOS/\") - endif() - if(${DIVE_ENABLE_SIGNING}) - message(STATUS \"Ad-hoc signing the application bundle\") - execute_process(COMMAND \"codesign\" --force --deep --sign - \"${CMAKE_INSTALL_PREFIX}/dive.app\") - endif() - " + TARGETS ${PROJECT_NAME} + BUNDLE DESTINATION "${DIVE_INSTALL_DEST_HOST}" ) else() - install(TARGETS ${PROJECT_NAME} DESTINATION "${DIVE_INSTALL_DESTINATION}") - # Add a [maybe empty] plugins directory. - install(DIRECTORY DESTINATION "${DIVE_PLUGINS_INSTALL_DESTINATION}") + install(TARGETS ${PROJECT_NAME} DESTINATION "${DIVE_INSTALL_DEST_HOST}") endif() install( - FILES "${CMAKE_CURRENT_BINARY_DIR}/NOTICE" - DESTINATION "${DIVE_INSTALL_DESTINATION}" + FILES "${CMAKE_CURRENT_BINARY_DIR}/${DIVE_LICENSE_FILE_NAME}" + DESTINATION "${DIVE_INSTALL_DEST_HOST}" ) add_dependencies(${PROJECT_NAME} notice_file) diff --git a/ui/about_window.cpp b/ui/about_window.cpp index 1d1c951f4..54735d365 100644 --- a/ui/about_window.cpp +++ b/ui/about_window.cpp @@ -16,6 +16,7 @@ #include "about_window.h" #include +#include #include #include #include @@ -26,8 +27,11 @@ #include #include #include +#include #include +#include "utils/device_resources.h" +#include "utils/device_resources_constants.h" #include "utils/version_info.h" // ================================================================================================= @@ -37,10 +41,22 @@ AboutDialog::AboutDialog(QWidget* parent) { auto main_layout = new QVBoxLayout; - main_layout->addLayout(CreateHeaderLayout()); - main_layout->addLayout(CreateVersionLayout()); - main_layout->addLayout(CreateLicenseLayout()); - main_layout->addLayout(CreateButtonLayout()); + if (auto layout = CreateHeaderLayout()) + { + main_layout->addLayout(layout); + } + if (auto layout = CreateVersionLayout()) + { + main_layout->addLayout(layout); + } + if (auto layout = CreateLicenseLayout()) + { + main_layout->addLayout(layout); + } + if (auto layout = CreateButtonLayout()) + { + main_layout->addLayout(layout); + } // Disable help icon, set size, title, and layout setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); @@ -87,11 +103,24 @@ QVBoxLayout* AboutDialog::CreateLicenseLayout() auto third_party_licenses = new QLabel("Third Party Licenses:"); auto license_notice = new QPlainTextEdit(); - QFile licenseFile{QDir{QCoreApplication::applicationDirPath()}.filePath("NOTICE")}; - if (licenseFile.open(QIODevice::ReadOnly)) + + absl::StatusOr notice_file_path = + Dive::ResolveHostResourcesLocalPath(Dive::GetLicenseFileName()); + if (!notice_file_path.ok()) + { + std::string err_msg = absl::StrFormat("Can't locate notice file, checked: %s", + notice_file_path.status().message()); + qDebug() << err_msg.c_str(); + return nullptr; + } + + QFile licenseFile{notice_file_path->generic_string().c_str()}; + if (!licenseFile.open(QIODevice::ReadOnly)) { - license_notice->setPlainText(licenseFile.readAll()); + qDebug() << "Could not open license file: " << notice_file_path->generic_string().c_str(); + return nullptr; } + license_notice->setPlainText(licenseFile.readAll()); license_notice->setReadOnly(true); QVBoxLayout* license_layout = new QVBoxLayout; diff --git a/ui/application_controller.cpp b/ui/application_controller.cpp index d660a1992..2aefb6895 100644 --- a/ui/application_controller.cpp +++ b/ui/application_controller.cpp @@ -69,18 +69,12 @@ bool ApplicationController::InitializePlugins() { return false; } - // This assumes plugins are in a 'plugins' subdirectory relative to the executable's directory. - std::string plugin_path = QCoreApplication::applicationDirPath().toStdString() + "/plugins"; - std::filesystem::path plugins_dir_path(plugin_path); - - if (absl::Status load_status = m_impl->m_plugin_manager.LoadPlugins(plugins_dir_path); - !load_status.ok()) + if (absl::Status load_status = m_impl->m_plugin_manager.LoadPlugins(); !load_status.ok()) { - QMessageBox::warning(m_impl->m_main_window, tr("Plugin Loading Failed"), - tr("Failed to load plugins from '%1'. \nError: %2") - .arg(QString::fromStdString(plugin_path)) - .arg(QString::fromStdString(std::string(load_status.message())))); + QMessageBox::warning( + m_impl->m_main_window, tr("Plugin Loading Failed"), + tr("Error: '%1'").arg(QString::fromStdString(std::string(load_status.message())))); return false; } return true; diff --git a/ui/main_window.cpp b/ui/main_window.cpp index dc8840cc2..e1937ac27 100644 --- a/ui/main_window.cpp +++ b/ui/main_window.cpp @@ -1527,11 +1527,10 @@ void MainWindow::OnSearchTrigger() void MainWindow::LoadAvailableMetrics() { std::filesystem::path metrics_file_path = - Dive::DeviceResourcesConstants::kProfilingPluginFolderName; - metrics_file_path /= Dive::DeviceResourcesConstants::kProfilingPluginMetricsFileName; + Dive::DeviceResourcesConstants::kProfilingPluginMetricsFileName; { absl::StatusOr ret = - Dive::ResolveResourcesLocalPath(metrics_file_path); + Dive::ResolveProfilingResourcesLocalPath(metrics_file_path); if (!ret.ok()) { std::string err_msg = absl::StrFormat(