]> Creatis software - cpPlugins.git/blobdiff - cmake/cpPlugins_Functions.cmake
Build procedure simplified
[cpPlugins.git] / cmake / cpPlugins_Functions.cmake
index 4337bd9f670347c4e54806604d85552d99e038b4..45d75528add1ed2bd4fff0184bf41fc780dde292 100644 (file)
 
+## ==============================
+## == Macro to normalize paths ==
+## ==============================
+
+FUNCTION(cpPlugins_NormalizePaths output_files)
+SET(_out)
+FOREACH(_f ${ARGN})
+  SET(_d)
+  FILE(TO_CMAKE_PATH ${_f} _d)
+  LIST(APPEND _out ${_d})
+ENDFOREACH(_f)
+SET(${output_files} "${_out}" PARENT_SCOPE)
+ENDFUNCTION()
+
+## ==========================
+## == Macro to wrap qt-uis ==
+## ==========================
+
+FUNCTION(cpPlugins_Wrap_Qt_ui output_files)
+cpPlugins_NormalizePaths(_source_dir ${PROJECT_SOURCE_DIR})
+cpPlugins_NormalizePaths(_binary_dir ${PROJECT_BINARY_DIR})
+SET(_out)
+FOREACH(_f ${ARGN})
+  IF(EXISTS ${_f})
+    GET_FILENAME_COMPONENT(_name ${_f} NAME_WE)
+    GET_FILENAME_COMPONENT(_dir ${_f} DIRECTORY)
+    SET(_base_dir ${_source_dir})
+    STRING(FIND "${_dir}" "${_base_dir}" _pos)
+    IF(${_pos} EQUAL -1)
+      SET(_base_dir ${_binary_dir})
+      STRING(FIND "${_dir}" "${_base_dir}" _pos)
+    ENDIF(${_pos} EQUAL -1)
+    IF(NOT ${_pos} EQUAL -1)
+      STRING(REPLACE "${_base_dir}/" "" _dir ${_dir})
+      SET(_out_f ${_binary_dir}/${_dir}/ui_${_name}.h)
+      LIST(APPEND _out ${_out_f})
+      ADD_CUSTOM_COMMAND(
+        OUTPUT ${_out_f}
+        COMMAND Qt4::uic
+        ARGS -o ${_out_f} ${_f}
+        MAIN_DEPENDENCY ${_f} VERBATIM
+        )
+    ENDIF(NOT ${_pos} EQUAL -1)
+  ENDIF(EXISTS ${_f})
+ENDFOREACH(_f)
+SET(${output_files} "${_out}" PARENT_SCOPE)
+ENDFUNCTION()
+
+## ==========================
+## == Macro to wrap qt-moc ==
+## ==========================
+
+FUNCTION(cpPlugins_Wrap_Qt_cpp output_files)
+SET(_out)
+FOREACH(_f ${ARGN})
+  IF(EXISTS ${_f})
+    FILE(READ ${_f} _txt)
+    STRING(FIND "${_txt}" "Q_OBJECT" _pos)
+    IF(NOT ${_pos} EQUAL -1)
+      SET(_s)
+      QT4_WRAP_CPP(_s ${_f})
+      SET(_out ${_out} ${_s})
+    ENDIF(NOT ${_pos} EQUAL -1)
+  ENDIF(EXISTS ${_f})
+ENDFOREACH(_f)
+SET(${output_files} "${_out}" PARENT_SCOPE)
+ENDFUNCTION()
+
 ## =================================
 ## == Function to build a library ==
 ## =================================
 
-FUNCTION(cpPlugins_ManageLibrary library_name type sources headers qt_files version short_version)
+FUNCTION(
+  cpPlugins_CreateLibrary
+  lib_name
+  lib_type
+  lib_source_files
+  lib_header_files
+  lib_qt_ui_files
+  lib_version
+  lib_short_version
+  )
 
-## -- Configure some simple values
-SET(_all_sources ${sources})
-SET(_all_headers ${headers})
+## -- Configure inputs to be cmake-path compatible
+cpPlugins_NormalizePaths(_sources ${lib_source_files})
+cpPlugins_NormalizePaths(_headers ${lib_header_files})
+cpPlugins_NormalizePaths(_qt_uis ${lib_qt_ui_files})
 
-## -- Guess what headers sould be qt-moc'ed
+# -- Prepare Qt4-based code
 IF(Qt4_FOUND)
-  FOREACH(_h ${headers})
-    FILE(READ ${_h} _txt)
-    STRING(FIND "${_txt}" "Q_OBJECT" _r)
-    IF(NOT ${_r} EQUAL -1)
-      SET(_s)
-      QT4_WRAP_CPP(_s ${_h})
-      SET(_all_sources ${_all_sources} ${_s})
-    ENDIF(NOT ${_r} EQUAL -1)
-  ENDFOREACH(_h)
-ENDIF(Qt4_FOUND)
 
-## -- Guess what qt-ui's sould be qt-uic'ed
-## -- Wrap qt-ui headers: this is equivalent to QT4_WRAP_UI except to change the
-## -- output file
-IF(Qt4_FOUND)
-  FOREACH(_ui ${qt_files})
-    SET(_base_dir ${CMAKE_CURRENT_SOURCE_DIR})
-    STRING(FIND "${_ui}" "${_base_dir}" _pos)
-    IF(${_pos} EQUAL -1)
-      SET(_base_dir ${CMAKE_CURRENT_BINARY_DIR})
-      STRING(FIND "${_ui}" "${_base_dir}" _pos)
-    ENDIF(${_pos} EQUAL -1)
-    SET(_relative_dir)
-    IF(NOT ${_pos} EQUAL -1)
-      FILE(TO_CMAKE_PATH ${_base_dir} _base_cmake_dir)
-      FILE(TO_CMAKE_PATH ${_ui} _ui_dir)
-      STRING(REPLACE "${_base_cmake_dir}/" "" _relative_dir ${_ui_dir})
-    ENDIF(NOT ${_pos} EQUAL -1)
-    GET_FILENAME_COMPONENT(_ui_name ${_ui} NAME_WE)
-    STRING(FIND "${_relative_dir}" "/" _pos REVERSE)
-    STRING(SUBSTRING "${_relative_dir}" 0 ${_pos} _o)
-    SET(_o_name ${CMAKE_CURRENT_BINARY_DIR}/${_o}/ui_${_ui_name}.h)
-    ADD_CUSTOM_COMMAND(
-      OUTPUT ${_o_name}
-      COMMAND Qt4::uic
-      ARGS -o ${_o_name} ${_ui}
-      MAIN_DEPENDENCY ${_ui} VERBATIM
-      )
-    SET(_all_sources ${_all_sources} ${_o_name})
-  ENDFOREACH(_ui)
+  ## -- Guess what headers sould be qt-moc'ed
+  cpPlugins_Wrap_Qt_cpp(_qt_moc_sources ${_headers})
+  IF(_qt_moc_sources)
+    SET(_sources ${_sources} ${_qt_moc_sources})
+  ENDIF(_qt_moc_sources)
+
+  ## -- Guess what qt-ui's sould be qt-uic'ed
+  ## -- Wrap qt-ui headers: this is equivalent to QT4_WRAP_UI except to change the
+  ## -- output file
+  cpPlugins_Wrap_Qt_ui(_qt_ui_headers ${_qt_uis})
+  IF(_qt_ui_headers)
+    SET(_headers ${_headers} ${_qt_ui_headers})
+    SET(_sources ${_sources} ${_qt_ui_headers})
+  ENDIF(_qt_ui_headers)
 ENDIF(Qt4_FOUND)
 
 ## -- Ok, compile library
-IF(_all_sources)
-
-  ## -- Try to guess the binary directory
-  SET(_relative_dir)
-  FOREACH(_s ${_all_sources})
-    GET_FILENAME_COMPONENT(_d ${_s} DIRECTORY)
-    SET(_base_dir ${CMAKE_CURRENT_SOURCE_DIR})
-    STRING(FIND "${_d}" "${_base_dir}" _pos)
-    IF(${_pos} EQUAL -1)
-      SET(_base_dir ${CMAKE_CURRENT_BINARY_DIR})
-      STRING(FIND "${_d}" "${_base_dir}" _pos)
-    ENDIF(${_pos} EQUAL -1)
-    IF(NOT ${_pos} EQUAL -1)
-      FILE(TO_CMAKE_PATH ${_base_dir} _base_cmake_dir)
-      FILE(TO_CMAKE_PATH ${_d} _d_dir)
-      STRING(REPLACE "${_base_cmake_dir}/" "" _almost_relative_dir ${_d_dir})
-      STRING(FIND "${_almost_relative_dir}" "/" _pos)
-      IF(NOT ${_pos} EQUAL -1)
-        STRING(SUBSTRING ${_almost_relative_dir} 0 ${_pos} _relative_dir)
-      ELSE(NOT ${_pos} EQUAL -1)
-        SET(_relative_dir ${_almost_relative_dir})
-      ENDIF(NOT ${_pos} EQUAL -1)
-      BREAK()
-    ENDIF(NOT ${_pos} EQUAL -1)
-  ENDFOREACH(_s)
-  SET(_cur_binary_dir "${CMAKE_CURRENT_BINARY_DIR}/${_relative_dir}")
-
-  ADD_LIBRARY(${library_name} SHARED ${_all_sources})
+IF(_sources)
+  cpPlugins_NormalizePaths(_cur_binary_dir ${CMAKE_CURRENT_BINARY_DIR})
+  ADD_LIBRARY(${lib_name} SHARED ${_sources} ${_headers})
   SET_TARGET_PROPERTIES(
-    ${library_name} PROPERTIES
-    VERSION "${version}"
-    SOVERSION "${short_version}"
+    ${lib_name}
+    PROPERTIES
+    VERSION "${lib_version}"
+    SOVERSION "${lib_short_version}"
     )
   GENERATE_EXPORT_HEADER(
-    ${library_name}
-    BASE_NAME ${library_name}
-    EXPORT_MACRO_NAME ${library_name}_EXPORT
-    EXPORT_FILE_NAME ${_cur_binary_dir}/${library_name}_Export.h
-    STATIC_DEFINE ${library_name}_BUILT_AS_STATIC
+    ${lib_name}
+    BASE_NAME ${lib_name}
+    EXPORT_MACRO_NAME ${lib_name}_EXPORT
+    EXPORT_FILE_NAME ${_cur_binary_dir}/${lib_name}_Export.h
+    STATIC_DEFINE ${lib_name}_BUILT_AS_STATIC
     )
-  TARGET_LINK_LIBRARIES(${library_name} ${ARGN})
-  SET(${library_name}_LIB ${library_name} CACHE INTERNAL "Library ${name}")
-ENDIF(_all_sources)
+  SET(${lib_name}_LIB ${lib_name} CACHE INTERNAL "Library ${lib_name}")
+ENDIF(_sources)
 
 ENDFUNCTION()
 
@@ -104,67 +132,92 @@ ENDFUNCTION()
 ## == Function to build a library from a directory ==
 ## ==================================================
 
-FUNCTION(cpPlugins_CreateLibraryFromDirectory library_name type source_dir binary_dir version short_version)
+FUNCTION(
+  cpPlugins_CreateLibraryFromDirectory
+  lib_name
+  lib_type
+  lib_source_dir
+  lib_version
+  lib_short_version
+  )
 
-## -- Some useful variables
-SET(_all_sources_extensions c cpp cxx)
-SET(_all_headers_extensions h hpp hxx)
-SET(_all_qt_ui_extensions ui)
-SET(_all_dirs ${source_dir} ${binary_dir})
-SET(_all_sources)
-SET(_all_headers)
-SET(_all_qt_ui)
+## -- Configure inputs to be cmake-path compatible
+cpPlugins_NormalizePaths(_global_source_dir ${PROJECT_SOURCE_DIR})
+cpPlugins_NormalizePaths(_global_binary_dir ${PROJECT_BINARY_DIR})
+cpPlugins_NormalizePaths(_source_dir ${lib_source_dir})
+STRING(REPLACE "${_global_source_dir}" "" _local_source_dir ${_source_dir})
+SET(_binary_dir ${_global_binary_dir}${_local_source_dir})
 
-## -- Configure some files
-FILE(GLOB_RECURSE _all_configs "${source_dir}/*.in")
-FOREACH(_c ${_all_configs})
-  SET(_base_dir ${CMAKE_CURRENT_SOURCE_DIR})
-  STRING(FIND "${_c}" "${_base_dir}" _pos)
-  IF(${_pos} EQUAL -1)
-    SET(_base_dir ${CMAKE_CURRENT_BINARY_DIR})
-    STRING(FIND "${_c}" "${_base_dir}" _pos)
-  ENDIF(${_pos} EQUAL -1)
-  SET(_relative_dir)
-  IF(NOT ${_pos} EQUAL -1)
-    FILE(TO_CMAKE_PATH ${_base_dir} _base_cmake_dir)
-    FILE(TO_CMAKE_PATH ${_c} _c_dir)
-    STRING(REPLACE "${_base_cmake_dir}/" "" _almost_relative_dir ${_c_dir})
-    STRING(FIND "${_almost_relative_dir}" "/" _pos)
-    SET(_relative_dir ${_almost_relative_dir})
-    IF(NOT ${_pos} EQUAL -1)
-      STRING(SUBSTRING ${_almost_relative_dir} 0 ${_pos} _relative_dir)
-    ENDIF(NOT ${_pos} EQUAL -1)
-  ENDIF(NOT ${_pos} EQUAL -1)
-  GET_FILENAME_COMPONENT(_c_name ${_c} NAME)
-  STRING(REGEX REPLACE ".in" "" _o_name ${_c_name})
-  CONFIGURE_FILE(
-    ${_c} ${CMAKE_CURRENT_BINARY_DIR}/${_relative_dir}/${_o_name} @ONLY
-    )
-  SET(_all_headers ${_all_headers} ${CMAKE_CURRENT_BINARY_DIR}/${_relative_dir}/${_o_name})
-ENDFOREACH(_c)
+## -- Some useful variables
+SET(_sources_extensions .c .cpp .cxx)
+SET(_headers_extensions .h .hpp .hxx)
+SET(_qt_ui_extensions .ui)
+SET(_dirs ${_source_dir} ${_binary_dir})
+SET(_sources)
+SET(_headers)
+SET(_qt_uis)
 
 ## -- Glob source code
-FOREACH(_d ${_all_dirs})
-  FOREACH(_e ${_all_sources_extensions})
-    FILE(GLOB_RECURSE _f "${_d}/*.${_e}")
-    SET(_all_sources ${_all_sources} ${_f})
+FOREACH(_d ${_dirs})
+  FOREACH(_e ${_sources_extensions})
+    FILE(GLOB_RECURSE _f "${_d}/*${_e}")
+    SET(_sources ${_sources} ${_f})
   ENDFOREACH(_e)
-  FOREACH(_e ${_all_headers_extensions})
-    FILE(GLOB_RECURSE _f "${_d}/*.${_e}")
-    SET(_all_headers ${_all_headers} ${_f})
+  FOREACH(_e ${_headers_extensions})
+    FILE(GLOB_RECURSE _f "${_d}/*${_e}")
+    SET(_headers ${_headers} ${_f})
   ENDFOREACH(_e)
-  FOREACH(_e ${_all_qt_ui_extensions})
-    FILE(GLOB_RECURSE _f "${_d}/*.${_e}")
-    SET(_all_qt_ui ${_all_qt_ui} ${_f})
+  FOREACH(_e ${_qt_ui_extensions})
+    FILE(GLOB_RECURSE _f "${_d}/*${_e}")
+    SET(_qt_uis ${_qt_uis} ${_f})
   ENDFOREACH(_e)
 ENDFOREACH(_d)
 
+## -- Configure some files
+FILE(GLOB_RECURSE _configs "${_source_dir}/*.in")
+FOREACH(_c ${_configs})
+
+  ## -- Build input and output names
+  cpPlugins_NormalizePaths(_input_file ${_c})
+  GET_FILENAME_COMPONENT(_input_name ${_input_file} NAME)
+  GET_FILENAME_COMPONENT(_input_dir ${_input_file} DIRECTORY)
+  STRING(REPLACE ".in" "" _output_name ${_input_name})
+  STRING(REPLACE "${_global_source_dir}" "" _output_dir ${_input_dir})
+  SET(_output_file "${_global_binary_dir}${_output_dir}/${_output_name}")
+
+  ## -- Configure file
+  CONFIGURE_FILE(${_input_file} ${_output_file} @ONLY)
+
+  ## -- Add it to the correct list
+  GET_FILENAME_COMPONENT(_output_ext ${_output_name} EXT)
+  IF(
+      "${_output_ext}" STREQUAL ".h"
+      OR
+      "${_output_ext}" STREQUAL ".hpp"
+      OR
+      "${_output_ext}" STREQUAL ".hxx"
+      )
+    SET(_headers ${_headers})
+  ENDIF()
+  IF(
+      "${_output_ext}" STREQUAL ".c"
+      OR
+      "${_output_ext}" STREQUAL ".cpp"
+      OR
+      "${_output_ext}" STREQUAL ".cxx"
+      )
+    SET(_sources ${_sources})
+  ENDIF()
+  IF("${_output_ext}" STREQUAL ".ui")
+    SET(_qt_uis ${_qt_uis})
+  ENDIF()
+ENDFOREACH(_c)
+
 ## -- Create library
-cpPlugins_ManageLibrary(
-  ${library_name} ${type}
-  "${_all_sources}" "${_all_headers}" "${_all_qt_ui}"
-  "${version}" "${short_version}"
-  ${ARGN}
+cpPlugins_CreateLibrary(
+  ${lib_name} ${lib_type}
+  "${_sources}" "${_headers}" "${_qt_uis}"
+  "${lib_version}" "${lib_short_version}"
   )
 
 ENDFUNCTION()
@@ -173,35 +226,48 @@ ENDFUNCTION()
 ## == Function to wrap instances ==
 ## ================================
 
-FUNCTION(cpPlugins_WrapInstances def_file prefix version short_version)
+FUNCTION(
+  cpPlugins_WrapInstances
+  out_lib_name
+  def_file
+  prefix
+  version
+  short_version
+  )
 
-## -- Configure some simple values
-SET(_def_canonical_file "${CMAKE_CURRENT_SOURCE_DIR}/${def_file}.i")
-SET(_header_file        "${CMAKE_CURRENT_BINARY_DIR}/${prefix}${def_file}.h")
-SET(_code_file          "${CMAKE_CURRENT_BINARY_DIR}/${prefix}${def_file}.cxx")
-SET(_extra_code_file    "${CMAKE_CURRENT_SOURCE_DIR}/${def_file}_extra.cxx")
-SET(_library_name       "${prefix}${def_file}")
+## -- Configure inputs to be cmake-path compatible
+cpPlugins_NormalizePaths(_def_file ${def_file})
+GET_FILENAME_COMPONENT(_def_name ${_def_file} NAME_WE)
+GET_FILENAME_COMPONENT(_def_dir ${_def_file} DIRECTORY)
+cpPlugins_NormalizePaths(_global_source_dir ${PROJECT_SOURCE_DIR})
+cpPlugins_NormalizePaths(_global_binary_dir ${PROJECT_BINARY_DIR})
+STRING(REPLACE "${_global_source_dir}" "" _out_dir ${_def_dir})
+SET(_out_base "${_global_binary_dir}${_out_dir}")
+SET(_out_header "${prefix}${_def_name}.h")
+SET(_out_code "${prefix}${_def_name}.cxx")
+SET(_lib_name "${prefix}${_def_name}")
+SET(_input_extra_code "${_global_source_dir}${_out_dir}/${_def_name}_extra.cxx")
 
 ## -- Add extra code, if any
-SET(_all_code_files ${_code_file})
-IF(EXISTS ${_extra_code_file})
-  SET(_all_code_files ${_all_code_files} ${_extra_code_file})
-ENDIF(EXISTS ${_extra_code_file})
+SET(_all_out_code ${_out_base}/${_out_code})
+IF(EXISTS ${_input_extra_code})
+  SET(_all_out_code ${_all_out_code} ${_input_extra_code})
+ENDIF(EXISTS ${_input_extra_code})
 
 ## -- Command to write source code
 ADD_CUSTOM_COMMAND(
-  OUTPUT ${_header_file} ${_code_file}
-  DEPENDS ${cpPlugins_CreateInstances_APP} ${_def_canonical_file}
-  COMMAND ${cpPlugins_CreateInstances_APP} ${_def_canonical_file} ${_library_name} ${CMAKE_CURRENT_BINARY_DIR}
+  OUTPUT ${_out_base}/${_out_header} ${_out_base}/${_out_code}
+  DEPENDS ${cpPlugins_CreateInstances_APP} ${_def_file}
+  COMMAND ${cpPlugins_CreateInstances_APP} ${_def_file} ${_lib_name} ${_out_base}
   )
 
 ## -- Create library
-cpPlugins_ManageLibrary(
-  ${_library_name} SHARED
-  "${_all_code_files}" "" ""
+cpPlugins_CreateLibrary(
+  "${_lib_name}" SHARED
+  "${_all_out_code}" "${_out_base}/${_out_header}" ""
   "${version}" "${short_version}"
-  ${ARGN}
   )
+SET(${out_lib_name} ${_lib_name} PARENT_SCOPE)
 
 ENDFUNCTION()
 
@@ -209,12 +275,17 @@ ENDFUNCTION()
 ## == Function to wrap plugins hosts ==
 ## ====================================
 
-FUNCTION(cpPlugins_WrapPlugins source_dir version short_version prefix)
+FUNCTION(cpPlugins_WrapPlugins output_lib source_dir version short_version prefix)
 
-## -- Some configuration values
-SET(_source_dir ${CMAKE_CURRENT_SOURCE_DIR}/${source_dir})
-SET(_binary_dir ${CMAKE_CURRENT_BINARY_DIR}/${source_dir})
-SET(_lib_name ${prefix}${source_dir})
+## -- Configure inputs to be cmake-path compatible
+cpPlugins_NormalizePaths(_source_dir ${source_dir})
+cpPlugins_NormalizePaths(_global_source_dir ${PROJECT_SOURCE_DIR})
+cpPlugins_NormalizePaths(_global_binary_dir ${PROJECT_BINARY_DIR})
+STRING(REPLACE "${_global_source_dir}" "" _out_dir ${_source_dir})
+SET(_out_dir "${_global_binary_dir}${_out_dir}")
+FILE(MAKE_DIRECTORY ${_out_dir})
+GET_FILENAME_COMPONENT(_lib_name ${_source_dir} NAME_WE)
+SET(_lib_name ${prefix}${_lib_name})
 
 ## -- Get source code
 FILE(GLOB_RECURSE _hdr_h   "${_source_dir}/*.h")
@@ -241,7 +312,7 @@ SET(_all_hdr ${_hdr_h} ${_hdr_hpp} ${_hdr_hxx})
 
 ## -- Wrap plugins
 IF(_hdr_to_wrap)
-  SET(_host ${_binary_dir}/${_lib_name}_host.cxx)
+  SET(_host ${_out_dir}/${_lib_name}_host.cxx)
   ADD_CUSTOM_COMMAND(
     OUTPUT ${_host}
     DEPENDS ${cpPlugins_HostCreator_APP} ${_hdr_to_wrap}
@@ -252,90 +323,127 @@ ENDIF(_hdr_to_wrap)
 
 ## -- Ok, build library
 IF(_all_src)
-  cpPlugins_ManageLibrary(
+  cpPlugins_CreateLibrary(
     ${_lib_name} SHARED
     "${_all_src}" "${_all_hdr}" "${_qt_ui}"
     "${version}" "${short_version}"
     ${ARGN}
     )
+  SET(${output_lib} ${_lib_name} PARENT_SCOPE)
 ELSE(_all_src)
   MESSAGE(FATAL_ERROR "No source code found to build \"${_lib_name}\"")
 ENDIF(_all_src)
-
 ENDFUNCTION()
 
 ## ======================================
 ## == Function to build an application ==
 ## ======================================
 
-FUNCTION(cpPlugins_BuildAppFromDirectory directory)
-
-## -- Some configuration values
-FILE(TO_CMAKE_PATH ${directory} _src_dir)
-STRING(REPLACE "${PROJECT_SOURCE_DIR}/" "" _bin_dir ${_src_dir})
-SET(_bin_dir "${PROJECT_BINARY_DIR}/${_bin_dir}")
-GET_FILENAME_COMPONENT(_app_name ${_src_dir} NAME)
-SET(_all_sources_extensions c cpp cxx)
-SET(_all_headers_extensions h hpp hxx)
-SET(_all_qt_ui_extensions ui)
-SET(_all_dirs ${_src_dir} ${_bin_dir})
-SET(_all_sources)
-SET(_all_headers)
-SET(_all_qt_ui)
-
-## -- Compilation option
-OPTION(BUILD_${_app_name} "Build \"${_app_name}\" application" OFF)
-
-## -- Glob source code
-FOREACH(_d ${_all_dirs})
-  FOREACH(_e ${_all_sources_extensions})
-    FILE(GLOB_RECURSE _f "${_d}/*.${_e}")
-    SET(_all_sources ${_all_sources} ${_f})
-  ENDFOREACH(_e)
-  FOREACH(_e ${_all_headers_extensions})
-    FILE(GLOB_RECURSE _f "${_d}/*.${_e}")
-    SET(_all_headers ${_all_headers} ${_f})
-  ENDFOREACH(_e)
-  FOREACH(_e ${_all_qt_ui_extensions})
-    FILE(GLOB_RECURSE _f "${_d}/*.${_e}")
-    SET(_all_qt_ui ${_all_qt_ui} ${_f})
-  ENDFOREACH(_e)
-ENDFOREACH(_d)
+FUNCTION(cpPlugins_BuildAppFromDirectory output_app source_dir)
 
-## -- Guess what headers sould be qt-moc'ed
-FOREACH(_h ${_all_headers})
-  FILE(READ ${_h} _txt)
-  STRING(FIND "${_txt}" "Q_OBJECT" _r)
-  IF(NOT ${_r} EQUAL -1)
-    SET(_s)
-    QT4_WRAP_CPP(_s ${_h})
-    SET(_all_sources ${_all_sources} ${_s})
-  ENDIF(NOT ${_r} EQUAL -1)
-ENDFOREACH(_h)
+## -- Configure inputs to be cmake-path compatible
+cpPlugins_NormalizePaths(_global_source_dir ${PROJECT_SOURCE_DIR})
+cpPlugins_NormalizePaths(_global_binary_dir ${PROJECT_BINARY_DIR})
+cpPlugins_NormalizePaths(_source_dir ${source_dir})
+STRING(REPLACE "${_global_source_dir}" "" _local_source_dir ${_source_dir})
+SET(_binary_dir ${_global_binary_dir}${_local_source_dir})
+GET_FILENAME_COMPONENT(_app_name ${_source_dir} NAME_WE)
+OPTION(BUILD_${_app_name} "Build \"${_app_name}\" application" OFF)
 
-## -- Guess what qt-ui's sould be qt-uic'ed
-## -- Wrap qt-ui headers: this is equivalent to QT4_WRAP_UI except to change the
-## -- output file
-FOREACH(_ui ${_all_qt_ui})
-  GET_FILENAME_COMPONENT(_r_ui ${_ui} NAME_WE)
-  SET(_o_ui ${_bin_dir}/ui_${_r_ui}.h)
-  ADD_CUSTOM_COMMAND(
-    OUTPUT ${_o_ui}
-    COMMAND Qt4::uic
-    ARGS -o ${_o_ui} ${_ui}
-    MAIN_DEPENDENCY ${_ui} VERBATIM
-    )
-  SET(_all_sources ${_all_sources} ${_o_ui})
-  SET(_all_headers ${_all_headers} ${_o_ui})
-ENDFOREACH(_ui)
-
-## -- Ok, compile application
-IF(_all_sources)
-  ADD_EXECUTABLE(${_app_name} ${_all_sources})
-  TARGET_LINK_LIBRARIES(${_app_name} ${ARGN})
-ELSE(_all_sources)
-  MESSAGE(FATAL_ERROR "No source code found to build \"${_app_name}\"")
-ENDIF(_all_sources)
+IF(BUILD_${_app_name})
+
+  ## -- Some useful variables
+  SET(_sources_extensions .c .cpp .cxx)
+  SET(_headers_extensions .h .hpp .hxx)
+  SET(_qt_ui_extensions .ui)
+  SET(_dirs ${_source_dir} ${_binary_dir})
+  SET(_sources)
+  SET(_headers)
+  SET(_qt_uis)
+
+  ## -- Glob source code
+  FOREACH(_d ${_dirs})
+    FOREACH(_e ${_sources_extensions})
+      FILE(GLOB_RECURSE _f "${_d}/*${_e}")
+      SET(_sources ${_sources} ${_f})
+    ENDFOREACH(_e)
+    FOREACH(_e ${_headers_extensions})
+      FILE(GLOB_RECURSE _f "${_d}/*${_e}")
+      SET(_headers ${_headers} ${_f})
+    ENDFOREACH(_e)
+    FOREACH(_e ${_qt_ui_extensions})
+      FILE(GLOB_RECURSE _f "${_d}/*${_e}")
+      SET(_qt_uis ${_qt_uis} ${_f})
+    ENDFOREACH(_e)
+  ENDFOREACH(_d)
+
+  ## -- Configure some files
+  FILE(GLOB_RECURSE _configs "${_source_dir}/*.in")
+  FOREACH(_c ${_configs})
+
+    ## -- Build input and output names
+    cpPlugins_NormalizePaths(_input_file ${_c})
+    GET_FILENAME_COMPONENT(_input_name ${_input_file} NAME)
+    GET_FILENAME_COMPONENT(_input_dir ${_input_file} DIRECTORY)
+    STRING(REPLACE ".in" "" _output_name ${_input_name})
+    STRING(REPLACE "${_global_source_dir}" "" _output_dir ${_input_dir})
+    SET(_output_file "${_global_binary_dir}${_output_dir}/${_output_name}")
+
+    ## -- Configure file
+    CONFIGURE_FILE(${_input_file} ${_output_file} @ONLY)
+
+    ## -- Add it to the correct list
+    GET_FILENAME_COMPONENT(_output_ext ${_output_name} EXT)
+    IF(
+        "${_output_ext}" STREQUAL ".h"
+        OR
+        "${_output_ext}" STREQUAL ".hpp"
+        OR
+        "${_output_ext}" STREQUAL ".hxx"
+        )
+      SET(_headers ${_headers})
+    ENDIF()
+    IF(
+        "${_output_ext}" STREQUAL ".c"
+        OR
+        "${_output_ext}" STREQUAL ".cpp"
+        OR
+        "${_output_ext}" STREQUAL ".cxx"
+        )
+      SET(_sources ${_sources})
+    ENDIF()
+    IF("${_output_ext}" STREQUAL ".ui")
+      SET(_qt_uis ${_qt_uis})
+    ENDIF()
+  ENDFOREACH(_c)
+
+  # -- Prepare Qt4-based code
+  IF(Qt4_FOUND)
+
+    ## -- Guess what headers sould be qt-moc'ed
+    cpPlugins_Wrap_Qt_cpp(_qt_moc_sources ${_headers})
+    IF(_qt_moc_sources)
+      SET(_sources ${_sources} ${_qt_moc_sources})
+    ENDIF(_qt_moc_sources)
+
+    ## -- Guess what qt-ui's sould be qt-uic'ed
+    ## -- Wrap qt-ui headers: this is equivalent to QT4_WRAP_UI except to
+    ## -- change the output file
+    cpPlugins_Wrap_Qt_ui(_qt_ui_headers ${_qt_uis})
+    IF(_qt_ui_headers)
+      SET(_headers ${_headers} ${_qt_ui_headers})
+      SET(_sources ${_sources} ${_qt_ui_headers})
+    ENDIF(_qt_ui_headers)
+  ENDIF(Qt4_FOUND)
+
+  ## -- Ok, compile application
+  IF(_sources)
+    ADD_EXECUTABLE(${_app_name} ${_sources})
+    SET(${output_app} ${_app_name} PARENT_SCOPE)
+  ELSE(_sources)
+    MESSAGE(FATAL_ERROR "No source code found to build \"${_app_name}\"")
+  ENDIF(_sources)
+ENDIF(BUILD_${_app_name})
 
 ENDFUNCTION()