Repository: mesonbuild/meson

Issue:
CMake translation handling macOS frameworks incorrectly
I'm attempting to compile cURL as a subproject and getting linker errors for the final executable. The issue appears to be the following snippet in the final linker call:
```
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk/System/Library/Frameworks/CoreFoundation.framework /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk/System/Library/Frameworks/Security.framework
```

This should instead just be `-framework CoreFoundation -framework Security`, and substituting appropriately causes the build to succeed.

This appears to come from the generated meson files. In `subprojects/curl/meson.build`:
```
  link_args : ['/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk/System/Library/Frameworks/CoreFoundation.framework', '/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk/System/Library/Frameworks/Security.framework', '/usr/local/lib/libssh2.dylib', '/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk/usr/lib/libz.tbd'],
```

The equivalent CMake appears to just be something like:
```
find_library(COREFOUNDATION_FRAMEWORK "CoreFoundation")
list(APPEND CURL_LIBS "${COREFOUNDATION_FRAMEWORK}")
```

I assume that macOS frameworks need to be special-cased for this to work.

Meson version: 0.56.0
CMake version: 3.19.0
MacOS version: 11.0.1

How I'm invoking the CMake module: https://github.com/TypesettingTools/ffi-experiments/blob/3b9efd7a8b4e93386e0bcbe84acf33a7a9ef8615/meson.build#L16-L41


Discussion:
Unfortunately, I don't have access to an OSX system. So, could you please provide the complete generated `meson.build`, `fileAPI.json` and `__CMake_build/cmake_trace.txt` for further diagnosis?
Happily! Thanks for the prompt response.
[cmake_framework_bug_logs.zip](https://github.com/mesonbuild/meson/files/5611267/cmake_framework_bug_logs.zip)

Hm, maybe it relates to a finding of [nevyn Bengtsson](https://twitter.com/nevyn/status/1331217137889931269):

> Goddammit. Remember when I complained months ago how bad it would be for _everyone_ if Big Sur really did ship without system library binaries? Less open, harder to develop, etc etc. Well, now even the latest version of CMake doesn't understand how to make Big Sur apps, it seems.

> Here's the solution. Replace `-framework AVFoundation` with FIND_LIBRARIES. Now it finds the `.tbd` and links with that INSTEAD.
btw. I have the same problem without a CMake dependency. Both happen on macOS 11.0.1 and both try to use an Apple framework. 

I think something changed in the Apple development stack and Apple did not documented/announced it properly...

```
one of 'OBJCXX_LD' are defined in the environment, not changing global flags.
None of 'OBJCPP_LD' are defined in the environment, not changing global flags.
Running compile:
Working directory:  .../core/build/apple-iphonesimulator13.0-x86_64-x86_64-little/meson-private/tmpnk1byvz5
Command line:  /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++ .../core/build/apple-iphonesimulator13.0-x86_64-x86_64-little/meson-private/tmpnk1byvz5/testfile.mm -o .../core/build/apple-iphonesimulator13.0-x86_64-x86_64-little/meson-private/tmpnk1byvz5/output.exe -pipe -O0 -framework LocalAuthentication 

Code:
 int main(void) { return 0; }
Compiler stdout:
 
Compiler stderr:
 ld: framework not found LocalAuthentication
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Run-time dependency appleframeworks found: NO (tried framework)

.../src/meson.build:2:0: Exception: Dependency "appleframeworks" not found, tried framework
```
If framework dependencies (ie, `dependency(..., method : 'extraframeworks')`) stopped working, file a separate bug for that. I'm not sure who has a Big Sur compatible machine, but you're more to get it solved in a separate bug.
If there's anything I can do to further help with this, please let me know; I have a recent fully-updated MBP handy.

Additionally, if anyone knows of a workaround that doesn't involve manually editing the final linker invocation that would be much appreciated.

Resolving patch:
diff --git a/mesonbuild/cmake/interpreter.py b/mesonbuild/cmake/interpreter.py
--- a/mesonbuild/cmake/interpreter.py
+++ b/mesonbuild/cmake/interpreter.py
@@ -502,6 +502,20 @@ def check_flag(flag: str) -> bool:
         self.link_libraries = [x for x in self.link_libraries if x.lower() not in blacklist_link_libs]
         self.link_flags = [x for x in self.link_flags if check_flag(x)]
 
+        # Handle OSX frameworks
+        def handle_frameworks(flags: T.List[str]) -> T.List[str]:
+            res: T.List[str] = []
+            for i in flags:
+                p = Path(i)
+                if not p.exists() or not p.name.endswith('.framework'):
+                    res += [i]
+                    continue
+                res += ['-framework', p.stem]
+            return res
+
+        self.link_libraries = handle_frameworks(self.link_libraries)
+        self.link_flags     = handle_frameworks(self.link_flags)
+
         # Handle explicit CMake add_dependency() calls
         for i in self.depends_raw:
             dep_tgt = output_target_map.target(i)


Test patch:
diff --git a/test cases/cmake/2 advanced/subprojects/cmMod/CMakeLists.txt b/test cases/cmake/2 advanced/subprojects/cmMod/CMakeLists.txt
--- a/test cases/cmake/2 advanced/subprojects/cmMod/CMakeLists.txt	
+++ b/test cases/cmake/2 advanced/subprojects/cmMod/CMakeLists.txt	
@@ -23,6 +23,16 @@ target_link_libraries(cmModLib       ZLIB::ZLIB)
 target_link_libraries(cmModLibStatic ;ZLIB::ZLIB;)
 target_link_libraries(testEXE cmModLib)
 
+if(APPLE)
+  find_library(COREFOUNDATION_FRAMEWORK "CoreFoundation")
+  if(NOT COREFOUNDATION_FRAMEWORK)
+    message(FATAL_ERROR "CoreFoundation framework not found")
+  endif()
+
+  target_link_libraries(cmModLibStatic "${COREFOUNDATION_FRAMEWORK}")
+  target_compile_definitions(cmModLibStatic PUBLIC USE_FRAMEWORK)
+endif()
+
 target_compile_definitions(cmModLibStatic PUBLIC CMMODLIB_STATIC_DEFINE)
 
 install(TARGETS testEXE LIBRARY DESTINATION lib RUNTIME DESTINATION bin)
diff --git a/test cases/cmake/2 advanced/subprojects/cmMod/lib/cmMod.cpp b/test cases/cmake/2 advanced/subprojects/cmMod/lib/cmMod.cpp
--- a/test cases/cmake/2 advanced/subprojects/cmMod/lib/cmMod.cpp	
+++ b/test cases/cmake/2 advanced/subprojects/cmMod/lib/cmMod.cpp	
@@ -6,10 +6,19 @@
 #error "Invalid value of CONFIG_OPT"
 #endif
 
+#ifdef USE_FRAMEWORK
+#include <CoreFoundation/CoreFoundation.h>
+#endif
+
 using namespace std;
 
 cmModClass::cmModClass(string foo) {
   str = foo + " World " + zlibVersion();
+
+#ifdef USE_FRAMEWORK
+  CFStringRef ref = CFStringCreateWithCString(NULL, str.c_str(), kCFStringEncodingUTF8);
+  CFRelease(ref);
+#endif
 }
 
 string cmModClass::getStr() const {