blob: 881c2fd1e088db31a4a6f331fec978b9edfeb9b7 [file] [log] [blame]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
find_program(JAR_COMMAND jar)
if(JAR_COMMAND)
message(STATUS "Using jar to create bundles")
else()
find_program(ZIP_COMMAND zip)
if(ZIP_COMMAND)
message(STATUS "Using zip to create bundles")
else()
get_filename_component(__cmake_path ${CMAKE_COMMAND} PATH)
find_program(CPACK_COMMAND cpack ${__cmake_path})
if(CPACK_COMMAND)
message(STATUS "Using cpack to create bundles.")
message(WARNING "Please note that using jar and/or zip is prefered. When packaging bundles with cpack you must use 'make install-all' to install the project instead of 'make install'")
else()
message(FATAL_ERROR "A jar,zip or cpack command is needed to jar,zip or pack bundles")
endif()
endif()
endif()
##### setup bundles/deploy target
add_custom_target(bundles ALL)
add_custom_target(deploy ALL)
set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${CMAKE_BINARY_DIR}/deploy")
#####
macro(extract_version_parts VERSION MAJOR MINOR PATCH)
set(MAJOR "0")
set(MINOR "0")
set(PATCH "0")
string(REGEX MATCH "^([0-9]+).*" TMP "${VERSION}")
if (CMAKE_MATCH_1)
set(MAJOR ${CMAKE_MATCH_1})
endif()
string(REGEX MATCH "^([0-9]+)\\.([0-9])+.*" TMP "${VERSION}")
if (CMAKE_MATCH_2)
set(MINOR ${CMAKE_MATCH_2})
endif()
string(REGEX MATCH "^([0-9]+)\\.([0-9]+)\\.([0-9]+).*" TMP "${VERSION}")
if (CMAKE_MATCH_3)
set(PATCH ${CMAKE_MATCH_3})
endif()
#TODO add support qualifier
endmacro()
function(set_library_version TARGET VERSION)
if (VERSION AND TARGET)
extract_version_parts("${VERSION}" MAJOR MINOR PATCH)
#NOTE setting aligning ABI version with major part of the interface version.
#This is simpeler than using the <current>:<revision>:<age> approach of libtool
set_property(TARGET ${TARGET} PROPERTY VERSION "${VERSION}")
set_property(TARGET ${TARGET} PROPERTY SOVERSION ${MAJOR})
else ()
message(WARNING "set_library_version: Cannot set version info TARGET and/or VERSION not provided")
endif ()
endfunction()
function(check_lib LIB)
if(TARGET ${LIB})
#ok
elseif(IS_ABSOLUTE ${LIB} AND EXISTS ${LIB})
#ok
else()
message(FATAL_ERROR "Provided library (${LIB}) is not a target nor a absolute path to an existing library")
endif()
endfunction()
function(check_bundle BUNDLE)
if(TARGET ${BUNDLE})
get_target_property(BUNDLE_FILE ${BUNDLE} "BUNDLE_FILE")
if(NOT BUNDLE_FILE)
message(FATAL_ERROR "Provided target must be a bundle target")
endif()
else()
message(FATAL_ERROR "first argument must be a target")
endif()
endfunction()
function(add_bundle)
list(GET ARGN 0 BUNDLE_TARGET_NAME)
list(REMOVE_AT ARGN 0)
set(OPTIONS NO_ACTIVATOR)
set(ONE_VAL_ARGS VERSION ACTIVATOR SYMBOLIC_NAME NAME DESCRIPTION)
set(MULTI_VAL_ARGS SOURCES PRIVATE_LIBRARIES EXPORT_LIBRARIES IMPORT_LIBRARIES HEADERS)
cmake_parse_arguments(BUNDLE "${OPTIONS}" "${ONE_VAL_ARGS}" "${MULTI_VAL_ARGS}" ${ARGN})
##check arguments
if(NOT BUNDLE_TARGET_NAME)
message(FATAL_ERROR "add_bunde function requires first target name argument")
endif()
if((NOT (BUNDLE_SOURCES OR BUNDLE_ACTIVATOR)) AND (NOT BUNDLE_NO_ACTIVATOR))
message(FATAL_ERROR "Bundle contain no SOURCES or ACTIVATOR target and the option NO_ACTIVATOR is not set")
endif()
if(BUNDLE_SOURCES AND BUNDLE_ACTIVATOR)
message(FATAL_ERROR "add_bundle function requires a value for SOURCES or ACTIVATOR not both")
endif()
if(BUNDLE_ACTIVATOR)
check_lib(${BUNDLE_ACTIVATOR})
endif()
#setting defaults
if(NOT BUNDLE_VERSION)
set(BUNDLE_VERSION "0.0.0")
message(WARNING "Bundle version for ${BUNDLE_NAME} not provided. Using 0.0.0")
endif()
if (NOT BUNDLE_NAME)
set(BUNDLE_NAME ${BUNDLE_TARGET_NAME})
endif()
if (NOT BUNDLE_SYMBOLIC_NAME)
set(BUNDLE_SYMBOLIC_NAME ${BUNDLE_TARGET_NAME})
endif()
set(BUNDLE_FILE "${CMAKE_CURRENT_BINARY_DIR}/${BUNDLE_TARGET_NAME}.zip")
set(BUNDLE_CONTENT_DIR "${CMAKE_CURRENT_BINARY_DIR}/${BUNDLE_TARGET_NAME}_content")
set(BUNDLE_GEN_DIR "${CMAKE_CURRENT_BINARY_DIR}/${BUNDLE_TARGET_NAME}_gen")
###### Setting up dependency for bundles target
get_target_property(DEPS bundles "BUNDLES_DEPS")
list(APPEND DEPS "${BUNDLE_FILE}")
set_target_properties(bundles PROPERTIES "BUNDLES_DEPS" "${DEPS}")
#####
####### Setting target for activator lib if neccesary ####################
if(BUNDLE_SOURCES)
#create lib from sources
add_library(${BUNDLE_TARGET_NAME} SHARED ${BUNDLE_SOURCES})
set_library_version(${BUNDLE_TARGET_NAME} ${BUNDLE_VERSION})
set_target_properties(${BUNDLE_TARGET_NAME} PROPERTIES "BUNDLE_TARGET_IS_LIB" TRUE)
else()
add_custom_target(${BUNDLE_TARGET_NAME})
endif()
add_custom_target(${BUNDLE_TARGET_NAME}_bundle
DEPENDS "$<TARGET_PROPERTY:${BUNDLE_TARGET_NAME},BUNDLE_FILE>"
)
add_dependencies(bundles ${BUNDLE_TARGET_NAME}_bundle)
#######################################################################
##### MANIFEST configuration and generation ##################
#Step1 configure the file so that the target name is present in in the template
configure_file(${CELIX_CMAKE_DIRECTORY}/cmake_celix/Manifest.template.in ${BUNDLE_GEN_DIR}/MANIFEST.step1)
#Step2 replace headers with target property values. Note this is done build time
file(GENERATE
OUTPUT "${BUNDLE_GEN_DIR}/MANIFEST.step2"
INPUT "${BUNDLE_GEN_DIR}/MANIFEST.step1"
)
#Step3 The replaced values in step 2 can contain generator expresssion, generated again to resolve those. Note this is done build time
file(GENERATE
OUTPUT "${BUNDLE_GEN_DIR}/MANIFEST.MF"
INPUT "${BUNDLE_GEN_DIR}/MANIFEST.step2"
)
#########################################################
###### Packaging the bundle using using jar,zip or cpack and a content dir. Configuring dependencies ######
if(JAR_COMMAND)
add_custom_command(OUTPUT ${BUNDLE_FILE}
COMMAND ${CMAKE_COMMAND} -E make_directory ${BUNDLE_CONTENT_DIR}
COMMAND ${JAR_COMMAND} -cfm ${BUNDLE_FILE} ${BUNDLE_GEN_DIR}/MANIFEST.MF -C ${BUNDLE_CONTENT_DIR} .
COMMENT "Packaging ${BUNDLE_TARGET_NAME}"
DEPENDS ${BUNDLE_TARGET_NAME} "$<TARGET_PROPERTY:${BUNDLE_TARGET_NAME},BUNDLE_DEPEND_TARGETS>" ${BUNDLE_GEN_DIR}/MANIFEST.MF
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
elseif(ZIP_COMMAND)
add_custom_command(OUTPUT ${BUNDLE_FILE}
COMMAND ${CMAKE_COMMAND} -E make_directory ${BUNDLE_CONTENT_DIR}
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${BUNDLE_GEN_DIR}/MANIFEST.MF META-INF/MANIFEST.MF
COMMAND ${ZIP_COMMAND} -rq ${BUNDLE_FILE} *
COMMENT "Packaging ${BUNDLE_TARGET_NAME}"
DEPENDS ${BUNDLE_TARGET_NAME} "$<TARGET_PROPERTY:${BUNDLE_TARGET_NAME},BUNDLE_DEPEND_TARGETS>" ${BUNDLE_GEN_DIR}/MANIFEST.MF
WORKING_DIRECTORY ${BUNDLE_CONTENT_DIR}
)
elseif(CPACK_COMMAND)
install(DIRECTORY ${BUNDLE_CONTENT_DIR}/ DESTINATION . COMPONENT ${BUNDLE_TARGET_NAME}_install_cmp)
install(FILES ${BUNDLE_GEN_DIR}/MANIFEST.MF DESTINATION META-INF COMPONENT ${BUNDLE_TARGET_NAME}_install_cmp)
file(GENERATE OUTPUT ${BUNDLE_GEN_DIR}/cpack.cmake CONTENT "
SET(CPACK_CMAKE_GENERATOR \"Unix Makefiles\")
SET(CPACK_GENERATOR \"ZIP\")
SET(CPACK_INSTALL_CMAKE_PROJECTS \"${CMAKE_CURRENT_BINARY_DIR};${BUNDLE_TARGET_NAME};${BUNDLE_TARGET_NAME}_install_cmp;/\")
SET(CPACK_PACKAGE_DESCRIPTION \"\")
SET(CPACK_PACKAGE_FILE_NAME \"${BUNDLE_TARGET_NAME}\")
SET(CPACK_PACKAGE_NAME \"${BUNDLE_TARGET_NAME}\")
SET(CPACK_PACKAGE_VERSION \"0.0.1\")
SET(CPACK_INCLUDE_TOPLEVEL_DIRECTORY \"0\")
")
add_custom_command(OUTPUT ${BUNDLE_FILE}
COMMAND ${CPACK_COMMAND} ARGS -C Debug --config ${BUNDLE_GEN_DIR}/cpack.cmake
COMMENT "Packaging ${BUNDLE_TARGET_NAME}"
DEPENDS ${BUNDLE_TARGET_NAME} "$<TARGET_PROPERTY:${BUNDLE_TARGET_NAME},BUNDLE_DEPEND_TARGETS>" ${BUNDLE_GEN_DIR}/MANIFEST.MF
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
endif()
###################################################################################
###################################
##### Additional Cleanup info #####
###################################
set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "$<TARGET_PROPERTY:${BUNDLE_TARGET_NAME},BUNDLE_GEN_DIR>;$<TARGET_PROPERTY:${BUNDLE_TARGET_NAME},BUNDLE_CONTENT_DIR>")
#############################
### BUNDLE TARGET PROPERTIES
#############################
#internal use
set_target_properties(${BUNDLE_TARGET_NAME} PROPERTIES "BUNDLE_DEPEND_TARGETS" "") #bundle target dependencies. Note can be extended after the add_bundle call
set_target_properties(${BUNDLE_TARGET_NAME} PROPERTIES "BUNDLE_GEN_DIR" ${BUNDLE_GEN_DIR}) #location for generated output.
#bundle specific
set_target_properties(${BUNDLE_TARGET_NAME} PROPERTIES "BUNDLE_CONTENT_DIR" ${BUNDLE_CONTENT_DIR}) #location where the content to be jar/zipped.
set_target_properties(${BUNDLE_TARGET_NAME} PROPERTIES "BUNDLE_FILE" ${BUNDLE_FILE}) #target bundle file (.zip)
#name and version
set_target_properties(${BUNDLE_TARGET_NAME} PROPERTIES "BUNDLE_NAME" ${BUNDLE_NAME}) #The bundle name default target name
set_target_properties(${BUNDLE_TARGET_NAME} PROPERTIES "BUNDLE_SYMBOLIC_NAME" ${BUNDLE_SYMBOLIC_NAME}) #The bundle symbolic name. Default target name
set_target_properties(${BUNDLE_TARGET_NAME} PROPERTIES "BUNDLE_VERSION" ${BUNDLE_VERSION}) #The bundle version. Default 0.0.0
set_target_properties(${BUNDLE_TARGET_NAME} PROPERTIES "BUNDLE_DESCRIPTION" "${BUNDLE_DESCRIPTION}") #The bundle description.
#headers
set_target_properties(${BUNDLE_TARGET_NAME} PROPERTIES "BUNDLE_ACTIVATOR" 1) #Library containing the activator (if any)
set_target_properties(${BUNDLE_TARGET_NAME} PROPERTIES "BUNDLE_PRIVATE_LIBS" "") #List of private libs.
set_target_properties(${BUNDLE_TARGET_NAME} PROPERTIES "BUNDLE_IMPORT_LIBS" "") #List of libs to import
set_target_properties(${BUNDLE_TARGET_NAME} PROPERTIES "BUNDLE_EXPORT_LIBS" "") #list of libs to export
set_target_properties(${BUNDLE_TARGET_NAME} PROPERTIES "BUNDLE_HEADERS" "") #Additional headers will be added (new line seperated) to the manifest
################################
################################
if(BUNDLE_SOURCES)
bundle_private_libs(${BUNDLE_TARGET_NAME} ${BUNDLE_TARGET_NAME})
set_target_properties(${BUNDLE_TARGET_NAME} PROPERTIES "BUNDLE_ACTIVATOR" "$<TARGET_SONAME_FILE_NAME:${BUNDLE_TARGET_NAME}>")
set_target_properties(${BUNDLE_TARGET_NAME} PROPERTIES "BUILD_WITH_INSTALL_RPATH" true)
if(APPLE)
set_target_properties(${BUNDLE_TARGET_NAME} PROPERTIES INSTALL_RPATH "@loader_path")
else()
set_target_properties(${BUNDLE_TARGET_NAME} PROPERTIES INSTALL_RPATH "$ORIGIN")
endif()
elseif(BUNDLE_NO_ACTIVATOR)
#do nothing
else() #ACTIVATOR
bundle_private_libs(${BUNDLE_TARGET_NAME} ${BUNDLE_ACTIVATOR})
get_filename_component(ACT_NAME ${BUNDLE_ACTIVATOR} NAME)
set_target_properties(${BUNDLE_TARGET_NAME} PROPERTIES "BUNDLE_ACTIVATOR" ${ACT_NAME})
endif()
bundle_private_libs(${BUNDLE_TARGET_NAME} ${BUNDLE_PRIVATE_LIBRARIES})
bundle_export_libs(${BUNDLE_TARGET_NAME} ${BUNDLE_EXPORT_LIBRARIES})
bundle_import_libs(${BUNDLE_TARGET_NAME} ${BUNDLE_IMPORT_LIBRARIES})
bundle_headers(${BUNDLE_TARGET_NAME} ${BUNDLE_HEADERS})
endfunction()
function(get_bundle_file BUNDLE OUT)
check_bundle(${BUNDLE})
get_target_property(${OUT} ${BUNDLE} "BUNDLE_FILE")
endfunction()
function(bundle_export_libs)
list(GET ARGN 0 BUNDLE)
list(REMOVE_AT ARGN 0)
bundle_libs(${BUNDLE} "EXPORT" ${ARGN})
endfunction()
function(bundle_private_libs)
list(GET ARGN 0 BUNDLE)
list(REMOVE_AT ARGN 0)
bundle_libs(${BUNDLE} "PRIVATE" ${ARGN})
endfunction()
function(bundle_libs)
#0 is bundle TARGET
#1 is type (PRIVATE,EXPORT
#2..n is libs
list(GET ARGN 0 BUNDLE)
list(REMOVE_AT ARGN 0)
list(GET ARGN 0 TYPE)
list(REMOVE_AT ARGN 0)
#check if arg 0 is corrent
check_bundle(${BUNDLE})
get_target_property(BUNDLE_DIR ${BUNDLE} "BUNDLE_CONTENT_DIR")
get_target_property(BUNDLE_GEN_DIR ${BUNDLE} "BUNDLE_GEN_DIR")
get_target_property(LIBS ${BUNDLE} "BUNDLE_${TYPE}_LIBS")
get_target_property(DEPS ${BUNDLE} "BUNDLE_DEPEND_TARGETS")
foreach(LIB IN ITEMS ${ARGN})
if(IS_ABSOLUTE ${LIB} AND EXISTS ${LIB})
get_filename_component(LIB_NAME ${LIB} NAME)
set(OUT "${BUNDLE_DIR}/${LIB_NAME}")
add_custom_command(OUTPUT ${OUT}
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${LIB} ${OUT}
)
list(APPEND LIBS ${LIB_NAME})
list(APPEND DEPS ${OUT})
else()
#Assuming target
#NOTE add_custom_command does not support generator expression in OUTPUT value (e.g. $<TARGET_FILE:${LIB}>)
#Using a two step approach to be able to use add_custom_command instead of add_custom_target
set(OUT "${BUNDLE_GEN_DIR}/lib-${LIB}-copy-timestamp")
add_custom_command(OUTPUT ${OUT}
COMMAND ${CMAKE_COMMAND} -E touch ${OUT}
COMMAND ${CMAKE_COMMAND} -E copy_if_different "$<TARGET_FILE:${LIB}>" "${BUNDLE_DIR}/$<TARGET_SONAME_FILE_NAME:${LIB}>"
DEPENDS ${LIB}
)
list(APPEND DEPS "${OUT}") #NOTE depending on ${OUT} not on $<TARGET_FILE:${LIB}>.
list(APPEND LIBS "$<TARGET_SONAME_FILE_NAME:${LIB}>")
endif()
get_target_property(IS_LIB ${BUNDLE} "BUNDLE_TARGET_IS_LIB")
if ("${LIB}" STREQUAL "${BUNDLE}")
#ignore. Do not have to link agaist own lib
elseif(IS_LIB)
target_link_libraries(${BUNDLE} ${LIB})
endif()
endforeach()
set_target_properties(${BUNDLE} PROPERTIES "BUNDLE_${TYPE}_LIBS" "${LIBS}")
set_target_properties(${BUNDLE} PROPERTIES "BUNDLE_DEPEND_TARGETS" "${DEPS}")
endfunction()
function(bundle_import_libs)
#0 is bundle TARGET
#2..n is import libs
list(GET ARGN 0 BUNDLE)
list(REMOVE_AT ARGN 0)
#check if arg 0 is corrent
check_bundle(${BUNDLE})
get_target_property(LIBS ${BUNDLE} "BUNDLE_IMPORT_LIBS")
set(LIBS )
foreach(LIB IN ITEMS ${ARGN})
if(IS_ABSOLUTE ${LIB} AND EXISTS ${LIB})
list(APPEND LIBS ${LIB_NAME})
else()
list(APPEND LIBS "$<TARGET_SONAME_FILE_NAME:${LIB}>")
endif()
target_link_libraries(${BUNDLE} ${LIB})
endforeach()
set_target_properties(${BUNDLE} PROPERTIES "BUNDLE_IMPORT_LIBS" "${LIBS}")
endfunction()
function(bundle_files)
#0 is bundle TARGET
#1..n is header name / header value
list(GET ARGN 0 BUNDLE)
list(REMOVE_AT ARGN 0)
set(OPTIONS )
set(ONE_VAL_ARGS DESTINATION)
set(MULTI_VAL_ARGS )
cmake_parse_arguments(FILES "${OPTIONS}" "${ONE_VAL_ARGS}" "${MULTI_VAL_ARGS}" ${ARGN})
get_target_property(BUNDLE_DIR ${BUNDLE} "BUNDLE_CONTENT_DIR")
if (FILES_DESTINATION)
set(DESTINATION "${BUNDLE_DIR}/${FILES_DESTINATION}")
else()
set(DESTINATION "${BUNDLE_DIR}")
endif()
#message("call: files(COPY ${FILES_UNPARSED_ARGUMENTS} DESTINATION \"${DESTINATION}\"")
file(COPY ${FILES_UNPARSED_ARGUMENTS} DESTINATION ${DESTINATION})
endfunction()
function(bundle_headers)
#0 is bundle TARGET
#1..n is header name / header value
list(GET ARGN 0 BUNDLE)
list(REMOVE_AT ARGN 0)
get_target_property(HEADERS ${BUNDLE} "BUNDLE_HEADERS")
foreach(HEADER IN ITEMS ${ARGN})
list(APPEND HEADERS "${HEADER}")
endforeach()
set_target_properties(${BUNDLE} PROPERTIES "BUNDLE_HEADERS" "${HEADERS}")
endfunction()
function(bundle_symbolic_name BUNDLE SYMBOLIC_NAME)
set_target_properties(${BUNDLE} PROPERTIES "BUNDLE_SYMBOLIC_NAME" ${SYMBOLIC_NAME})
endfunction()
function(bundle_name BUNDLE NAME)
set_target_properties(${BUNDLE} PROPERTIES "BUNDLE_NAME" ${NAME})
endfunction()
function(bundle_version BUNDLE VERSION)
set_target_properties(${BUNDLE} PROPERTIES "BUNDLE_VERSION" ${VERSION})
endfunction()
function(bundle_description BUNDLE DESC)
set_target_properties(${BUNDLE} PROPERTIES "BUNDLE_DESCRIPTION" ${DESC})
endfunction()
function(install_bundle)
#0 is bundle TARGET
list(GET ARGN 0 BUNDLE)
list(REMOVE_AT ARGN 0)
set(OPTIONS )
set(ONE_VAL_ARGS PROJECT_NAME BUNDLE_NAME)
set(MULTI_VAL_ARGS HEADERS RESOURCES)
cmake_parse_arguments(INSTALL "${OPTIONS}" "${ONE_VAL_ARGS}" "${MULTI_VAL_ARGS}" ${ARGN})
if (NOT INSTALL_PROJECT_NAME)
string(TOLOWER ${PROJECT_NAME} INSTALL_PROJECT_NAME)
endif()
if (NOT INSTALL_BUNDLE_NAME)
set(INSTALL_BUNDLE_NAME ${BUNDLE})
endif()
install(FILES "$<TARGET_PROPERTY:${BUNDLE},BUNDLE_FILE>" DESTINATION share/${INSTALL_PROJECT_NAME}/bundles COMPONENT ${BUNDLE})
if(INSTALL_HEADERS)
install (FILES ${INSTALL_HEADERS} DESTINATION include/${INSTALL_PROJECT_NAME}/${INSTALL_BUNDLE_NAME} COMPONENT ${BUNDLE})
endif()
if (INSTALL_RESOURCES)
install (FILES ${INSTALL_RESOURCES} DESTINATION share/${INSTALL_PROJECT_NAME}/${INSTALL_BUNDLE_NAME} COMPONENT ${BUNDLE})
endif()
endfunction()
function(add_deploy)
list(GET ARGN 0 DEPLOY_TARGET)
list(REMOVE_AT ARGN 0)
set(OPTIONS COPY)
set(ONE_VAL_ARGS GROUP NAME LAUNCHER)
set(MULTI_VAL_ARGS BUNDLES PROPERTIES)
cmake_parse_arguments(DEPLOY "${OPTIONS}" "${ONE_VAL_ARGS}" "${MULTI_VAL_ARGS}" ${ARGN})
##### Check arguments #####
if(NOT DEPLOY_NAME)
set(DEPLOY_NAME "${DEPLOY_TARGET}")
endif()
######
##### Setting defaults #####
if(DEPLOY_GROUP)
set(DEPLOY_LOCATION "${CMAKE_BINARY_DIR}/deploy/${DEPLOY_GROUP}/${DEPLOY_NAME}")
set(DEPLOY_PRINT_NAME "${DEPLOY_GROUP}/${DEPLOY_NAME}")
else()
set(DEPLOY_LOCATION "${CMAKE_BINARY_DIR}/deploy/${DEPLOY_NAME}")
set(DEPLOY_PRINT_NAME "${DEPLOY_NAME}")
endif()
######
###### Setup deploy custom target and config.properties file
set(TIMESTAMP_FILE "${CMAKE_CURRENT_BINARY_DIR}/${DEPLOY_TARGET}-deploy-timestamp")
add_custom_target(${DEPLOY_TARGET}
DEPENDS ${TIMESTAMP_FILE}
)
add_dependencies(deploy ${DEPLOY_TARGET})
#FILE TARGETS FOR DEPLOY
set(DEPLOY_EXE "${DEPLOY_LOCATION}/${DEPLOY_NAME}")
set(DEPLOY_RUN_SH "${DEPLOY_LOCATION}/run.sh")
set(DEPLOY_PROPS "${DEPLOY_LOCATION}/config.properties")
set(DEPLOY_ECLIPSE_LAUNCHER "${DEPLOY_LOCATION}/${DEPLOY_NAME}.launch")
set(DEPLOY_RELEASE_SH "${DEPLOY_LOCATION}/release.sh")
find_program(LINK_CMD ln)
if (LINK_CMD)
#if ln is available use a softlink to celix exe instead of a run.sh
list(APPEND DEPLOY_FILE_TARGETS ${DEPLOY_PROPS} ${DEPLOY_ECLIPSE_LAUNCHER} ${DEPLOY_RELEASE_SH} ${DEPLOY_RUN_SH} ${DEPLOY_EXE})
else()
list(APPEND DEPLOY_FILE_TARGETS ${DEPLOY_PROPS} ${DEPLOY_ECLIPSE_LAUNCHER} ${DEPLOY_RELEASE_SH} ${DEPLOY_RUN_SH})
endif()
#setup dependencies based on timestamp
add_custom_command(OUTPUT "${TIMESTAMP_FILE}"
COMMAND ${CMAKE_COMMAND} -E touch ${TIMESTAMP_FILE}
DEPENDS "$<TARGET_PROPERTY:${DEPLOY_TARGET},DEPLOY_TARGET_DEPS>" ${DEPLOY_FILE_TARGETS}
WORKING_DIRECTORY "${DEPLOY_LOCATION}"
COMMENT "Deploying ${DEPLOY_PRINT_NAME}" VERBATIM
)
#Setting CELIX_LIB_DIRS, CELIX_BIN_DIR and CELIX_LAUNCHER
if (EXISTS ${CELIX_FRAMEWORK_LIBRARY})
#CELIX_FRAMEWORK_LIBRARY set by FindCelix.cmake -> Celix Based Project
get_filename_component(CELIX_LIB_DIR ${CELIX_FRAMEWORK_LIBRARY} DIRECTORY) #Note assuming all celix libs are in the same dir
set(CELIX_LIB_DIRS "${CELIX_LIB_DIR}")
#CELIX_LAUNCHER is set by FindCelix.cmake
get_filename_component(CELIX_BIN_DIR ${CELIX_LAUNCHER} DIRECTORY)
else()
#Celix Main Project
set(CELIX_LIB_DIRS "$<TARGET_FILE_DIR:celix_framework>:$<TARGET_FILE_DIR:celix_utils>:$<TARGET_FILE_DIR:celix_dfi>")
set(CELIX_LAUNCHER "$<TARGET_FILE:celix>")
set(CELIX_BIN_DIR "$<TARGET_FILE_DIR:celix>")
endif()
#generate config.properties
set(STAGE1_PROPERTIES "${CMAKE_CURRENT_BINARY_DIR}/${DEPLOY_TARGET}-deploy-config-stage1.properties")
file(GENERATE
OUTPUT "${STAGE1_PROPERTIES}"
CONTENT "cosgi.auto.start.1=$<JOIN:$<TARGET_PROPERTY:${DEPLOY_TARGET},DEPLOY_BUNDLES>, >
$<JOIN:$<TARGET_PROPERTY:${DEPLOY_TARGET},DEPLOY_PROPERTIES>,
>
"
)
file(GENERATE
OUTPUT "${DEPLOY_PROPS}"
INPUT "${STAGE1_PROPERTIES}"
)
#Setup launcher using celix target, celix binary or custom launcher
if (DEPLOY_LAUNCHER)
if (IS_ABSOLUTE "${DEPLOY_LAUNCHER}")
#assuming target
set(LAUNCHER "${DEPLOY_LAUNCHER}")
else()
set(LAUNCHER "$<TARGET_FILE:${DEPLOY_LAUNCHER}>")
endif()
else()
#Use CELIX_LAUNCHER
set(LAUNCHER "${CELIX_LAUNCHER}")
endif()
#softlink celix exe file
add_custom_command(OUTPUT "${DEPLOY_EXE}"
COMMAND ${LINK_CMD} -s "${LAUNCHER}" "${DEPLOY_EXE}"
WORKING_DIRECTORY ${DEPLOY_LOCATION}
DEPENDS "${LAUNCHER}"
COMMENT "Symbolic link launcher to ${DEPLOY_EXE}" VERBATIM
)
#generate release.sh and optional run.sh
if(APPLE)
set(LIB_PATH_NAME "DYLD_LIBRARY_PATH")
else()
set(LIB_PATH_NAME "LD_LIBRARY_PATH")
endif()
set(RELEASE_CONTENT "#!/bin/sh\nexport ${LIB_PATH_NAME}=${CELIX_LIB_DIRS}:\${${LIB_PATH_NAME}}\nexport PATH=${CELIX_BIN_DIR}:\${PATH}")
file(GENERATE
OUTPUT ${DEPLOY_RELEASE_SH}
CONTENT ${RELEASE_CONTENT}
)
set(RUN_CONTENT "${RELEASE_CONTENT}\n${LAUNCHER} \$@\n")
file(GENERATE
OUTPUT ${DEPLOY_RUN_SH}
CONTENT ${RUN_CONTENT}
)
#generate eclipse project launch file
set(PROGRAM_NAME "${LAUNCHER}")
set(CONTAINER_NAME ${DEPLOY_NAME})
set(PROJECT_ATTR "${CMAKE_PROJECT_NAME}-build")
set(WORKING_DIRECTORY ${DEPLOY_LOCATION})
include("${CELIX_CMAKE_DIRECTORY}/cmake_celix/RunConfig.in.cmake") #set VAR RUN_CONFIG_IN
file(GENERATE
OUTPUT "${DEPLOY_ECLIPSE_LAUNCHER}"
CONTENT "${RUN_CONFIG_IN}"
)
##### Deploy Target Properties #####
#internal use
set_target_properties(${DEPLOY_TARGET} PROPERTIES "DEPLOY_TARGET_DEPS" "") #bundles to deploy.
set_target_properties(${DEPLOY_TARGET} PROPERTIES "DEPLOY_BUNDLES" "") #bundles to deploy.
set_target_properties(${DEPLOY_TARGET} PROPERTIES "DEPLOY_COPY_BUNDLES" ${DEPLOY_COPY}) #copy bundles in bundle dir or link using abs paths.
#deploy specific
set_target_properties(${DEPLOY_TARGET} PROPERTIES "DEPLOY_LOCATION" ${DEPLOY_LOCATION})
set_target_properties(${DEPLOY_TARGET} PROPERTIES "DEPLOY_PROPERTIES" "")
#####
deploy_bundles(${DEPLOY_TARGET} ${DEPLOY_BUNDLES})
deploy_properties(${DEPLOY_TARGET} ${DEPLOY_PROPERTIES})
endfunction()
#NOTE can be used for drivers/proxies/endpoints bundle dirs
function(deploy_bundles_dir)
list(GET ARGN 0 DEPLOY_NAME)
list(REMOVE_AT ARGN 0)
set(OPTIONS)
set(ONE_VAL_ARGS DIR_NAME)
set(MULTI_VAL_ARGS BUNDLES)
cmake_parse_arguments(BD "${OPTIONS}" "${ONE_VAL_ARGS}" "${MULTI_VAL_ARGS}" ${ARGN})
if(NOT BD_DIR_NAME)
message(FATAL_ERROR "Missing mandatory DIR_NAME argument")
endif()
get_target_property(DEPLOY_LOC ${DEPLOY_NAME} "DEPLOY_LOCATION")
get_target_property(DEPS ${DEPLOY_NAME} "DEPLOY_TARGET_DEPS")
foreach(BUNDLE IN ITEMS ${BD_BUNDLES})
if (IS_ABSOLUTE ${BUNDLE} AND EXISTS ${BUNDLE})
get_filename_component(BUNDLE_FILENAME ${BUNDLE} NAME)
set(OUT "${DEPLOY_LOC}/${BD_DIR_NAME}/${BUNDLE_FILENAME}")
add_custom_command(OUTPUT ${OUT}
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${BUNDLE} ${OUT}
COMMENT "Copying bundle '${BUNDLE}' to '${DEPLOY_LOC}/${BD_DIR_NAME}'"
DEPENDS ${BUNDLE}
)
else()
set(OUT "${DEPLOY_LOC}/${BD_DIR_NAME}/${BUNDLE}.zip")
add_custom_command(OUTPUT ${OUT}
COMMAND ${CMAKE_COMMAND} -E copy_if_different "$<TARGET_PROPERTY:${BUNDLE},BUNDLE_FILE>" ${OUT}
COMMENT "Copying bundle '${BUNDLE}' to '${DEPLOY_LOC}/${BD_DIR_NAME}'"
DEPENDS ${BUNDLE} #Note cannot directly depends on ${BUNDLE}_bundle, depending in ${BUNDLE} triggering build instead.
)
add_dependencies(${DEPLOY_NAME} ${BUNDLE}_bundle) #ensure the the deploy depends on the _bundle target, custom_command depends on add_library
endif()
list(APPEND DEPS "${OUT}")
endforeach()
set_target_properties(${DEPLOY_NAME} PROPERTIES "DEPLOY_TARGET_DEPS" "${DEPS}")
endfunction()
function(deploy_bundles)
#0 is deploy TARGET
#1..n is bundles
list(GET ARGN 0 DEPLOY_NAME)
list(REMOVE_AT ARGN 0)
get_target_property(BUNDLES ${DEPLOY_NAME} "DEPLOY_BUNDLES")
get_target_property(COPY ${DEPLOY_NAME} "DEPLOY_COPY_BUNDLES")
foreach(BUNDLE IN ITEMS ${ARGN})
if(COPY)
if(IS_ABSOLUTE ${BUNDLE} AND EXISTS ${BUNDLE})
get_filename_component(BUNDLE_FILENAME ${BUNDLE} NAME)
list(APPEND BUNDLES "bundles/${BUNDLE_FILENAME}")
else() #assuming target
list(APPEND BUNDLES "bundles/${BUNDLE}.zip")
endif()
else()
if(IS_ABSOLUTE ${BUNDLE} AND EXISTS ${BUNDLE})
list(APPEND BUNDLES ${BUNDLE})
else() #assuming target
list(APPEND BUNDLES "$<TARGET_PROPERTY:${BUNDLE},BUNDLE_FILE>")
endif()
endif()
endforeach()
if(COPY)
deploy_bundles_dir(${DEPLOY_NAME} DIR_NAME bundles BUNDLES ${ARGN})
endif()
set_target_properties(${DEPLOY_NAME} PROPERTIES "DEPLOY_BUNDLES" "${BUNDLES}")
endfunction()
function(deploy_properties)
#0 is deploy TARGET
#1..n is bundles
list(GET ARGN 0 DEPLOY_NAME)
list(REMOVE_AT ARGN 0)
get_target_property(PROPS ${DEPLOY_NAME} "DEPLOY_PROPERTIES")
foreach(PROP IN ITEMS ${ARGN})
list(APPEND PROPS ${PROP})
endforeach()
set_target_properties(${DEPLOY_NAME} PROPERTIES "DEPLOY_PROPERTIES" "${PROPS}")
endfunction()