diff --git a/cmake/Modules/FindDOOCS.cmake b/cmake/Modules/FindDOOCS.cmake index 07182359..a6b76c0c 100644 --- a/cmake/Modules/FindDOOCS.cmake +++ b/cmake/Modules/FindDOOCS.cmake @@ -4,17 +4,23 @@ # # By default, only the client API is included. If the component "server" is specified, also the # server library will be used. If the component "zmq" is specified, the DOOCSdzmq library will be used as well. +# Currently support components: api, server, zmq, dapi, ddaq, daqreader, daqsndlib, timinglib # # returns: # DOOCS_FOUND : true or false, depending on whether the package was found # DOOCS_VERSION : the package version +# DOOCS_LIBRARIES : list of libraries to link against +# DOOCS_DIR : doocs library dir +# +# Also returns following for compatibility, however imported targets should be preferred for usage: # DOOCS_INCLUDE_DIRS : path to the include directory # DOOCS_LIBRARY_DIRS : path to the library directory -# DOOCS_LIBRARIES : list of libraries to link against # DOOCS_CXX_FLAGS : Flags needed to be passed to the c++ compiler # DOOCS_LINK_FLAGS : Flags needed to be passed to the linker # -# @author Martin Hierholzer, DESY +# For each component , an imported target DOOCS:: is returned. +# We support calling find_package(DOOCS COMPONENTS ) several times, for adding in different components . +# DOOCS_LIBRARIES will be updated to include all requested components as imported targets. # ####################################################################################################################### @@ -32,80 +38,170 @@ SET(DOOCS_FOUND 0) -list(PREPEND DOOCS_FIND_COMPONENTS doocsapi) +# if set, include the --no-as-needed linker flag which helps if inner dependencies between libs are not properly +# set inside the library binaries +set(DOOCS_noAsNeededFlag 1) -if (";${DOOCS_FIND_COMPONENTS};" MATCHES ";zmq;") - list(APPEND DOOCS_FIND_COMPONENTS doocsdzmq) - list(REMOVE_ITEM DOOCS_FIND_COMPONENTS zmq) -endif() +# note, helper functions and variables should also be prefixed with DOOCS_, since everything is exported to +# project calling find_package(DOOCS) -if (";${DOOCS_FIND_COMPONENTS};" MATCHES ";dapi;") - list(APPEND DOOCS_FIND_COMPONENTS doocsdapi) - list(REMOVE_ITEM DOOCS_FIND_COMPONENTS dapi) -endif() +function (DOOCS_addToPkgConfPath newPath) + if (NOT (":$ENV{PKG_CONFIG_PATH}:" MATCHES ":${newPath}:")) + set(ENV{PKG_CONFIG_PATH} $ENV{PKG_CONFIG_PATH}:${newPath}) + endif() +endfunction() -if (";${DOOCS_FIND_COMPONENTS};" MATCHES ";server;") - list(APPEND DOOCS_FIND_COMPONENTS serverlib) - list(REMOVE_ITEM DOOCS_FIND_COMPONENTS server) +if(DOOCS_DIR) + DOOCS_addToPkgConfPath(${DOOCS_DIR}/pkgconfig) endif() - -set(DOOCS_FIND_COMPONENTS_DDAQ false) -if (";${DOOCS_FIND_COMPONENTS};" MATCHES ";ddaq;") - # This library seems not yet to come with a pkg-config module - list(REMOVE_ITEM DOOCS_FIND_COMPONENTS ddaq) - set(DOOCS_FIND_COMPONENTS_DDAQ true) +DOOCS_addToPkgConfPath(/export/doocs/lib/pkgconfig) +if (NOT DOOCS_FIND_QUIETLY) + message("FindDOOCS: Using PKG_CONFIG_PATH=$ENV{PKG_CONFIG_PATH}") endif() -if (";${DOOCS_FIND_COMPONENTS};" MATCHES ";daqreader;") - list(APPEND DOOCS_FIND_COMPONENTS daqreaderlib) - list(REMOVE_ITEM DOOCS_FIND_COMPONENTS daqreader) -endif() - -# For newer cmake versions, the following foreach() can be replaced by this: -# list(TRANSFORM DOOCS_FIND_COMPONENTS PREPEND "doocs-") -foreach(component ${DOOCS_FIND_COMPONENTS}) - list(APPEND DOOCS_FIND_COMPONENTS_TRANSFORMED "doocs-${component}") -endforeach() -set(DOOCS_FIND_COMPONENTS ${DOOCS_FIND_COMPONENTS_TRANSFORMED}) - -include(FindPkgConfig) - -if(DEFINED DOOCS_DIR) - set(ENV{PKG_CONFIG_PATH} $ENV{PKG_CONFIG_PATH}:${DOOCS_DIR}/pkgconfig) +# We add the always - required API component +if (NOT (";${DOOCS_FIND_COMPONENTS};" MATCHES ";api;")) + list(PREPEND DOOCS_FIND_COMPONENTS "api") endif() -set(ENV{PKG_CONFIG_PATH} $ENV{PKG_CONFIG_PATH}:/export/doocs/lib/pkgconfig) -message("Using PKG_CONFIG_PATH=$ENV{PKG_CONFIG_PATH}") - -# WORK AROUND FOR BROKEN DOOCS PKG CONFIG FILES: Search for libgul14 which is required by DOOCS libraries -list(APPEND DOOCS_FIND_COMPONENTS libgul14) -# END OF WORK AROUND -pkg_check_modules(DOOCS REQUIRED ${DOOCS_FIND_COMPONENTS}) +function(expandDoocsComponentName longName shortName) + if (";${shortName};" MATCHES ";api;") + set(${longName} "doocs-doocsapi" PARENT_SCOPE) + elseif (";${shortName};" MATCHES ";zmq;") + set(${longName} "doocs-doocsdzmq" PARENT_SCOPE) + elseif (";${shortName};" MATCHES ";dapi;") + set(${longName} "doocs-doocsdapi" PARENT_SCOPE) + elseif (";${shortName};" MATCHES ";server;") + set(${longName} "doocs-serverlib" PARENT_SCOPE) + elseif (";${shortName};" MATCHES ";ddaq;") + set(${longName} "doocs-doocsddaq" PARENT_SCOPE) + elseif (";${shortName};" MATCHES ";daqreader;") + set(${longName} "doocs-daqreaderlib" PARENT_SCOPE) + elseif (";${shortName};" MATCHES ";daqsndlib;") + set(${longName} "doocs-daqsndlib" PARENT_SCOPE) + elseif (";${shortName};" MATCHES ";timinglib;") + # we define it as alias to doocs-doocsapi and check additional requirements + set(${longName} "doocs-doocsapi" PARENT_SCOPE) + else() + set(${longName} "${shortName}" PARENT_SCOPE) + endif() +endfunction() -string(REPLACE ";" " " DOOCS_CFLAGS "${DOOCS_CFLAGS}") -string(REPLACE ";" " " DOOCS_LDFLAGS "${DOOCS_LDFLAGS}") +include(FindPkgConfig) # thread libraries are required by DOOCS but seem not to be added through pkgconfig... find_package(Threads REQUIRED) -set(DOOCS_DIR "${DOOCS_doocs-doocsapi_LIBDIR}") -set(DOOCS_VERSION "${DOOCS_doocs-doocsapi_VERSION}") +# We expect that find_package will be called more than once, with different components. +# Since imported targets cannot be replaced, the only clean solution is to define an imported component per pkgconfig component. +# pkg_check_modules can be called more than once, with different components. +# We define DOOCS_FIND_COMPONENTS_ALL to collect all asked-for components +foreach(component ${DOOCS_FIND_COMPONENTS}) + expandDoocsComponentName(componentLongName ${component}) + if (NOT ";${DOOCS_FIND_COMPONENTS_ALL};" MATCHES ";${componentLongName};") + list(APPEND DOOCS_FIND_COMPONENTS_ALL ${componentLongName}) + # IMPORTED_TARGET means also imported target PkgConfig::DOOCS will be defined. GLOBAL so we can alias. + pkg_check_modules(DOOCS_${component} REQUIRED IMPORTED_TARGET GLOBAL ${componentLongName}) + if (DOOCS_${component}_FOUND) + set(importedTarget PkgConfig::DOOCS_${component}) + if (NOT DOOCS_FIND_QUIETLY) + message(STATUS "FindDOOCS: imported target is ${importedTarget}. Defining alias DOOCS::${component}") + endif() + add_library(DOOCS::${component} ALIAS ${importedTarget}) + set(DOOCS_LIBRARIES ${DOOCS_LIBRARIES} "DOOCS::${component}") + + if (${component} STREQUAL "api") + # add Threads lib only if not yet in + get_target_property(doocsLinkLibs ${importedTarget} INTERFACE_LINK_LIBRARIES) + if (NOT (";${doocsLinkLibs};" MATCHES ";Threads::Threads;")) + set_target_properties(${importedTarget} PROPERTIES INTERFACE_LINK_LIBRARIES "${doocsLinkLibs};Threads::Threads" ) + endif() + if(DOOCS_noAsNeededFlag) + get_target_property(doocsLinkFlags ${importedTarget} INTERFACE_LINK_OPTIONS) + string(REGEX REPLACE ".*-NOTFOUND" "" doocsLinkFlags "${doocsLinkFlags}") + set_target_properties(${importedTarget} PROPERTIES INTERFACE_LINK_OPTIONS "-Wl,--no-as-needed;${doocsLinkFlags}") + endif() + else() + # since we did some changes on DOOCS::api, add that as implicit dependency of the other components + # This makes sure projects not explicitly linking to DOOCS::api have the changes + get_target_property(doocsLinkLibs ${importedTarget} INTERFACE_LINK_LIBRARIES) + string(REGEX REPLACE ".*-NOTFOUND" "" doocsLinkLibs "${doocsLinkLibs}") + set_target_properties(${importedTarget} PROPERTIES INTERFACE_LINK_LIBRARIES "DOOCS::api;${doocsLinkLibs}") + endif() + + # print some info about targets + get_target_property(doocsIncDirs ${importedTarget} INTERFACE_INCLUDE_DIRECTORIES) + message(VERBOSE " include dirs: ${doocsIncDirs}") + get_target_property(doocsCxxFlags ${importedTarget} INTERFACE_COMPILE_OPTIONS) + message(VERBOSE " compile options: ${doocsCxxFlags}") + get_target_property(doocsLinkFlags ${importedTarget} INTERFACE_LINK_OPTIONS) + message(VERBOSE " link options: ${doocsLinkFlags}") + get_target_property(doocsLinkLibs ${importedTarget} INTERFACE_LINK_LIBRARIES) + message(VERBOSE " link libs: ${doocsLinkLibs}") + get_target_property(doocsLinkDirs ${importedTarget} INTERFACE_LINK_DIRECTORIES) + message(VERBOSE " link dirs: ${doocsLinkDirs}") + + else() + message(FATAL_ERROR "DOOCS component ${component} not found!") + endif() + endif() + if(${component} STREQUAL "timinglib") + # Find doocs/TimingWord.h from dev-doocs-doocstiminglib + # which unfortunately does not provide pkgconfig + find_path(DOOCS_timingLib_INCLUDE_DIRS doocs/TimingWord.h REQUIRED PATHS ${DOOCS_api_INCLUDE_DIRS}) + if (NOT DOOCS_timingLib_INCLUDE_DIRS) + message(FATAL_ERROR "FindDOOCS: Failed to find TimingWord.h") + set(DOOCS_timingLib_FOUND FALSE) + else() + if (NOT DOOCS_FIND_QUIETLY) + message(STATUS "FindDOOCS: Found timinglib, include dirs: ${DOOCS_timingLib_INCLUDE_DIRS}") + endif() + set(DOOCS_timingLib_FOUND TRUE) + # include dir is always same as for api component, so alias is sufficient + add_library(DOOCS::${component} ALIAS PkgConfig::DOOCS_api) + endif() + endif() +endforeach() +#message(DEBUG "complete list of searched components: ${DOOCS_FIND_COMPONENTS_ALL}") + +# append to list (arg) to space-separated list, only include not yet existing elements +macro(DOOCS_appendListToList list arg) + foreach(DOOCS_appendListToList_arg ${arg}) + string(FIND " ${${list}} " " ${DOOCS_appendListToList_arg} " DOOCS_appendListToList_pos) + if (${DOOCS_appendListToList_pos} EQUAL -1) + string(APPEND ${list} " ${DOOCS_appendListToList_arg}") + # strip leading spaces since they might cause problems + string(REGEX REPLACE "^[ \t]+" "" ${list} "${${list}}") + endif() + endforeach() +endmacro() + +# note, pkg_check_modules output variables _VERSION and _LIBDIR are different, +# depending on length of given module list! +set(DOOCS_DIR "${DOOCS_api_LIBDIR}") +set(DOOCS_VERSION "${DOOCS_api_VERSION}") + +set(DOOCS_LIBRARIES ${DOOCS_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) + +# following lines are compatibiliy layer, required only if using project does not make use of imported targets +# here we should gather from all components +set(DOOCS_CFLAGS "") +set(DOOCS_LDFLAGS "") +if(DOOCS_noAsNeededFlag) + set(DOOCS_LDFLAGS "-Wl,--no-as-needed") +endif() +set(DOOCS_INCLUDE_DIRS "") +set(DOOCS_LIBRARY_DIRS "") +foreach(component api zmq server ddaq daqreader daqsndlib) + DOOCS_appendListToList(DOOCS_CFLAGS "${DOOCS_${component}_CFLAGS}") + DOOCS_appendListToList(DOOCS_LDFLAGS "${DOOCS_${component}_LDFLAGS}") + DOOCS_appendListToList(DOOCS_INCLUDE_DIRS "${DOOCS_${component}_INCLUDE_DIRS}") + DOOCS_appendListToList(DOOCS_LIBRARY_DIRS "${DOOCS_${component}_LIBRARY_DIRS}") +endforeach() set(DOOCS_CXX_FLAGS ${DOOCS_CFLAGS}) -set(DOOCS_LIBRARIES ${DOOCS_LDFLAGS} ${CMAKE_THREAD_LIBS_INIT} tinemt) -set(DOOCS_LINKER_FLAGS "-Wl,--no-as-needed") +set(DOOCS_LINKER_FLAGS ${DOOCS_LDFLAGS}) set(DOOCS_LINK_FLAGS ${DOOCS_LINKER_FLAGS}) -set(COMPONENT_DIRS "") -if(DOOCS_FIND_COMPONENTS_DDAQ) - message("Searching for libDOOCSddaq.so") - FIND_PATH(DOOCS_DIR_ddaq libDOOCSddaq.so - ${DOOCS_DIR} - ) - set(DOOCS_LIBRARIES ${DOOCS_LIBRARIES} DOOCSddaq timinginfo daqevstat DAQFSM TTF2XML xerces-c BM TTF2evutl DAQsvrutil) - set(COMPONENT_DIRS ${COMPONENT_DIRS} DOOCS_DIR_ddaq) -endif() - # use a macro provided by CMake to check if all the listed arguments are valid and set DOOCS_FOUND accordingly include(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(DOOCS REQUIRED_VARS DOOCS_DIR ${COMPONENT_DIRS} VERSION_VAR DOOCS_VERSION ) - +FIND_PACKAGE_HANDLE_STANDARD_ARGS(DOOCS REQUIRED_VARS DOOCS_DIR VERSION_VAR DOOCS_VERSION ) diff --git a/cmake/Modules/FindGccAtomic.cmake b/cmake/Modules/FindGccAtomic.cmake index 5b6e233e..284f7bed 100644 --- a/cmake/Modules/FindGccAtomic.cmake +++ b/cmake/Modules/FindGccAtomic.cmake @@ -1,7 +1,7 @@ # This scripts finds gcc's built-in atomic shared library (libatomic.so). # It is required to link against this library on gcc when using 16 byte atomics, even when running on x86_64/amd64. -FIND_LIBRARY(GCCLIBATOMIC_LIBRARY NAMES atomic atomic.so.1 libatomic.so.1 +FIND_LIBRARY(GccAtomic_LIBRARY NAMES atomic atomic.so.1 libatomic.so.1 HINTS $ENV{HOME}/local/lib64 $ENV{HOME}/local/lib @@ -15,5 +15,10 @@ FIND_LIBRARY(GCCLIBATOMIC_LIBRARY NAMES atomic atomic.so.1 libatomic.so.1 /lib ) +# we don't want to export the full path since this introduces problems with yocto cross-compilation +# so replace by simple lib name +if (GccAtomic_LIBRARY) + set(GccAtomic_LIBRARY "atomic") +endif() include(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(GCCLIBATOMIC DEFAULT_MSG GCCLIBATOMIC_LIBRARY) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(GccAtomic DEFAULT_MSG GccAtomic_LIBRARY) diff --git a/cmake/PROJECT_NAMEConfig.cmake.in.in b/cmake/PROJECT_NAMEConfig.cmake.in.in index 17f556a0..b07f6352 100644 --- a/cmake/PROJECT_NAMEConfig.cmake.in.in +++ b/cmake/PROJECT_NAMEConfig.cmake.in.in @@ -11,6 +11,14 @@ # @PROJECT_NAME@_CXX_FLAGS : additional C++ compiler flags # @PROJECT_NAME@_LINKER_FLAGS : additional linker flags # +# Note for exporting project: +# If @PROJECT_NAME@ sets PROVIDES_EXPORTED_TARGETS, we also generate target EXPORTS. In this case the its CMakeLists.txt +# must also have +# install(TARGETS EXPORT ${PROJECT_NAME}Targets) +# before. The target will be named ChimeraTK::${PROJECT_NAME} . +# We keep above mentioned return variables for compatibility, but finally, when all projects use imported targets, +# all execept _FOUND and _VERSION will be superfluous. +# # @author Martin Killenberg, DESY # ####################################################################################################################### @@ -27,42 +35,73 @@ # ####################################################################################################################### -# The library itself must be "searched" using the FIND_LIBRARY command in the known install directory, to set -# the variable properly -FIND_LIBRARY(@PROJECT_NAME@_LIBRARY @PROJECT_NAME@ - @CMAKE_INSTALL_PREFIX@/lib - NO_DEFAULT_PATH -) +# In case of packages with components, loading dependencies can cause trouble if required component list are differ. +# E.g. if Boost is required from the project, and also required from the dependency, but with less components, +# and the dependency is resolved later, then Boost_LIBRARIES content will be different than expected. +# To protect against this, save state and restore it later. +# Since imported targets are never unloaded, the loaded dependency should still work. +set(Boost_LIBRARIES_savedState_@PROJECT_NAME@ ${Boost_LIBRARIES}) +# this code loads public dependencies @@PROJECT_NAME@_PUBLIC_DEPENDENCIES_L@ +set(Boost_LIBRARIES ${Boost_LIBRARIES_savedState_@PROJECT_NAME@}) # Since this file is already part of the installation to be found, the configuration can be hard-coded at # installation time set(@PROJECT_NAME@_VERSION "@@PROJECT_NAME@_SOVERSION@") -set(@PROJECT_NAME@_INCLUDE_DIRS @@PROJECT_NAME@_INCLUDE_DIRS@) -set(@PROJECT_NAME@_LIBRARY_DIRS @@PROJECT_NAME@_LIBRARY_DIRS@) -if(@@PROJECT_NAME@_HAS_LIBRARY@) - set(@PROJECT_NAME@_LIBRARIES ${@PROJECT_NAME@_LIBRARY} @@PROJECT_NAME@_LIBRARIES@) -else() - set(@PROJECT_NAME@_LIBRARIES @@PROJECT_NAME@_LIBRARIES@) -endif() -set(@PROJECT_NAME@_CXX_FLAGS "@@PROJECT_NAME@_CXX_FLAGS@") -set(@PROJECT_NAME@_LINKER_FLAGS "@@PROJECT_NAME@_LINKER_FLAGS@ @@PROJECT_NAME@_LINK_FLAGS@") -set(@PROJECT_NAME@_LINK_FLAGS "@@PROJECT_NAME@_LINKER_FLAGS@ @@PROJECT_NAME@_LINK_FLAGS@") set(@PROJECT_NAME@_PREFIX "@CMAKE_INSTALL_PREFIX@") # Use a macro provided by CMake to check if all the listed arguments are valid and set @PROJECT_NAME@_FOUND accordingly. # This is mainly important to check the version. -set(@PROJECT_NAME@_FOUND 0) include(FindPackageHandleStandardArgs) -# The FOUND_VAR option in FIND_PACKAGE_HANDLE_STANDARD_ARGS was introduced in cmake-2.8.11, but Ubuntu 12.04 has cmake-2.8.7 only. -# Thus we use a work around here for older cmake versions. -if("${CMAKE_VERSION}" VERSION_LESS 2.8.11) - # The old version always provides a variable with upper case project name, so we just copy that - FIND_PACKAGE_HANDLE_STANDARD_ARGS(@PROJECT_NAME@ REQUIRED_VARS @PROJECT_NAME@_PREFIX VERSION_VAR @PROJECT_NAME@_VERSION) - STRING(TOUPPER "@PROJECT_NAME@" PROJECT_NAME_UPPERCASE) - set(@PROJECT_NAME@_FOUND ${${PROJECT_NAME_UPPERCASE}_FOUND}) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(@PROJECT_NAME@ REQUIRED_VARS @PROJECT_NAME@_PREFIX VERSION_VAR @PROJECT_NAME@_VERSION FOUND_VAR @PROJECT_NAME@_FOUND) + +# switch for exported target. We don't do this automatically, because the calling CMakeLists.txt +# first must be edited so that it properly defines PUBLIC set of compile and link options +if(@PROVIDES_EXPORTED_TARGETS@) + + @PACKAGE_INIT@ + + # include cmake's auto-generated exports file + include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") + # this will set ${PROJECT_NAME}_FOUND if required components are missing + check_required_components(@PROJECT_NAME@) + else() - FIND_PACKAGE_HANDLE_STANDARD_ARGS(@PROJECT_NAME@ REQUIRED_VARS @PROJECT_NAME@_PREFIX VERSION_VAR @PROJECT_NAME@_VERSION FOUND_VAR @PROJECT_NAME@_FOUND) -endif() + if(@@PROJECT_NAME@_HAS_LIBRARY@) + # has true compiled library as output + # The library itself must be "searched" using the FIND_LIBRARY command in the known install directory, to set + # the variable properly + FIND_LIBRARY(@PROJECT_NAME@_LIBRARY @PROJECT_NAME@ + @CMAKE_INSTALL_PREFIX@/lib + NO_DEFAULT_PATH + ) + if(NOT @PROJECT_NAME@_LIBRARY) + set(@PROJECT_NAME@_FOUND FALSE) + message(SEND_ERROR "FIND_LIBRARY returned error: ${@PROJECT_NAME@_LIBRARY}") + else() + # prepend it to lib list + set(@PROJECT_NAME@_LIBRARIES ${@PROJECT_NAME@_LIBRARY} ${@PROJECT_NAME@_LIBRARIES}) + endif() + endif() +endif() + +# Compatibility layer definitions. +# The following variables are generated automatically for projects supporting cmake-exports. +# Otherwise, values must be provided as inputs to create_cmake_config_files. +# The types of generated lists are precisely as in old DeviceAccess config +# inc dirs, lib dirs, libs are ";" separated +# cxx flags, link flags are " " separated +# ";" separated +set(@PROJECT_NAME@_INCLUDE_DIRS @@PROJECT_NAME@_INCLUDE_DIRS@) +# ";" separated +set(@PROJECT_NAME@_LIBRARY_DIRS @@PROJECT_NAME@_LIBRARY_DIRS@) +# ";" separated +set(@PROJECT_NAME@_LIBRARIES ${@PROJECT_NAME@_LIBRARIES} @@PROJECT_NAME@_LIBRARIES@) +# " " separated +set(@PROJECT_NAME@_CXX_FLAGS "@@PROJECT_NAME@_CXX_FLAGS@") +# " " separated +set(@PROJECT_NAME@_LINKER_FLAGS "@@PROJECT_NAME@_LINKER_FLAGS@ @@PROJECT_NAME@_LINK_FLAGS@") +# " " separated +set(@PROJECT_NAME@_LINK_FLAGS "@@PROJECT_NAME@_LINKER_FLAGS@ @@PROJECT_NAME@_LINK_FLAGS@") diff --git a/cmake/add_dependency.cmake b/cmake/add_dependency.cmake index 539efe02..bccd9196 100644 --- a/cmake/add_dependency.cmake +++ b/cmake/add_dependency.cmake @@ -32,6 +32,9 @@ FUNCTION(add_dependency dependency_project_name required_version) foreach(arg IN LISTS ARGN) SET(components ${components} ${arg}) endforeach() + if("${required_version}" MATCHES "REQUIRED") + message(FATAL_ERROR "wrong usage: add_dependency(${dependency_project_name} ${required_version} ...)") + endif() FIND_PACKAGE(${dependency_project_name} ${required_version} COMPONENTS ${components}) include_directories(SYSTEM ${${dependency_project_name}_INCLUDE_DIRS} ${${dependency_project_name}_INCLUDE_DIR}) link_directories(${${dependency_project_name}_LIBRARY_DIRS}) @@ -50,3 +53,12 @@ FUNCTION(add_dependency dependency_project_name required_version) SET(${dependency_project_name}_PREFIX ${${dependency_project_name}_PREFIX} PARENT_SCOPE) ENDFUNCTION(add_dependency) +# make sure that cmake finds modules provided by project-template. +# since with new cmake concept for imported targets, dependencies also search for implicit dependencies, +# all projects using add_dependency also require this module path. +set(_projectTemplateModulePath ${CMAKE_SOURCE_DIR}/cmake/Modules) +# substr search is better than regex if paths have special characters +string(FIND ":${CMAKE_MODULE_PATH}:" ":${_projectTemplateModulePath}:" _projectTemplateModulePathPos) +if (${_projectTemplateModulePathPos} EQUAL -1) + list(APPEND CMAKE_MODULE_PATH "${_projectTemplateModulePath}") +endif() diff --git a/cmake/create_cmake_config_files.cmake b/cmake/create_cmake_config_files.cmake index 6924fac7..70922052 100644 --- a/cmake/create_cmake_config_files.cmake +++ b/cmake/create_cmake_config_files.cmake @@ -5,13 +5,15 @@ # # Expects the following input variables: # ${PROJECT_NAME}_SOVERSION - version of the .so library file (or just MAJOR.MINOR without the patch level) +# ${PROJECT_NAME}_MEXFLAGS - (optional) mex compiler flags +# +# and only required, if project does not yet provide cmake-export: # ${PROJECT_NAME}_INCLUDE_DIRS - list include directories needed when compiling against this project # ${PROJECT_NAME}_LIBRARY_DIRS - list of library directories needed when linking against this project # ${PROJECT_NAME}_LIBRARIES - list of additional libraries needed when linking against this project. The library # provided by the project will be added automatically # ${PROJECT_NAME}_CXX_FLAGS - list of additional C++ compiler flags needed when compiling against this project # ${PROJECT_NAME}_LINKER_FLAGS - list of additional linker flags needed when linking against this project -# ${PROJECT_NAME}_MEXFLAGS - (optional) mex compiler flags # ####################################################################################################################### @@ -27,51 +29,242 @@ # ####################################################################################################################### +macro(handleGeneratorExprs var) + # Unfortunately, I do not see a solution for correct generator expression handling by cmake. So instead, do some simple replacements. + # $ defines path relative to install location. + string(REGEX REPLACE "\\$" "${CMAKE_INSTALL_PREFIX}/\\1" ${var} "${${var}}") + # remove any other generator expression + string(REGEX REPLACE "\\$<.*>" "" ${var} "${${var}}") +endmacro() + +# append element-wise to (space-separated!) list, but only if not yet existing +# arg is allowed to be space-separated or ;-separated list +macro(appendToList list arg) + string(REPLACE " " ";" appendToList_args "${arg}") + foreach(item ${appendToList_args}) + handleGeneratorExprs(item) + string(FIND " ${${list}} " " ${item} " appendToList_pos) + if (${appendToList_pos} EQUAL -1) + string(APPEND ${list} " ${item}") + # strip leading spaces since they might cause problems + string(REGEX REPLACE "^[ \t]+" "" ${list} "${${list}}") + endif() + endforeach() +endmacro() +# prepend element-wise to (space-separated!) list, but only if not yet existing +# arg is allowed to be space-separated or ;-separated list +macro(prependToList list arg) + string(REPLACE " " ";" prependToList_args "${arg}") + foreach(item ${prependToList_args}) + handleGeneratorExprs(item) + string(FIND " ${${list}} " " ${item} " prependToList_pos) + if (${prependToList_pos} EQUAL -1) + string(PREPEND ${list} "${item} ") + # strip trailing spaces since they might cause problems + string(REGEX REPLACE "[ \t]+$" "" ${list} "${${list}}") + endif() + endforeach() +endmacro() + +# for lib, which might be lib File or linker flag or imported target, +# puts recursively resolved library list into ${linkLibs}, which will contain a library file list +# and recursively resolve link flags into ${linkFlags} +# Note, since some projects ignore libDirs, we put them also into linkFlags. +function(resolveImportedLib lib linkLibs linkFlags libDirs incDirs cxxFlags) + set(linkLibs1 "") + set(linkFlags1 "") + set(libDirs1 "") + set(incDirs1 "") + set(cxxFlags1 "") + if(lib MATCHES "/") # library name contains slashes: link against the a file path name + appendToList(linkLibs1 "${lib}") + elseif(lib MATCHES "^[ \t]*-l") + # library name does not contain slashes but already the -l option: directly quote it + # although technically a linker flag, we put it to lib list because order matters sometimes + appendToList(linkLibs1 "${lib}") + elseif(lib MATCHES "::") # library name is an imported target - we need to resolve it for Makefiles + if (NOT TARGET ${lib}) + message(FATAL_ERROR "dependency ${lib} not available as target, maybe find_package was forgotten?") + endif() + get_target_property(_libraryType ${lib} TYPE) + # boost exports appear as UNKNOWN_LIBRARY but also have target location + if ((${_libraryType} MATCHES SHARED_LIBRARY) OR (${_libraryType} MATCHES STATIC_LIBRARY) OR (${_libraryType} MATCHES UNKNOWN_LIBRARY)) + if(";${lib};" MATCHES ";.*::${PROJECT_NAME};") + # We cannot find target library location of this project via target properties at this point. + # Therefore, we simply assume that by convention, all our libs are installed into ${CMAKE_INSTALL_PREFIX}/lib. + # Exceptions are allowed if -L is already in linker flags + appendToList(linkFlags1 "-L${CMAKE_INSTALL_PREFIX}/lib") + appendToList(libDirs1 "${CMAKE_INSTALL_PREFIX}/lib") + appendToList(linkLibs1 "-l${PROJECT_NAME}") + else() + get_property(lib_loc TARGET ${lib} PROPERTY LOCATION) + #message("imported target ${lib} is actual library. location=${lib_loc}") + appendToList(linkLibs1 "${lib_loc}") + endif() + endif() + get_target_property(_linkLibs ${lib} INTERFACE_LINK_LIBRARIES) + if (NOT "${_linkLibs}" MATCHES "-NOTFOUND") + message(VERBOSE "imported target ${lib} is interface, recursively go over its interface requirements ${_linkLibs}") + foreach(_lib ${_linkLibs}) + if (${lib} STREQUAL ${_lib}) + message(FATAL_ERROR "self-reference in dependencies of ${_lib}! Aborting recursion.") + endif() + resolveImportedLib(${_lib} linkLibs2 linkFlags2 libDirs2 incDirs2 cxxFlags2) + appendToList(linkLibs1 "${linkLibs2}") + appendToList(linkFlags1 "${linkFlags2}") + appendToList(libDirs1 "${libDirs2}") + appendToList(incDirs1 "${incDirs2}") + appendToList(cxxFlags1 "${cxxFlags2}") + endforeach() + endif() + + get_target_property(_incDirs ${lib} INTERFACE_INCLUDE_DIRECTORIES) + if (_incDirs) + appendToList(incDirs1 "${_incDirs}") + endif() + get_target_property(_cxxFlags ${lib} INTERFACE_COMPILE_OPTIONS) + if (_cxxFlags) + appendToList(cxxFlags1 "${_cxxFlags}") + endif() + get_target_property(_cxxFlags ${lib} INTERFACE_COMPILE_DEFINITIONS) + if (_cxxFlags) + foreach(flag ${_cxxFlags}) + appendToList(cxxFlags1 "-D${flag}") + endforeach() + endif() + get_target_property(_linkFlags ${lib} INTERFACE_LINK_OPTIONS) + if (_linkFlags) + appendToList(linkFlags1 "${_linkFlags}") + endif() + get_target_property(_linkDirs ${lib} INTERFACE_LINK_DIRECTORES) + if (_linkDirs) + foreach(flag ${_linkDirs}) + handleGeneratorExprs(flag) + appendToList(linkFlags1 "-L${flag}") + appendToList(libDirs1 "${flag}") + endforeach() + endif() + + else() + # link against library with -l option + handleGeneratorExprs(lib) + # although technically a linker flag, we put it to lib list because for some linker flags, it is important + # that they come before libs + appendToList(linkLibs1 "-l${lib}") + endif() + + set(${linkLibs} "${linkLibs1}" PARENT_SCOPE) + set(${linkFlags} "${linkFlags1}" PARENT_SCOPE) + set(${libDirs} "${libDirs1}" PARENT_SCOPE) + set(${incDirs} "${incDirs1}" PARENT_SCOPE) + set(${cxxFlags} "${cxxFlags1}" PARENT_SCOPE) +endfunction() + + +# if we already have cmake-exports for this project: +# sets the vars ${PROJECT_NAME}_INCLUDE_DIRS, ${PROJECT_NAME}_CXX_FLAGS, ${PROJECT_NAME}_LIBRARY_DIRS, +# ${PROJECT_NAME}_LINKER_FLAGS, and ${PROJECT_NAME}_LIBRARIES +# so that compatibility layer is provided automatically. +if(${PROVIDES_EXPORTED_TARGETS}) + # imported targets should be namespaced, so define namespaced alias + add_library(ChimeraTK::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) + + resolveImportedLib(ChimeraTK::${PROJECT_NAME} linkLibs linkFlags libDirs incDirs cxxFlags) + + # printing results will help resolve problems with auto-generated compatibility layer + message(VERBOSE "explicitly provided compatibility layer,") + message(VERBOSE " old libset: ${${PROJECT_NAME}_LIBRARIES}") + message(VERBOSE " old linkflags: ${${PROJECT_NAME}_LINKER_FLAGS}") + message(VERBOSE " old cxxflags: ${${PROJECT_NAME}_CXX_FLAGS}") + message(VERBOSE " old incDirs: ${${PROJECT_NAME}_INCLUDE_DIRS}") + message(VERBOSE " old libDirs: ${${PROJECT_NAME}_LIBRARY_DIRS}") + set(${PROJECT_NAME}_INCLUDE_DIRS "${incDirs}" ) + set(${PROJECT_NAME}_LIBRARY_DIRS "${libDirs}" ) + set(${PROJECT_NAME}_LIBRARIES "${linkLibs}" ) + set(${PROJECT_NAME}_CXX_FLAGS "${cxxFlags}" ) + set(${PROJECT_NAME}_LINKER_FLAGS "${linkFlags}" ) + message(VERBOSE "will be overwritten by automatically generated compatibility layer from cmake-exports,") + message(VERBOSE " new libset: ${${PROJECT_NAME}_LIBRARIES}") + message(VERBOSE " new linkflags: ${${PROJECT_NAME}_LINKER_FLAGS}") + message(VERBOSE " new cxxflags: ${${PROJECT_NAME}_CXX_FLAGS}") + message(VERBOSE " new incDirs: ${${PROJECT_NAME}_INCLUDE_DIRS}") + message(VERBOSE " new libDirs: ${${PROJECT_NAME}_LIBRARY_DIRS}") +endif() + # create variables for standard makefiles and pkgconfig set(${PROJECT_NAME}_CXX_FLAGS_MAKEFILE "${${PROJECT_NAME}_CXX_FLAGS}") string(REPLACE " " ";" LIST "${${PROJECT_NAME}_INCLUDE_DIRS}") foreach(INCLUDE_DIR ${LIST}) - set(${PROJECT_NAME}_CXX_FLAGS_MAKEFILE "${${PROJECT_NAME}_CXX_FLAGS_MAKEFILE} -I${INCLUDE_DIR}") + appendToList(${PROJECT_NAME}_CXX_FLAGS_MAKEFILE "-I${INCLUDE_DIR}") endforeach() -set(${PROJECT_NAME}_LINKER_FLAGS_MAKEFILE "${${PROJECT_NAME}_LINKER_FLAGS} ${${PROJECT_NAME}_LINK_FLAGS}") +# some old code still might call linker flags _LINK_FLAGS, also include that +appendToList(${PROJECT_NAME}_LINKER_FLAGS_MAKEFILE "${${PROJECT_NAME}_LINK_FLAGS}") string(REPLACE " " ";" LIST "${${PROJECT_NAME}_LIBRARY_DIRS}") foreach(LIBRARY_DIR ${LIST}) - set(${PROJECT_NAME}_LINKER_FLAGS_MAKEFILE "${${PROJECT_NAME}_LINKER_FLAGS_MAKEFILE} -L${LIBRARY_DIR}") + appendToList(${PROJECT_NAME}_LINKER_FLAGS_MAKEFILE "-L${LIBRARY_DIR}") endforeach() -string(REPLACE " " ";" LIST "${PROJECT_NAME} ${${PROJECT_NAME}_LIBRARIES}") -foreach(LIBRARY ${LIST}) - if(LIBRARY MATCHES "/") # library name contains slashes: link against the a file path name - set(${PROJECT_NAME}_LINKER_FLAGS_MAKEFILE "${${PROJECT_NAME}_LINKER_FLAGS_MAKEFILE} ${LIBRARY}") - elseif(LIBRARY MATCHES "^-l") # library name does not contain slashes but already the -l option: directly quote it - set(${PROJECT_NAME}_LINKER_FLAGS_MAKEFILE "${${PROJECT_NAME}_LINKER_FLAGS_MAKEFILE} ${LIBRARY}") - elseif(LIBRARY MATCHES "::") # library name is an exported target - we need to resolve it for Makefiles - get_property(lib_loc TARGET ${LIBRARY} PROPERTY LOCATION) - string(APPEND ${PROJECT_NAME}_LINKER_FLAGS_MAKEFILE " ${lib_loc}") - else() # link against library with -l option - set(${PROJECT_NAME}_LINKER_FLAGS_MAKEFILE "${${PROJECT_NAME}_LINKER_FLAGS_MAKEFILE} -l${LIBRARY}") - endif() -endforeach() +if(${PROVIDES_EXPORTED_TARGETS}) + # libraries have already been resolved above, add them to linker flags + appendToList(${PROJECT_NAME}_LINKER_FLAGS_MAKEFILE "${${PROJECT_NAME}_LIBRARIES}") +else() + # recursive resolution of linker flags is necessary, since dependencies could contain imported targets + string(REPLACE " " ";" LIST "${PROJECT_NAME} ${${PROJECT_NAME}_LIBRARIES}") + foreach(LIBRARY ${LIST}) + resolveImportedLib(${LIBRARY} linkLibs linkFlags libDirs incDirs cxxFlags) + + appendToList(${PROJECT_NAME}_CXX_FLAGS_MAKEFILE "${cxxFlags}") + + string(REPLACE " " ";" LIST "${incDirs}") + foreach(INCLUDE_DIR ${LIST}) + appendToList(${PROJECT_NAME}_CXX_FLAGS_MAKEFILE "-I${INCLUDE_DIR}") + endforeach() + + # for some linker flags, it is important that they come before the libs + prependToList(${PROJECT_NAME}_LINKER_FLAGS_MAKEFILE "${linkFlags}") + appendToList(${PROJECT_NAME}_LINKER_FLAGS_MAKEFILE "${linkLibs}") + string(REPLACE " " ";" LIST "${libDirs}") + foreach(LIBRARY_DIR ${LIST}) + appendToList(${PROJECT_NAME}_LINKER_FLAGS_MAKEFILE "-L${LIBRARY_DIR}") + endforeach() + endforeach() +endif() set(${PROJECT_NAME}_PUBLIC_DEPENDENCIES_L "") foreach(DEPENDENCY ${${PROJECT_NAME}_PUBLIC_DEPENDENCIES}) + # we only care about required dependencies: if some lib has an optional dependency and is built against it + # after it has been found, the dependency became mandatory for downstream libs. + # Note, keyword REQUIRED as not according to spec but it works... string(APPEND ${PROJECT_NAME}_PUBLIC_DEPENDENCIES_L "find_package(${DEPENDENCY} REQUIRED)\n") endforeach() if(TARGET ${PROJECT_NAME}) - set(${PROJECT_NAME}_HAS_LIBRARY 1) + # set _HAS_LIBRARY only if we have a true library, interface libraries (introduced for imported targets, + # e.g. header-only library) don't count. + get_target_property(targetLoc ${PROJECT_NAME} TYPE) + if(NOT "INTERFACE_LIBRARY" MATCHES "${targetLoc}") + set(${PROJECT_NAME}_HAS_LIBRARY 1) + endif() else() set(${PROJECT_NAME}_HAS_LIBRARY 0) endif() + # we have nested @-statements, so we have to parse twice: # create the cmake find_package configuration file +set(PACKAGE_INIT "@PACKAGE_INIT@") # replacement handled later, so leave untouched here +cmake_policy(SET CMP0053 NEW) # less warnings about irrelevant stuff in comments configure_file(cmake/PROJECT_NAMEConfig.cmake.in.in "${PROJECT_BINARY_DIR}/cmake/${PROJECT_NAME}Config.cmake.in" @ONLY) -configure_file(${PROJECT_BINARY_DIR}/cmake/${PROJECT_NAME}Config.cmake.in "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" @ONLY) +if(${PROVIDES_EXPORTED_TARGETS}) + # we will configure later +else() + set(PACKAGE_INIT "") # required to avoid parse error + configure_file(${PROJECT_BINARY_DIR}/cmake/${PROJECT_NAME}Config.cmake.in "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" @ONLY) +endif() configure_file(cmake/PROJECT_NAMEConfigVersion.cmake.in.in "${PROJECT_BINARY_DIR}/cmake/${PROJECT_NAME}ConfigVersion.cmake.in" @ONLY) configure_file(${PROJECT_BINARY_DIR}/cmake/${PROJECT_NAME}ConfigVersion.cmake.in "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" @ONLY) @@ -83,19 +276,47 @@ configure_file(${PROJECT_BINARY_DIR}/cmake/${PROJECT_NAME}-config.in "${PROJECT_ configure_file(cmake/PROJECT_NAME.pc.in.in "${PROJECT_BINARY_DIR}/cmake/${PROJECT_NAME}.pc.in" @ONLY) configure_file(${PROJECT_BINARY_DIR}/cmake/${PROJECT_NAME}.pc.in "${PROJECT_BINARY_DIR}/${PROJECT_NAME}.pc" @ONLY) - -# install cmake find_package configuration file -install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" - DESTINATION lib/cmake/${PROJECT_NAME} COMPONENT dev) -install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" - DESTINATION lib/cmake/${PROJECT_NAME} COMPONENT dev) - -# install same cmake configuration file another time into the Modules cmake subdirectory for compatibility reasons -install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" - DESTINATION share/cmake-${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}/Modules RENAME Find${PROJECT_NAME}.cmake COMPONENT dev) - # install script for Makefiles install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config DESTINATION bin COMPONENT dev) # install configuration file for pkgconfig install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}.pc" DESTINATION share/pkgconfig COMPONENT dev) + + +if(${PROVIDES_EXPORTED_TARGETS}) + # imported targets should be namespaced, so define namespaced alias + add_library(ChimeraTK::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) + + # generate and install export file + install(EXPORT ${PROJECT_NAME}Targets + FILE ${PROJECT_NAME}Targets.cmake + NAMESPACE ChimeraTK:: + DESTINATION "lib/cmake/${PROJECT_NAME}" + ) + + include(CMakePackageConfigHelpers) + # create config file + # although @ONLY arg is not supported, this behaves in the same way. + configure_package_config_file("${PROJECT_BINARY_DIR}/cmake/${PROJECT_NAME}Config.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" + INSTALL_DESTINATION "lib/cmake/${PROJECT_NAME}" + ) + + # remove any previously installed share/cmake-xx/Modules/Find.cmake from this project since it does not harmonize with new Config + set(fileToRemove "share/cmake-${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}/Modules/Find${PROJECT_NAME}.cmake") + install(CODE "FILE(REMOVE ${CMAKE_INSTALL_PREFIX}/${fileToRemove})") +else() + # install same cmake configuration file another time into the Modules cmake subdirectory for compatibility reasons + # We do this only if we did not move yet to exported target, since it does not harmonize + install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" + DESTINATION share/cmake-${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}/Modules RENAME Find${PROJECT_NAME}.cmake COMPONENT dev) + +endif() + +# install cmake find_package configuration file +install(FILES + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" + DESTINATION "lib/cmake/${PROJECT_NAME}" + COMPONENT dev +) diff --git a/cmake/format_options.cmake b/cmake/format_options.cmake new file mode 100644 index 00000000..ed97831e --- /dev/null +++ b/cmake/format_options.cmake @@ -0,0 +1,8 @@ + +# function that reformat flags so they become compatible with target_compile_options, target_link_options etc. +function(formatOptionsAsArray outVar inVar) + string(REGEX REPLACE " +" ";" tmpVar "${inVar}") + string(REGEX REPLACE "^;+" "" tmpVar "${tmpVar}") + string(REGEX REPLACE ";+$" "" tmpVar "${tmpVar}") + set(${outVar} "${tmpVar}" PARENT_SCOPE) +endfunction() diff --git a/cmake/set_control_system_adapter.cmake b/cmake/set_control_system_adapter.cmake index a9521695..e95c1a13 100644 --- a/cmake/set_control_system_adapter.cmake +++ b/cmake/set_control_system_adapter.cmake @@ -28,22 +28,22 @@ # Select control system adapter IF(ADAPTER STREQUAL "OPCUA") message("Building against the OPC UA ControlSystemAdater") - add_dependency(ChimeraTK-ControlSystemAdapter-OPCUAAdapter REQUIRED) + add_dependency(ChimeraTK-ControlSystemAdapter-OPCUAAdapter 03.00 REQUIRED) set(Adapter_LINK_FLAGS ${ChimeraTK-ControlSystemAdapter-OPCUAAdapter_LINK_FLAGS}) set(Adapter_LIBRARIES ${ChimeraTK-ControlSystemAdapter-OPCUAAdapter_LIBRARIES}) ELSEIF(ADAPTER STREQUAL "DOOCS") message("Building against the DOOCS ControlSystemAdater") - add_dependency(ChimeraTK-ControlSystemAdapter-DoocsAdapter REQUIRED) + add_dependency(ChimeraTK-ControlSystemAdapter-DoocsAdapter 01.08 REQUIRED) set(Adapter_LINK_FLAGS ${ChimeraTK-ControlSystemAdapter-DoocsAdapter_LINK_FLAGS}) set(Adapter_LIBRARIES ${ChimeraTK-ControlSystemAdapter-DoocsAdapter_LIBRARIES}) ELSEIF(ADAPTER STREQUAL "EPICSIOC") message("Building against the EPICS IOC ControlSystemAdater") - add_dependency(ChimeraTK-ControlSystemAdapter-EPICS-IOC-Adapter REQUIRED) + add_dependency(ChimeraTK-ControlSystemAdapter-EPICS-IOC-Adapter 02.00 REQUIRED) set(Adapter_LINK_FLAGS ${ChimeraTK-ControlSystemAdapter-EPICS-IOC-Adapter_LINK_FLAGS}) set(Adapter_LIBRARIES ${ChimeraTK-ControlSystemAdapter-EPICS-IOC-Adapter_LIBRARIES}) ELSEIF(ADAPTER STREQUAL "EPICS7IOC") message("Building against the EPICS ver. 7.0 IOC ControlSystemAdater") - add_dependency(ChimeraTK-ControlSystemAdapter-EPICS7-IOC-Adapter REQUIRED) + add_dependency(ChimeraTK-ControlSystemAdapter-EPICS7-IOC-Adapter 02.00 REQUIRED) set(Adapter_LINK_FLAGS ${ChimeraTK-ControlSystemAdapter-EPICS7-IOC-Adapter_LINK_FLAGS}) set(Adapter_LIBRARIES ${ChimeraTK-ControlSystemAdapter-EPICS7-IOC-Adapter_LIBRARIES}) ELSE()