Browse Source

Allow possibility of building Urho3D without C++ exceptions feature.
Disallow Android build to turn off C++ RTTI feature.

Yao Wei Tjong 姚伟忠 9 years ago
parent
commit
0c88c99112

+ 77 - 53
CMake/Modules/CheckCompilerToolchain.cmake

@@ -27,8 +27,9 @@
 #
 #
 # Target architecture:
 # Target architecture:
 #  ARM
 #  ARM
-#  RPI
+#  MIPS
 #  POWERPC
 #  POWERPC
+#  X86
 #
 #
 # Compiler version in major.minor.patch format, except MSVC where it follows its own format:
 # Compiler version in major.minor.patch format, except MSVC where it follows its own format:
 #  COMPILER_VERSION
 #  COMPILER_VERSION
@@ -44,6 +45,10 @@
 #  HAVE_NEON
 #  HAVE_NEON
 #  NEON
 #  NEON
 #
 #
+# C++ features:
+#  RTTI
+#  EXCEPTIONS
+#
 
 
 if (EMSCRIPTEN AND CMAKE_HOST_WIN32)
 if (EMSCRIPTEN AND CMAKE_HOST_WIN32)
     set (EMCC_FIX EMCC_FIX)
     set (EMCC_FIX EMCC_FIX)
@@ -51,22 +56,6 @@ if (EMSCRIPTEN AND CMAKE_HOST_WIN32)
     execute_process (COMMAND ${CMAKE_COMMAND} -E touch ${NULL_DEVICE${EMCC_FIX}})
     execute_process (COMMAND ${CMAKE_COMMAND} -E touch ${NULL_DEVICE${EMCC_FIX}})
 endif ()
 endif ()
 
 
-if (NOT MSVC AND NOT DEFINED CCT_NATIVE_PREDEFINED_MACROS)
-    if (IOS OR TVOS)
-        # Assume arm64 is the native arch (this does not prevent our build system to target armv7 later in universal binary build)
-        set (ARCH_FLAGS -arch arm64)
-    elseif (ANDROID AND CMAKE_CXX_COMPILER_ID MATCHES Clang)
-        # Use the same target flag as configured by Android/CMake toolchain file
-        string (REGEX REPLACE "^.*-target ([^ ]+).*$" "-target;\\1" ARCH_FLAGS "${CMAKE_CXX_FLAGS}")
-    endif ()
-    execute_process (COMMAND ${CMAKE_C_COMPILER} ${ARCH_FLAGS} -E -dM -xc ${NULL_DEVICE${EMCC_FIX}} RESULT_VARIABLE CC_EXIT_STATUS OUTPUT_VARIABLE CCT_NATIVE_PREDEFINED_MACROS ERROR_QUIET)
-    if (NOT CC_EXIT_STATUS EQUAL 0)
-        message (FATAL_ERROR "Could not check compiler toolchain as it does not handle '-E -dM' compiler flags correctly")
-    endif ()
-    string (REPLACE \n ";" CCT_NATIVE_PREDEFINED_MACROS "${CCT_NATIVE_PREDEFINED_MACROS}")    # Stringify for string replacement
-    set (CCT_NATIVE_PREDEFINED_MACROS ${CCT_NATIVE_PREDEFINED_MACROS} CACHE INTERNAL "Compiler toolchain native predefined macros")
-endif ()
-
 macro (check_native_define REGEX OUTPUT_VAR)
 macro (check_native_define REGEX OUTPUT_VAR)
     if (NOT DEFINED CCT_${OUTPUT_VAR})
     if (NOT DEFINED CCT_${OUTPUT_VAR})
         string (REGEX MATCH "#define +${REGEX} +([^;]+)" matched "${CCT_NATIVE_PREDEFINED_MACROS}")
         string (REGEX MATCH "#define +${REGEX} +([^;]+)" matched "${CCT_NATIVE_PREDEFINED_MACROS}")
@@ -87,33 +76,6 @@ macro (check_native_define REGEX OUTPUT_VAR)
     set (${OUTPUT_VAR} ${CCT_${OUTPUT_VAR}})
     set (${OUTPUT_VAR} ${CCT_${OUTPUT_VAR}})
 endmacro ()
 endmacro ()
 
 
-if (MSVC)
-    # TODO: revisit this later because VS may use Clang as compiler in the future
-    # On MSVC compiler, use the chosen CMake/VS generator to determine the ABI
-    set (NATIVE_64BIT ${CMAKE_CL_64})
-    # Determine MSVC compiler version based on CMake informational variables
-    set (COMPILER_VERSION ${MSVC_VERSION})
-else ()
-    # Determine the native ABI based on the size of pointer
-    check_native_define (__SIZEOF_POINTER__ SIZEOF_POINTER)
-    if (SIZEOF_POINTER EQUAL 8)
-        set (NATIVE_64BIT 1)
-    endif ()
-    # Android arm64 compiler only emits __aarch64__ while iOS arm64 emits __aarch64__, __arm64__, and __arm__; for armv7a all emit __arm__
-    check_native_define ("__(arm|aarch64)__" ARM)
-    # For completeness sake as currently we do not support PowerPC (yet)
-    check_native_define ("__(ppc|PPC|powerpc|POWERPC)(64)*__" POWERPC)
-    # GCC/Clang and all their derivatives should understand this command line option to get the compiler version
-    if (NOT DEFINED COMPILER_VERSION)
-        if (EMSCRIPTEN)
-            set (COMPILER_VERSION ${EMSCRIPTEN_EMCC_VERSION})
-        else ()
-            execute_process (COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE COMPILER_VERSION ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
-        endif ()
-        set (COMPILER_VERSION ${COMPILER_VERSION} CACHE INTERNAL "GCC/Clang Compiler version")
-    endif ()
-endif ()
-
 macro (check_extension EXTENSION)
 macro (check_extension EXTENSION)
     string (TOUPPER "${EXTENSION}" UCASE_EXT_NAME)   # Stringify to guard against empty variable
     string (TOUPPER "${EXTENSION}" UCASE_EXT_NAME)   # Stringify to guard against empty variable
     string (REGEX REPLACE [^=]+= "" UCASE_EXT_NAME "${UCASE_EXT_NAME}")
     string (REGEX REPLACE [^=]+= "" UCASE_EXT_NAME "${UCASE_EXT_NAME}")
@@ -138,18 +100,18 @@ macro (check_extension EXTENSION)
     set (HAVE_${UCASE_EXT_NAME} ${CCT_HAVE_${UCASE_EXT_NAME}})
     set (HAVE_${UCASE_EXT_NAME} ${CCT_HAVE_${UCASE_EXT_NAME}})
 endmacro ()
 endmacro ()
 
 
-macro (check_extension_enabled EXTENSION)
-    if (NOT DEFINED CCT_${EXTENSION})
-        set (COMPILER_FLAGS ${CMAKE_C_FLAGS})
+macro (check_feature_enabled FEATURE)
+    if (NOT DEFINED CCT_${FEATURE})
+        set (COMPILER_FLAGS ${CMAKE_CXX_FLAGS})
         separate_arguments (COMPILER_FLAGS)
         separate_arguments (COMPILER_FLAGS)
-        execute_process (COMMAND ${CMAKE_C_COMPILER} ${COMPILER_FLAGS} -E -dM -xc ${NULL_DEVICE} RESULT_VARIABLE CC_EXIT_STATUS OUTPUT_VARIABLE PREDEFINED_MACROS ERROR_QUIET)
-        if (NOT CC_EXIT_STATUS EQUAL 0)
+        execute_process (COMMAND ${CMAKE_CXX_COMPILER} ${COMPILER_FLAGS} -E -dM -xc++ ${NULL_DEVICE} RESULT_VARIABLE CXX_EXIT_STATUS OUTPUT_VARIABLE PREDEFINED_MACROS ERROR_QUIET)
+        if (NOT CXX_EXIT_STATUS EQUAL 0)
             message (FATAL_ERROR "Could not check compiler toolchain CPU instruction extension as it does not handle '-E -dM' compiler flags correctly")
             message (FATAL_ERROR "Could not check compiler toolchain CPU instruction extension as it does not handle '-E -dM' compiler flags correctly")
         endif ()
         endif ()
         if (NOT ${ARGN} STREQUAL "")
         if (NOT ${ARGN} STREQUAL "")
             set (EXPECTED_MACRO ${ARGN})
             set (EXPECTED_MACRO ${ARGN})
         else ()
         else ()
-            set (EXPECTED_MACRO __${EXTENSION}__)
+            set (EXPECTED_MACRO __${FEATURE})
         endif ()
         endif ()
         string (REGEX MATCH "#define +${EXPECTED_MACRO} +1" matched "${PREDEFINED_MACROS}")
         string (REGEX MATCH "#define +${EXPECTED_MACRO} +1" matched "${PREDEFINED_MACROS}")
         if (matched)
         if (matched)
@@ -157,16 +119,78 @@ macro (check_extension_enabled EXTENSION)
         else ()
         else ()
             set (matched 0)
             set (matched 0)
         endif ()
         endif ()
-        set (CCT_${EXTENSION} ${matched} CACHE INTERNAL "Is ${EXTENSION} enabled")
+        set (CCT_${FEATURE} ${matched} CACHE INTERNAL "Is ${FEATURE} enabled")
     endif ()
     endif ()
-    set (${EXTENSION} ${CCT_${EXTENSION}})
+    set (${FEATURE} ${CCT_${FEATURE}})
 endmacro ()
 endmacro ()
 
 
+if (INVALIDATE_CCT)
+    get_cmake_property (CACHE_VARIABLES CACHE_VARIABLES)
+    foreach (VAR ${CACHE_VARIABLES})
+        if (VAR MATCHES ^CCT_)
+            unset (${VAR} CACHE)
+        endif ()
+    endforeach ()
+endif ()
+
+if (NOT MSVC AND NOT DEFINED CCT_NATIVE_PREDEFINED_MACROS)
+    if (IOS OR TVOS)
+        # Assume arm64 is the native arch (this does not prevent our build system to target armv7 later in universal binary build)
+        set (ARCH_FLAGS -arch arm64)
+    elseif (ANDROID AND CMAKE_CXX_COMPILER_ID MATCHES Clang)
+        # Use the same target flag as configured by Android/CMake toolchain file
+        string (REGEX REPLACE "^.*-target ([^ ]+).*$" "-target;\\1" ARCH_FLAGS "${CMAKE_CXX_FLAGS}")
+    endif ()
+    execute_process (COMMAND ${CMAKE_C_COMPILER} ${ARCH_FLAGS} -E -dM -xc ${NULL_DEVICE} RESULT_VARIABLE CC_EXIT_STATUS OUTPUT_VARIABLE CCT_NATIVE_PREDEFINED_MACROS ERROR_QUIET)
+    if (NOT CC_EXIT_STATUS EQUAL 0)
+        message (FATAL_ERROR "Could not check compiler toolchain as it does not handle '-E -dM' compiler flags correctly")
+    endif ()
+    string (REPLACE \n ";" CCT_NATIVE_PREDEFINED_MACROS "${CCT_NATIVE_PREDEFINED_MACROS}")    # Stringify for string replacement
+    set (CCT_NATIVE_PREDEFINED_MACROS ${CCT_NATIVE_PREDEFINED_MACROS} CACHE INTERNAL "Compiler toolchain native predefined macros")
+endif ()
+
+if (MSVC)
+    # TODO: revisit this later because VS may use Clang as compiler in the future
+    # On MSVC compiler, use the chosen CMake/VS generator to determine the ABI
+    set (NATIVE_64BIT ${CMAKE_CL_64})
+    # We only support one target arch when using MSVC for now
+    set (X86 1)
+    # Determine MSVC compiler version based on CMake informational variables
+    set (COMPILER_VERSION ${MSVC_VERSION})
+    # Assume all C++ features are ON
+    set (RTTI 1)
+    set (EXCEPTIONS 1)
+else ()
+    # Determine the native ABI based on the size of pointer
+    check_native_define (__SIZEOF_POINTER__ SIZEOF_POINTER)
+    if (SIZEOF_POINTER EQUAL 8)
+        set (NATIVE_64BIT 1)
+    endif ()
+    # Android arm64 compiler only emits __aarch64__ while iOS arm64 emits __aarch64__, __arm64__, and __arm__; for armv7a all emit __arm__
+    check_native_define ("__(arm|aarch64)__" ARM)
+    # Compiler should emit __x86_64__, __i686__, or __i386__, etc when targeting archs using Intel or AMD processors
+    check_native_define ("__(i.86|x86_64)__" X86)
+    # For completeness sake as currently we do not support MIPS and PowerPC (yet)
+    check_native_define ("__MIPSEL__" MIPS)
+    check_native_define ("__(ppc|PPC|powerpc|POWERPC)(64)*__" POWERPC)
+    # GCC/Clang and all their derivatives should understand this command line option to get the compiler version
+    if (NOT DEFINED COMPILER_VERSION)
+        if (EMSCRIPTEN)
+            set (COMPILER_VERSION ${EMSCRIPTEN_EMCC_VERSION})
+        else ()
+            execute_process (COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE COMPILER_VERSION ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
+        endif ()
+        set (COMPILER_VERSION ${COMPILER_VERSION} CACHE INTERNAL "GCC/Clang Compiler version")
+    endif ()
+    check_feature_enabled (RTTI __GXX_RTTI)
+    check_feature_enabled (EXCEPTIONS)
+endif ()
+
 if (ARM)
 if (ARM)
     if (MSVC)
     if (MSVC)
         message (FATAL_ERROR "This build system does not support ARM build using MSVC compiler toolchain yet. Contribution is welcome.")
         message (FATAL_ERROR "This build system does not support ARM build using MSVC compiler toolchain yet. Contribution is welcome.")
     else ()
     else ()
-        check_extension_enabled (NEON __ARM_NEON)
+        check_feature_enabled (NEON __ARM_NEON)
         if (NEON)
         if (NEON)
             set (HAVE_NEON 1)
             set (HAVE_NEON 1)
         else ()
         else ()

+ 2 - 1
CMake/Modules/UrhoCommon.cmake

@@ -106,7 +106,8 @@ cmake_dependent_option (URHO3D_64BIT "Enable 64-bit build, the default is set ba
 option (URHO3D_ANGELSCRIPT "Enable AngelScript scripting support" TRUE)
 option (URHO3D_ANGELSCRIPT "Enable AngelScript scripting support" TRUE)
 option (URHO3D_LUA "Enable additional Lua scripting support" TRUE)
 option (URHO3D_LUA "Enable additional Lua scripting support" TRUE)
 option (URHO3D_NAVIGATION "Enable navigation support" TRUE)
 option (URHO3D_NAVIGATION "Enable navigation support" TRUE)
-cmake_dependent_option (URHO3D_NETWORK "Enable networking support" TRUE "NOT WEB" FALSE)
+# Urho's Network subsystem depends on kNet library which uses C++ exceptions feature
+cmake_dependent_option (URHO3D_NETWORK "Enable networking support" TRUE "NOT WEB AND EXCEPTIONS" FALSE)
 option (URHO3D_PHYSICS "Enable physics support" TRUE)
 option (URHO3D_PHYSICS "Enable physics support" TRUE)
 option (URHO3D_URHO2D "Enable 2D graphics and physics support" TRUE)
 option (URHO3D_URHO2D "Enable 2D graphics and physics support" TRUE)
 if (ARM AND NOT ANDROID AND NOT RPI AND NOT IOS AND NOT TVOS)
 if (ARM AND NOT ANDROID AND NOT RPI AND NOT IOS AND NOT TVOS)

+ 8 - 7
CMake/Toolchains/Android.cmake

@@ -246,12 +246,7 @@ if (NOT IN_TRY_COMPILE)
         # Invalidate internal caches that depend on ANDROID_ABI, if any
         # Invalidate internal caches that depend on ANDROID_ABI, if any
         unset (ANDROID_STL_SAVED CACHE)     # This should cause ANDROID_STL option to be revalidated
         unset (ANDROID_STL_SAVED CACHE)     # This should cause ANDROID_STL option to be revalidated
         if (CLANG)
         if (CLANG)
-            get_cmake_property (CACHE_VARIABLES CACHE_VARIABLES)
-            foreach (VAR ${CACHE_VARIABLES})
-                if (VAR MATCHES ^CCT_)
-                    unset (${VAR} CACHE)
-                endif ()
-            endforeach ()
+            set (INVALIDATE_CCT 1)
         endif ()
         endif ()
     endif ()
     endif ()
     # First, derive variable values based on chosen compiler toolchain
     # First, derive variable values based on chosen compiler toolchain
@@ -344,8 +339,14 @@ if (NOT IN_TRY_COMPILE)
 
 
     # C++ STL runtimes
     # C++ STL runtimes
     option (ANDROID_STL_FORCE_FEATURES "Automatically configure rtti and exceptions support based on the chosen C++ STL runtime" TRUE)
     option (ANDROID_STL_FORCE_FEATURES "Automatically configure rtti and exceptions support based on the chosen C++ STL runtime" TRUE)
-    cmake_dependent_option (ANDROID_RTTI "Set ON to enable RTTI" TRUE "NOT ANDROID_STL_FORCE_FEATURES" TRUE)
+    # Urho3D - always use RTTI due to dynamic cast usage in the codebase
+    #cmake_dependent_option (ANDROID_RTTI "Set ON to enable RTTI" TRUE "NOT ANDROID_STL_FORCE_FEATURES" TRUE)
+    set (ANDROID_RTTI 1)
     cmake_dependent_option (ANDROID_EXCEPTIONS "Set ON to enable C++ exceptions" TRUE "NOT ANDROID_STL_FORCE_FEATURES" TRUE)
     cmake_dependent_option (ANDROID_EXCEPTIONS "Set ON to enable C++ exceptions" TRUE "NOT ANDROID_STL_FORCE_FEATURES" TRUE)
+    if (NOT FEATURE_SIGNATURE STREQUAL "${ANDROID_STL_FORCE_FEATURES}-${ANDROID_RTTI}-${ANDROID_EXCEPTIONS}")
+        set (INVALIDATE_CCT 1)
+        set (FEATURE_SIGNATURE "${ANDROID_STL_FORCE_FEATURES}-${ANDROID_RTTI}-${ANDROID_EXCEPTIONS}" CACHE INTERNAL "Signature when the C++ features are last cached")
+    endif ()
     # Urho3D - warn if static runtime is chosen when using SHARED Urho3D library type
     # Urho3D - warn if static runtime is chosen when using SHARED Urho3D library type
     if (URHO3D_LIB_TYPE STREQUAL SHARED AND ANDROID_STL MATCHES static)
     if (URHO3D_LIB_TYPE STREQUAL SHARED AND ANDROID_STL MATCHES static)
         message (WARNING "Using static C++ STL runtime (${ANDROID_STL}) with SHARED Urho3D library type may result in unpredictable runtime behavior.")
         message (WARNING "Using static C++ STL runtime (${ANDROID_STL}) with SHARED Urho3D library type may result in unpredictable runtime behavior.")

+ 4 - 0
Source/ThirdParty/AngelScript/CMakeLists.txt

@@ -23,6 +23,10 @@
 # Define target name
 # Define target name
 set (TARGET_NAME AngelScript)
 set (TARGET_NAME AngelScript)
 
 
+# Define preprocessor macros
+if (NOT EXCEPTIONS)
+    add_definitions (-DAS_NO_EXCEPTIONS)
+endif ()
 # Add compiler define to build the library with the normal function/method macros
 # Add compiler define to build the library with the normal function/method macros
 add_definitions (-DAS_IS_BUILDING)
 add_definitions (-DAS_IS_BUILDING)
 
 

+ 4 - 3
Source/Urho3D/Engine/Application.cpp

@@ -62,11 +62,10 @@ Application::Application(Context* context) :
 
 
 int Application::Run()
 int Application::Run()
 {
 {
-    // Emscripten-specific: C++ exceptions are turned off by default in -O1 (and above), unless '-s DISABLE_EXCEPTION_CATCHING=0' flag is set
-    // Urho3D build configuration uses -O3 (Release), -O2 (RelWithDebInfo), and -O0 (Debug)
-    // Thus, the try-catch block below should be optimised out except in Debug build configuration
+#if !defined(__GNUC__) || __EXCEPTIONS
     try
     try
     {
     {
+#endif
         Setup();
         Setup();
         if (exitCode_)
         if (exitCode_)
             return exitCode_;
             return exitCode_;
@@ -98,12 +97,14 @@ int Application::Run()
 #endif
 #endif
 
 
         return exitCode_;
         return exitCode_;
+#if !defined(__GNUC__) || __EXCEPTIONS
     }
     }
     catch (std::bad_alloc&)
     catch (std::bad_alloc&)
     {
     {
         ErrorDialog(GetTypeName(), "An out-of-memory error occurred. The application will now exit.");
         ErrorDialog(GetTypeName(), "An out-of-memory error occurred. The application will now exit.");
         return EXIT_FAILURE;
         return EXIT_FAILURE;
     }
     }
+#endif
 }
 }
 
 
 void Application::ErrorExit(const String& message)
 void Application::ErrorExit(const String& message)