diff --git a/.github/workflows/latex.yml b/.github/workflows/latex.yml deleted file mode 100644 index 9c68cace..00000000 --- a/.github/workflows/latex.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: Manual - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -jobs: - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - name: Fix stupidity - run: | - cp AUTHORS AUTHORS. - cp LICENSE LICENSE. - - name: Compile LaTeX - uses: xu-cheng/latex-action@v3 - with: - working_directory: manual - root_file: tracy.tex - - uses: actions/upload-artifact@v4 - with: - name: manual - path: manual/tracy.pdf diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 04f8d41e..8fbd272b 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -2,40 +2,116 @@ name: linux on: push: - branches: [ master ] + branches: [master] pull_request: - branches: [ master ] + branches: [master] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true jobs: build: - - runs-on: ubuntu-22.04 - container: archlinux:base-devel + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + runs-on: ${{ matrix.os }} + continue-on-error: true # Allow other platforms to build even if one fails steps: - - uses: actions/checkout@v4 - - name: Install linux libraries - run: pacman -Syu --noconfirm && pacman -S --noconfirm --needed freetype2 capstone tbb debuginfod wayland dbus libxkbcommon libglvnd meson - - name: Profiler GUI - run: make -j`nproc` -C profiler/build/unix debug release - - name: Update utility - run: make -j`nproc` -C update/build/unix debug release - - name: Capture utility - run: make -j`nproc` -C capture/build/unix debug release - - name: Csvexport utility - run: make -j`nproc` -C csvexport/build/unix debug release - - name: Import-chrome utility - run: make -j`nproc` -C import-chrome/build/unix debug release - - name: Import-fuchsia utility - run: make -j`nproc` -C import-fuchsia/build/unix debug release - - name: Library - run: make -j`nproc` -C library/unix debug release - - name: Library (meson) - run: meson setup -Dprefix=$PWD/install build && meson compile -C build && meson install -C build - - name: Test application - run: | - make -j`nproc` -C test - make -j`nproc` -C test clean - make -j`nproc` -C test TRACYFLAGS=-DTRACY_ON_DEMAND - make -j`nproc` -C test clean - make -j`nproc` -C test TRACYFLAGS="-DTRACY_DELAYED_INIT -DTRACY_MANUAL_LIFETIME" - make -C test -B ../public/TracyClient.o DEFINES='-DTRACY_DEMANGLE' + - name: Checkout + uses: actions/checkout@v2 + + - name: Install Linux Dependencies + if: startsWith(matrix.os, 'ubuntu') + run: sudo apt-get install -y libcapstone-dev libtbb-dev libglfw3-dev libgtk-3-dev + + - name: Windows MSVC + if: startsWith(matrix.os, 'windows') + uses: microsoft/setup-msbuild@v2 + + - name: Install Windows Dependencies + if: startsWith(matrix.os, 'windows') + run: vcpkg integrate install + + - name: Install MacOS Dependencies + if: startsWith(matrix.os, 'macos') + run: brew install capstone tbb pkg-config glfw meson dbus + + - name: Build Profiler + run: | + cmake -B build/profiler -S profiler -DLEGACY=ON + cmake --build build/profiler --config Release --parallel + + - name: Build Update + run: | + cmake -B build/update -S update + cmake --build build/update --config Release --parallel + + - name: Build Capture + run: | + cmake -B build/capture -S capture + cmake --build build/capture --config Release --parallel + + - name: Build Csv Export + run: | + cmake -B build/csvexport -S csvexport + cmake --build build/csvexport --config Release --parallel + + - name: Build Import Chrome + run: | + cmake -B build/import-chrome -S import-chrome + cmake --build build/import-chrome --config Release --parallel + + - name: Build Import Fuchsia + run: | + cmake -B build/import-fuchsia -S import-fuchsia + cmake --build build/import-fuchsia --config Release --parallel + + - name: Find Artifacts + if: ${{ !startsWith(matrix.os, 'windows') }} + id: find_artifacts + run: | + echo PROFILER_PATH=build/profiler/Tracy >> $GITHUB_OUTPUT + echo UPDATE_PATH=build/update/update >> $GITHUB_OUTPUT + echo CAPTURE_PATH=build/capture/capture >> $GITHUB_OUTPUT + echo CSVEXPORT_PATH=build/csvexport/csvexport >> $GITHUB_OUTPUT + echo IMPORT_CHROME_PATH=build/import-chrome/import-chrome >> $GITHUB_OUTPUT + echo IMPORT_FUCHSIA_PATH=build/import-fuchsia/import-fuchsia >> $GITHUB_OUTPUT + + - name: Find Artifacts Windows + if: startsWith(matrix.os, 'windows') + id: find_artifacts_windows + run: | + echo PROFILER_PATH=build/profiler/Release/Tracy.exe >> $GITHUB_OUTPUT + echo UPDATE_PATH=build/update/Release/update.exe >> $GITHUB_OUTPUT + echo CAPTURE_PATH=build/capture/Release/capture.exe >> $GITHUB_OUTPUT + echo CSVEXPORT_PATH=build/csvexport/Release/csvexport.exe >> $GITHUB_OUTPUT + echo IMPORT_CHROME_PATH=build/import-chrome/Release/import-chrome.exe >> $GITHUB_OUTPUT + echo IMPORT_FUCHSIA_PATH=build/import-fuchsia/Release/import-fuchsia.exe >> $GITHUB_OUTPUT + + - name: Export Artifacts + if: ${{ !startsWith(matrix.os, 'windows') }} + uses: actions/upload-artifact@v2 + with: + name: ${{ matrix.os }} + path: | + ${{ steps.find_artifacts.outputs.PROFILER_PATH }} + ${{ steps.find_artifacts.outputs.UPDATE_PATH }} + ${{ steps.find_artifacts.outputs.CAPTURE_PATH }} + ${{ steps.find_artifacts.outputs.CSVEXPORT_PATH }} + ${{ steps.find_artifacts.outputs.IMPORT_CHROME_PATH }} + ${{ steps.find_artifacts.outputs.IMPORT_FUCHSIA_PATH }} + + - name: Export Artifacts Windows + if: startsWith(matrix.os, 'windows') + uses: actions/upload-artifact@v2 + with: + name: ${{ matrix.os }} + path: | + ${{ steps.find_artifacts_windows.outputs.PROFILER_PATH }} + ${{ steps.find_artifacts_windows.outputs.UPDATE_PATH }} + ${{ steps.find_artifacts_windows.outputs.CAPTURE_PATH }} + ${{ steps.find_artifacts_windows.outputs.CSVEXPORT_PATH }} + ${{ steps.find_artifacts_windows.outputs.IMPORT_CHROME_PATH }} + ${{ steps.find_artifacts_windows.outputs.IMPORT_FUCHSIA_PATH }} + diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml deleted file mode 100644 index 98f095c7..00000000 --- a/.github/workflows/macos.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: macos - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -jobs: - build: - - runs-on: macOS-latest - steps: - - uses: actions/checkout@v4 - - name: Install macos libraries - run: brew install capstone tbb pkg-config glfw meson - - name: Profiler GUI - run: make -j`nproc` -C profiler/build/unix debug release - - name: Update utility - run: make -j`nproc` -C update/build/unix debug release - - name: Capture utility - run: make -j`nproc` -C capture/build/unix debug release - - name: Csvexport utility - run: make -j`nproc` -C csvexport/build/unix debug release - - name: Import-chrome utility - run: make -j`nproc` -C import-chrome/build/unix debug release - - name: Import-fuchsia utility - run: make -j`nproc` -C import-fuchsia/build/unix debug release - - name: Library - run: make -j`nproc` -C library/unix debug release - - name: Library (meson) - run: meson setup -Dprefix=$PWD/install build && meson compile -C build && meson install -C build - - name: Test application - run: | - make -j`nproc` -C test - make -j`nproc` -C test clean - make -j`nproc` -C test TRACYFLAGS=-DTRACY_ON_DEMAND - make -j`nproc` -C test clean - make -j`nproc` -C test TRACYFLAGS="-DTRACY_DELAYED_INIT -DTRACY_MANUAL_LIFETIME" - make -C test -B ../public/TracyClient.o DEFINES='-DTRACY_DEMANGLE' diff --git a/.github/workflows/msvc.yml b/.github/workflows/msvc.yml deleted file mode 100644 index f20abe73..00000000 --- a/.github/workflows/msvc.yml +++ /dev/null @@ -1,76 +0,0 @@ -name: MSVC - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -jobs: - build-with-vcpkg-integration: - - runs-on: windows-2022 - - steps: - - uses: actions/checkout@v4 - - uses: microsoft/setup-msbuild@v2 - - name: Integrate vcpkg - run: vcpkg integrate install - - name: Profiler GUI Debug - run: msbuild .\profiler\build\win32\Tracy.vcxproj /property:Configuration=Debug /property:Platform=x64 - - name: Profiler GUI Release - run: msbuild .\profiler\build\win32\Tracy.vcxproj /property:Configuration=Release /property:Platform=x64 - - name: Update utility Debug - run: msbuild .\update\build\win32\update.vcxproj /property:Configuration=Debug /property:Platform=x64 - - name: Update utility Release - run: msbuild .\update\build\win32\update.vcxproj /property:Configuration=Release /property:Platform=x64 - - name: Capture utility Debug - run: msbuild .\capture\build\win32\capture.vcxproj /property:Configuration=Debug /property:Platform=x64 - - name: Capture utility Release - run: msbuild .\capture\build\win32\capture.vcxproj /property:Configuration=Release /property:Platform=x64 - - name: Csvexport utility Debug - run: msbuild .\csvexport\build\win32\csvexport.vcxproj /property:Configuration=Debug /property:Platform=x64 - - name: Csvexport utility Release - run: msbuild .\csvexport\build\win32\csvexport.vcxproj /property:Configuration=Release /property:Platform=x64 - - name: Import-chrome utility Debug - run: msbuild .\import-chrome\build\win32\import-chrome.vcxproj /property:Configuration=Debug /property:Platform=x64 - - name: Import-chrome utility Release - run: msbuild .\import-chrome\build\win32\import-chrome.vcxproj /property:Configuration=Release /property:Platform=x64 - - name: Import-fuchsia utility Debug - run: msbuild .\import-fuchsia\build\win32\import-fuchsia.vcxproj /property:Configuration=Debug /property:Platform=x64 - - name: Import-fuchsia utility Release - run: msbuild .\import-fuchsia\build\win32\import-fuchsia.vcxproj /property:Configuration=Release /property:Platform=x64 - - name: Library - run: msbuild .\library\win32\TracyProfiler.vcxproj /property:Configuration=Release /property:Platform=x64 - - name: Package binaries - run: | - mkdir bin - mkdir bin\dev - copy profiler\build\win32\x64\Release\Tracy.exe bin - copy update\build\win32\x64\Release\update.exe bin - copy capture\build\win32\x64\Release\capture.exe bin - copy import-chrome\build\win32\x64\Release\import-chrome.exe bin - copy csvexport\build\win32\x64\Release\csvexport.exe bin - copy library\win32\x64\Release\TracyProfiler.dll bin\dev - copy library\win32\x64\Release\TracyProfiler.lib bin\dev - 7z a Tracy.7z bin - - uses: actions/upload-artifact@v4 - with: - path: Tracy.7z - - build-without-vcpkg-integration: - - runs-on: windows-2022 - - env: - VCPKG_ROOT: '' - - steps: - - uses: actions/checkout@v4 - - uses: microsoft/setup-msbuild@v2 - - name: Install vcpkg dependencies - run: vcpkg/install_vcpkg_dependencies.bat - - name: Profiler GUI Release - run: msbuild .\profiler\build\win32\Tracy.vcxproj /property:Configuration=Release /property:Platform=x64 - - name: Capture utility Release - run: msbuild .\capture\build\win32\capture.vcxproj /property:Configuration=Release /property:Platform=x64 diff --git a/.gitignore b/.gitignore index f14f6af1..fd171d1a 100644 --- a/.gitignore +++ b/.gitignore @@ -44,3 +44,7 @@ compile_commands.json profiler/build/wasm/Tracy-release.* profiler/build/wasm/Tracy-debug.* profiler/build/wasm/embed.tracy + + +# Only ignore top-level build directory +/build \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 4c700702..15377822 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.10) # Run version helper script -include(version.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/cmake/version.cmake) set(TRACY_VERSION_MAJOR ${major}) set(TRACY_VERSION_MINOR ${minor}) @@ -20,7 +20,7 @@ option(TRACY_STATIC "Whether to build Tracy as a static library" ${DEFAULT_STATI find_package(Threads REQUIRED) -set(TRACY_PUBLIC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/public) +set(TRACY_PUBLIC_DIR ${CMAKE_CURRENT_LIST_DIR}/public) if(TRACY_STATIC) set(TRACY_VISIBILITY "STATIC") @@ -52,16 +52,22 @@ endif() add_library(Tracy::TracyClient ALIAS TracyClient) -macro(set_option option help value) - option(${option} ${help} ${value}) +macro(log_option option help value) if(${option}) message(STATUS "${option}: ON") - target_compile_definitions(TracyClient PUBLIC ${option}) else() message(STATUS "${option}: OFF") endif() endmacro() +macro(set_option option help value) + option(${option} ${help} ${value}) + if(${option}) + target_compile_definitions(TracyClient PUBLIC ${option}) + endif() + log_option(${option} ${help} ${value}) +endmacro() + set_option(TRACY_ENABLE "Enable profiling" ON) set_option(TRACY_ON_DEMAND "On-demand profiling" OFF) set_option(TRACY_CALLSTACK "Enforce callstack collection for tracy regions" OFF) @@ -162,7 +168,7 @@ install(EXPORT TracyConfig FILE TracyTargets.cmake DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/Tracy) include(CMakePackageConfigHelpers) -configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in +configure_package_config_file(${CMAKE_CURRENT_LIST_DIR}/Config.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/TracyConfig.cmake" INSTALL_DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/Tracy) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/TracyConfig.cmake diff --git a/README.md b/README.md index 32bdca35..2c278284 100644 --- a/README.md +++ b/README.md @@ -26,3 +26,51 @@ Tracy supports profiling CPU (Direct support is provided for C, C++, and Lua int [New features in Tracy Profiler v0.6](https://www.youtube.com/watch?v=uJkrFgriuOo) [New features in Tracy Profiler v0.7](https://www.youtube.com/watch?v=_hU7vw00MZ4) [New features in Tracy Profiler v0.8](https://www.youtube.com/watch?v=30wpRpHTTag) + +# Building the executables + +For an indepth build guide please refer to the [documentation](https://github.com/wolfpld/tracy/releases/latest/download/tracy.pdf) + +For a quick build guide with CMake: + +### Profiler + +```bash +cmake -B build/profiler -S profiler +cmake --build build/profiler +``` + +### Update + +```bash +cmake -B build/update -S update +cmake --build build/update +``` + +### Capture + +```bash +cmake -B build/capture -S capture +cmake --build build/capture +``` + +### Csv Export + +```bash +cmake -B build/csvexport -S csvexport +cmake --build build/csvexport +``` + +### Import Chrome + +```bash +cmake -B build/import-chrome -S import-chrome +cmake --build build/import-chrome +``` + +## Import Fuchsia + +```bash +cmake -B build/import-fuchsia -S import-fuchsia +cmake --build build/import-fuchsia +``` \ No newline at end of file diff --git a/capture/CMakeLists.txt b/capture/CMakeLists.txt new file mode 100644 index 00000000..ed7efd21 --- /dev/null +++ b/capture/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.19) +project(capture C CXX ASM) + +set(CMAKE_CXX_STANDARD 17) + +include(${CMAKE_CURRENT_LIST_DIR}/../cmake/vendor.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/../cmake/server.cmake) + +set(CAPTURE_SOURCE + src/capture.cpp +) + +add_executable(capture ${CAPTURE_SOURCE}) +target_include_directories(capture PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) +target_link_libraries(capture PRIVATE TracyServer) \ No newline at end of file diff --git a/cmake/CPM.cmake b/cmake/CPM.cmake new file mode 100644 index 00000000..c82a3865 --- /dev/null +++ b/cmake/CPM.cmake @@ -0,0 +1,1161 @@ +# CPM.cmake - CMake's missing package manager +# =========================================== +# See https://github.com/cpm-cmake/CPM.cmake for usage and update instructions. +# +# MIT License +# ----------- +#[[ + Copyright (c) 2019-2023 Lars Melchior and contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +]] + +cmake_minimum_required(VERSION 3.14 FATAL_ERROR) + +# Initialize logging prefix +if(NOT CPM_INDENT) + set(CPM_INDENT + "CPM:" + CACHE INTERNAL "" + ) +endif() + +if(NOT COMMAND cpm_message) + function(cpm_message) + message(${ARGV}) + endfunction() +endif() + +set(CURRENT_CPM_VERSION 0.38.7) + +get_filename_component(CPM_CURRENT_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}" REALPATH) +if(CPM_DIRECTORY) + if(NOT CPM_DIRECTORY STREQUAL CPM_CURRENT_DIRECTORY) + if(CPM_VERSION VERSION_LESS CURRENT_CPM_VERSION) + message( + AUTHOR_WARNING + "${CPM_INDENT} \ +A dependency is using a more recent CPM version (${CURRENT_CPM_VERSION}) than the current project (${CPM_VERSION}). \ +It is recommended to upgrade CPM to the most recent version. \ +See https://github.com/cpm-cmake/CPM.cmake for more information." + ) + endif() + if(${CMAKE_VERSION} VERSION_LESS "3.17.0") + include(FetchContent) + endif() + return() + endif() + + get_property( + CPM_INITIALIZED GLOBAL "" + PROPERTY CPM_INITIALIZED + SET + ) + if(CPM_INITIALIZED) + return() + endif() +endif() + +if(CURRENT_CPM_VERSION MATCHES "development-version") + message( + WARNING "${CPM_INDENT} Your project is using an unstable development version of CPM.cmake. \ +Please update to a recent release if possible. \ +See https://github.com/cpm-cmake/CPM.cmake for details." + ) +endif() + +set_property(GLOBAL PROPERTY CPM_INITIALIZED true) + +macro(cpm_set_policies) + # the policy allows us to change options without caching + cmake_policy(SET CMP0077 NEW) + set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) + + # the policy allows us to change set(CACHE) without caching + if(POLICY CMP0126) + cmake_policy(SET CMP0126 NEW) + set(CMAKE_POLICY_DEFAULT_CMP0126 NEW) + endif() + + # The policy uses the download time for timestamp, instead of the timestamp in the archive. This + # allows for proper rebuilds when a projects url changes + if(POLICY CMP0135) + cmake_policy(SET CMP0135 NEW) + set(CMAKE_POLICY_DEFAULT_CMP0135 NEW) + endif() + + # treat relative git repository paths as being relative to the parent project's remote + if(POLICY CMP0150) + cmake_policy(SET CMP0150 NEW) + set(CMAKE_POLICY_DEFAULT_CMP0150 NEW) + endif() +endmacro() +cpm_set_policies() + +option(CPM_USE_LOCAL_PACKAGES "Always try to use `find_package` to get dependencies" + $ENV{CPM_USE_LOCAL_PACKAGES} +) +option(CPM_LOCAL_PACKAGES_ONLY "Only use `find_package` to get dependencies" + $ENV{CPM_LOCAL_PACKAGES_ONLY} +) +option(CPM_DOWNLOAD_ALL "Always download dependencies from source" $ENV{CPM_DOWNLOAD_ALL}) +option(CPM_DONT_UPDATE_MODULE_PATH "Don't update the module path to allow using find_package" + $ENV{CPM_DONT_UPDATE_MODULE_PATH} +) +option(CPM_DONT_CREATE_PACKAGE_LOCK "Don't create a package lock file in the binary path" + $ENV{CPM_DONT_CREATE_PACKAGE_LOCK} +) +option(CPM_INCLUDE_ALL_IN_PACKAGE_LOCK + "Add all packages added through CPM.cmake to the package lock" + $ENV{CPM_INCLUDE_ALL_IN_PACKAGE_LOCK} +) +option(CPM_USE_NAMED_CACHE_DIRECTORIES + "Use additional directory of package name in cache on the most nested level." + $ENV{CPM_USE_NAMED_CACHE_DIRECTORIES} +) + +set(CPM_VERSION + ${CURRENT_CPM_VERSION} + CACHE INTERNAL "" +) +set(CPM_DIRECTORY + ${CPM_CURRENT_DIRECTORY} + CACHE INTERNAL "" +) +set(CPM_FILE + ${CMAKE_CURRENT_LIST_FILE} + CACHE INTERNAL "" +) +set(CPM_PACKAGES + "" + CACHE INTERNAL "" +) +set(CPM_DRY_RUN + OFF + CACHE INTERNAL "Don't download or configure dependencies (for testing)" +) + +if(DEFINED ENV{CPM_SOURCE_CACHE}) + set(CPM_SOURCE_CACHE_DEFAULT $ENV{CPM_SOURCE_CACHE}) +else() + set(CPM_SOURCE_CACHE_DEFAULT OFF) +endif() + +set(CPM_SOURCE_CACHE + ${CPM_SOURCE_CACHE_DEFAULT} + CACHE PATH "Directory to download CPM dependencies" +) + +if(NOT CPM_DONT_UPDATE_MODULE_PATH) + set(CPM_MODULE_PATH + "${CMAKE_BINARY_DIR}/CPM_modules" + CACHE INTERNAL "" + ) + # remove old modules + file(REMOVE_RECURSE ${CPM_MODULE_PATH}) + file(MAKE_DIRECTORY ${CPM_MODULE_PATH}) + # locally added CPM modules should override global packages + set(CMAKE_MODULE_PATH "${CPM_MODULE_PATH};${CMAKE_MODULE_PATH}") +endif() + +if(NOT CPM_DONT_CREATE_PACKAGE_LOCK) + set(CPM_PACKAGE_LOCK_FILE + "${CMAKE_BINARY_DIR}/cpm-package-lock.cmake" + CACHE INTERNAL "" + ) + file(WRITE ${CPM_PACKAGE_LOCK_FILE} + "# CPM Package Lock\n# This file should be committed to version control\n\n" + ) +endif() + +include(FetchContent) + +# Try to infer package name from git repository uri (path or url) +function(cpm_package_name_from_git_uri URI RESULT) + if("${URI}" MATCHES "([^/:]+)/?.git/?$") + set(${RESULT} + ${CMAKE_MATCH_1} + PARENT_SCOPE + ) + else() + unset(${RESULT} PARENT_SCOPE) + endif() +endfunction() + +# Try to infer package name and version from a url +function(cpm_package_name_and_ver_from_url url outName outVer) + if(url MATCHES "[/\\?]([a-zA-Z0-9_\\.-]+)\\.(tar|tar\\.gz|tar\\.bz2|zip|ZIP)(\\?|/|$)") + # We matched an archive + set(filename "${CMAKE_MATCH_1}") + + if(filename MATCHES "([a-zA-Z0-9_\\.-]+)[_-]v?(([0-9]+\\.)*[0-9]+[a-zA-Z0-9]*)") + # We matched - (ie foo-1.2.3) + set(${outName} + "${CMAKE_MATCH_1}" + PARENT_SCOPE + ) + set(${outVer} + "${CMAKE_MATCH_2}" + PARENT_SCOPE + ) + elseif(filename MATCHES "(([0-9]+\\.)+[0-9]+[a-zA-Z0-9]*)") + # We couldn't find a name, but we found a version + # + # In many cases (which we don't handle here) the url would look something like + # `irrelevant/ACTUAL_PACKAGE_NAME/irrelevant/1.2.3.zip`. In such a case we can't possibly + # distinguish the package name from the irrelevant bits. Moreover if we try to match the + # package name from the filename, we'd get bogus at best. + unset(${outName} PARENT_SCOPE) + set(${outVer} + "${CMAKE_MATCH_1}" + PARENT_SCOPE + ) + else() + # Boldly assume that the file name is the package name. + # + # Yes, something like `irrelevant/ACTUAL_NAME/irrelevant/download.zip` will ruin our day, but + # such cases should be quite rare. No popular service does this... we think. + set(${outName} + "${filename}" + PARENT_SCOPE + ) + unset(${outVer} PARENT_SCOPE) + endif() + else() + # No ideas yet what to do with non-archives + unset(${outName} PARENT_SCOPE) + unset(${outVer} PARENT_SCOPE) + endif() +endfunction() + +function(cpm_find_package NAME VERSION) + string(REPLACE " " ";" EXTRA_ARGS "${ARGN}") + find_package(${NAME} ${VERSION} ${EXTRA_ARGS} QUIET) + if(${CPM_ARGS_NAME}_FOUND) + if(DEFINED ${CPM_ARGS_NAME}_VERSION) + set(VERSION ${${CPM_ARGS_NAME}_VERSION}) + endif() + cpm_message(STATUS "${CPM_INDENT} Using local package ${CPM_ARGS_NAME}@${VERSION}") + CPMRegisterPackage(${CPM_ARGS_NAME} "${VERSION}") + set(CPM_PACKAGE_FOUND + YES + PARENT_SCOPE + ) + else() + set(CPM_PACKAGE_FOUND + NO + PARENT_SCOPE + ) + endif() +endfunction() + +# Create a custom FindXXX.cmake module for a CPM package This prevents `find_package(NAME)` from +# finding the system library +function(cpm_create_module_file Name) + if(NOT CPM_DONT_UPDATE_MODULE_PATH) + # erase any previous modules + file(WRITE ${CPM_MODULE_PATH}/Find${Name}.cmake + "include(\"${CPM_FILE}\")\n${ARGN}\nset(${Name}_FOUND TRUE)" + ) + endif() +endfunction() + +# Find a package locally or fallback to CPMAddPackage +function(CPMFindPackage) + set(oneValueArgs NAME VERSION GIT_TAG FIND_PACKAGE_ARGUMENTS) + + cmake_parse_arguments(CPM_ARGS "" "${oneValueArgs}" "" ${ARGN}) + + if(NOT DEFINED CPM_ARGS_VERSION) + if(DEFINED CPM_ARGS_GIT_TAG) + cpm_get_version_from_git_tag("${CPM_ARGS_GIT_TAG}" CPM_ARGS_VERSION) + endif() + endif() + + set(downloadPackage ${CPM_DOWNLOAD_ALL}) + if(DEFINED CPM_DOWNLOAD_${CPM_ARGS_NAME}) + set(downloadPackage ${CPM_DOWNLOAD_${CPM_ARGS_NAME}}) + elseif(DEFINED ENV{CPM_DOWNLOAD_${CPM_ARGS_NAME}}) + set(downloadPackage $ENV{CPM_DOWNLOAD_${CPM_ARGS_NAME}}) + endif() + if(downloadPackage) + CPMAddPackage(${ARGN}) + cpm_export_variables(${CPM_ARGS_NAME}) + return() + endif() + + cpm_check_if_package_already_added(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}") + if(CPM_PACKAGE_ALREADY_ADDED) + cpm_export_variables(${CPM_ARGS_NAME}) + return() + endif() + + cpm_find_package(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}" ${CPM_ARGS_FIND_PACKAGE_ARGUMENTS}) + + if(NOT CPM_PACKAGE_FOUND) + CPMAddPackage(${ARGN}) + cpm_export_variables(${CPM_ARGS_NAME}) + endif() + +endfunction() + +# checks if a package has been added before +function(cpm_check_if_package_already_added CPM_ARGS_NAME CPM_ARGS_VERSION) + if("${CPM_ARGS_NAME}" IN_LIST CPM_PACKAGES) + CPMGetPackageVersion(${CPM_ARGS_NAME} CPM_PACKAGE_VERSION) + if("${CPM_PACKAGE_VERSION}" VERSION_LESS "${CPM_ARGS_VERSION}") + message( + WARNING + "${CPM_INDENT} Requires a newer version of ${CPM_ARGS_NAME} (${CPM_ARGS_VERSION}) than currently included (${CPM_PACKAGE_VERSION})." + ) + endif() + cpm_get_fetch_properties(${CPM_ARGS_NAME}) + set(${CPM_ARGS_NAME}_ADDED NO) + set(CPM_PACKAGE_ALREADY_ADDED + YES + PARENT_SCOPE + ) + cpm_export_variables(${CPM_ARGS_NAME}) + else() + set(CPM_PACKAGE_ALREADY_ADDED + NO + PARENT_SCOPE + ) + endif() +endfunction() + +# Parse the argument of CPMAddPackage in case a single one was provided and convert it to a list of +# arguments which can then be parsed idiomatically. For example gh:foo/bar@1.2.3 will be converted +# to: GITHUB_REPOSITORY;foo/bar;VERSION;1.2.3 +function(cpm_parse_add_package_single_arg arg outArgs) + # Look for a scheme + if("${arg}" MATCHES "^([a-zA-Z]+):(.+)$") + string(TOLOWER "${CMAKE_MATCH_1}" scheme) + set(uri "${CMAKE_MATCH_2}") + + # Check for CPM-specific schemes + if(scheme STREQUAL "gh") + set(out "GITHUB_REPOSITORY;${uri}") + set(packageType "git") + elseif(scheme STREQUAL "gl") + set(out "GITLAB_REPOSITORY;${uri}") + set(packageType "git") + elseif(scheme STREQUAL "bb") + set(out "BITBUCKET_REPOSITORY;${uri}") + set(packageType "git") + # A CPM-specific scheme was not found. Looks like this is a generic URL so try to determine + # type + elseif(arg MATCHES ".git/?(@|#|$)") + set(out "GIT_REPOSITORY;${arg}") + set(packageType "git") + else() + # Fall back to a URL + set(out "URL;${arg}") + set(packageType "archive") + + # We could also check for SVN since FetchContent supports it, but SVN is so rare these days. + # We just won't bother with the additional complexity it will induce in this function. SVN is + # done by multi-arg + endif() + else() + if(arg MATCHES ".git/?(@|#|$)") + set(out "GIT_REPOSITORY;${arg}") + set(packageType "git") + else() + # Give up + message(FATAL_ERROR "${CPM_INDENT} Can't determine package type of '${arg}'") + endif() + endif() + + # For all packages we interpret @... as version. Only replace the last occurrence. Thus URIs + # containing '@' can be used + string(REGEX REPLACE "@([^@]+)$" ";VERSION;\\1" out "${out}") + + # Parse the rest according to package type + if(packageType STREQUAL "git") + # For git repos we interpret #... as a tag or branch or commit hash + string(REGEX REPLACE "#([^#]+)$" ";GIT_TAG;\\1" out "${out}") + elseif(packageType STREQUAL "archive") + # For archives we interpret #... as a URL hash. + string(REGEX REPLACE "#([^#]+)$" ";URL_HASH;\\1" out "${out}") + # We don't try to parse the version if it's not provided explicitly. cpm_get_version_from_url + # should do this at a later point + else() + # We should never get here. This is an assertion and hitting it means there's a bug in the code + # above. A packageType was set, but not handled by this if-else. + message(FATAL_ERROR "${CPM_INDENT} Unsupported package type '${packageType}' of '${arg}'") + endif() + + set(${outArgs} + ${out} + PARENT_SCOPE + ) +endfunction() + +# Check that the working directory for a git repo is clean +function(cpm_check_git_working_dir_is_clean repoPath gitTag isClean) + + find_package(Git REQUIRED) + + if(NOT GIT_EXECUTABLE) + # No git executable, assume directory is clean + set(${isClean} + TRUE + PARENT_SCOPE + ) + return() + endif() + + # check for uncommitted changes + execute_process( + COMMAND ${GIT_EXECUTABLE} status --porcelain + RESULT_VARIABLE resultGitStatus + OUTPUT_VARIABLE repoStatus + OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET + WORKING_DIRECTORY ${repoPath} + ) + if(resultGitStatus) + # not supposed to happen, assume clean anyway + message(WARNING "${CPM_INDENT} Calling git status on folder ${repoPath} failed") + set(${isClean} + TRUE + PARENT_SCOPE + ) + return() + endif() + + if(NOT "${repoStatus}" STREQUAL "") + set(${isClean} + FALSE + PARENT_SCOPE + ) + return() + endif() + + # check for committed changes + execute_process( + COMMAND ${GIT_EXECUTABLE} diff -s --exit-code ${gitTag} + RESULT_VARIABLE resultGitDiff + OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_QUIET + WORKING_DIRECTORY ${repoPath} + ) + + if(${resultGitDiff} EQUAL 0) + set(${isClean} + TRUE + PARENT_SCOPE + ) + else() + set(${isClean} + FALSE + PARENT_SCOPE + ) + endif() + +endfunction() + +# method to overwrite internal FetchContent properties, to allow using CPM.cmake to overload +# FetchContent calls. As these are internal cmake properties, this method should be used carefully +# and may need modification in future CMake versions. Source: +# https://github.com/Kitware/CMake/blob/dc3d0b5a0a7d26d43d6cfeb511e224533b5d188f/Modules/FetchContent.cmake#L1152 +function(cpm_override_fetchcontent contentName) + cmake_parse_arguments(PARSE_ARGV 1 arg "" "SOURCE_DIR;BINARY_DIR" "") + if(NOT "${arg_UNPARSED_ARGUMENTS}" STREQUAL "") + message(FATAL_ERROR "${CPM_INDENT} Unsupported arguments: ${arg_UNPARSED_ARGUMENTS}") + endif() + + string(TOLOWER ${contentName} contentNameLower) + set(prefix "_FetchContent_${contentNameLower}") + + set(propertyName "${prefix}_sourceDir") + define_property( + GLOBAL + PROPERTY ${propertyName} + BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" + FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" + ) + set_property(GLOBAL PROPERTY ${propertyName} "${arg_SOURCE_DIR}") + + set(propertyName "${prefix}_binaryDir") + define_property( + GLOBAL + PROPERTY ${propertyName} + BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" + FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" + ) + set_property(GLOBAL PROPERTY ${propertyName} "${arg_BINARY_DIR}") + + set(propertyName "${prefix}_populated") + define_property( + GLOBAL + PROPERTY ${propertyName} + BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" + FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" + ) + set_property(GLOBAL PROPERTY ${propertyName} TRUE) +endfunction() + +# Download and add a package from source +function(CPMAddPackage) + cpm_set_policies() + + list(LENGTH ARGN argnLength) + if(argnLength EQUAL 1) + cpm_parse_add_package_single_arg("${ARGN}" ARGN) + + # The shorthand syntax implies EXCLUDE_FROM_ALL and SYSTEM + set(ARGN "${ARGN};EXCLUDE_FROM_ALL;YES;SYSTEM;YES;") + endif() + + set(oneValueArgs + NAME + FORCE + VERSION + GIT_TAG + DOWNLOAD_ONLY + GITHUB_REPOSITORY + GITLAB_REPOSITORY + BITBUCKET_REPOSITORY + GIT_REPOSITORY + SOURCE_DIR + FIND_PACKAGE_ARGUMENTS + NO_CACHE + SYSTEM + GIT_SHALLOW + EXCLUDE_FROM_ALL + SOURCE_SUBDIR + ) + + set(multiValueArgs URL OPTIONS DOWNLOAD_COMMAND) + + cmake_parse_arguments(CPM_ARGS "" "${oneValueArgs}" "${multiValueArgs}" "${ARGN}") + + # Set default values for arguments + + if(NOT DEFINED CPM_ARGS_VERSION) + if(DEFINED CPM_ARGS_GIT_TAG) + cpm_get_version_from_git_tag("${CPM_ARGS_GIT_TAG}" CPM_ARGS_VERSION) + endif() + endif() + + if(CPM_ARGS_DOWNLOAD_ONLY) + set(DOWNLOAD_ONLY ${CPM_ARGS_DOWNLOAD_ONLY}) + else() + set(DOWNLOAD_ONLY NO) + endif() + + if(DEFINED CPM_ARGS_GITHUB_REPOSITORY) + set(CPM_ARGS_GIT_REPOSITORY "https://github.com/${CPM_ARGS_GITHUB_REPOSITORY}.git") + elseif(DEFINED CPM_ARGS_GITLAB_REPOSITORY) + set(CPM_ARGS_GIT_REPOSITORY "https://gitlab.com/${CPM_ARGS_GITLAB_REPOSITORY}.git") + elseif(DEFINED CPM_ARGS_BITBUCKET_REPOSITORY) + set(CPM_ARGS_GIT_REPOSITORY "https://bitbucket.org/${CPM_ARGS_BITBUCKET_REPOSITORY}.git") + endif() + + if(DEFINED CPM_ARGS_GIT_REPOSITORY) + list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_REPOSITORY ${CPM_ARGS_GIT_REPOSITORY}) + if(NOT DEFINED CPM_ARGS_GIT_TAG) + set(CPM_ARGS_GIT_TAG v${CPM_ARGS_VERSION}) + endif() + + # If a name wasn't provided, try to infer it from the git repo + if(NOT DEFINED CPM_ARGS_NAME) + cpm_package_name_from_git_uri(${CPM_ARGS_GIT_REPOSITORY} CPM_ARGS_NAME) + endif() + endif() + + set(CPM_SKIP_FETCH FALSE) + + if(DEFINED CPM_ARGS_GIT_TAG) + list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_TAG ${CPM_ARGS_GIT_TAG}) + # If GIT_SHALLOW is explicitly specified, honor the value. + if(DEFINED CPM_ARGS_GIT_SHALLOW) + list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_SHALLOW ${CPM_ARGS_GIT_SHALLOW}) + endif() + endif() + + if(DEFINED CPM_ARGS_URL) + # If a name or version aren't provided, try to infer them from the URL + list(GET CPM_ARGS_URL 0 firstUrl) + cpm_package_name_and_ver_from_url(${firstUrl} nameFromUrl verFromUrl) + # If we fail to obtain name and version from the first URL, we could try other URLs if any. + # However multiple URLs are expected to be quite rare, so for now we won't bother. + + # If the caller provided their own name and version, they trump the inferred ones. + if(NOT DEFINED CPM_ARGS_NAME) + set(CPM_ARGS_NAME ${nameFromUrl}) + endif() + if(NOT DEFINED CPM_ARGS_VERSION) + set(CPM_ARGS_VERSION ${verFromUrl}) + endif() + + list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS URL "${CPM_ARGS_URL}") + endif() + + # Check for required arguments + + if(NOT DEFINED CPM_ARGS_NAME) + message( + FATAL_ERROR + "${CPM_INDENT} 'NAME' was not provided and couldn't be automatically inferred for package added with arguments: '${ARGN}'" + ) + endif() + + # Check if package has been added before + cpm_check_if_package_already_added(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}") + if(CPM_PACKAGE_ALREADY_ADDED) + cpm_export_variables(${CPM_ARGS_NAME}) + return() + endif() + + # Check for manual overrides + if(NOT CPM_ARGS_FORCE AND NOT "${CPM_${CPM_ARGS_NAME}_SOURCE}" STREQUAL "") + set(PACKAGE_SOURCE ${CPM_${CPM_ARGS_NAME}_SOURCE}) + set(CPM_${CPM_ARGS_NAME}_SOURCE "") + CPMAddPackage( + NAME "${CPM_ARGS_NAME}" + SOURCE_DIR "${PACKAGE_SOURCE}" + EXCLUDE_FROM_ALL "${CPM_ARGS_EXCLUDE_FROM_ALL}" + SYSTEM "${CPM_ARGS_SYSTEM}" + OPTIONS "${CPM_ARGS_OPTIONS}" + SOURCE_SUBDIR "${CPM_ARGS_SOURCE_SUBDIR}" + DOWNLOAD_ONLY "${DOWNLOAD_ONLY}" + FORCE True + ) + cpm_export_variables(${CPM_ARGS_NAME}) + return() + endif() + + # Check for available declaration + if(NOT CPM_ARGS_FORCE AND NOT "${CPM_DECLARATION_${CPM_ARGS_NAME}}" STREQUAL "") + set(declaration ${CPM_DECLARATION_${CPM_ARGS_NAME}}) + set(CPM_DECLARATION_${CPM_ARGS_NAME} "") + CPMAddPackage(${declaration}) + cpm_export_variables(${CPM_ARGS_NAME}) + # checking again to ensure version and option compatibility + cpm_check_if_package_already_added(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}") + return() + endif() + + if(NOT CPM_ARGS_FORCE) + if(CPM_USE_LOCAL_PACKAGES OR CPM_LOCAL_PACKAGES_ONLY) + cpm_find_package(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}" ${CPM_ARGS_FIND_PACKAGE_ARGUMENTS}) + + if(CPM_PACKAGE_FOUND) + cpm_export_variables(${CPM_ARGS_NAME}) + return() + endif() + + if(CPM_LOCAL_PACKAGES_ONLY) + message( + SEND_ERROR + "${CPM_INDENT} ${CPM_ARGS_NAME} not found via find_package(${CPM_ARGS_NAME} ${CPM_ARGS_VERSION})" + ) + endif() + endif() + endif() + + CPMRegisterPackage("${CPM_ARGS_NAME}" "${CPM_ARGS_VERSION}") + + if(DEFINED CPM_ARGS_GIT_TAG) + set(PACKAGE_INFO "${CPM_ARGS_GIT_TAG}") + elseif(DEFINED CPM_ARGS_SOURCE_DIR) + set(PACKAGE_INFO "${CPM_ARGS_SOURCE_DIR}") + else() + set(PACKAGE_INFO "${CPM_ARGS_VERSION}") + endif() + + if(DEFINED FETCHCONTENT_BASE_DIR) + # respect user's FETCHCONTENT_BASE_DIR if set + set(CPM_FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR}) + else() + set(CPM_FETCHCONTENT_BASE_DIR ${CMAKE_BINARY_DIR}/_deps) + endif() + + if(DEFINED CPM_ARGS_DOWNLOAD_COMMAND) + list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS DOWNLOAD_COMMAND ${CPM_ARGS_DOWNLOAD_COMMAND}) + elseif(DEFINED CPM_ARGS_SOURCE_DIR) + list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS SOURCE_DIR ${CPM_ARGS_SOURCE_DIR}) + if(NOT IS_ABSOLUTE ${CPM_ARGS_SOURCE_DIR}) + # Expand `CPM_ARGS_SOURCE_DIR` relative path. This is important because EXISTS doesn't work + # for relative paths. + get_filename_component( + source_directory ${CPM_ARGS_SOURCE_DIR} REALPATH BASE_DIR ${CMAKE_CURRENT_BINARY_DIR} + ) + else() + set(source_directory ${CPM_ARGS_SOURCE_DIR}) + endif() + if(NOT EXISTS ${source_directory}) + string(TOLOWER ${CPM_ARGS_NAME} lower_case_name) + # remove timestamps so CMake will re-download the dependency + file(REMOVE_RECURSE "${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-subbuild") + endif() + elseif(CPM_SOURCE_CACHE AND NOT CPM_ARGS_NO_CACHE) + string(TOLOWER ${CPM_ARGS_NAME} lower_case_name) + set(origin_parameters ${CPM_ARGS_UNPARSED_ARGUMENTS}) + list(SORT origin_parameters) + if(CPM_USE_NAMED_CACHE_DIRECTORIES) + string(SHA1 origin_hash "${origin_parameters};NEW_CACHE_STRUCTURE_TAG") + set(download_directory ${CPM_SOURCE_CACHE}/${lower_case_name}/${origin_hash}/${CPM_ARGS_NAME}) + else() + string(SHA1 origin_hash "${origin_parameters}") + set(download_directory ${CPM_SOURCE_CACHE}/${lower_case_name}/${origin_hash}) + endif() + # Expand `download_directory` relative path. This is important because EXISTS doesn't work for + # relative paths. + get_filename_component(download_directory ${download_directory} ABSOLUTE) + list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS SOURCE_DIR ${download_directory}) + + if(CPM_SOURCE_CACHE) + file(LOCK ${download_directory}/../cmake.lock) + endif() + + if(EXISTS ${download_directory}) + if(CPM_SOURCE_CACHE) + file(LOCK ${download_directory}/../cmake.lock RELEASE) + endif() + + cpm_store_fetch_properties( + ${CPM_ARGS_NAME} "${download_directory}" + "${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-build" + ) + cpm_get_fetch_properties("${CPM_ARGS_NAME}") + + if(DEFINED CPM_ARGS_GIT_TAG AND NOT (PATCH_COMMAND IN_LIST CPM_ARGS_UNPARSED_ARGUMENTS)) + # warn if cache has been changed since checkout + cpm_check_git_working_dir_is_clean(${download_directory} ${CPM_ARGS_GIT_TAG} IS_CLEAN) + if(NOT ${IS_CLEAN}) + message( + WARNING "${CPM_INDENT} Cache for ${CPM_ARGS_NAME} (${download_directory}) is dirty" + ) + endif() + endif() + + cpm_add_subdirectory( + "${CPM_ARGS_NAME}" + "${DOWNLOAD_ONLY}" + "${${CPM_ARGS_NAME}_SOURCE_DIR}/${CPM_ARGS_SOURCE_SUBDIR}" + "${${CPM_ARGS_NAME}_BINARY_DIR}" + "${CPM_ARGS_EXCLUDE_FROM_ALL}" + "${CPM_ARGS_SYSTEM}" + "${CPM_ARGS_OPTIONS}" + ) + set(PACKAGE_INFO "${PACKAGE_INFO} at ${download_directory}") + + # As the source dir is already cached/populated, we override the call to FetchContent. + set(CPM_SKIP_FETCH TRUE) + cpm_override_fetchcontent( + "${lower_case_name}" SOURCE_DIR "${${CPM_ARGS_NAME}_SOURCE_DIR}/${CPM_ARGS_SOURCE_SUBDIR}" + BINARY_DIR "${${CPM_ARGS_NAME}_BINARY_DIR}" + ) + + else() + # Enable shallow clone when GIT_TAG is not a commit hash. Our guess may not be accurate, but + # it should guarantee no commit hash get mis-detected. + if(NOT DEFINED CPM_ARGS_GIT_SHALLOW) + cpm_is_git_tag_commit_hash("${CPM_ARGS_GIT_TAG}" IS_HASH) + if(NOT ${IS_HASH}) + list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_SHALLOW TRUE) + endif() + endif() + + # remove timestamps so CMake will re-download the dependency + file(REMOVE_RECURSE ${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-subbuild) + set(PACKAGE_INFO "${PACKAGE_INFO} to ${download_directory}") + endif() + endif() + + cpm_create_module_file(${CPM_ARGS_NAME} "CPMAddPackage(\"${ARGN}\")") + + if(CPM_PACKAGE_LOCK_ENABLED) + if((CPM_ARGS_VERSION AND NOT CPM_ARGS_SOURCE_DIR) OR CPM_INCLUDE_ALL_IN_PACKAGE_LOCK) + cpm_add_to_package_lock(${CPM_ARGS_NAME} "${ARGN}") + elseif(CPM_ARGS_SOURCE_DIR) + cpm_add_comment_to_package_lock(${CPM_ARGS_NAME} "local directory") + else() + cpm_add_comment_to_package_lock(${CPM_ARGS_NAME} "${ARGN}") + endif() + endif() + + cpm_message( + STATUS "${CPM_INDENT} Adding package ${CPM_ARGS_NAME}@${CPM_ARGS_VERSION} (${PACKAGE_INFO})" + ) + + if(NOT CPM_SKIP_FETCH) + cpm_declare_fetch( + "${CPM_ARGS_NAME}" "${CPM_ARGS_VERSION}" "${PACKAGE_INFO}" "${CPM_ARGS_UNPARSED_ARGUMENTS}" + ) + cpm_fetch_package("${CPM_ARGS_NAME}" populated) + if(CPM_SOURCE_CACHE AND download_directory) + file(LOCK ${download_directory}/../cmake.lock RELEASE) + endif() + if(${populated}) + cpm_add_subdirectory( + "${CPM_ARGS_NAME}" + "${DOWNLOAD_ONLY}" + "${${CPM_ARGS_NAME}_SOURCE_DIR}/${CPM_ARGS_SOURCE_SUBDIR}" + "${${CPM_ARGS_NAME}_BINARY_DIR}" + "${CPM_ARGS_EXCLUDE_FROM_ALL}" + "${CPM_ARGS_SYSTEM}" + "${CPM_ARGS_OPTIONS}" + ) + endif() + cpm_get_fetch_properties("${CPM_ARGS_NAME}") + endif() + + set(${CPM_ARGS_NAME}_ADDED YES) + cpm_export_variables("${CPM_ARGS_NAME}") +endfunction() + +# Fetch a previously declared package +macro(CPMGetPackage Name) + if(DEFINED "CPM_DECLARATION_${Name}") + CPMAddPackage(NAME ${Name}) + else() + message(SEND_ERROR "${CPM_INDENT} Cannot retrieve package ${Name}: no declaration available") + endif() +endmacro() + +# export variables available to the caller to the parent scope expects ${CPM_ARGS_NAME} to be set +macro(cpm_export_variables name) + set(${name}_SOURCE_DIR + "${${name}_SOURCE_DIR}" + PARENT_SCOPE + ) + set(${name}_BINARY_DIR + "${${name}_BINARY_DIR}" + PARENT_SCOPE + ) + set(${name}_ADDED + "${${name}_ADDED}" + PARENT_SCOPE + ) + set(CPM_LAST_PACKAGE_NAME + "${name}" + PARENT_SCOPE + ) +endmacro() + +# declares a package, so that any call to CPMAddPackage for the package name will use these +# arguments instead. Previous declarations will not be overridden. +macro(CPMDeclarePackage Name) + if(NOT DEFINED "CPM_DECLARATION_${Name}") + set("CPM_DECLARATION_${Name}" "${ARGN}") + endif() +endmacro() + +function(cpm_add_to_package_lock Name) + if(NOT CPM_DONT_CREATE_PACKAGE_LOCK) + cpm_prettify_package_arguments(PRETTY_ARGN false ${ARGN}) + file(APPEND ${CPM_PACKAGE_LOCK_FILE} "# ${Name}\nCPMDeclarePackage(${Name}\n${PRETTY_ARGN})\n") + endif() +endfunction() + +function(cpm_add_comment_to_package_lock Name) + if(NOT CPM_DONT_CREATE_PACKAGE_LOCK) + cpm_prettify_package_arguments(PRETTY_ARGN true ${ARGN}) + file(APPEND ${CPM_PACKAGE_LOCK_FILE} + "# ${Name} (unversioned)\n# CPMDeclarePackage(${Name}\n${PRETTY_ARGN}#)\n" + ) + endif() +endfunction() + +# includes the package lock file if it exists and creates a target `cpm-update-package-lock` to +# update it +macro(CPMUsePackageLock file) + if(NOT CPM_DONT_CREATE_PACKAGE_LOCK) + get_filename_component(CPM_ABSOLUTE_PACKAGE_LOCK_PATH ${file} ABSOLUTE) + if(EXISTS ${CPM_ABSOLUTE_PACKAGE_LOCK_PATH}) + include(${CPM_ABSOLUTE_PACKAGE_LOCK_PATH}) + endif() + if(NOT TARGET cpm-update-package-lock) + add_custom_target( + cpm-update-package-lock COMMAND ${CMAKE_COMMAND} -E copy ${CPM_PACKAGE_LOCK_FILE} + ${CPM_ABSOLUTE_PACKAGE_LOCK_PATH} + ) + endif() + set(CPM_PACKAGE_LOCK_ENABLED true) + endif() +endmacro() + +# registers a package that has been added to CPM +function(CPMRegisterPackage PACKAGE VERSION) + list(APPEND CPM_PACKAGES ${PACKAGE}) + set(CPM_PACKAGES + ${CPM_PACKAGES} + CACHE INTERNAL "" + ) + set("CPM_PACKAGE_${PACKAGE}_VERSION" + ${VERSION} + CACHE INTERNAL "" + ) +endfunction() + +# retrieve the current version of the package to ${OUTPUT} +function(CPMGetPackageVersion PACKAGE OUTPUT) + set(${OUTPUT} + "${CPM_PACKAGE_${PACKAGE}_VERSION}" + PARENT_SCOPE + ) +endfunction() + +# declares a package in FetchContent_Declare +function(cpm_declare_fetch PACKAGE VERSION INFO) + if(${CPM_DRY_RUN}) + cpm_message(STATUS "${CPM_INDENT} Package not declared (dry run)") + return() + endif() + + FetchContent_Declare(${PACKAGE} ${ARGN}) +endfunction() + +# returns properties for a package previously defined by cpm_declare_fetch +function(cpm_get_fetch_properties PACKAGE) + if(${CPM_DRY_RUN}) + return() + endif() + + set(${PACKAGE}_SOURCE_DIR + "${CPM_PACKAGE_${PACKAGE}_SOURCE_DIR}" + PARENT_SCOPE + ) + set(${PACKAGE}_BINARY_DIR + "${CPM_PACKAGE_${PACKAGE}_BINARY_DIR}" + PARENT_SCOPE + ) +endfunction() + +function(cpm_store_fetch_properties PACKAGE source_dir binary_dir) + if(${CPM_DRY_RUN}) + return() + endif() + + set(CPM_PACKAGE_${PACKAGE}_SOURCE_DIR + "${source_dir}" + CACHE INTERNAL "" + ) + set(CPM_PACKAGE_${PACKAGE}_BINARY_DIR + "${binary_dir}" + CACHE INTERNAL "" + ) +endfunction() + +# adds a package as a subdirectory if viable, according to provided options +function( + cpm_add_subdirectory + PACKAGE + DOWNLOAD_ONLY + SOURCE_DIR + BINARY_DIR + EXCLUDE + SYSTEM + OPTIONS +) + + if(NOT DOWNLOAD_ONLY AND EXISTS ${SOURCE_DIR}/CMakeLists.txt) + set(addSubdirectoryExtraArgs "") + if(EXCLUDE) + list(APPEND addSubdirectoryExtraArgs EXCLUDE_FROM_ALL) + endif() + if("${SYSTEM}" AND "${CMAKE_VERSION}" VERSION_GREATER_EQUAL "3.25") + # https://cmake.org/cmake/help/latest/prop_dir/SYSTEM.html#prop_dir:SYSTEM + list(APPEND addSubdirectoryExtraArgs SYSTEM) + endif() + if(OPTIONS) + foreach(OPTION ${OPTIONS}) + cpm_parse_option("${OPTION}") + set(${OPTION_KEY} "${OPTION_VALUE}") + endforeach() + endif() + set(CPM_OLD_INDENT "${CPM_INDENT}") + set(CPM_INDENT "${CPM_INDENT} ${PACKAGE}:") + add_subdirectory(${SOURCE_DIR} ${BINARY_DIR} ${addSubdirectoryExtraArgs}) + set(CPM_INDENT "${CPM_OLD_INDENT}") + endif() +endfunction() + +# downloads a previously declared package via FetchContent and exports the variables +# `${PACKAGE}_SOURCE_DIR` and `${PACKAGE}_BINARY_DIR` to the parent scope +function(cpm_fetch_package PACKAGE populated) + set(${populated} + FALSE + PARENT_SCOPE + ) + if(${CPM_DRY_RUN}) + cpm_message(STATUS "${CPM_INDENT} Package ${PACKAGE} not fetched (dry run)") + return() + endif() + + FetchContent_GetProperties(${PACKAGE}) + + string(TOLOWER "${PACKAGE}" lower_case_name) + + if(NOT ${lower_case_name}_POPULATED) + FetchContent_Populate(${PACKAGE}) + set(${populated} + TRUE + PARENT_SCOPE + ) + endif() + + cpm_store_fetch_properties( + ${CPM_ARGS_NAME} ${${lower_case_name}_SOURCE_DIR} ${${lower_case_name}_BINARY_DIR} + ) + + set(${PACKAGE}_SOURCE_DIR + ${${lower_case_name}_SOURCE_DIR} + PARENT_SCOPE + ) + set(${PACKAGE}_BINARY_DIR + ${${lower_case_name}_BINARY_DIR} + PARENT_SCOPE + ) +endfunction() + +# splits a package option +function(cpm_parse_option OPTION) + string(REGEX MATCH "^[^ ]+" OPTION_KEY "${OPTION}") + string(LENGTH "${OPTION}" OPTION_LENGTH) + string(LENGTH "${OPTION_KEY}" OPTION_KEY_LENGTH) + if(OPTION_KEY_LENGTH STREQUAL OPTION_LENGTH) + # no value for key provided, assume user wants to set option to "ON" + set(OPTION_VALUE "ON") + else() + math(EXPR OPTION_KEY_LENGTH "${OPTION_KEY_LENGTH}+1") + string(SUBSTRING "${OPTION}" "${OPTION_KEY_LENGTH}" "-1" OPTION_VALUE) + endif() + set(OPTION_KEY + "${OPTION_KEY}" + PARENT_SCOPE + ) + set(OPTION_VALUE + "${OPTION_VALUE}" + PARENT_SCOPE + ) +endfunction() + +# guesses the package version from a git tag +function(cpm_get_version_from_git_tag GIT_TAG RESULT) + string(LENGTH ${GIT_TAG} length) + if(length EQUAL 40) + # GIT_TAG is probably a git hash + set(${RESULT} + 0 + PARENT_SCOPE + ) + else() + string(REGEX MATCH "v?([0123456789.]*).*" _ ${GIT_TAG}) + set(${RESULT} + ${CMAKE_MATCH_1} + PARENT_SCOPE + ) + endif() +endfunction() + +# guesses if the git tag is a commit hash or an actual tag or a branch name. +function(cpm_is_git_tag_commit_hash GIT_TAG RESULT) + string(LENGTH "${GIT_TAG}" length) + # full hash has 40 characters, and short hash has at least 7 characters. + if(length LESS 7 OR length GREATER 40) + set(${RESULT} + 0 + PARENT_SCOPE + ) + else() + if(${GIT_TAG} MATCHES "^[a-fA-F0-9]+$") + set(${RESULT} + 1 + PARENT_SCOPE + ) + else() + set(${RESULT} + 0 + PARENT_SCOPE + ) + endif() + endif() +endfunction() + +function(cpm_prettify_package_arguments OUT_VAR IS_IN_COMMENT) + set(oneValueArgs + NAME + FORCE + VERSION + GIT_TAG + DOWNLOAD_ONLY + GITHUB_REPOSITORY + GITLAB_REPOSITORY + BITBUCKET_REPOSITORY + GIT_REPOSITORY + SOURCE_DIR + FIND_PACKAGE_ARGUMENTS + NO_CACHE + SYSTEM + GIT_SHALLOW + EXCLUDE_FROM_ALL + SOURCE_SUBDIR + ) + set(multiValueArgs URL OPTIONS DOWNLOAD_COMMAND) + cmake_parse_arguments(CPM_ARGS "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + foreach(oneArgName ${oneValueArgs}) + if(DEFINED CPM_ARGS_${oneArgName}) + if(${IS_IN_COMMENT}) + string(APPEND PRETTY_OUT_VAR "#") + endif() + if(${oneArgName} STREQUAL "SOURCE_DIR") + string(REPLACE ${CMAKE_SOURCE_DIR} "\${CMAKE_SOURCE_DIR}" CPM_ARGS_${oneArgName} + ${CPM_ARGS_${oneArgName}} + ) + endif() + string(APPEND PRETTY_OUT_VAR " ${oneArgName} ${CPM_ARGS_${oneArgName}}\n") + endif() + endforeach() + foreach(multiArgName ${multiValueArgs}) + if(DEFINED CPM_ARGS_${multiArgName}) + if(${IS_IN_COMMENT}) + string(APPEND PRETTY_OUT_VAR "#") + endif() + string(APPEND PRETTY_OUT_VAR " ${multiArgName}\n") + foreach(singleOption ${CPM_ARGS_${multiArgName}}) + if(${IS_IN_COMMENT}) + string(APPEND PRETTY_OUT_VAR "#") + endif() + string(APPEND PRETTY_OUT_VAR " \"${singleOption}\"\n") + endforeach() + endif() + endforeach() + + if(NOT "${CPM_ARGS_UNPARSED_ARGUMENTS}" STREQUAL "") + if(${IS_IN_COMMENT}) + string(APPEND PRETTY_OUT_VAR "#") + endif() + string(APPEND PRETTY_OUT_VAR " ") + foreach(CPM_ARGS_UNPARSED_ARGUMENT ${CPM_ARGS_UNPARSED_ARGUMENTS}) + string(APPEND PRETTY_OUT_VAR " ${CPM_ARGS_UNPARSED_ARGUMENT}") + endforeach() + string(APPEND PRETTY_OUT_VAR "\n") + endif() + + set(${OUT_VAR} + ${PRETTY_OUT_VAR} + PARENT_SCOPE + ) + +endfunction() diff --git a/cmake/server.cmake b/cmake/server.cmake new file mode 100644 index 00000000..b6ef2ec4 --- /dev/null +++ b/cmake/server.cmake @@ -0,0 +1,104 @@ + +set(TRACY_CLIENT_SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../public/TracyClient.cpp + ${CMAKE_CURRENT_LIST_DIR}/../public/common/TracyStackFrames.cpp +) + +add_library(TracyClient STATIC ${TRACY_CLIENT_SOURCES}) +target_include_directories(TracyClient PUBLIC ${CMAKE_CURRENT_LIST_DIR}/../public) +target_compile_definitions(TracyClient PUBLIC TRACY_ENABLE) +if (TRACY_NO_STATISTICS) + target_compile_definitions(TracyClient PUBLIC TRACY_NO_STATISTICS) +endif() + +set(SERVER_SOURCES + TracyEventDebug.cpp + TracyTimelineController.cpp + TracyView_Playback.cpp + TracyTexture.cpp + TracyView_Locks.cpp + TracyView_Memory.cpp + TracyFileselector.cpp + TracyView_Compare.cpp + TracyView_ZoneInfo.cpp + TracyView_Callstack.cpp + TracySourceContents.cpp + TracyPrint.cpp + TracyStorage.cpp + TracyTextureCompression.cpp + TracySourceView.cpp + TracyView_ContextSwitch.cpp + TracyUserData.cpp + TracySourceTokenizer.cpp + TracyView_Statistics.cpp + TracyView_Timeline.cpp + TracyUtility.cpp + TracyTimelineItemCpuData.cpp + TracyView_FrameTree.cpp + TracyMicroArchitecture.cpp + TracyView_Ranges.cpp + TracyView.cpp + TracyMemory.cpp + TracyView_ConnectionState.cpp + TracyView_Navigation.cpp + TracyView_Utility.cpp + TracyView_Plots.cpp + TracyProtoHistory.cpp + TracyView_FrameTimeline.cpp + TracyView_FindZone.cpp + TracyThreadCompress.cpp + TracyImGui.cpp + TracyView_GpuTimeline.cpp + TracyTaskDispatch.cpp + TracyTimelineItemThread.cpp + TracyTimelineItemPlot.cpp + TracyWeb.cpp + TracyTimelineItem.cpp + TracyColor.cpp + TracyWorker.cpp + TracyView_FrameOverview.cpp + TracyView_Samples.cpp + TracyMouse.cpp + TracyView_Messages.cpp + TracyMmap.cpp + TracyView_ZoneTimeline.cpp + TracyView_Annotations.cpp + TracyFilesystem.cpp + TracyView_TraceInfo.cpp + TracyView_NotificationArea.cpp + TracyTimelineItemGpu.cpp + TracyView_CpuData.cpp + TracyBadVersion.cpp + TracyView_Options.cpp +) + +list(TRANSFORM SERVER_SOURCES PREPEND ${CMAKE_CURRENT_SOURCE_DIR}/../server/) + +add_library(TracyServer STATIC ${SERVER_SOURCES}) +target_include_directories(TracyServer PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../server) +target_link_libraries(TracyServer PUBLIC TracyImGui TracyCapstone TracyZstd TracyClient) + +target_compile_definitions(TracyServer PUBLIC NOMINMAX) # Windows.h defines min and max macros which conflict with std::min and std::max + +if (NOT NO_TBB) + target_link_libraries(TracyServer PUBLIC TracyTbb) +endif() + +if (TRACY_NO_STATISTICS) + message(STATUS "Disabling server statistics") + target_compile_definitions(TracyServer PUBLIC TRACY_NO_STATISTICS) +endif() + +if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + if (CMAKE_LINKER MATCHES "ld.mold") + set(LDFLAGS "-fuse-ld=mold") + endif() +endif() + +if (NOT TRACY_NO_ISA_EXTENSIONS) + if (CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64" OR CMAKE_SYSTEM_PROCESSOR MATCHES "arm64") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mcpu=native") + elseif(UNIX) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native") + endif() +endif() \ No newline at end of file diff --git a/cmake/vendor.cmake b/cmake/vendor.cmake new file mode 100644 index 00000000..29f537a2 --- /dev/null +++ b/cmake/vendor.cmake @@ -0,0 +1,227 @@ +# Vendor Specific CMake +# The Tracy project keeps most vendor source locally + +set (ROOT_DIR "${CMAKE_CURRENT_LIST_DIR}/../") + +# Dependencies are taken from the system first and if not found, they are pulled with CPM and built from source + +include(FindPkgConfig) +include(${CMAKE_CURRENT_LIST_DIR}/CPM.cmake) + +option(TRACY_DOWNLOAD_CAPSTONE "Force download capstone" OFF) +option(TRACY_DOWNLOAD_GLFW "Force download glfw" OFF) +option(TRACY_DOWNLOAD_FREETYPE "Force download freetype" OFF) + +# capstone + +# pkg_check_modules(CAPSTONE capstone) +if(CAPSTONE_FOUND AND NOT TRACY_DOWNLOAD_CAPSTONE) + message(STATUS "Capstone found: ${CAPSTONE}") + add_library(TracyCapstone INTERFACE) + target_include_directories(TracyCapstone INTERFACE ${CAPSTONE_INCLUDE_DIRS}) + target_link_libraries(TracyCapstone INTERFACE ${CAPSTONE_LINK_LIBRARIES}) +else() + CPMAddPackage( + NAME capstone + GITHUB_REPOSITORY capstone-engine/capstone + GIT_TAG 5.0.1 + ) + add_library(TracyCapstone INTERFACE) + target_link_libraries(TracyCapstone INTERFACE capstone) + + target_include_directories(TracyCapstone INTERFACE ${capstone_SOURCE_DIR}/include/capstone) +endif() + +# GLFW + +if (NOT UNIX) + set(LEGACY ON) +endif() + +if (LEGACY) + pkg_check_modules(GLFW glfw3) + if (GLFW_FOUND AND NOT TRACY_DOWNLOAD_GLFW) + add_library(TracyGlfw3 INTERFACE) + target_include_directories(TracyGlfw3 INTERFACE ${GLFW_INCLUDE_DIRS}) + target_link_libraries(TracyGlfw3 INTERFACE ${GLFW_LINK_LIBRARIES}) + else() + CPMAddPackage( + NAME glfw + GITHUB_REPOSITORY glfw/glfw + GIT_TAG 3.3.9 + ) + add_library(TracyGlfw3 INTERFACE) + target_link_libraries(TracyGlfw3 INTERFACE glfw) + endif() +endif() + +# freetype + +pkg_check_modules(FREETYPE freetype2) +if (FREETYPE_FOUND AND NOT TRACY_DOWNLOAD_FREETYPE) + add_library(TracyFreetype INTERFACE) + target_include_directories(TracyFreetype INTERFACE ${FREETYPE_INCLUDE_DIRS}) + target_link_libraries(TracyFreetype INTERFACE ${FREETYPE_LINK_LIBRARIES}) +else() + CPMAddPackage( + NAME freetype + GITHUB_REPOSITORY freetype/freetype + GIT_TAG VER-2-13-2 + ) + add_library(TracyFreetype INTERFACE) + target_link_libraries(TracyFreetype INTERFACE freetype) +endif() + +# zstd + +set(ZSTD_DIR "${ROOT_DIR}/zstd") + +set(ZSTD_SOURCES + decompress/zstd_ddict.c + decompress/zstd_decompress_block.c + decompress/huf_decompress.c + decompress/zstd_decompress.c + common/zstd_common.c + common/error_private.c + common/xxhash.c + common/entropy_common.c + common/debug.c + common/threading.c + common/pool.c + common/fse_decompress.c + compress/zstd_ldm.c + compress/zstd_compress_superblock.c + compress/zstd_opt.c + compress/zstd_compress_sequences.c + compress/fse_compress.c + compress/zstd_double_fast.c + compress/zstd_compress.c + compress/zstd_compress_literals.c + compress/hist.c + compress/zstdmt_compress.c + compress/zstd_lazy.c + compress/huf_compress.c + compress/zstd_fast.c + dictBuilder/zdict.c + dictBuilder/cover.c + dictBuilder/divsufsort.c + dictBuilder/fastcover.c + + # Assembly + decompress/huf_decompress_amd64.S +) + +list(TRANSFORM ZSTD_SOURCES PREPEND "${ZSTD_DIR}/") + +set_property(SOURCE ${ZSTD_DIR}/decompress/huf_decompress_amd64.S APPEND PROPERTY COMPILE_OPTIONS "-x" "assembler-with-cpp") + +add_library(TracyZstd STATIC ${ZSTD_SOURCES}) +target_include_directories(TracyZstd PUBLIC ${ZSTD_DIR}) + + +# Diff Template Library + +set(DTL_DIR "${ROOT_DIR}/dtl") +file(GLOB_RECURSE DTL_HEADERS CONFIGURE_DEPENDS RELATIVE ${DTL_DIR} "*.hpp") +add_library(TracyDtl INTERFACE) +target_sources(TracyDtl INTERFACE ${DTL_HEADERS}) +target_include_directories(TracyDtl INTERFACE ${DTL_DIR}) + +# Get Opt + +set(GETOPT_DIR "${ROOT_DIR}/getopt") +set(GETOPT_SOURCES ${GETOPT_DIR}/getopt.c) +set(GETOPT_HEADERS ${GETOPT_DIR}/getopt.h) +add_library(TracyGetOpt STATIC ${GETOPT_SOURCES} ${GETOPT_HEADERS}) +target_include_directories(TracyGetOpt PUBLIC ${GETOPT_DIR}) + + +# ImGui + +set(IMGUI_DIR "${ROOT_DIR}/imgui") + +set(IMGUI_SOURCES + ${IMGUI_DIR}/imgui_widgets.cpp + ${IMGUI_DIR}/imgui_draw.cpp + ${IMGUI_DIR}/imgui_demo.cpp + ${IMGUI_DIR}/imgui.cpp + ${IMGUI_DIR}/imgui_tables.cpp +) + +set(IMGUI_FREETYPE_SOURCES + ${IMGUI_DIR}/misc/freetype/imgui_freetype.cpp +) + +add_library(TracyImGui STATIC ${IMGUI_SOURCES} ${IMGUI_FREETYPE_SOURCES}) +target_include_directories(TracyImGui PUBLIC ${IMGUI_DIR}) +target_link_libraries(TracyImGui PUBLIC TracyFreetype) + +if (LEGACY) + target_link_libraries(TracyImGui PUBLIC TracyGlfw3) +endif() + +# NFD + +if (NOT TRACY_NO_FILESELECTOR) + set(NFD_DIR "${ROOT_DIR}/nfd") + + if (WIN32) + set(NFD_SOURCES "${NFD_DIR}/nfd_win.cpp") + elseif (APPLE) + set(NFD_SOURCES "${NFD_DIR}/nfd_cocoa.m") + else() + if (TRACY_GTK_FILESELECTOR) + set(NFD_SOURCES "${NFD_DIR}/nfd_gtk.cpp") + else() + set(NFD_SOURCES "${NFD_DIR}/nfd_portal.cpp") + endif() + endif() + + file(GLOB_RECURSE NFD_HEADERS CONFIGURE_DEPENDS RELATIVE ${NFD_DIR} "*.h") + add_library(TracyNfd STATIC ${NFD_SOURCES} ${NFD_HEADERS}) + target_include_directories(TracyNfd PUBLIC ${NFD_DIR}) + + if (APPLE) + find_library(APPKIT_LIBRARY AppKit) + find_library(UNIFORMTYPEIDENTIFIERS_LIBRARY UniformTypeIdentifiers) + target_link_libraries(TracyNfd PUBLIC ${APPKIT_LIBRARY} ${UNIFORMTYPEIDENTIFIERS_LIBRARY}) + endif() + + + if (UNIX) + if (TRACY_GTK_FILESELECTOR) + pkg_check_modules(GTK3 gtk+-3.0) + if (NOT GTK3_FOUND) + message(FATAL_ERROR "GTK3 not found. Please install it or set TRACY_GTK_FILESELECTOR to OFF.") + endif() + add_library(TracyGtk3 INTERFACE) + target_include_directories(TracyGtk3 INTERFACE ${GTK3_INCLUDE_DIRS}) + target_link_libraries(TracyGtk3 INTERFACE ${GTK3_LINK_LIBRARIES}) + target_link_libraries(TracyNfd PUBLIC TracyGtk3) + else() + pkg_check_modules(DBUS dbus-1) + if (NOT DBUS_FOUND) + message(FATAL_ERROR "D-Bus not found. Please install it or set TRACY_GTK_FILESELECTOR to ON.") + endif() + add_library(TracyDbus INTERFACE) + target_include_directories(TracyDbus INTERFACE ${DBUS_INCLUDE_DIRS}) + target_link_libraries(TracyDbus INTERFACE ${DBUS_LINK_LIBRARIES}) + target_link_libraries(TracyNfd PUBLIC TracyDbus) + endif() + endif() +endif() + +# TBB + +if (NOT NO_TBB) + # Tracy does not use TBB directly, but the implementation of parallel algorithms + # in some versions of libstdc++ depends on TBB. When it does, you must + # explicitly link against -ltbb. + # + # Some distributions have pgk-config files for TBB, others don't. + + pkg_check_modules(TBB tbb) + add_library(TracyTbb INTERFACE) + target_include_directories(TracyTbb INTERFACE ${TBB_INCLUDE_DIRS}) + target_link_libraries(TracyTbb INTERFACE ${TBB_LINK_LIBRARIES}) +endif() \ No newline at end of file diff --git a/version.cmake b/cmake/version.cmake similarity index 85% rename from version.cmake rename to cmake/version.cmake index 02ca8748..18eee5e7 100644 --- a/version.cmake +++ b/cmake/version.cmake @@ -1,8 +1,10 @@ cmake_minimum_required(VERSION 3.10) +set(ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/..) + message("Parsing public/common/TracyVersion.hpp file") -file(READ "public/common/TracyVersion.hpp" version) +file(READ "${ROOT_DIR}/public/common/TracyVersion.hpp" version) # Note: This looks for a specific pattern in TracyVersion.hpp, if it changes # this needs updating. diff --git a/csvexport/CMakeLists.txt b/csvexport/CMakeLists.txt new file mode 100644 index 00000000..90f9d993 --- /dev/null +++ b/csvexport/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.19) +project(csvexport C CXX ASM) + +set(CMAKE_CXX_STANDARD 17) + +include(${CMAKE_CURRENT_LIST_DIR}/../cmake/vendor.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/../cmake/server.cmake) + +set(CSVEXPORT_SRC + src/csvexport.cpp +) + +add_executable(csvexport ${CSVEXPORT_SRC}) +target_include_directories(csvexport PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) +target_link_libraries(csvexport PRIVATE TracyServer) \ No newline at end of file diff --git a/import-chrome/CMakeLists.txt b/import-chrome/CMakeLists.txt new file mode 100644 index 00000000..b9f54708 --- /dev/null +++ b/import-chrome/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.19) +project(import-chrome C CXX ASM) + +set(CMAKE_CXX_STANDARD 17) + +include(${CMAKE_CURRENT_LIST_DIR}/../cmake/vendor.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/../cmake/server.cmake) + +set(SOURCES + src/import-chrome.cpp +) + +add_executable(import-chrome ${SOURCES}) +target_include_directories(import-chrome PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) +target_link_libraries(import-chrome PRIVATE TracyServer) \ No newline at end of file diff --git a/import-fuchsia/CMakeLists.txt b/import-fuchsia/CMakeLists.txt new file mode 100644 index 00000000..bf76d6e3 --- /dev/null +++ b/import-fuchsia/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.19) +project(import-fuchsia C CXX ASM) + +set(CMAKE_CXX_STANDARD 17) + +include(${CMAKE_CURRENT_LIST_DIR}/../cmake/vendor.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/../cmake/server.cmake) + +set(SOURCES + src/import-fuchsia.cpp +) + +add_executable(import-fuchsia ${SOURCES}) +target_include_directories(import-fuchsia PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) +target_link_libraries(import-fuchsia PRIVATE TracyServer) \ No newline at end of file diff --git a/profiler/CMakeLists.txt b/profiler/CMakeLists.txt new file mode 100644 index 00000000..0de138cd --- /dev/null +++ b/profiler/CMakeLists.txt @@ -0,0 +1,59 @@ +cmake_minimum_required(VERSION 3.19) +project(Profiler C CXX ASM) + +set(CMAKE_CXX_STANDARD 17) + +include(${CMAKE_CURRENT_LIST_DIR}/../cmake/vendor.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/../cmake/server.cmake) + +set(PROFILER_SOURCE + src/ImGuiContext.cpp + src/HttpRequest.cpp + src/RunQueue.cpp + src/main.cpp + src/winmainArchDiscovery.cpp + src/winmain.cpp + src/WindowPosition.cpp + src/imgui/imgui_impl_opengl3.cpp + src/ResolvService.cpp + src/Fonts.cpp + src/ConnectionHistory.cpp + src/IsElevated.cpp + src/Filters.cpp + src/ini.c +) + +set(GLFW_SOURCE + src/BackendGlfw.cpp + src/imgui/imgui_impl_glfw.cpp +) + +set(WAYLAND_SOURCE + src/wayland/xdg-decoration.c + src/wayland/xdg-shell.c + src/wayland/xdg-activation.c + src/BackendWayland.cpp +) + +if (NOT UNIX) + set(LEGACY ON) +endif() + +if (LEGACY) + message(STATUS "Using legacy backend") + list(APPEND PROFILER_SOURCE ${GLFW_SOURCE}) +else() + message(STATUS "Using Wayland backend") + list(APPEND PROFILER_SOURCE ${WAYLAND_SOURCE}) +endif() + + +add_executable(Tracy ${PROFILER_SOURCE}) +target_include_directories(Tracy PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) +target_link_libraries(Tracy PRIVATE TracyImGui TracyServer) + +if (TRACY_NO_FILESELECTOR) + target_compile_definitions(Tracy PRIVATE TRACY_NO_FILESELECTOR) +else() + target_link_libraries(Tracy PRIVATE TracyNfd) +endif() diff --git a/public/TracyClient.cpp b/public/TracyClient.cpp index 26387b76..a39450bc 100644 --- a/public/TracyClient.cpp +++ b/public/TracyClient.cpp @@ -20,6 +20,7 @@ #endif #include "common/tracy_lz4.cpp" +#include "common/tracy_lz4hc.cpp" #include "client/TracyProfiler.cpp" #include "client/TracyCallstack.cpp" #include "client/TracySysPower.cpp" diff --git a/public/client/TracyFastVector.hpp b/public/client/TracyFastVector.hpp index 38accc92..0114bc2e 100644 --- a/public/client/TracyFastVector.hpp +++ b/public/client/TracyFastVector.hpp @@ -3,6 +3,7 @@ #include #include +#include #include "../common/TracyAlloc.hpp" #include "../common/TracyForceInline.hpp" diff --git a/server/TracyView.hpp b/server/TracyView.hpp index 05ac2ebd..4bd2bb83 100644 --- a/server/TracyView.hpp +++ b/server/TracyView.hpp @@ -26,6 +26,11 @@ #include "TracyWorker.hpp" #include "tracy_robin_hood.h" +// Windows defines small +#ifdef small +#undef small +#endif + namespace tracy { diff --git a/update/CMakeLists.txt b/update/CMakeLists.txt new file mode 100644 index 00000000..568c605a --- /dev/null +++ b/update/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.19) +project(update C CXX ASM) + +set(CMAKE_CXX_STANDARD 17) + +include(${CMAKE_CURRENT_LIST_DIR}/../cmake/vendor.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/../cmake/server.cmake) + +set(UPDATE_SOURCE + src/OfflineSymbolResolverDbgHelper.cpp + src/OfflineSymbolResolver.cpp + src/OfflineSymbolResolverAddr2Line.cpp + src/update.cpp +) + +add_executable(update ${UPDATE_SOURCE}) +target_include_directories(update PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) +target_link_libraries(update PRIVATE TracyServer) \ No newline at end of file