Repository: mesonbuild/meson

Issue:
Missing LINK_ARGS -framework for OpenCL run-time dependency tries to link a directory
Looks like it's attempting to link a directory instead of referencing the framework:
```
ld: can't map file, errno=22 file '/System/Library/Frameworks/OpenCL.framework' for architecture x86_64
```

In https://github.com/LeelaChessZero/lc0/issues/972 I bisected meson finding two changes that seemed to change the build.ninja line for LINK_ARGS.

0.51.0:
```
-L/usr/local/opt/openssl/lib
-Wl,-dead_strip_dylibs
/usr/local/Cellar/protobuf/3.10.0/lib/libprotobuf.dylib
-lpthread
-F/System/Library/Frameworks
-framework
Accelerate
-F/System/Library/Frameworks
-framework
OpenCL
/usr/lib/libz.dylib
-Wl,-headerpad_max_install_names
-Wl,-rpath,/usr/local/Cellar/protobuf/3.10.0/lib
-Wl,-rpath,/usr/lib
```
(Has `-framework OpenCL`)

After https://github.com/mesonbuild/meson/commit/5bd21a96b89efc5fe96025398151dcbce34345ac
```
-L/usr/local/opt/openssl/lib
-Wl,-dead_strip_dylibs
/usr/local/Cellar/protobuf/3.10.0/lib/libprotobuf.dylib
-lpthread
-F/System/Library/Frameworks
-framework
Accelerate
/usr/lib/libz.dylib
-Wl,-headerpad_max_install_names
-Wl,-rpath,/usr/local/Cellar/protobuf/3.10.0/lib
-Wl,-rpath,/usr/lib
```
(Removes `-framework OpenCL`)

After https://github.com/mesonbuild/meson/commit/f097b96883a54868cf98600be23893268b5832f4
```
-L/usr/local/opt/openssl/lib
-Wl,-dead_strip_dylibs
-Wl,-undefined,error
-Wl,-headerpad_max_install_names
/usr/local/Cellar/protobuf/3.10.0/lib/libprotobuf.dylib
-lpthread
-F/System/Library/Frameworks
-framework
Accelerate
/System/Library/Frameworks/OpenCL.framework
/usr/lib/libz.dylib
-Wl,-headerpad_max_install_names
-Wl,-rpath,/usr/local/Cellar/protobuf/3.10.0/lib
-Wl,-rpath,/usr/lib
```
(Adds `/System/Library/Frameworks/OpenCL.framework`)


Discussion:
@mensinda or @jpakkane was this an intended change from https://github.com/mesonbuild/meson/commit/5bd21a96b89efc5fe96025398151dcbce34345ac and https://github.com/mesonbuild/meson/commit/f097b96883a54868cf98600be23893268b5832f4 so we should be adding the OpenCL dependency a different way?
Sorry for noticing this only now. No breaking OpenCL on macOS was certainly not intended. Also, I have absolutely no idea how 5bd21a9 could remove `-framework OpenCL`. It just slightly changes the starting conditions for CMake.

Unfortunately, I don't have access to a macOS machine and I am unable to debug this issue myself.
Could you please log the values of `incDirs`, `compileDefinitions`, `compileOptions` and `libraries` of [base.py](https://github.com/mesonbuild/meson/blob/master/mesonbuild/dependencies/base.py#L1444) (before and after the conversion)?
Looks like before the change, opencl detection was falling back to some other behavior and happened to find the "right" dependency? Here's the lines from `meson-log.txt` at various meson commits:

Before https://github.com/mesonbuild/meson/commit/5bd21a96b89efc5fe96025398151dcbce34345ac, e.g., tag: 0.51.0
```
Library OpenCL found: NO
Pkg-config binary for MachineChoice.HOST is cached.
Determining dependency 'OpenCL' with pkg-config executable '/usr/local/bin/pkg-config'
PKG_CONFIG_PATH: /usr/local/opt/openssl/lib/pkgconfig
Called `/usr/local/bin/pkg-config --modversion OpenCL` -> 1

CMake binary for MachineChoice.HOST is cached.

Determining dependency 'OpenCL' with CMake executable '/usr/local/bin/cmake'
Try CMake generator: auto
Called `/usr/local/bin/cmake --trace-expand -DNAME=OpenCL -DARCHS= .` in /Users/Ed/Development/lc0/build/meson-private/cmake_OpenCL -> 1
CMake failed for generator  and package OpenCL with error code 1
```
…
~6000 lines related to cmake failure with generators "", "", "Ninja", "Unix Makefiles", "Visual Studio 10 2010"
…
```
Finding framework path by running:  ccache c++ -v -E - -pipe -I/usr/local/opt/openssl/include

Looking for framework OpenCL in /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks
Running compile:
Working directory:  /Users/Ed/Development/lc0/build/meson-private/tmpahiq__i4
Command line:  ccache c++ -L/usr/local/opt/openssl/lib -I/usr/local/opt/openssl/include /Users/Ed/Development/lc0/build/meson-private/tmpahiq__i4/testfile.cpp -o /Users/Ed/Development/lc0/build/meson-private/

Code:
 int main(int argc, char **argv) { return 0; }
Compiler stdout:

Compiler stderr:

Run-time dependency opencl found: YES (/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/OpenCL.framework)
```
(No Include Dirs, etc logged.)

---

At https://github.com/mesonbuild/meson/commit/5bd21a96b89efc5fe96025398151dcbce34345ac
```
Library OpenCL found: NO
Pkg-config binary for MachineChoice.HOST is cached.
Determining dependency 'OpenCL' with pkg-config executable '/usr/local/bin/pkg-config'
PKG_CONFIG_PATH: /usr/local/opt/openssl/lib/pkgconfig
Called `/usr/local/bin/pkg-config --modversion OpenCL` -> 1

CMake binary for MachineChoice.HOST is cached.

Determining dependency 'OpenCL' with CMake executable '/usr/local/bin/cmake'
Try CMake generator: auto
Called `/usr/local/bin/cmake --trace-expand -DNAME=OpenCL -DARCHS= .` in /Users/Ed/Development/lc0/build/meson-private/cmake_OpenCL -> 0
Guessed CMake target 'OpenCL::OpenCL'
CMake TARGET:
  -- name:      OpenCL::OpenCL
  -- type:      INTERFACE
  -- properies: {
      'INTERFACE_LINK_LIBRARIES': ['/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/OpenCL.framework']
      'INTERFACE_INCLUDE_DIRECTORIES': ['/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/OpenCL.framework']
     }
Include Dirs:         ['/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/OpenCL.framework']
Compiler Definitions: []
Compiler Options:     []
Libraries:            []
Run-time dependency opencl found: YES 1.2
```

---

At https://github.com/mesonbuild/meson/commit/f097b96883a54868cf98600be23893268b5832f4
```
Library OpenCL found: NO
Pkg-config binary for MachineChoice.HOST is cached.
Determining dependency 'OpenCL' with pkg-config executable '/usr/local/bin/pkg-config'
PKG_CONFIG_PATH: /usr/local/opt/openssl/lib/pkgconfig
Called `/usr/local/bin/pkg-config --modversion OpenCL` -> 1

CMake binary for MachineChoice.HOST is cached.

Determining dependency 'OpenCL' with CMake executable '/usr/local/bin/cmake'
Try CMake generator: auto
Called `/usr/local/bin/cmake --trace-expand -DNAME=OpenCL -DARCHS= .` in /Users/Ed/Development/lc0/build/meson-private/cmake_OpenCL -> 0
Guessed CMake target 'OpenCL::OpenCL'
CMake TARGET:
  -- name:      OpenCL::OpenCL
  -- type:      INTERFACE
  -- properies: {
      'INTERFACE_LINK_LIBRARIES': ['/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/OpenCL.framework']
      'INTERFACE_INCLUDE_DIRECTORIES': ['/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/OpenCL.framework']
     }
Include Dirs:         ['/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/OpenCL.framework']
Compiler Definitions: []
Compiler Options:     []
Libraries:            ['/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/OpenCL.framework']
Run-time dependency opencl found: YES 1.2
```
OK, I think I know what is going on here. The commits you specified fixed the CMake dependency lookup on macOS, however not good enough, hence the errors.

Before the commits, meson was falling back to using the internal framework lookup, which succeeded.

You can test this theory by using `dependency(..., method: 'extraframework')`. This will force the internal meson framework lookup to be used.
Ah indeed, with `method: 'extraframework'` in `meson.build`, I see generally the same output for 0.51.0, https://github.com/mesonbuild/meson/commit/5bd21a96b89efc5fe96025398151dcbce34345ac, https://github.com/mesonbuild/meson/commit/f097b96883a54868cf98600be23893268b5832f4, and latest master https://github.com/mesonbuild/meson/commit/9c72d0fdb287f1838c68915e469b6db455f59a7e (except slight differences in the working directory and dummy `main` code), 
```
Library OpenCL found: NO
Finding framework path by running:  ccache c++ -v -E - -pipe -I/usr/local/opt/openssl/include

Looking for framework OpenCL in /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks
Running compile:
Working directory:  /Users/Ed/Development/lc0/build/meson-private/tmpnoeofk9j
Command line:  ccache c++ -L/usr/local/opt/openssl/lib -I/usr/local/opt/openssl/include /Users/Ed/Development/lc0/build/meson-private/tmpnoeofk9j/testfile.cpp -o /Users/Ed/Development/lc0/build/meson-private/tmpnoeofk9j/output.exe -pipe -O0 -fpermissive -F/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks -framework OpenCL

Code:
 int main(void) { return 0; }
Compiler stdout:
 
Compiler stderr:
 
Run-time dependency opencl found: YES (/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/OpenCL.framework)
```

And the generated build.ninja `LINK_ARGS` includes:
```
-F/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks -framework OpenCL
```

Resolving patch:
diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py
--- a/mesonbuild/dependencies/base.py
+++ b/mesonbuild/dependencies/base.py
@@ -2294,13 +2294,15 @@ def _build_external_dependency_list(name, env: Environment, kwargs: Dict[str, An
     # Otherwise, just use the pkgconfig and cmake dependency detector
     if 'auto' == kwargs.get('method', 'auto'):
         candidates.append(functools.partial(PkgConfigDependency, name, env, kwargs))
-        candidates.append(functools.partial(CMakeDependency,     name, env, kwargs))
 
         # On OSX, also try framework dependency detector
         if mesonlib.is_osx():
             candidates.append(functools.partial(ExtraFrameworkDependency, name,
                                                 False, None, env, None, kwargs))
 
+        # Only use CMake as a last resort, since it might not work 100% (see #6113)
+        candidates.append(functools.partial(CMakeDependency, name, env, kwargs))
+
     return candidates
 
 


Test patch: