cmake(android): refactor copying of Android samples project files

This commit is contained in:
Alexander Alekhin 2018-01-03 01:40:22 +00:00
parent 9966903ae1
commit 431b3b4323
4 changed files with 263 additions and 46 deletions

View File

@ -228,23 +228,16 @@ macro(add_android_project target path)
project(${target})
set(android_proj_bin_dir "${CMAKE_CURRENT_BINARY_DIR}/.build")
# get project sources
file(GLOB_RECURSE android_proj_files RELATIVE "${path}" "${path}/res/*" "${path}/src/*")
# project sources
set(__src_glob "${path}/res/*" "${path}/src/*")
if(NOT android_proj_IGNORE_MANIFEST)
list(APPEND android_proj_files ${ANDROID_MANIFEST_FILE})
list(APPEND __src_glob "${path}/${ANDROID_MANIFEST_FILE}")
endif()
# copy sources out from the build tree
set(android_proj_file_deps "")
foreach(f ${android_proj_files})
add_custom_command(
OUTPUT "${android_proj_bin_dir}/${f}"
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${path}/${f}" "${android_proj_bin_dir}/${f}"
MAIN_DEPENDENCY "${path}/${f}"
COMMENT "Copying ${f}")
list(APPEND android_proj_file_deps "${path}/${f}" "${android_proj_bin_dir}/${f}")
endforeach()
ocv_copyfiles_append_dir(SRC_COPY "${path}" "${android_proj_bin_dir}" ${__src_glob})
ocv_copyfiles_add_forced_target(${target}_copy_src SRC_COPY "Copy project sources: ${target}")
set(android_proj_file_deps ${target}_copy_src "${OPENCV_DEPHELPER}/${target}_copy_src")
set(android_proj_lib_deps_commands "")
set(android_proj_target_files ${ANDROID_PROJECT_FILES})
@ -261,10 +254,11 @@ macro(add_android_project target path)
add_custom_command(
OUTPUT ${android_proj_target_files}
COMMAND ${CMAKE_COMMAND} -E remove ${android_proj_target_files}
"${android_proj_bin_dir}/bin/${ANDROID_MANIFEST_FILE}" # avoid warning about sub-projects
COMMAND ${ANDROID_EXECUTABLE} --silent update project --path "${android_proj_bin_dir}" --target "${android_proj_sdk_target}" --name "${target}"
${android_proj_lib_deps_commands}
MAIN_DEPENDENCY "${android_proj_bin_dir}/${ANDROID_MANIFEST_FILE}"
DEPENDS "${path}/${ANDROID_MANIFEST_FILE}"
WORKING_DIRECTORY "${android_proj_bin_dir}"
DEPENDS ${android_proj_file_deps}
COMMENT "Updating Android project at ${path}. SDK target: ${android_proj_sdk_target}"
)
@ -272,7 +266,6 @@ macro(add_android_project target path)
# build native part
file(GLOB_RECURSE android_proj_jni_files "${path}/jni/*.c" "${path}/jni/*.h" "${path}/jni/*.cpp" "${path}/jni/*.hpp")
ocv_list_filterout(android_proj_jni_files "\\\\.svn")
if(android_proj_jni_files AND EXISTS ${path}/jni/Android.mk AND NOT DEFINED JNI_LIB_NAME)
# find local module name in Android.mk file to build native lib
@ -310,36 +303,44 @@ macro(add_android_project target path)
list(APPEND android_proj_extra_deps "${OpenCV_BINARY_DIR}/bin/classes.jar.dephelper" opencv_java)
endif()
add_custom_command(
OUTPUT "${android_proj_bin_dir}/bin/${target}-debug.apk"
COMMAND ${ANT_EXECUTABLE} -q -noinput -k debug -Djava.target=1.6 -Djava.source=1.6
COMMAND ${CMAKE_COMMAND} -E touch "${android_proj_bin_dir}/bin/${target}-debug.apk" # needed because ant does not update the timestamp of updated apk
WORKING_DIRECTORY "${android_proj_bin_dir}"
MAIN_DEPENDENCY "${android_proj_bin_dir}/${ANDROID_MANIFEST_FILE}"
DEPENDS ${android_proj_extra_deps} ${android_proj_file_deps} ${JNI_LIB_NAME})
OUTPUT "${android_proj_bin_dir}/bin/${target}-debug.apk"
COMMAND ${ANT_EXECUTABLE} -q -noinput -k debug -Djava.target=1.6 -Djava.source=1.6
COMMAND ${CMAKE_COMMAND} -E touch "${android_proj_bin_dir}/bin/${target}-debug.apk" # needed because ant does not update the timestamp of updated apk
WORKING_DIRECTORY "${android_proj_bin_dir}"
DEPENDS ${android_proj_extra_deps} ${android_proj_file_deps} ${JNI_LIB_NAME}
COMMENT "Generating ${target}-debug.apk"
)
unset(JNI_LIB_NAME)
add_custom_target(${target} ALL SOURCES "${android_proj_bin_dir}/bin/${target}-debug.apk" )
set(_native_deps "")
if(NOT android_proj_IGNORE_JAVA)
add_dependencies(${target} opencv_java)
set(_native_deps opencv_java)
endif()
if(android_proj_native_deps)
add_dependencies(${target} ${android_proj_native_deps})
list(APPEND _native_deps ${android_proj_native_deps})
endif()
if(_native_deps)
add_dependencies(${target} ${_native_deps})
endif()
if (android_proj_COPY_LIBS OR ANDROID_EXAMPLES_WITH_LIBS)
message(STATUS "Android project with libs: " ${target})
add_custom_target(
${target}_copy_libs
COMMAND ${CMAKE_COMMAND} -DSRC_DIR=${OpenCV_BINARY_DIR}/lib -DDST_DIR=${android_proj_bin_dir}/libs -P ${OpenCV_SOURCE_DIR}/cmake/copyAndroidLibs.cmake
WORKING_DIRECTORY ${OpenCV_BINARY_DIR}/lib
)
if((android_proj_COPY_LIBS OR ANDROID_EXAMPLES_WITH_LIBS) AND _native_deps)
message(STATUS "Android project with native libs: " ${target} " (" ${_native_deps} ")")
ocv_copyfiles_append_dir(NATIVE_COPY "${OpenCV_BINARY_DIR}/lib" "${android_proj_bin_dir}/libs" "${OpenCV_BINARY_DIR}/lib/*.so")
ocv_copyfiles_add_target(${target}_copy_libs NATIVE_COPY "Copy native libs for project: ${target}" ${_native_deps})
add_dependencies(${target} ${target}_copy_libs)
if (ANDROID_EXAMPLES_WITH_LIBS)
add_dependencies(${target}_copy_libs "${OpenCV_BINARY_DIR}/bin/classes.jar.dephelper" opencv_java)
add_dependencies(${target}_copy_libs opencv_java)
endif()
endif()
# There is some strange problem with concurrent Android .APK builds:
# <android-sdk>/tools/ant/build.xml:781: Problem reading <build_dir>/bin/classes.jar'
if(__android_project_chain)
add_dependencies(${target} ${__android_project_chain})
endif()
@ -361,11 +362,9 @@ FOREACH(f ${ANDROID_PROJECT_FILES})
ENDFOREACH()
" COMPONENT samples)
#java part
list(REMOVE_ITEM android_proj_files ${ANDROID_MANIFEST_FILE})
foreach(f ${android_proj_files} ${ANDROID_MANIFEST_FILE})
get_filename_component(install_subdir "${f}" PATH)
install(FILES "${android_proj_bin_dir}/${f}" DESTINATION "samples/${sample_dir}/${install_subdir}" COMPONENT samples)
endforeach()
install(DIRECTORY "${android_proj_bin_dir}/res" DESTINATION "samples/${sample_dir}" COMPONENT samples)
install(DIRECTORY "${android_proj_bin_dir}/src" DESTINATION "samples/${sample_dir}" COMPONENT samples)
install(FILES "${android_proj_bin_dir}/${ANDROID_MANIFEST_FILE}" DESTINATION "samples/${sample_dir}" COMPONENT samples)
#jni part + eclipse files
file(GLOB_RECURSE jni_files RELATIVE "${path}" "${path}/jni/*" "${path}/.cproject")
ocv_list_filterout(jni_files "\\\\.svn")

View File

@ -519,6 +519,45 @@ endmacro()
if(NOT DEFINED CMAKE_ARGC) # Guard CMake standalone invocations
# Use this option carefully, CMake's install() will install symlinks instead of real files
# It is fine for development, but should not be used by real installations
set(__symlink_default OFF) # preprocessing is required for old CMake like 2.8.12
if(DEFINED ENV{BUILD_USE_SYMLINKS})
set(__symlink_default $ENV{BUILD_USE_SYMLINKS})
endif()
OCV_OPTION(BUILD_USE_SYMLINKS "Use symlinks instead of files copying during build (and !!INSTALL!!)" (${__symlink_default}) IF (UNIX OR DEFINED __symlink_default))
if(CMAKE_VERSION VERSION_LESS "3.2")
macro(ocv_cmake_byproducts var_name)
set(${var_name}) # nothing
endmacro()
else()
macro(ocv_cmake_byproducts var_name)
set(${var_name} BYPRODUCTS ${ARGN})
endmacro()
endif()
set(OPENCV_DEPHELPER "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/dephelper" CACHE INTERNAL "")
file(MAKE_DIRECTORY ${OPENCV_DEPHELPER})
if(BUILD_USE_SYMLINKS)
set(__file0 "${CMAKE_CURRENT_LIST_FILE}")
set(__file1 "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/symlink_test")
if(NOT IS_SYMLINK "${__file1}")
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink "${__file0}" "${__file1}"
RESULT_VARIABLE SYMLINK_RESULT)
if(NOT SYMLINK_RESULT EQUAL 0)
file(REMOVE "${__file1}")
endif()
if(NOT IS_SYMLINK "${__file1}")
set(BUILD_USE_SYMLINKS 0 CACHE INTERNAL "")
endif()
endif()
if(NOT BUILD_USE_SYMLINKS)
message(STATUS "Build symlinks are not available (disabled)")
endif()
endif()
set(OPENCV_BUILD_INFO_STR "" CACHE INTERNAL "")
function(ocv_output_status msg)
message(STATUS "${msg}")
@ -1266,3 +1305,81 @@ set(${var_name} \"${${var_name}}\")
")
endforeach()
endmacro()
macro(ocv_copyfiles_append_file list_var src dst)
list(LENGTH ${list_var} __id)
list(APPEND ${list_var} ${__id})
set(${list_var}_SRC_${__id} "${src}")
set(${list_var}_DST_${__id} "${dst}")
endmacro()
macro(ocv_copyfiles_append_dir list_var src dst)
set(__glob ${ARGN})
list(LENGTH ${list_var} __id)
list(APPEND ${list_var} ${__id})
set(${list_var}_SRC_${__id} "${src}")
set(${list_var}_DST_${__id} "${dst}")
set(${list_var}_MODE_${__id} "COPYDIR")
if(__glob)
set(${list_var}_GLOB_${__id} ${__glob})
endif()
endmacro()
macro(ocv_copyfiles_make_config_string content_var list_var)
set(var_name "${list_var}")
set(${content_var} "${${content_var}}
set(${var_name} \"${${var_name}}\")
")
foreach(__id ${${list_var}})
set(${content_var} "${${content_var}}
set(${list_var}_SRC_${__id} \"${${list_var}_SRC_${__id}}\")
set(${list_var}_DST_${__id} \"${${list_var}_DST_${__id}}\")
")
if(DEFINED ${list_var}_MODE_${__id})
set(${content_var} "${${content_var}}set(${list_var}_MODE_${__id} \"${${list_var}_MODE_${__id}}\")\n")
endif()
if(DEFINED ${list_var}_GLOB_${__id})
set(${content_var} "${${content_var}}set(${list_var}_GLOB_${__id} \"${${list_var}_GLOB_${__id}}\")\n")
endif()
endforeach()
endmacro()
macro(ocv_copyfiles_make_config_file filename_var list_var)
ocv_copyfiles_make_config_string(${list_var}_CONFIG ${list_var})
set(${filename_var} "${CMAKE_CURRENT_BINARY_DIR}/copyfiles-${list_var}.cmake")
file(WRITE "${${filename_var}}" "${${list_var}_CONFIG}")
endmacro()
macro(ocv_copyfiles_add_forced_target target list_var comment_str)
ocv_copyfiles_make_config_file(CONFIG_FILE ${list_var})
ocv_cmake_byproducts(__byproducts BYPRODUCTS "${OPENCV_DEPHELPER}/${target}")
add_custom_target(${target}
${__byproducts} # required for add_custom_target() by ninja
COMMAND ${CMAKE_COMMAND}
"-DCONFIG_FILE:PATH=${CONFIG_FILE}"
"-DCOPYLIST_VAR:STRING=${list_var}"
"-DDEPHELPER=${OPENCV_DEPHELPER}/${target}"
-P "${OpenCV_SOURCE_DIR}/cmake/copy_files.cmake"
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
COMMENT "${comment_str}"
DEPENDS "${OpenCV_SOURCE_DIR}/cmake/copy_files.cmake"
# ninja warn about file(WRITE): "${SRC_COPY_CONFIG_FILE}"
)
endmacro()
macro(ocv_copyfiles_add_target target list_var comment_str)
set(deps ${ARGN})
ocv_copyfiles_make_config_file(CONFIG_FILE ${list_var})
add_custom_command(OUTPUT "${OPENCV_DEPHELPER}/${target}"
COMMAND ${CMAKE_COMMAND}
"-DCONFIG_FILE:PATH=${CONFIG_FILE}"
"-DCOPYLIST_VAR:STRING=${list_var}"
"-DDEPHELPER=${OPENCV_DEPHELPER}/${target}"
-P "${OpenCV_SOURCE_DIR}/cmake/copy_files.cmake"
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
COMMENT "${comment_str}"
DEPENDS "${OpenCV_SOURCE_DIR}/cmake/copy_files.cmake" ${deps}
# ninja warn about file(WRITE): "${SRC_COPY_CONFIG_FILE}"
)
add_custom_target(${target} DEPENDS "${OPENCV_DEPHELPER}/${target}")
endmacro()

View File

@ -1,8 +0,0 @@
# helper file for Android samples build
file(GLOB_RECURSE LIBS RELATIVE ${SRC_DIR} "*.so")
foreach(l ${LIBS})
message(STATUS " Copying: ${l} ...")
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different ${SRC_DIR}/${l} ${DST_DIR}/${l})
endforeach()

109
cmake/copy_files.cmake Normal file
View File

@ -0,0 +1,109 @@
include("${CONFIG_FILE}")
set(prefix "COPYFILES: ")
set(use_symlink 0)
if(IS_SYMLINK "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/symlink_test")
set(use_symlink 1)
endif()
set(update_dephelper 0)
if(DEFINED DEPHELPER AND NOT EXISTS "${DEPHELPER}")
set(update_dephelper 1)
endif()
set(__state "")
macro(copy_file_ src dst prefix)
string(REPLACE "${CMAKE_BINARY_DIR}/" "" dst_name "${dst}")
set(local_update 0)
if(NOT EXISTS "${dst}")
set(local_update 1)
endif()
if(use_symlink)
if(local_update OR NOT IS_SYMLINK "${dst}")
message("${prefix}Symlink: '${dst_name}' ...")
endif()
get_filename_component(target_path "${dst}" PATH)
file(MAKE_DIRECTORY "${target_path}")
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink ${src} ${dst}
RESULT_VARIABLE SYMLINK_RESULT)
if(NOT SYMLINK_RESULT EQUAL 0)
#message("Symlink failed, fallback to 'copy'")
set(use_symlink 0)
endif()
endif()
if(NOT use_symlink)
if("${src}" IS_NEWER_THAN "${dst}" OR IS_SYMLINK "${dst}")
file(REMOVE "${dst}") # configure_file(COPYONLY) doesn't update timestamp sometimes
set(local_update 1)
endif()
if(local_update)
message("${prefix}Copying: '${dst_name}' ...")
configure_file(${src} ${dst} COPYONLY)
else()
#message("${prefix}Up-to-date: '${dst_name}'")
endif()
endif()
if(local_update)
set(update_dephelper 1)
endif()
file(TIMESTAMP "${dst}" dst_t UTC)
set(__state "${__state}${dst_t} ${dst}\n")
endmacro()
if(NOT DEFINED COPYLIST_VAR)
set(COPYLIST_VAR "COPYLIST")
endif()
list(LENGTH ${COPYLIST_VAR} __length)
message("${prefix}... ${__length} entries (${COPYLIST_VAR})")
foreach(id ${${COPYLIST_VAR}})
set(src "${${COPYLIST_VAR}_SRC_${id}}")
set(dst "${${COPYLIST_VAR}_DST_${id}}")
if(NOT EXISTS ${src})
message(FATAL_ERROR "Source file/dir is missing: ${src} (${CONFIG_FILE})")
endif()
set(_mode "COPYFILE")
if(DEFINED ${COPYLIST_VAR}_MODE_${id})
set(_mode "${${COPYLIST_VAR}_MODE_${id}}")
endif()
if(_mode STREQUAL "COPYFILE")
#message("... COPY ${src} => ${dst}")
copy_file_("${src}" "${dst}" "${prefix} ")
elseif(_mode STREQUAL "COPYDIR")
get_filename_component(src_name "${src}" NAME)
get_filename_component(src_path "${src}" PATH)
get_filename_component(src_name2 "${src_path}" NAME)
set(src_glob "${src}/*")
if(DEFINED ${COPYLIST_VAR}_GLOB_${id})
set(src_glob "${${COPYLIST_VAR}_GLOB_${id}}")
endif()
file(GLOB_RECURSE _files RELATIVE "${src}" ${src_glob})
list(LENGTH _files __length)
message("${prefix} ... directory '.../${src_name2}/${src_name}' with ${__length} files")
foreach(f ${_files})
if(NOT EXISTS "${src}/${f}")
message(FATAL_ERROR "COPY ERROR: Source file is missing: ${src}/${f}")
endif()
copy_file_("${src}/${f}" "${dst}/${f}" "${prefix} ")
endforeach()
endif()
endforeach()
set(STATE_FILE "${CONFIG_FILE}.state")
if(EXISTS "${STATE_FILE}")
file(READ "${STATE_FILE}" __prev_state)
else()
set(__prev_state "")
endif()
if(NOT "${__state}" STREQUAL "${__prev_state}")
file(WRITE "${STATE_FILE}" "${__state}")
message("${prefix}Updated!")
set(update_dephelper 1)
endif()
if(NOT update_dephelper)
message("${prefix}All files are up-to-date.")
elseif(DEFINED DEPHELPER)
file(WRITE "${DEPHELPER}" "")
endif()