Repository: mesonbuild/meson

Issue:
CMake translation missing Objective-C++ files in wxWidgets
Attempting to build and link against wxWidgets on MacOS results in various linker errors. Looking up the symbols, they seem to be coming from the various objective-c++ `.mm` files in `src/osx/cocoa`. Compiling directly with CMake does seem to include those files. 

Unfortunately, I don't have a minimal repro handy. If that's needed, please let me know and I can try to make one. I've uploaded `meson.build`, `fileAPI.json` and `__CMake_build/cmake_trace.txt`, but if there's anything else I can provide I'd be happy to since this is blocking.

[cmake_objcpp_bug_logs.zip](https://github.com/mesonbuild/meson/files/5742882/cmake_objcpp_bug_logs.zip)

CMake module invocation: https://github.com/TypesettingTools/Aegisub/blob/meson-vs2019/meson.build#L125

System:
MacOS 11.1
Python 3.9.1
Meson 0.56.0
CMake 3.19.2


Discussion:
It looks like you didn't add `objcpp` and `objc` to the languages in your project call. Could you please try adding these languages and check if this makes a difference?

Resolving patch:
diff --git a/mesonbuild/cmake/interpreter.py b/mesonbuild/cmake/interpreter.py
--- a/mesonbuild/cmake/interpreter.py
+++ b/mesonbuild/cmake/interpreter.py
@@ -231,7 +231,7 @@ def __init__(self, target: CMakeTarget, env: 'Environment', for_machine: Machine
         if target.install_paths:
             self.install_dir = target.install_paths[0]
 
-        self.languages           = []  # type: T.List[str]
+        self.languages           = set() # type: T.Set[str]
         self.sources             = []  # type: T.List[Path]
         self.generated           = []  # type: T.List[Path]
         self.generated_ctgt      = []  # type: T.List[CustomTargetReference]
@@ -250,19 +250,40 @@ def __init__(self, target: CMakeTarget, env: 'Environment', for_machine: Machine
         self.name = _sanitize_cmake_name(self.name)
 
         self.generated_raw = []  # type: T.List[Path]
+
         for i in target.files:
-            # Determine the meson language
+            languages    = set()  #  type: T.Set[str]
+            src_suffixes = set()  #  type: T.Set[str]
+
+            # Insert suffixes
+            for j in i.sources:
+                if not j.suffix:
+                    continue
+                src_suffixes.add(j.suffix[1:])
+
+            # Determine the meson language(s)
+            # Extract the default language from the explicit CMake field
             lang_cmake_to_meson = {val.lower(): key for key, val in language_map.items()}
-            lang = lang_cmake_to_meson.get(i.language.lower(), 'c')
-            if lang not in self.languages:
-                self.languages += [lang]
-            if lang not in self.compile_opts:
-                self.compile_opts[lang] = []
+            languages.add(lang_cmake_to_meson.get(i.language.lower(), 'c'))
+
+            # Determine missing languages from the source suffixes
+            for sfx in src_suffixes:
+                for key, val in lang_suffixes.items():
+                    if sfx in val:
+                        languages.add(key)
+                        break
+
+            # Register the new languages and initialize the compile opts array
+            for lang in languages:
+                self.languages.add(lang)
+                if lang not in self.compile_opts:
+                    self.compile_opts[lang] = []
 
             # Add arguments, but avoid duplicates
             args = i.flags
             args += ['-D{}'.format(x) for x in i.defines]
-            self.compile_opts[lang] += [x for x in args if x not in self.compile_opts[lang]]
+            for lang in languages:
+                self.compile_opts[lang] += [x for x in args if x not in self.compile_opts[lang]]
 
             # Handle include directories
             self.includes += [x.path for x in i.includes if x.path not in self.includes and not x.isSystem]


Test patch:
diff --git a/test cases/cmake/24 mixing languages/main.c b/test cases/cmake/24 mixing languages/main.c
new file mode 100644
--- /dev/null
+++ b/test cases/cmake/24 mixing languages/main.c	
@@ -0,0 +1,5 @@
+#include <cmTest.h>
+
+int main(void) {
+  return doStuff();
+}
diff --git a/test cases/cmake/24 mixing languages/meson.build b/test cases/cmake/24 mixing languages/meson.build
new file mode 100644
--- /dev/null
+++ b/test cases/cmake/24 mixing languages/meson.build	
@@ -0,0 +1,13 @@
+project('CMake mix', ['c', 'cpp'])
+
+if not add_languages('objc', required : false)
+  error('MESON_SKIP_TEST: No ObjC compiler')
+endif
+
+cm = import('cmake')
+
+sub_pro = cm.subproject('cmTest')
+sub_dep = sub_pro.dependency('cmTest', include_type: 'system')
+
+exe1 = executable('exe1', ['main.c'], dependencies: [sub_dep])
+test('test1', exe1)
diff --git a/test cases/cmake/24 mixing languages/subprojects/cmTest/CMakeLists.txt b/test cases/cmake/24 mixing languages/subprojects/cmTest/CMakeLists.txt
new file mode 100644
--- /dev/null
+++ b/test cases/cmake/24 mixing languages/subprojects/cmTest/CMakeLists.txt	
@@ -0,0 +1,8 @@
+cmake_minimum_required(VERSION 3.5)
+
+project(cmTest)
+
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
+
+add_library(cmTest STATIC cmTest.c cmTest.m)
+target_compile_definitions(cmTest PUBLIC SOME_MAGIC_DEFINE=42)
diff --git a/test cases/cmake/24 mixing languages/subprojects/cmTest/cmTest.c b/test cases/cmake/24 mixing languages/subprojects/cmTest/cmTest.c
new file mode 100644
--- /dev/null
+++ b/test cases/cmake/24 mixing languages/subprojects/cmTest/cmTest.c	
@@ -0,0 +1,13 @@
+#include "cmTest.h"
+#include <stdio.h>
+
+#if SOME_MAGIC_DEFINE != 42
+#error "SOME_MAGIC_DEFINE != 42"
+#endif
+
+int foo(int x);
+
+int doStuff(void) {
+  printf("Hello World\n");
+  return foo(42);
+}
diff --git a/test cases/cmake/24 mixing languages/subprojects/cmTest/cmTest.h b/test cases/cmake/24 mixing languages/subprojects/cmTest/cmTest.h
new file mode 100644
--- /dev/null
+++ b/test cases/cmake/24 mixing languages/subprojects/cmTest/cmTest.h	
@@ -0,0 +1,3 @@
+#pragma once
+
+int doStuff(void);
diff --git a/test cases/cmake/24 mixing languages/subprojects/cmTest/cmTest.m b/test cases/cmake/24 mixing languages/subprojects/cmTest/cmTest.m
new file mode 100644
--- /dev/null
+++ b/test cases/cmake/24 mixing languages/subprojects/cmTest/cmTest.m	
@@ -0,0 +1,7 @@
+#if SOME_MAGIC_DEFINE != 42
+#error "SOME_MAGIC_DEFINE != 42"
+#endif
+
+int foo(int x) {
+  return 42 - x;
+}