Преглед изворни кода

Enable support for writing CTK Plugins in external projects.

Sascha Zelzer пре 14 година
родитељ
комит
9a6381c907

+ 80 - 0
CMake/ctkFunctionGetIncludeDirs.cmake

@@ -0,0 +1,80 @@
+###########################################################################
+#
+#  Library: CTK
+#
+#  Copyright (c) German Cancer Research Center,
+#    Division of Medical and Biological Informatics
+#
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+#
+###########################################################################
+
+FUNCTION(ctkFunctionGetIncludeDirs var_include_dirs)
+
+  IF(NOT ARGN)
+    MESSAGE(FATAL_ERROR "No targets given")
+  ENDIF()
+
+  SET(_include_dirs ${${var_include_dirs}})
+  FOREACH(_target ${ARGN})
+
+    # Add the include directories from the plugin dependencies
+    # The variable ${_target}_DEPENDENCIES is set in the
+    # macro ctkMacroValidateBuildOptions
+
+    SET(ctk_deps )
+    SET(ext_deps )
+
+    ctkMacroGetAllCTKTargetLibraries("${${_target}_DEPENDENCIES}" ctk_deps)
+    ctkMacroGetAllNonCTKTargetLibraries("${${_target}_DEPENDENCIES}" ext_deps)
+
+    FOREACH(dep ${ctk_deps})
+      LIST(APPEND _include_dirs
+           ${${dep}_SOURCE_DIR}
+           ${${dep}_BINARY_DIR}
+           )
+
+      # For external projects, CTKConfig.cmake contains variables
+      # listening the include dirs for CTK libraries and plugins
+      IF(${dep}_INCLUDE_DIRS)
+        LIST(APPEND _include_dirs ${${dep}_INCLUDE_DIRS})
+      ENDIF()
+    ENDFOREACH()
+
+    FOREACH(dep ${ext_deps})
+
+      IF(${dep}_INCLUDE_DIRS)
+        STRING(REPLACE "^" ";" _ext_include_dirs "${${dep}_INCLUDE_DIRS}")
+        LIST(APPEND _include_dirs ${_ext_include_dirs})
+      ENDIF()
+
+      # This is for resolving include dependencies between
+      # libraries / plugins from external projects using CTK
+      IF(${dep}_SOURCE_DIR)
+        LIST(APPEND _include_dirs ${${dep}_SOURCE_DIR})
+      ENDIF()
+
+      IF(${dep}_BINARY_DIR)
+        LIST(APPEND _include_dirs ${${dep}_BINARY_DIR})
+      ENDIF()
+
+    ENDFOREACH()
+
+  ENDFOREACH()
+
+  IF(_include_dirs)
+    LIST(REMOVE_DUPLICATES _include_dirs)
+  ENDIF()
+  SET(${var_include_dirs} ${_include_dirs} PARENT_SCOPE)
+
+ENDFUNCTION()

+ 55 - 0
CMake/ctkFunctionSetupExternalPlugins.cmake

@@ -0,0 +1,55 @@
+###########################################################################
+#
+#  Library: CTK
+#
+#  Copyright (c) German Cancer Research Center,
+#    Division of Medical and Biological Informatics
+#
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+#
+###########################################################################
+
+FUNCTION(ctkFunctionSetupExternalPlugins )
+
+  ctkMacroParseArguments(MY "BUILD_OPTION_PREFIX" "" ${ARGN})
+
+  IF(NOT MY_DEFAULT_ARGS)
+    MESSAGE(FATAL_ERROR "Empty plugin list")
+  ENDIF()
+
+  SET(plugin_list ${MY_DEFAULT_ARGS})
+
+  IF(NOT MY_BUILD_OPTION_PREFIX)
+    SET(MY_BUILD_OPTION_PREFIX "BUILD_")
+  ENDIF()
+
+  SET(plugin_dirswithoption )
+  SET(plugin_subdirs )
+  FOREACH(plugin ${plugin_list})
+    ctkFunctionExtractOptionNameAndValue(${plugin} plugin_name plugin_value)
+    SET(option_name ${MY_BUILD_OPTION_PREFIX}${plugin_name})
+    OPTION(${option_name} "Build ${plugin_name} Plugin." ${plugin_value})
+    LIST(APPEND plugin_subdirs "${plugin_name}")
+    LIST(APPEND plugin_dirswithoption "${CMAKE_CURRENT_SOURCE_DIR}/${plugin_name}^^${option_name}")
+  ENDFOREACH()
+
+  ctkFunctionGenerateDGraphInput(${CMAKE_CURRENT_BINARY_DIR} "${plugin_dirswithoption}" WITH_EXTERNALS)
+  ctkMacroValidateBuildOptions("${CMAKE_CURRENT_BINARY_DIR}" "${CTK_DGRAPH_EXECUTABLE}" "${plugin_dirswithoption}")
+
+  FOREACH(plugin ${plugin_subdirs})
+    IF(BUILD_${plugin})
+      ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/${plugin})
+    ENDIF()
+  ENDFOREACH()
+
+ENDFUNCTION()

+ 1 - 20
CMake/ctkMacroBuildApp.cmake

@@ -63,26 +63,7 @@ MACRO(ctkMacroBuildApp)
     )  
 
   # Add the include directories from the library dependencies
-  # The variable ${lib_name}_DEPENDENCIES is set in the
-  # macro ctkMacroValidateBuildOptions
-  SET(ctk_deps )
-  SET(ext_deps )
-  ctkMacroGetAllCTKTargetLibraries("${${proj_name}_DEPENDENCIES}" ctk_deps)
-  ctkMacroGetAllNonCTKTargetLibraries("${${proj_name}_DEPENDENCIES}" ext_deps)
-
-  FOREACH(dep ${ctk_deps})
-    LIST(APPEND my_includes
-         ${${dep}_SOURCE_DIR}
-         ${${dep}_BINARY_DIR}
-         )
-  ENDFOREACH()
-
-  FOREACH(dep ${ext_deps})
-    STRING(REPLACE "^" ";" _include_dirs "${${dep}_INCLUDE_DIRS}")
-    LIST(APPEND my_includes ${_include_dirs})
-  ENDFOREACH()
-
-  LIST(REMOVE_DUPLICATES my_includes)
+  ctkFunctionGetIncludeDirs(my_includes ${proj_name})
 
   INCLUDE_DIRECTORIES(${my_includes})
 

+ 1 - 20
CMake/ctkMacroBuildLib.cmake

@@ -59,26 +59,7 @@ MACRO(ctkMacroBuildLib)
     )  
 
   # Add the include directories from the library dependencies
-  # The variable ${lib_name}_DEPENDENCIES is set in the
-  # macro ctkMacroValidateBuildOptions
-  SET(ctk_deps )
-  SET(ext_deps )
-  ctkMacroGetAllCTKTargetLibraries("${${lib_name}_DEPENDENCIES}" ctk_deps)
-  ctkMacroGetAllNonCTKTargetLibraries("${${lib_name}_DEPENDENCIES}" ext_deps)
-
-  FOREACH(dep ${ctk_deps})
-    LIST(APPEND my_includes
-         ${${dep}_SOURCE_DIR}
-         ${${dep}_BINARY_DIR}
-         )
-  ENDFOREACH()
-
-  FOREACH(dep ${ext_deps})
-    STRING(REPLACE "^" ";" _include_dirs "${${dep}_INCLUDE_DIRS}")
-    LIST(APPEND my_includes ${_include_dirs})
-  ENDFOREACH()
-
-  LIST(REMOVE_DUPLICATES my_includes)
+  ctkFunctionGetIncludeDirs(my_includes ${lib_name})
 
   INCLUDE_DIRECTORIES(
     ${my_includes}

+ 21 - 25
CMake/ctkMacroBuildPlugin.cmake

@@ -96,26 +96,8 @@ MACRO(ctkMacroBuildPlugin)
     )
 
   # Add the include directories from the plugin dependencies
-  # The variable ${lib_name}_DEPENDENCIES is set in the
-  # macro ctkMacroValidateBuildOptions
-  SET(ctk_deps )
-  SET(ext_deps )
-  ctkMacroGetAllCTKTargetLibraries("${${lib_name}_DEPENDENCIES}" ctk_deps)
-  ctkMacroGetAllNonCTKTargetLibraries("${${lib_name}_DEPENDENCIES}" ext_deps)
-
-  FOREACH(dep ${ctk_deps})
-    LIST(APPEND my_includes
-         ${${dep}_SOURCE_DIR}
-         ${${dep}_BINARY_DIR}
-         )
-  ENDFOREACH()
-
-  FOREACH(dep ${ext_deps})
-    STRING(REPLACE "^" ";" _include_dirs "${${dep}_INCLUDE_DIRS}")
-    LIST(APPEND my_includes ${_include_dirs})
-  ENDFOREACH()
-
-  LIST(REMOVE_DUPLICATES my_includes)
+  # and external dependencies
+  ctkFunctionGetIncludeDirs(my_includes ${lib_name})
 
   INCLUDE_DIRECTORIES(
     ${my_includes}
@@ -126,7 +108,7 @@ MACRO(ctkMacroBuildPlugin)
   SET(MY_LIBNAME ${lib_name})
   
   CONFIGURE_FILE(
-    ${CTK_SOURCE_DIR}/Libs/ctkExport.h.in
+    ${CTK_EXPORT_HEADER_TEMPLATE}
     ${CMAKE_CURRENT_BINARY_DIR}/${MY_EXPORT_HEADER_PREFIX}Export.h
     )
   SET(dynamicHeaders
@@ -195,11 +177,20 @@ MACRO(ctkMacroBuildPlugin)
     ${MY_QRC_SRCS}
     )
 
-  SET(runtime_output_dir "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/plugins")
-  SET(library_output_dir "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/plugins")
+  # Set the output directory for the plugin
+  SET(output_dir_suffix "plugins")
   IF(MY_TEST_PLUGIN)
-    SET(runtime_output_dir "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_plugins")
-    SET(library_output_dir "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/test_plugins")
+    SET(output_dir_suffix "test_plugins")
+  ENDIF()
+  IF(CMAKE_RUNTIME_OUTPUT_DIRECTORY)
+    SET(runtime_output_dir "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${output_dir_suffix}")
+  ELSE()
+    SET(runtime_output_dir "${CMAKE_CURRENT_BINARY_DIR}/${output_dir_suffix}")
+  ENDIF()
+  IF(CMAKE_LIBRARY_OUTPUT_DIRECTORY)
+    SET(library_output_dir "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${output_dir_suffix}")
+  ELSE()
+    SET(library_output_dir "${CMAKE_CURRENT_BINARY_DIR}/${output_dir_suffix}")
   ENDIF()
 
   # Apply properties to the library target.
@@ -228,6 +219,11 @@ MACRO(ctkMacroBuildPlugin)
   ENDIF()
 
   TARGET_LINK_LIBRARIES(${lib_name} ${my_libs})
+
+  # Update CTK_PLUGINS
+  IF(NOT MY_TEST_PLUGIN)
+    SET(CTK_PLUGIN_LIBRARIES ${CTK_PLUGIN_LIBRARIES} ${lib_name} CACHE INTERNAL "CTK plugins" FORCE)
+  ENDIF()
   
   # Install headers
   #FILE(GLOB headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h")

+ 32 - 8
CMake/ctkMacroValidateBuildOptions.cmake

@@ -49,6 +49,7 @@ MACRO(ctkMacroValidateBuildOptions dir executable target_directories)
     MESSAGE(FATAL_ERROR "Executable ${executable} doesn't exist!")
   ENDIF()
 
+  SET(known_targets)
   SET(target_directories_with_target_name)
   
   # Create target_directories_with_target_name
@@ -82,8 +83,21 @@ MACRO(ctkMacroValidateBuildOptions dir executable target_directories)
     LIST(APPEND target_directories_with_target_name
       ${target_dir}^^${option_name}^^${target_project_name}
       )
+
+    LIST(APPEND known_targets ${target_project_name})
   ENDFOREACH()
 
+  # This is for external projects using CTK
+  # The variables CTK_PLUGIN_LIBRARIES and CTK_LIBRARIES are set in CTKConfig.cmake
+  IF(CTK_PLUGIN_LIBRARIES)
+    LIST(APPEND known_targets ${CTK_PLUGIN_LIBRARIES})
+  ENDIF()
+  IF(CTK_LIBRARIES)
+    LIST(APPEND known_targets ${CTK_LIBRARIES})
+  ENDIF()
+
+  #MESSAGE("Known targets: ${known_targets}")
+
   SET(EXTERNAL_TARGETS ) # This is used in CMakeLists.txt
   FOREACH(target_info ${target_directories_with_target_name})
 
@@ -116,8 +130,8 @@ MACRO(ctkMacroValidateBuildOptions dir executable target_directories)
       # Obtain dependency path
       ctkMacroSetPaths("${QT_INSTALLED_LIBRARY_DIR}")
       EXECUTE_PROCESS(
-        COMMAND "${executable}" "${CTK_BINARY_DIR}/DGraphInput-alldep-withext.txt" -sort ${target_project_name}
-        WORKING_DIRECTORY ${CTK_BINARY_DIR}
+        COMMAND "${executable}" "${dir}/DGraphInput-alldep-withext.txt" -sort ${target_project_name}
+        WORKING_DIRECTORY ${dir}
         RESULT_VARIABLE RESULT_VAR
         OUTPUT_VARIABLE dep_path
         ERROR_VARIABLE error
@@ -140,19 +154,29 @@ MACRO(ctkMacroValidateBuildOptions dir executable target_directories)
 
       #MESSAGE("path for ${target_project_name} is: ${dep_path_list}")
 
-      # Check if all CTK targets included in the dependency path are enabled
-      SET(ctk_dep_path_list )
+      # Check if all internal CTK targets included in the dependency path are enabled
+      SET(int_dep_path_list )
       SET(ext_dep_path_list ${dep_path_list})
-      ctkMacroGetAllCTKTargetLibraries("${dep_path_list}" ctk_dep_path_list)
-      IF(ctk_dep_path_list)
-        LIST(REMOVE_ITEM ext_dep_path_list ${ctk_dep_path_list})
+      # Allow external projects to override the set of internal targets
+      IF(COMMAND GetMyTargetLibraries)
+        GetMyTargetLibraries("${dep_path_list}" int_dep_path_list)
+      ELSE()
+        ctkMacroGetAllCTKTargetLibraries("${dep_path_list}" int_dep_path_list)
+      ENDIF()
+      IF(int_dep_path_list)
+        LIST(REMOVE_ITEM ext_dep_path_list ${int_dep_path_list})
       ENDIF()
 
       IF(ext_dep_path_list)
         LIST(APPEND EXTERNAL_TARGETS ${ext_dep_path_list})
       ENDIF()
 
-      FOREACH(dep ${ctk_dep_path_list})
+      FOREACH(dep ${int_dep_path_list})
+        LIST(FIND known_targets ${dep} dep_found)
+        IF(dep_found LESS 0)
+          MESSAGE(FATAL_ERROR "${target_project_name} depends on ${dep}, which does not exist")
+        ENDIF()
+
         ctkMacroGetOptionName("${target_directories_with_target_name}" ${dep} dep_option)
         IF(NOT ${${dep_option}})
           # Enable option

+ 8 - 0
CMakeLists.txt

@@ -131,6 +131,7 @@ SET(CTK_WRAPPED_LIBRARIES_PYTHONQT CACHE INTERNAL "CTK libraries wrapped using P
 
 # Variable use in CTKConfig.cmake.in
 SET(CTK_LIBRARIES CACHE INTERNAL "CTK libraries" FORCE)
+SET(CTK_PLUGIN_LIBRARIES CACHE INTERNAL "CTK plugins" FORCE)
 
 #-----------------------------------------------------------------------------
 # CMake Function(s) and Macro(s)
@@ -154,6 +155,7 @@ INCLUDE(CMake/ctkFunctionGenerateProjectXml.cmake)
 INCLUDE(CMake/ctkFunctionGeneratePluginManifest.cmake)
 INCLUDE(CMake/ctkMacroGeneratePluginResourceFile.cmake)
 INCLUDE(CMake/ctkFunctionCheckCompilerFlags.cmake)
+INCLUDE(CMake/ctkFunctionGetIncludeDirs.cmake)
 
 # Used by CTKGenerateCTKConfig.cmake
 SET(CTK_CMAKE_DIR ${CTK_SOURCE_DIR}/CMake)
@@ -563,6 +565,12 @@ SET(CMAKE_CXX_FLAGS ${CTK_CXX_FLAGS} CACHE STRING "CMake C Flags" FORCE)
 SET(CMAKE_C_FLAGS ${CTK_C_FLAGS} CACHE STRING "CMake CXX Flags" FORCE)
 
 #-----------------------------------------------------------------------------
+# Set the header template which defines custom export/import macros
+# for shared libraries
+#
+SET(CTK_EXPORT_HEADER_TEMPLATE "${CTK_SOURCE_DIR}/Libs/ctkExport.h.in")
+
+#-----------------------------------------------------------------------------
 # Add CTK library subdirectories
 #
 FOREACH(lib ${CTK_LIBS_SUBDIRS})

+ 28 - 0
CTKConfig.cmake.in

@@ -40,14 +40,42 @@
 # to load CTK's settings for an external project.
 
 
+# Import CTK targets
+INCLUDE(@CTK_SUPERBUILD_BINARY_DIR@/CTKExports.cmake)
+
+# Include CTK macros
+INCLUDE(@CTK_CMAKE_DIR_CONFIG@/ctkMacroParseArguments.cmake)
+INCLUDE(@CTK_CMAKE_DIR_CONFIG@/ctkMacroSetPaths.cmake)
+INCLUDE(@CTK_CMAKE_DIR_CONFIG@/ctkMacroListFilter.cmake)
+INCLUDE(@CTK_CMAKE_DIR_CONFIG@/ctkMacroBuildPlugin.cmake)
+INCLUDE(@CTK_CMAKE_DIR_CONFIG@/ctkMacroTargetLibraries.cmake) # Import multiple macros
+INCLUDE(@CTK_CMAKE_DIR_CONFIG@/ctkFunctionExtractOptionNameAndValue.cmake)
+INCLUDE(@CTK_CMAKE_DIR_CONFIG@/ctkMacroValidateBuildOptions.cmake)
+INCLUDE(@CTK_CMAKE_DIR_CONFIG@/ctkFunctionGenerateDGraphInput.cmake)
+INCLUDE(@CTK_CMAKE_DIR_CONFIG@/ctkFunctionGeneratePluginManifest.cmake)
+INCLUDE(@CTK_CMAKE_DIR_CONFIG@/ctkMacroGeneratePluginResourceFile.cmake)
+INCLUDE(@CTK_CMAKE_DIR_CONFIG@/ctkFunctionGetIncludeDirs.cmake)
+INCLUDE(@CTK_CMAKE_DIR_CONFIG@/ctkFunctionSetupExternalPlugins.cmake)
+
+SET(CTK_EXPORT_HEADER_TEMPLATE @CTK_EXPORT_HEADER_TEMPLATE@)
+
+# The CTK DGraph executable used to compute target dependency graphs
+SET(CTK_DGRAPH_EXECUTABLE @DGraph_EXECUTABLE@)
+
 # List all libraries
 SET(CTK_LIBRARIES @CTK_LIBRARIES@)
 
+# List all plugins
+SET(CTK_PLUGIN_LIBRARIES @CTK_PLUGIN_LIBRARIES@)
+
 # List all CTK libraries wrapped with PythonQt
 SET(CTK_WRAPPED_LIBRARIES_PYTHONQT @CTK_WRAPPED_LIBRARIES_PYTHONQT@)
 
 @CTK_CONFIG_INSTALL_ONLY@
 
+# Plugin specific include directories
+@CTK_PLUGIN_INCLUDE_DIRS_CONFIG@
+
 # The CTK include file directories.
 SET(CTK_INCLUDE_DIRS "@CTK_INCLUDE_DIRS_CONFIG@")
  

+ 1 - 1
UseCTK.cmake.in

@@ -31,6 +31,6 @@ IF(NOT CTK_USE_FILE_INCLUDED)
   INCLUDE_DIRECTORIES(${CTK_INCLUDE_DIRS})
  
   # Add link directories needed to use CTK.
-  LINK_DIRECTORIES(${CTK_LIBRARY_DIRS} ${CTK_EXTERNAL_LIBRARY_DIRS})
+  # LINK_DIRECTORIES(${CTK_LIBRARY_DIRS} ${CTK_EXTERNAL_LIBRARY_DIRS})
  
 ENDIF()

+ 13 - 0
Utilities/LastConfigureStep/CTKGenerateCTKConfig.cmake

@@ -64,6 +64,19 @@ SET(CTK_CONFIG_INSTALL_ONLY)
 # The "use" file.
 SET(CTK_USE_FILE ${CTK_SUPERBUILD_BINARY_DIR}/UseCTK.cmake)
 
+# Export targets so they can be imported by a project using CTK
+# as an external library
+EXPORT(TARGETS ${CTK_LIBRARIES} ${CTK_PLUGIN_LIBRARIES} FILE ${CTK_SUPERBUILD_BINARY_DIR}/CTKExports.cmake)
+
+# Write a set of variables containing plugin specific include directories
+SET(CTK_PLUGIN_INCLUDE_DIRS_CONFIG)
+FOREACH(plugin ${CTK_PLUGIN_LIBRARIES})
+  SET(${plugin}_INCLUDE_DIRS ${${plugin}_SOURCE_DIR} ${${plugin}_BINARY_DIR})
+  ctkFunctionGetIncludeDirs(${plugin}_INCLUDE_DIRS ${plugin})
+  SET(CTK_PLUGIN_INCLUDE_DIRS_CONFIG "${CTK_PLUGIN_INCLUDE_DIRS_CONFIG}
+SET(${plugin}_INCLUDE_DIRS \"${${plugin}_INCLUDE_DIRS}\")")
+ENDFOREACH()
+
 # Determine the include directories needed.
 SET(CTK_INCLUDE_DIRS_CONFIG
   ${CTK_BASE_INCLUDE_DIRS}