Repository: godotengine/godot (language: cpp)

Issue:
`print_verbose` makes build fail when `scu_build=yes`
### Tested versions

- 4.4.beta

### System information

Windows 11

### Issue description

The `print_verbose` macro is causing one of the CI jobs that uses `scu_build=yes` to fail in my PR although I didn't modify the file calling it.
https://github.com/godotengine/godot/actions/runs/12934119444/job/36074414239

My local build also fails when I use `scu_build=yes` but works fine otherwise.
```sh
[100%] godot\core/debugger/remote_debugger_peer.cpp(172): error C3861: 'print_verbose': identifier not found
```

By the way, it works if I replace it with `WARN_VERBOSE`.

### Steps to reproduce

- Checkout https://github.com/godotengine/godot/pull/100516
- I changed calls to `print_verbose`  in `core/debugger/remote_debugger_peer.cpp` to `WARN_VERBOSE` to fix CI. Change it back to `print_verbose`. 
- Build it with `scons scu_build=yes`.

### Minimal reproduction project (MRP)

N/A


Discussion / hints:
I can confirm that cherry-picking the mentioned pr and trying to compile with `scu_build=yes` in MSVC 14.3 results in the error (i cherry-picked before the change in the pr that replace the `print_verbose` for `WARN_VERBOSE`)

![Image](https://github.com/user-attachments/assets/784c5a90-6d12-444c-a35d-05834addb85f)
The problem is likely due to this, in `variant_utility.cpp` and `variant_utility.h`:
```
#undef print_verbose
```
This means anything that tries to use `print_verbose` after these files will fail (unless it is defined after this point).

We can't do much about the header, but for the cpp, we can add it as an exception from the scu build so it gets compiled on its own and doesn't affect any other files.

It likely wasn't due to your PR, but your PR may have inadvertently changed the grouping of which files were compiled together, which exposed this bug.

I'll see if it can be fixed with a simple exception rule.

### UPDATE
The gravy thickens:
```
    process_folder(["core/variant"], ["variant_utility"])
```
It is already added as an exception in the SCU build, so the problem may be the header, and inclusion order. This may be a gotcha of the header (and if so could theoretically also occur in non-scu build). I'll see if there is a sensible fix.

I *think* that `VariantUtility` is providing it's own version of `print_verbose` (instead of the define) so the function can be bound and used by gdscript using the same name.

The problem the `#undef` causes is that any file that includes `variant_utility.h` can no longer use `print_verbose` from c++ _unless_ it includes `core/string/print_string.h` _after_ variant utility. Unfortunately the `clangformat` step re-orders includes, so could inadvertently cause this problem. 🤔 

Yes I confirmed the hypothesis.
Adding:
```
#ifndef print_verbose
#define print_verbose(m_text)             \
{                                     \
			if (is_print_verbose_enabled()) { \
				print_line(m_text);           \
	}                                 \
}
#endif
```
Into `remote_debugger_peer.cpp` solves the problem (although isn't a good proper fix).

Essentially this happens:
* `print_string.h` is included (defining print_verbose)
* Someone includes `variant_utility.h` (undefining it)
* At this stage reincluding `print_string.h` doesn't work as the include guards prevent it running a second time, and `print_verbose` remains undefined.

Fix patch:
diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp
index ec9492ac5d1c..a53b5660d5a5 100644
--- a/core/variant/variant_utility.cpp
+++ b/core/variant/variant_utility.cpp
@@ -999,9 +999,7 @@ void VariantUtilityFunctions::print_rich(const Variant **p_args, int p_arg_count
 	r_error.error = Callable::CallError::CALL_OK;
 }
 
-#undef print_verbose
-
-void VariantUtilityFunctions::print_verbose(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
+void VariantUtilityFunctions::_print_verbose(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
 	if (OS::get_singleton()->is_stdout_verbose()) {
 		String s;
 		for (int i = 0; i < p_arg_count; i++) {
@@ -1581,16 +1579,16 @@ static _FORCE_INLINE_ Variant::Type get_ret_type_helper(void (*p_func)(P...)) {
 	};                                                                                                           \
 	register_utility_function<Func_##m_func>(#m_func, m_args)
 
-#define FUNCBINDVARARGV(m_func, m_args, m_category)                                                              \
+#define FUNCBINDVARARGV_CNAME(m_func, m_func_cname, m_args, m_category)                                          \
 	class Func_##m_func {                                                                                        \
 	public:                                                                                                      \
 		static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { \
 			r_error.error = Callable::CallError::CALL_OK;                                                        \
-			VariantUtilityFunctions::m_func(p_args, p_argcount, r_error);                                        \
+			VariantUtilityFunctions::m_func_cname(p_args, p_argcount, r_error);                                  \
 		}                                                                                                        \
 		static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) {                     \
 			Callable::CallError c;                                                                               \
-			VariantUtilityFunctions::m_func(p_args, p_argcount, c);                                              \
+			VariantUtilityFunctions::m_func_cname(p_args, p_argcount, c);                                        \
 		}                                                                                                        \
 		static void ptrcall(void *ret, const void **p_args, int p_argcount) {                                    \
 			Vector<Variant> args;                                                                                \
@@ -1625,6 +1623,8 @@ static _FORCE_INLINE_ Variant::Type get_ret_type_helper(void (*p_func)(P...)) {
 	};                                                                                                           \
 	register_utility_function<Func_##m_func>(#m_func, m_args)
 
+#define FUNCBINDVARARGV(m_func, m_args, m_category) FUNCBINDVARARGV_CNAME(m_func, m_func, m_args, m_category)
+
 #define FUNCBIND(m_func, m_args, m_category)                                                                     \
 	class Func_##m_func {                                                                                        \
 	public:                                                                                                      \
@@ -1832,7 +1832,7 @@ void Variant::_register_variant_utility_functions() {
 	FUNCBINDVARARGV(printt, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL);
 	FUNCBINDVARARGV(prints, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL);
 	FUNCBINDVARARGV(printraw, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL);
-	FUNCBINDVARARGV(print_verbose, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL);
+	FUNCBINDVARARGV_CNAME(print_verbose, _print_verbose, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL);
 	FUNCBINDVARARGV(push_error, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL);
 	FUNCBINDVARARGV(push_warning, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL);
 
diff --git a/core/variant/variant_utility.h b/core/variant/variant_utility.h
index 75cde4942b5f..a653369621a0 100644
--- a/core/variant/variant_utility.h
+++ b/core/variant/variant_utility.h
@@ -133,8 +133,7 @@ struct VariantUtilityFunctions {
 	static String type_string(Variant::Type p_type);
 	static void print(const Variant **p_args, int p_arg_count, Callable::CallError &r_error);
 	static void print_rich(const Variant **p_args, int p_arg_count, Callable::CallError &r_error);
-#undef print_verbose
-	static void print_verbose(const Variant **p_args, int p_arg_count, Callable::CallError &r_error);
+	static void _print_verbose(const Variant **p_args, int p_arg_count, Callable::CallError &r_error);
 	static void printerr(const Variant **p_args, int p_arg_count, Callable::CallError &r_error);
 	static void printt(const Variant **p_args, int p_arg_count, Callable::CallError &r_error);
 	static void prints(const Variant **p_args, int p_arg_count, Callable::CallError &r_error);


Test patch: