diff --git a/CHANGES.current b/CHANGES.current
index bfe3f8b0a..921441645 100644
--- a/CHANGES.current
+++ b/CHANGES.current
@@ -7,6 +7,17 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
Version 4.1.0 (in progress)
===========================
+2022-10-04: olly
+ #1050 Consistently define SWIG_VERSION both at SWIG-time and in
+ the generated wrapper. Best practice remains to check at SWIG-time
+ where possible because that results in smaller generated wrapper
+ sources.
+
+ SWIGGO and SWIGJAVASCRIPT are now defined in the generated wrappers
+ to match behaviour for all other target languages.
+
+ The undocumented SWIGVERSION macro is no longer defined.
+
2022-09-29: olly
#2303 SWIG's internal hash tables now use a better hash function.
diff --git a/Doc/Manual/Preprocessor.html b/Doc/Manual/Preprocessor.html
index 0d5cc6300..c612c56ce 100644
--- a/Doc/Manual/Preprocessor.html
+++ b/Doc/Manual/Preprocessor.html
@@ -147,6 +147,14 @@ SWIGTCL Defined when using Tcl
SWIGXML Defined when using XML
+
+SWIG also defines SWIG_VERSION and a target language macro in
+the generated wrapper file (since SWIG 4.2.0 - in older versions these
+were defined for some target languages but this wasn't consistent). Best
+practice is to use SWIG-time conditional checks because that results in smaller
+generated wrapper sources.
+
+
In addition, SWIG defines the following set of standard C/C++ macros:
diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk
index da90dd9fd..a308d53c2 100644
--- a/Examples/test-suite/common.mk
+++ b/Examples/test-suite/common.mk
@@ -788,6 +788,7 @@ C_TEST_CASES += \
preproc_gcc_output \
preproc_include \
preproc_line_file \
+ preproc_predefined \
register_par \
ret_by_value \
simple_array \
diff --git a/Examples/test-suite/preproc_predefined.h b/Examples/test-suite/preproc_predefined.h
new file mode 100644
index 000000000..8d6b6ee28
--- /dev/null
+++ b/Examples/test-suite/preproc_predefined.h
@@ -0,0 +1,27 @@
+/* This list will need updating when new target languages are added. */
+#if (0\
+ +defined(SWIGCSHARP)\
+ +defined(SWIGD)\
+ +defined(SWIGGO)\
+ +defined(SWIGGUILE)\
+ +defined(SWIGJAVA)\
+ +defined(SWIGJAVASCRIPT)\
+ +defined(SWIGLUA)\
+ +defined(SWIGMZSCHEME)\
+ +defined(SWIGOCAML)\
+ +defined(SWIGOCTAVE)\
+ +defined(SWIGPERL)\
+ +defined(SWIGPHP)\
+ +defined(SWIGPYTHON)\
+ +defined(SWIGR)\
+ +defined(SWIGRUBY)\
+ +defined(SWIGSCILAB)\
+ +defined(SWIGTCL)\
+ +defined(SWIGXML)\
+ ) != 1
+# ifdef SWIG
+# error Did not detect exactly one target-language-specific macro defined at SWIG time.
+# else
+# error Did not detect exactly one target-language-specific macro defined in the generated wrapper.
+# endif
+#endif
diff --git a/Examples/test-suite/preproc_predefined.i b/Examples/test-suite/preproc_predefined.i
new file mode 100644
index 000000000..7db5352f5
--- /dev/null
+++ b/Examples/test-suite/preproc_predefined.i
@@ -0,0 +1,40 @@
+%module preproc_predefined
+
+/* Test that SWIG_VERSION is defined at SWIG-time and in the wrapper. */
+#ifndef SWIG_VERSION
+# error SWIG_VERSION not defined at SWIG-time
+#endif
+%{
+#ifndef SWIG_VERSION
+# error SWIG_VERSION not defined in the generated wrapper
+#endif
+%}
+
+/* Test that SWIGVERSION is NOT defined at SWIG-time or in the wrapper.
+ * It used to be defined in the wrapper as a side-effect of how SWIG_VERSION
+ * was defined in the wrapper but was never documented and is redundant.
+ */
+#ifdef SWIGVERSION
+# error SWIGVERSION should not be defined at SWIG-time
+#endif
+%{
+#ifdef SWIGVERSION
+# error SWIGVERSION should not be defined in the generated wrapper
+#endif
+%}
+
+/* Test that SWIG is defined at SWIG-time but not in the wrapper. */
+#ifndef SWIG
+# error SWIG not defined at SWIG-time
+#endif
+%{
+#ifdef SWIG
+# error SWIG should not be defined in the generated wrapper
+#endif
+%}
+
+/* Test that SWIGxxx is defined at SWIG-time and in the wrapper. */
+%include "preproc_predefined.h"
+%{
+#include "preproc_predefined.h"
+%}
diff --git a/Lib/csharp/csharp.swg b/Lib/csharp/csharp.swg
index 1f80d12a1..8514a7705 100644
--- a/Lib/csharp/csharp.swg
+++ b/Lib/csharp/csharp.swg
@@ -4,6 +4,8 @@
* C# typemaps
* ----------------------------------------------------------------------------- */
+%include
+
%include
/* The ctype, imtype and cstype typemaps work together and so there should be one of each.
diff --git a/Lib/go/go.swg b/Lib/go/go.swg
index 348ae5f0d..47486ab75 100644
--- a/Lib/go/go.swg
+++ b/Lib/go/go.swg
@@ -4,6 +4,8 @@
* Go configuration module.
* ------------------------------------------------------------ */
+%include
+
%include
/* Code insertion directives */
diff --git a/Lib/guile/guile.i b/Lib/guile/guile.i
index ef270d74b..10438f483 100644
--- a/Lib/guile/guile.i
+++ b/Lib/guile/guile.i
@@ -4,6 +4,8 @@
* SWIG Configuration File for Guile.
* ----------------------------------------------------------------------------- */
+%include
+
/* Macro for inserting Scheme code into the stub */
#define %scheme %insert("scheme")
#define %goops %insert("goops")
diff --git a/Lib/java/java.swg b/Lib/java/java.swg
index 8719818bb..28eb8fd0d 100644
--- a/Lib/java/java.swg
+++ b/Lib/java/java.swg
@@ -4,6 +4,8 @@
* Java typemaps
* ----------------------------------------------------------------------------- */
+%include
+
%include
/* The jni, jtype and jstype typemaps work together and so there should be one of each.
diff --git a/Lib/lua/lua.swg b/Lib/lua/lua.swg
index 12c635d77..263c3966f 100644
--- a/Lib/lua/lua.swg
+++ b/Lib/lua/lua.swg
@@ -5,6 +5,8 @@
* This file is parsed by SWIG before reading any other interface file.
* ----------------------------------------------------------------------------- */
+%include
+
/* -----------------------------------------------------------------------------
* includes
* ----------------------------------------------------------------------------- */
diff --git a/Lib/mzscheme/mzscheme.swg b/Lib/mzscheme/mzscheme.swg
index f45c87250..8ded91f3e 100644
--- a/Lib/mzscheme/mzscheme.swg
+++ b/Lib/mzscheme/mzscheme.swg
@@ -5,6 +5,8 @@
* This file is parsed by SWIG before reading any other interface file.
* ----------------------------------------------------------------------------- */
+%include
+
/* Include headers */
%runtime "swigrun.swg" // Common C API type-checking code
%runtime "swigerrors.swg" // SWIG errors
diff --git a/Lib/ocaml/ocaml.i b/Lib/ocaml/ocaml.i
index cc26d1859..117d0a9b5 100644
--- a/Lib/ocaml/ocaml.i
+++ b/Lib/ocaml/ocaml.i
@@ -4,6 +4,8 @@
* SWIG Configuration File for Ocaml
* ----------------------------------------------------------------------------- */
+%include
+
/* Insert common stuff */
%insert(runtime) "swigrun.swg"
diff --git a/Lib/php/php.swg b/Lib/php/php.swg
index 04b7075b7..b22166593 100644
--- a/Lib/php/php.swg
+++ b/Lib/php/php.swg
@@ -4,6 +4,8 @@
* PHP configuration file
* ----------------------------------------------------------------------------- */
+%include
+
// Default to generating PHP type declarations (for PHP >= 8) except for
// cases which are liable to cause compatibility issues with existing
// bindings.
diff --git a/Lib/typemaps/README b/Lib/typemaps/README
index 65134578d..22a0fc0bb 100644
--- a/Lib/typemaps/README
+++ b/Lib/typemaps/README
@@ -48,6 +48,7 @@ std_strings.swg Common macros to implemented the std::string/std::wstring typem
strings.swg Common macros and typemaps for string and wstring (char *, wchar_t *)
swigmacros.swg Basic macros
+swigversion.swg Define SWIG_VERSION
fragments.swg Macros for fragment manipulations
diff --git a/Lib/typemaps/swigmacros.swg b/Lib/typemaps/swigmacros.swg
index 687b0680e..7db6871d4 100644
--- a/Lib/typemaps/swigmacros.swg
+++ b/Lib/typemaps/swigmacros.swg
@@ -109,15 +109,7 @@ nocppval
#endif
%enddef
-/* insert the SWIGVERSION in the interface and the wrapper code */
-#if SWIG_VERSION
-%insert("header") {
-%define_as(SWIGVERSION, SWIG_VERSION)
-%#define SWIG_VERSION SWIGVERSION
-}
-#endif
-
-
+%include
/* -----------------------------------------------------------------------------
* Casting operators
diff --git a/Lib/typemaps/swigversion.swg b/Lib/typemaps/swigversion.swg
new file mode 100644
index 000000000..18f897cad
--- /dev/null
+++ b/Lib/typemaps/swigversion.swg
@@ -0,0 +1,17 @@
+/* -----------------------------------------------------------------------------
+ * Define SWIG_VERSION
+ * ----------------------------------------------------------------------------- */
+
+/* Define SWIG_VERSION in the interface and the wrapper code.
+ *
+ * Best practice is to use SWIG-time checks for SWIG_VERSION, but SWIG_VERSION
+ * was unintentionally defined like this for many years, and while it was never
+ * documented there are likely user interface files which rely on it.
+ */
+%define %define_swig_version_()%#define SWIG_VERSION_ SWIG_VERSION %enddef
+%insert("header") {
+%define_swig_version_()
+%#define SWIG_VERSION SWIG_VERSION_
+%#undef SWIG_VERSION_
+}
+#undef %define_swig_version_
diff --git a/Source/Modules/go.cxx b/Source/Modules/go.cxx
index 1692e905a..7f0ccbe8b 100644
--- a/Source/Modules/go.cxx
+++ b/Source/Modules/go.cxx
@@ -515,6 +515,8 @@ private:
}
Printf(f_c_runtime, "#define SWIGMODULE %s\n", module);
+ Printf(f_c_runtime, "#ifndef SWIGGO\n#define SWIGGO\n#endif\n\n");
+
if (gccgo_flag) {
Printf(f_c_runtime, "#define SWIGGO_PREFIX %s\n", go_prefix);
}
diff --git a/Source/Modules/javascript.cxx b/Source/Modules/javascript.cxx
index b17c5e503..e6e47e3f3 100644
--- a/Source/Modules/javascript.cxx
+++ b/Source/Modules/javascript.cxx
@@ -1615,6 +1615,8 @@ int JSCEmitter::initialize(Node *n) {
Swig_banner(f_wrap_cpp);
+ Printf(f_runtime, "#ifndef SWIGJAVASCRIPT\n#define SWIGJAVASCRIPT\n#endif\n\n");
+
return SWIG_OK;
}
@@ -1945,6 +1947,8 @@ int V8Emitter::initialize(Node *n) {
Swig_banner(f_wrap_cpp);
+ Printf(f_runtime, "#ifndef SWIGJAVASCRIPT\n#define SWIGJAVASCRIPT\n#endif\n\n");
+
return SWIG_OK;
}