diff options
-rw-r--r-- | Help/command/macro.rst | 2 | ||||
-rw-r--r-- | Help/prop_sf/SKIP_PRECOMPILE_HEADERS.rst | 4 | ||||
-rw-r--r-- | Help/variable/CMAKE_CURRENT_FUNCTION.rst | 6 | ||||
-rw-r--r-- | Help/variable/CMAKE_CURRENT_FUNCTION_LIST_DIR.rst | 50 | ||||
-rw-r--r-- | Help/variable/CMAKE_CURRENT_FUNCTION_LIST_FILE.rst | 6 | ||||
-rw-r--r-- | Help/variable/CMAKE_CURRENT_FUNCTION_LIST_LINE.rst | 7 | ||||
-rw-r--r-- | Modules/FindCUDAToolkit.cmake | 22 | ||||
-rw-r--r-- | Modules/FindMPI.cmake | 6 | ||||
-rw-r--r-- | Modules/FindPython/Support.cmake | 18 | ||||
-rw-r--r-- | Modules/Platform/Darwin-Initialize.cmake | 87 | ||||
-rw-r--r-- | Source/cmFileCommand.cxx | 7 | ||||
-rw-r--r-- | Source/cmTarget.cxx | 7 |
12 files changed, 168 insertions, 54 deletions
diff --git a/Help/command/macro.rst b/Help/command/macro.rst index 3f6f2f9..008d049 100644 --- a/Help/command/macro.rst +++ b/Help/command/macro.rst @@ -95,7 +95,7 @@ Unlike a function, the :variable:`CMAKE_CURRENT_FUNCTION`, :variable:`CMAKE_CURRENT_FUNCTION_LIST_DIR`, :variable:`CMAKE_CURRENT_FUNCTION_LIST_FILE`, :variable:`CMAKE_CURRENT_FUNCTION_LIST_LINE` variables are not -set for macro. +set for a macro. .. _`Argument Caveats`: diff --git a/Help/prop_sf/SKIP_PRECOMPILE_HEADERS.rst b/Help/prop_sf/SKIP_PRECOMPILE_HEADERS.rst index 5f39f30..0031da3 100644 --- a/Help/prop_sf/SKIP_PRECOMPILE_HEADERS.rst +++ b/Help/prop_sf/SKIP_PRECOMPILE_HEADERS.rst @@ -6,8 +6,8 @@ Is this source file skipped by :prop_tgt:`PRECOMPILE_HEADERS` feature. This property helps with build problems that one would run into when using the :prop_tgt:`PRECOMPILE_HEADERS` feature. -One example would be the usage of Objective-C (*.m) files, and -Objective-C++ (*.mm) files, which lead to compilation failure +One example would be the usage of Objective-C (``*.m``) files, and +Objective-C++ (``*.mm``) files, which lead to compilation failure because they are treated (in case of Ninja / Makefile generator) as C, and CXX respectively. The precompile headers are not compatible between languages. diff --git a/Help/variable/CMAKE_CURRENT_FUNCTION.rst b/Help/variable/CMAKE_CURRENT_FUNCTION.rst index aa2936c..fb7f610 100644 --- a/Help/variable/CMAKE_CURRENT_FUNCTION.rst +++ b/Help/variable/CMAKE_CURRENT_FUNCTION.rst @@ -2,5 +2,9 @@ CMAKE_CURRENT_FUNCTION ---------------------- When executing code inside a :command:`function`, this variable -contains the name of the current function. It can be used for +contains the name of the current function. It can be useful for diagnostic or debug messages. + +See also :variable:`CMAKE_CURRENT_FUNCTION_LIST_DIR`, +:variable:`CMAKE_CURRENT_FUNCTION_LIST_FILE` and +:variable:`CMAKE_CURRENT_FUNCTION_LIST_LINE`. diff --git a/Help/variable/CMAKE_CURRENT_FUNCTION_LIST_DIR.rst b/Help/variable/CMAKE_CURRENT_FUNCTION_LIST_DIR.rst index 0119381..44ae1e5 100644 --- a/Help/variable/CMAKE_CURRENT_FUNCTION_LIST_DIR.rst +++ b/Help/variable/CMAKE_CURRENT_FUNCTION_LIST_DIR.rst @@ -2,32 +2,40 @@ CMAKE_CURRENT_FUNCTION_LIST_DIR ------------------------------- When executing code inside a :command:`function`, this variable -contains the full directory of the listfile defining the current function. +contains the full directory of the listfile that defined the current function. -It is quite common practice in CMake that modules use some additional files -(e.g., templates to render). And the code typically did the following: +It is quite common practice in CMake for modules to use some additional files, +such as templates to be copied in after substituting CMake variables. +In such cases, a function needs to know where to locate those files in a way +that doesn't depend on where the function is called. Without +``CMAKE_CURRENT_FUNCTION_LIST_DIR``, the code to do that would typically use +the following pattern: .. code-block:: cmake - :caption: Bad - set(_THIS_MODULE_BASE_DIR "${CMAKE_CURRENT_LIST_DIR}") + set(_THIS_MODULE_BASE_DIR "${CMAKE_CURRENT_LIST_DIR}") - function(foo) - configure_file( - "${_THIS_MODULE_BASE_DIR}/some.template.in" - some.output - ) - endfunction() + function(foo) + configure_file( + "${_THIS_MODULE_BASE_DIR}/some.template.in" + some.output + ) + endfunction() -Using this variable inside a function eliminates the neccessity of the -additional one with "global" scope: +Using ``CMAKE_CURRENT_FUNCTION_LIST_DIR`` inside the function instead +eliminates the need for the extra variable which would otherwise be visible +outside the function's scope. +The above example can be written in the more concise and more robust form: .. code-block:: cmake - :caption: Good - - function(foo) - configure_file( - "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/some.template.in" - some.output - ) - endfunction() + + function(foo) + configure_file( + "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/some.template.in" + some.output + ) + endfunction() + +See also :variable:`CMAKE_CURRENT_FUNCTION`, +:variable:`CMAKE_CURRENT_FUNCTION_LIST_FILE` and +:variable:`CMAKE_CURRENT_FUNCTION_LIST_LINE`. diff --git a/Help/variable/CMAKE_CURRENT_FUNCTION_LIST_FILE.rst b/Help/variable/CMAKE_CURRENT_FUNCTION_LIST_FILE.rst index d2c846a..c737af9 100644 --- a/Help/variable/CMAKE_CURRENT_FUNCTION_LIST_FILE.rst +++ b/Help/variable/CMAKE_CURRENT_FUNCTION_LIST_FILE.rst @@ -2,4 +2,8 @@ CMAKE_CURRENT_FUNCTION_LIST_FILE -------------------------------- When executing code inside a :command:`function`, this variable -contains the full path to the listfile declaring a current function. +contains the full path to the listfile that defined the current function. + +See also :variable:`CMAKE_CURRENT_FUNCTION`, +:variable:`CMAKE_CURRENT_FUNCTION_LIST_DIR` and +:variable:`CMAKE_CURRENT_FUNCTION_LIST_LINE`. diff --git a/Help/variable/CMAKE_CURRENT_FUNCTION_LIST_LINE.rst b/Help/variable/CMAKE_CURRENT_FUNCTION_LIST_LINE.rst index 5a7cd13..ad6282e 100644 --- a/Help/variable/CMAKE_CURRENT_FUNCTION_LIST_LINE.rst +++ b/Help/variable/CMAKE_CURRENT_FUNCTION_LIST_LINE.rst @@ -2,4 +2,9 @@ CMAKE_CURRENT_FUNCTION_LIST_LINE -------------------------------- When executing code inside a :command:`function`, this variable -contains the line number in the listfile where a current function has defined. +contains the line number in the listfile where the current function +was defined. + +See also :variable:`CMAKE_CURRENT_FUNCTION`, +:variable:`CMAKE_CURRENT_FUNCTION_LIST_DIR` and +:variable:`CMAKE_CURRENT_FUNCTION_LIST_FILE`. diff --git a/Modules/FindCUDAToolkit.cmake b/Modules/FindCUDAToolkit.cmake index 4b14ddc..de7e785 100644 --- a/Modules/FindCUDAToolkit.cmake +++ b/Modules/FindCUDAToolkit.cmake @@ -711,8 +711,15 @@ find_path(CUDAToolkit_INCLUDE_DIR # And find the CUDA Runtime Library libcudart find_library(CUDA_CUDART NAMES cudart - PATH_SUFFIXES lib64 lib64/stubs lib/x64 + PATH_SUFFIXES lib64 lib/x64 ) +if (NOT CUDA_CUDART) + find_library(CUDA_CUDART + NAMES cudart + PATH_SUFFIXES lib64/stubs lib/x64/stubs + ) +endif() + if (NOT CUDA_CUDART AND NOT CUDAToolkit_FIND_QUIETLY) message(STATUS "Unable to find cudart library.") endif() @@ -759,9 +766,20 @@ if(CUDAToolkit_FOUND) NAMES ${search_names} HINTS ${CUDAToolkit_LIBRARY_DIR} ENV CUDA_PATH - PATH_SUFFIXES nvidia/current lib64 lib64/stubs lib/x64 lib lib/stubs + PATH_SUFFIXES nvidia/current lib64 lib/x64 lib ${arg_EXTRA_PATH_SUFFIXES} ) + # Don't try any stub directories intil we have exhausted all other + # search locations. + if(NOT CUDA_${lib_name}_LIBRARY) + find_library(CUDA_${lib_name}_LIBRARY + NAMES ${search_names} + HINTS ${CUDAToolkit_LIBRARY_DIR} + ENV CUDA_PATH + PATH_SUFFIXES lib64/stubs lib/x64/stubs lib/stubs stubs + ) + endif() + mark_as_advanced(CUDA_${lib_name}_LIBRARY) if (NOT TARGET CUDA::${lib_name} AND CUDA_${lib_name}_LIBRARY) diff --git a/Modules/FindMPI.cmake b/Modules/FindMPI.cmake index 41e1d08..cdbb927 100644 --- a/Modules/FindMPI.cmake +++ b/Modules/FindMPI.cmake @@ -298,9 +298,9 @@ else() endif() # PGI compiler names -set(_MPI_PGI_C_COMPILER_NAMES mpipgcc mppgcc) -set(_MPI_PGI_CXX_COMPILER_NAMES mpipgCC mppgCC) -set(_MPI_PGI_Fortran_COMPILER_NAMES mpipgf95 mpipgf90 mppgf95 mppgf90 mpipgf77 mppgf77) +set(_MPI_PGI_C_COMPILER_NAMES mpipgicc mpipgcc mppgcc) +set(_MPI_PGI_CXX_COMPILER_NAMES mpipgic++ mpipgCC mppgCC) +set(_MPI_PGI_Fortran_COMPILER_NAMES mpipgifort mpipgf95 mpipgf90 mppgf95 mppgf90 mpipgf77 mppgf77) # XLC MPI Compiler names set(_MPI_XL_C_COMPILER_NAMES mpxlc mpxlc_r mpixlc mpixlc_r) diff --git a/Modules/FindPython/Support.cmake b/Modules/FindPython/Support.cmake index 6bd10b3..0581145 100644 --- a/Modules/FindPython/Support.cmake +++ b/Modules/FindPython/Support.cmake @@ -440,7 +440,7 @@ function (_PYTHON_GET_VERSION) set (${_PGV_PREFIX}VERSION_PATCH ${version_patch} PARENT_SCOPE) # compute ABI flags - if (version_major VERSION_GREATER 2) + if (version_major VERSION_GREATER "2") file (STRINGS "${_${_PYTHON_PREFIX}_INCLUDE_DIR}/pyconfig.h" config REGEX "(Py_DEBUG|WITH_PYMALLOC|Py_UNICODE_SIZE|MS_WIN32)") set (abi) if (config MATCHES "#[ ]*define[ ]+MS_WIN32") @@ -813,7 +813,7 @@ endif() # Set ABIs to search ## default: search any ABI -if (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR VERSION_LESS 3) +if (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR VERSION_LESS "3") # ABI not supported unset (_${_PYTHON_PREFIX}_FIND_ABI) set (_${_PYTHON_PREFIX}_ABIFLAGS "") @@ -1399,7 +1399,7 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) unset (${_PYTHON_PREFIX}_SITEARCH) endif() - if (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR VERSION_GREATER_EQUAL 3) + if (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR VERSION_GREATER_EQUAL "3") _python_get_config_var (${_PYTHON_PREFIX}_SOABI SOABI) endif() @@ -1587,7 +1587,7 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) if (_${_PYTHON_PREFIX}_COMPILER AND _${_PYTHON_PREFIX}_COMPILER_USABLE) if (${_PYTHON_PREFIX}_Interpreter_FOUND) # Compiler must be compatible with interpreter - if (${_${_PYTHON_PREFIX}_VERSION_MAJOR}.${_${_PYTHON_PREFIX}_VERSION_MINOR} VERSION_EQUAL ${${_PYTHON_PREFIX}_VERSION_MAJOR}.${${_PYTHON_PREFIX}_VERSION_MINOR}) + if ("${_${_PYTHON_PREFIX}_VERSION_MAJOR}.${_${_PYTHON_PREFIX}_VERSION_MINOR}" VERSION_EQUAL "${${_PYTHON_PREFIX}_VERSION_MAJOR}.${${_PYTHON_PREFIX}_VERSION_MINOR}") set (${_PYTHON_PREFIX}_Compiler_FOUND TRUE) endif() elseif (${_PYTHON_PREFIX}_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR) @@ -2224,7 +2224,7 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS _python_get_version (INCLUDE PREFIX _${_PYTHON_PREFIX}_INC_) # update versioning - if (_${_PYTHON_PREFIX}_INC_VERSION VERSION_EQUAL ${_${_PYTHON_PREFIX}_VERSION}) + if (_${_PYTHON_PREFIX}_INC_VERSION VERSION_EQUAL _${_PYTHON_PREFIX}_VERSION) set (_${_PYTHON_PREFIX}_VERSION_PATCH ${_${_PYTHON_PREFIX}_INC_VERSION_PATCH}) endif() endif() @@ -2266,12 +2266,12 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE AND _${_PYTHON_PREFIX}_INCLUDE_DIR) if (${_PYTHON_PREFIX}_Interpreter_FOUND OR ${_PYTHON_PREFIX}_Compiler_FOUND) # development environment must be compatible with interpreter/compiler - if (${_${_PYTHON_PREFIX}_VERSION_MAJOR}.${_${_PYTHON_PREFIX}_VERSION_MINOR} VERSION_EQUAL ${${_PYTHON_PREFIX}_VERSION_MAJOR}.${${_PYTHON_PREFIX}_VERSION_MINOR} - AND ${_${_PYTHON_PREFIX}_INC_VERSION_MAJOR}.${_${_PYTHON_PREFIX}_INC_VERSION_MINOR} VERSION_EQUAL ${_${_PYTHON_PREFIX}_VERSION_MAJOR}.${_${_PYTHON_PREFIX}_VERSION_MINOR}) + if ("${_${_PYTHON_PREFIX}_VERSION_MAJOR}.${_${_PYTHON_PREFIX}_VERSION_MINOR}" VERSION_EQUAL "${${_PYTHON_PREFIX}_VERSION_MAJOR}.${${_PYTHON_PREFIX}_VERSION_MINOR}" + AND "${_${_PYTHON_PREFIX}_INC_VERSION_MAJOR}.${_${_PYTHON_PREFIX}_INC_VERSION_MINOR}" VERSION_EQUAL "${_${_PYTHON_PREFIX}_VERSION_MAJOR}.${_${_PYTHON_PREFIX}_VERSION_MINOR}") set (${_PYTHON_PREFIX}_Development_FOUND TRUE) endif() elseif (${_PYTHON_PREFIX}_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR - AND ${_${_PYTHON_PREFIX}_INC_VERSION_MAJOR}.${_${_PYTHON_PREFIX}_INC_VERSION_MINOR} VERSION_EQUAL ${_${_PYTHON_PREFIX}_VERSION_MAJOR}.${_${_PYTHON_PREFIX}_VERSION_MINOR}) + AND "${_${_PYTHON_PREFIX}_INC_VERSION_MAJOR}.${_${_PYTHON_PREFIX}_INC_VERSION_MINOR}" VERSION_EQUAL "${_${_PYTHON_PREFIX}_VERSION_MAJOR}.${_${_PYTHON_PREFIX}_VERSION_MINOR}") set (${_PYTHON_PREFIX}_Development_FOUND TRUE) endif() if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI AND @@ -2281,7 +2281,7 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS endif() endif() - if (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR VERSION_GREATER_EQUAL 3 + if (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR VERSION_GREATER_EQUAL "3" AND NOT DEFINED ${_PYTHON_PREFIX}_SOABI) _python_get_config_var (${_PYTHON_PREFIX}_SOABI SOABI) endif() diff --git a/Modules/Platform/Darwin-Initialize.cmake b/Modules/Platform/Darwin-Initialize.cmake index 80e668e..80e9a40 100644 --- a/Modules/Platform/Darwin-Initialize.cmake +++ b/Modules/Platform/Darwin-Initialize.cmake @@ -133,6 +133,80 @@ function(_apple_resolve_sdk_path sdk_name ret) ) set(${ret} "${_stdout}" PARENT_SCOPE) endfunction() + +function(_apple_resolve_supported_archs_for_sdk_from_system_lib sdk_path ret ret_failed) + # Detect the supported SDK architectures by inspecting the main libSystem library. + set(common_lib_prefix "${sdk_path}/usr/lib/libSystem") + set(system_lib_dylib_path "${common_lib_prefix}.dylib") + set(system_lib_tbd_path "${common_lib_prefix}.tbd") + + # Newer SDKs ship text based dylib stub files which contain the architectures supported by the + # library in text form. + if(EXISTS "${system_lib_tbd_path}") + file(STRINGS "${system_lib_tbd_path}" tbd_lines REGEX "^archs: +\\[.+\\]") + if(NOT tbd_lines) + set(${ret_failed} TRUE PARENT_SCOPE) + return() + endif() + + # The tbd architectures line looks like the following: + # archs: [ armv7, armv7s, arm64, arm64e ] + list(GET tbd_lines 0 first_arch_line) + string(REGEX REPLACE + "archs: +\\[ (.+) \\]" "\\1" arches_comma_separated "${first_arch_line}") + string(STRIP "${arches_comma_separated}" arches_comma_separated) + string(REPLACE "," ";" arch_list "${arches_comma_separated}") + string(REPLACE " " "" arch_list "${arch_list}") + if(NOT arch_list) + set(${ret_failed} TRUE PARENT_SCOPE) + return() + endif() + set(${ret} "${arch_list}" PARENT_SCOPE) + elseif(EXISTS "${system_lib_dylib_path}") + # Old SDKs (Xcode < 7) ship dylib files, use lipo to inspect the supported architectures. + # Can't use -archs because the option is not available in older Xcode versions. + execute_process( + COMMAND lipo -info ${system_lib_dylib_path} + OUTPUT_VARIABLE lipo_output + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_VARIABLE _stderr + RESULT_VARIABLE _failed + ) + if(_failed OR NOT lipo_output OR NOT lipo_output MATCHES "(Non-fat file:|Architectures in the fat file:)") + set(${ret_failed} TRUE PARENT_SCOPE) + return() + endif() + + # The lipo output looks like the following: + # Non-fat file: <path> is architecture: i386 + # Architectures in the fat file: <path> are: i386 x86_64 + string(REGEX REPLACE + "^(.+)is architecture:(.+)" "\\2" arches_space_separated "${lipo_output}") + string(REGEX REPLACE + "^(.+)are:(.+)" "\\2" arches_space_separated "${arches_space_separated}") + + # Need to clean up the arches, with Xcode 4.6.3 the output of lipo -info contains some + # additional info, e.g. + # Architectures in the fat file: <path> are: armv7 (cputype (12) cpusubtype (11)) + string(REGEX REPLACE + "\\(.+\\)" "" arches_space_separated "${arches_space_separated}") + + # The output is space separated. + string(STRIP "${arches_space_separated}" arches_space_separated) + string(REPLACE " " ";" arch_list "${arches_space_separated}") + + if(NOT arch_list) + set(${ret_failed} TRUE PARENT_SCOPE) + return() + endif() + set(${ret} "${arch_list}" PARENT_SCOPE) + else() + # This shouldn't happen, but keep it for safety. + message(WARNING "No way to find architectures for given sdk_path '${sdk_path}'") + set(${ret_failed} TRUE PARENT_SCOPE) + endif() +endfunction() + # Handle multi-arch sysroots. Do this before CMAKE_OSX_SYSROOT is # transformed into a path, so that we know the sysroot name. function(_apple_resolve_multi_arch_sysroots) @@ -166,13 +240,8 @@ function(_apple_resolve_multi_arch_sysroots) continue() endif() - execute_process( - COMMAND plutil -extract SupportedTargets.${sdk}.Archs json ${_sdk_path}/SDKSettings.plist -o - - OUTPUT_VARIABLE _sdk_archs_json - OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_VARIABLE _stderr - RESULT_VARIABLE _failed - ) + _apple_resolve_supported_archs_for_sdk_from_system_lib(${_sdk_path} _sdk_archs _failed) + if(_failed) # Failure to extract supported architectures for an SDK means that the installed SDK is old # and does not provide such information (SDKs that come with Xcode >= 10.x started providing @@ -181,10 +250,6 @@ function(_apple_resolve_multi_arch_sysroots) return() endif() - # Poor man's JSON decoding - string(REGEX REPLACE "[]\\[\"]" "" _sdk_archs ${_sdk_archs_json}) - string(REPLACE "," ";" _sdk_archs ${_sdk_archs}) - set(_sdk_archs_${sdk} ${_sdk_archs}) set(_sdk_path_${sdk} ${_sdk_path}) endforeach() diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 79110ab..e36abdc 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -2051,6 +2051,13 @@ bool HandleUploadCommand(std::vector<std::string> const& args, cmFileCommandCurlDebugCallback); check_curl_result(res, "UPLOAD cannot set debug function: "); + // make sure default CAInfo is set + std::string const& cainfo_err = cmCurlSetCAInfo(curl, nullptr); + if (!cainfo_err.empty()) { + status.SetError(cainfo_err); + return false; + } + cmFileCommandVectorOfChar chunkResponse; cmFileCommandVectorOfChar chunkDebug; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 97d7fce..1ad9fd1 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -238,8 +238,11 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, !impl->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX").empty(); // Check whether we are targeting AIX. - impl->IsAIX = - (impl->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME") == "AIX"); + { + std::string const& systemName = + impl->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME"); + impl->IsAIX = (systemName == "AIX" || systemName == "OS400"); + } // Check whether we are targeting an Android platform. impl->IsAndroid = |