Repository: mesonbuild/meson

Issue:
Issue with env CMAKE_PREFIX_PATH and the host’s native path separator
**Describe the bug**
Building a project which dependencies ([libigl](https://github.com/libigl/libigl) and [alembic](https://github.com/alembic/alembic)) only provides cmake config files. They add their cmake path to the CMAKE_PREFIX_PATH environment variable using the host's native path separator (`:` in my case). Other projects that are using pure cmake finds these just fine. But meson can only find them separately, i.e. if only one of them is listed.

It will work if I change the separator to a `;`, then it will find both. Reading the cmake docs, [CMAKE_PREFIX_PATH](https://cmake.org/cmake/help/v3.17/variable/CMAKE_PREFIX_PATH.html) is defined as a semicolon-separated list. But reading the [search-procedure](https://cmake.org/cmake/help/v3.17/command/find_package.html#search-procedure) in the find-package documentation it looks like it is both. I.e. CMAKE_PREFIX_PATH defined from the commandline by `-D` or in a CMakeLists.txt is semicolon-separated, the environment variant of it is host specific (`:` for unix and `;` for windows).

Digging through the logs, it looks like meson does not take this in to consideration.

E.g. a snippet from the `CMakeLists.txt` meson generates when searching for alembic
```cmake
list(APPEND TMP_PATHS_LIST ${CMAKE_PREFIX_PATH})
#...
list(APPEND TMP_PATHS_LIST $ENV{CMAKE_PREFIX_PATH})
#...
```
**To Reproduce**

This is simplified version of the command I'm using:
```
 CMAKE_PREFIX_PATH=$LIBIGL_PACKAGE_ROOT/share/libigl/cmake:$ALEMBIC_LIBRARY_PATH/cmake/Alembic meson build -Dbuildtype=release
```
Where `LIBIGL_PACKAGE_ROOT`  contains the path to where the libigl package is installed (e.g. `/home/plattfot/libigl/2.0.0`) and `ALEMBIC_LIBRARY_PATH` contains the library path (e.g. `/home/plattfot/alembic/1.7.7/lib`). 

And the simplified meson.build file:
```
project('cmake-issue')
alembic_dep = dependency('Alembic', include_type: 'system')
igl_dep = dependency('libigl', modules: ['igl::core'], include_type: 'system')
```
Here follows some examples where it managed to find one of them or both.

This will find alembic, but fail to find libigl:
```
 CMAKE_PREFIX_PATH=$ALEMBIC_LIBRARY_PATH/cmake/Alembic  meson build -Dbuildtype=release
```

This will find libigl, but fail to find alembic (Need to change the order in the `meson.build`):
```
 CMAKE_PREFIX_PATH=$LIBIGL_PACKAGE_ROOT/share/libigl/cmake meson build -Dbuildtype=release
```

And this will find both, note changed the `:` to a `;`:
```
 CMAKE_PREFIX_PATH="$LIBIGL_PACKAGE_ROOT/share/libigl/cmake;$ALEMBIC_LIBRARY_PATH/cmake/Alembic" meson build -Dbuildtype=release
```
And is the current one I'm using to workaround the issue.

**Expected behavior**
Expect meson to find the dependencies with the colon separated environment variable `CMAKE_PREFIX_PATH`. As that is the behavior when using pure cmake.

**system parameters**
* Is this a [cross build](https://mesonbuild.com/Cross-compilation.html) or just a plain native build (for the same computer)?
native build
* what operating system (e.g. MacOS Catalina, Windows 10, CentOS 8.0, Ubuntu 18.04, etc.)
cent6 with non standard install of dependencies
* what Python version are you using e.g. 3.8.0
python-3.7.4
* what `meson --version`
0.54.2
* what `ninja --version` if it's a Ninja build
1.9.0


Discussion:

Resolving patch:
diff --git a/mesonbuild/cmake/executor.py b/mesonbuild/cmake/executor.py
--- a/mesonbuild/cmake/executor.py
+++ b/mesonbuild/cmake/executor.py
@@ -69,7 +69,7 @@ def __init__(self, environment: Environment, version: str, for_machine: MachineC
             self.environment.is_cross_build(),
             'CMAKE_PREFIX_PATH')
         if env_pref_path is not None:
-            env_pref_path = env_pref_path.split(os.pathsep)
+            env_pref_path = re.split(r':|;', env_pref_path)
             env_pref_path = [x for x in env_pref_path if x]  # Filter out empty strings
             if not self.prefix_paths:
                 self.prefix_paths = []
diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py
--- a/mesonbuild/dependencies/base.py
+++ b/mesonbuild/dependencies/base.py
@@ -1137,12 +1137,17 @@ def _get_cmake_info(self):
         except MesonException:
             return None
 
+        def process_paths(l: T.List[str]) -> T.Set[str]:
+            l = [x.split(':') for x in l]
+            l = [x for sublist in l for x in sublist]
+            return set(l)
+
         # Extract the variables and sanity check them
-        root_paths = set(temp_parser.get_cmake_var('MESON_FIND_ROOT_PATH'))
-        root_paths.update(set(temp_parser.get_cmake_var('MESON_CMAKE_SYSROOT')))
+        root_paths = process_paths(temp_parser.get_cmake_var('MESON_FIND_ROOT_PATH'))
+        root_paths.update(process_paths(temp_parser.get_cmake_var('MESON_CMAKE_SYSROOT')))
         root_paths = sorted(root_paths)
         root_paths = list(filter(lambda x: os.path.isdir(x), root_paths))
-        module_paths = set(temp_parser.get_cmake_var('MESON_PATHS_LIST'))
+        module_paths = process_paths(temp_parser.get_cmake_var('MESON_PATHS_LIST'))
         rooted_paths = []
         for j in [Path(x) for x in root_paths]:
             for i in [Path(x) for x in module_paths]:


Test patch:
diff --git a/run_project_tests.py b/run_project_tests.py
--- a/run_project_tests.py
+++ b/run_project_tests.py
@@ -438,7 +438,10 @@ def validate_output(test: TestDef, stdo: str, stde: str) -> str:
 # coded to run as a batch process.
 def clear_internal_caches():
     import mesonbuild.interpreterbase
+    from mesonbuild.dependencies import CMakeDependency
+    from mesonbuild.mesonlib import PerMachine
     mesonbuild.interpreterbase.FeatureNew.feature_registry = {}
+    CMakeDependency.class_cmakeinfo = PerMachine(None, None)
 
 def run_test_inprocess(testdir):
     old_stdout = sys.stdout
diff --git a/test cases/linuxlike/13 cmake dependency/cmake_fake1/cmMesonTestF1Config.cmake b/test cases/linuxlike/13 cmake dependency/cmake_fake1/cmMesonTestF1Config.cmake
new file mode 100644
--- /dev/null
+++ b/test cases/linuxlike/13 cmake dependency/cmake_fake1/cmMesonTestF1Config.cmake	
@@ -0,0 +1,9 @@
+find_package(ZLIB)
+
+if(ZLIB_FOUND OR ZLIB_Found)
+  set(cmMesonTestF1_FOUND        ON)
+  set(cmMesonTestF1_LIBRARIES    ${ZLIB_LIBRARY})
+  set(cmMesonTestF1_INCLUDE_DIRS ${ZLIB_INCLUDE_DIR})
+else()
+  set(cmMesonTestF1_FOUND       OFF)
+endif()
diff --git a/test cases/linuxlike/13 cmake dependency/cmake_fake2/cmMesonTestF2Config.cmake b/test cases/linuxlike/13 cmake dependency/cmake_fake2/cmMesonTestF2Config.cmake
new file mode 100644
--- /dev/null
+++ b/test cases/linuxlike/13 cmake dependency/cmake_fake2/cmMesonTestF2Config.cmake	
@@ -0,0 +1,9 @@
+find_package(ZLIB)
+
+if(ZLIB_FOUND OR ZLIB_Found)
+  set(cmMesonTestF2_FOUND        ON)
+  set(cmMesonTestF2_LIBRARIES    ${ZLIB_LIBRARY})
+  set(cmMesonTestF2_INCLUDE_DIRS ${ZLIB_INCLUDE_DIR})
+else()
+  set(cmMesonTestF2_FOUND       OFF)
+endif()
diff --git a/test cases/linuxlike/13 cmake dependency/meson.build b/test cases/linuxlike/13 cmake dependency/meson.build
--- a/test cases/linuxlike/13 cmake dependency/meson.build	
+++ b/test cases/linuxlike/13 cmake dependency/meson.build	
@@ -44,6 +44,8 @@ assert(depf2.found() == false, 'Invalid CMake targets should fail')
 # Try to find cmMesonTestDep in a custom prefix
 # setup_env.json is used by run_project_tests.py:_run_test to point to ./cmake_pref_env/
 depPrefEnv = dependency('cmMesonTestDep', required : true, method : 'cmake')
+depPrefEnv1 = dependency('cmMesonTestF1', required : true, method : 'cmake')
+depPrefEnv2 = dependency('cmMesonTestF2', required : true, method : 'cmake')
 
 # Try to find a dependency with a custom CMake module
 
diff --git a/test cases/linuxlike/13 cmake dependency/test.json b/test cases/linuxlike/13 cmake dependency/test.json
--- a/test cases/linuxlike/13 cmake dependency/test.json	
+++ b/test cases/linuxlike/13 cmake dependency/test.json	
@@ -1,5 +1,5 @@
 {
   "env": {
-    "CMAKE_PREFIX_PATH": "@ROOT@/cmake_pref_env"
+    "CMAKE_PREFIX_PATH": "@ROOT@/cmake_fake1;@ROOT@/cmake_fake2:@ROOT@/cmake_pref_env"
   }
 }