Repository: mesonbuild/meson

Issue:
cmake subproject dependency() fails with "ERROR: Arguments must be strings."
**Describe the bug**
See title

**To Reproduce**
See files below.

**Expected behavior**
Either a proper error message if my input is invalid or not to fail.

**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 (inside MSYS2 on Windows 10)
* what operating system (e.g. MacOS Catalina, Windows 10, CentOS 8.0, Ubuntu 18.04, etc.) Windows 10 (MSYS2 command line)
* what Python version are you using e.g. 3.8.0: Python 3.8.5
* what `meson --version` 0.55.1
* what `ninja --version` if it's a Ninja build  1.10.1

cmake version is: 3.17.3.

See the output below:
```
$ meson build
The Meson build system
Version: 0.55.1
Source dir: C:/msys64/tmp/test
Build dir: C:/msys64/tmp/test/build
Build type: native build
Using 'PKG_CONFIG_PATH' from environment with value: 'C:\\msys64\\mingw64\\lib\\pkgconfig;C:\\msys64\\mingw64\\share\\pkgconfig'
Using 'PKG_CONFIG_PATH' from environment with value: 'C:\\msys64\\mingw64\\lib\\pkgconfig;C:\\msys64\\mingw64\\share\\pkgconfig'
Project name: test
Project version: 0.1
C compiler for the host machine: cc (gcc 10.2.0 "cc (Rev1, Built by MSYS2 project) 10.2.0")
C linker for the host machine: cc ld.bfd 2.35
Host machine cpu family: x86_64
Host machine cpu: x86_64

|Executing subproject drmingw method cmake
|
|Found CMake: C:\msys64\mingw64\bin/cmake.EXE (3.17.3)
|
||Configuring the build directory with CMake version 3.17.3
||Running: -DCMAKE_C_COMPILER=cc -G Ninja -DCMAKE_INSTALL_PREFIX=C:/msys64/mingw64 -DCMAKE_POSITION_INDEPENDENT_CODE=ON
||  - build directory:          C:/msys64/tmp/test/build/subprojects/drmingw/__CMake_build
||  - source directory:         C:/msys64/tmp/test/subprojects/drmingw
||  - trace args:               --trace-expand --trace-format=json-v1 --no-warn-unused-cli --trace-redirect=cmake_trace.txt
||  - preload file:             C:/msys64/tmp/test/build/meson-private/data/preload.cmake
||  - disabled policy warnings: [CMP0025, CMP0047, CMP0056, CMP0060, CMP0065, CMP0066, CMP0067, CMP0082, CMP0089]
||
||Running with expanded trace output on.
||Not searching for unused variables given on the command line.
||Trace will be written to cmake_trace.txt
||-- The C compiler identification is GNU 10.2.0
||-- The CXX compiler identification is GNU 10.2.0
||-- Check for working C compiler: C:/msys64/mingw64/bin/cc.exe
||-- Check for working C compiler: C:/msys64/mingw64/bin/cc.exe - works
||-- Detecting C compiler ABI info
||-- Detecting C compiler ABI info - done
||-- Detecting C compile features
||-- Detecting C compile features - done
||-- Check for working CXX compiler: C:/msys64/mingw64/bin/c++.exe
||-- Check for working CXX compiler: C:/msys64/mingw64/bin/c++.exe - works
||-- Detecting CXX compiler ABI info
||-- Detecting CXX compiler ABI info - done
||-- Detecting CXX compile features
||-- Detecting CXX compile features - done
||-- Could NOT find WinDbg (missing: WINDBG_DIR)
||-- Performing Test HAVE_STATIC_LIBGCC_FLAG
||-- Performing Test HAVE_STATIC_LIBGCC_FLAG - Success
||-- Performing Test HAVE_STATIC_LIBSTDCXX_FLAG
||-- Performing Test HAVE_STATIC_LIBSTDCXX_FLAG - Success
||-- Performing Test HAVE_EXCEPTION_REGISTRATION_RECORD
||-- Performing Test HAVE_EXCEPTION_REGISTRATION_RECORD - Success
||-- Found Python3: C:/msys64/mingw64/bin/python3.8.exe (found version "3.8.5") found components: Interpreter
||-- Configuring done
||-- Generating done
||-- Build files have been written to: C:/msys64/tmp/test/build/subprojects/drmingw/__CMake_build
|
|CMake configuration: SUCCEEDED
|WARNING: Unknown cpp_std "gnu++11" -> Ignoring. Try setting the project-level cpp_std if build errors occur. Known cpp_stds are:
|CMake project drmingw has 64 build targets.
|
||Processing generated meson AST
||Build file: C:/msys64/tmp/test/build/subprojects/drmingw/meson.build
||
||Using 'PKG_CONFIG_PATH' from environment with value: 'C:\\msys64\\mingw64\\lib\\pkgconfig;C:\\msys64\\mingw64\\share\\pkgconfig'
||Using 'PKG_CONFIG_PATH' from environment with value: 'C:\\msys64\\mingw64\\lib\\pkgconfig;C:\\msys64\\mingw64\\share\\pkgconfig'
||Project name: drmingw
||Project version: undefined
||C compiler for the host machine: cc (gcc 10.2.0 "cc (Rev1, Built by MSYS2 project) 10.2.0")
||C linker for the host machine: cc ld.bfd 2.35
||C++ compiler for the host machine: c++ (gcc 10.2.0 "c++ (Rev1, Built by MSYS2 project) 10.2.0")
||C++ linker for the host machine: c++ ld.bfd 2.35
||Build targets in project: 64
||Subproject drmingw finished.
|


meson.build:11:0: ERROR: Arguments must be strings.

A full log can be found at C:/msys64/tmp/test/build/meson-logs/meson-log.txt
```

meson.build:
```meson
project('test', 'c',
  version : '0.1',
  default_options : ['warning_level=3'])

cmake = import ('cmake')
cmake_opts = cmake.subproject_options ()
cmake_opts.add_cmake_defines ({'CMAKE_POSITION_INDEPENDENT_CODE': 'ON'})

drmingw_subproject = cmake.subproject (
  'drmingw', options: cmake_opts)
drmingw_dep = drmingw_subproject.dependency ('exchndl')
```

subprojects/drmingw.wrap:
```
[wrap-git]
url = https://github.com/jrfonseca/drmingw
revision = 0ec7a6cb768b185271b0015f5dfaef1e44c88849
```


Discussion:
tried with 0.54.3

output:
```
../meson/meson.py build
The Meson build system
Version: 0.54.3
Source dir: C:/msys64/tmp/test
Build dir: C:/msys64/tmp/test/build
Build type: native build
Using 'PKG_CONFIG_PATH' from environment with value: 'C:\\msys64\\mingw64\\lib\\pkgconfig;C:\\msys64\\mingw64\\share\\pkgconfig'
Using 'PKG_CONFIG_PATH' from environment with value: 'C:\\msys64\\mingw64\\lib\\pkgconfig;C:\\msys64\\mingw64\\share\\pkgconfig'
Project name: test
Project version: 0.1
C compiler for the host machine: cc (gcc 10.2.0 "cc (Rev1, Built by MSYS2 project) 10.2.0")
C linker for the host machine: cc ld.bfd 2.35
Host machine cpu family: x86_64
Host machine cpu: x86_64

|Executing subproject drmingw method cmake
|
|Found CMake: C:\msys64\mingw64\bin/cmake.EXE (3.17.3)
|
||Configuring the build directory with CMake version 3.17.3
||Running: -DCMAKE_C_COMPILER=cc -G Ninja -DCMAKE_INSTALL_PREFIX=c:/
||  - build directory:          C:/msys64/tmp/test/build/subprojects/drmingw/__CMake_build
||  - source directory:         C:/msys64/tmp/test/subprojects/drmingw
||  - trace args:               --trace-expand --trace-format=json-v1 --no-warn-unused-cli --trace-redirect=cmake_trace.txt
||  - preload file:             C:/msys64/tmp/meson/mesonbuild/cmake/data/preload.cmake
||  - disabled policy warnings: [CMP0025, CMP0047, CMP0056, CMP0060, CMP0065, CMP0066, CMP0067, CMP0082, CMP0089]
||
||Running with expanded trace output on.
||Not searching for unused variables given on the command line.
||Trace will be written to cmake_trace.txt
||-- Could NOT find WinDbg (missing: WINDBG_DIR)
||-- Configuring done
||-- Generating done
||-- Build files have been written to: C:/msys64/tmp/test/build/subprojects/drmingw/__CMake_build
|
|CMake configuration: SUCCEEDED
|WARNING: Unknown cpp_std "gnu++11" -> Ignoring. Try setting the project-level cpp_std if build errors occur. Known cpp_stds are:
|CMake project drmingw has 64 build targets.
|
||Processing generated meson AST
||Build file: C:/msys64/tmp/test/build/subprojects/drmingw/meson.build
||
||Using 'PKG_CONFIG_PATH' from environment with value: 'C:\\msys64\\mingw64\\lib\\pkgconfig;C:\\msys64\\mingw64\\share\\pkgconfig'
||Using 'PKG_CONFIG_PATH' from environment with value: 'C:\\msys64\\mingw64\\lib\\pkgconfig;C:\\msys64\\mingw64\\share\\pkgconfig'
||Project name: drmingw
||Project version: undefined
||C compiler for the host machine: cc (gcc 10.2.0 "cc (Rev1, Built by MSYS2 project) 10.2.0")
||C linker for the host machine: cc ld.bfd 2.35
||C++ compiler for the host machine: c++ (gcc 10.2.0 "c++ (Rev1, Built by MSYS2 project) 10.2.0")
||C++ linker for the host machine: c++ ld.bfd 2.35
||Program C:/msys64/tmp/meson/mesonbuild/cmake/data/run_ctgt.py found: YES (C:/msys64/mingw64/bin/python3.exe C:/msys64/tmp/meson/mesonbuild/cmake/data/run_ctgt.py)
||Build targets in project: 64
||Subproject drmingw finished.
|


meson.build:11:0: ERROR: Get_variable first argument must be a string.

A full log can be found at C:/msys64/tmp/test/build/meson-logs/meson-log.txt
```

meson.build:
```meson
project('test', 'c',
  version : '0.1',
  default_options : ['warning_level=3'])

cmake = import ('cmake')
#cmake_opts = cmake.subproject_options ()
#cmake_opts.add_cmake_defines ({'CMAKE_POSITION_INDEPENDENT_CODE': 'ON'})

drmingw_subproject = cmake.subproject (
  'drmingw')
drmingw_dep = drmingw_subproject.dependency ('exchndl')
```

Resolving patch:
diff --git a/mesonbuild/cmake/interpreter.py b/mesonbuild/cmake/interpreter.py
--- a/mesonbuild/cmake/interpreter.py
+++ b/mesonbuild/cmake/interpreter.py
@@ -1235,6 +1235,10 @@ def process_target(tgt: ConverterTarget):
                 if tgt_func in ['static_library', 'shared_library']:
                     dep_node = assign(dep_var, function('declare_dependency', kwargs=dep_kwargs))
                     node_list += [dep_node]
+                elif tgt_func in ['shared_module']:
+                    del dep_kwargs['link_with']
+                    dep_node = assign(dep_var, function('declare_dependency', kwargs=dep_kwargs))
+                    node_list += [dep_node]
                 else:
                     dep_var = None
 


Test patch:
diff --git a/test cases/cmake/21 shared module/meson.build b/test cases/cmake/21 shared module/meson.build
new file mode 100644
--- /dev/null
+++ b/test cases/cmake/21 shared module/meson.build	
@@ -0,0 +1,13 @@
+project('cmakeSharedModule', ['c', 'cpp'])
+
+cm = import('cmake')
+
+sub_pro = cm.subproject('cmMod')
+sub_dep = sub_pro.dependency('myMod')
+
+dl = meson.get_compiler('c').find_library('dl', required: false)
+
+l = shared_library('runtime', 'runtime.c')
+e = executable('prog', ['prog.c'], link_with: l, dependencies: [sub_dep, dl])
+m = sub_pro.target('myMod')
+test('test1', e, args : m)
diff --git a/test cases/cmake/21 shared module/prog.c b/test cases/cmake/21 shared module/prog.c
new file mode 100644
--- /dev/null
+++ b/test cases/cmake/21 shared module/prog.c	
@@ -0,0 +1,108 @@
+
+#include <stdio.h>
+#include "module.h"
+
+#if SPECIAL_MAGIC_DEFINE != 42
+#error "SPECIAL_MAGIC_DEFINE is not defined"
+#endif
+
+int func_from_language_runtime(void);
+typedef int (*fptr) (void);
+
+#ifdef _WIN32
+
+#include <windows.h>
+
+static wchar_t*
+win32_get_last_error (void)
+{
+    wchar_t *msg = NULL;
+
+    FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER
+                    | FORMAT_MESSAGE_IGNORE_INSERTS
+                    | FORMAT_MESSAGE_FROM_SYSTEM,
+                    NULL, GetLastError (), 0,
+                    (LPWSTR) &msg, 0, NULL);
+    return msg;
+}
+
+int main(int argc, char **argv)
+{
+    HINSTANCE handle;
+    fptr importedfunc;
+    int expected, actual;
+    int ret = 1;
+    if(argc==0) {};
+
+    handle = LoadLibraryA (argv[1]);
+    if (!handle) {
+        wchar_t *msg = win32_get_last_error ();
+        printf ("Could not open %s: %S\n", argv[1], msg);
+        goto nohandle;
+    }
+
+    importedfunc = (fptr) GetProcAddress (handle, "func");
+    if (importedfunc == NULL) {
+        wchar_t *msg = win32_get_last_error ();
+        printf ("Could not find 'func': %S\n", msg);
+        goto out;
+    }
+
+    actual = importedfunc ();
+    expected = func_from_language_runtime ();
+    if (actual != expected) {
+        printf ("Got %i instead of %i\n", actual, expected);
+        goto out;
+    }
+
+    ret = 0;
+out:
+    FreeLibrary (handle);
+nohandle:
+    return ret;
+}
+
+#else
+
+#include<dlfcn.h>
+#include<assert.h>
+
+int main(int argc, char **argv) {
+    void *dl;
+    fptr importedfunc;
+    int expected, actual;
+    char *error;
+    int ret = 1;
+    if(argc==0) {};
+
+    dlerror();
+    dl = dlopen(argv[1], RTLD_LAZY);
+    error = dlerror();
+    if(error) {
+        printf("Could not open %s: %s\n", argv[1], error);
+        goto nodl;
+    }
+
+    importedfunc = (fptr) dlsym(dl, "func");
+    if (importedfunc == NULL) {
+        printf ("Could not find 'func'\n");
+        goto out;
+    }
+
+    assert(importedfunc != func_from_language_runtime);
+
+    actual = (*importedfunc)();
+    expected = func_from_language_runtime ();
+    if (actual != expected) {
+        printf ("Got %i instead of %i\n", actual, expected);
+        goto out;
+    }
+
+    ret = 0;
+out:
+    dlclose(dl);
+nodl:
+    return ret;
+}
+
+#endif
diff --git a/test cases/cmake/21 shared module/runtime.c b/test cases/cmake/21 shared module/runtime.c
new file mode 100644
--- /dev/null
+++ b/test cases/cmake/21 shared module/runtime.c	
@@ -0,0 +1,19 @@
+#if defined _WIN32 || defined __CYGWIN__
+  #define DLL_PUBLIC __declspec(dllexport)
+#else
+  #if defined __GNUC__
+    #define DLL_PUBLIC __attribute__ ((visibility("default")))
+  #else
+    #pragma message ("Compiler does not support symbol visibility.")
+    #define DLL_PUBLIC
+  #endif
+#endif
+
+/*
+ * This file pretends to be a language runtime that supports extension
+ * modules.
+ */
+
+int DLL_PUBLIC func_from_language_runtime(void) {
+    return 86;
+}
diff --git a/test cases/cmake/21 shared module/subprojects/cmMod/CMakeLists.txt b/test cases/cmake/21 shared module/subprojects/cmMod/CMakeLists.txt
new file mode 100644
--- /dev/null
+++ b/test cases/cmake/21 shared module/subprojects/cmMod/CMakeLists.txt	
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 3.5)
+
+project(cmModule)
+
+include_directories("${CMAKE_CURRENT_SOURCE_DIR}/module")
+
+add_library(myMod MODULE "${CMAKE_CURRENT_SOURCE_DIR}/module/module.c")
diff --git a/test cases/cmake/21 shared module/subprojects/cmMod/module/module.c b/test cases/cmake/21 shared module/subprojects/cmMod/module/module.c
new file mode 100644
--- /dev/null
+++ b/test cases/cmake/21 shared module/subprojects/cmMod/module/module.c	
@@ -0,0 +1,96 @@
+#if defined _WIN32 || defined __CYGWIN__
+  #define DLL_PUBLIC __declspec(dllexport)
+#else
+  #if defined __GNUC__
+    #define DLL_PUBLIC __attribute__ ((visibility("default")))
+  #else
+    #pragma message ("Compiler does not support symbol visibility.")
+    #define DLL_PUBLIC
+  #endif
+#endif
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+
+#include <stdio.h>
+
+typedef int (*fptr) (void);
+
+#ifdef __CYGWIN__
+
+#include <dlfcn.h>
+
+fptr find_any_f (const char *name) {
+    return (fptr) dlsym(RTLD_DEFAULT, name);
+}
+#else /* _WIN32 */
+
+#include <windows.h>
+#include <tlhelp32.h>
+
+static wchar_t*
+win32_get_last_error (void)
+{
+    wchar_t *msg = NULL;
+
+    FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER
+                    | FORMAT_MESSAGE_IGNORE_INSERTS
+                    | FORMAT_MESSAGE_FROM_SYSTEM,
+                    NULL, GetLastError (), 0,
+                    (LPWSTR) &msg, 0, NULL);
+    return msg;
+}
+
+/* Unlike Linux and OS X, when a library is loaded, all the symbols aren't
+ * loaded into a single namespace. You must fetch the symbol by iterating over
+ * all loaded modules. Code for finding the function from any of the loaded
+ * modules is taken from gmodule.c in glib */
+fptr find_any_f (const char *name) {
+    fptr f;
+    HANDLE snapshot;
+    MODULEENTRY32 me32;
+
+    snapshot = CreateToolhelp32Snapshot (TH32CS_SNAPMODULE, 0);
+    if (snapshot == (HANDLE) -1) {
+        wchar_t *msg = win32_get_last_error();
+        printf("Could not get snapshot: %S\n", msg);
+        return 0;
+    }
+
+    me32.dwSize = sizeof (me32);
+
+    f = NULL;
+    if (Module32First (snapshot, &me32)) {
+        do {
+            if ((f = (fptr) GetProcAddress (me32.hModule, name)) != NULL)
+                break;
+        } while (Module32Next (snapshot, &me32));
+    }
+
+    CloseHandle (snapshot);
+    return f;
+}
+#endif
+
+int DLL_PUBLIC func(void) {
+    fptr f;
+
+    f = find_any_f ("func_from_language_runtime");
+    if (f != NULL)
+        return f();
+    printf ("Could not find function\n");
+    return 1;
+}
+
+#else
+/*
+ * Shared modules often have references to symbols that are not defined
+ * at link time, but which will be provided from deps of the executable that
+ * dlopens it. We need to make sure that this works, i.e. that we do
+ * not pass -Wl,--no-undefined when linking modules.
+ */
+int func_from_language_runtime(void);
+
+int DLL_PUBLIC func(void) {
+    return func_from_language_runtime();
+}
+#endif
diff --git a/test cases/cmake/21 shared module/subprojects/cmMod/module/module.h b/test cases/cmake/21 shared module/subprojects/cmMod/module/module.h
new file mode 100644
--- /dev/null
+++ b/test cases/cmake/21 shared module/subprojects/cmMod/module/module.h	
@@ -0,0 +1,3 @@
+#pragma once
+
+#define SPECIAL_MAGIC_DEFINE 42