Windows: Add support for building with clang.
authorRay Molenkamp <github@lazydodo.com>
Mon, 28 May 2018 20:34:47 +0000 (14:34 -0600)
committerRay Molenkamp <github@lazydodo.com>
Mon, 28 May 2018 20:34:47 +0000 (14:34 -0600)
This commit contains the minimum to make clang build/work with blender, asan and ninja build support is forthcoming

Things to note:

1) Builds and runs, and is able to pass all tests (except for the freestyle_stroke_material.blend test which was broken at that time for all platforms by the looks of it)

2) It's slightly faster than msvc when using cycles. (time in seconds, on an i7-3370)

victor_cpu
msvc:3099.51
clang:2796.43

pavillon_barcelona_cpu
msvc:1872.05
clang:1827.72

koro_cpu
msvc:1097.58
clang:1006.51

fishy_cat_cpu
msvc:815.37
clang:722.2

classroom_cpu
msvc:1705.39
clang:1575.43

bmw27_cpu
msvc:552.38
clang:561.53

barbershop_interior_cpu
msvc:2134.93
clang:1922.33

3) clang on windows uses a drop in replacement for the Microsoft cl.exe (takes some of the Microsoft parameters, but not all, and takes some of the clang parameters but not all) and uses ms headers + libraries + linker, so you still need visual studio installed and will use our existing vc14 svn libs.

4) X64 only currently, X86 builds but crashes on startup.

5) Tested with llvm/clang 6.0.0

6) Requires visual studio integration, available at https://github.com/LazyDodo/llvm-vs2017-integration

7) The Microsoft compiler spawns a few copies of cl in parallel to get faster build times, clang doesn't, so the build time is 3-4x slower than with msvc.

8) No openmp support yet. Have not looked at this much, the binary distribution of clang doesn't seem to include it on windows.

9) No ASAN support yet, some of the sanitizers can be made to work, but it was decided to leave support out of this commit.

Reviewers: campbellbarton

Differential Revision: https://developer.blender.org/D3304

20 files changed:
CMakeLists.txt
build_files/build_environment/patches/boost.diff
build_files/build_environment/patches/osl.diff
build_files/cmake/platform/platform_win32.cmake
build_files/windows/configure_msbuild.cmd
build_files/windows/configure_ninja.cmd
build_files/windows/parse_arguments.cmd
build_files/windows/reset_variables.cmd
extern/Eigen3/Eigen/src/Core/arch/SSE/PacketMath.h
extern/Eigen3/patches/blender.diff [new file with mode: 0644]
extern/bullet2/patches/blender.patch
extern/bullet2/src/LinearMath/btScalar.h
intern/atomic/intern/atomic_ops_msvc.h
intern/cycles/CMakeLists.txt
intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h
source/blender/blenkernel/intern/rigidbody.c
source/blender/blenlib/BLI_utildefines.h
source/blender/bmesh/CMakeLists.txt
source/blender/makesrna/intern/makesrna.c
source/blender/python/intern/stubs.c

index 0388e251b6fff87f50c6ec9b08b5631b3bead0f5..6ffe87da673623193ec657d6e5195693b9e84d6e 100644 (file)
@@ -1612,7 +1612,12 @@ else()
 endif()
 
 # Visual Studio has all standards it supports available by default
-if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang" OR CMAKE_C_COMPILER_ID MATCHES "Intel")
+# Clang on windows copies this behavior and does not support these switches
+if(
+       CMAKE_COMPILER_IS_GNUCC OR
+       (CMAKE_C_COMPILER_ID MATCHES "Clang" AND (NOT MSVC)) OR
+       (CMAKE_C_COMPILER_ID MATCHES "Intel")
+)
        # Use C99 + GNU extensions, works with GCC, Clang, ICC
        if(WITH_C11)
                set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu11")
index ea3ec035518d79a620fbd3629b1b93fb67914baa..41b40d7a9150938b7c63c995073d7b39150ca89b 100644 (file)
 -#     pragma message("Unknown compiler version - please run the configure tests and report the results")
 -#  endif
 -#endif
+--- a/boost/type_traits/has_nothrow_assign.hpp 2015-12-13 05:49:42 -0700
++++ b/boost/type_traits/has_nothrow_assign.hpp 2018-05-27 11:11:02 -0600
+@@ -24,7 +24,7 @@
+ #include <boost/type_traits/remove_reference.hpp>
+ #endif
+ #endif
+-#if defined(__GNUC__) || defined(__SUNPRO_CC)
++#if defined(__GNUC__) || defined(__SUNPRO_CC) || defined(__clang__)
+ #include <boost/type_traits/is_const.hpp>
+ #include <boost/type_traits/is_volatile.hpp>
+ #include <boost/type_traits/is_assignable.hpp>
+--- a/boost/type_traits/has_nothrow_constructor.hpp    2015-12-13 05:49:42 -0700
++++ b/boost/type_traits/has_nothrow_constructor.hpp    2018-05-27 11:11:02 -0600
+@@ -17,7 +17,7 @@
+ #if defined(BOOST_MSVC) || defined(BOOST_INTEL)
+ #include <boost/type_traits/has_trivial_constructor.hpp>
+ #endif
+-#if defined(__GNUC__ ) || defined(__SUNPRO_CC)
++#if defined(__GNUC__ ) || defined(__SUNPRO_CC) || defined(__clang__)
+ #include <boost/type_traits/is_default_constructible.hpp>
+ #endif
index fcb5ec4165fd40085e4035fb3a935a121e7f8b73..960a25063749ec2d1738b3c31420652d1db60cc1 100644 (file)
@@ -10,3 +10,29 @@ diff -Naur osl/src/external_osl/src/cmake/flexbison.cmake osl_bak/src/external_o
            MAIN_DEPENDENCY ${flexsrc}
            DEPENDS ${${compiler_headers}}
            WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} )
+--- a/src/include/OSL/oslconfig.h      2016-10-31 16:48:19 -0600
++++ b/src/include/OSL/oslconfig.h      2018-05-27 11:18:08 -0600
+@@ -44,12 +44,18 @@
+ // same if another packages is compiling against OSL and using these headers
+ // (OSL may be C++11 but the client package may be older, or vice versa --
+ // use these two symbols to differentiate these cases, when important).
+-#if (__cplusplus >= 201402L)
+-#  define OSL_CPLUSPLUS_VERSION  14
+-#elif (__cplusplus >= 201103L)
+-#  define OSL_CPLUSPLUS_VERSION  11
++
++// Force C++03 for MSVC in blender since svn the libraries are build with that
++#if !defined(_MSC_VER)
++      #if (__cplusplus >= 201402L)
++      #  define OSL_CPLUSPLUS_VERSION  14
++      #elif (__cplusplus >= 201103L)
++      #  define OSL_CPLUSPLUS_VERSION  11
++      #else
++      #  define OSL_CPLUSPLUS_VERSION  3 /* presume C++03 */
++      #endif
+ #else
+-#  define OSL_CPLUSPLUS_VERSION  3 /* presume C++03 */
++      #  define OSL_CPLUSPLUS_VERSION  3 /* presume C++03 */
+ #endif
+ // Symbol export defines
index 3520ac9c075ed33cc9102c185ff57b7d03679a87..205040ac0cf2c6434a9d70972f8009448a35ec09 100644 (file)
@@ -29,7 +29,10 @@ if(NOT MSVC)
        message(FATAL_ERROR "Compiler is unsupported")
 endif()
 
-# Libraries configuration for Windows when compiling with MSVC.
+if(CMAKE_C_COMPILER_ID MATCHES "Clang")
+       set(MSVC_CLANG On)
+       file(TO_CMAKE_PATH $ENV{VCToolsRedistDir} MSVC_REDIST_DIR)
+endif()
 
 set_property(GLOBAL PROPERTY USE_FOLDERS ${WINDOWS_USE_VISUAL_STUDIO_FOLDERS})
 
@@ -121,8 +124,16 @@ include(InstallRequiredSystemLibraries)
 
 remove_cc_flag("/MDd" "/MD")
 
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /nologo /J /Gd /MP /EHsc")
-set(CMAKE_C_FLAGS     "${CMAKE_C_FLAGS} /nologo /J /Gd /MP")
+if(MSVC_CLANG) # Clangs version of cl doesn't support all flags 
+       if(NOT WITH_CXX11) # C++11 is on by default in clang-cl and can't be turned off, if c++11 is not enabled in blender repress some c++11 related warnings. 
+               set(CXX_WARN_FLAGS "-Wno-inconsistent-missing-override")
+       endif()
+       set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_WARN_FLAGS} /nologo /J /Gd /EHsc -Wno-unused-command-line-argument -Wno-microsoft-enum-forward-reference ")
+       set(CMAKE_C_FLAGS     "${CMAKE_C_FLAGS} /nologo /J /Gd -Wno-unused-command-line-argument -Wno-microsoft-enum-forward-reference")
+else()
+       set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /nologo /J /Gd /MP /EHsc")
+       set(CMAKE_C_FLAGS     "${CMAKE_C_FLAGS} /nologo /J /Gd /MP")
+endif()
 
 set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
 set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MTd")
index 135b7933ab25292f97acb06f989b1b7656de4a6c..95a8882a9ab4e5c38516940551fbb60169e6533e 100644 (file)
@@ -4,6 +4,10 @@ if "%BUILD_ARCH%"=="x64" (
        set MSBUILD_PLATFORM=x64
 ) else if "%BUILD_ARCH%"=="x86" (
        set MSBUILD_PLATFORM=win32
+       if "%WITH_CLANG%"=="1" (
+               echo Clang not supported for X86
+               exit /b 1
+       )
 )
 
 if NOT EXIST %BUILD_DIR%\nul (
index 13797543bcc3746e13945b2b693bdfc02fce5604..24911a10275c394d510c4b62ac08b1eb184166b4 100644 (file)
@@ -1,4 +1,10 @@
 set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -G "Ninja" %TESTS_CMAKE_ARGS% -DCMAKE_BUILD_TYPE=%BUILD_TYPE%
+
+if "%WITH_CLANG%" == "1" (
+       echo Building with ninja and clang not supported yet.
+       exit /b 1
+)
+
 :DetectionComplete
 if NOT "%verbose%" == "" (
        echo BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% 
index 5a82bf3cf04fcb78b2532b55ccb9bb2f2b08b4f4..1cb2e1f3e8ca237b92d5e4ed526f213aa224135b 100644 (file)
@@ -36,6 +36,9 @@ if NOT "%1" == "" (
        ) else if "%1" == "bpy" (
                set TARGET=Bpy
                set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -C"%BLENDER_DIR%\build_files\cmake\config\bpy_module.cmake"
+       ) else if "%1" == "clang" (
+               set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -T"LLVM-vs2017"
+               set WITH_CLANG=1
        ) else if "%1" == "release" (
                set TARGET=Release
        ) else if "%1" == "x86" (
index 34af3ff938900bd66f8691282e960303af879bce..d9a50a7f8090af236df1c3d718b7b609d4d4cefc 100644 (file)
@@ -21,3 +21,4 @@ set BUILD_UPDATE=
 set BUILD_SHOW_HASHES=
 set SHOW_HELP=
 set BUILD_WITH_NINJA=
+set WITH_CLANG=
\ No newline at end of file
index fc8ae50fed77044310d5a4f0aea1b0bafcf0ab4a..cb535e1b78f307de5bba39ba74a617b4248f8d4f 100644 (file)
@@ -335,7 +335,7 @@ template<> EIGEN_STRONG_INLINE void prefetch<float>(const float*   addr) { _mm_p
 template<> EIGEN_STRONG_INLINE void prefetch<double>(const double* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); }
 template<> EIGEN_STRONG_INLINE void prefetch<int>(const int*       addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); }
 
-#if defined(_MSC_VER) && defined(_WIN64) && !defined(__INTEL_COMPILER)
+#if defined(_MSC_VER) && defined(_WIN64) && !defined(__INTEL_COMPILER) && !defined(__clang__)
 // The temporary variable fixes an internal compilation error in vs <= 2008 and a wrong-result bug in vs 2010
 // Direct of the struct members fixed bug #62.
 template<> EIGEN_STRONG_INLINE float  pfirst<Packet4f>(const Packet4f& a) { return a.m128_f32[0]; }
diff --git a/extern/Eigen3/patches/blender.diff b/extern/Eigen3/patches/blender.diff
new file mode 100644 (file)
index 0000000..3d7ba6e
--- /dev/null
@@ -0,0 +1,12 @@
+diff -Naur c:\blender-git\blender\extern\Eigen3/Eigen/src/Core/arch/SSE/PacketMath.h k:\BlenderGit\blender\extern\Eigen3/Eigen/src/Core/arch/SSE/PacketMath.h
+--- c:\blender-git\blender\extern\Eigen3/Eigen/src/Core/arch/SSE/PacketMath.h  2018-05-25 13:29:14 -0600
++++ k:\BlenderGit\blender\extern\Eigen3/Eigen/src/Core/arch/SSE/PacketMath.h   2018-05-26 19:56:36 -0600
+@@ -335,7 +335,7 @@
+ template<> EIGEN_STRONG_INLINE void prefetch<double>(const double* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); }
+ template<> EIGEN_STRONG_INLINE void prefetch<int>(const int*       addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); }
+-#if defined(_MSC_VER) && defined(_WIN64) && !defined(__INTEL_COMPILER)
++#if defined(_MSC_VER) && defined(_WIN64) && !defined(__INTEL_COMPILER) && !defined(__clang__)
+ // The temporary variable fixes an internal compilation error in vs <= 2008 and a wrong-result bug in vs 2010
+ // Direct of the struct members fixed bug #62.
+ template<> EIGEN_STRONG_INLINE float  pfirst<Packet4f>(const Packet4f& a) { return a.m128_f32[0]; }
index 96357ddd31573cee049370b766df5783ee81210c..cb3bf2ba38a0b9015d2e9a72e9d19f7c884de6fa 100644 (file)
@@ -1,3 +1,34 @@
+diff --git a/extern/bullet2/src/LinearMath/btScalar.h b/extern/bullet2/src/LinearMath/btScalar.h
+--- a/extern/bullet2/src/LinearMath/btScalar.h
++++ b/extern/bullet2/src/LinearMath/btScalar.h
+@@ -16,6 +16,9 @@
+ #ifndef BT_SCALAR_H
+ #define BT_SCALAR_H
++#if defined(_MSC_VER) && defined(__clang__) /* clang supplies it's own overloads already */
++#define BT_NO_SIMD_OPERATOR_OVERLOADS
++#endif
+ #ifdef BT_MANAGED_CODE
+ //Aligned data types not supported in managed code
+@@ -83,7 +86,7 @@
+                       #ifdef BT_USE_SSE
+ #if (_MSC_FULL_VER >= 170050727)//Visual Studio 2012 can compile SSE4/FMA3 (but SSE4/FMA3 is not enabled by default)
+-                      #define BT_ALLOW_SSE4
++                      //#define BT_ALLOW_SSE4 //disable this cause blender targets sse2 
+ #endif //(_MSC_FULL_VER >= 160040219)
+                       //BT_USE_SSE_IN_API is disabled under Windows by default, because 
+@@ -102,7 +105,7 @@
+               #endif //__MINGW32__
+ #ifdef BT_DEBUG
+-      #ifdef _MSC_VER
++      #if defined(_MSC_VER) && !defined(__clang__)
+               #include <stdio.h>
+               #define btAssert(x) { if(!(x)){printf("Assert "__FILE__ ":%u ("#x")\n", __LINE__);__debugbreak();       }}
+       #else//_MSC_VER
 diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h
 index be9eca6..ec40c96 100644
 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h
index 0bfd255bdb4244c242842a1740befbc6e148e9c8..898669f86e2c82bfe3878158bc7ff0c726ef51c2 100644 (file)
@@ -16,6 +16,9 @@ subject to the following restrictions:
 
 #ifndef BT_SCALAR_H
 #define BT_SCALAR_H
+#if defined(_MSC_VER) && defined(__clang__) /* clang supplies it's own overloads already */
+#define BT_NO_SIMD_OPERATOR_OVERLOADS
+#endif
 
 #ifdef BT_MANAGED_CODE
 //Aligned data types not supported in managed code
@@ -83,7 +86,7 @@ inline int    btGetVersion()
                        #ifdef BT_USE_SSE
 
 #if (_MSC_FULL_VER >= 170050727)//Visual Studio 2012 can compile SSE4/FMA3 (but SSE4/FMA3 is not enabled by default)
-                       #define BT_ALLOW_SSE4
+                       //#define BT_ALLOW_SSE4 //disable this cause blender targets sse2 
 #endif //(_MSC_FULL_VER >= 160040219)
 
                        //BT_USE_SSE_IN_API is disabled under Windows by default, because 
@@ -102,7 +105,7 @@ inline int  btGetVersion()
                #endif //__MINGW32__
 
 #ifdef BT_DEBUG
-       #ifdef _MSC_VER
+       #if defined(_MSC_VER) && !defined(__clang__)
                #include <stdio.h>
                #define btAssert(x) { if(!(x)){printf("Assert "__FILE__ ":%u ("#x")\n", __LINE__);__debugbreak();       }}
        #else//_MSC_VER
index c24a909573536088d75b2cf8ad39eea3b6d31025..39ed4efe3a877c73bc1180f1d99cbb70c52554b9 100644 (file)
 #include <windows.h>
 #include <intrin.h>
 
-/******************************************************************************/
+#if defined (__clang__)
+#  pragma GCC diagnostic push
+#  pragma GCC diagnostic ignored "-Wincompatible-pointer-types"
+#endif
+
 /* 64-bit operations. */
 #if (LG_SIZEOF_PTR == 8 || LG_SIZEOF_INT == 8)
 /* Unsigned */
@@ -205,4 +209,9 @@ ATOMIC_INLINE int8_t atomic_fetch_and_or_int8(int8_t *p, int8_t b)
 #endif
 }
 
+
+#if defined (__clang__)
+#  pragma GCC diagnostic pop
+#endif
+
 #endif /* __ATOMIC_OPS_MSVC_H__ */
index c3305ac3dd82effda4e8c066e75874d5d2afbdbb..100a52625d159594bd885625db19fafb55ef84f6 100644 (file)
@@ -31,7 +31,7 @@ elseif(NOT WITH_CPU_SSE)
        set(CXX_HAS_SSE FALSE)
        set(CXX_HAS_AVX FALSE)
        set(CXX_HAS_AVX2 FALSE)
-elseif(WIN32 AND MSVC)
+elseif(WIN32 AND MSVC AND NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang")
        set(CXX_HAS_SSE TRUE)
        set(CXX_HAS_AVX TRUE)
        set(CXX_HAS_AVX2 TRUE)
@@ -306,7 +306,7 @@ if(WITH_CYCLES_CUDA_BINARIES AND (NOT WITH_CYCLES_CUBIN_COMPILER))
                elseif(${CUDA_VERSION} EQUAL "9.1")
                        set(MAX_MSVC 1911)
                endif()
-               if(NOT MSVC_VERSION LESS ${MAX_MSVC})
+               if(NOT MSVC_VERSION LESS ${MAX_MSVC} OR CMAKE_C_COMPILER_ID MATCHES "Clang")
                        message(STATUS "nvcc not supported for this compiler version, using cycles_cubin_cc instead.")
                        set(WITH_CYCLES_CUBIN_COMPILER ON)
                endif()
index 56c38d8101cb07c9baac4bd95a64edb9061e539a..7bf833eadbc9f8dfe0db924d8688e462ed2c4b1a 100644 (file)
@@ -349,7 +349,7 @@ template<typename T> struct TextureInterpolator  {
         * Only happens for AVX2 kernel and global __KERNEL_SSE__ vectorization
         * enabled.
         */
-#ifdef __GNUC__
+#if defined(__GNUC__) || defined(__clang__)
        static ccl_always_inline
 #else
        static ccl_never_inline
index b8873cca0fbeff1fefbeaae70cb7c515c326d76f..ecb8814dd70a1c601d05b09e6c93cb23f053f460 100644 (file)
@@ -1658,7 +1658,7 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime)
 #else  /* WITH_BULLET */
 
 /* stubs */
-#ifdef __GNUC__
+#if defined(__GNUC__) || defined(__clang__)
 #  pragma GCC diagnostic push
 #  pragma GCC diagnostic ignored "-Wunused-parameter"
 #endif
@@ -1684,7 +1684,7 @@ void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw) {}
 void BKE_rigidbody_rebuild_world(Scene *scene, float ctime) {}
 void BKE_rigidbody_do_simulation(Scene *scene, float ctime) {}
 
-#ifdef __GNUC__
+#if defined(__GNUC__) || defined(__clang__)
 #  pragma GCC diagnostic pop
 #endif
 
index c0b76aa9cbfa5e2c55e2ced3b4f8e164bf9d5785..75ddb5e739ccb8b85af222f1c22823ad42c97dc2 100644 (file)
@@ -552,13 +552,13 @@ extern bool BLI_memory_is_zero(const void *arr, const size_t arr_size);
 
 
 /* UNUSED macro, for function argument */
-#ifdef __GNUC__
+#if defined(__GNUC__) || defined(__clang__) 
 #  define UNUSED(x) UNUSED_ ## x __attribute__((__unused__))
 #else
 #  define UNUSED(x) UNUSED_ ## x
 #endif
 
-#ifdef __GNUC__
+#if defined(__GNUC__) || defined(__clang__) 
 #  define UNUSED_FUNCTION(x) __attribute__((__unused__)) UNUSED_ ## x
 #else
 #  define UNUSED_FUNCTION(x) UNUSED_ ## x
index 5245d24a0756edd4873c40328e0215fd0cf7ee2e..320bebc9958138f38742c5ec79435b21e0aa9eb9 100644 (file)
@@ -169,7 +169,7 @@ set(SRC
        bmesh_tools.h
 )
 
-if(MSVC)
+if(MSVC AND NOT MSVC_CLANG)
        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX /wd4101")
 endif()
 
index 26ce24d59110d556587fadaee81ad3dc2ce4adf5..e197a8a3a4dd68ae404c39c0b7f4083b1bdea1c9 100644 (file)
@@ -3445,7 +3445,7 @@ static void rna_generate(BlenderRNA *brna, FILE *f, const char *filename, const
 
        /* we want the included C files to have warnings enabled but for the generated code
         * ignore unused-parameter warnings which are hard to prevent */
-#ifdef __GNUC__
+#if defined( __GNUC__) || defined(__clang__)
        fprintf(f, "#pragma GCC diagnostic ignored \"-Wunused-parameter\"\n\n");
 #endif
 
index cc186be60ea5a58ede6b5d5555b129efcaabd27c..3b3a4d6d2fe03acfbc2c251dbd8e594444067d4e 100644 (file)
@@ -32,7 +32,7 @@
 
 #include "BPY_extern.h"
 
-#if defined(__GNUC__)
+#if defined(__GNUC__) || defined(__clang__)
 #  pragma GCC diagnostic error "-Wmissing-prototypes"
 #  pragma GCC diagnostic ignored "-Wunused-parameter"
 #endif