8feb6bf8b6
- The primary feature of this PR is the **addition of support for scoping the collection of tracing/profiling data into one or more time-based windows** - Closes #222 - Closes #207 - Support for a real-clock time delay and/or a duration for tracing/profiling was added, *resembling the support for this feature during sampling and process-sampling* - However, above paradigm was enhanced for tracing - Instead of one delay and/or one duration based on real time, ***tracing supports periodic and varying delays and durations and these delay+duration sets can be controlled with different clocks*** - At some point, this capability will be extended to sampling and process-sampling - A secondary feature of this PR are the improvements to the handling of categories (by-product of the primary feature) - For example, previously setting `OMNITRACE_ENABLE_CATEGORIES` to a specific set of categories only eliminated the disabled categories from the perfetto trace, now these are applied to timemory profiles too - A new configuration variable `OMNITRACE_DISABLE_CATEGORIES` was added for when disabling only a handful of categories is easier - There are quite a few miscellaneous modifications which pollute this PR a bit ## Multiple Tracing Windows As noted above, tracing now supports specifying multiple delays and durations _and_ with different clocks. Consider the configuration below with two entries in the format `<DELAY>:<DURATION>:<REPEAT>:<CLOCK_TYPE>`: ```console OMNITRACE_TRACE_PERIODS = 0.5:1.0:2:realtime 10.0:5.0:3:cputime ``` The above configuration defines: 1. `0.5:1.0:2:realtime` - A delay of 0.5 seconds (real-time) - Followed by a data collection duration of 1 second (real-time) - This delay + duration is repeated 2x - Summary: tracing data is collected for 2 out of the first 3 seconds of the application's execution 2. `10.0:5.0:3:cputime` - A delay of 10 seconds (process _CPU-time_) - Followed by a data collection duration of 5 seconds (process _CPU-time_) - This delay + duration is repeated 3x - Summary: tracing data is collected for a total of 15 seconds of process CPU-time in the ensuing 75 seconds of CPU-time during the application execution. - Note: the elapsed CPU-time is the aggregate of the CPU-time consumed by all the threads in the process and should be scaled accordingly, e.g., 4 threads running constantly for 1 second of real-time is ~4 seconds of CPU time. ## `omnitrace-sample` Changes Formerly, `--wait` and `--duration` command-line options only applied to sampling delay and duration. The value of these options are now applied to the tracing delay and duration. To retain the ability to control sampling delay/duration without setting tracing delay/duration or vice versa, `--sampling-wait`, `--sampling-duration`, `--trace-wait`, and `--trace-duration` options were added. `omnitrace-sample` also has new options for most of the new configuration options detailed below. ## New configuration options | Option | Description | | ------- | ----------- | | `OMNITRACE_DISABLE_CATEGORIES` | inverse behavior from `OMNITRACE_ENABLE_CATEGORIES` -- populates list of all available categories and then removes the specified ones. | | `OMNITRACE_TRACE_DELAY` | Single floating-point number specifying time to wait before starting data collection. Analagous to `OMNITRACE_SAMPLING_DELAY` and `OMNITRACE_PROCESS_SAMPLING_DELAY` | | `OMNITRACE_TRACE_DURATION` | Single floating-point number specifying data collection duration. Analagous to `OMNITRACE_SAMPLING_DURATION` and `OMNITRACE_PROCESS_SAMPLING_DURATION` | | `OMNITRACE_TRACE_PERIOD_CLOCK_ID` | Sets the default clock-type for tracing delay/duration. Always applied to above two options, can be overridden in below option. Accepts `CLOCK_REALTIME`, `CLOCK_MONOTONIC`, `CLOCK_PROCESS_CPUTIME_ID`, `CLOCK_MONOTONIC_RAW`, `CLOCK_REALTIME_COARSE`, `CLOCK_MONOTONIC_COARSE`, `CLOCK_BOOTTIME`. See `man 2 clock_gettime` for details on differences. | | `OMNITRACE_TRACE_PERIODS` | More powerful version for specifying delay + duration. Supports formats: `<DELAY>`, `<DELAY>:<DURATION>`, `<DELAY>:<DURATION>:<REPEAT>`, and `<DELAY>:<DURATION>:<REPEAT>:<CLOCK_ID>`. | ## Miscellaneous Changes - Expanded `critical_trace_categories_t` to include tracing data from MPI, pthread, HIP, HSA, RCCL, NUMA, and Python. - Added categories `thread_wall_time` and `thread_cpu_time` (derived from sampling) - Read DWARF info for breakpoints - Relocated some source code - Reason: necessary to make `libomnitrace` a bit more modular. Eventually, a large chunk will be separated into `libomnitrace-core`, `libomnitrace-binary`, etc. in order to facilitate re-usability - Relocated some functionality from `runtime.cpp` to `config.cpp` - Relocated code using rocm-smi library to query number of devices to `gpu.cpp` (where the code for using HIP to query number of devices is) - Relocated code for perfetto config and perfetto session out of tracing namespace to reside with other perfetto code - `OMNITRACE_COLORIZED_LOG` configuration option renamed to `OMNITRACE_MONOCHROME` - Backwards compatibility via a deprecated option was not retained here since the logic changed (i.e. true in former means false in latter) - Replaced `TIMEMORY_DEFAULT_OBJECT` macro with `OMNITRACE_DEFAULT_OBJECT` macro - Updated some code in roctracer to use `component::category_region` instead of explicitly using `tracing::` functions - Updated `backtrace_metrics` to better support controlling their presence in the traces/profiles via categories - Added support for `--print` in `validate-timemory-json.py` - Generic `OMNITRACE_ADD_VALIDATION_TEST` CMake function ## Git Log * OMNITRACE_DEFAULT_OBJECT - replace TIMEMORY_DEFAULT_OBJECT with TIMEMORY_DEFAULT_OBJECT * trace-time-window example + tests - adds cmake OMNITRACE_ADD_VALIDATION_TEST function for testing - validate-timemory-json.py now supports printing (-p) - update to OMNITRACE_STRIP_TARGET * Update timemory submodule - detailed backtrace print /proc/<PID>/maps - operation::push_node verbosity change - storage::insert_hierarchy use emplace + at instead of operator[] - concepts::is_type_listing - argparse updates for start/end group - argparse color fixes * perfetto updates - Remove OMNITRACE_CUSTOM_DATA_SOURCE CMake option - move tracing::get_perfetto_config and tracing::get_perfetto_session to perfetto.cpp * config and runtime updates - OMNITRACE_DISABLE_CATEGORIES option - get_enabled_categories() + get_disabled_categories() - config impl handles populating them - OMNITRACE_TRACE_DELAY option - OMNITRACE_TRACE_DURATION option - OMNITRACE_TRACE_PERIODS option - {get,set}_signal_handler - removes config.cpp link dependency for omnitrace_finalize - get_realtime_signal() + get_cputime_signal() + get_sampling_signals() - moved from runtime.cpp to config.cpp * utility::convert - helper function for converting string to a type * pthread_create_gotcha + thread_info updates - thread_index_data::as_string() - tweak printing info about new thread / exited thread * binary updates - get_binary_info has arg to disable dwarf parsing - binary_info contains vector of breakpoint addresses - binary_info:filename() function - binary::get_linked_path - binary::get_link_map has args for dlopen mode - symbol::read_dwarf -> symbol::read_dwarf_entries - symbol::read_dwarf_breakpoints * library updates + categories impl - implement config::set_signal_handler - categories.cpp for handling trace delays - implement trace delay/duration/periods * concepts + debug + defines - tuple_element in concepts - removed runtime header from debug header - OMNITRACE_DEFAULT_COPY_MOVE * gpu + rocm_smi - moved rsmi_num_monitor_devices call to gpu.cpp - gpu::rsmi_device_count() * roctracer updates - roctracer_bundle_t -> roctracer_hip_bundle_t - use category_region instead of explicit tracing push/pop calls * sampling + backtrace_metrics - rework backtrace_metrics to support categories * tracing updates - category stack counters (i.e. push vs. pop counter) for profiling and tracing - push_timemory and pop_timemory accept string_view instead of const char* - tweaked the pop_timemory hash search - {push,pop}_perfetto theoretically supports same invocations as for {push,pop}_perfetto_ts and {push,pop}_perfetto_track - mark_perfetto, mark_perfetto_ts, mark_perfetto_track * category_region update - expanded the critical trace categories - use category_push_disabled - use category_pop_disabled - use category_mark_disabled * constraint implementation - This provides generic functionality for constraining data collection within a windows of time. - E.g., delay, delay + duration, (delay + duration) * nrepeat * COLORIZED_LOG -> MONOCHROME * constraint + omnitrace-causal + omnitrace-sample updates - support for using different clock IDs for constraints - OMNITRACE_TRACE_PERIOD_CLOCK_ID option - tweak to trace-time-window example - tweak to trace-time-window tests * Fix formatting * Update time-window tests - Fix detection of validation support for perfetto - Using the --caller-include feature + runtime instrumentation on Ubuntu 18.04 and OpenSUSE 15.2 results in a segfault in the internals of Dyninst. - For now, mark that these tests will fail - Later, determine if updating Dyninst submodule fixes this problem * Fix OMNITRACE_OUTPUT_PATH for all tests - Provide absolute path instead of relative * Tweak lambda for checking whether HW counters are enabled - causing strange build errors on older GCC compilers * Update dyninst submodule - fix issues with using --caller-include for Ubuntu 18.04, OpenSUSE 15.x * cmake formatting * fix sampling compiler issue for GCC 8 * Tweak thread create message * Increase causal validation iterations
896 líneas
33 KiB
CMake
896 líneas
33 KiB
CMake
# include guard
|
|
include_guard(DIRECTORY)
|
|
|
|
# MacroUtilities - useful macros and functions for generic tasks
|
|
#
|
|
|
|
cmake_policy(PUSH)
|
|
cmake_policy(SET CMP0054 NEW)
|
|
cmake_policy(SET CMP0057 NEW)
|
|
|
|
include(CMakeDependentOption)
|
|
include(CMakeParseArguments)
|
|
|
|
# -----------------------------------------------------------------------
|
|
# message which handles OMNITRACE_QUIET_CONFIG settings
|
|
# -----------------------------------------------------------------------
|
|
#
|
|
function(OMNITRACE_MESSAGE TYPE)
|
|
if(NOT OMNITRACE_QUIET_CONFIG)
|
|
message(${TYPE} "[omnitrace] ${ARGN}")
|
|
endif()
|
|
endfunction()
|
|
|
|
# -----------------------------------------------------------------------
|
|
# Save a set of variables with the given prefix
|
|
# -----------------------------------------------------------------------
|
|
macro(OMNITRACE_SAVE_VARIABLES _PREFIX)
|
|
# parse args
|
|
cmake_parse_arguments(
|
|
SAVE
|
|
"" # options
|
|
"CONDITION" # single value args
|
|
"VARIABLES" # multiple value args
|
|
${ARGN})
|
|
if(DEFINED SAVE_CONDITION AND NOT "${SAVE_CONDITION}" STREQUAL "")
|
|
if(${SAVE_CONDITION})
|
|
foreach(_VAR ${SAVE_VARIABLES})
|
|
if(DEFINED ${_VAR})
|
|
set(${_PREFIX}_${_VAR} "${${_VAR}}")
|
|
else()
|
|
message(AUTHOR_WARNING "${_VAR} is not defined")
|
|
endif()
|
|
endforeach()
|
|
endif()
|
|
else()
|
|
foreach(_VAR ${SAVE_VARIABLES})
|
|
if(DEFINED ${_VAR})
|
|
set(${_PREFIX}_${_VAR} "${${_VAR}}")
|
|
else()
|
|
message(AUTHOR_WARNING "${_VAR} is not defined")
|
|
endif()
|
|
endforeach()
|
|
endif()
|
|
unset(SAVE_CONDITION)
|
|
unset(SAVE_VARIABLES)
|
|
endmacro()
|
|
|
|
# -----------------------------------------------------------------------
|
|
# Restore a set of variables with the given prefix
|
|
# -----------------------------------------------------------------------
|
|
macro(OMNITRACE_RESTORE_VARIABLES _PREFIX)
|
|
# parse args
|
|
cmake_parse_arguments(
|
|
RESTORE
|
|
"" # options
|
|
"CONDITION" # single value args
|
|
"VARIABLES" # multiple value args
|
|
${ARGN})
|
|
if(DEFINED RESTORE_CONDITION AND NOT "${RESTORE_CONDITION}" STREQUAL "")
|
|
if(${RESTORE_CONDITION})
|
|
foreach(_VAR ${RESTORE_VARIABLES})
|
|
if(DEFINED ${_PREFIX}_${_VAR})
|
|
set(${_VAR} ${${_PREFIX}_${_VAR}})
|
|
unset(${_PREFIX}_${_VAR})
|
|
else()
|
|
message(AUTHOR_WARNING "${_PREFIX}_${_VAR} is not defined")
|
|
endif()
|
|
endforeach()
|
|
endif()
|
|
else()
|
|
foreach(_VAR ${RESTORE_VARIABLES})
|
|
if(DEFINED ${_PREFIX}_${_VAR})
|
|
set(${_VAR} ${${_PREFIX}_${_VAR}})
|
|
unset(${_PREFIX}_${_VAR})
|
|
else()
|
|
message(AUTHOR_WARNING "${_PREFIX}_${_VAR} is not defined")
|
|
endif()
|
|
endforeach()
|
|
endif()
|
|
unset(RESTORE_CONDITION)
|
|
unset(RESTORE_VARIABLES)
|
|
endmacro()
|
|
|
|
# -----------------------------------------------------------------------
|
|
# function - omnitrace_capitalize - make a string capitalized (first letter is capital)
|
|
# usage: capitalize("SHARED" CShared) message(STATUS "-- CShared is \"${CShared}\"") $ --
|
|
# CShared is "Shared"
|
|
function(OMNITRACE_CAPITALIZE str var)
|
|
# make string lower
|
|
string(TOLOWER "${str}" str)
|
|
string(SUBSTRING "${str}" 0 1 _first)
|
|
string(TOUPPER "${_first}" _first)
|
|
string(SUBSTRING "${str}" 1 -1 _remainder)
|
|
string(CONCAT str "${_first}" "${_remainder}")
|
|
set(${var}
|
|
"${str}"
|
|
PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
# ------------------------------------------------------------------------------#
|
|
# function omnitrace_strip_target(<TARGET> [FORCE] [EXPLICIT])
|
|
#
|
|
# Creates a post-build command which strips a binary. FORCE flag will override
|
|
#
|
|
function(OMNITRACE_STRIP_TARGET)
|
|
cmake_parse_arguments(STRIP "FORCE;EXPLICIT" "" "ARGS" ${ARGN})
|
|
|
|
list(LENGTH STRIP_UNPARSED_ARGUMENTS NUM_UNPARSED)
|
|
|
|
if(NUM_UNPARSED EQUAL 1)
|
|
set(_TARGET "${STRIP_UNPARSED_ARGUMENTS}")
|
|
else()
|
|
omnitrace_message(FATAL_ERROR
|
|
"omnitrace_strip_target cannot deduce target from \"${ARGN}\"")
|
|
endif()
|
|
|
|
if(NOT TARGET "${_TARGET}")
|
|
omnitrace_message(
|
|
FATAL_ERROR
|
|
"omnitrace_strip_target not provided valid target: \"${_TARGET}\"")
|
|
endif()
|
|
|
|
if(CMAKE_STRIP AND (STRIP_FORCE OR OMNITRACE_STRIP_LIBRARIES))
|
|
if(STRIP_EXPLICIT)
|
|
add_custom_command(
|
|
TARGET ${_TARGET}
|
|
POST_BUILD
|
|
COMMAND ${CMAKE_STRIP} ${STRIP_ARGS} $<TARGET_FILE:${_TARGET}>
|
|
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
|
COMMENT "Stripping ${_TARGET}...")
|
|
else()
|
|
add_custom_command(
|
|
TARGET ${_TARGET}
|
|
POST_BUILD
|
|
COMMAND
|
|
${CMAKE_STRIP} -w --keep-symbol="omnitrace_init"
|
|
--keep-symbol="omnitrace_finalize"
|
|
--keep-symbol="omnitrace_push_trace"
|
|
--keep-symbol="omnitrace_pop_trace"
|
|
--keep-symbol="omnitrace_push_region"
|
|
--keep-symbol="omnitrace_pop_region" --keep-symbol="omnitrace_set_env"
|
|
--keep-symbol="omnitrace_set_mpi"
|
|
--keep-symbol="omnitrace_reset_preload"
|
|
--keep-symbol="omnitrace_user_*" --keep-symbol="ompt_start_tool"
|
|
--keep-symbol="kokkosp_*" --keep-symbol="OnLoad"
|
|
--keep-symbol="OnUnload" --keep-symbol="OnLoadToolProp"
|
|
--keep-symbol="OnUnloadTool" --keep-symbol="__libc_start_main"
|
|
${STRIP_ARGS} $<TARGET_FILE:${_TARGET}>
|
|
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
|
COMMENT "Stripping ${_TARGET}...")
|
|
endif()
|
|
endif()
|
|
endfunction()
|
|
|
|
# ------------------------------------------------------------------------------#
|
|
# function add_omnitrace_test_target()
|
|
#
|
|
# Creates a target which runs ctest but depends on all the tests being built.
|
|
#
|
|
function(ADD_OMNITRACE_TEST_TARGET)
|
|
if(NOT TARGET omnitrace-test)
|
|
add_custom_target(
|
|
omnitrace-test
|
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR} --target test
|
|
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
|
COMMENT "Running tests...")
|
|
endif()
|
|
endfunction()
|
|
|
|
# ----------------------------------------------------------------------------------------#
|
|
# macro omnitrace_checkout_git_submodule()
|
|
#
|
|
# Run "git submodule update" if a file in a submodule does not exist
|
|
#
|
|
# ARGS: RECURSIVE (option) -- add "--recursive" flag RELATIVE_PATH (one value) --
|
|
# typically the relative path to submodule from PROJECT_SOURCE_DIR WORKING_DIRECTORY (one
|
|
# value) -- (default: PROJECT_SOURCE_DIR) TEST_FILE (one value) -- file to check for
|
|
# (default: CMakeLists.txt) ADDITIONAL_CMDS (many value) -- any addition commands to pass
|
|
#
|
|
function(OMNITRACE_CHECKOUT_GIT_SUBMODULE)
|
|
# parse args
|
|
cmake_parse_arguments(
|
|
CHECKOUT "RECURSIVE"
|
|
"RELATIVE_PATH;WORKING_DIRECTORY;TEST_FILE;REPO_URL;REPO_BRANCH"
|
|
"ADDITIONAL_CMDS" ${ARGN})
|
|
|
|
if(NOT CHECKOUT_WORKING_DIRECTORY)
|
|
set(CHECKOUT_WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
|
|
endif()
|
|
|
|
if(NOT CHECKOUT_TEST_FILE)
|
|
set(CHECKOUT_TEST_FILE "CMakeLists.txt")
|
|
endif()
|
|
|
|
# default assumption
|
|
if(NOT CHECKOUT_REPO_BRANCH)
|
|
set(CHECKOUT_REPO_BRANCH "master")
|
|
endif()
|
|
|
|
find_package(Git)
|
|
set(_DIR "${CHECKOUT_WORKING_DIRECTORY}/${CHECKOUT_RELATIVE_PATH}")
|
|
# ensure the (possibly empty) directory exists
|
|
if(NOT EXISTS "${_DIR}")
|
|
if(NOT CHECKOUT_REPO_URL)
|
|
message(FATAL_ERROR "submodule directory does not exist")
|
|
endif()
|
|
endif()
|
|
|
|
# if this file exists --> project has been checked out if not exists --> not been
|
|
# checked out
|
|
set(_TEST_FILE "${_DIR}/${CHECKOUT_TEST_FILE}")
|
|
# assuming a .gitmodules file exists
|
|
set(_SUBMODULE "${PROJECT_SOURCE_DIR}/.gitmodules")
|
|
|
|
set(_TEST_FILE_EXISTS OFF)
|
|
if(EXISTS "${_TEST_FILE}" AND NOT IS_DIRECTORY "${_TEST_FILE}")
|
|
set(_TEST_FILE_EXISTS ON)
|
|
endif()
|
|
|
|
if(_TEST_FILE_EXISTS)
|
|
return()
|
|
endif()
|
|
|
|
find_package(Git REQUIRED)
|
|
|
|
set(_SUBMODULE_EXISTS OFF)
|
|
if(EXISTS "${_SUBMODULE}" AND NOT IS_DIRECTORY "${_SUBMODULE}")
|
|
set(_SUBMODULE_EXISTS ON)
|
|
endif()
|
|
|
|
set(_HAS_REPO_URL OFF)
|
|
if(NOT "${CHECKOUT_REPO_URL}" STREQUAL "")
|
|
set(_HAS_REPO_URL ON)
|
|
endif()
|
|
|
|
# if the module has not been checked out
|
|
if(NOT _TEST_FILE_EXISTS AND _SUBMODULE_EXISTS)
|
|
# perform the checkout
|
|
execute_process(
|
|
COMMAND ${GIT_EXECUTABLE} submodule update --init ${_RECURSE}
|
|
${CHECKOUT_ADDITIONAL_CMDS} ${CHECKOUT_RELATIVE_PATH}
|
|
WORKING_DIRECTORY ${CHECKOUT_WORKING_DIRECTORY}
|
|
RESULT_VARIABLE RET)
|
|
|
|
# check the return code
|
|
if(RET GREATER 0)
|
|
set(_CMD "${GIT_EXECUTABLE} submodule update --init ${_RECURSE}
|
|
${CHECKOUT_ADDITIONAL_CMDS} ${CHECKOUT_RELATIVE_PATH}")
|
|
message(STATUS "function(omnitrace_checkout_git_submodule) failed.")
|
|
message(FATAL_ERROR "Command: \"${_CMD}\"")
|
|
else()
|
|
set(_TEST_FILE_EXISTS ON)
|
|
endif()
|
|
endif()
|
|
|
|
if(NOT _TEST_FILE_EXISTS AND _HAS_REPO_URL)
|
|
message(
|
|
STATUS "Checking out '${CHECKOUT_REPO_URL}' @ '${CHECKOUT_REPO_BRANCH}'...")
|
|
|
|
# remove the existing directory
|
|
if(EXISTS "${_DIR}")
|
|
execute_process(COMMAND ${CMAKE_COMMAND} -E remove_directory ${_DIR})
|
|
endif()
|
|
|
|
# perform the checkout
|
|
execute_process(
|
|
COMMAND
|
|
${GIT_EXECUTABLE} clone -b ${CHECKOUT_REPO_BRANCH}
|
|
${CHECKOUT_ADDITIONAL_CMDS} ${CHECKOUT_REPO_URL} ${CHECKOUT_RELATIVE_PATH}
|
|
WORKING_DIRECTORY ${CHECKOUT_WORKING_DIRECTORY}
|
|
RESULT_VARIABLE RET)
|
|
|
|
# perform the submodule update
|
|
if(CHECKOUT_RECURSIVE
|
|
AND EXISTS "${_DIR}"
|
|
AND IS_DIRECTORY "${_DIR}")
|
|
execute_process(
|
|
COMMAND ${GIT_EXECUTABLE} submodule update --init ${_RECURSE}
|
|
WORKING_DIRECTORY ${_DIR}
|
|
RESULT_VARIABLE RET)
|
|
endif()
|
|
|
|
# check the return code
|
|
if(RET GREATER 0)
|
|
set(_CMD
|
|
"${GIT_EXECUTABLE} clone -b ${CHECKOUT_REPO_BRANCH}
|
|
${CHECKOUT_ADDITIONAL_CMDS} ${CHECKOUT_REPO_URL} ${CHECKOUT_RELATIVE_PATH}"
|
|
)
|
|
message(STATUS "function(omnitrace_checkout_git_submodule) failed.")
|
|
message(FATAL_ERROR "Command: \"${_CMD}\"")
|
|
else()
|
|
set(_TEST_FILE_EXISTS ON)
|
|
endif()
|
|
endif()
|
|
|
|
if(NOT EXISTS "${_TEST_FILE}" OR NOT _TEST_FILE_EXISTS)
|
|
message(
|
|
FATAL_ERROR
|
|
"Error checking out submodule: '${CHECKOUT_RELATIVE_PATH}' to '${_DIR}'")
|
|
endif()
|
|
|
|
endfunction()
|
|
|
|
# ----------------------------------------------------------------------------------------#
|
|
# try to find a package quietly
|
|
#
|
|
function(OMNITRACE_TEST_FIND_PACKAGE PACKAGE_NAME OUTPUT_VAR)
|
|
cmake_parse_arguments(PACKAGE "" "" "UNSET" ${ARGN})
|
|
find_package(${PACKAGE_NAME} QUIET ${PACKAGE_UNPARSED_ARGUMENTS})
|
|
if(NOT ${PACKAGE_NAME}_FOUND)
|
|
set(${OUTPUT_VAR}
|
|
OFF
|
|
PARENT_SCOPE)
|
|
else()
|
|
set(${OUTPUT_VAR}
|
|
ON
|
|
PARENT_SCOPE)
|
|
endif()
|
|
foreach(_ARG ${PACKAGE_UNSET} FIND_PACKAGE_MESSAGE_DETAILS_${PACKAGE_NAME})
|
|
unset(${_ARG} CACHE)
|
|
endforeach()
|
|
endfunction()
|
|
|
|
# ----------------------------------------------------------------------------------------#
|
|
# macro to add an interface lib
|
|
#
|
|
macro(OMNITRACE_ADD_INTERFACE_LIBRARY _TARGET)
|
|
add_library(${_TARGET} INTERFACE)
|
|
add_library(${PROJECT_NAME}::${_TARGET} ALIAS ${_TARGET})
|
|
install(
|
|
TARGETS ${_TARGET}
|
|
DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
COMPONENT core
|
|
EXPORT ${PROJECT_NAME}-library-depends
|
|
OPTIONAL)
|
|
if(NOT "${ARGN}" STREQUAL "")
|
|
set_property(GLOBAL APPEND PROPERTY ${PROJECT_NAME}_CMAKE_INTERFACE_DOC
|
|
"${PROJECT_NAME}::${_TARGET}` | ${ARGN} |")
|
|
endif()
|
|
endmacro()
|
|
|
|
# -----------------------------------------------------------------------
|
|
# function add_feature(<NAME> <DOCSTRING>) Add a project feature, whose activation is
|
|
# specified by the existence of the variable <NAME>, to the list of enabled/disabled
|
|
# features, plus a docstring describing the feature
|
|
#
|
|
function(OMNITRACE_ADD_FEATURE _var _description)
|
|
set(EXTRA_DESC "")
|
|
foreach(currentArg ${ARGN})
|
|
if(NOT "${currentArg}" STREQUAL "${_var}"
|
|
AND NOT "${currentArg}" STREQUAL "${_description}"
|
|
AND NOT "${currentArg}" STREQUAL "CMAKE_DEFINE"
|
|
AND NOT "${currentArg}" STREQUAL "DOC")
|
|
set(EXTRA_DESC "${EXTA_DESC}${currentArg}")
|
|
endif()
|
|
endforeach()
|
|
|
|
set_property(GLOBAL APPEND PROPERTY ${PROJECT_NAME}_FEATURES ${_var})
|
|
set_property(GLOBAL PROPERTY ${_var}_DESCRIPTION "${_description}${EXTRA_DESC}")
|
|
|
|
if("CMAKE_DEFINE" IN_LIST ARGN)
|
|
set_property(GLOBAL APPEND PROPERTY ${PROJECT_NAME}_CMAKE_DEFINES
|
|
"${_var} @${_var}@")
|
|
if(OMNITRACE_BUILD_DOCS)
|
|
set_property(
|
|
GLOBAL APPEND PROPERTY ${PROJECT_NAME}_CMAKE_OPTIONS_DOC
|
|
"${_var}` | ${_description}${EXTRA_DESC} |")
|
|
endif()
|
|
elseif("DOC" IN_LIST ARGN AND OMNITRACE_BUILD_DOCS)
|
|
set_property(GLOBAL APPEND PROPERTY ${PROJECT_NAME}_CMAKE_OPTIONS_DOC
|
|
"${_var}` | ${_description}${EXTRA_DESC} |")
|
|
endif()
|
|
endfunction()
|
|
|
|
# ----------------------------------------------------------------------------------------#
|
|
# function add_option(<OPTION_NAME> <DOCSRING> <DEFAULT_SETTING> [NO_FEATURE]) Add an
|
|
# option and add as a feature if NO_FEATURE is not provided
|
|
#
|
|
function(OMNITRACE_ADD_OPTION _NAME _MESSAGE _DEFAULT)
|
|
option(${_NAME} "${_MESSAGE}" ${_DEFAULT})
|
|
if("NO_FEATURE" IN_LIST ARGN)
|
|
mark_as_advanced(${_NAME})
|
|
else()
|
|
omnitrace_add_feature(${_NAME} "${_MESSAGE}")
|
|
if(OMNITRACE_BUILD_DOCS)
|
|
set_property(GLOBAL APPEND PROPERTY ${PROJECT_NAME}_CMAKE_OPTIONS_DOC
|
|
"${_NAME}` | ${_MESSAGE} |")
|
|
endif()
|
|
endif()
|
|
if("ADVANCED" IN_LIST ARGN)
|
|
mark_as_advanced(${_NAME})
|
|
endif()
|
|
if("CMAKE_DEFINE" IN_LIST ARGN)
|
|
set_property(GLOBAL APPEND PROPERTY ${PROJECT_NAME}_CMAKE_DEFINES ${_NAME})
|
|
endif()
|
|
endfunction()
|
|
|
|
# ----------------------------------------------------------------------------------------#
|
|
# function omnitrace_add_cache_option(<OPTION_NAME> <DOCSRING> <TYPE> <DEFAULT_VALUE>
|
|
# [NO_FEATURE] [ADVANCED] [CMAKE_DEFINE])
|
|
#
|
|
function(OMNITRACE_ADD_CACHE_OPTION _NAME _MESSAGE _TYPE _DEFAULT)
|
|
set(_FORCE)
|
|
if("FORCE" IN_LIST ARGN)
|
|
set(_FORCE FORCE)
|
|
endif()
|
|
|
|
set(${_NAME}
|
|
"${_DEFAULT}"
|
|
CACHE ${_TYPE} "${_MESSAGE}" ${_FORCE})
|
|
|
|
if("NO_FEATURE" IN_LIST ARGN)
|
|
mark_as_advanced(${_NAME})
|
|
else()
|
|
omnitrace_add_feature(${_NAME} "${_MESSAGE}")
|
|
|
|
if(OMNITRACE_BUILD_DOCS)
|
|
set_property(GLOBAL APPEND PROPERTY ${PROJECT_NAME}_CMAKE_OPTIONS_DOC
|
|
"${_NAME}` | ${_MESSAGE} |")
|
|
endif()
|
|
endif()
|
|
|
|
if("ADVANCED" IN_LIST ARGN)
|
|
mark_as_advanced(${_NAME})
|
|
endif()
|
|
|
|
if("CMAKE_DEFINE" IN_LIST ARGN)
|
|
set_property(GLOBAL APPEND PROPERTY ${PROJECT_NAME}_CMAKE_DEFINES ${_NAME})
|
|
endif()
|
|
endfunction()
|
|
|
|
# ----------------------------------------------------------------------------------------#
|
|
# function omnitrace_report_feature_changes() :: print changes in features
|
|
#
|
|
function(OMNITRACE_REPORT_FEATURE_CHANGES)
|
|
get_property(_features GLOBAL PROPERTY ${PROJECT_NAME}_FEATURES)
|
|
if(NOT "${_features}" STREQUAL "")
|
|
list(REMOVE_DUPLICATES _features)
|
|
list(SORT _features)
|
|
endif()
|
|
foreach(_feature ${_features})
|
|
if("${ARGN}" STREQUAL "")
|
|
omnitrace_watch_for_change(${_feature})
|
|
elseif("${_feature}" IN_LIST ARGN)
|
|
omnitrace_watch_for_change(${_feature})
|
|
endif()
|
|
endforeach()
|
|
endfunction()
|
|
|
|
# ----------------------------------------------------------------------------------------#
|
|
# function print_enabled_features() Print enabled features plus their docstrings.
|
|
#
|
|
function(OMNITRACE_PRINT_ENABLED_FEATURES)
|
|
set(_basemsg "The following features are defined/enabled (+):")
|
|
set(_currentFeatureText "${_basemsg}")
|
|
get_property(_features GLOBAL PROPERTY ${PROJECT_NAME}_FEATURES)
|
|
if(NOT "${_features}" STREQUAL "")
|
|
list(REMOVE_DUPLICATES _features)
|
|
list(SORT _features)
|
|
endif()
|
|
foreach(_feature ${_features})
|
|
if(${_feature})
|
|
# add feature to text
|
|
set(_currentFeatureText "${_currentFeatureText}\n ${_feature}")
|
|
# get description
|
|
get_property(_desc GLOBAL PROPERTY ${_feature}_DESCRIPTION)
|
|
# print description, if not standard ON/OFF, print what is set to
|
|
if(_desc)
|
|
if(NOT "${${_feature}}" STREQUAL "ON" AND NOT "${${_feature}}" STREQUAL
|
|
"TRUE")
|
|
set(_currentFeatureText
|
|
"${_currentFeatureText}: ${_desc} -- [\"${${_feature}}\"]")
|
|
else()
|
|
string(REGEX REPLACE "^${PROJECT_NAME}_USE_" "" _feature_tmp
|
|
"${_feature}")
|
|
string(TOLOWER "${_feature_tmp}" _feature_tmp_l)
|
|
omnitrace_capitalize("${_feature_tmp}" _feature_tmp_c)
|
|
foreach(_var _feature _feature_tmp _feature_tmp_l _feature_tmp_c)
|
|
set(_ver "${${${_var}}_VERSION}")
|
|
if(NOT "${_ver}" STREQUAL "")
|
|
set(_desc "${_desc} -- [found version ${_ver}]")
|
|
break()
|
|
endif()
|
|
unset(_ver)
|
|
endforeach()
|
|
set(_currentFeatureText "${_currentFeatureText}: ${_desc}")
|
|
endif()
|
|
set(_desc NOTFOUND)
|
|
endif()
|
|
endif()
|
|
endforeach()
|
|
|
|
if(NOT "${_currentFeatureText}" STREQUAL "${_basemsg}")
|
|
message(STATUS "${_currentFeatureText}\n")
|
|
endif()
|
|
endfunction()
|
|
|
|
# ----------------------------------------------------------------------------------------#
|
|
# function print_disabled_features() Print disabled features plus their docstrings.
|
|
#
|
|
function(OMNITRACE_PRINT_DISABLED_FEATURES)
|
|
set(_basemsg "The following features are NOT defined/enabled (-):")
|
|
set(_currentFeatureText "${_basemsg}")
|
|
get_property(_features GLOBAL PROPERTY ${PROJECT_NAME}_FEATURES)
|
|
if(NOT "${_features}" STREQUAL "")
|
|
list(REMOVE_DUPLICATES _features)
|
|
list(SORT _features)
|
|
endif()
|
|
foreach(_feature ${_features})
|
|
if(NOT ${_feature})
|
|
set(_currentFeatureText "${_currentFeatureText}\n ${_feature}")
|
|
|
|
get_property(_desc GLOBAL PROPERTY ${_feature}_DESCRIPTION)
|
|
|
|
if(_desc)
|
|
set(_currentFeatureText "${_currentFeatureText}: ${_desc}")
|
|
set(_desc NOTFOUND)
|
|
endif(_desc)
|
|
endif()
|
|
endforeach(_feature)
|
|
|
|
if(NOT "${_currentFeatureText}" STREQUAL "${_basemsg}")
|
|
message(STATUS "${_currentFeatureText}\n")
|
|
endif()
|
|
endfunction()
|
|
|
|
# ----------------------------------------------------------------------------------------#
|
|
# function print_features() Print all features plus their docstrings.
|
|
#
|
|
function(OMNITRACE_PRINT_FEATURES)
|
|
omnitrace_report_feature_changes()
|
|
omnitrace_print_enabled_features()
|
|
omnitrace_print_disabled_features()
|
|
endfunction()
|
|
|
|
# ----------------------------------------------------------------------------------------#
|
|
# this function is provided to easily select which files use alternative compiler:
|
|
#
|
|
# GLOBAL --> all files TARGET --> all files in a target SOURCE --> specific
|
|
# source files DIRECTORY --> all files in directory PROJECT --> all files/targets in
|
|
# a project/subproject
|
|
#
|
|
function(omnitrace_custom_compilation)
|
|
cmake_parse_arguments(COMP "GLOBAL;PROJECT" "COMPILER" "DIRECTORY;TARGET;SOURCE"
|
|
${ARGN})
|
|
|
|
# find omnitrace-launch-compiler
|
|
find_program(
|
|
OMNITRACE_COMPILE_LAUNCHER
|
|
NAMES omnitrace-launch-compiler
|
|
HINTS ${PROJECT_SOURCE_DIR} ${CMAKE_SOURCE_DIR}
|
|
PATHS ${PROJECT_SOURCE_DIR} ${CMAKE_SOURCE_DIR}
|
|
PATH_SUFFIXES scripts bin)
|
|
|
|
if(NOT COMP_COMPILER)
|
|
message(FATAL_ERROR "omnitrace_custom_compilation not provided COMPILER argument")
|
|
endif()
|
|
|
|
if(NOT OMNITRACE_COMPILE_LAUNCHER)
|
|
message(
|
|
FATAL_ERROR
|
|
"omnitrace could not find 'omnitrace-launch-compiler'. Please set '-DOMNITRACE_COMPILE_LAUNCHER=/path/to/launcher'"
|
|
)
|
|
endif()
|
|
|
|
if(COMP_GLOBAL)
|
|
# if global, don't bother setting others
|
|
set_property(
|
|
GLOBAL
|
|
PROPERTY
|
|
RULE_LAUNCH_COMPILE
|
|
"${OMNITRACE_COMPILE_LAUNCHER} ${COMP_COMPILER} ${CMAKE_CXX_COMPILER}")
|
|
set_property(
|
|
GLOBAL
|
|
PROPERTY
|
|
RULE_LAUNCH_LINK
|
|
"${OMNITRACE_COMPILE_LAUNCHER} ${COMP_COMPILER} ${CMAKE_CXX_COMPILER}")
|
|
else()
|
|
foreach(_TYPE PROJECT DIRECTORY TARGET SOURCE)
|
|
# make project/subproject scoping easy, e.g.
|
|
# omnitrace_custom_compilation(PROJECT) after project(...)
|
|
if("${_TYPE}" STREQUAL "PROJECT" AND COMP_${_TYPE})
|
|
list(APPEND COMP_DIRECTORY ${PROJECT_SOURCE_DIR})
|
|
unset(COMP_${_TYPE})
|
|
endif()
|
|
# set the properties if defined
|
|
if(COMP_${_TYPE})
|
|
foreach(_VAL ${COMP_${_TYPE}})
|
|
set_property(
|
|
${_TYPE} ${_VAL}
|
|
PROPERTY
|
|
RULE_LAUNCH_COMPILE
|
|
"${OMNITRACE_COMPILE_LAUNCHER} ${COMP_COMPILER} ${CMAKE_CXX_COMPILER}"
|
|
)
|
|
set_property(
|
|
${_TYPE} ${_VAL}
|
|
PROPERTY
|
|
RULE_LAUNCH_LINK
|
|
"${OMNITRACE_COMPILE_LAUNCHER} ${COMP_COMPILER} ${CMAKE_CXX_COMPILER}"
|
|
)
|
|
endforeach()
|
|
endif()
|
|
endforeach()
|
|
endif()
|
|
endfunction()
|
|
|
|
function(OMNITRACE_WATCH_FOR_CHANGE _var)
|
|
list(LENGTH ARGN _NUM_EXTRA_ARGS)
|
|
if(_NUM_EXTRA_ARGS EQUAL 1)
|
|
set(_VAR ${ARGN})
|
|
else()
|
|
set(_VAR)
|
|
endif()
|
|
|
|
macro(update_var _VAL)
|
|
if(_VAR)
|
|
set(${_VAR}
|
|
${_VAL}
|
|
PARENT_SCOPE)
|
|
endif()
|
|
endmacro()
|
|
|
|
update_var(OFF)
|
|
|
|
set(_omnitrace_watch_var_name OMNITRACE_WATCH_VALUE_${_var})
|
|
if(DEFINED ${_omnitrace_watch_var_name})
|
|
if("${${_var}}" STREQUAL "${${_omnitrace_watch_var_name}}")
|
|
return()
|
|
else()
|
|
omnitrace_message(
|
|
STATUS
|
|
"${_var} changed :: ${${_omnitrace_watch_var_name}} --> ${${_var}}")
|
|
update_var(ON)
|
|
endif()
|
|
else()
|
|
if(NOT "${${_var}}" STREQUAL "")
|
|
omnitrace_message(STATUS "${_var} :: ${${_var}}")
|
|
update_var(ON)
|
|
endif()
|
|
endif()
|
|
|
|
# store the value for the next run
|
|
set(${_omnitrace_watch_var_name}
|
|
"${${_var}}"
|
|
CACHE INTERNAL "Last value of ${_var}" FORCE)
|
|
endfunction()
|
|
|
|
function(OMNITRACE_DIRECTORY)
|
|
cmake_parse_arguments(F "MKDIR;FAIL;FORCE" "PREFIX;OUTPUT_VARIABLE;WORKING_DIRECTORY"
|
|
"PATHS" ${ARGN})
|
|
|
|
if(F_PREFIX AND NOT IS_ABSOLUTE "${F_PREFIX}")
|
|
if(F_WORKING_DIRECTORY)
|
|
omnitrace_message(
|
|
STATUS
|
|
"PREFIX was specified as a relative path, using working directory + prefix :: '${F_WORKING_DIRECTORY}/${F_PREFIX}'..."
|
|
)
|
|
set(F_PREFIX ${F_WORKING_DIRECTORY}/${F_PREFIX})
|
|
else()
|
|
omnitrace_message(
|
|
FATAL_ERROR
|
|
"PREFIX was specified but it is not an absolute path: ${F_PREFIX}")
|
|
endif()
|
|
endif()
|
|
|
|
if(NOT F_WORKING_DIRECTORY)
|
|
set(F_WORKING_DIRECTORY ${PROJECT_BINARY_DIR})
|
|
endif()
|
|
|
|
foreach(_PATH ${F_PREFIX} ${F_PATHS})
|
|
if(F_PREFIX AND NOT "${_PATH}" STREQUAL "${F_PREFIX}")
|
|
# if path is relative, set to prefix + path
|
|
if(NOT IS_ABSOLUTE "${_PATH}")
|
|
set(_PATH ${F_PREFIX}/${_PATH})
|
|
endif()
|
|
list(APPEND _OUTPUT_VAR ${_PATH})
|
|
elseif(NOT F_PREFIX)
|
|
list(APPEND _OUTPUT_VAR ${_PATH})
|
|
endif()
|
|
|
|
if(NOT EXISTS "${_PATH}" AND F_FAIL)
|
|
omnitrace_message(FATAL_ERROR "Directory '${_PATH}' does not exist")
|
|
elseif(NOT IS_DIRECTORY "${_PATH}" AND F_FAIL)
|
|
omnitrace_message(FATAL_ERROR "'${_PATH}' exists but is not a directory")
|
|
elseif(NOT EXISTS "${_PATH}" AND F_MKDIR)
|
|
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${_PATH}
|
|
WORKING_DIRECTORY ${F_WORKING_DIRECTORY})
|
|
elseif(
|
|
EXISTS "${_PATH}"
|
|
AND NOT IS_DIRECTORY "${_PATH}"
|
|
AND F_MKDIR)
|
|
if(F_FORCE)
|
|
execute_process(COMMAND ${CMAKE_COMMAND} -E rm ${_PATH}
|
|
WORKING_DIRECTORY ${F_WORKING_DIRECTORY})
|
|
endif()
|
|
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${_PATH}
|
|
WORKING_DIRECTORY ${F_WORKING_DIRECTORY})
|
|
endif()
|
|
endforeach()
|
|
|
|
if(F_OUTPUT_VARIABLE)
|
|
set(${F_OUTPUT_VARIABLE}
|
|
"${_OUTPUT_VAR}"
|
|
PARENT_SCOPE)
|
|
endif()
|
|
endfunction()
|
|
|
|
function(OMNITRACE_CHECK_PYTHON_DIRS_AND_VERSIONS)
|
|
cmake_parse_arguments(F "FAIL;UNSET" "RESULT_VARIABLE;OUTPUT_VARIABLE" "" ${ARGN})
|
|
|
|
list(LENGTH OMNITRACE_PYTHON_VERSIONS _NUM_PYTHON_VERSIONS)
|
|
list(LENGTH OMNITRACE_PYTHON_ROOT_DIRS _NUM_PYTHON_ROOT_DIRS)
|
|
|
|
if(NOT _NUM_PYTHON_VERSIONS EQUAL _NUM_PYTHON_ROOT_DIRS)
|
|
set(_RET 1)
|
|
else()
|
|
set(_RET 0)
|
|
if(F_OUTPUT_VARIABLE)
|
|
set(${F_OUTPUT_VARIABLE}
|
|
${_NUM_PYTHON_VERSIONS}
|
|
PARENT_SCOPE)
|
|
endif()
|
|
endif()
|
|
|
|
if(F_RESULT_VARIABLE)
|
|
set(${F_RESULT_VARIABLE}
|
|
${_RET}
|
|
PARENT_SCOPE)
|
|
endif()
|
|
|
|
if(NOT ${_RET} EQUAL 0)
|
|
if(F_FAIL)
|
|
omnitrace_message(
|
|
WARNING
|
|
"Error! Number of python versions : ${_NUM_PYTHON_VERSIONS}. VERSIONS :: ${OMNITRACE_PYTHON_VERSIONS}"
|
|
)
|
|
omnitrace_message(
|
|
WARNING
|
|
"Error! Number of python root directories : ${_NUM_PYTHON_ROOT_DIRS}. ROOT DIRS :: ${OMNITRACE_PYTHON_ROOT_DIRS}"
|
|
)
|
|
omnitrace_message(
|
|
FATAL_ERROR
|
|
"Error! Number of python versions != number of python root directories")
|
|
elseif(F_UNSET)
|
|
unset(OMNITRACE_PYTHON_VERSIONS CACHE)
|
|
unset(OMNITRACE_PYTHON_ROOT_DIRS CACHE)
|
|
if(F_OUTPUT_VARIABLE)
|
|
set(${F_OUTPUT_VARIABLE} 0)
|
|
endif()
|
|
endif()
|
|
endif()
|
|
endfunction()
|
|
|
|
# ----------------------------------------------------------------------------
|
|
# Console scripts
|
|
#
|
|
function(OMNITRACE_PYTHON_CONSOLE_SCRIPT SCRIPT_NAME SCRIPT_SUBMODULE)
|
|
set(options)
|
|
set(args VERSION ROOT_DIR)
|
|
set(kwargs)
|
|
cmake_parse_arguments(ARG "${options}" "${args}" "${kwargs}" ${ARGN})
|
|
|
|
if(ARG_VERSION AND ARG_ROOT_DIR)
|
|
set(Python3_ROOT_DIR "${ARG_ROOT_DIR}")
|
|
find_package(Python3 ${ARG_VERSION} EXACT QUIET MODULE COMPONENTS Interpreter)
|
|
set(PYTHON_EXECUTABLE "${Python3_EXECUTABLE}")
|
|
configure_file(${PROJECT_SOURCE_DIR}/cmake/Templates/console-script.in
|
|
${PROJECT_BINARY_DIR}/bin/${SCRIPT_NAME}-${ARG_VERSION} @ONLY)
|
|
|
|
if(CMAKE_INSTALL_PYTHONDIR)
|
|
install(
|
|
PROGRAMS ${PROJECT_BINARY_DIR}/bin/${SCRIPT_NAME}-${ARG_VERSION}
|
|
DESTINATION ${CMAKE_INSTALL_BINDIR}
|
|
COMPONENT python
|
|
OPTIONAL)
|
|
endif()
|
|
|
|
if(OMNITRACE_BUILD_TESTING OR OMNITRACE_BUILD_PYTHON)
|
|
add_test(
|
|
NAME ${SCRIPT_NAME}-console-script-test-${ARG_VERSION}
|
|
COMMAND ${PROJECT_BINARY_DIR}/bin/${SCRIPT_NAME}-${ARG_VERSION} --help
|
|
WORKING_DIRECTORY ${PROJECT_BINARY_DIR})
|
|
set_tests_properties(
|
|
${SCRIPT_NAME}-console-script-test-${ARG_VERSION}
|
|
PROPERTIES LABELS "python;python-${ARG_VERSION};console-script")
|
|
add_test(
|
|
NAME ${SCRIPT_NAME}-generic-console-script-test-${ARG_VERSION}
|
|
COMMAND ${PROJECT_BINARY_DIR}/bin/${SCRIPT_NAME} --help
|
|
WORKING_DIRECTORY ${PROJECT_BINARY_DIR})
|
|
set_tests_properties(
|
|
${SCRIPT_NAME}-generic-console-script-test-${ARG_VERSION}
|
|
PROPERTIES ENVIRONMENT "PYTHON_EXECUTABLE=${PYTHON_EXECUTABLE}" LABELS
|
|
"python;python-${ARG_VERSION};console-script")
|
|
endif()
|
|
else()
|
|
set(PYTHON_EXECUTABLE "python3")
|
|
|
|
configure_file(${PROJECT_SOURCE_DIR}/cmake/Templates/console-script.in
|
|
${PROJECT_BINARY_DIR}/bin/${SCRIPT_NAME} @ONLY)
|
|
|
|
if(CMAKE_INSTALL_PYTHONDIR)
|
|
install(
|
|
PROGRAMS ${PROJECT_BINARY_DIR}/bin/${SCRIPT_NAME}
|
|
DESTINATION ${CMAKE_INSTALL_BINDIR}
|
|
COMPONENT python
|
|
OPTIONAL)
|
|
endif()
|
|
endif()
|
|
endfunction()
|
|
|
|
function(OMNITRACE_FIND_STATIC_LIBRARY)
|
|
set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX})
|
|
find_library(${ARGN})
|
|
endfunction()
|
|
|
|
function(OMNITRACE_FIND_SHARED_LIBRARY)
|
|
set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_SHARED_LIBRARY_SUFFIX})
|
|
find_library(${ARGN})
|
|
endfunction()
|
|
|
|
function(OMNITRACE_BUILDTREE_TPL _TPL_TARGET _NEW_NAME _BUILD_TREE_DIR)
|
|
get_target_property(_TPL_VERSION ${_TPL_TARGET} VERSION)
|
|
get_target_property(_TPL_SOVERSION ${_TPL_TARGET} SOVERSION)
|
|
get_target_property(_TPL_NAME ${_TPL_TARGET} OUTPUT_NAME)
|
|
set(_TPL_PREFIX ${CMAKE_SHARED_LIBRARY_PREFIX})
|
|
set(_TPL_SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX})
|
|
|
|
foreach(_TAIL ${_TPL_SUFFIX} ${_TPL_SUFFIX}.${_TPL_SOVERSION}
|
|
${_TPL_SUFFIX}.${_TPL_VERSION})
|
|
set(_INP ${_TPL_PREFIX}${_TPL_NAME}${_TAIL})
|
|
set(_OUT ${_TPL_PREFIX}${_NEW_NAME}${_TAIL})
|
|
endforeach()
|
|
|
|
string(REPLACE " " "-" _TAIL "${ARGN}")
|
|
|
|
# build tree symbolic links
|
|
add_custom_target(
|
|
${_NEW_NAME}-build-tree-library${_TAIL} ALL
|
|
${CMAKE_COMMAND} -E create_symlink $<TARGET_FILE:${_TPL_TARGET}>
|
|
${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_VERSION}
|
|
COMMAND
|
|
${CMAKE_COMMAND} -E create_symlink
|
|
${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_VERSION}
|
|
${_BUILD_TREE_DIR}/${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_SOVERSION}
|
|
COMMAND
|
|
${CMAKE_COMMAND} -E create_symlink
|
|
${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_SOVERSION}
|
|
${_BUILD_TREE_DIR}/${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}
|
|
WORKING_DIRECTORY ${_BUILD_TREE_DIR}
|
|
DEPENDS ${_TPL_TARGET}
|
|
COMMENT "Creating ${_NEW_NAME} from ${_TPL_TARGET}...")
|
|
endfunction()
|
|
|
|
function(OMNITRACE_INSTALL_TPL _TPL_TARGET _NEW_NAME _BUILD_TREE_DIR _COMPONENT)
|
|
get_target_property(_TPL_VERSION ${_TPL_TARGET} VERSION)
|
|
get_target_property(_TPL_SOVERSION ${_TPL_TARGET} SOVERSION)
|
|
get_target_property(_TPL_NAME ${_TPL_TARGET} OUTPUT_NAME)
|
|
set(_TPL_PREFIX ${CMAKE_SHARED_LIBRARY_PREFIX})
|
|
set(_TPL_SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX})
|
|
|
|
foreach(_TAIL ${_TPL_SUFFIX} ${_TPL_SUFFIX}.${_TPL_SOVERSION}
|
|
${_TPL_SUFFIX}.${_TPL_VERSION})
|
|
set(_INP ${_TPL_PREFIX}${_TPL_NAME}${_TAIL})
|
|
set(_OUT ${_TPL_PREFIX}${_NEW_NAME}${_TAIL})
|
|
endforeach()
|
|
|
|
# build tree symbolic links
|
|
omnitrace_buildtree_tpl("${_TPL_TARGET}" "${_NEW_NAME}" "${_BUILD_TREE_DIR}" ${ARGN})
|
|
|
|
install(
|
|
FILES $<TARGET_FILE:${_TPL_TARGET}>
|
|
DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
COMPONENT ${_COMPONENT}
|
|
RENAME ${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_VERSION})
|
|
|
|
install(
|
|
FILES
|
|
${_BUILD_TREE_DIR}/${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_SOVERSION}
|
|
${_BUILD_TREE_DIR}/${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}
|
|
DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
COMPONENT ${_COMPONENT})
|
|
|
|
endfunction()
|
|
|
|
cmake_policy(POP)
|