diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..f3d9872 --- /dev/null +++ b/.clang-format @@ -0,0 +1,4 @@ +--- +BasedOnStyle: LLVM +--- +Language: Cpp diff --git a/.gitignore b/.gitignore index b25c15b..bdc5af0 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ *~ +build diff --git a/CMakeLists.txt b/CMakeLists.txt index 3981010..b5705c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,62 +1,62 @@ -# ====================================================================== -# larsoft main build file -# -# cd .../path/to/build/directory -# source .../path/to/larsoft/ups/setup_for_development <-d|-p> -# cmake [-DCMAKE_INSTALL_PREFIX=/install/path] -# -DCMAKE_BUILD_TYPE=$CETPKG_TYPE -# $CETPKG_SOURCE -# make -# make test -# make install -# make package (builds distribution tarfile) -# ====================================================================== - - cmake_minimum_required (VERSION 3.20 FATAL_ERROR) -# cmake_policy(VERSION 3.18) - -find_package(cetmodules REQUIRED) -project(duneanaobj LANGUAGES CXX) -set(${PROJECT_NAME}_CMAKE_PROJECT_VERSION_STRING 03.11.00) - -message(STATUS "\n\n ========================== ${PROJECT_NAME} ==========================") - -if(DEFINED ENV{UPS_DIR}) - # cetbuildtools contains our cmake modules - - include(CetCMakeEnv) - cet_cmake_env() - set_install_root() +project(duneanaobj VERSION 4.0.0 LANGUAGES CXX) - # The specification of the C++ standard is required because CET macros - # set it to C++98 by default, and then override it depending on the - # compiler version, as determined by the compiler qualifier. - # Removing that qualifier, we need to supply that information manually, - # and maintain it too. - cet_set_compiler_flags(DIAGS CAUTIOUS - WERROR - NO_UNDEFINED - ALLOW_DEPRECATIONS - EXTRA_FLAGS -pedantic -Wno-unused-local-typedefs -Wno-undefined-var-template -I $ENV{CLANG_FQ_DIR}/include/c++/v1 - ) +string(REPLACE "." ";" VERSION_LIST ${PROJECT_VERSION}) +list(GET VERSION_LIST 0 duneanaobj_VERSION_MAJOR) +list(GET VERSION_LIST 1 duneanaobj_VERSION_MINOR) +list(GET VERSION_LIST 2 duneanaobj_VERSION_PATCH) - cet_report_compiler_flags() +LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake/Modules) - # these are minimum required versions, not the actual product versions - find_package(ROOT 6.00.00 REQUIRED) +option(duneanaobj_PYTHON_ENABLED "Whether to build python bindings to proxy classes." OFF) - include(BuildDictionary) +include(CPM) - # packaging utility +SET(SRProxy_MIN_VERSION 0.46.0) +CPMFindPackage( + NAME SRProxy + GIT_TAG feature/Clingification_rebase3 + GITHUB_REPOSITORY luketpickering/SRProxy + VERSION ${SRProxy_MIN_VERSION} +) -else() - find_package(ROOT) - include_directories(.) -endif() +find_package(ROOT 6.20 REQUIRED) add_subdirectory(duneanaobj) -cet_cmake_config() +add_library(duneanaobj_all INTERFACE) +set_target_properties(duneanaobj_all PROPERTIES EXPORT_NAME all) + +target_link_libraries(duneanaobj_all INTERFACE + duneanaobj::StandardRecordProxy + duneanaobj::StandardRecordFlat + duneanaobj::StandardRecord) + +install(TARGETS duneanaobj_all EXPORT duneanaobj_targets) + +add_library(duneanaobj::all ALIAS duneanaobj_all) + +add_subdirectory(app) + +include(CMakePackageConfigHelpers) +write_basic_package_version_file( + "${PROJECT_BINARY_DIR}/duneanaobjConfigVersion.cmake" + VERSION ${PROJECT_VERSION} + COMPATIBILITY AnyNewerVersion +) +configure_package_config_file( + "${CMAKE_CURRENT_LIST_DIR}/cmake/Templates/duneanaobjConfig.cmake.in" + "${PROJECT_BINARY_DIR}/duneanaobjConfig.cmake" + INSTALL_DESTINATION this/is/ignored + NO_SET_AND_CHECK_MACRO + NO_CHECK_REQUIRED_COMPONENTS_MACRO +) + +install(EXPORT duneanaobj_targets + NAMESPACE duneanaobj:: + DESTINATION lib/cmake/duneanaobj) +install(FILES "${PROJECT_BINARY_DIR}/duneanaobjConfigVersion.cmake" + "${PROJECT_BINARY_DIR}/duneanaobjConfig.cmake" + DESTINATION lib/cmake/duneanaobj) diff --git a/README.md b/README.md index 2fa78a9..f6cd2f6 100644 --- a/README.md +++ b/README.md @@ -192,3 +192,12 @@ CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +# Build outside of FNAL Stack like + +``` +mkdir build; cd build +cmake .. -DSTANDALONE_BUILD=ON -DCMAKE_INSTALL_PREFIX=/path/to/install/dir +make install +``` + +This will build and install the standard record dictionary and SRProxy class. Flat class on the way. diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt new file mode 100644 index 0000000..0bca718 --- /dev/null +++ b/app/CMakeLists.txt @@ -0,0 +1,5 @@ +add_executable(duneanaobj_dumpevent duneanaobj_dumpevent.cxx) +target_link_libraries(duneanaobj_dumpevent duneanaobj::all ROOT::Tree ROOT::RIO) + +install(TARGETS duneanaobj_dumpevent + DESTINATION bin) diff --git a/app/duneanaobj_dumpevent.cxx b/app/duneanaobj_dumpevent.cxx new file mode 100644 index 0000000..e5fa896 --- /dev/null +++ b/app/duneanaobj_dumpevent.cxx @@ -0,0 +1,38 @@ +#include "duneanaobj/StandardRecord/Proxy/SRProxy.h" + +#include "TFile.h" +#include "TTree.h" + +#include + +using namespace caf; + +int main(int argc, char const *argv[]) { + + TFile fin(argv[1], "READ"); + + TTree *tin = fin.Get("caf"); + + StandardRecordProxy srp(tin, "StandardRecord"); + + Long64_t ents = tin->GetEntries(); + std::cout << "Input tree has " << ents << " entries." << std::endl; + + for (Long64_t i = 0; i < ents; ++i) { + tin->GetEntry(i); + + std::cout << "Entry: " << i << std::endl; + + std::cout << "\tsrp.duneanaobj_gitshorthash: " + << srp.duneanaobj_gitshorthash.GetValue() << std::endl; + std::cout << "\tsrp.duneanaobj_version: " << srp.duneanaobj_version[0] + << ", " << srp.duneanaobj_version[1] << ", " + << srp.duneanaobj_version[2] << std::endl; + + std::cout << "\tsrp.nd.lar.ndlp: " << srp.nd.lar.ndlp.GetValue() << std::endl; + std::cout << "\tsrp.nd.lar.npandora: " << srp.nd.lar.npandora.GetValue() + << std::endl; + + std::cout << "\tsrp.nd.tms.nixn: " << srp.nd.tms.nixn.GetValue() << std::endl; + } +} diff --git a/cmake/Modules/CPM.cmake b/cmake/Modules/CPM.cmake new file mode 100644 index 0000000..8269a8b --- /dev/null +++ b/cmake/Modules/CPM.cmake @@ -0,0 +1,1269 @@ +# 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.40.2) + +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_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 problem with 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() + +# Add PATCH_COMMAND to CPM_ARGS_UNPARSED_ARGUMENTS. This method consumes a list of files in ARGN +# then generates a `PATCH_COMMAND` appropriate for `ExternalProject_Add()`. This command is appended +# to the parent scope's `CPM_ARGS_UNPARSED_ARGUMENTS`. +function(cpm_add_patches) + # Return if no patch files are supplied. + if(NOT ARGN) + return() + endif() + + # Find the patch program. + find_program(PATCH_EXECUTABLE patch) + if(WIN32 AND NOT PATCH_EXECUTABLE) + # The Windows git executable is distributed with patch.exe. Find the path to the executable, if + # it exists, then search `../usr/bin` and `../../usr/bin` for patch.exe. + find_package(Git QUIET) + if(GIT_EXECUTABLE) + get_filename_component(extra_search_path ${GIT_EXECUTABLE} DIRECTORY) + get_filename_component(extra_search_path_1up ${extra_search_path} DIRECTORY) + get_filename_component(extra_search_path_2up ${extra_search_path_1up} DIRECTORY) + find_program( + PATCH_EXECUTABLE patch HINTS "${extra_search_path_1up}/usr/bin" + "${extra_search_path_2up}/usr/bin" + ) + endif() + endif() + if(NOT PATCH_EXECUTABLE) + message(FATAL_ERROR "Couldn't find `patch` executable to use with PATCHES keyword.") + endif() + + # Create a temporary + set(temp_list ${CPM_ARGS_UNPARSED_ARGUMENTS}) + + # Ensure each file exists (or error out) and add it to the list. + set(first_item True) + foreach(PATCH_FILE ${ARGN}) + # Make sure the patch file exists, if we can't find it, try again in the current directory. + if(NOT EXISTS "${PATCH_FILE}") + if(NOT EXISTS "${CMAKE_CURRENT_LIST_DIR}/${PATCH_FILE}") + message(FATAL_ERROR "Couldn't find patch file: '${PATCH_FILE}'") + endif() + set(PATCH_FILE "${CMAKE_CURRENT_LIST_DIR}/${PATCH_FILE}") + endif() + + # Convert to absolute path for use with patch file command. + get_filename_component(PATCH_FILE "${PATCH_FILE}" ABSOLUTE) + + # The first patch entry must be preceded by "PATCH_COMMAND" while the following items are + # preceded by "&&". + if(first_item) + set(first_item False) + list(APPEND temp_list "PATCH_COMMAND") + else() + list(APPEND temp_list "&&") + endif() + # Add the patch command to the list + list(APPEND temp_list "${PATCH_EXECUTABLE}" "-p1" "<" "${PATCH_FILE}") + endforeach() + + # Move temp out into parent scope. + set(CPM_ARGS_UNPARSED_ARGUMENTS + ${temp_list} + PARENT_SCOPE + ) + +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 + CUSTOM_CACHE_KEY + ) + + set(multiValueArgs URL OPTIONS DOWNLOAD_COMMAND PATCHES) + + 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}" + PATCHES "${CPM_ARGS_PATCHES}" + 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() + + cpm_add_patches(${CPM_ARGS_PATCHES}) + + 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_ARGS_CUSTOM_CACHE_KEY) + # Application set a custom unique directory name + set(download_directory ${CPM_SOURCE_CACHE}/${lower_case_name}/${CPM_ARGS_CUSTOM_CACHE_KEY}) + elseif(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) + # CMake 3.28 added EXCLUDE, SYSTEM (3.25), and SOURCE_SUBDIR (3.18) to FetchContent_Declare. + # Calling FetchContent_MakeAvailable will then internally forward these options to + # add_subdirectory. Up until these changes, we had to call FetchContent_Populate and + # add_subdirectory separately, which is no longer necessary and has been deprecated as of 3.30. + set(fetchContentDeclareExtraArgs "") + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.28.0") + if(${CPM_ARGS_EXCLUDE_FROM_ALL}) + list(APPEND fetchContentDeclareExtraArgs EXCLUDE_FROM_ALL) + endif() + if(${CPM_ARGS_SYSTEM}) + list(APPEND fetchContentDeclareExtraArgs SYSTEM) + endif() + if(DEFINED CPM_ARGS_SOURCE_SUBDIR) + list(APPEND fetchContentDeclareExtraArgs SOURCE_SUBDIR ${CPM_ARGS_SOURCE_SUBDIR}) + endif() + # For CMake version <3.28 OPTIONS are parsed in cpm_add_subdirectory + if(CPM_ARGS_OPTIONS AND NOT DOWNLOAD_ONLY) + foreach(OPTION ${CPM_ARGS_OPTIONS}) + cpm_parse_option("${OPTION}") + set(${OPTION_KEY} "${OPTION_VALUE}") + endforeach() + endif() + endif() + cpm_declare_fetch( + "${CPM_ARGS_NAME}" ${fetchContentDeclareExtraArgs} "${CPM_ARGS_UNPARSED_ARGUMENTS}" + ) + + cpm_fetch_package("${CPM_ARGS_NAME}" ${DOWNLOAD_ONLY} populated ${CPM_ARGS_UNPARSED_ARGUMENTS}) + if(CPM_SOURCE_CACHE AND download_directory) + file(LOCK ${download_directory}/../cmake.lock RELEASE) + endif() + if(${populated} AND ${CMAKE_VERSION} VERSION_LESS "3.28.0") + 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) + 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 DOWNLOAD_ONLY 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) + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.28.0") + if(DOWNLOAD_ONLY) + # MakeAvailable will call add_subdirectory internally which is not what we want when + # DOWNLOAD_ONLY is set. Populate will only download the dependency without adding it to the + # build + FetchContent_Populate( + ${PACKAGE} + SOURCE_DIR "${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-src" + BINARY_DIR "${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-build" + SUBBUILD_DIR "${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-subbuild" + ${ARGN} + ) + else() + FetchContent_MakeAvailable(${PACKAGE}) + endif() + else() + FetchContent_Populate(${PACKAGE}) + endif() + 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/Templates/duneanaobjConfig.cmake.in b/cmake/Templates/duneanaobjConfig.cmake.in new file mode 100644 index 0000000..3b47280 --- /dev/null +++ b/cmake/Templates/duneanaobjConfig.cmake.in @@ -0,0 +1,42 @@ +@PACKAGE_INIT@ + +set(duneanaobj_VERSION @PROJECT_VERSION@) + +find_package(SRProxy @SRProxy_MIN_VERSION@ REQUIRED) + +set(duneanaobj_CXX_STANDARD @duneanaobj_CXX_STANDARD@) + +set(duneanaobj_FOUND TRUE) + +include(${CMAKE_CURRENT_LIST_DIR}/duneanaobj_targets.cmake) +if(NOT TARGET duneanaobj::all) + message(WARNING "Expected to find target duneanaobj::all in ${CMAKE_CURRENT_LIST_DIR}/duneanaobj_targets.cmake") + set(duneanaobj_FOUND FALSE) + return() +endif() + +get_filename_component(duneanaobj_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) + +find_path(duneanaobj_INCLUDE_DIR + NAMES duneanaobj/StandardRecord/StandardRecord.h + PATHS ${duneanaobj_CMAKE_DIR}/../../../include +) + +find_path(duneanaobj_LIB_DIR + NAMES libduneanaobj_StandardRecord.so + PATHS ${duneanaobj_CMAKE_DIR}/../../ +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(duneanaobj + REQUIRED_VARS + duneanaobj_INCLUDE_DIR + duneanaobj_LIB_DIR + VERSION_VAR + duneanaobj_VERSION +) + +message(STATUS "Found duneanaobj Version: ${duneanaobj_VERSION} in \"${duneanaobj_CMAKE_DIR}\"") +message(STATUS " duneanaobj_CXX_STANDARD: ${duneanaobj_CXX_STANDARD}") +message(STATUS " duneanaobj_INCLUDE_DIR: ${duneanaobj_INCLUDE_DIR}") +message(STATUS " duneanaobj_LIB_DIR: ${duneanaobj_LIB_DIR}") diff --git a/cmake/Templates/setup.duneanaobj.sh.in b/cmake/Templates/setup.duneanaobj.sh.in new file mode 100644 index 0000000..abb8d94 --- /dev/null +++ b/cmake/Templates/setup.duneanaobj.sh.in @@ -0,0 +1,87 @@ +#!/bin/bash + +if ! type add_to_PATH &> /dev/null; then + +### Adapted from https://unix.stackexchange.com/questions/4965/keep-duplicates-out-of-path-on-source +function add_to_PATH () { + for d; do + + d=$(cd -- "$d" && { pwd -P || pwd; }) 2>/dev/null # canonicalize symbolic links + if [ -z "$d" ]; then continue; fi # skip nonexistent directory + + if [ "$d" == "/usr/bin" ] || [ "$d" == "/usr/bin64" ] || [ "$d" == "/usr/local/bin" ] || [ "$d" == "/usr/local/bin64" ]; then + case ":$PATH:" in + *":$d:"*) :;; + *) export PATH=$PATH:$d;; + esac + else + case ":$PATH:" in + *":$d:"*) :;; + *) export PATH=$d:$PATH;; + esac + fi + done +} + +fi + +if ! type add_to_LD_LIBRARY_PATH &> /dev/null; then + +function add_to_LD_LIBRARY_PATH () { + for d; do + + d=$(cd -- "$d" && { pwd -P || pwd; }) 2>/dev/null # canonicalize symbolic links + if [ -z "$d" ]; then continue; fi # skip nonexistent directory + + if [ "$d" == "/usr/lib" ] || [ "$d" == "/usr/lib64" ] || [ "$d" == "/usr/local/lib" ] || [ "$d" == "/usr/local/lib64" ]; then + case ":$LD_LIBRARY_PATH:" in + *":$d:"*) :;; + *) export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$d;; + esac + else + case ":$LD_LIBRARY_PATH:" in + *":$d:"*) :;; + *) export LD_LIBRARY_PATH=$d:$LD_LIBRARY_PATH;; + esac + fi + done +} + +function add_to_CMAKE_PREFIX_PATH () { + for d; do + + d=$(cd -- "$d" && { pwd -P || pwd; }) 2>/dev/null # canonicalize symbolic links + if [ -z "$d" ]; then continue; fi # skip nonexistent directory + + if [ "$d" == "/usr/lib" ] || [ "$d" == "/usr/lib64" ] || [ "$d" == "/usr/local/lib" ] || [ "$d" == "/usr/local/lib64" ]; then + case ":$CMAKE_PREFIX_PATH:" in + *":$d:"*) :;; + *) export CMAKE_PREFIX_PATH=$CMAKE_PREFIX_PATH:$d;; + esac + else + case ":$CMAKE_PREFIX_PATH:" in + *":$d:"*) :;; + *) export CMAKE_PREFIX_PATH=$d:$CMAKE_PREFIX_PATH;; + esac + fi + done +} + +fi + +#if it was sourced as . setup.sh then you can't scrub off the end... assume that +#we are in the correct directory. +if ! echo "${BASH_SOURCE}" | grep "/" --silent; then + SETUPDIR=$(readlink -f ${PWD}/..) +else + SETUPDIR=$(readlink -f ${BASH_SOURCE%/*}/..) +fi + +export DUNEANAOBJ_VERSION=@DUNEANAOBJ_VERSION@ +export DUNEANAOBJ_INC=${SETUPDIR}/include + +add_to_PATH ${SETUPDIR}/bin +add_to_LD_LIBRARY_PATH ${SETUPDIR}/lib +add_to_CMAKE_PREFIX_PATH ${SETUPDIR} + +unset SETUPDIR diff --git a/duneanaobj/StandardRecord/CMakeLists.txt b/duneanaobj/StandardRecord/CMakeLists.txt index bd5677b..2bfefdc 100644 --- a/duneanaobj/StandardRecord/CMakeLists.txt +++ b/duneanaobj/StandardRecord/CMakeLists.txt @@ -1,32 +1,104 @@ -add_subdirectory(Proxy) -add_subdirectory(Flat) +execute_process(COMMAND git rev-parse --short=8 HEAD + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../.. + OUTPUT_VARIABLE duneanaobj_GITSHORTHASH8 + RESULT_VARIABLE GIT_CMD_SUCCESS + OUTPUT_STRIP_TRAILING_WHITESPACE) -# for classes_def.xml!! -include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ) +if(NOT GIT_CMD_SUCCESS EQUAL 0) + message(FATAL_ERROR "Failed to run git rev-parse --short=8 HEAD in ${CMAKE_CURRENT_SOURCE_DIR}/../..") +endif() -set( PACKAGE duneanaobj_StandardRecord ) -FILE( GLOB src_files *.cxx ) +configure_file(StandardRecord.cxx.in ${CMAKE_CURRENT_BINARY_DIR}/StandardRecord.cxx @ONLY) -# For this directory only, pedantic option to catch uninitialized SR fields -# add_compile_options(-Weffc++) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../..) -if(DEFINED CETMODULES_CURRENT_PROJECT_NAME) - cet_make_library( LIBRARY_NAME duneanaobj_StandardRecord - SOURCE ${src_files} - LIBRARIES ROOT::Core ROOT::Physics - ) +ROOT_GENERATE_DICTIONARY(StandardRecordDict StandardRecord.h + LINKDEF classes_def.xml) - build_dictionary( duneanaobj_StandardRecord - DICTIONARY_LIBRARIES duneanaobj_StandardRecord - ) +SET(SR_IMPL_FILES + Navigate.cxx + SRFD.cxx + SRGArTrack.cxx + SRGlobal.cxx + SRInteraction.cxx + SRLorentzVector.cxx + SRMeta.cxx + SRMINERvA.cxx + SRNDLAr.cxx + SRSystParamHeader.cxx + SRTrack.cxx + SRTruthBranch.cxx + SRVector3D.cxx + SRWeightGlobal.cxx + StandardRecord.cxx + ${CMAKE_CURRENT_BINARY_DIR}/StandardRecordDict.cxx +) - install_headers() - install_source() -else() - add_library(duneanaobj_StandardRecord - ${src_files}) - target_link_libraries(duneanaobj_StandardRecord - ROOT::Core ROOT::Physics ) +SET(SR_HEADER_FILES + SRBeamBranch.h + SRCommonRecoBranch.h + SRCVNScoreBranch.h + SRDetectorMetaBranch.h + SRDirectionBranch.h + SREnums.h + SRFD.h + SRFDBranch.h + SRGAr.h + SRGArECAL.h + SRGArTrack.h + SRGlobal.h + SRInteraction.h + SRInteractionBranch.h + SRLorentzVector.h + SRMeta.h + SRMINERvA.h + SRNDAssnBranch.h + SRNDBranch.h + SRNDLAr.h + SRNDShowerAssn.h + SRNDTrackAssn.h + SRNeutrinoEnergyBranch.h + SRNeutrinoHypothesisBranch.h + SROpticalFlash.h + SRPFP.h + SRRecoParticle.h + SRRecoParticlesBranch.h + SRSAND.h + SRShower.h + SRSystParamHeader.h + SRTMS.h + SRTrack.h + SRTrueInteraction.h + SRTrueParticle.h + SRTruthBranch.h + SRVector3D.h + SRWeightGlobal.h +) - # n.b.: missing the dictionary and installation! -endif() +add_library(duneanaobj_StandardRecord SHARED ${SR_IMPL_FILES}) +target_link_libraries(duneanaobj_StandardRecord PUBLIC ROOT::Physics ROOT::MathCore) +target_include_directories(duneanaobj_StandardRecord PUBLIC + $ + $) +target_include_directories(duneanaobj_StandardRecord PRIVATE + $ #root puts this in the dictionary + ) +set_target_properties(duneanaobj_StandardRecord PROPERTIES EXPORT_NAME StandardRecord) +install(TARGETS duneanaobj_StandardRecord EXPORT duneanaobj_targets DESTINATION lib) +install(FILES ${SR_HEADER_FILES} DESTINATION include/duneanaobj/StandardRecord) +install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/libStandardRecordDict_rdict.pcm + ${CMAKE_CURRENT_BINARY_DIR}/libStandardRecordDict.rootmap + DESTINATION lib) + +add_library(duneanaobj::StandardRecord ALIAS duneanaobj_StandardRecord) + +# get the location of these to allow the code generation scripts to properly set up +# dependencies +SET(SR_HEADER_FILE_FQPS) +foreach(HDR ${SR_HEADER_FILES}) + LIST(APPEND SR_HEADER_FILE_FQPS ${CMAKE_CURRENT_SOURCE_DIR}/${HDR}) +endforeach() + +add_subdirectory(Proxy) +add_subdirectory(Flat) diff --git a/duneanaobj/StandardRecord/Flat/CMakeLists.txt b/duneanaobj/StandardRecord/Flat/CMakeLists.txt index 25d2ad8..34114e9 100644 --- a/duneanaobj/StandardRecord/Flat/CMakeLists.txt +++ b/duneanaobj/StandardRecord/Flat/CMakeLists.txt @@ -1,31 +1,22 @@ -FILE(GLOB SR_DEPENDENCIES duneanaobj/StandardRecord/*.h) +GenSRProxy( + HEADER duneanaobj/StandardRecord/StandardRecord.h + FLAT + OUTPUT_NAME SRFlat + TARGETNAME caf::StandardRecord + PROLOG ${CMAKE_CURRENT_SOURCE_DIR}/Prolog.h + INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../../.. ${ROOT_INCLUDE_DIRS} + DEPENDENCIES ${SR_HEADER_FILE_FQPS}) -add_custom_command(# Rebuild if anything in StandardRecord/ changes - DEPENDS ${SR_DEPENDENCIES} - OUTPUT FlatRecord.cxx FlatRecord.h FwdDeclare.h - COMMAND gen_srproxy --flat -i duneanaobj/StandardRecord/StandardRecord.h -o FlatRecord --target caf::StandardRecord --include-path ${PROJECT_SOURCE_DIR}:$ENV{ROOT_INC} --output-path duneanaobj/StandardRecord/Flat/ --prolog ${CMAKE_CURRENT_SOURCE_DIR}/Prolog.h --extra-cflags ' -D_Float16=short -fsized-deallocation' - ) +add_library(duneanaobj_StandardRecordFlat SHARED SRFlat.cxx) +target_link_libraries(duneanaobj_StandardRecordFlat PUBLIC SRProxy::FlatTypes) +target_include_directories(duneanaobj_StandardRecordFlat PUBLIC + $ + $ + $) -include_directories($ENV{SRPROXY_INC}) +install(TARGETS duneanaobj_StandardRecordFlat EXPORT duneanaobj_targets DESTINATION lib) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/SRFlat.h + ${CMAKE_CURRENT_BINARY_DIR}/FwdDeclare.h + DESTINATION include/duneanaobj/StandardRecord/Flat) -if(DEFINED CETMODULES_CURRENT_PROJECT_NAME) - cet_make_library(LIBRARY_NAME duneanaobj_StandardRecordFlat - SOURCE FlatRecord.cxx - LIBRARIES ${ROOT_BASIC_LIB_LIST} ROOT::TreePlayer - ) - - if (DEFINED ENV{MRB_BUILDDIR} AND NOT "$ENV{MRB_BUILDDIR}" STREQUAL "") - set(builddir $ENV{MRB_BUILDDIR}/duneanaobj) - else() - set(builddir ${CMAKE_BINARY_DIR}) - endif() - install_headers(EXTRAS ${builddir}/duneanaobj/StandardRecord/Flat/FlatRecord.h ${builddir}/duneanaobj/StandardRecord/Flat/FwdDeclare.h) -else() - add_library(duneanaobj_StandardRecordFlat - FlatRecord.cxx) - target_link_libraries(duneanaobj_StandardRecordFlat ${ROOT_BASIC_LIB_LIST} ROOT::TreePlayer) - - install(FILES ${CMAKE_BINARY_DIR}/duneanaobj/StandardRecord/Flat/FlatRecord.h ${CMAKE_BINARY_DIR}/duneanaobj/StandardRecord/Flat/FwdDeclare.h - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/duneanaobj) - -endif() +add_library(duneanaobj::StandardRecordFlat ALIAS duneanaobj_StandardRecordFlat) diff --git a/duneanaobj/StandardRecord/Proxy/CMakeLists.txt b/duneanaobj/StandardRecord/Proxy/CMakeLists.txt index 3ae40de..ae55f7a 100644 --- a/duneanaobj/StandardRecord/Proxy/CMakeLists.txt +++ b/duneanaobj/StandardRecord/Proxy/CMakeLists.txt @@ -1,35 +1,61 @@ -FILE(GLOB SR_DEPENDENCIES duneanaobj/StandardRecord/*.h) +SET(GEN_PYTHON_BINDINGS) +if(duneanaobj_PYTHON_ENABLED) + SET(GEN_PYTHON_BINDINGS EMIT_PYTHON_BINDINGS) +endif() + +GenSRProxy( + HEADER duneanaobj/StandardRecord/StandardRecord.h + OUTPUT_NAME SRProxy + TARGETNAME caf::StandardRecord + PROLOG ${CMAKE_CURRENT_SOURCE_DIR}/Prolog.h + EPILOG_FWD ${CMAKE_CURRENT_SOURCE_DIR}/EpilogFwd.h + INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../../.. ${ROOT_INCLUDE_DIRS} + DEPENDENCIES ${SR_HEADER_FILE_FQPS} + ${GEN_PYTHON_BINDINGS} + VVERBOSE) + +add_library(duneanaobj_StandardRecordProxy SHARED SRProxy.cxx) +target_link_libraries(duneanaobj_StandardRecordProxy PUBLIC SRProxy::BasicTypes duneanaobj_StandardRecord) +target_include_directories(duneanaobj_StandardRecordProxy PUBLIC + $ + $ + $) + +install(TARGETS duneanaobj_StandardRecordProxy EXPORT duneanaobj_targets DESTINATION lib) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/SRProxy.h + ${CMAKE_CURRENT_BINARY_DIR}/FwdDeclare.h + DESTINATION include/duneanaobj/StandardRecord/Proxy) + +add_library(duneanaobj::StandardRecordProxy ALIAS duneanaobj_StandardRecordProxy) + +if(duneanaobj_PYTHON_ENABLED) + find_package(Python3 REQUIRED COMPONENTS Development Interpreter) + + # PYTHON PATHS + set(duneanaobj_PYTHONPATH "python/${Python3_VERSION_MAJOR}.${Python3_VERSION_MINOR}") -add_custom_command(# Rebuild if anything in StandardRecord/ changes - DEPENDS ${SR_DEPENDENCIES} - OUTPUT SRProxy.cxx SRProxy.h FwdDeclare.h - COMMAND gen_srproxy -i duneanaobj/StandardRecord/StandardRecord.h -o SRProxy --target caf::StandardRecord --include-path ${PROJECT_SOURCE_DIR}:$ENV{ROOT_INC} --output-path duneanaobj/StandardRecord/Proxy/ --prolog ${CMAKE_CURRENT_SOURCE_DIR}/Prolog.h --epilog-fwd ${CMAKE_CURRENT_SOURCE_DIR}/EpilogFwd.h --extra-cflags ' -D_Float16=short -fsized-deallocation' + include(FetchContent) + + FetchContent_Declare( + pybind11 + GIT_REPOSITORY https://github.com/pybind/pybind11.git + GIT_TAG f5fbe86 # release-3.0.1 ) -include_directories($ENV{SRPROXY_INC}) - -# This is a very picky error buried inside template instantiations -#add_definitions(-Wno-int-in-bool-context) - -if(DEFINED CETMODULES_CURRENT_PROJECT_NAME) - message(STATUS "CETMODULES_CURRENT_PROJECT_NAME = '${CETMODULES_CURRENT_PROJECT_NAME}'") - cet_make_library(LIBRARY_NAME duneanaobj_StandardRecordProxy - SOURCE SRProxy.cxx Instantiations.cxx - LIBRARIES ${ROOT_BASIC_LIB_LIST} ROOT::TreePlayer) - - if (DEFINED ENV{MRB_BUILDDIR} AND NOT "$ENV{MRB_BUILDDIR}" STREQUAL "") - message(STATUS "MRB_BUILDDIR = $ENV{MRB_BUILDDIR}") - set(builddir $ENV{MRB_BUILDDIR}/duneanaobj) - else() - set(builddir ${CMAKE_BINARY_DIR}) - endif() - install_headers(EXTRAS ${builddir}/duneanaobj/StandardRecord/Proxy/SRProxy.h ${builddir}/duneanaobj/StandardRecord/Proxy/FwdDeclare.h) -else() - add_library(duneanaobj_StandardRecordProxy - SRProxy.cxx Instantiations.cxx) - target_link_libraries(duneanaobj_StandardRecordProxy ${ROOT_BASIC_LIB_LIST} ROOT::TreePlayer) - - install(FILES ${CMAKE_BINARY_DIR}/duneanaobj/StandardRecord/Proxy/SRProxy.h ${CMAKE_BINARY_DIR}/duneanaobj/StandardRecord/Proxy/FwdDeclare.h - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/duneanaobj) -endif() + FetchContent_MakeAvailable(pybind11) + + pybind11_add_module(pySRProxy SHARED SRProxy.pybind.cxx) + target_include_directories(pySRProxy + PRIVATE + $ + $ + ) + + target_link_libraries(pySRProxy + PRIVATE + duneanaobj::StandardRecordProxy) + + install(TARGETS pySRProxy + LIBRARY DESTINATION ${duneanaobj_PYTHONPATH}) +endif() diff --git a/duneanaobj/StandardRecord/Proxy/EpilogFwd.h b/duneanaobj/StandardRecord/Proxy/EpilogFwd.h index 5f1a363..68f76e0 100644 --- a/duneanaobj/StandardRecord/Proxy/EpilogFwd.h +++ b/duneanaobj/StandardRecord/Proxy/EpilogFwd.h @@ -1,3 +1,3 @@ - -namespace caf{using SRProxy = caf::Proxy;} - +namespace caf { +using SRProxy = caf::Proxy; +} diff --git a/duneanaobj/StandardRecord/SRLorentzVector.h b/duneanaobj/StandardRecord/SRLorentzVector.h index 6830811..244a69e 100644 --- a/duneanaobj/StandardRecord/SRLorentzVector.h +++ b/duneanaobj/StandardRecord/SRLorentzVector.h @@ -30,8 +30,6 @@ namespace caf SRLorentzVector(); virtual ~SRLorentzVector() = default; -#if !defined(__GCCXML__) && !defined(__castxml__) - SRLorentzVector(const TLorentzVector& v); /// Recommend users convert back to TLorentzVector for boosts etc @@ -50,7 +48,6 @@ namespace caf float Gamma() const {return 1.0/sqrt(1-Beta()*Beta());} TVector3 Vect() const {return TVector3(px, py, pz);} -#endif float E; float px; diff --git a/duneanaobj/StandardRecord/SRTrack.h b/duneanaobj/StandardRecord/SRTrack.h index 64e8a41..f4658b3 100644 --- a/duneanaobj/StandardRecord/SRTrack.h +++ b/duneanaobj/StandardRecord/SRTrack.h @@ -42,8 +42,6 @@ namespace caf } -#if !defined(__GCCXML__) && !defined(__castxml__) std::ostream & operator<<(std::ostream & stream, const caf::SRTrack & tr); -#endif #endif //DUNEANAOBJ_SRTRACK_H diff --git a/duneanaobj/StandardRecord/StandardRecord.cxx b/duneanaobj/StandardRecord/StandardRecord.cxx deleted file mode 100644 index c507d96..0000000 --- a/duneanaobj/StandardRecord/StandardRecord.cxx +++ /dev/null @@ -1,3 +0,0 @@ -// n.b.: this file exists only so that CMake can discover all the *other* headers that it depends on - -#include "duneanaobj/StandardRecord/StandardRecord.h" diff --git a/duneanaobj/StandardRecord/StandardRecord.cxx.in b/duneanaobj/StandardRecord/StandardRecord.cxx.in new file mode 100644 index 0000000..88bee0a --- /dev/null +++ b/duneanaobj/StandardRecord/StandardRecord.cxx.in @@ -0,0 +1,17 @@ +#include "duneanaobj/StandardRecord/StandardRecord.h" + +#include + +namespace caf +{ + StandardRecord::StandardRecord() : + duneanaobj_gitshorthash("@duneanaobj_GITSHORTHASH8@"), + duneanaobj_version{@duneanaobj_VERSION_MAJOR@,@duneanaobj_VERSION_MINOR@,@duneanaobj_VERSION_PATCH@} + { + } + + StandardRecord::~StandardRecord() + { + } + +} // end namespace caf \ No newline at end of file diff --git a/duneanaobj/StandardRecord/StandardRecord.h b/duneanaobj/StandardRecord/StandardRecord.h index 42fe948..58f6a66 100644 --- a/duneanaobj/StandardRecord/StandardRecord.h +++ b/duneanaobj/StandardRecord/StandardRecord.h @@ -24,6 +24,13 @@ namespace caf class StandardRecord { public: + + StandardRecord(); + ~StandardRecord(); + + std::string duneanaobj_gitshorthash; + unsigned short duneanaobj_version[3]; + /// Metadata about the detectors SRDetectorMetaBranch meta; diff --git a/duneanaobj/StandardRecord/classes.h b/duneanaobj/StandardRecord/classes.h deleted file mode 100644 index 8040fdd..0000000 --- a/duneanaobj/StandardRecord/classes.h +++ /dev/null @@ -1,4 +0,0 @@ -#include - -#include "duneanaobj/StandardRecord/StandardRecord.h" -#include "duneanaobj/StandardRecord/SRGlobal.h" diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..f3fc89e --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,2 @@ +add_executable(duneanaobj_dummyevent duneanaobj_dummyevent.cxx) +target_link_libraries(duneanaobj_dummyevent duneanaobj::All ROOT::Tree ROOT::RIO) \ No newline at end of file diff --git a/test/duneanaobj_dummyevent.cxx b/test/duneanaobj_dummyevent.cxx new file mode 100644 index 0000000..49b9257 --- /dev/null +++ b/test/duneanaobj_dummyevent.cxx @@ -0,0 +1,92 @@ +#include "duneanaobj/StandardRecord/StandardRecord.h" + +#include "TFile.h" +#include "TTree.h" + +using namespace caf; + +int main(int argc, char const *argv[]) { + + TFile fout(argv[1], "RECREATE"); + + TTree *tout = new TTree("caf", "dummy caf tree"); + + StandardRecord *sr = nullptr; + + tout->Branch("StandardRecord", &sr); + + SRParticleTruth NDLArTrack_truth; + NDLArTrack_truth.trkid = 1; + NDLArTrack_truth.pdg = 13; + NDLArTrack_truth.motherpdg = 14; + NDLArTrack_truth.p = SRLorentzVector(TLorentzVector(1, 2, 3, 4)); + NDLArTrack_truth.motherp = SRLorentzVector(TLorentzVector(0, 0, 5, 5)); + NDLArTrack_truth.start = SRVector3D(0.1, 0.2, 0.3); + + SRTrack NDLArTrack; + NDLArTrack.start = SRVector3D(1, 2, 3); + NDLArTrack.end = SRVector3D(4, 5, 6); + NDLArTrack.dir = SRVector3D(3, 2, 1); + NDLArTrack.enddir = SRVector3D(6, 5, 4); + NDLArTrack.Evis = 100; + NDLArTrack.len_gcm2 = 200; + NDLArTrack.E = 300; + NDLArTrack.len_cm = 400; + NDLArTrack.qual = 500; + NDLArTrack.truth = NDLArTrack_truth; + + SRParticleTruth NDLArShower_truth; + NDLArShower_truth.trkid = 4; + NDLArShower_truth.pdg = 11; + NDLArShower_truth.motherpdg = 12; + NDLArShower_truth.p = SRLorentzVector(TLorentzVector(4, 3, 2, 1)); + NDLArShower_truth.motherp = SRLorentzVector(TLorentzVector(0, 0, 6, 6)); + NDLArShower_truth.start = SRVector3D(0.4, 0.5, 0.6); + + SRShower NDLArShower; + NDLArShower.start = SRVector3D(10, 20, 30); + NDLArShower.direction = SRVector3D(40, 50, 60); + NDLArShower.Evis = 10; + NDLArShower.truth = NDLArShower_truth; + + sr->nd.lar.tracks.push_back(NDLArTrack); + sr->nd.lar.ntracks = 1; + sr->nd.lar.showers.push_back(NDLArShower); + sr->nd.lar.nshowers = 1; + + SRParticleTruth TMSTrack_truth; + TMSTrack_truth.trkid = 1; + TMSTrack_truth.pdg = 13; + TMSTrack_truth.motherpdg = 14; + TMSTrack_truth.p = SRLorentzVector(TLorentzVector(1, 2, 3, 4)); + TMSTrack_truth.motherp = SRLorentzVector(TLorentzVector(0, 0, 5, 5)); + TMSTrack_truth.start = SRVector3D(0.1, 0.2, 0.3); + + SRTrack TMSTrack; + TMSTrack.start = SRVector3D(11, 12, 13); + TMSTrack.end = SRVector3D(14, 15, 16); + TMSTrack.dir = SRVector3D(-3, -2, -1); + TMSTrack.enddir = SRVector3D(-6, -5, -4); + TMSTrack.Evis = 150; + TMSTrack.len_gcm2 = 250; + TMSTrack.E = 350; + TMSTrack.len_cm = 450; + TMSTrack.qual = 550; + TMSTrack.truth = TMSTrack_truth; + + sr->nd.tms.tracks.push_back(TMSTrack); + sr->nd.tms.ntracks = 1; + + sr->nd.ntrkmatch = 1; + sr->nd.trkmatch.push_back(SRNDTrackAssn{0, 0, 123, 456}); + + sr->nd.LArID = 1337; + sr->nd.TMSID = 7331; + sr->nd.Residual = 12345; + sr->nd.cosTheta = 0.12345; + + tout->Fill(); + + fout.Write(); + fout.Close(); +} \ No newline at end of file diff --git a/ups/setup_for_development b/ups/setup_for_development deleted file mode 100644 index e46765f..0000000 --- a/ups/setup_for_development +++ /dev/null @@ -1,260 +0,0 @@ -######################################################################## -# This script is shell-agnostic, which involves much acrobatics to avoid -# causing errors in one interpreter or another (*stares in csh*). -# -# There should be as little as possible here, with most of the heavy -# lifting done by other small scripts. -# -# When sourcing this file from a script, you may have to tell this -# source file where it is via the fw_db shell (or env) variable, i.e. -# set fw_db=/some/path; source /some/path/this_file -# or fw_db=/some/path; . /some/path/this_file -# -# Generated by cetmodules 3.22.02 at Wed Sep 13 16:53:29 CDT 2023 -######################################################################## - -######################################################################## -# NO USER-SERVICEABLE PARTS BELOW. -######################################################################## - -# Determine shell flavor. -true && test $?shell = 1 && set _cetpkg_shell_flavor=csh || _cetpkg_shell_flavor=sh - -#################################### -# A common set of commands to use to hide as many shell flavor -# differences as possible. - -################## -# IMPORTANT NOTE: -# -# Following extensive tests in multiple shells, I have reached the -# conclusion that it is not actually possible for a function to mirror -# the semantics of an assignment with respect to the status code of `` -# and compound statements joined with "||" or "&&". To handle this, we -# write a large chunk of shell code to a temporary file in the current -# directory a.k.a. CETPKG_BUILD with shell variable assignments correct -# according to the shell flavor, and then source it. This also allows us -# to deal with the fact that some shells don't pass arguments to sourced -# scripts *stares harder in csh*. -# -# 2020-06-24 CHG. -################## - -# If we're C-flavored, set up the commands using alias. -test "$_cetpkg_shell_flavor" = csh && \ - set _cetpkg_nobuild="" && \ - set _cetpkg_shell_var_set=set\\1 && \ - set _cetpkg_to_stderr="| sh -c 'cat 1>\\&2'" && \ - alias vecho_ 'if ($?vv == 1) echo \>\> \!*' && \ - alias unsetenv_ unsetenv && \ - alias tnotnull "eval '"'test $?'"\!* -eq 1' && eval '"'test -n "$'"\!*"'"'"'" && \ - alias nullout "\!* >& /dev/null" && \ - alias __TOP_EOF__ '' && \ - alias return exit - -# For Bourne-flavored shells, use functions. -test "$_cetpkg_shell_flavor" = sh && \ - _cetpkg_nobuild="" && \ - _cetpkg_shell_var_set= && \ - _cetpkg_to_stderr='1>\&2' && \ - eval 'vecho_() { test -n "${vv-}" && echo ">> $*"; return 0; }' && \ - eval 'setenv() { eval "$1=\"\${2-}\"; export $1"; }' && \ - eval 'unsetenv_() { unset "$@"; }' && \ - eval 'source() { . "$@"; }' && \ - eval 'tnotnull() { eval "test -n \"\${$1-}\""; }' && \ - eval 'nullout() { "$@" >/dev/null 2>&1; }' -#################################### - -################## -# Check for UPS (uses alias for return in C-flavored shells). -test -z "$UPS_DIR" && \ - ( echo ""; echo "ERROR: you MUST set up UPS"; echo "" ) && \ - return 1 || true -################## - -#################################### -# Need to find ourselves to set CETPKG_SOURCE. - -# Define empty variables for C-flavor shells to make things easier. -test "$_cetpkg_shell_flavor" = csh && \ - set _cetpkg_fw_db= _cetpkg_myself= _cetpkg_mydir= - -# If user has set fw_db, identify our top-level source directory now. -test "$_cetpkg_shell_flavor" = csh && tnotnull fw_db && \ - set _cetpkg_fw_db=`sh -c "cd $fw_db:q >/dev/null 2>&1 && /bin/pwd -P"` && \ - vecho_ "found ourselves through fw_db" || true -test "$_cetpkg_shell_flavor" = sh && tnotnull fw_db && \ - _cetpkg_fw_db=`sh -c "cd \"$fw_db\" >/dev/null 2>&1 && /bin/pwd -P"` && \ - vecho_ "found ourselves through fw_db" || true - -################## -# For Bash and zsh, identify ourselves now so we don't have to go -# through acrobatics later in the sourced script. -test "$_cetpkg_shell_flavor" = sh && tnotnull BASH_SOURCE && \ - _cetpkg_myself="$BASH_SOURCE" && test -n "$BASH_SOURCE" && \ - vecho_ "found ourselves through BASH_SOURCE" || true -test "$_cetpkg_shell_flavor" = sh -a -z "$_cetpkg_myself" && \ - tnotnull ZSH_VERSION && eval '_cetpkg_myself="${(%):-%x}"' && \ - test -n "$_cetpkg_myself" && \ - vecho_ "found ourselves through ZSH prompt logic" || true -test "$_cetpkg_shell_flavor" = sh && tnotnull _cetpkg_myself && \ - _cetpkg_mydir=`dirname "$_cetpkg_myself"` && \ - _cetpkg_fw_db=`sh -c "cd $_cetpkg_mydir >/dev/null 2>&1 && /bin/pwd -P"` || true -################## - -################## -# History is applicable only for interactive t/csh. -test -z "$_cetpkg_fw_db" -a "$_cetpkg_shell_flavor" = csh -a $?history = 0 && \ - set history=5 || true -test -z "$_cetpkg_fw_db" -a "$_cetpkg_shell_flavor" = csh && \ - set _cetpkg_mydir=`history 1|sed -Ee 's/^[[:space:][:digit:]:]*.*\bsource[[:space:]]+//'` && \ - test -n "$_cetpkg_mydir" && set _cetpkg_mydir=`dirname $_cetpkg_mydir[1]:q` && \ - set _cetpkg_fw_db=`sh -c "cd $_cetpkg_mydir:q >/dev/null 2>&1 && /bin/pwd -P"` && \ - vecho_ 'setting db via interactive history' || true -################## - -# Set CETPKG_SOURCE. -test -n "$_cetpkg_fw_db" && \ - vecho_ "_cetpkg_fw_db=$_cetpkg_fw_db" && \ - setenv CETPKG_SOURCE `dirname $_cetpkg_fw_db` || \ - printf "WARNING: please set shell or env. variable fw_db (to be the path to the\n\ - framework source code). Fix this and other errors may go away.\n" -#################################### - -################## -# Set CETPKG_BUILD. -setenv CETPKG_BUILD `/bin/pwd -P` -################## - -######################################################################## -# Write the rest of ourselves to a file and source it to handle status -# code semantics for variable assignments. -# -# Note that even here we have to play a trick or two due to the fact -# that we have to deal with the difference in the way sh- and csh-flavor -# shells handle a quoted delimiter word for a HERE document: the latter -# expect the delimiter to include the quoting; the former do not. This -# is the reason for the C-flavored __TOP_EOF__ alias, and the explicit -# return at the end of the sourced script. -# -######################################################################## - -sed -Ee 's&(^|[^[:alnum:]_])__SET__([[:space:]]+)&'$_cetpkg_shell_var_set'&g' \ - -e 's&__SETUP_ARGS__&'"$*"'&g' \ - -e 's&__TO_STDERR__&'"$_cetpkg_to_stderr"'&g' \ - > ./setup_common.$_cetpkg_shell_flavor <<\__TOP_EOF__ -######################################################################## - -#################################### -# Personality check: are we setup_deps or setup_for_development? -# -# If we're sourcing setup.in directly (e.g. for cetmodules itself) then -# we select "setup_for_development" behavior, otherwise _cetpkg_nobuild -# will be set appropriately by CMake's CONFIGURE() command for -# setup_for_development or setup_deps. - -test -z "$_cetpkg_nobuild" -o "$_cetpkg_nobuild" = "--nobuild" || \ - __SET__ _cetpkg_nobuild="" || true -#################################### - -#################################### -# Initial info. - -printf "\n"; -test -z "$_cetpkg_nobuild" && \ - echo "The working build directory is $CETPKG_BUILD" || true -cat <= 2.00.00" || true -test -n "$_cetpkg_status" -o -z "$_cetpkg_cetmsetup" || setup -B $_cetpkg_cetmsetup -test $? != 0 && __SET__ _cetpkg_status=1 && \ - echo "ERROR: setup of $_cetpkg_cetmsetup has failed" || true -test -z "$_cetpkg_status$_cetpkg_cetmsetup" && setenv PATH `dropit -sfe "$CETPKG_SOURCE/bin"` && __SET__ _cetpkg_cettop="$CETPKG_SOURCE" || true -test -z "$_cetpkg_status$_cetpkg_cettop" -a -n "$CETMODULES_DIR" && __SET__ _cetpkg_cettop="$CETMODULES_DIR" -#################################### - -######################################################################## -# A bootstrapped Perl environment is only needed if we're building -# cetmodules itself. - -test -n "$_cetpkg_status" || test -n "$CETMODULES_DIR" || \ - setup cetpkgsupport -test $? != 0 && __SET__ _cetpkg_status=1 && \ - echo "ERROR: setup of cetpkgsupport has failed" || true -test -n "$_cetpkg_status" || test -n "$CETMODULES_DIR" || \ - yes n | "$_cetpkg_cettop/libexec/bootstrap-perl-env" > \ - "$CETPKG_BUILD/bootstrap.log" -test $? != 0 && __SET__ _cetpkg_status=1 && \ - echo "ERROR: bootstrap of Perl environment for cetmodules has failed: see $CETPKG_BUILD/bootstrap.log" || true -test -n "$_cetpkg_status" || test -n "$CETMODULES_DIR" || \ - eval "`perl -I\"$CETPKG_BUILD/$CET_SUBDIR/CPAN/lib/perl5\" -Mlocal::lib=\"$CETPKG_BUILD/$CET_SUBDIR/CPAN\",\"$CETPKG_BUILD/$CET_SUBDIR/cpan_build\"\`test \$?shell = 1 && printf \",--shelltype=csh\"\``" -test $? != 0 && __SET__ _cetpkg_status=1 && \ - echo "ERROR: setup of Perl environment for cetmodules has failed" || true - -#################################### -# Generate the setup script to set up dependencies. - -test -n "$_cetpkg_status" || \ - __SET__ _cetpkg_setup="`${_cetpkg_cettop}/libexec/set_dev_products $_cetpkg_nobuild __SETUP_ARGS__`" -test $? != 0 -o -z "$_cetpkg_setup" && __SET__ _cetpkg_status=1 && \ - echo "ERROR: generation of setup script has failed" || true -#################################### - -#################################### -# Source the setup script to set up dependencies. - -test -n "$_cetpkg_status" || source "$_cetpkg_setup" -test $? != 0 && __SET__ _cetpkg_status=1 && \ - echo "ERROR: setup of required products has failed" || true -__SET__ _cetpkg_setup_errlog="$CETPKG_BUILD/cetpkg_setup.err" -test -s "$_cetpkg_setup_errlog" && cat "$_cetpkg_setup_errlog" || \ - rm -f "$_cetpkg_setup_errlog" -#################################### - -cat <