Merge pull request #21349 from alalek:cmake_link_no_undefined
[platform/upstream/opencv.git] / cmake / OpenCVCompilerOptions.cmake
index dd4dcc2..90f1896 100644 (file)
@@ -8,13 +8,27 @@ function(access_CMAKE_COMPILER_IS_CCACHE)
   endif()
 endfunction()
 variable_watch(CMAKE_COMPILER_IS_CCACHE access_CMAKE_COMPILER_IS_CCACHE)
-if(ENABLE_CCACHE AND NOT OPENCV_COMPILER_IS_CCACHE AND NOT CMAKE_GENERATOR MATCHES "Xcode")
+if(ENABLE_CCACHE AND NOT OPENCV_COMPILER_IS_CCACHE)
   # This works fine with Unix Makefiles and Ninja generators
   find_host_program(CCACHE_PROGRAM ccache)
   if(CCACHE_PROGRAM)
     message(STATUS "Looking for ccache - found (${CCACHE_PROGRAM})")
     get_property(__OLD_RULE_LAUNCH_COMPILE GLOBAL PROPERTY RULE_LAUNCH_COMPILE)
-    if(__OLD_RULE_LAUNCH_COMPILE)
+    if(CMAKE_GENERATOR MATCHES "Xcode")
+      configure_file("${CMAKE_CURRENT_LIST_DIR}/templates/xcode-launch-c.in" "${CMAKE_BINARY_DIR}/xcode-launch-c")
+      configure_file("${CMAKE_CURRENT_LIST_DIR}/templates/xcode-launch-cxx.in" "${CMAKE_BINARY_DIR}/xcode-launch-cxx")
+      execute_process(COMMAND chmod a+rx
+          "${CMAKE_BINARY_DIR}/xcode-launch-c"
+          "${CMAKE_BINARY_DIR}/xcode-launch-cxx"
+      )
+      # Xcode project attributes
+      set(CMAKE_XCODE_ATTRIBUTE_CC         "${CMAKE_BINARY_DIR}/xcode-launch-c")
+      set(CMAKE_XCODE_ATTRIBUTE_CXX        "${CMAKE_BINARY_DIR}/xcode-launch-cxx")
+      set(CMAKE_XCODE_ATTRIBUTE_LD         "${CMAKE_BINARY_DIR}/xcode-launch-c")
+      set(CMAKE_XCODE_ATTRIBUTE_LDPLUSPLUS "${CMAKE_BINARY_DIR}/xcode-launch-cxx")
+      set(OPENCV_COMPILER_IS_CCACHE 1)
+      message(STATUS "ccache: enable support through Xcode project properties")
+    elseif(__OLD_RULE_LAUNCH_COMPILE)
       message(STATUS "Can't replace CMake compiler launcher")
     else()
       set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}")
@@ -120,7 +134,6 @@ if(CV_GCC OR CV_CLANG)
   add_extra_compiler_option(-Wshadow)
   add_extra_compiler_option(-Wsign-promo)
   add_extra_compiler_option(-Wuninitialized)
-  add_extra_compiler_option(-Winit-self)
   if(CV_GCC AND (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 6.0) AND (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0))
     add_extra_compiler_option(-Wno-psabi)
   endif()
@@ -151,6 +164,10 @@ if(CV_GCC OR CV_CLANG)
     if(CV_GCC AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0)
       add_extra_compiler_option(-Wno-missing-field-initializers)  # GCC 4.x emits warnings about {}, fixed in GCC 5+
     endif()
+    if(CV_CLANG AND NOT CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 10.0)
+      add_extra_compiler_option(-Wno-deprecated-enum-enum-conversion)
+      add_extra_compiler_option(-Wno-deprecated-anon-enum-enum-conversion)
+    endif()
   endif()
   add_extra_compiler_option(-fdiagnostics-show-option)
 
@@ -160,7 +177,13 @@ if(CV_GCC OR CV_CLANG)
   endif()
 
   # We need pthread's
-  if(UNIX AND NOT ANDROID AND NOT (APPLE AND CV_CLANG)) # TODO
+  if((UNIX
+          AND NOT ANDROID
+          AND NOT (APPLE AND CV_CLANG)
+          AND NOT EMSCRIPTEN
+      )
+      OR (EMSCRIPTEN AND WITH_PTHREADS_PF)  # https://github.com/opencv/opencv/issues/20285
+  )
     add_extra_compiler_option(-pthread)
   endif()
 
@@ -185,7 +208,6 @@ if(CV_GCC OR CV_CLANG)
 
   # Profiling?
   if(ENABLE_PROFILING)
-    add_extra_compiler_option("-pg -g")
     # turn off incompatible options
     foreach(flags CMAKE_CXX_FLAGS CMAKE_C_FLAGS CMAKE_CXX_FLAGS_RELEASE CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_DEBUG CMAKE_C_FLAGS_DEBUG
                   OPENCV_EXTRA_FLAGS_RELEASE OPENCV_EXTRA_FLAGS_DEBUG OPENCV_EXTRA_C_FLAGS OPENCV_EXTRA_CXX_FLAGS)
@@ -193,6 +215,9 @@ if(CV_GCC OR CV_CLANG)
       string(REPLACE "-ffunction-sections" "" ${flags} "${${flags}}")
       string(REPLACE "-fdata-sections" "" ${flags} "${${flags}}")
     endforeach()
+    # -pg should be placed both in the linker and in the compiler settings
+    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg")
+    add_extra_compiler_option("-pg -g")
   else()
     if(MSVC)
       # TODO: Clang/C2 is not supported
@@ -206,9 +231,11 @@ if(CV_GCC OR CV_CLANG)
         if(APPLE)
           set(OPENCV_EXTRA_EXE_LINKER_FLAGS "${OPENCV_EXTRA_EXE_LINKER_FLAGS} -Wl,-dead_strip")
           set(OPENCV_EXTRA_SHARED_LINKER_FLAGS "${OPENCV_EXTRA_SHARED_LINKER_FLAGS} -Wl,-dead_strip")
+          set(OPENCV_EXTRA_MODULE_LINKER_FLAGS "${OPENCV_EXTRA_MODULE_LINKER_FLAGS} -Wl,-dead_strip")
         else()
           set(OPENCV_EXTRA_EXE_LINKER_FLAGS "${OPENCV_EXTRA_EXE_LINKER_FLAGS} -Wl,--gc-sections")
           set(OPENCV_EXTRA_SHARED_LINKER_FLAGS "${OPENCV_EXTRA_SHARED_LINKER_FLAGS} -Wl,--gc-sections")
+          set(OPENCV_EXTRA_MODULE_LINKER_FLAGS "${OPENCV_EXTRA_MODULE_LINKER_FLAGS} -Wl,--gc-sections")
         endif()
       endif()
     endif()
@@ -260,6 +287,7 @@ if(MSVC)
     set(OPENCV_EXTRA_FLAGS_RELEASE "${OPENCV_EXTRA_FLAGS_RELEASE} /Zi")
     set(OPENCV_EXTRA_EXE_LINKER_FLAGS_RELEASE "${OPENCV_EXTRA_EXE_LINKER_FLAGS_RELEASE} /debug")
     set(OPENCV_EXTRA_SHARED_LINKER_FLAGS_RELEASE "${OPENCV_EXTRA_SHARED_LINKER_FLAGS_RELEASE} /debug")
+    set(OPENCV_EXTRA_MODULE_LINKER_FLAGS_RELEASE "${OPENCV_EXTRA_MODULE_LINKER_FLAGS_RELEASE} /debug")
   endif()
 
   # Remove unreferenced functions: function level linking
@@ -327,6 +355,23 @@ if(NOT OPENCV_SKIP_LINK_AS_NEEDED)
     if(HAVE_LINK_AS_NEEDED)
       set(OPENCV_EXTRA_EXE_LINKER_FLAGS "${OPENCV_EXTRA_EXE_LINKER_FLAGS} ${_option}")
       set(OPENCV_EXTRA_SHARED_LINKER_FLAGS "${OPENCV_EXTRA_SHARED_LINKER_FLAGS} ${_option}")
+      set(OPENCV_EXTRA_MODULE_LINKER_FLAGS "${OPENCV_EXTRA_MODULE_LINKER_FLAGS} ${_option}")
+    endif()
+  endif()
+endif()
+
+# Apply "-Wl,--no-undefined" linker flags: https://github.com/opencv/opencv/pull/21347
+if(NOT OPENCV_SKIP_LINK_NO_UNDEFINED)
+  if(UNIX AND (NOT APPLE OR NOT CMAKE_VERSION VERSION_LESS "3.2"))
+    set(_option "-Wl,--no-undefined")
+    set(_saved_CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}")
+    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${_option}")  # requires CMake 3.2+ and CMP0056
+    ocv_check_compiler_flag(CXX "" HAVE_LINK_NO_UNDEFINED)
+    set(CMAKE_EXE_LINKER_FLAGS "${_saved_CMAKE_EXE_LINKER_FLAGS}")
+    if(HAVE_LINK_NO_UNDEFINED)
+      set(OPENCV_EXTRA_EXE_LINKER_FLAGS "${OPENCV_EXTRA_EXE_LINKER_FLAGS} ${_option}")
+      set(OPENCV_EXTRA_SHARED_LINKER_FLAGS "${OPENCV_EXTRA_SHARED_LINKER_FLAGS} ${_option}")
+      set(OPENCV_EXTRA_MODULE_LINKER_FLAGS "${OPENCV_EXTRA_MODULE_LINKER_FLAGS} ${_option}")
     endif()
   endif()
 endif()
@@ -345,6 +390,9 @@ if(NOT OPENCV_SKIP_EXTRA_COMPILER_FLAGS)
   set(CMAKE_SHARED_LINKER_FLAGS         "${CMAKE_SHARED_LINKER_FLAGS} ${OPENCV_EXTRA_SHARED_LINKER_FLAGS}")
   set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} ${OPENCV_EXTRA_SHARED_LINKER_FLAGS_RELEASE}")
   set(CMAKE_SHARED_LINKER_FLAGS_DEBUG   "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} ${OPENCV_EXTRA_SHARED_LINKER_FLAGS_DEBUG}")
+  set(CMAKE_MODULE_LINKER_FLAGS         "${CMAKE_MODULE_LINKER_FLAGS} ${OPENCV_EXTRA_MODULE_LINKER_FLAGS}")
+  set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} ${OPENCV_EXTRA_MODULE_LINKER_FLAGS_RELEASE}")
+  set(CMAKE_MODULE_LINKER_FLAGS_DEBUG   "${CMAKE_MODULE_LINKER_FLAGS_DEBUG} ${OPENCV_EXTRA_MODULE_LINKER_FLAGS_DEBUG}")
 endif()
 
 if(MSVC)
@@ -368,6 +416,9 @@ if(MSVC)
     endif()
   endif()
 
+  # Enable [[attribute]] syntax checking to prevent silent failure: "attribute is ignored in this syntactic position"
+  add_extra_compiler_option("/w15240")
+
   if(NOT ENABLE_NOISY_WARNINGS)
     ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4127) # conditional expression is constant
     ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4251) # class 'std::XXX' needs to have dll-interface to be used by clients of YYY
@@ -442,3 +493,38 @@ if(OPENCV_EXTRA_RPATH_LINK_PATH)
     message(WARNING "OPENCV_EXTRA_RPATH_LINK_PATH may not work properly because CMAKE_EXECUTABLE_RPATH_LINK_CXX_FLAG is not defined (not supported)")
   endif()
 endif()
+
+# Control MSVC /MP flag
+# Input variables: OPENCV_MSVC_PARALLEL (ON,1,2,3,...) + OPENCV_SKIP_MSVC_PARALLEL
+# Details:
+# - https://docs.microsoft.com/en-us/cpp/build/reference/mp-build-with-multiple-processes
+# - https://docs.microsoft.com/en-us/cpp/build/reference/cl-environment-variables
+# - https://gitlab.kitware.com/cmake/cmake/merge_requests/1718/diffs
+if(CMAKE_GENERATOR MATCHES "Visual Studio" AND CMAKE_CXX_COMPILER_ID MATCHES "MSVC|Intel")
+  ocv_check_environment_variables(OPENCV_SKIP_MSVC_PARALLEL)
+  if(OPENCV_SKIP_MSVC_PARALLEL)
+    # nothing
+  elseif(" ${CMAKE_CXX_FLAGS}" MATCHES "/MP")
+    # nothing, already defined in compiler flags
+  elseif(DEFINED ENV{CL} AND " $ENV{CL}" MATCHES "/MP")
+    # nothing, compiler will use CL environment variable
+  elseif(DEFINED ENV{_CL_} AND " $ENV{_CL_}" MATCHES "/MP")
+    # nothing, compiler will use _CL_ environment variable
+  else()
+    ocv_check_environment_variables(OPENCV_MSVC_PARALLEL)
+    set(_mp_value "ON")
+    if(DEFINED OPENCV_MSVC_PARALLEL)
+      set(_mp_value "${OPENCV_MSVC_PARALLEL}")
+    endif()
+    set(OPENCV_MSVC_PARALLEL "${_mp_value}" CACHE STRING "Control MSVC /MP flag")
+    if(_mp_value)
+      if(_mp_value GREATER 0)
+        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP${_mp_value}")
+        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP${_mp_value}")
+      else()
+        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP")
+        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
+      endif()
+    endif()
+  endif()
+endif()