Merge branch 'release-4.0'
[kiteware-cmake.git] / Modules / AndroidTestUtilities / PushToAndroidDevice.cmake
blob306181ded920fb8d1947e5f1a50e1508f73ea19a
1 # Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2 # file Copyright.txt or https://cmake.org/licensing for details.
4 # This function handles pushing all of the test files needed to the device.
5 # It places the data files in the object store and makes links to them from
6 # the appropriate directories.
8 # This function accepts the following named parameters:
9 # DIRS          : one or more directories needed for testing.
10 # FILES         : one or more files needed for testing.
11 # LIBS          : one or more libraries needed for testing.
12 # DIRS_DEST     : specify where the directories should be installed.
13 # FILES_DEST    : specify where the files should be installed.
14 # LIBS_DEST     : specify where the libraries should be installed.
15 # DEV_OBJ_STORE : specify where the actual data files should be placed.
16 # DEV_TEST_DIR  : specify the root file for the module test directory.
17 # The DEV_OBJ_STORE and DEV_TEST_DIR variables are required.
19 # The parameters to this function should be set to the list of directories,
20 # files, and libraries that need to be installed prior to testing.
21 function(android_push_test_files_to_device)
23   # The functions in the module need the adb executable.
24   find_program(adb_executable adb)
25   if(NOT adb_executable)
26     message(FATAL_ERROR "could not find adb")
27   endif()
29   function(execute_adb_command)
30     execute_process(COMMAND ${adb_executable} ${ARGN} RESULT_VARIABLE res_var OUTPUT_VARIABLE out_var ERROR_VARIABLE err_var)
31     set(out_var ${out_var} PARENT_SCOPE)
32     if(res_var)
33       string(REGEX REPLACE ";" " " com "${ARGN}")
34       message(FATAL_ERROR "Error occurred during adb command: adb ${com}\nError: ${err_var}.")
35     endif()
36   endfunction()
38   # Checks to make sure that a given file exists on the device. If it does,
39   # if(file_exists) will return true.
40   macro(check_device_file_exists device_file file_exists)
41     set(${file_exists} "")
42     execute_process(
43       COMMAND ${adb_executable} shell ls ${device_file}
44       OUTPUT_VARIABLE out_var ERROR_VARIABLE out_var)
45     if(NOT out_var) # when a directory exists but is empty the output is empty
46       set(${file_exists} "YES")
47     else()
48       string(FIND ${out_var} "No such file or directory" no_file_exists)
49       if(${no_file_exists} STREQUAL "-1") # -1 means the file exists
50         set(${file_exists} "YES")
51       endif()
52     endif()
53   endmacro()
55   # Checks to see if a filename matches a regex.
56   function(filename_regex filename reg_ex)
57     string(REGEX MATCH ${reg_ex} filename_match ${filename})
58     set(filename_match ${filename_match} PARENT_SCOPE)
59   endfunction()
61   # If a file with given name exists in the CMAKE_BINARY_DIR then use that file.
62   # Otherwise use the file with root in CMAKE_CURRENT_SOURCE_DIR.
63   macro(set_absolute_path relative_path absolute_path)
64     set(${absolute_path} ${arg_src_dir}/${relative_path})
65     if(EXISTS ${CMAKE_BINARY_DIR}/${relative_path})
66       set(${absolute_path} ${CMAKE_BINARY_DIR}/${relative_path})
67     endif()
68     if(NOT EXISTS ${${absolute_path}})
69       if(EXISTS ${relative_path})
70         set(${absolute_path} ${relative_path})
71       else()
72         message(FATAL_ERROR "Cannot find file for specified path: ${relative_path}")
73       endif()
74     endif()
75   endmacro()
77   # This function pushes the data into the device object store and
78   # creates a link to that data file in a specified location.
79   #
80   # This function requires the following un-named parameters:
81   # data_path        : absolute path to data to load into dev obj store.
82   # dev_object_store : absolute path to the device object store directory.
83   # link_origin      : absolute path to the origin of the link to the dev obj store data file.
84   function(push_and_link data_path dev_object_store link_origin)
85     file(SHA1 ${data_path} hash_val)
86     set(obj_store_dst ${dev_object_store}/${hash_val})
87     check_device_file_exists(${obj_store_dst} obj_store_file_exists)
88     # TODO: Verify that the object store file is indeed hashed correctly. Could use md5.
89     if(NOT obj_store_file_exists)
90       execute_adb_command(push ${data_path} ${obj_store_dst})
91     endif()
92     check_device_file_exists(${link_origin} link_exists)
93     if(link_exists)
94       execute_adb_command(shell rm -f ${link_origin})
95     endif()
96     foreach(ex ${arg_no_link_regex})
97       filename_regex(${data_path} ${ex})
98       list(APPEND match_ex ${filename_match})
99     endforeach()
100     if(match_ex)
101       execute_adb_command(shell cp ${obj_store_dst} ${link_origin})
102     else()
103       execute_adb_command(shell ln -s ${obj_store_dst} ${link_origin})
104     endif()
105   endfunction()
107   #----------------------------------------------------------------------------
108   #--------------------Beginning of actual function----------------------------
109   #----------------------------------------------------------------------------
110   set(oneValueArgs FILES_DEST LIBS_DEST DEV_TEST_DIR DEV_OBJ_STORE)
111   set(multiValueArgs FILES LIBS)
112   cmake_parse_arguments(_arg "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
114   # Setup of object store and test dir.
115   check_device_file_exists(${_arg_DEV_OBJ_STORE} dev_obj_store_exists)
116   if(NOT dev_obj_store_exists)
117     execute_adb_command(shell mkdir -p ${_arg_DEV_OBJ_STORE})
118   endif()
119   check_device_file_exists(${_arg_DEV_TEST_DIR} test_dir_exists)
120   if(test_dir_exists)
121     # This is protected in the SetupProjectTests module.
122     execute_adb_command(shell rm -r ${_arg_DEV_TEST_DIR})
123   endif()
124   execute_adb_command(shell mkdir -p ${_arg_DEV_TEST_DIR})
126   # Looping over the various types of test data possible.
127   foreach(TYPE ${multiValueArgs})
128     if(_arg_${TYPE})
130       # determine if the data type destination has been explicitly specified.
131       if(_arg_${TYPE}_DEST)
132         set(dest ${_arg_${TYPE}_DEST})
133       else()
134         if(${TYPE} STREQUAL LIBS)
135           set(dest ${_arg_DEV_TEST_DIR}/lib)
136         else()
137           set(dest ${_arg_DEV_TEST_DIR})
138         endif()
139       endif()
140       execute_adb_command(shell mkdir -p ${dest})
142       # Loop over the files passed in
143       foreach(relative_path ${_arg_${TYPE}})
144         # The absolute path can be through the source directory or the build directory.
145         # If the file/dir exists in the build directory that version is chosen.
146         set_absolute_path(${relative_path} absolute_path)
147         # Need to transfer all data files in the data directories to the device
148         # except those explicitly ignored.
149         if(${TYPE} STREQUAL FILES)
150           get_filename_component(file_dir ${relative_path} DIRECTORY)
151           # dest was determined earlier, relative_path is a dir, file is path from relative path to a data
152           set(cur_dest ${dest}/${relative_path})
153           set(on_dev_dir ${dest}/${file_dir})
154           execute_adb_command(shell mkdir -p ${on_dev_dir})
155           if(IS_SYMLINK ${absolute_path})
156             get_filename_component(real_data_origin ${absolute_path} REALPATH)
157             push_and_link(${real_data_origin} ${_arg_DEV_OBJ_STORE} ${cur_dest})
158           else()
159             push_and_link(${absolute_path} ${_arg_DEV_OBJ_STORE} ${cur_dest})
160           endif()
161         else() # LIBS
162           execute_adb_command(push ${absolute_path} ${dest})
163         endif()
164       endforeach()
165     endif()
166   endforeach()
167 endfunction()
169 android_push_test_files_to_device(
170   FILES_DEST ${arg_files_dest}
171   LIBS_DEST ${arg_libs_dest}
172   DEV_TEST_DIR ${arg_dev_test_dir}
173   DEV_OBJ_STORE ${arg_dev_obj_store}
174   FILES ${arg_files}
175   LIBS ${arg_libs}
176   )