From beddc2af0afb78dcb4537e87a2204739f71f6026 Mon Sep 17 00:00:00 2001 From: Rashad Kanavath <rashad.kanavath@c-s.fr> Date: Wed, 12 Oct 2016 16:36:46 +0200 Subject: [PATCH] PKG: fixes for boost and shark build with cxx11 --- CMake/OTBCheckCpp11Keywords.cmake | 85 ++++++++++++++++++- CMake/otbCheckCXX11.cpp | 8 -- CMake/otbTestNullPtr.cpp | 6 -- CMake/otbTestOverride.cpp | 22 ----- CMake/otbTestUniquePtr.cpp | 14 --- .../Adapters/GdalAdapters/test/CMakeLists.txt | 5 +- Modules/ThirdParty/Boost/CMakeLists.txt | 11 ++- Modules/ThirdParty/MuParserX/CMakeLists.txt | 6 +- SuperBuild/CMake/External_boost.cmake | 69 +++++++++++---- SuperBuild/CMake/External_curl.cmake | 11 +-- SuperBuild/CMake/External_gdal.cmake | 6 +- SuperBuild/CMake/External_otb.cmake | 1 + SuperBuild/CMake/External_shark.cmake | 7 +- SuperBuild/CMake/SuperBuild_Macro.cmake | 7 ++ SuperBuild/CMakeLists.txt | 40 +++++++-- SuperBuild/patches/BOOST/CMakeLists.txt | 7 -- .../patches/BOOST/boost-1-fix-macx.diff | 12 +++ 17 files changed, 214 insertions(+), 103 deletions(-) delete mode 100644 CMake/otbCheckCXX11.cpp delete mode 100644 CMake/otbTestNullPtr.cpp delete mode 100644 CMake/otbTestOverride.cpp delete mode 100644 CMake/otbTestUniquePtr.cpp delete mode 100644 SuperBuild/patches/BOOST/CMakeLists.txt create mode 100644 SuperBuild/patches/BOOST/boost-1-fix-macx.diff diff --git a/CMake/OTBCheckCpp11Keywords.cmake b/CMake/OTBCheckCpp11Keywords.cmake index 31a30c5cde..0056461ca5 100644 --- a/CMake/OTBCheckCpp11Keywords.cmake +++ b/CMake/OTBCheckCpp11Keywords.cmake @@ -1,5 +1,82 @@ +include(CheckCXXSourceCompiles) + +unset(OTB_HAS_CXX11 CACHE) +CHECK_CXX_SOURCE_COMPILES(" +#ifdef _MSC_VER + #if _MSC_VER <= 1700 + #error Compiler is not C++11 compliant + #endif +#else + #if __cplusplus <= 199711L + #error Compiler is not C++11 compliant + #endif +#endif + +int main(int argc, char *argv[]) +{ + return 0; +} + +" +OTB_HAS_CXX11 ) + +unset(OTB_CXX_HAS_UNIQUE_PTR CACHE) +CHECK_CXX_SOURCE_COMPILES(" +#include <memory> +struct Foo +{ + Foo() { } + ~Foo() { } +}; + +int main(int argc, char *argv[]) +{ + std::unique_ptr<Foo> p(new Foo); + return 0; +} + +" +OTB_CXX_HAS_UNIQUE_PTR ) + +unset(OTB_CXX_HAS_OVERRIDE_SPECIFIER CACHE) +CHECK_CXX_SOURCE_COMPILES(" +struct A +{ + A() { } + ~A() { } + virtual void foo( ) { } +}; + +struct B : A +{ + B() { } + ~B() { } + void foo( ) override { } +}; + +int main(int argc, char *argv[]) +{ + A* p = new B; + p->foo(); + return 0; +} + +" +OTB_CXX_HAS_OVERRIDE_SPECIFIER ) + +unset(OTB_CXX_HAS_NULLPTR CACHE) +CHECK_CXX_SOURCE_COMPILES(" +int main(int argc, char *argv[]) +{ + int *p = nullptr; + return 0; +} +" +OTB_CXX_HAS_NULLPTR ) + +# try_compile( +# OTB_HAS_CXX11 +# ${CMAKE_CURRENT_BINARY_DIR}/CMake +# ${CMAKE_SOURCE_DIR}/CMake/otbTestUniquePtr.cpp +# ) -try_compile(OTB_IS_UNIQUE_PTR_DEFINED ${CMAKE_CURRENT_BINARY_DIR}/CMake ${CMAKE_SOURCE_DIR}/CMake/otbTestUniquePtr.cpp) -try_compile(OTB_IS_OVERRIDE_DEFINED ${CMAKE_CURRENT_BINARY_DIR}/CMake ${CMAKE_SOURCE_DIR}/CMake/otbTestUniquePtr.cpp) -try_compile(OTB_IS_NULLPTR_DEFINED ${CMAKE_CURRENT_BINARY_DIR}/CMake ${CMAKE_SOURCE_DIR}/CMake/otbTestUniquePtr.cpp) -try_compile(OTB_HAS_CXX11 ${CMAKE_CURRENT_BINARY_DIR}/CMake ${CMAKE_SOURCE_DIR}/CMake/otbTestUniquePtr.cpp) diff --git a/CMake/otbCheckCXX11.cpp b/CMake/otbCheckCXX11.cpp deleted file mode 100644 index 17853f2a02..0000000000 --- a/CMake/otbCheckCXX11.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#if __cplusplus <= 199711L - #error Compiler is not C++11 compliant -#endif - -int main(int argc, char *argv[]) -{ - return 0; -} diff --git a/CMake/otbTestNullPtr.cpp b/CMake/otbTestNullPtr.cpp deleted file mode 100644 index 8abf4a6cae..0000000000 --- a/CMake/otbTestNullPtr.cpp +++ /dev/null @@ -1,6 +0,0 @@ - -int main(int argc, char *argv[]) -{ - int *p = ITK_NULLPTR; - return 0; -} diff --git a/CMake/otbTestOverride.cpp b/CMake/otbTestOverride.cpp deleted file mode 100644 index 54cf9a80f5..0000000000 --- a/CMake/otbTestOverride.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include <iostream> - -struct A -{ - A() {} - ~A() {} - virtual void foo() { std::cout << "A::foo()\n"; } -}; - -struct B : A -{ - B() {} - ~B() {} - void foo() override { std::cout << "B::foo()\n"; } -}; - -int main(int argc, char *argv[]) -{ - A* p = new B; - p->foo(); - return 0; -} diff --git a/CMake/otbTestUniquePtr.cpp b/CMake/otbTestUniquePtr.cpp deleted file mode 100644 index 292792edbf..0000000000 --- a/CMake/otbTestUniquePtr.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include <iostream> -#include <memory> - -struct Foo -{ - Foo() { std::cout << "Constructor\n"; } - ~Foo() { std::cout << "Destructor\n"; } -}; - -int main(int argc, char *argv[]) -{ - std::unique_ptr<Foo> p(new Foo); - return 0; -} diff --git a/Modules/Adapters/GdalAdapters/test/CMakeLists.txt b/Modules/Adapters/GdalAdapters/test/CMakeLists.txt index 978e59b27a..96b54047d9 100644 --- a/Modules/Adapters/GdalAdapters/test/CMakeLists.txt +++ b/Modules/Adapters/GdalAdapters/test/CMakeLists.txt @@ -2,7 +2,10 @@ otb_module_test() if (Boost_UNIT_TEST_FRAMEWORK_FOUND) add_executable(otbOGRTests otbOGRDataSourceWrapperNew.cxx) - target_link_libraries(otbOGRTests ${OTBGdalAdapters-Test_LIBRARIES}) + target_link_libraries( + otbOGRTests + ${OTBGdalAdapters-Test_LIBRARIES} + ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} ) add_test(NAME coTuOGRDataSourceWrapperNew COMMAND otbOGRTests coTuOGRDataSourceWrapperNew diff --git a/Modules/ThirdParty/Boost/CMakeLists.txt b/Modules/ThirdParty/Boost/CMakeLists.txt index be133cffe4..3bacc785ad 100644 --- a/Modules/ThirdParty/Boost/CMakeLists.txt +++ b/Modules/ThirdParty/Boost/CMakeLists.txt @@ -3,9 +3,14 @@ project(OTBBoost) set(OTBBoost_SYSTEM_INCLUDE_DIRS ${Boost_INCLUDE_DIRS}) set(OTBBoost_INCLUDE_DIRS ${OTBBoost_SOURCE_DIR}/src) -if(Boost_LIBRARIES) - set(OTBBoost_LIBRARIES "${Boost_LIBRARIES}") -endif() +# Do not include boost libraries into full list of OTB_LIBRARIES +# That will drag them in linking all otb modules and executables which is bad. +# OTB uses only header only libraries of boost. A non-header only library +# named 'unit_testing_framework' is used in two tests. +# why drag a semi-standard c++ library for use in two tests?. +# if(Boost_LIBRARIES) +# set(OTBBoost_LIBRARIES "${Boost_LIBRARIES}") +# endif() set(Boost_VERSION_STRING "${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}" CACHE INTERNAL "" FORCE) diff --git a/Modules/ThirdParty/MuParserX/CMakeLists.txt b/Modules/ThirdParty/MuParserX/CMakeLists.txt index 51526161df..e0eaf85daa 100644 --- a/Modules/ThirdParty/MuParserX/CMakeLists.txt +++ b/Modules/ThirdParty/MuParserX/CMakeLists.txt @@ -5,19 +5,19 @@ set(OTBMuParserX_LIBRARIES "${MUPARSERX_LIBRARIES}") set(OTBMuParserX_INCLUDE_DIRS ${OTBMuParserX_BINARY_DIR}/src) # as advised by Ingo Berg : avoid using those #define with MSVC -if(OTB_IS_UNIQUE_PTR_DEFINED OR MSVC) +if(OTB_CXX_HAS_UNIQUE_PTR OR MSVC) set(OTB_MUPARSERX_HIDE_UNIQUE_PTR 0) else() set(OTB_MUPARSERX_HIDE_UNIQUE_PTR 1) endif() -if(OTB_IS_OVERRIDE_DEFINED OR MSVC) +if(OTB_CXX_HAS_OVERRIDE_SPECIFIER OR MSVC) set(OTB_MUPARSERX_HIDE_OVERRIDE 0) else() set(OTB_MUPARSERX_HIDE_OVERRIDE 1) endif() -if(OTB_IS_NULLPTR_DEFINED OR MSVC) +if(OTB_CXX_HAS_NULLPTR OR MSVC) set(OTB_MUPARSERX_HIDE_NULLPTR 0) else() set(OTB_MUPARSERX_HIDE_NULLPTR 1) diff --git a/SuperBuild/CMake/External_boost.cmake b/SuperBuild/CMake/External_boost.cmake index f451b94ef1..b92f9ff010 100644 --- a/SuperBuild/CMake/External_boost.cmake +++ b/SuperBuild/CMake/External_boost.cmake @@ -2,30 +2,67 @@ INCLUDE_ONCE_MACRO(BOOST) SETUP_SUPERBUILD(BOOST) -#all we loose is one single test from not building boost unit-testing-framework. -#That is single test code. I don't see why we can't use something in-house -#change test code to not use boost unit-testing-framework and all is well. +set(_SB_Boost_INCLUDE_DIR ${SB_INSTALL_PREFIX}/include) +set(_SB_BOOST_LIBRARYDIR ${SB_INSTALL_PREFIX}/lib) + +set(BOOST_SB_CONFIG) + +if(OTB_COMPILER_ARCH_IS_X64) + set(BOOST_SB_CONFIG architecture=x86 address-model=64) +else() + set(BOOST_SB_CONFIG architecture=x86) +endif() + +set(BOOST_SB_CONFIG + ${BOOST_SB_CONFIG} + variant=release + link=shared + threading=multi + runtime-link=shared + --prefix=${SB_INSTALL_PREFIX} + --includedir=${_SB_Boost_INCLUDE_DIR} + --libdir=${_SB_Boost_LIBRARY_DIR} + --with-system + --with-serialization + --with-filesystem + --with-test + --with-date_time + --with-program_options + --with-thread + -d0 + ) -if(MSVC) - set(BOOST_URL "http://download.sourceforge.net/project/boost/boost/1.60.0/boost_1_60_0.tar.bz2") - set(BOOST_URL_MD5 "65a840e1a0b13a558ff19eeb2c4f0cbe") +if(UNIX) + set(BOOST_BOOTSTRAP_FILE "./bootstrap.sh") + set(BOOST_B2_EXE "./b2") else() - set(BOOST_URL "http://download.sourceforge.net/project/boost/boost/1.50.0/boost_1_50_0.tar.bz2") - set(BOOST_URL_MD5 "52dd00be775e689f55a987baebccc462") + set(BOOST_BOOTSTRAP_FILE "bootstrap.bat") + set(BOOST_B2_EXE "b2.exe") endif() +set(BOOST_CONFIGURE_COMMAND ${CMAKE_COMMAND} + -E chdir ${BOOST_SB_SRC} + ${BOOST_BOOTSTRAP_FILE} + --prefix=${SB_INSTALL_PREFIX} + ) + +set(BOOST_BUILD_COMMAND ${CMAKE_COMMAND} + -E chdir ${BOOST_SB_SRC} + ${BOOST_B2_EXE} + ${BOOST_SB_CONFIG} + install + ) + ExternalProject_Add(BOOST PREFIX BOOST - URL "${BOOST_URL}" - URL_MD5 ${BOOST_URL_MD5} + URL "http://download.sourceforge.net/project/boost/boost/1.60.0/boost_1_60_0.tar.bz2" + URL_MD5 65a840e1a0b13a558ff19eeb2c4f0cbe BINARY_DIR ${BOOST_SB_BUILD_DIR} INSTALL_DIR ${SB_INSTALL_PREFIX} DOWNLOAD_DIR ${DOWNLOAD_LOCATION} - CMAKE_CACHE_ARGS ${SB_CMAKE_CACHE_ARGS} - PATCH_COMMAND ${CMAKE_COMMAND} -E copy - ${CMAKE_SOURCE_DIR}/patches/BOOST/CMakeLists.txt - ${BOOST_SB_SRC} + CONFIGURE_COMMAND ${BOOST_CONFIGURE_COMMAND} + BUILD_COMMAND ${BOOST_BUILD_COMMAND} + INSTALL_COMMAND "" ) -set(_SB_Boost_INCLUDE_DIR ${SB_INSTALL_PREFIX}/include) -set(_SB_Boost_LIBRARY_DIR ${SB_INSTALL_PREFIX}/lib) +SUPERBUILD_PATCH_SOURCE(BOOST) \ No newline at end of file diff --git a/SuperBuild/CMake/External_curl.cmake b/SuperBuild/CMake/External_curl.cmake index c3604d246d..977fe5632f 100644 --- a/SuperBuild/CMake/External_curl.cmake +++ b/SuperBuild/CMake/External_curl.cmake @@ -15,11 +15,11 @@ if(MSVC) return() endif() -if(OTB_MSVC_COMPILER_ARCH_IS_X64) - set(CURL_INSTALL_DIR_PREFIX "libcurl-vc-x64") -else() - set(CURL_INSTALL_DIR_PREFIX "libcurl-vc-x86") -endif() + if(OTB_COMPILER_ARCH_IS_X64) + set(CURL_INSTALL_DIR_PREFIX "libcurl-vc-x64") + else() + set(CURL_INSTALL_DIR_PREFIX "libcurl-vc-x86") + endif() set(CURL_INSTALL_DIR_PREFIX "${CURL_INSTALL_DIR_PREFIX}-release-dll-zlib-dll-ipv6-sspi-winssl") @@ -39,6 +39,7 @@ endif() ) else(UNIX) + ExternalProject_Add(CURL PREFIX CURL URL "http://curl.haxx.se/download/curl-7.40.0.tar.gz" diff --git a/SuperBuild/CMake/External_gdal.cmake b/SuperBuild/CMake/External_gdal.cmake index fc1eaed82c..20c6909385 100644 --- a/SuperBuild/CMake/External_gdal.cmake +++ b/SuperBuild/CMake/External_gdal.cmake @@ -92,10 +92,10 @@ else(MSVC) STRING(REGEX REPLACE "/$" "" CMAKE_WIN_INSTALL_PREFIX ${SB_INSTALL_PREFIX}) STRING(REGEX REPLACE "/" "\\\\" CMAKE_WIN_INSTALL_PREFIX ${CMAKE_WIN_INSTALL_PREFIX}) configure_file( - ${CMAKE_SOURCE_DIR}/patches/GDAL/nmake_gdal_extra.opt.in - ${CMAKE_BINARY_DIR}/nmake_gdal_extra.opt) + ${CMAKE_SOURCE_DIR}/patches/GDAL/nmake_gdal_extra.opt.in + ${CMAKE_BINARY_DIR}/nmake_gdal_extra.opt) - if(OTB_MSVC_COMPILER_ARCH_IS_X64) + if(OTB_COMPILER_ARCH_IS_X64) file(APPEND "${CMAKE_BINARY_DIR}/nmake_gdal_extra.opt" "WIN64=YES") endif() diff --git a/SuperBuild/CMake/External_otb.cmake b/SuperBuild/CMake/External_otb.cmake index b460bac4ac..ef6385174f 100644 --- a/SuperBuild/CMake/External_otb.cmake +++ b/SuperBuild/CMake/External_otb.cmake @@ -44,6 +44,7 @@ endif() if(OTB_USE_SHARK) ADDTO_DEPENDENCIES_IF_NOT_SYSTEM(OTB SHARK) + ADD_SUPERBUILD_CMAKE_VAR(OTB Shark_DIR) endif() if(OTB_USE_LIBSVM) diff --git a/SuperBuild/CMake/External_shark.cmake b/SuperBuild/CMake/External_shark.cmake index 6d4be53e70..ccd87888a5 100644 --- a/SuperBuild/CMake/External_shark.cmake +++ b/SuperBuild/CMake/External_shark.cmake @@ -5,8 +5,10 @@ SETUP_SUPERBUILD(SHARK) # declare dependencies ADDTO_DEPENDENCIES_IF_NOT_SYSTEM(SHARK BOOST) +package_require_cxx11(SHARK) + ADD_SUPERBUILD_CMAKE_VAR(SHARK Boost_INCLUDE_DIR) -ADD_SUPERBUILD_CMAKE_VAR(SHARK Boost_LIBRARY_DIR) +ADD_SUPERBUILD_CMAKE_VAR(SHARK BOOST_LIBRARYDIR) ExternalProject_Add(SHARK PREFIX SHARK @@ -23,7 +25,8 @@ ExternalProject_Add(SHARK -DBUILD_EXAMPLES:BOOL=OFF -DBUILD_TESTING:BOOL=OFF -DENABLE_HDF5:BOOL=OFF + -DENABLE_CBLAS:BOOL=OFF CMAKE_COMMAND ${SB_CMAKE_COMMAND} ) -set(_SB_SHARK_DIR ${SB_INSTALL_PREFIX}/share/Shark) +set(_SB_Shark_DIR ${SB_INSTALL_PREFIX}/lib/cmake/Shark) diff --git a/SuperBuild/CMake/SuperBuild_Macro.cmake b/SuperBuild/CMake/SuperBuild_Macro.cmake index 533968ef01..616d0dd203 100644 --- a/SuperBuild/CMake/SuperBuild_Macro.cmake +++ b/SuperBuild/CMake/SuperBuild_Macro.cmake @@ -174,3 +174,10 @@ macro(SUPERBUILD_UPDATE_CMAKE_VARIABLES PROJECT with_prefix) set(_SB_${PROJECT}_LIBRARY ${SB_INSTALL_PREFIX}/lib/${lib_file}) endmacro() + +macro(package_require_cxx11 project) + if(NOT OTB_HAS_CXX11) + message(FATAL_ERROR "${project} requires C++11 support. consider adding --std=c++11 to your cxx compiler flags or disable ${project} ") + endif() +endmacro() + diff --git a/SuperBuild/CMakeLists.txt b/SuperBuild/CMakeLists.txt index 2e109d4d60..b31ec28aeb 100644 --- a/SuperBuild/CMakeLists.txt +++ b/SuperBuild/CMakeLists.txt @@ -7,10 +7,13 @@ project(OTB-SuperBuild) set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/CMake ${CMAKE_SOURCE_DIR}/../CMake - ${CMAKE_MODULE_PATH}) + ${CMAKE_MODULE_PATH} + ) include(ExternalProject) +include(OTBCheckCpp11Keywords) + option(BUILD_SHARED_LIBS "Build OTB with shared libraries." ON) set(OTB_ADDITIONAL_CACHE "" CACHE STRING "Additional cmake option for OTB -DVAR:TYPE=VALUE ...") @@ -22,19 +25,38 @@ if(APPLE) set(CMAKE_MACOSX_RPATH TRUE) endif() +set(OTB_COMPILER_ARCH_IS_X64 TRUE) + if(MSVC) execute_process( - COMMAND ${CMAKE_C_COMPILER} - ERROR_VARIABLE ev - OUTPUT_VARIABLE ov - OUTPUT_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) + COMMAND ${CMAKE_C_COMPILER} + ERROR_VARIABLE ev + OUTPUT_VARIABLE ov + OUTPUT_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE + ) - set(OTB_MSVC_COMPILER_ARCH_IS_X64 TRUE) + set(OTB_COMPILER_ARCH_IS_X64 TRUE) + set(OTB_COMPILER_ARCH x64) if("${ev}" MATCHES "x86") - set(OTB_MSVC_COMPILER_ARCH_IS_X64 FALSE) + set(OTB_COMPILER_ARCH x86) + set(OTB_COMPILER_ARCH_IS_X64 FALSE) + endif() + +endif() #MSVC + +if(UNIX) + execute_process( + COMMAND uname -m + ERROR_VARIABLE ev + OUTPUT_VARIABLE ov + OUTPUT_STRIP_TRAILING_WHITESPACE) + + set(OTB_COMPILER_ARCH ${ov}) + set(OTB_COMPILER_ARCH_IS_X64 FALSE) + if("${ov}" STREQUAL "x86_64") + set(OTB_COMPILER_ARCH_IS_X64 TRUE) endif() - endif() # use, i.e. don't skip the full RPATH for the build tree diff --git a/SuperBuild/patches/BOOST/CMakeLists.txt b/SuperBuild/patches/BOOST/CMakeLists.txt deleted file mode 100644 index d5f069dadc..0000000000 --- a/SuperBuild/patches/BOOST/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -cmake_minimum_required(VERSION 2.8.3) - -project(OTB-SuperBuildBoost) - -install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/boost - DESTINATION ${CMAKE_INSTALL_PREFIX}/include - FILES_MATCHING PATTERN "*.hpp" PATTERN "*.ipp" PATTERN "*.h") diff --git a/SuperBuild/patches/BOOST/boost-1-fix-macx.diff b/SuperBuild/patches/BOOST/boost-1-fix-macx.diff new file mode 100644 index 0000000000..45cc21a82b --- /dev/null +++ b/SuperBuild/patches/BOOST/boost-1-fix-macx.diff @@ -0,0 +1,12 @@ +diff -burN boost_1_60_0.orig/tools/build/src/tools/darwin.jam boost_1_60_0/tools/build/src/tools/darwin.jam +--- boost_1_60_0.orig/tools/build/src/tools/darwin.jam 2016-10-11 14:27:28.000000000 +0200 ++++ boost_1_60_0/tools/build/src/tools/darwin.jam 2016-10-11 14:27:40.000000000 +0200 +@@ -579,7 +579,7 @@ + + actions link.dll bind LIBRARIES + { +- "$(CONFIG_COMMAND)" -dynamiclib -Wl,-single_module -install_name "$(<:B)$(<:S)" -L"$(LINKPATH)" -o "$(<)" "$(>)" "$(LIBRARIES)" -l$(FINDLIBS-SA) -l$(FINDLIBS-ST) $(FRAMEWORK_PATH) -framework$(_)$(FRAMEWORK:D=:S=) $(OPTIONS) $(USER_OPTIONS) ++ "$(CONFIG_COMMAND)" -dynamiclib -Wl,-single_module -install_name "@rpath/$(<:B)$(<:S)" -L"$(LINKPATH)" -o "$(<)" "$(>)" "$(LIBRARIES)" -l$(FINDLIBS-SA) -l$(FINDLIBS-ST) $(FRAMEWORK_PATH) -framework$(_)$(FRAMEWORK:D=:S=) $(OPTIONS) $(USER_OPTIONS) + } + + # We use libtool instead of ar to support universal binary linking -- GitLab