blob: 74279c4df36fc155e1e2c1d845500b83bab04f02 [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.
##### setup docker target
if (APPLE) #create filesystem script is not working on mac os, exclude target from ALL
add_custom_target(celix-build-docker-dirs
DEPENDS $<TARGET_PROPERTY:celix-build-docker-dirs,DOCKER_DEPS>
)
else ()
add_custom_target(celix-build-docker-dirs ALL
DEPENDS $<TARGET_PROPERTY:celix-build-docker-dirs,DOCKER_DEPS>
)
endif ()
set_target_properties(celix-build-docker-dirs PROPERTIES "DOCKER_DEPS" "") #initial empty deps list
add_custom_target(celix-build-docker-images)
set(DOCKER_USE_SUDO ON CACHE BOOL "Wether the use of sudo is needed to run docker")
set(DOCKER_CMD "docker" CACHE STRING "Docker command to use.")
get_directory_property(CLEANFILES ADDITIONAL_MAKE_CLEAN_FILES)
list(APPEND CLEANFILES "${CMAKE_BINARY_DIR}/docker")
set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${CLEANFILES}")
#####
function(add_celix_docker)
list(GET ARGN 0 DOCKER_TARGET)
list(REMOVE_AT ARGN 0)
set(OPTIONS CXX)
set(ONE_VAL_ARGS GROUP NAME FROM BUNDLES_DIR WORKDIR IMAGE_NAME)
set(MULTI_VAL_ARGS BUNDLES PROPERTIES INSTRUCTIONS)
cmake_parse_arguments(DOCKER "${OPTIONS}" "${ONE_VAL_ARGS}" "${MULTI_VAL_ARGS}" ${ARGN})
#set defaults
if (NOT DOCKER_FROM)
set(DOCKER_FROM "scratch")
set(DOCKER_CREATE_FS true)
else()
set(DOCKER_CREATE_FS false)
endif()
if (NOT DOCKER_NAME)
set(DOCKER_NAME "${DOCKER_TARGET}")
endif()
if (NOT DOCKER_IMAGE_NAME)
set(DOCKER_IMAGE_NAME "${DOCKER_NAME}")
endif()
if (NOT DOCKER_WORKDIR)
set(DOCKER_WORKDIR "/root")
endif()
if (NOT DOCKER_GROUP)
set(DOCKER_LOC "${CMAKE_BINARY_DIR}/docker/${DOCKER_NAME}")
else()
set(DOCKER_LOC "${CMAKE_BINARY_DIR}/docker/${DOCKER_GROUP}/${DOCKER_NAME}")
endif()
if (NOT DOCKER_BUNDLES_DIR)
set(DOCKER_BUNDLES_DIR "/bundles")
endif()
#ensure the docker dir will be deleted during clean
get_directory_property(CLEANFILES ADDITIONAL_MAKE_CLEAN_FILES)
list(APPEND CLEANFILES "$<TARGET_PROPERTY:${DOCKER_TARGET},DOCKER_LOC>")
set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${CLEANFILES}")
if (DOCKER_LAUNCHER_SRC)
get_filename_component(SRC_FILENAME ${DOCKER_LAUNCHER_SRC} NAME)
set(LAUNCHER_SRC "${PROJECT_BINARY_DIR}/celix/gen/${DOCKER_TARGET}-${SRC_FILENAME}")
set(LAUNCHER_ORG "${DOCKER_LAUNCHER_SRC}")
elseif (DOCKER_CXX)
set(LAUNCHER_SRC "${PROJECT_BINARY_DIR}/celix/gen/${DOCKER_TARGET}-main.cc")
set(LAUNCHER_ORG "${CELIX_CMAKE_DIRECTORY}/cmake_celix/main.c.in")
else()
set(LAUNCHER_SRC "${PROJECT_BINARY_DIR}/celix/gen/${DOCKER_TARGET}-main.c")
set(LAUNCHER_ORG "${CELIX_CMAKE_DIRECTORY}/cmake_celix/main.c.in")
endif()
if (DOCKER_LAUNCHER)
add_custom_target(${DOCKER_TARGET})
if (IS_ABSOLUTE "${DOCKER_LAUNCHER}")
set(LAUNCHER "${DOCKER_LAUNCHER}")
get_filename_component(EXE_FILENAME ${DOCKER_LAUNCHER} NAME)
set(DOCKER_ENTRYPOINT "ENTRYPOINT [\"/bin/${EXE_FILENAME}\"]")
else()
#assuming target
set(LAUNCHER "$<TARGET_FILE:${DOCKER_LAUNCHER}>")
set(DOCKER_ENTRYPOINT "ENTRYPOINT [\"/bin/$<TARGET_FILE_NAME:${DOCKER_TARGET}>\"]")
endif()
else ()
add_custom_command(OUTPUT ${LAUNCHER_SRC}
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/celix/gen
)
if (DOCKER_CXX)
set(LAUNCHER_STAGE1 "${CMAKE_CURRENT_BINARY_DIR}/${DOCKER_TARGET}-docker-main-stage1.cc")
else()
set(LAUNCHER_STAGE1 "${CMAKE_CURRENT_BINARY_DIR}/${DOCKER_TARGET}-docker-main-stage1.c")
endif()
file(GENERATE
OUTPUT "${LAUNCHER_STAGE1}"
CONTENT "#include <celix_launcher.h>
int main(int argc, char *argv[]) {
const char * config = \"cosgi.auto.start.1=$<JOIN:$<TARGET_PROPERTY:${DOCKER_TARGET},DOCKER_BUNDLES>, >\\n\\
$<JOIN:$<TARGET_PROPERTY:${DOCKER_TARGET},DOCKER_PROPERTIES>,\\n\\
>\";
properties_pt packedConfig = properties_loadFromString(config);
return celixLauncher_launchWithArgsAndProps(argc, argv, packedConfig);
}
"
)
file(GENERATE
OUTPUT "${LAUNCHER_SRC}"
INPUT "${LAUNCHER_STAGE1}"
)
add_executable(${DOCKER_TARGET} EXCLUDE_FROM_ALL ${LAUNCHER_SRC})
# set_target_properties(${DOCKER_TARGET} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${DOCKER_LOC})
target_include_directories(${DOCKER_TARGET} PRIVATE ${CELIX_INCLUDE_DIRS})
target_link_libraries(${DOCKER_TARGET} PRIVATE ${CELIX_FRAMEWORK_LIBRARY} ${CELIX_UTILS_LIBRARY})
set(LAUNCHER "$<TARGET_FILE:${DOCKER_TARGET}>")
set(DOCKER_ENTRYPOINT "ENTRYPOINT [\"/bin/$<TARGET_FILE_NAME:${DOCKER_TARGET}>\"]")
endif ()
###### Setup docker custom target timestamp
add_custom_target(${DOCKER_TARGET}-deps
DEPENDS ${FS_TIMESTAMP_FILE} $<TARGET_PROPERTY:${DOCKER_TARGET},DOCKER_DEPS>
)
add_dependencies(${DOCKER_TARGET} ${DOCKER_TARGET}-deps)
#setup dependencies based on timestamp
if (DOCKER_CREATE_FS)
add_custom_command(TARGET ${DOCKER_TARGET} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory $<TARGET_PROPERTY:${DOCKER_TARGET},DOCKER_LOC>
COMMAND cd $<TARGET_PROPERTY:${DOCKER_TARGET},DOCKER_LOC> && /bin/bash ${CELIX_CMAKE_DIRECTORY}/cmake_celix/create_target_filesystem.sh -e ${LAUNCHER} > /dev/null
WORKING_DIRECTORY "${DOCKER_LOC}"
COMMENT "Creating docker dir for ${DOCKER_TARGET}" VERBATIM
)
else ()
add_custom_command(TARGET ${DOCKER_TARGET} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory $<TARGET_PROPERTY:${DOCKER_TARGET},DOCKER_LOC>/bin
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${LAUNCHER} $<TARGET_PROPERTY:${DOCKER_TARGET},DOCKER_LOC>/bin/
WORKING_DIRECTORY "${DOCKER_LOC}"
COMMENT "Creating docker dir for ${DOCKER_TARGET}" VERBATIM
)
endif ()
##### Deploy Target Properties for Dockerfile #####
set_target_properties(${DOCKER_TARGET} PROPERTIES "DOCKER_LOC" "${DOCKER_LOC}")
set_target_properties(${DOCKER_TARGET} PROPERTIES "DOCKER_FROM" "${DOCKER_FROM}") #name of docker base, default celix-base
set_target_properties(${DOCKER_TARGET} PROPERTIES "DOCKER_IMAGE_NAME" "${DOCKER_IMAGE_NAME}") #name of docker images, default deploy target name
set_target_properties(${DOCKER_TARGET} PROPERTIES "DOCKER_BUNDLES_DIR" "${DOCKER_BUNDLES_DIR}") #bundles directory in docker image
set_target_properties(${DOCKER_TARGET} PROPERTIES "DOCKER_BUNDLES" "") #bundles
set_target_properties(${DOCKER_TARGET} PROPERTIES "DOCKER_WORKDIR" "${DOCKER_WORKDIR}") #workdir in docker image, should also contain the config.properties
set_target_properties(${DOCKER_TARGET} PROPERTIES "DOCKER_ENTRYPOINT" "${DOCKER_ENTRYPOINT}")
set_target_properties(${DOCKER_TARGET} PROPERTIES "DOCKER_CREATE_FS" "${DOCKER_CREATE_FS}") #wether to create a fs with the minimal needed libraries / etc files
set_target_properties(${DOCKER_TARGET} PROPERTIES "DOCKER_INSTRUCTIONS" "") #list of additional instructions
set_target_properties(${DOCKER_TARGET} PROPERTIES "DOCKER_PROPERTIES" "")
set_target_properties(${DOCKER_TARGET} PROPERTIES "DOCKER_DEPS" "")
set(DOCKERFILE_STAGE1 ${CMAKE_BINARY_DIR}/celix/gen/${DOCKER_TARGET}-Dockerfile.in)
set(DOCKERFILE "$<TARGET_PROPERTY:${DOCKER_TARGET},DOCKER_LOC>/Dockerfile")
file(GENERATE
OUTPUT "${DOCKERFILE_STAGE1}"
CONTENT "# Dockerfile for celix based image
FROM $<TARGET_PROPERTY:${DOCKER_TARGET},DOCKER_FROM>
ENV IMAGE_NAME $<TARGET_PROPERTY:${DOCKER_TARGET},DOCKER_IMAGE_NAME>
COPY . /
WORKDIR $<TARGET_PROPERTY:${DOCKER_TARGET},DOCKER_WORKDIR>
$<TARGET_PROPERTY:${DOCKER_TARGET},DOCKER_ENTRYPOINT>
$<JOIN:$<TARGET_PROPERTY:${DOCKER_TARGET},DOCKER_INSTRUCTIONS>,
>
")
file(GENERATE
OUTPUT ${DOCKERFILE}
INPUT ${DOCKERFILE_STAGE1}
)
#generate config.properties
set(DOCKER_PROPERTIES_FILE "${DOCKER_LOC}/${DOCKER_WORKDIR}/config.properties")
set(STAGE1_PROPERTIES_FILE "${CMAKE_BINARY_DIR}/celix/gen/${DOCKER_TARGET}-docker-config-stage1.properties")
file(GENERATE
OUTPUT "${STAGE1_PROPERTIES_FILE}"
CONTENT "cosgi.auto.start.1=$<JOIN:$<TARGET_PROPERTY:${DOCKER_TARGET},DOCKER_BUNDLES>, >
$<JOIN:$<TARGET_PROPERTY:${DOCKER_TARGET},DOCKER_PROPERTIES>,
>
"
)
file(GENERATE
OUTPUT "${DOCKER_PROPERTIES_FILE}"
INPUT "${STAGE1_PROPERTIES_FILE}"
)
if (DOCKER_BUNDLES)
celix_docker_bundles(${DOCKER_TARGET} ${DOCKER_BUNDLES})
endif()
if (DOCKER_PROPERTIES)
celix_docker_properties(${DOCKER_TARGET} ${DOCKER_PROPERTIES})
endif ()
if (DOCKER_INSTRUCTIONS)
celix_docker_instructions(${DOCKER_TARGET} ${DOCKER_INSTRUCTIONS})
endif ()
get_target_property(DEPS celix-build-docker-dirs "DOCKER_DEPS")
list(APPEND DEPS ${DOCKER_TARGET})
set_target_properties(celix-build-docker-dirs PROPERTIES "DOCKER_DEPS" "${DEPS}")
add_custom_target(celix-build-${DOCKER_TARGET}-docker-image
COMMAND cd $<TARGET_PROPERTY:${DOCKER_TARGET},DOCKER_LOC> && ${DOCKER_CMD} build -t "$<TARGET_PROPERTY:${DOCKER_TARGET},DOCKER_IMAGE_NAME>" .
DEPENDS ${DOCKERFILE} ${DOCKER_TARGET}
COMMENT "Creating docker image for target '${DOCKER_TARGET}'" VERBATIM
)
add_dependencies(celix-build-docker-images celix-build-${DOCKER_TARGET}-docker-image)
endfunction()
function(celix_docker_bundles)
#0 is docker TARGET
#1..n is bundles
list(GET ARGN 0 DOCKER_TARGET)
list(REMOVE_AT ARGN 0)
get_target_property(BUNDLES ${DOCKER_TARGET} "DOCKER_BUNDLES")
get_target_property(BUNDLES_DIR ${DOCKER_TARGET} "DOCKER_BUNDLES_DIR")
get_target_property(LOC ${DOCKER_TARGET} "DOCKER_LOC")
get_target_property(DEPS ${DOCKER_TARGET} "DOCKER_DEPS")
foreach(BUNDLE IN ITEMS ${ARGN})
if(IS_ABSOLUTE ${BUNDLE} AND EXISTS ${BUNDLE})
get_filename_component(BUNDLE_FILENAME ${BUNDLE} NAME)
list(APPEND BUNDLES "${BUNDLES_DIR}/${BUNDLE_FILENAME}")
set(OUT "${LOC}/${BUNDLES_DIR}/${BUNDLE_FILENAME}")
add_custom_command(OUTPUT ${OUT}
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${BUNDLE} ${OUT}
COMMENT "Copying bundle '${BUNDLE}' to '${OUT}'"
DEPENDS ${BUNDLE}
)
else() #assuming target
get_target_property(BFN ${BUNDLE} BUNDLE_FILE_NAME)
list(APPEND BUNDLES "${BUNDLES_DIR}/${BFN}")
set(OUT ${LOC}/${BUNDLES_DIR}/${BFN})
add_custom_command(OUTPUT ${OUT}
COMMAND ${CMAKE_COMMAND} -E copy_if_different "$<TARGET_PROPERTY:${BUNDLE},BUNDLE_FILE>" "${OUT}"
COMMENT "Copying bundle '${BUNDLE}' to '${OUT}'"
DEPENDS ${BUNDLE} ${BUNDLE}_bundle
)
endif()
list(APPEND DEPS "${OUT}")
endforeach()
set_target_properties(${DOCKER_TARGET} PROPERTIES "DOCKER_BUNDLES" "${BUNDLES}")
set_target_properties(${DOCKER_TARGET} PROPERTIES "DOCKER_DEPS" "${DEPS}")
endfunction()
function(celix_docker_properties)
#0 is docker TARGET
#1..n is properties
list(GET ARGN 0 DOCKER_TARGET)
list(REMOVE_AT ARGN 0)
get_target_property(PROPS ${DOCKER_TARGET} "DOCKER_PROPERTIES")
foreach(PROP IN ITEMS ${ARGN})
list(APPEND PROPS ${PROP})
endforeach()
set_target_properties(${DOCKER_TARGET} PROPERTIES "DOCKER_PROPERTIES" "${PROPS}")
endfunction()
function(celix_docker_instructions)
#0 is docker TARGET
#1..n is instructions
list(GET ARGN 0 DOCKER_TARGET)
list(REMOVE_AT ARGN 0)
get_target_property(INSTRUCTIONS ${DOCKER_TARGET} "DOCKER_INSTRUCTIONS")
foreach(INSTR IN ITEMS ${ARGN})
list(APPEND INSTRUCTIONS ${INSTR})
endforeach()
set_target_properties(${DOCKER_TARGET} PROPERTIES "DOCKER_INSTRUCTIONS" "${INSTRUCTIONS}")
endfunction()