From d591d86f9c9b3114608b0c6478170ded7b784bf8 Mon Sep 17 00:00:00 2001 From: Daniel Agar Date: Mon, 15 Oct 2018 09:15:54 -0400 Subject: [PATCH] initial optional cmake support (#6862) --- .gitignore | 3 +- CMakeLists.txt | 890 +++++++++ Jenkinsfile | 115 ++ Makefile | 135 ++ QGCCommon.pri | 1 - android/AndroidManifest.xml.in | 33 + cmake/AddQtAndroidApk.cmake | 178 ++ cmake/MacOSXBundleInfo.plist.in | 38 + cmake/Macdeployqt.cmake | 42 + cmake/Windeployqt.cmake | 102 + cmake/android.toolchain.cmake | 1688 +++++++++++++++++ cmake/qtdeploy.json.in | 17 + cmake/windows_metafile.rc.in | 29 + deploy/create_linux_appimage.sh | 12 +- localization/qgc.ts | 13 - qgroundcontrol.pro | 2 +- .../APM/APMPowerComponentController.cc | 161 -- .../APM/APMPowerComponentController.h | 57 - src/Camera/QGCCameraControl.cc | 2 +- src/KMLFileHelper.cc | 1 + src/QGCMessageBox.h | 2 +- src/QGCQuickWidget.cc | 2 +- src/QmlControls/ScreenToolsController.h | 6 +- src/VideoStreaming/VideoStreaming.cc | 6 +- .../gstqtvideosink/utils/glutils.h | 2 +- src/comm/QGCFlightGearLink.cc | 2 +- src/input/Mouse6dofInput.cpp | 320 ---- src/input/Mouse6dofInput.h | 96 - src/main.cc | 3 + src/ui/InputConfiguration.cc | 33 - src/ui/MainWindow.cc | 21 - src/ui/MainWindow.h | 15 - src/ui/QGCWebView.cc | 28 - src/ui/QGCWebView.h | 26 - src/ui/QGCWebView.ui | 37 - src/ui/{ => linechart}/Linechart.ui | 0 36 files changed, 3291 insertions(+), 827 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 Makefile create mode 100644 android/AndroidManifest.xml.in create mode 100644 cmake/AddQtAndroidApk.cmake create mode 100644 cmake/MacOSXBundleInfo.plist.in create mode 100644 cmake/Macdeployqt.cmake create mode 100644 cmake/Windeployqt.cmake create mode 100644 cmake/android.toolchain.cmake create mode 100644 cmake/qtdeploy.json.in create mode 100644 cmake/windows_metafile.rc.in delete mode 100644 src/AutoPilotPlugins/APM/APMPowerComponentController.cc delete mode 100644 src/AutoPilotPlugins/APM/APMPowerComponentController.h delete mode 100644 src/input/Mouse6dofInput.cpp delete mode 100644 src/input/Mouse6dofInput.h delete mode 100644 src/ui/InputConfiguration.cc delete mode 100644 src/ui/QGCWebView.cc delete mode 100644 src/ui/QGCWebView.h delete mode 100644 src/ui/QGCWebView.ui rename src/ui/{ => linechart}/Linechart.ui (100%) diff --git a/.gitignore b/.gitignore index 7b39ff4dd..04fa3cab7 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,6 @@ libs/lib/Frameworks/GStreamer.framework *.swp *.nfs CMakeFiles -*Makefile* tags build*/ Info.plist @@ -86,4 +85,6 @@ src/latex/ .vagrant/ Qt*-linux*.tar.* +.vs/ + libs/airmapd/include/boost diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 000000000..e3ff71765 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,890 @@ +cmake_minimum_required(VERSION 3.2) + +project(QGroundControl LANGUAGES CXX) + +set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug;Release;RelWithDebInfo;MinSizeRel;Coverage") + +# CMake build type +# Debug Release RelWithDebInfo MinSizeRel Coverage +if (NOT CMAKE_BUILD_TYPE) + # default to release with debug symbols + set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Build type" FORCE) +endif() + +if(DEFINED ENV{QT_VERSION}) + set(QT_VERSION $ENV{QT_VERSION}) +endif() + +if(NOT QT_VERSION) + # try Qt 5.11.0 if none specified + set(QT_VERSION "5.11.1") +endif() + +if(DEFINED ENV{QT_MKSPEC}) + set(QT_MKSPEC $ENV{QT_MKSPEC}) +endif() + +if(UNIX AND NOT APPLE) + set(LINUX TRUE) +endif() + +if(NOT QT_MKSPEC) + if(APPLE) + set(QT_MKSPEC clang_64) + elseif(LINUX) + set(QT_MKSPEC gcc_64) + elseif(WIN32) + set(QT_MKSPEC msvc2017_64) + #set(QT_MKSPEC winrt_x64_msvc2017) + endif() +endif() + +# Add folder where are supportive functions +list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) + +message(STATUS "Build Type: ${CMAKE_BUILD_TYPE}") +message(STATUS "Qt version: ${QT_VERSION}") +message(STATUS "Qt spec: ${QT_MKSPEC}") + +set(COMPANY "Mavlink") +set(COPYRIGHT "Copyright (c) 2018 QGroundControl. All rights reserved.") +set(IDENTIFIER "io.mavlink.qgroundcontrol") + +execute_process( + COMMAND git submodule update --init + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + ) + +execute_process( + COMMAND git describe --always --tags + OUTPUT_VARIABLE git_tag + OUTPUT_STRIP_TRAILING_WHITESPACE + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + ) + +add_definitions( + -DQGC_APPLICATION_NAME="QGroundControl" + -DQGC_ORG_NAME="QGroundControl.org" + -DQGC_ORG_DOMAIN="org.qgroundcontrol" + ) + +message(STATUS "QGroundControl version: ${git_tag}") + +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTOUIC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +#============================================================================= +# ccache +# +option(CCACHE "Use ccache if available" ON) +find_program(CCACHE_PROGRAM ccache) +if (CCACHE AND CCACHE_PROGRAM AND NOT DEFINED ENV{CCACHE_DISABLE}) + set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}") +endif() + +#============================================================================= +# Qt5 +# +find_package(Qt5 ${QT_VERSION} + COMPONENTS + Bluetooth + Concurrent + Core + Location + Multimedia + Network + Positioning + Quick + QuickWidgets + Sql + Svg + Test + TextToSpeech + Widgets + Xml + REQUIRED + HINTS + $ENV{HOME}/Qt/${QT_VERSION}/${QT_MKSPEC} + $ENV{QT_PATH}/${QT_VERSION}/${QT_MKSPEC} + C:/Qt +) + +if(NOT QT_MKSPEC MATCHES "winrt") + find_package(Qt5 ${QT_VERSION} + COMPONENTS + SerialPort + REQUIRED + HINTS + $ENV{HOME}/Qt/${QT_VERSION}/${QT_MKSPEC} + $ENV{QT_PATH}/${QT_VERSION}/${QT_MKSPEC} + C:/Qt + ) +endif() + +if(${CMAKE_BUILD_TYPE} MATCHES "Debug") + include(CTest) + enable_testing() + add_definitions(-DUNITTEST_BUILD) +endif() + +if(LINUX) + find_package(SDL2 REQUIRED) + include_directories(${SDL2_INCLUDE_DIRS}) + string(STRIP ${SDL2_LIBRARIES} SDL2_LIBRARIES) # work around for cmake warning +elseif(APPLE) + include_directories(libs/lib/Frameworks/SDL2.framework/Headers) +elseif(WIN32) + include_directories(libs/lib/sdl2/msvc/include) +endif() + +if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + # clang and AppleClang + add_compile_options( + -Wall + -Wextra + -Werror + + -frtti + + -Wno-address-of-packed-member # ignore for mavlink + ) + +elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + # GCC + if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.9) + add_compile_options(-fdiagnostics-color=always) + endif() + + add_compile_options( + -Wall + -Wextra + -Werror + + -frtti + ) + +elseif (WIN32) + + add_definitions(-D_USE_MATH_DEFINES) + add_compile_options( + /wd4244 # warning C4244: '=': conversion from 'double' to 'float', possible loss of data + ) + +endif() + + +set(QGC_SRC) +list(APPEND QGC_SRC + + libs/qwt/qwt_abstract_legend.cpp + libs/qwt/qwt_abstract_scale.cpp + libs/qwt/qwt_abstract_scale_draw.cpp + libs/qwt/qwt_abstract_slider.cpp + libs/qwt/qwt_analog_clock.cpp + libs/qwt/qwt_arrow_button.cpp + libs/qwt/qwt_clipper.cpp + libs/qwt/qwt_color_map.cpp + libs/qwt/qwt_compass.cpp + libs/qwt/qwt_compass_rose.cpp + libs/qwt/qwt_counter.cpp + libs/qwt/qwt_curve_fitter.cpp + libs/qwt/qwt_dial.cpp + libs/qwt/qwt_dial_needle.cpp + libs/qwt/qwt_dyngrid_layout.cpp + libs/qwt/qwt_event_pattern.cpp + libs/qwt/qwt_graphic.cpp + libs/qwt/qwt_interval.cpp + libs/qwt/qwt_knob.cpp + libs/qwt/qwt_legend.cpp + libs/qwt/qwt_legend_data.cpp + libs/qwt/qwt_legend_label.cpp + libs/qwt/qwt_magnifier.cpp + libs/qwt/qwt_math.cpp + libs/qwt/qwt_null_paintdevice.cpp + libs/qwt/qwt_painter.cpp + libs/qwt/qwt_painter_command.cpp + libs/qwt/qwt_panner.cpp + libs/qwt/qwt_picker.cpp + libs/qwt/qwt_picker_machine.cpp + libs/qwt/qwt_pixel_matrix.cpp + libs/qwt/qwt_plot.cpp + libs/qwt/qwt_plot_axis.cpp + libs/qwt/qwt_plot_canvas.cpp + libs/qwt/qwt_plot_curve.cpp + libs/qwt/qwt_plot_dict.cpp + libs/qwt/qwt_plot_grid.cpp + libs/qwt/qwt_plot_item.cpp + libs/qwt/qwt_plot_layout.cpp + libs/qwt/qwt_plot_magnifier.cpp + libs/qwt/qwt_plot_marker.cpp + libs/qwt/qwt_plot_panner.cpp + libs/qwt/qwt_plot_picker.cpp + libs/qwt/qwt_plot_rasteritem.cpp + libs/qwt/qwt_plot_scaleitem.cpp + libs/qwt/qwt_plot_seriesitem.cpp + libs/qwt/qwt_plot_spectrogram.cpp + libs/qwt/qwt_plot_svgitem.cpp + libs/qwt/qwt_plot_xml.cpp + libs/qwt/qwt_plot_zoomer.cpp + libs/qwt/qwt_point_data.cpp + libs/qwt/qwt_point_mapper.cpp + libs/qwt/qwt_raster_data.cpp + libs/qwt/qwt_round_scale_draw.cpp + libs/qwt/qwt_scale_div.cpp + libs/qwt/qwt_scale_draw.cpp + libs/qwt/qwt_scale_engine.cpp + libs/qwt/qwt_scale_map.cpp + libs/qwt/qwt_scale_widget.cpp + libs/qwt/qwt_series_data.cpp + libs/qwt/qwt_slider.cpp + libs/qwt/qwt_spline.cpp + libs/qwt/qwt_symbol.cpp + libs/qwt/qwt_text.cpp + libs/qwt/qwt_text_engine.cpp + libs/qwt/qwt_text_label.cpp + libs/qwt/qwt_thermo.cpp + libs/qwt/qwt_transform.cpp + libs/qwt/qwt_wheel.cpp + libs/qwt/qwt_widget_overlay.cpp + + src/AnalyzeView/ExifParser.cc + src/AnalyzeView/GeoTagController.cc + src/AnalyzeView/LogDownloadController.cc + src/AnalyzeView/MavlinkConsoleController.cc + src/AnalyzeView/PX4LogParser.cc + src/AnalyzeView/ULogParser.cc + + src/api/QGCCorePlugin.cc + src/api/QGCOptions.cc + src/api/QGCSettings.cc + src/api/QmlComponentInfo.cc + + src/Audio/AudioOutput.cc + + src/AutoPilotPlugins/APM/APMAirframeComponent.cc + src/AutoPilotPlugins/APM/APMAirframeComponentAirframes.cc + src/AutoPilotPlugins/APM/APMAirframeComponentController.cc + src/AutoPilotPlugins/APM/APMAirframeLoader.cc + src/AutoPilotPlugins/APM/APMAutoPilotPlugin.cc + src/AutoPilotPlugins/APM/APMCameraComponent.cc + src/AutoPilotPlugins/APM/APMCompassCal.cc + src/AutoPilotPlugins/APM/APMFlightModesComponent.cc + src/AutoPilotPlugins/APM/APMFlightModesComponentController.cc + src/AutoPilotPlugins/APM/APMLightsComponent.cc + src/AutoPilotPlugins/APM/APMPowerComponent.cc + src/AutoPilotPlugins/APM/APMRadioComponent.cc + src/AutoPilotPlugins/APM/APMSafetyComponent.cc + src/AutoPilotPlugins/APM/APMSensorsComponent.cc + src/AutoPilotPlugins/APM/APMSensorsComponentController.cc + src/AutoPilotPlugins/APM/APMSubFrameComponent.cc + src/AutoPilotPlugins/APM/APMTuningComponent.cc + src/AutoPilotPlugins/APM/APMHeliComponent.cc + + src/AutoPilotPlugins/Common/ESP8266Component.cc + src/AutoPilotPlugins/Common/ESP8266ComponentController.cc + src/AutoPilotPlugins/Common/MotorComponent.cc + src/AutoPilotPlugins/Common/RadioComponentController.cc + src/AutoPilotPlugins/Common/SyslinkComponent.cc + src/AutoPilotPlugins/Common/SyslinkComponentController.cc + + src/AutoPilotPlugins/PX4/AirframeComponent.cc + src/AutoPilotPlugins/PX4/AirframeComponentAirframes.cc + src/AutoPilotPlugins/PX4/AirframeComponentController.cc + src/AutoPilotPlugins/PX4/CameraComponent.cc + src/AutoPilotPlugins/PX4/FlightModesComponent.cc + src/AutoPilotPlugins/PX4/PowerComponent.cc + src/AutoPilotPlugins/PX4/PowerComponentController.cc + src/AutoPilotPlugins/PX4/PX4AdvancedFlightModesController.cc + src/AutoPilotPlugins/PX4/PX4AirframeLoader.cc + src/AutoPilotPlugins/PX4/PX4AutoPilotPlugin.cc + src/AutoPilotPlugins/PX4/PX4RadioComponent.cc + src/AutoPilotPlugins/PX4/PX4SimpleFlightModesController.cc + src/AutoPilotPlugins/PX4/PX4TuningComponent.cc + src/AutoPilotPlugins/PX4/SafetyComponent.cc + src/AutoPilotPlugins/PX4/SensorsComponent.cc + src/AutoPilotPlugins/PX4/SensorsComponentController.cc + + src/AutoPilotPlugins/AutoPilotPlugin.cc + src/AutoPilotPlugins/Generic/GenericAutoPilotPlugin.cc + + src/Camera/QGCCameraControl.cc + src/Camera/QGCCameraIO.cc + src/Camera/QGCCameraManager.cc + + #src/comm/BluetoothLink.cc + src/comm/LinkConfiguration.cc + src/comm/LinkInterface.cc + src/comm/LinkManager.cc + src/comm/LogReplayLink.cc + src/comm/MavlinkMessagesTimer.cc + src/comm/MAVLinkProtocol.cc + src/comm/QGCFlightGearLink.cc + src/comm/QGCJSBSimLink.cc + src/comm/QGCMAVLink.cc + src/comm/QGCSerialPortInfo.cc + src/comm/QGCXPlaneLink.cc + src/comm/SerialLink.cc + src/comm/TCPLink.cc + src/comm/UDPLink.cc + + src/FactSystem/Fact.cc + src/FactSystem/FactControls/FactPanelController.cc + src/FactSystem/FactGroup.cc + src/FactSystem/FactMetaData.cc + src/FactSystem/FactSystem.cc + src/FactSystem/FactValueSliderListModel.cc + src/FactSystem/ParameterManager.cc + src/FactSystem/SettingsFact.cc + + src/FirmwarePlugin/APM/APMFirmwarePlugin.cc + src/FirmwarePlugin/APM/APMFirmwarePluginFactory.cc + src/FirmwarePlugin/APM/APMParameterMetaData.cc + src/FirmwarePlugin/APM/ArduCopterFirmwarePlugin.cc + src/FirmwarePlugin/APM/ArduPlaneFirmwarePlugin.cc + src/FirmwarePlugin/APM/ArduRoverFirmwarePlugin.cc + src/FirmwarePlugin/APM/ArduSubFirmwarePlugin.cc + + src/FirmwarePlugin/CameraMetaData.cc + src/FirmwarePlugin/FirmwarePlugin.cc + src/FirmwarePlugin/FirmwarePluginManager.cc + + src/FirmwarePlugin/PX4/PX4FirmwarePlugin.cc + src/FirmwarePlugin/PX4/PX4FirmwarePluginFactory.cc + src/FirmwarePlugin/PX4/PX4ParameterMetaData.cc + + src/FlightDisplay/VideoManager.cc + + src/FlightMap/Widgets/ValuesWidgetController.cc + + src/FollowMe/FollowMe.cc + + src/GPS/Drivers/src/ashtech.cpp + src/GPS/Drivers/src/gps_helper.cpp + src/GPS/Drivers/src/mtk.cpp + src/GPS/Drivers/src/rtcm.cpp + src/GPS/Drivers/src/ubx.cpp + src/GPS/GPSManager.cc + src/GPS/GPSProvider.cc + src/GPS/RTCM/RTCMMavlink.cc + + src/Joystick/Joystick.cc + src/Joystick/JoystickManager.cc + src/Joystick/JoystickSDL.cc + + src/MissionManager/CameraCalc.cc + src/MissionManager/CameraSection.cc + src/MissionManager/CameraSpec.cc + src/MissionManager/ComplexMissionItem.cc + src/MissionManager/CorridorScanComplexItem.cc + src/MissionManager/FixedWingLandingComplexItem.cc + src/MissionManager/GeoFenceController.cc + src/MissionManager/GeoFenceManager.cc + src/MissionManager/KML.cc + src/MissionManager/MissionCommandList.cc + src/MissionManager/MissionCommandTree.cc + src/MissionManager/MissionCommandUIInfo.cc + src/MissionManager/MissionController.cc + src/MissionManager/MissionItem.cc + src/MissionManager/MissionManager.cc + src/MissionManager/MissionSettingsItem.cc + src/MissionManager/PlanElementController.cc + src/MissionManager/PlanManager.cc + src/MissionManager/PlanMasterController.cc + src/MissionManager/QGCFenceCircle.cc + src/MissionManager/QGCFencePolygon.cc + src/MissionManager/QGCMapCircle.cc + src/MissionManager/QGCMapPolygon.cc + src/MissionManager/QGCMapPolyline.cc + src/MissionManager/RallyPoint.cc + src/MissionManager/RallyPointController.cc + src/MissionManager/RallyPointManager.cc + src/MissionManager/SimpleMissionItem.cc + src/MissionManager/SpeedSection.cc + src/MissionManager/StructureScanComplexItem.cc + src/MissionManager/SurveyComplexItem.cc + src/MissionManager/TransectStyleComplexItem.cc + src/MissionManager/VisualMissionItem.cc + + src/PositionManager/PositionManager.cpp + src/PositionManager/SimulatedPosition.cc + + src/QmlControls/AppMessages.cc + src/QmlControls/CoordinateVector.cc + src/QmlControls/EditPositionDialogController.cc + src/QmlControls/ParameterEditorController.cc + src/QmlControls/QGCFileDialogController.cc + src/QmlControls/QGCGeoBoundingCube.cc + src/QmlControls/QGCImageProvider.cc + src/QmlControls/QGroundControlQmlGlobal.cc + src/QmlControls/QmlObjectListModel.cc + src/QmlControls/QmlTestWidget.cc + src/QmlControls/RCChannelMonitorController.cc + src/QmlControls/ScreenToolsController.cc + + src/QtLocationPlugin/QGCMapEngine.cpp + src/QtLocationPlugin/QGCMapTileSet.cpp + src/QtLocationPlugin/QGCMapUrlEngine.cpp + src/QtLocationPlugin/QGCTileCacheWorker.cpp + src/QtLocationPlugin/QGeoCodeReplyQGC.cpp + src/QtLocationPlugin/QGeoCodingManagerEngineQGC.cpp + src/QtLocationPlugin/QGeoMapReplyQGC.cpp + src/QtLocationPlugin/QGeoServiceProviderPluginQGC.cpp + src/QtLocationPlugin/QGeoTiledMappingManagerEngineQGC.cpp + src/QtLocationPlugin/QGeoTileFetcherQGC.cpp + src/QtLocationPlugin/QMLControl/QGCMapEngineManager.cc + + src/Settings/AppSettings.cc + src/Settings/AutoConnectSettings.cc + src/Settings/BrandImageSettings.cc + src/Settings/FlightMapSettings.cc + src/Settings/GuidedSettings.cc + src/Settings/RTKSettings.cc + src/Settings/SettingsGroup.cc + src/Settings/SettingsManager.cc + src/Settings/UnitsSettings.cc + src/Settings/VideoSettings.cc + + src/Terrain/TerrainQuery.cc + + src/uas/FileManager.cc + src/uas/UAS.cc + src/uas/UASMessageHandler.cc + + src/ui/HILDockWidget.cc + src/ui/linechart/ChartPlot.cc + src/ui/linechart/IncrementalPlot.cc + src/ui/linechart/LinechartPlot.cc + src/ui/linechart/Linecharts.cc + src/ui/linechart/LinechartWidget.cc + src/ui/linechart/Scrollbar.cc + src/ui/linechart/ScrollZoomer.cc + src/ui/MainWindow.cc + src/ui/MAVLinkDecoder.cc + src/ui/MultiVehicleDockWidget.cc + src/ui/QGCHilConfiguration.cc + src/ui/QGCHilFlightGearConfiguration.cc + src/ui/QGCHilJSBSimConfiguration.cc + src/ui/QGCHilXPlaneConfiguration.cc + src/ui/QGCMapRCToParamDialog.cpp + src/ui/QGCMAVLinkInspector.cc + src/ui/QGCMAVLinkLogPlayer.cc + src/ui/QGCPluginHost.cc + src/ui/QGCUASFileView.cc + src/ui/QGCUASFileViewMulti.cc + src/ui/uas/QGCUnconnectedInfoWidget.cc + + src/Vehicle/ADSBVehicle.cc + src/Vehicle/GPSRTKFactGroup.cc + src/Vehicle/MAVLinkLogManager.cc + src/Vehicle/MultiVehicleManager.cc + src/Vehicle/Vehicle.cc + + src/VehicleSetup/Bootloader.cc + src/VehicleSetup/FirmwareImage.cc + src/VehicleSetup/FirmwareUpgradeController.cc + src/VehicleSetup/JoystickConfigController.cc + src/VehicleSetup/PX4FirmwareUpgradeThread.cc + src/VehicleSetup/VehicleComponent.cc + + src/VideoStreaming/VideoItem.cc + src/VideoStreaming/VideoReceiver.cc + src/VideoStreaming/VideoStreaming.cc + src/VideoStreaming/VideoSurface.cc + + src/ViewWidgets/CustomCommandWidget.cc + src/ViewWidgets/CustomCommandWidgetController.cc + src/ViewWidgets/ViewWidgetController.cc + + src/CmdLineOptParser.cc + src/JsonHelper.cc + src/KMLFileHelper.cc + src/LogCompressor.cc + src/main.cc + src/QGC.cc + src/QGCApplication.cc + src/QGCComboBox.cc + src/QGCDockWidget.cc + src/QGCFileDownload.cc + src/QGCGeo.cc + src/QGCLoggingCategory.cc + src/QGCMapPalette.cc + src/QGCPalette.cc + src/QGCQFileDialog.cc + src/QGCQGeoCoordinate.cc + src/QGCQmlWidgetHolder.cpp + src/QGCQuickWidget.cc + src/QGCTemporaryFile.cc + src/QGCToolbox.cc + src/RunGuard.cc + src/TerrainTile.cc + src/UTM.cpp + + # HEADERS + # shouldn't be listed here, but aren't named properly for AUTOMOC + src/comm/QGCFlightGearLink.h + src/comm/QGCHilLink.h + src/comm/QGCJSBSimLink.h + src/MissionManager/Section.h + src/QtLocationPlugin/QGCMapEngineData.h + src/uas/UAS.h + src/uas/UASInterface.h + src/ui/QGCHilFlightGearConfiguration.h + src/ui/QGCHilJSBSimConfiguration.h +) + +if(QGC_AIRMAP) + + list(APPEND QGC_SRC + src/Airmap/AirMapAdvisoryManager.cc + src/Airmap/AirMapFlightManager.cc + src/Airmap/AirMapFlightPlanManager.cc + src/Airmap/AirMapManager.cc + src/Airmap/AirMapRestrictionManager.cc + src/Airmap/AirMapRulesetsManager.cc + src/Airmap/AirMapSettings.cc + src/Airmap/AirMapSharedState.cc + src/Airmap/AirMapTelemetry.cc + src/Airmap/AirMapTrafficMonitor.cc + src/Airmap/AirMapVehicleManager.cc + src/Airmap/AirMapWeatherInfoManager.cc + + src/AirspaceManagement/AirspaceAdvisoryProvider.cc + src/AirspaceManagement/AirspaceFlightPlanProvider.cc + src/AirspaceManagement/AirspaceManager.cc + src/AirspaceManagement/AirspaceRestriction.cc + src/AirspaceManagement/AirspaceRestrictionProvider.cc + src/AirspaceManagement/AirspaceRulesetsProvider.cc + src/AirspaceManagement/AirspaceVehicleManager.cc + src/AirspaceManagement/AirspaceWeatherInfoProvider.cc + ) +else() + list(APPEND QGC_SRC + src/Airmap/dummy/AirspaceManager.cc + ) + include_directories(src/Airmap/dummy) +endif() + +set_source_files_properties(${CMAKE_SOURCE_DIR}/src/QGCApplication.cc PROPERTIES COMPILE_DEFINITIONS GIT_VERSION="${git_tag}") + +if(MOBILE) + list(APPEND QGC_SRC + src/MobileScreenMgr.cc + ) + + if (ANDROID) + list(APPEND QGC_SRC + libs/qtandroidserialport/src/qserialport.cpp + libs/qtandroidserialport/src/qserialport_android.cpp + libs/qtandroidserialport/src/qserialportinfo.cpp + libs/qtandroidserialport/src/qserialportinfo_android.cpp + + src/Joystick/JoystickAndroid.cc + ) + endif() +endif() + +if(BUILD_TESTING) + + add_custom_target(check + COMMAND ctest --output-on-failure . + USES_TERMINAL + ) + + function (add_qgc_test test_name) + add_test( + NAME ${test_name} + COMMAND $ --unittest:${test_name} + ) + add_dependencies(check QGroundControl) + endfunction() + + list(APPEND QGC_SRC + src/AnalyzeView/LogDownloadTest.cc + + src/Audio/AudioOutputTest.cc + + src/comm/MockLink.cc + src/comm/MockLinkFileServer.cc + src/comm/MockLinkMissionItemHandler.cc + + src/FactSystem/FactSystemTestBase.cc + src/FactSystem/FactSystemTestGeneric.cc + src/FactSystem/FactSystemTestPX4.cc + src/FactSystem/ParameterManagerTest.cc + + src/MissionManager/CameraCalcTest.cc + src/MissionManager/CameraSectionTest.cc + src/MissionManager/CorridorScanComplexItemTest.cc + src/MissionManager/MissionCommandTreeTest.cc + src/MissionManager/MissionControllerManagerTest.cc + src/MissionManager/MissionControllerTest.cc + src/MissionManager/MissionItemTest.cc + src/MissionManager/MissionManagerTest.cc + src/MissionManager/MissionSettingsTest.cc + src/MissionManager/PlanMasterControllerTest.cc + src/MissionManager/QGCMapPolygonTest.cc + src/MissionManager/QGCMapPolylineTest.cc + src/MissionManager/SectionTest.cc + src/MissionManager/SimpleMissionItemTest.cc + src/MissionManager/SpeedSectionTest.cc + src/MissionManager/StructureScanComplexItemTest.cc + src/MissionManager/SurveyComplexItemTest.cc + src/MissionManager/TransectStyleComplexItemTest.cc + src/MissionManager/VisualMissionItemTest.cc + + src/qgcunittest/FileDialogTest.cc + src/qgcunittest/FileManagerTest.cc + src/qgcunittest/FlightGearTest.cc + src/qgcunittest/GeoTest.cc + src/qgcunittest/LinkManagerTest.cc + src/qgcunittest/MainWindowTest.cc + src/qgcunittest/MavlinkLogTest.cc + src/qgcunittest/MessageBoxTest.cc + src/qgcunittest/MultiSignalSpy.cc + src/qgcunittest/RadioConfigTest.cc + src/qgcunittest/TCPLinkTest.cc + src/qgcunittest/TCPLoopBackServer.cc + src/qgcunittest/UnitTest.cc + src/qgcunittest/UnitTestList.cc + + src/Vehicle/SendMavCommandTest.cc + ) + + add_qgc_test(AudioOutputTest) + add_qgc_test(CameraCalcTest) + add_qgc_test(CameraSectionTest) + add_qgc_test(CorridorScanComplexItemTest) + add_qgc_test(FactSystemTestGeneric) + add_qgc_test(FactSystemTestPX4) + add_qgc_test(FileDialogTest) + add_qgc_test(FileManagerTest) + add_qgc_test(FlightGearUnitTest) + add_qgc_test(GeoTest) + add_qgc_test(LinkManagerTest) + add_qgc_test(LogDownloadTest) + add_qgc_test(MessageBoxTest) + add_qgc_test(MissionCommandTreeTest) + add_qgc_test(MissionControllerTest) + add_qgc_test(MissionItemTest) + add_qgc_test(MissionManagerTest) + add_qgc_test(MissionSettingsTest) + add_qgc_test(ParameterManagerTest) + add_qgc_test(PlanMasterControllerTest) + add_qgc_test(QGCMapPolygonTest) + add_qgc_test(QGCMapPolylineTest) + add_qgc_test(RadioConfigTest) + add_qgc_test(SendMavCommandTest) + add_qgc_test(SimpleMissionItemTest) + add_qgc_test(SpeedSectionTest) + add_qgc_test(StructureScanComplexItemTest) + add_qgc_test(SurveyComplexItemTest) + add_qgc_test(TCPLinkTest) + add_qgc_test(TransectStyleComplexItemTest) + +endif() + +if (VIDEO) + list(APPEND QGC_SRC + src/VideoStreaming/gstqtvideosink/delegates/basedelegate.cpp + src/VideoStreaming/gstqtvideosink/delegates/qtquick2videosinkdelegate.cpp + src/VideoStreaming/gstqtvideosink/delegates/qtvideosinkdelegate.cpp + src/VideoStreaming/gstqtvideosink/delegates/qwidgetvideosinkdelegate.cpp + src/VideoStreaming/gstqtvideosink/gstqtglvideosink.cpp + src/VideoStreaming/gstqtvideosink/gstqtglvideosinkbase.cpp + src/VideoStreaming/gstqtvideosink/gstqtquick2videosink.cpp + src/VideoStreaming/gstqtvideosink/gstqtvideosink.cpp + src/VideoStreaming/gstqtvideosink/gstqtvideosinkbase.cpp + src/VideoStreaming/gstqtvideosink/gstqtvideosinkplugin.cpp + src/VideoStreaming/gstqtvideosink/gstqwidgetvideosink.cpp + src/VideoStreaming/gstqtvideosink/painters/genericsurfacepainter.cpp + src/VideoStreaming/gstqtvideosink/painters/openglsurfacepainter.cpp + src/VideoStreaming/gstqtvideosink/painters/videomaterial.cpp + src/VideoStreaming/gstqtvideosink/painters/videonode.cpp + src/VideoStreaming/gstqtvideosink/utils/bufferformat.cpp + src/VideoStreaming/gstqtvideosink/utils/utils.cpp + ) +endif() + +set(QGC_RESOURCES) +list(APPEND QGC_RESOURCES + #HackAndroidFileDialog.qrc + HackFileDialog.qrc + qgcresources.qrc + qgroundcontrol.qrc + src/FirmwarePlugin/APM/APMResources.qrc + src/FirmwarePlugin/PX4/PX4Resources.qrc + + src/Airmap/airmap.qrc +) + +if(BUILD_TESTING) + list(APPEND QGC_RESOURCES + UnitTest.qrc + ) +endif() + +# TODO: get qtquick compiler working +#qtquick_compiler_add_resources(QGC_RESOURCES ${QGC_RESOURCES} +#find_package(Qt5QuickCompiler) + +set(QGC_UI) +list(APPEND QGC_UI + #src/ui/Linechart.ui + src/QGCQmlWidgetHolder.ui + src/ui/MainWindow.ui + src/ui/MultiVehicleDockWidget.ui + src/ui/QGCHilConfiguration.ui + src/ui/QGCHilFlightGearConfiguration.ui + src/ui/QGCHilJSBSimConfiguration.ui + src/ui/QGCHilXPlaneConfiguration.ui + src/ui/QGCMapRCToParamDialog.ui + src/ui/QGCMAVLinkInspector.ui + src/ui/QGCMAVLinkLogPlayer.ui + src/ui/QGCPluginHost.ui + src/ui/QGCUASFileView.ui + src/ui/QGCUASFileViewMulti.ui + src/ui/QMap3D.ui + src/ui/uas/QGCUnconnectedInfoWidget.ui +) + +include_directories( + + src/QtLocationPlugin/QMLControl + #src/QtLocationPlugin/qtlocation/include/QtLocation + #src/QtLocationPlugin/qtlocation/include/QtLocation/5.5.1 + #src/QtLocationPlugin/qtlocation/include/QtPositioning/5.5.1 + ${Qt5Location_PRIVATE_INCLUDE_DIRS} + + libs/eigen + + libs/mavlink/include/mavlink/v2.0 + libs/mavlink/include/mavlink/v2.0/ardupilotmega + libs/mavlink/include/mavlink/v2.0/common + + libs/qwt + + src + + src/AnalyzeView + src/api + src/Audio + src/AutoPilotPlugins + src/AutoPilotPlugins/APM + src/AutoPilotPlugins/Common + src/AutoPilotPlugins/PX4 + src/Camera + src/comm + src/FactSystem + src/FactSystem/FactControls + src/FirmwarePlugin + src/FirmwarePlugin/APM + src/FlightDisplay + src/FlightMap/Widgets + src/FollowMe + src/GPS + src/Joystick + src/MissionManager + src/PositionManager + src/qgcunittest + src/QmlControls + src/QtLocationPlugin + src/Settings + src/Terrain + src/uas + src/ui + src/ui/linechart + src/Vehicle + src/VehicleSetup + src/VideoStreaming + src/ViewWidgets +) + +if(ANDROID) + add_library(QGroundControl SHARED ${QGC_SRC} ${QGC_RESOURCES} ${QGC_UI}) +else() + add_executable(QGroundControl ${QGC_SRC} ${QGC_RESOURCES} ${QGC_UI}) +endif() + +target_link_libraries(QGroundControl + Qt5::Bluetooth + Qt5::Concurrent + Qt5::Core + Qt5::Quick + Qt5::QuickWidgets + Qt5::Location + Qt5::Multimedia + Qt5::Positioning + Qt5::Sql + Qt5::Svg + Qt5::Test + Qt5::TextToSpeech + Qt5::Xml + Qt5::Widgets + ) + +if(NOT QT_MKSPEC MATCHES "winrt") + target_link_libraries(QGroundControl + Qt5::SerialPort + ) +endif() + +if(LINUX) + target_link_libraries(QGroundControl ${SDL2_LIBRARIES}) +elseif(APPLE) + target_link_libraries(QGroundControl -F${CMAKE_SOURCE_DIR}/libs/lib/Frameworks "-framework SDL2") + + set_target_properties(${PROJECT_NAME} PROPERTIES + MACOSX_BUNDLE YES + ) + + # deploy + include(Macdeployqt) + macdeployqt(QGroundControl) + +elseif(WIN32) + + if(MSVC) # Check if we are using the Visual Studio compiler + set_target_properties(${PROJECT_NAME} PROPERTIES + WIN32_EXECUTABLE YES + LINK_FLAGS "/ENTRY:mainCRTStartup" + ) + endif() + + # Support both 32 and 64 bit builds + if (${CMAKE_SIZEOF_VOID_P} MATCHES 8) + set(SDL2_LIBRARIES "${CMAKE_SOURCE_DIR}/libs/lib/sdl2/msvc/lib/x64/SDL2.lib;${CMAKE_SOURCE_DIR}/libs/lib/sdl2/msvc/lib/x64/SDL2main.lib") + else () + set(SDL2_LIBRARIES "${CMAKE_SOURCE_DIR}/libs/lib/sdl2/msvc/lib/x86/SDL2.lib;${CMAKE_SOURCE_DIR}/libs/lib/sdl2/msvc/lib/x86/SDL2main.lib") + endif () + + string(STRIP "${SDL2_LIBRARIES}" SDL2_LIBRARIES) + + target_link_libraries(QGroundControl ${SDL2_LIBRARIES}) + + # deploy + include(Windeployqt) + windeployqt(QGroundControl "QGroundControl-installer.exe") + +elseif(ANDROID) + include(AddQtAndroidApk) + add_qt_android_apk(QGroundControl.apk QGroundControl + PACKAGE_NAME "io.mavlink.qgroundcontrol" + #KEYSTORE ${CMAKE_CURRENT_LIST_DIR}/mykey.keystore myalias + #KEYSTORE_PASSWORD xxxxx + ) + +elseif(LINUX) + # TODO: investigate https://github.com/probonopd/linuxdeployqt + + add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/release/package/QGroundControl.AppImage + COMMAND ${CMAKE_SOURCE_DIR}/deploy/create_linux_appimage.sh ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}/release/package; + DEPENDS QGroundControl + USES_TERMINAL + ) + add_custom_target(appimage DEPENDS ${CMAKE_BINARY_DIR}/release/package/QGroundControl.AppImage) + +endif() + diff --git a/Jenkinsfile b/Jenkinsfile index e71b5e69e..859166b78 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -63,6 +63,36 @@ pipeline { } } + stage('Linux Debug (cmake)') { + environment { + CCACHE_BASEDIR = "${env.WORKSPACE}" + CMAKE_BUILD_TYPE = 'Debug' + QT_VERSION = "5.11.0" + QT_MKSPEC = "gcc_64" + } + agent { + docker { + image 'mavlink/qgc-build-linux:2018-06-07' + args '-v ${CCACHE_DIR}:${CCACHE_DIR}:rw' + } + } + steps { + sh 'export' + sh 'ccache -z' + sh 'make distclean' + sh 'make submodulesclean' + sh 'make linux' + //sh 'make linux check' // TODO: needs Xvfb or similar + sh 'ccache -s' + sh 'make distclean' + } + post { + cleanup { + sh 'git clean -ff -x -d .' + } + } + } + stage('Linux Release') { environment { CCACHE_BASEDIR = "${env.WORKSPACE}" @@ -95,6 +125,35 @@ pipeline { } } + stage('Linux Release (cmake)') { + environment { + CCACHE_BASEDIR = "${env.WORKSPACE}" + CMAKE_BUILD_TYPE = 'Release' + QT_VERSION = "5.11.0" + QT_MKSPEC = "gcc_64" + } + agent { + docker { + image 'mavlink/qgc-build-linux:2018-06-07' + args '-v ${CCACHE_DIR}:${CCACHE_DIR}:rw' + } + } + steps { + sh 'export' + sh 'ccache -z' + sh 'make distclean' + sh 'make submodulesclean' + sh 'make linux' + sh 'ccache -s' + sh 'make distclean' + } + post { + cleanup { + sh 'git clean -ff -x -d .' + } + } + } + stage('OSX Debug') { agent { node { @@ -123,6 +182,34 @@ pipeline { } } + stage('OSX Debug (cmake)') { + agent { + node { + label 'mac' + } + } + environment { + CCACHE_BASEDIR = "${env.WORKSPACE}" + CMAKE_BUILD_TYPE = 'Debug' + QT_VERSION = "5.11.0" + QT_MKSPEC = "clang_64" + } + steps { + sh 'export' + sh 'ccache -z' + sh 'make distclean' + sh 'make submodulesclean' + sh 'make mac' + sh 'ccache -s' + sh 'make distclean' + } + post { + cleanup { + sh 'git clean -ff -x -d .' + } + } + } + stage('OSX Release') { agent { node { @@ -175,6 +262,34 @@ pipeline { } } + stage('OSX Release (cmake)') { + agent { + node { + label 'mac' + } + } + environment { + CCACHE_BASEDIR = "${env.WORKSPACE}" + CMAKE_BUILD_TYPE = 'Release' + QT_VERSION = "5.11.0" + QT_MKSPEC = "clang_64" + } + steps { + sh 'export' + sh 'ccache -z' + sh 'make distclean' + sh 'make submodulesclean' + sh 'make mac' + sh 'ccache -s' + sh 'make distclean' + } + post { + cleanup { + sh 'git clean -ff -x -d .' + } + } + } + } // parallel } // stage('build') } // stages diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..072569fca --- /dev/null +++ b/Makefile @@ -0,0 +1,135 @@ + +# Enforce the presence of the GIT repository +# +# We depend on our submodules, so we have to prevent attempts to +# compile without it being present. +ifeq ($(wildcard .git),) + $(error YOU HAVE TO USE GIT TO DOWNLOAD THIS REPOSITORY. ABORTING.) +endif + + +# explicity set default build target +all: linux + +# Parsing +# -------------------------------------------------------------------- +# assume 1st argument passed is the main target, the +# rest are arguments to pass to the makefile generated +# by cmake in the subdirectory +FIRST_ARG := $(firstword $(MAKECMDGOALS)) +ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS)) +j ?= 4 + +NINJA_BIN := ninja +ifndef NO_NINJA_BUILD + NINJA_BUILD := $(shell $(NINJA_BIN) --version 2>/dev/null) + + ifndef NINJA_BUILD + NINJA_BIN := ninja-build + NINJA_BUILD := $(shell $(NINJA_BIN) --version 2>/dev/null) + endif +endif + +ifdef NINJA_BUILD + PX4_CMAKE_GENERATOR := Ninja + PX4_MAKE := $(NINJA_BIN) + + ifdef VERBOSE + PX4_MAKE_ARGS := -v + else + PX4_MAKE_ARGS := + endif +else + ifdef SYSTEMROOT + # Windows + PX4_CMAKE_GENERATOR := "MSYS\ Makefiles" + else + PX4_CMAKE_GENERATOR := "Unix\ Makefiles" + endif + PX4_MAKE = $(MAKE) + PX4_MAKE_ARGS = -j$(j) --no-print-directory +endif + +CMAKE_BUILD_TYPE ?= RelWithDebInfo + +SRC_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) + +# Functions +# -------------------------------------------------------------------- +# describe how to build a cmake config +define cmake-build ++@$(eval BUILD_DIR = $(SRC_DIR)/build/$@$(BUILD_DIR_SUFFIX)) ++@if [ $(PX4_CMAKE_GENERATOR) = "Ninja" ] && [ -e $(BUILD_DIR)/Makefile ]; then rm -rf $(BUILD_DIR); fi ++@if [ ! -e $(BUILD_DIR)/CMakeCache.txt ]; then mkdir -p $(BUILD_DIR) && cd $(BUILD_DIR) && cmake $(2) -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -G"$(PX4_CMAKE_GENERATOR)" -DQT_MKSPEC=$(1) || (rm -rf $(BUILD_DIR)); fi ++@(cd $(BUILD_DIR) && $(PX4_MAKE) $(PX4_MAKE_ARGS) $(ARGS)) +endef + + +# Qt mkspec +# android_armv7 android_x86 gcc_64 + +gcc_64: + $(call cmake-build,$@,$(SRC_DIR)) + +android_armv7: + $(call cmake-build,$@,$(SRC_DIR)) + +android_x86: + $(call cmake-build,$@,$(SRC_DIR)) + +clang_64: + $(call cmake-build,$@,$(SRC_DIR)) + +xcode: + @mkdir -p build/xcode; cd build/xcode; cmake -GXcode -DCMAKE_BUILD_TYPE=RelWithDebInfo $(SRC_DIR) + +linux: gcc_64 + +android: android_armv7 + +mac: clang_64 + + +# Astyle +# -------------------------------------------------------------------- +.PHONY: check_format format + +check_format: + $(call colorecho,"Checking formatting with astyle") + @$(SRC_DIR)/Tools/astyle/check_code_style_all.sh + @cd $(SRC_DIR) && git diff --check + +format: + $(call colorecho,"Formatting with astyle") + @$(SRC_DIR)/Tools/astyle/check_code_style_all.sh --fix + +# Testing +# -------------------------------------------------------------------- +.PHONY: tests tests_coverage + +tests: + +tests_coverage: + +# Cleanup +# -------------------------------------------------------------------- +.PHONY: clean submodulesclean submodulesupdate distclean + +clean: + @rm -rf $(SRC_DIR)/build + +submodulesclean: + @git submodule foreach --quiet --recursive git clean -ff -x -d + @git submodule update --quiet --init --recursive --force || true + @git submodule sync --recursive + @git submodule update --init --recursive --force + +submodulesupdate: + @git submodule update --quiet --init --recursive || true + @git submodule sync --recursive + @git submodule update --init --recursive + +distclean: + @git submodule deinit -f . + @git clean -ff -x -d -e ".project" -e ".cproject" -e ".idea" -e ".settings" -e ".vscode" + diff --git a/QGCCommon.pri b/QGCCommon.pri index 6317279bb..21b88be8e 100644 --- a/QGCCommon.pri +++ b/QGCCommon.pri @@ -57,7 +57,6 @@ linux { macx-clang | macx-llvm { message("Mac build") CONFIG += MacBuild - DEFINES += __macos__ CONFIG += x86_64 CONFIG -= x86 equals(QT_MAJOR_VERSION, 5) | greaterThan(QT_MINOR_VERSION, 5) { diff --git a/android/AndroidManifest.xml.in b/android/AndroidManifest.xml.in new file mode 100644 index 000000000..2d9c543f2 --- /dev/null +++ b/android/AndroidManifest.xml.in @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmake/AddQtAndroidApk.cmake b/cmake/AddQtAndroidApk.cmake new file mode 100644 index 000000000..ecb4ba78f --- /dev/null +++ b/cmake/AddQtAndroidApk.cmake @@ -0,0 +1,178 @@ +cmake_minimum_required(VERSION 3.0) +cmake_policy(SET CMP0026 OLD) # allow use of the LOCATION target property + +# store the current source directory for future use +set(QT_ANDROID_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}) + +# check the JAVA_HOME environment variable +# (I couldn't find a way to set it from this script, it has to be defined outside) +set(JAVA_HOME $ENV{JAVA_HOME}) +if(NOT JAVA_HOME) + message(FATAL_ERROR "The JAVA_HOME environment variable is not set. Please set it to the root directory of the JDK.") +endif() + +# make sure that the Android toolchain is used +if(NOT ANDROID) + message(FATAL_ERROR "Trying to use the CMake Android package without the Android toolchain. Please use the provided toolchain (toolchain/android.toolchain.cmake)") +endif() + +# find the Qt root directory +if(NOT Qt5Core_DIR) + find_package(Qt5Core REQUIRED) +endif() +get_filename_component(QT_ANDROID_QT_ROOT "${Qt5Core_DIR}/../../.." ABSOLUTE) +message(STATUS "Found Qt for Android: ${QT_ANDROID_QT_ROOT}") + +# find the Android SDK +if(NOT QT_ANDROID_SDK_ROOT) + set(QT_ANDROID_SDK_ROOT $ENV{ANDROID_SDK}) + if(NOT QT_ANDROID_SDK_ROOT) + message(FATAL_ERROR "Could not find the Android SDK. Please set either the ANDROID_SDK environment variable, or the QT_ANDROID_SDK_ROOT CMake variable to the root directory of the Android SDK") + endif() +endif() +string(REPLACE "\\" "/" QT_ANDROID_SDK_ROOT ${QT_ANDROID_SDK_ROOT}) # androiddeployqt doesn't like backslashes in paths +message(STATUS "Found Android SDK: ${QT_ANDROID_SDK_ROOT}") + +# find the Android NDK +if(NOT QT_ANDROID_NDK_ROOT) + set(QT_ANDROID_NDK_ROOT $ENV{ANDROID_NDK}) + if(NOT QT_ANDROID_NDK_ROOT) + set(QT_ANDROID_NDK_ROOT ${ANDROID_NDK}) + if(NOT QT_ANDROID_NDK_ROOT) + message(FATAL_ERROR "Could not find the Android NDK. Please set either the ANDROID_NDK environment or CMake variable, or the QT_ANDROID_NDK_ROOT CMake variable to the root directory of the Android NDK") + endif() + endif() +endif() +string(REPLACE "\\" "/" QT_ANDROID_NDK_ROOT ${QT_ANDROID_NDK_ROOT}) # androiddeployqt doesn't like backslashes in paths +message(STATUS "Found Android NDK: ${QT_ANDROID_NDK_ROOT}") + +include(CMakeParseArguments) + +# define a macro to create an Android APK target +# +# example: +# add_qt_android_apk(my_app_apk my_app +# NAME "My App" +# VERSION_CODE 12 +# PACKAGE_NAME "org.mycompany.myapp" +# PACKAGE_SOURCES ${CMAKE_CURRENT_LIST_DIR}/my-android-sources +# BUILDTOOLS_REVISION "23.0.3" +# KEYSTORE ${CMAKE_CURRENT_LIST_DIR}/mykey.keystore myalias +# KEYSTORE_PASSWORD xxxx +# DEPENDS a_linked_target "path/to/a_linked_library.so" ... +# INSTALL +#) +# +macro(add_qt_android_apk TARGET SOURCE_TARGET) + + # parse the macro arguments + cmake_parse_arguments(ARG "INSTALL" "NAME;VERSION_CODE;PACKAGE_NAME;PACKAGE_SOURCES;KEYSTORE_PASSWORD;BUILDTOOLS_REVISION" "DEPENDS;KEYSTORE" ${ARGN}) + + # extract the full path of the source target binary + if(CMAKE_BUILD_TYPE STREQUAL "Debug") + get_property(QT_ANDROID_APP_PATH TARGET ${SOURCE_TARGET} PROPERTY DEBUG_LOCATION) + else() + get_property(QT_ANDROID_APP_PATH TARGET ${SOURCE_TARGET} PROPERTY LOCATION) + endif() + + # define the application name + if(ARG_NAME) + set(QT_ANDROID_APP_NAME ${ARG_NAME}) + else() + set(QT_ANDROID_APP_NAME ${SOURCE_TARGET}) + endif() + + # define the application package name + if(ARG_PACKAGE_NAME) + set(QT_ANDROID_APP_PACKAGE_NAME ${ARG_PACKAGE_NAME}) + else() + set(QT_ANDROID_APP_PACKAGE_NAME org.qtproject.${SOURCE_TARGET}) + endif() + + # set the Android SDK build-tools revision + if(ARG_BUILDTOOLS_REVISION) + set(QT_ANDROID_SDK_BUILDTOOLS_REVISION ${ARG_BUILDTOOLS_REVISION}) + else() + set(QT_ANDROID_SDK_BUILDTOOLS_REVISION "") + endif() + + # define the application source package directory + if(ARG_PACKAGE_SOURCES) + set(QT_ANDROID_APP_PACKAGE_SOURCE_ROOT ${ARG_PACKAGE_SOURCES}) + else() + # get version code from arguments, or generate a fixed one if not provided + set(QT_ANDROID_APP_VERSION_CODE ${ARG_VERSION_CODE}) + if(NOT QT_ANDROID_APP_VERSION_CODE) + set(QT_ANDROID_APP_VERSION_CODE 1) + endif() + + # try to extract the app version from the target properties, or use the version code if not provided + get_property(QT_ANDROID_APP_VERSION TARGET ${SOURCE_TARGET} PROPERTY VERSION) + if(NOT QT_ANDROID_APP_VERSION) + set(QT_ANDROID_APP_VERSION ${QT_ANDROID_APP_VERSION_CODE}) + endif() + + # create a subdirectory for the extra package sources + set(QT_ANDROID_APP_PACKAGE_SOURCE_ROOT "${CMAKE_CURRENT_BINARY_DIR}/package") + + # generate a manifest from the template + configure_file(${QT_ANDROID_SOURCE_DIR}/AndroidManifest.xml.in ${QT_ANDROID_APP_PACKAGE_SOURCE_ROOT}/AndroidManifest.xml @ONLY) + endif() + + # set the list of dependant libraries + if(ARG_DEPENDS) + foreach(LIB ${ARG_DEPENDS}) + if(TARGET ${LIB}) + # item is a CMake target, extract the library path + if(CMAKE_BUILD_TYPE STREQUAL "Debug") + get_property(LIB_PATH TARGET ${LIB} PROPERTY DEBUG_LOCATION) + else() + get_property(LIB_PATH TARGET ${LIB} PROPERTY LOCATION) + endif() + set(LIB ${LIB_PATH}) + endif() + if(EXTRA_LIBS) + set(EXTRA_LIBS "${EXTRA_LIBS},${LIB}") + else() + set(EXTRA_LIBS "${LIB}") + endif() + endforeach() + set(QT_ANDROID_APP_EXTRA_LIBS "\"android-extra-libs\": \"${EXTRA_LIBS}\",") + endif() + + # make sure that the output directory for the Android package exists + file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/libs/${ANDROID_ABI}) + + # create the configuration file that will feed androiddeployqt + configure_file(${QT_ANDROID_SOURCE_DIR}/qtdeploy.json.in ${CMAKE_CURRENT_BINARY_DIR}/qtdeploy.json @ONLY) + + # check if the apk must be signed + if(ARG_KEYSTORE) + set(SIGN_OPTIONS --release --sign ${ARG_KEYSTORE} --tsa http://timestamp.digicert.com) + if(ARG_KEYSTORE_PASSWORD) + set(SIGN_OPTIONS ${SIGN_OPTIONS} --storepass ${ARG_KEYSTORE_PASSWORD}) + endif() + endif() + + # check if the apk must be installed to the device + if(ARG_INSTALL) + set(INSTALL_OPTIONS --reinstall) + endif() + + # specify the Android API level + if(ANDROID_NATIVE_API_LEVEL) + set(TARGET_LEVEL_OPTIONS --android-platform android-${ANDROID_NATIVE_API_LEVEL}) + endif() + + # create a custom command that will run the androiddeployqt utility to prepare the Android package + add_custom_target( + ${TARGET} + ALL + DEPENDS ${SOURCE_TARGET} + COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_CURRENT_BINARY_DIR}/libs/${ANDROID_ABI} # it seems that recompiled libraries are not copied if we don't remove them first + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/libs/${ANDROID_ABI} + COMMAND ${CMAKE_COMMAND} -E copy ${QT_ANDROID_APP_PATH} ${CMAKE_CURRENT_BINARY_DIR}/libs/${ANDROID_ABI} + COMMAND ${QT_ANDROID_QT_ROOT}/bin/androiddeployqt --verbose --output ${CMAKE_CURRENT_BINARY_DIR} --input ${CMAKE_CURRENT_BINARY_DIR}/qtdeploy.json --gradle ${TARGET_LEVEL_OPTIONS} ${INSTALL_OPTIONS} ${SIGN_OPTIONS} + ) + +endmacro() diff --git a/cmake/MacOSXBundleInfo.plist.in b/cmake/MacOSXBundleInfo.plist.in new file mode 100644 index 000000000..1cbddabce --- /dev/null +++ b/cmake/MacOSXBundleInfo.plist.in @@ -0,0 +1,38 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${MACOSX_BUNDLE_EXECUTABLE_NAME} + CFBundleGetInfoString + ${MACOSX_BUNDLE_INFO_STRING} + CFBundleIconFile + ${MACOSX_BUNDLE_ICON_FILE} + CFBundleIdentifier + ${MACOSX_BUNDLE_GUI_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleLongVersionString + ${MACOSX_BUNDLE_LONG_VERSION_STRING} + CFBundleName + ${MACOSX_BUNDLE_BUNDLE_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + ${MACOSX_BUNDLE_SHORT_VERSION_STRING} + CFBundleSignature + ???? + CFBundleVersion + ${MACOSX_BUNDLE_BUNDLE_VERSION} + CSResourcesFileMapped + + LSRequiresCarbon + + NSHumanReadableCopyright + ${MACOSX_BUNDLE_COPYRIGHT} + NSPrincipalClass + NSApplication + + diff --git a/cmake/Macdeployqt.cmake b/cmake/Macdeployqt.cmake new file mode 100644 index 000000000..70d707942 --- /dev/null +++ b/cmake/Macdeployqt.cmake @@ -0,0 +1,42 @@ +# The MIT License (MIT) +# +# Copyright (c) 2017 Nathan Osman +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +find_package(Qt5Core REQUIRED) + +# Retrieve the absolute path to qmake and then use that path to find +# the macdeployqt binary +get_target_property(_qmake_executable Qt5::qmake IMPORTED_LOCATION) +get_filename_component(_qt_bin_dir "${_qmake_executable}" DIRECTORY) +find_program(MACDEPLOYQT_EXECUTABLE macdeployqt HINTS "${_qt_bin_dir}") + +# Add commands that copy the required Qt files to the application bundle +# represented by the target +function(macdeployqt target) + add_custom_command(TARGET ${target} POST_BUILD + COMMAND "${MACDEPLOYQT_EXECUTABLE}" + \"$/../..\" + -always-overwrite + COMMENT "Deploying Qt..." + ) +endfunction() + +mark_as_advanced(MACDEPLOYQT_EXECUTABLE) diff --git a/cmake/Windeployqt.cmake b/cmake/Windeployqt.cmake new file mode 100644 index 000000000..c0f77d9d3 --- /dev/null +++ b/cmake/Windeployqt.cmake @@ -0,0 +1,102 @@ +# The MIT License (MIT) +# +# Copyright (c) 2017 Nathan Osman +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +find_package(Qt5Core REQUIRED) + +# Retrieve the absolute path to qmake and then use that path to find +# the windeployqt binary +get_target_property(_qmake_executable Qt5::qmake IMPORTED_LOCATION) +get_filename_component(_qt_bin_dir "${_qmake_executable}" DIRECTORY) +find_program(WINDEPLOYQT_EXECUTABLE windeployqt HINTS "${_qt_bin_dir}") + +# Running this with MSVC 2015 requires CMake 3.6+ +if((MSVC_VERSION VERSION_EQUAL 1900 OR MSVC_VERSION VERSION_GREATER 1900) + AND CMAKE_VERSION VERSION_LESS "3.6") + message(WARNING "Deploying with MSVC 2015+ requires CMake 3.6+") +endif() + +# Add commands that copy the Qt runtime to the target's output directory after +# build and install the Qt runtime to the specified directory +function(windeployqt target directory) + + # Run windeployqt immediately after build + add_custom_command(TARGET ${target} POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E + env PATH="${_qt_bin_dir}" "${WINDEPLOYQT_EXECUTABLE}" + --verbose 0 + --no-compiler-runtime + --no-angle + --no-opengl-sw + \"$\" + ) + + # install(CODE ...) doesn't support generator expressions, but + # file(GENERATE ...) does - store the path in a file + file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${target}_path" + CONTENT "$" + ) + + # Before installation, run a series of commands that copy each of the Qt + # runtime files to the appropriate directory for installation + install(CODE + " + file(READ \"${CMAKE_CURRENT_BINARY_DIR}/${target}_path\" _file) + execute_process( + COMMAND \"${CMAKE_COMMAND}\" -E + env PATH=\"${_qt_bin_dir}\" \"${WINDEPLOYQT_EXECUTABLE}\" + --dry-run + --no-compiler-runtime + --no-angle + --no-opengl-sw + --list mapping + \${_file} + OUTPUT_VARIABLE _output + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + separate_arguments(_files WINDOWS_COMMAND \${_output}) + while(_files) + list(GET _files 0 _src) + list(GET _files 1 _dest) + execute_process( + COMMAND \"${CMAKE_COMMAND}\" -E + copy \${_src} \"\${CMAKE_INSTALL_PREFIX}/${directory}/\${_dest}\" + ) + list(REMOVE_AT _files 0 1) + endwhile() + " + ) + + # windeployqt doesn't work correctly with the system runtime libraries, + # so we fall back to one of CMake's own modules for copying them over + set(CMAKE_INSTALL_UCRT_LIBRARIES TRUE) + include(InstallRequiredSystemLibraries) + foreach(lib ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS}) + get_filename_component(filename "${lib}" NAME) + add_custom_command(TARGET ${target} POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E + copy_if_different "${lib}" \"$\" + ) + endforeach() + +endfunction() + +mark_as_advanced(WINDEPLOYQT_EXECUTABLE) diff --git a/cmake/android.toolchain.cmake b/cmake/android.toolchain.cmake new file mode 100644 index 000000000..07100ee33 --- /dev/null +++ b/cmake/android.toolchain.cmake @@ -0,0 +1,1688 @@ +# Copyright (c) 2010-2011, Ethan Rublee +# Copyright (c) 2011-2014, Andrey Kamaev +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from this +# software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +# ------------------------------------------------------------------------------ +# Android CMake toolchain file, for use with the Android NDK r5-r10d +# Requires cmake 2.6.3 or newer (2.8.9 or newer is recommended). +# See home page: https://github.com/taka-no-me/android-cmake +# +# Usage Linux: +# $ export ANDROID_NDK=/absolute/path/to/the/android-ndk +# $ mkdir build && cd build +# $ cmake -DCMAKE_TOOLCHAIN_FILE=path/to/the/android.toolchain.cmake .. +# $ make -j8 +# +# Usage Windows: +# You need native port of make to build your project. +# Android NDK r7 (and newer) already has make.exe on board. +# For older NDK you have to install it separately. +# For example, this one: http://gnuwin32.sourceforge.net/packages/make.htm +# +# $ SET ANDROID_NDK=C:\absolute\path\to\the\android-ndk +# $ mkdir build && cd build +# $ cmake.exe -G"MinGW Makefiles" +# -DCMAKE_TOOLCHAIN_FILE=path\to\the\android.toolchain.cmake +# -DCMAKE_MAKE_PROGRAM="%ANDROID_NDK%\prebuilt\windows\bin\make.exe" .. +# $ cmake.exe --build . +# +# +# Options (can be set as cmake parameters: -D=): +# ANDROID_NDK=/opt/android-ndk - path to the NDK root. +# Can be set as environment variable. Can be set only at first cmake run. +# +# ANDROID_ABI=armeabi-v7a - specifies the target Application Binary +# Interface (ABI). This option nearly matches to the APP_ABI variable +# used by ndk-build tool from Android NDK. +# +# Possible targets are: +# "armeabi" - ARMv5TE based CPU with software floating point operations +# "armeabi-v7a" - ARMv7 based devices with hardware FPU instructions +# this ABI target is used by default +# "armeabi-v7a with NEON" - same as armeabi-v7a, but +# sets NEON as floating-point unit +# "armeabi-v7a with VFPV3" - same as armeabi-v7a, but +# sets VFPV3 as floating-point unit (has 32 registers instead of 16) +# "armeabi-v6 with VFP" - tuned for ARMv6 processors having VFP +# "x86" - IA-32 instruction set +# "mips" - MIPS32 instruction set +# +# 64-bit ABIs for NDK r10 and newer: +# "arm64-v8a" - ARMv8 AArch64 instruction set +# "x86_64" - Intel64 instruction set (r1) +# "mips64" - MIPS64 instruction set (r6) +# +# ANDROID_NATIVE_API_LEVEL=android-8 - level of Android API compile for. +# Option is read-only when standalone toolchain is used. +# Note: building for "android-L" requires explicit configuration. +# +# ANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-4.9 - the name of compiler +# toolchain to be used. The list of possible values depends on the NDK +# version. For NDK r10c the possible values are: +# +# * aarch64-linux-android-4.9 +# * aarch64-linux-android-clang3.4 +# * aarch64-linux-android-clang3.5 +# * arm-linux-androideabi-4.6 +# * arm-linux-androideabi-4.8 +# * arm-linux-androideabi-4.9 (default) +# * arm-linux-androideabi-clang3.4 +# * arm-linux-androideabi-clang3.5 +# * mips64el-linux-android-4.9 +# * mips64el-linux-android-clang3.4 +# * mips64el-linux-android-clang3.5 +# * mipsel-linux-android-4.6 +# * mipsel-linux-android-4.8 +# * mipsel-linux-android-4.9 +# * mipsel-linux-android-clang3.4 +# * mipsel-linux-android-clang3.5 +# * x86-4.6 +# * x86-4.8 +# * x86-4.9 +# * x86-clang3.4 +# * x86-clang3.5 +# * x86_64-4.9 +# * x86_64-clang3.4 +# * x86_64-clang3.5 +# +# ANDROID_FORCE_ARM_BUILD=OFF - set ON to generate 32-bit ARM instructions +# instead of Thumb. Is not available for "armeabi-v6 with VFP" +# (is forced to be ON) ABI. +# +# ANDROID_NO_UNDEFINED=ON - set ON to show all undefined symbols as linker +# errors even if they are not used. +# +# ANDROID_SO_UNDEFINED=OFF - set ON to allow undefined symbols in shared +# libraries. Automatically turned for NDK r5x and r6x due to GLESv2 +# problems. +# +# ANDROID_STL=gnustl_static - specify the runtime to use. +# +# Possible values are: +# none -> Do not configure the runtime. +# system -> Use the default minimal system C++ runtime library. +# Implies -fno-rtti -fno-exceptions. +# Is not available for standalone toolchain. +# system_re -> Use the default minimal system C++ runtime library. +# Implies -frtti -fexceptions. +# Is not available for standalone toolchain. +# gabi++_static -> Use the GAbi++ runtime as a static library. +# Implies -frtti -fno-exceptions. +# Available for NDK r7 and newer. +# Is not available for standalone toolchain. +# gabi++_shared -> Use the GAbi++ runtime as a shared library. +# Implies -frtti -fno-exceptions. +# Available for NDK r7 and newer. +# Is not available for standalone toolchain. +# stlport_static -> Use the STLport runtime as a static library. +# Implies -fno-rtti -fno-exceptions for NDK before r7. +# Implies -frtti -fno-exceptions for NDK r7 and newer. +# Is not available for standalone toolchain. +# stlport_shared -> Use the STLport runtime as a shared library. +# Implies -fno-rtti -fno-exceptions for NDK before r7. +# Implies -frtti -fno-exceptions for NDK r7 and newer. +# Is not available for standalone toolchain. +# gnustl_static -> Use the GNU STL as a static library. +# Implies -frtti -fexceptions. +# gnustl_shared -> Use the GNU STL as a shared library. +# Implies -frtti -fno-exceptions. +# Available for NDK r7b and newer. +# Silently degrades to gnustl_static if not available. +# +# ANDROID_STL_FORCE_FEATURES=ON - turn rtti and exceptions support based on +# chosen runtime. If disabled, then the user is responsible for settings +# these options. +# +# What?: +# android-cmake toolchain searches for NDK/toolchain in the following order: +# ANDROID_NDK - cmake parameter +# ANDROID_NDK - environment variable +# ANDROID_STANDALONE_TOOLCHAIN - cmake parameter +# ANDROID_STANDALONE_TOOLCHAIN - environment variable +# ANDROID_NDK - default locations +# ANDROID_STANDALONE_TOOLCHAIN - default locations +# +# Make sure to do the following in your scripts: +# SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${my_cxx_flags}" ) +# SET( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${my_cxx_flags}" ) +# The flags will be prepopulated with critical flags, so don't loose them. +# Also be aware that toolchain also sets configuration-specific compiler +# flags and linker flags. +# +# ANDROID and BUILD_ANDROID will be set to true, you may test any of these +# variables to make necessary Android-specific configuration changes. +# +# Also ARMEABI or ARMEABI_V7A or X86 or MIPS or ARM64_V8A or X86_64 or MIPS64 +# will be set true, mutually exclusive. NEON option will be set true +# if VFP is set to NEON. +# +# ------------------------------------------------------------------------------ + +cmake_minimum_required( VERSION 2.6.3 ) + +if( DEFINED CMAKE_CROSSCOMPILING ) + # subsequent toolchain loading is not really needed + return() +endif() + +if( CMAKE_TOOLCHAIN_FILE ) + # touch toolchain variable to suppress "unused variable" warning +endif() + +# inherit settings in recursive loads +get_property( _CMAKE_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE ) +if( _CMAKE_IN_TRY_COMPILE ) + include( "${CMAKE_CURRENT_SOURCE_DIR}/../android.toolchain.config.cmake" OPTIONAL ) +endif() + +# this one is important +if( CMAKE_VERSION VERSION_GREATER "3.0.99" ) + set( CMAKE_SYSTEM_NAME Android ) +else() + set( CMAKE_SYSTEM_NAME Linux ) +endif() + +# this one not so much +set( CMAKE_SYSTEM_VERSION 1 ) + +# rpath makes low sense for Android +set( CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "" ) +set( CMAKE_SKIP_RPATH TRUE CACHE BOOL "If set, runtime paths are not added when using shared libraries." ) + +# NDK search paths +set( ANDROID_SUPPORTED_NDK_VERSIONS ${ANDROID_EXTRA_NDK_VERSIONS} -r10d -r10c -r10b -r10 -r9d -r9c -r9b -r9 -r8e -r8d -r8c -r8b -r8 -r7c -r7b -r7 -r6b -r6 -r5c -r5b -r5 "" ) +if( NOT DEFINED ANDROID_NDK_SEARCH_PATHS ) + if( CMAKE_HOST_WIN32 ) + file( TO_CMAKE_PATH "$ENV{PROGRAMFILES}" ANDROID_NDK_SEARCH_PATHS ) + set( ANDROID_NDK_SEARCH_PATHS "${ANDROID_NDK_SEARCH_PATHS}" "$ENV{SystemDrive}/NVPACK" ) + else() + file( TO_CMAKE_PATH "$ENV{HOME}" ANDROID_NDK_SEARCH_PATHS ) + set( ANDROID_NDK_SEARCH_PATHS /opt "${ANDROID_NDK_SEARCH_PATHS}/NVPACK" ) + endif() +endif() +if( NOT DEFINED ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH ) + set( ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH /opt/android-toolchain ) +endif() + +# known ABIs +set( ANDROID_SUPPORTED_ABIS_arm "armeabi-v7a;armeabi;armeabi-v7a with NEON;armeabi-v7a with VFPV3;armeabi-v6 with VFP" ) +set( ANDROID_SUPPORTED_ABIS_arm64 "arm64-v8a" ) +set( ANDROID_SUPPORTED_ABIS_x86 "x86" ) +set( ANDROID_SUPPORTED_ABIS_x86_64 "x86_64" ) +set( ANDROID_SUPPORTED_ABIS_mips "mips" ) +set( ANDROID_SUPPORTED_ABIS_mips64 "mips64" ) + +# API level defaults +set( ANDROID_DEFAULT_NDK_API_LEVEL 8 ) +set( ANDROID_DEFAULT_NDK_API_LEVEL_arm64 21 ) +set( ANDROID_DEFAULT_NDK_API_LEVEL_x86 9 ) +set( ANDROID_DEFAULT_NDK_API_LEVEL_x86_64 21 ) +set( ANDROID_DEFAULT_NDK_API_LEVEL_mips 9 ) +set( ANDROID_DEFAULT_NDK_API_LEVEL_mips64 21 ) + + +macro( __LIST_FILTER listvar regex ) + if( ${listvar} ) + foreach( __val ${${listvar}} ) + if( __val MATCHES "${regex}" ) + list( REMOVE_ITEM ${listvar} "${__val}" ) + endif() + endforeach() + endif() +endmacro() + +macro( __INIT_VARIABLE var_name ) + set( __test_path 0 ) + foreach( __var ${ARGN} ) + if( __var STREQUAL "PATH" ) + set( __test_path 1 ) + break() + endif() + endforeach() + + if( __test_path AND NOT EXISTS "${${var_name}}" ) + unset( ${var_name} CACHE ) + endif() + + if( " ${${var_name}}" STREQUAL " " ) + set( __values 0 ) + foreach( __var ${ARGN} ) + if( __var STREQUAL "VALUES" ) + set( __values 1 ) + elseif( NOT __var STREQUAL "PATH" ) + if( __var MATCHES "^ENV_.*$" ) + string( REPLACE "ENV_" "" __var "${__var}" ) + set( __value "$ENV{${__var}}" ) + elseif( DEFINED ${__var} ) + set( __value "${${__var}}" ) + elseif( __values ) + set( __value "${__var}" ) + else() + set( __value "" ) + endif() + + if( NOT " ${__value}" STREQUAL " " AND (NOT __test_path OR EXISTS "${__value}") ) + set( ${var_name} "${__value}" ) + break() + endif() + endif() + endforeach() + unset( __value ) + unset( __values ) + endif() + + if( __test_path ) + file( TO_CMAKE_PATH "${${var_name}}" ${var_name} ) + endif() + unset( __test_path ) +endmacro() + +macro( __DETECT_NATIVE_API_LEVEL _var _path ) + set( __ndkApiLevelRegex "^[\t ]*#define[\t ]+__ANDROID_API__[\t ]+([0-9]+)[\t ]*.*$" ) + file( STRINGS ${_path} __apiFileContent REGEX "${__ndkApiLevelRegex}" ) + if( NOT __apiFileContent ) + message( SEND_ERROR "Could not get Android native API level. Probably you have specified invalid level value, or your copy of NDK/toolchain is broken." ) + endif() + string( REGEX REPLACE "${__ndkApiLevelRegex}" "\\1" ${_var} "${__apiFileContent}" ) + unset( __apiFileContent ) + unset( __ndkApiLevelRegex ) +endmacro() + +macro( __DETECT_TOOLCHAIN_MACHINE_NAME _var _root ) + if( EXISTS "${_root}" ) + file( GLOB __gccExePath RELATIVE "${_root}/bin/" "${_root}/bin/*-gcc${TOOL_OS_SUFFIX}" ) + __LIST_FILTER( __gccExePath "^[.].*" ) + list( LENGTH __gccExePath __gccExePathsCount ) + if( NOT __gccExePathsCount EQUAL 1 AND NOT _CMAKE_IN_TRY_COMPILE ) + message( WARNING "Could not determine machine name for compiler from ${_root}" ) + set( ${_var} "" ) + else() + get_filename_component( __gccExeName "${__gccExePath}" NAME_WE ) + string( REPLACE "-gcc" "" ${_var} "${__gccExeName}" ) + endif() + unset( __gccExePath ) + unset( __gccExePathsCount ) + unset( __gccExeName ) + else() + set( ${_var} "" ) + endif() +endmacro() + + +# fight against cygwin +set( ANDROID_FORBID_SYGWIN TRUE CACHE BOOL "Prevent cmake from working under cygwin and using cygwin tools") +mark_as_advanced( ANDROID_FORBID_SYGWIN ) +if( ANDROID_FORBID_SYGWIN ) + if( CYGWIN ) + message( FATAL_ERROR "Android NDK and android-cmake toolchain are not welcome Cygwin. It is unlikely that this cmake toolchain will work under cygwin. But if you want to try then you can set cmake variable ANDROID_FORBID_SYGWIN to FALSE and rerun cmake." ) + endif() + + if( CMAKE_HOST_WIN32 ) + # remove cygwin from PATH + set( __new_path "$ENV{PATH}") + __LIST_FILTER( __new_path "cygwin" ) + set(ENV{PATH} "${__new_path}") + unset(__new_path) + endif() +endif() + + +# detect current host platform +if( NOT DEFINED ANDROID_NDK_HOST_X64 AND (CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "amd64|x86_64|AMD64" OR CMAKE_HOST_APPLE) ) + set( ANDROID_NDK_HOST_X64 1 CACHE BOOL "Try to use 64-bit compiler toolchain" ) + mark_as_advanced( ANDROID_NDK_HOST_X64 ) +endif() + +set( TOOL_OS_SUFFIX "" ) +if( CMAKE_HOST_APPLE ) + set( ANDROID_NDK_HOST_SYSTEM_NAME "darwin-x86_64" ) + set( ANDROID_NDK_HOST_SYSTEM_NAME2 "darwin-x86" ) +elseif( CMAKE_HOST_WIN32 ) + set( ANDROID_NDK_HOST_SYSTEM_NAME "windows-x86_64" ) + set( ANDROID_NDK_HOST_SYSTEM_NAME2 "windows" ) + set( TOOL_OS_SUFFIX ".exe" ) +elseif( CMAKE_HOST_UNIX ) + set( ANDROID_NDK_HOST_SYSTEM_NAME "linux-x86_64" ) + set( ANDROID_NDK_HOST_SYSTEM_NAME2 "linux-x86" ) +else() + message( FATAL_ERROR "Cross-compilation on your platform is not supported by this cmake toolchain" ) +endif() + +if( NOT ANDROID_NDK_HOST_X64 ) + set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) +endif() + +# see if we have path to Android NDK +if( NOT ANDROID_NDK AND NOT ANDROID_STANDALONE_TOOLCHAIN ) + __INIT_VARIABLE( ANDROID_NDK PATH ENV_ANDROID_NDK ) +endif() +if( NOT ANDROID_NDK ) + # see if we have path to Android standalone toolchain + __INIT_VARIABLE( ANDROID_STANDALONE_TOOLCHAIN PATH ENV_ANDROID_STANDALONE_TOOLCHAIN ) + + if( NOT ANDROID_STANDALONE_TOOLCHAIN ) + #try to find Android NDK in one of the the default locations + set( __ndkSearchPaths ) + foreach( __ndkSearchPath ${ANDROID_NDK_SEARCH_PATHS} ) + foreach( suffix ${ANDROID_SUPPORTED_NDK_VERSIONS} ) + list( APPEND __ndkSearchPaths "${__ndkSearchPath}/android-ndk${suffix}" ) + endforeach() + endforeach() + __INIT_VARIABLE( ANDROID_NDK PATH VALUES ${__ndkSearchPaths} ) + unset( __ndkSearchPaths ) + + if( ANDROID_NDK ) + message( STATUS "Using default path for Android NDK: ${ANDROID_NDK}" ) + message( STATUS " If you prefer to use a different location, please define a cmake or environment variable: ANDROID_NDK" ) + else() + #try to find Android standalone toolchain in one of the the default locations + __INIT_VARIABLE( ANDROID_STANDALONE_TOOLCHAIN PATH ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH ) + + if( ANDROID_STANDALONE_TOOLCHAIN ) + message( STATUS "Using default path for standalone toolchain ${ANDROID_STANDALONE_TOOLCHAIN}" ) + message( STATUS " If you prefer to use a different location, please define the variable: ANDROID_STANDALONE_TOOLCHAIN" ) + endif( ANDROID_STANDALONE_TOOLCHAIN ) + endif( ANDROID_NDK ) + endif( NOT ANDROID_STANDALONE_TOOLCHAIN ) +endif( NOT ANDROID_NDK ) + +# remember found paths +if( ANDROID_NDK ) + get_filename_component( ANDROID_NDK "${ANDROID_NDK}" ABSOLUTE ) + set( ANDROID_NDK "${ANDROID_NDK}" CACHE INTERNAL "Path of the Android NDK" FORCE ) + set( BUILD_WITH_ANDROID_NDK True ) + if( EXISTS "${ANDROID_NDK}/RELEASE.TXT" ) + file( STRINGS "${ANDROID_NDK}/RELEASE.TXT" ANDROID_NDK_RELEASE_FULL LIMIT_COUNT 1 REGEX "r[0-9]+[a-z]?" ) + string( REGEX MATCH "r([0-9]+)([a-z]?)" ANDROID_NDK_RELEASE "${ANDROID_NDK_RELEASE_FULL}" ) + else() + set( ANDROID_NDK_RELEASE "r1x" ) + set( ANDROID_NDK_RELEASE_FULL "unreleased" ) + endif() + string( REGEX REPLACE "r([0-9]+)([a-z]?)" "\\1*1000" ANDROID_NDK_RELEASE_NUM "${ANDROID_NDK_RELEASE}" ) + string( FIND " abcdefghijklmnopqastuvwxyz" "${CMAKE_MATCH_2}" __ndkReleaseLetterNum ) + math( EXPR ANDROID_NDK_RELEASE_NUM "${ANDROID_NDK_RELEASE_NUM}+${__ndkReleaseLetterNum}" ) +elseif( ANDROID_STANDALONE_TOOLCHAIN ) + get_filename_component( ANDROID_STANDALONE_TOOLCHAIN "${ANDROID_STANDALONE_TOOLCHAIN}" ABSOLUTE ) + # try to detect change + if( CMAKE_AR ) + string( LENGTH "${ANDROID_STANDALONE_TOOLCHAIN}" __length ) + string( SUBSTRING "${CMAKE_AR}" 0 ${__length} __androidStandaloneToolchainPreviousPath ) + if( NOT __androidStandaloneToolchainPreviousPath STREQUAL ANDROID_STANDALONE_TOOLCHAIN ) + message( FATAL_ERROR "It is not possible to change path to the Android standalone toolchain on subsequent run." ) + endif() + unset( __androidStandaloneToolchainPreviousPath ) + unset( __length ) + endif() + set( ANDROID_STANDALONE_TOOLCHAIN "${ANDROID_STANDALONE_TOOLCHAIN}" CACHE INTERNAL "Path of the Android standalone toolchain" FORCE ) + set( BUILD_WITH_STANDALONE_TOOLCHAIN True ) +else() + list(GET ANDROID_NDK_SEARCH_PATHS 0 ANDROID_NDK_SEARCH_PATH) + message( FATAL_ERROR "Could not find neither Android NDK nor Android standalone toolchain. + You should either set an environment variable: + export ANDROID_NDK=~/my-android-ndk + or + export ANDROID_STANDALONE_TOOLCHAIN=~/my-android-toolchain + or put the toolchain or NDK in the default path: + sudo ln -s ~/my-android-ndk ${ANDROID_NDK_SEARCH_PATH}/android-ndk + sudo ln -s ~/my-android-toolchain ${ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH}" ) +endif() + +# android NDK layout +if( BUILD_WITH_ANDROID_NDK ) + if( NOT DEFINED ANDROID_NDK_LAYOUT ) + # try to automatically detect the layout + if( EXISTS "${ANDROID_NDK}/RELEASE.TXT") + set( ANDROID_NDK_LAYOUT "RELEASE" ) + elseif( EXISTS "${ANDROID_NDK}/../../linux-x86/toolchain/" ) + set( ANDROID_NDK_LAYOUT "LINARO" ) + elseif( EXISTS "${ANDROID_NDK}/../../gcc/" ) + set( ANDROID_NDK_LAYOUT "ANDROID" ) + endif() + endif() + set( ANDROID_NDK_LAYOUT "${ANDROID_NDK_LAYOUT}" CACHE STRING "The inner layout of NDK" ) + mark_as_advanced( ANDROID_NDK_LAYOUT ) + if( ANDROID_NDK_LAYOUT STREQUAL "LINARO" ) + set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) # only 32-bit at the moment + set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/../../${ANDROID_NDK_HOST_SYSTEM_NAME}/toolchain" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH "" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "" ) + elseif( ANDROID_NDK_LAYOUT STREQUAL "ANDROID" ) + set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) # only 32-bit at the moment + set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/../../gcc/${ANDROID_NDK_HOST_SYSTEM_NAME}/arm" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH "" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "" ) + else() # ANDROID_NDK_LAYOUT STREQUAL "RELEASE" + set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/toolchains" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH "/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME2}" ) + endif() + get_filename_component( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK_TOOLCHAINS_PATH}" ABSOLUTE ) + + # try to detect change of NDK + if( CMAKE_AR ) + string( LENGTH "${ANDROID_NDK_TOOLCHAINS_PATH}" __length ) + string( SUBSTRING "${CMAKE_AR}" 0 ${__length} __androidNdkPreviousPath ) + if( NOT __androidNdkPreviousPath STREQUAL ANDROID_NDK_TOOLCHAINS_PATH ) + message( FATAL_ERROR "It is not possible to change the path to the NDK on subsequent CMake run. You must remove all generated files from your build folder first. + " ) + endif() + unset( __androidNdkPreviousPath ) + unset( __length ) + endif() +endif() + + +# get all the details about standalone toolchain +if( BUILD_WITH_STANDALONE_TOOLCHAIN ) + __DETECT_NATIVE_API_LEVEL( ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot/usr/include/android/api-level.h" ) + set( ANDROID_STANDALONE_TOOLCHAIN_API_LEVEL ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} ) + set( __availableToolchains "standalone" ) + __DETECT_TOOLCHAIN_MACHINE_NAME( __availableToolchainMachines "${ANDROID_STANDALONE_TOOLCHAIN}" ) + if( NOT __availableToolchainMachines ) + message( FATAL_ERROR "Could not determine machine name of your toolchain. Probably your Android standalone toolchain is broken." ) + endif() + if( __availableToolchainMachines MATCHES x86_64 ) + set( __availableToolchainArchs "x86_64" ) + elseif( __availableToolchainMachines MATCHES i686 ) + set( __availableToolchainArchs "x86" ) + elseif( __availableToolchainMachines MATCHES aarch64 ) + set( __availableToolchainArchs "arm64" ) + elseif( __availableToolchainMachines MATCHES arm ) + set( __availableToolchainArchs "arm" ) + elseif( __availableToolchainMachines MATCHES mips64el ) + set( __availableToolchainArchs "mips64" ) + elseif( __availableToolchainMachines MATCHES mipsel ) + set( __availableToolchainArchs "mips" ) + endif() + execute_process( COMMAND "${ANDROID_STANDALONE_TOOLCHAIN}/bin/${__availableToolchainMachines}-gcc${TOOL_OS_SUFFIX}" -dumpversion + OUTPUT_VARIABLE __availableToolchainCompilerVersions OUTPUT_STRIP_TRAILING_WHITESPACE ) + string( REGEX MATCH "[0-9]+[.][0-9]+([.][0-9]+)?" __availableToolchainCompilerVersions "${__availableToolchainCompilerVersions}" ) + if( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/bin/clang${TOOL_OS_SUFFIX}" ) + list( APPEND __availableToolchains "standalone-clang" ) + list( APPEND __availableToolchainMachines ${__availableToolchainMachines} ) + list( APPEND __availableToolchainArchs ${__availableToolchainArchs} ) + list( APPEND __availableToolchainCompilerVersions ${__availableToolchainCompilerVersions} ) + endif() +endif() + +macro( __GLOB_NDK_TOOLCHAINS __availableToolchainsVar __availableToolchainsLst __toolchain_subpath ) + foreach( __toolchain ${${__availableToolchainsLst}} ) + if( "${__toolchain}" MATCHES "-clang3[.][0-9]$" AND NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${__toolchain}${__toolchain_subpath}" ) + SET( __toolchainVersionRegex "^TOOLCHAIN_VERSION[\t ]+:=[\t ]+(.*)$" ) + FILE( STRINGS "${ANDROID_NDK_TOOLCHAINS_PATH}/${__toolchain}/setup.mk" __toolchainVersionStr REGEX "${__toolchainVersionRegex}" ) + if( __toolchainVersionStr ) + string( REGEX REPLACE "${__toolchainVersionRegex}" "\\1" __toolchainVersionStr "${__toolchainVersionStr}" ) + string( REGEX REPLACE "-clang3[.][0-9]$" "-${__toolchainVersionStr}" __gcc_toolchain "${__toolchain}" ) + else() + string( REGEX REPLACE "-clang3[.][0-9]$" "-4.6" __gcc_toolchain "${__toolchain}" ) + endif() + unset( __toolchainVersionStr ) + unset( __toolchainVersionRegex ) + else() + set( __gcc_toolchain "${__toolchain}" ) + endif() + __DETECT_TOOLCHAIN_MACHINE_NAME( __machine "${ANDROID_NDK_TOOLCHAINS_PATH}/${__gcc_toolchain}${__toolchain_subpath}" ) + if( __machine ) + string( REGEX MATCH "[0-9]+[.][0-9]+([.][0-9x]+)?$" __version "${__gcc_toolchain}" ) + if( __machine MATCHES x86_64 ) + set( __arch "x86_64" ) + elseif( __machine MATCHES i686 ) + set( __arch "x86" ) + elseif( __machine MATCHES aarch64 ) + set( __arch "arm64" ) + elseif( __machine MATCHES arm ) + set( __arch "arm" ) + elseif( __machine MATCHES mips64el ) + set( __arch "mips64" ) + elseif( __machine MATCHES mipsel ) + set( __arch "mips" ) + else() + set( __arch "" ) + endif() + #message("machine: !${__machine}!\narch: !${__arch}!\nversion: !${__version}!\ntoolchain: !${__toolchain}!\n") + if (__arch) + list( APPEND __availableToolchainMachines "${__machine}" ) + list( APPEND __availableToolchainArchs "${__arch}" ) + list( APPEND __availableToolchainCompilerVersions "${__version}" ) + list( APPEND ${__availableToolchainsVar} "${__toolchain}" ) + endif() + endif() + unset( __gcc_toolchain ) + endforeach() +endmacro() + +# get all the details about NDK +if( BUILD_WITH_ANDROID_NDK ) + file( GLOB ANDROID_SUPPORTED_NATIVE_API_LEVELS RELATIVE "${ANDROID_NDK}/platforms" "${ANDROID_NDK}/platforms/android-*" ) + string( REPLACE "android-" "" ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_SUPPORTED_NATIVE_API_LEVELS}" ) + set( __availableToolchains "" ) + set( __availableToolchainMachines "" ) + set( __availableToolchainArchs "" ) + set( __availableToolchainCompilerVersions "" ) + if( ANDROID_TOOLCHAIN_NAME AND EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_TOOLCHAIN_NAME}/" ) + # do not go through all toolchains if we know the name + set( __availableToolchainsLst "${ANDROID_TOOLCHAIN_NAME}" ) + __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH}" ) + if( NOT __availableToolchains AND NOT ANDROID_NDK_TOOLCHAINS_SUBPATH STREQUAL ANDROID_NDK_TOOLCHAINS_SUBPATH2 ) + __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH2}" ) + if( __availableToolchains ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH ${ANDROID_NDK_TOOLCHAINS_SUBPATH2} ) + endif() + endif() + endif() + if( NOT __availableToolchains ) + file( GLOB __availableToolchainsLst RELATIVE "${ANDROID_NDK_TOOLCHAINS_PATH}" "${ANDROID_NDK_TOOLCHAINS_PATH}/*" ) + if( __availableToolchains ) + list(SORT __availableToolchainsLst) # we need clang to go after gcc + endif() + __LIST_FILTER( __availableToolchainsLst "^[.]" ) + __LIST_FILTER( __availableToolchainsLst "llvm" ) + __LIST_FILTER( __availableToolchainsLst "renderscript" ) + __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH}" ) + if( NOT __availableToolchains AND NOT ANDROID_NDK_TOOLCHAINS_SUBPATH STREQUAL ANDROID_NDK_TOOLCHAINS_SUBPATH2 ) + __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH2}" ) + if( __availableToolchains ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH ${ANDROID_NDK_TOOLCHAINS_SUBPATH2} ) + endif() + endif() + endif() + if( NOT __availableToolchains ) + message( FATAL_ERROR "Could not find any working toolchain in the NDK. Probably your Android NDK is broken." ) + endif() +endif() + +# build list of available ABIs +set( ANDROID_SUPPORTED_ABIS "" ) +set( __uniqToolchainArchNames ${__availableToolchainArchs} ) +list( REMOVE_DUPLICATES __uniqToolchainArchNames ) +list( SORT __uniqToolchainArchNames ) +foreach( __arch ${__uniqToolchainArchNames} ) + list( APPEND ANDROID_SUPPORTED_ABIS ${ANDROID_SUPPORTED_ABIS_${__arch}} ) +endforeach() +unset( __uniqToolchainArchNames ) +if( NOT ANDROID_SUPPORTED_ABIS ) + message( FATAL_ERROR "No one of known Android ABIs is supported by this cmake toolchain." ) +endif() + +# choose target ABI +__INIT_VARIABLE( ANDROID_ABI VALUES ${ANDROID_SUPPORTED_ABIS} ) +# verify that target ABI is supported +list( FIND ANDROID_SUPPORTED_ABIS "${ANDROID_ABI}" __androidAbiIdx ) +if( __androidAbiIdx EQUAL -1 ) + string( REPLACE ";" "\", \"" PRINTABLE_ANDROID_SUPPORTED_ABIS "${ANDROID_SUPPORTED_ABIS}" ) + message( FATAL_ERROR "Specified ANDROID_ABI = \"${ANDROID_ABI}\" is not supported by this cmake toolchain or your NDK/toolchain. + Supported values are: \"${PRINTABLE_ANDROID_SUPPORTED_ABIS}\" + " ) +endif() +unset( __androidAbiIdx ) + +# set target ABI options +if( ANDROID_ABI STREQUAL "x86" ) + set( X86 true ) + set( ANDROID_NDK_ABI_NAME "x86" ) + set( ANDROID_ARCH_NAME "x86" ) + set( ANDROID_LLVM_TRIPLE "i686-none-linux-android" ) + set( CMAKE_SYSTEM_PROCESSOR "i686" ) +elseif( ANDROID_ABI STREQUAL "x86_64" ) + set( X86 true ) + set( X86_64 true ) + set( ANDROID_NDK_ABI_NAME "x86_64" ) + set( ANDROID_ARCH_NAME "x86_64" ) + set( CMAKE_SYSTEM_PROCESSOR "x86_64" ) + set( ANDROID_LLVM_TRIPLE "x86_64-none-linux-android" ) +elseif( ANDROID_ABI STREQUAL "mips64" ) + set( MIPS64 true ) + set( ANDROID_NDK_ABI_NAME "mips64" ) + set( ANDROID_ARCH_NAME "mips64" ) + set( ANDROID_LLVM_TRIPLE "mips64el-none-linux-android" ) + set( CMAKE_SYSTEM_PROCESSOR "mips64" ) +elseif( ANDROID_ABI STREQUAL "mips" ) + set( MIPS true ) + set( ANDROID_NDK_ABI_NAME "mips" ) + set( ANDROID_ARCH_NAME "mips" ) + set( ANDROID_LLVM_TRIPLE "mipsel-none-linux-android" ) + set( CMAKE_SYSTEM_PROCESSOR "mips" ) +elseif( ANDROID_ABI STREQUAL "arm64-v8a" ) + set( ARM64_V8A true ) + set( ANDROID_NDK_ABI_NAME "arm64-v8a" ) + set( ANDROID_ARCH_NAME "arm64" ) + set( ANDROID_LLVM_TRIPLE "aarch64-none-linux-android" ) + set( CMAKE_SYSTEM_PROCESSOR "aarch64" ) + set( VFPV3 true ) + set( NEON true ) +elseif( ANDROID_ABI STREQUAL "armeabi" ) + set( ARMEABI true ) + set( ANDROID_NDK_ABI_NAME "armeabi" ) + set( ANDROID_ARCH_NAME "arm" ) + set( ANDROID_LLVM_TRIPLE "armv5te-none-linux-androideabi" ) + set( CMAKE_SYSTEM_PROCESSOR "armv5te" ) +elseif( ANDROID_ABI STREQUAL "armeabi-v6 with VFP" ) + set( ARMEABI_V6 true ) + set( ANDROID_NDK_ABI_NAME "armeabi" ) + set( ANDROID_ARCH_NAME "arm" ) + set( ANDROID_LLVM_TRIPLE "armv5te-none-linux-androideabi" ) + set( CMAKE_SYSTEM_PROCESSOR "armv6" ) + # need always fallback to older platform + set( ARMEABI true ) +elseif( ANDROID_ABI STREQUAL "armeabi-v7a") + set( ARMEABI_V7A true ) + set( ANDROID_NDK_ABI_NAME "armeabi-v7a" ) + set( ANDROID_ARCH_NAME "arm" ) + set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" ) + set( CMAKE_SYSTEM_PROCESSOR "armv7-a" ) +elseif( ANDROID_ABI STREQUAL "armeabi-v7a with VFPV3" ) + set( ARMEABI_V7A true ) + set( ANDROID_NDK_ABI_NAME "armeabi-v7a" ) + set( ANDROID_ARCH_NAME "arm" ) + set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" ) + set( CMAKE_SYSTEM_PROCESSOR "armv7-a" ) + set( VFPV3 true ) +elseif( ANDROID_ABI STREQUAL "armeabi-v7a with NEON" ) + set( ARMEABI_V7A true ) + set( ANDROID_NDK_ABI_NAME "armeabi-v7a" ) + set( ANDROID_ARCH_NAME "arm" ) + set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" ) + set( CMAKE_SYSTEM_PROCESSOR "armv7-a" ) + set( VFPV3 true ) + set( NEON true ) +else() + message( SEND_ERROR "Unknown ANDROID_ABI=\"${ANDROID_ABI}\" is specified." ) +endif() + +if( CMAKE_BINARY_DIR AND EXISTS "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeSystem.cmake" ) + # really dirty hack + # it is not possible to change CMAKE_SYSTEM_PROCESSOR after the first run... + file( APPEND "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeSystem.cmake" "SET(CMAKE_SYSTEM_PROCESSOR \"${CMAKE_SYSTEM_PROCESSOR}\")\n" ) +endif() + +if( ANDROID_ARCH_NAME STREQUAL "arm" AND NOT ARMEABI_V6 ) + __INIT_VARIABLE( ANDROID_FORCE_ARM_BUILD VALUES OFF ) + set( ANDROID_FORCE_ARM_BUILD ${ANDROID_FORCE_ARM_BUILD} CACHE BOOL "Use 32-bit ARM instructions instead of Thumb-1" FORCE ) + mark_as_advanced( ANDROID_FORCE_ARM_BUILD ) +else() + unset( ANDROID_FORCE_ARM_BUILD CACHE ) +endif() + +# choose toolchain +if( ANDROID_TOOLCHAIN_NAME ) + list( FIND __availableToolchains "${ANDROID_TOOLCHAIN_NAME}" __toolchainIdx ) + if( __toolchainIdx EQUAL -1 ) + list( SORT __availableToolchains ) + string( REPLACE ";" "\n * " toolchains_list "${__availableToolchains}" ) + set( toolchains_list " * ${toolchains_list}") + message( FATAL_ERROR "Specified toolchain \"${ANDROID_TOOLCHAIN_NAME}\" is missing in your NDK or broken. Please verify that your NDK is working or select another compiler toolchain. +To configure the toolchain set CMake variable ANDROID_TOOLCHAIN_NAME to one of the following values:\n${toolchains_list}\n" ) + endif() + list( GET __availableToolchainArchs ${__toolchainIdx} __toolchainArch ) + if( NOT __toolchainArch STREQUAL ANDROID_ARCH_NAME ) + message( SEND_ERROR "Selected toolchain \"${ANDROID_TOOLCHAIN_NAME}\" is not able to compile binaries for the \"${ANDROID_ARCH_NAME}\" platform." ) + endif() +else() + set( __toolchainIdx -1 ) + set( __applicableToolchains "" ) + set( __toolchainMaxVersion "0.0.0" ) + list( LENGTH __availableToolchains __availableToolchainsCount ) + math( EXPR __availableToolchainsCount "${__availableToolchainsCount}-1" ) + foreach( __idx RANGE ${__availableToolchainsCount} ) + list( GET __availableToolchainArchs ${__idx} __toolchainArch ) + if( __toolchainArch STREQUAL ANDROID_ARCH_NAME ) + list( GET __availableToolchainCompilerVersions ${__idx} __toolchainVersion ) + string( REPLACE "x" "99" __toolchainVersion "${__toolchainVersion}") + if( __toolchainVersion VERSION_GREATER __toolchainMaxVersion ) + set( __toolchainMaxVersion "${__toolchainVersion}" ) + set( __toolchainIdx ${__idx} ) + endif() + endif() + endforeach() + unset( __availableToolchainsCount ) + unset( __toolchainMaxVersion ) + unset( __toolchainVersion ) +endif() +unset( __toolchainArch ) +if( __toolchainIdx EQUAL -1 ) + message( FATAL_ERROR "No one of available compiler toolchains is able to compile for ${ANDROID_ARCH_NAME} platform." ) +endif() +list( GET __availableToolchains ${__toolchainIdx} ANDROID_TOOLCHAIN_NAME ) +list( GET __availableToolchainMachines ${__toolchainIdx} ANDROID_TOOLCHAIN_MACHINE_NAME ) +list( GET __availableToolchainCompilerVersions ${__toolchainIdx} ANDROID_COMPILER_VERSION ) + +unset( __toolchainIdx ) +unset( __availableToolchains ) +unset( __availableToolchainMachines ) +unset( __availableToolchainArchs ) +unset( __availableToolchainCompilerVersions ) + +# choose native API level +__INIT_VARIABLE( ANDROID_NATIVE_API_LEVEL ENV_ANDROID_NATIVE_API_LEVEL ANDROID_API_LEVEL ENV_ANDROID_API_LEVEL ANDROID_STANDALONE_TOOLCHAIN_API_LEVEL ANDROID_DEFAULT_NDK_API_LEVEL_${ANDROID_ARCH_NAME} ANDROID_DEFAULT_NDK_API_LEVEL ) +string( REPLACE "android-" "" ANDROID_NATIVE_API_LEVEL "${ANDROID_NATIVE_API_LEVEL}" ) +string( STRIP "${ANDROID_NATIVE_API_LEVEL}" ANDROID_NATIVE_API_LEVEL ) +# adjust API level +set( __real_api_level ${ANDROID_DEFAULT_NDK_API_LEVEL_${ANDROID_ARCH_NAME}} ) +foreach( __level ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} ) + if( (__level LESS ANDROID_NATIVE_API_LEVEL OR __level STREQUAL ANDROID_NATIVE_API_LEVEL) AND NOT __level LESS __real_api_level ) + set( __real_api_level ${__level} ) + endif() +endforeach() +if( __real_api_level AND NOT ANDROID_NATIVE_API_LEVEL STREQUAL __real_api_level ) + message( STATUS "Adjusting Android API level 'android-${ANDROID_NATIVE_API_LEVEL}' to 'android-${__real_api_level}'") + set( ANDROID_NATIVE_API_LEVEL ${__real_api_level} ) +endif() +unset(__real_api_level) +# validate +list( FIND ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_NATIVE_API_LEVEL}" __levelIdx ) +if( __levelIdx EQUAL -1 ) + message( SEND_ERROR "Specified Android native API level 'android-${ANDROID_NATIVE_API_LEVEL}' is not supported by your NDK/toolchain." ) +else() + if( BUILD_WITH_ANDROID_NDK ) + __DETECT_NATIVE_API_LEVEL( __realApiLevel "${ANDROID_NDK}/platforms/android-${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME}/usr/include/android/api-level.h" ) + if( NOT __realApiLevel EQUAL ANDROID_NATIVE_API_LEVEL AND NOT __realApiLevel GREATER 9000 ) + message( SEND_ERROR "Specified Android API level (${ANDROID_NATIVE_API_LEVEL}) does not match to the level found (${__realApiLevel}). Probably your copy of NDK is broken." ) + endif() + unset( __realApiLevel ) + endif() + set( ANDROID_NATIVE_API_LEVEL "${ANDROID_NATIVE_API_LEVEL}" CACHE STRING "Android API level for native code" FORCE ) + set( CMAKE_ANDROID_API ${ANDROID_NATIVE_API_LEVEL} ) + if( CMAKE_VERSION VERSION_GREATER "2.8" ) + list( SORT ANDROID_SUPPORTED_NATIVE_API_LEVELS ) + set_property( CACHE ANDROID_NATIVE_API_LEVEL PROPERTY STRINGS ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} ) + endif() +endif() +unset( __levelIdx ) + + +# remember target ABI +set( ANDROID_ABI "${ANDROID_ABI}" CACHE STRING "The target ABI for Android. If arm, then armeabi-v7a is recommended for hardware floating point." FORCE ) +if( CMAKE_VERSION VERSION_GREATER "2.8" ) + list( SORT ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_NAME} ) + set_property( CACHE ANDROID_ABI PROPERTY STRINGS ${ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_NAME}} ) +endif() + + +# runtime choice (STL, rtti, exceptions) +if( NOT ANDROID_STL ) + set( ANDROID_STL gnustl_static ) +endif() +set( ANDROID_STL "${ANDROID_STL}" CACHE STRING "C++ runtime" ) +set( ANDROID_STL_FORCE_FEATURES ON CACHE BOOL "automatically configure rtti and exceptions support based on C++ runtime" ) +mark_as_advanced( ANDROID_STL ANDROID_STL_FORCE_FEATURES ) + +if( BUILD_WITH_ANDROID_NDK ) + if( NOT "${ANDROID_STL}" MATCHES "^(none|system|system_re|gabi\\+\\+_static|gabi\\+\\+_shared|stlport_static|stlport_shared|gnustl_static|gnustl_shared)$") + message( FATAL_ERROR "ANDROID_STL is set to invalid value \"${ANDROID_STL}\". +The possible values are: + none -> Do not configure the runtime. + system -> Use the default minimal system C++ runtime library. + system_re -> Same as system but with rtti and exceptions. + gabi++_static -> Use the GAbi++ runtime as a static library. + gabi++_shared -> Use the GAbi++ runtime as a shared library. + stlport_static -> Use the STLport runtime as a static library. + stlport_shared -> Use the STLport runtime as a shared library. + gnustl_static -> (default) Use the GNU STL as a static library. + gnustl_shared -> Use the GNU STL as a shared library. +" ) + endif() +elseif( BUILD_WITH_STANDALONE_TOOLCHAIN ) + if( NOT "${ANDROID_STL}" MATCHES "^(none|gnustl_static|gnustl_shared)$") + message( FATAL_ERROR "ANDROID_STL is set to invalid value \"${ANDROID_STL}\". +The possible values are: + none -> Do not configure the runtime. + gnustl_static -> (default) Use the GNU STL as a static library. + gnustl_shared -> Use the GNU STL as a shared library. +" ) + endif() +endif() + +unset( ANDROID_RTTI ) +unset( ANDROID_EXCEPTIONS ) +unset( ANDROID_STL_INCLUDE_DIRS ) +unset( __libstl ) +unset( __libsupcxx ) + +if( NOT _CMAKE_IN_TRY_COMPILE AND ANDROID_NDK_RELEASE STREQUAL "r7b" AND ARMEABI_V7A AND NOT VFPV3 AND ANDROID_STL MATCHES "gnustl" ) + message( WARNING "The GNU STL armeabi-v7a binaries from NDK r7b can crash non-NEON devices. The files provided with NDK r7b were not configured properly, resulting in crashes on Tegra2-based devices and others when trying to use certain floating-point functions (e.g., cosf, sinf, expf). +You are strongly recommended to switch to another NDK release. +" ) +endif() + +if( NOT _CMAKE_IN_TRY_COMPILE AND X86 AND ANDROID_STL MATCHES "gnustl" AND ANDROID_NDK_RELEASE STREQUAL "r6" ) + message( WARNING "The x86 system header file from NDK r6 has incorrect definition for ptrdiff_t. You are recommended to upgrade to a newer NDK release or manually patch the header: +See https://android.googlesource.com/platform/development.git f907f4f9d4e56ccc8093df6fee54454b8bcab6c2 + diff --git a/ndk/platforms/android-9/arch-x86/include/machine/_types.h b/ndk/platforms/android-9/arch-x86/include/machine/_types.h + index 5e28c64..65892a1 100644 + --- a/ndk/platforms/android-9/arch-x86/include/machine/_types.h + +++ b/ndk/platforms/android-9/arch-x86/include/machine/_types.h + @@ -51,7 +51,11 @@ typedef long int ssize_t; + #endif + #ifndef _PTRDIFF_T + #define _PTRDIFF_T + -typedef long ptrdiff_t; + +# ifdef __ANDROID__ + + typedef int ptrdiff_t; + +# else + + typedef long ptrdiff_t; + +# endif + #endif +" ) +endif() + + +# setup paths and STL for standalone toolchain +if( BUILD_WITH_STANDALONE_TOOLCHAIN ) + set( ANDROID_TOOLCHAIN_ROOT "${ANDROID_STANDALONE_TOOLCHAIN}" ) + set( ANDROID_CLANG_TOOLCHAIN_ROOT "${ANDROID_STANDALONE_TOOLCHAIN}" ) + set( ANDROID_SYSROOT "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot" ) + + if( NOT ANDROID_STL STREQUAL "none" ) + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_STANDALONE_TOOLCHAIN}/include/c++/${ANDROID_COMPILER_VERSION}" ) + if( NOT EXISTS "${ANDROID_STL_INCLUDE_DIRS}" ) + # old location ( pre r8c ) + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/include/c++/${ANDROID_COMPILER_VERSION}" ) + endif() + if( ARMEABI_V7A AND EXISTS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}/bits" ) + list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}" ) + elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/thumb/bits" ) + list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/thumb" ) + else() + list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}" ) + endif() + # always search static GNU STL to get the location of libsupc++.a + if( ARMEABI_V7A AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb/libstdc++.a" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb" ) + elseif( ARMEABI_V7A AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libstdc++.a" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}" ) + elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libstdc++.a" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb" ) + elseif( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libstdc++.a" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib" ) + endif() + if( __libstl ) + set( __libsupcxx "${__libstl}/libsupc++.a" ) + set( __libstl "${__libstl}/libstdc++.a" ) + endif() + if( NOT EXISTS "${__libsupcxx}" ) + message( FATAL_ERROR "The required libstdsupc++.a is missing in your standalone toolchain. + Usually it happens because of bug in make-standalone-toolchain.sh script from NDK r7, r7b and r7c. + You need to either upgrade to newer NDK or manually copy + $ANDROID_NDK/sources/cxx-stl/gnu-libstdc++/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a + to + ${__libsupcxx} + " ) + endif() + if( ANDROID_STL STREQUAL "gnustl_shared" ) + if( ARMEABI_V7A AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libgnustl_shared.so" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libgnustl_shared.so" ) + elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libgnustl_shared.so" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libgnustl_shared.so" ) + elseif( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libgnustl_shared.so" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libgnustl_shared.so" ) + endif() + endif() + endif() +endif() + +# clang +if( "${ANDROID_TOOLCHAIN_NAME}" STREQUAL "standalone-clang" ) + set( ANDROID_COMPILER_IS_CLANG 1 ) + execute_process( COMMAND "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/clang${TOOL_OS_SUFFIX}" --version OUTPUT_VARIABLE ANDROID_CLANG_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE ) + string( REGEX MATCH "[0-9]+[.][0-9]+" ANDROID_CLANG_VERSION "${ANDROID_CLANG_VERSION}") +elseif( "${ANDROID_TOOLCHAIN_NAME}" MATCHES "-clang3[.][0-9]?$" ) + string( REGEX MATCH "3[.][0-9]$" ANDROID_CLANG_VERSION "${ANDROID_TOOLCHAIN_NAME}") + string( REGEX REPLACE "-clang${ANDROID_CLANG_VERSION}$" "-${ANDROID_COMPILER_VERSION}" ANDROID_GCC_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_NAME}" ) + if( NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/llvm-${ANDROID_CLANG_VERSION}${ANDROID_NDK_TOOLCHAINS_SUBPATH}/bin/clang${TOOL_OS_SUFFIX}" ) + message( FATAL_ERROR "Could not find the Clang compiler driver" ) + endif() + set( ANDROID_COMPILER_IS_CLANG 1 ) + set( ANDROID_CLANG_TOOLCHAIN_ROOT "${ANDROID_NDK_TOOLCHAINS_PATH}/llvm-${ANDROID_CLANG_VERSION}${ANDROID_NDK_TOOLCHAINS_SUBPATH}" ) +else() + set( ANDROID_GCC_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_NAME}" ) + unset( ANDROID_COMPILER_IS_CLANG CACHE ) +endif() + +string( REPLACE "." "" _clang_name "clang${ANDROID_CLANG_VERSION}" ) +if( NOT EXISTS "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" ) + set( _clang_name "clang" ) +endif() + + +# setup paths and STL for NDK +if( BUILD_WITH_ANDROID_NDK ) + set( ANDROID_TOOLCHAIN_ROOT "${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}${ANDROID_NDK_TOOLCHAINS_SUBPATH}" ) + set( ANDROID_SYSROOT "${ANDROID_NDK}/platforms/android-${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME}" ) + + if( ANDROID_STL STREQUAL "none" ) + # do nothing + elseif( ANDROID_STL STREQUAL "system" ) + set( ANDROID_RTTI OFF ) + set( ANDROID_EXCEPTIONS OFF ) + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/system/include" ) + elseif( ANDROID_STL STREQUAL "system_re" ) + set( ANDROID_RTTI ON ) + set( ANDROID_EXCEPTIONS ON ) + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/system/include" ) + elseif( ANDROID_STL MATCHES "gabi" ) + if( ANDROID_NDK_RELEASE_NUM LESS 7000 ) # before r7 + message( FATAL_ERROR "gabi++ is not awailable in your NDK. You have to upgrade to NDK r7 or newer to use gabi++.") + endif() + set( ANDROID_RTTI ON ) + set( ANDROID_EXCEPTIONS OFF ) + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/gabi++/include" ) + set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gabi++/libs/${ANDROID_NDK_ABI_NAME}/libgabi++_static.a" ) + elseif( ANDROID_STL MATCHES "stlport" ) + if( NOT ANDROID_NDK_RELEASE_NUM LESS 8004 ) # before r8d + set( ANDROID_EXCEPTIONS ON ) + else() + set( ANDROID_EXCEPTIONS OFF ) + endif() + if( ANDROID_NDK_RELEASE_NUM LESS 7000 ) # before r7 + set( ANDROID_RTTI OFF ) + else() + set( ANDROID_RTTI ON ) + endif() + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/stlport/stlport" ) + set( __libstl "${ANDROID_NDK}/sources/cxx-stl/stlport/libs/${ANDROID_NDK_ABI_NAME}/libstlport_static.a" ) + elseif( ANDROID_STL MATCHES "gnustl" ) + set( ANDROID_EXCEPTIONS ON ) + set( ANDROID_RTTI ON ) + if( EXISTS "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}" ) + if( ARMEABI_V7A AND ANDROID_COMPILER_VERSION VERSION_EQUAL "4.7" AND ANDROID_NDK_RELEASE STREQUAL "r8d" ) + # gnustl binary for 4.7 compiler is buggy :( + # TODO: look for right fix + set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.6" ) + else() + set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}" ) + endif() + else() + set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++" ) + endif() + set( ANDROID_STL_INCLUDE_DIRS "${__libstl}/include" "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/include" "${__libstl}/include/backward" ) + if( EXISTS "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libgnustl_static.a" ) + set( __libstl "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libgnustl_static.a" ) + else() + set( __libstl "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libstdc++.a" ) + endif() + else() + message( FATAL_ERROR "Unknown runtime: ${ANDROID_STL}" ) + endif() + # find libsupc++.a - rtti & exceptions + if( ANDROID_STL STREQUAL "system_re" OR ANDROID_STL MATCHES "gnustl" ) + set( __libsupcxx "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" ) # r8b or newer + if( NOT EXISTS "${__libsupcxx}" ) + set( __libsupcxx "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" ) # r7-r8 + endif() + if( NOT EXISTS "${__libsupcxx}" ) # before r7 + if( ARMEABI_V7A ) + if( ANDROID_FORCE_ARM_BUILD ) + set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libsupc++.a" ) + else() + set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb/libsupc++.a" ) + endif() + elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD ) + set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libsupc++.a" ) + else() + set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libsupc++.a" ) + endif() + endif() + if( NOT EXISTS "${__libsupcxx}") + message( ERROR "Could not find libsupc++.a for a chosen platform. Either your NDK is not supported or is broken.") + endif() + endif() +endif() + + +# case of shared STL linkage +if( ANDROID_STL MATCHES "shared" AND DEFINED __libstl ) + string( REPLACE "_static.a" "_shared.so" __libstl "${__libstl}" ) + # TODO: check if .so file exists before the renaming +endif() + + +# ccache support +__INIT_VARIABLE( _ndk_ccache NDK_CCACHE ENV_NDK_CCACHE ) +if( _ndk_ccache ) + if( DEFINED NDK_CCACHE AND NOT EXISTS NDK_CCACHE ) + unset( NDK_CCACHE CACHE ) + endif() + find_program( NDK_CCACHE "${_ndk_ccache}" DOC "The path to ccache binary") +else() + unset( NDK_CCACHE CACHE ) +endif() +unset( _ndk_ccache ) + + +# setup the cross-compiler +if( NOT CMAKE_C_COMPILER ) + if( NDK_CCACHE AND NOT ANDROID_SYSROOT MATCHES "[ ;\"]" ) + set( CMAKE_C_COMPILER "${NDK_CCACHE}" CACHE PATH "ccache as C compiler" ) + set( CMAKE_CXX_COMPILER "${NDK_CCACHE}" CACHE PATH "ccache as C++ compiler" ) + if( ANDROID_COMPILER_IS_CLANG ) + set( CMAKE_C_COMPILER_ARG1 "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" CACHE PATH "C compiler") + set( CMAKE_CXX_COMPILER_ARG1 "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler") + else() + set( CMAKE_C_COMPILER_ARG1 "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "C compiler") + set( CMAKE_CXX_COMPILER_ARG1 "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-g++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler") + endif() + else() + if( ANDROID_COMPILER_IS_CLANG ) + set( CMAKE_C_COMPILER "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" CACHE PATH "C compiler") + set( CMAKE_CXX_COMPILER "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler") + else() + set( CMAKE_C_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "C compiler" ) + set( CMAKE_CXX_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-g++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler" ) + endif() + endif() + set( CMAKE_ASM_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "assembler" ) + set( CMAKE_STRIP "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-strip${TOOL_OS_SUFFIX}" CACHE PATH "strip" ) + set( CMAKE_AR "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ar${TOOL_OS_SUFFIX}" CACHE PATH "archive" ) + set( CMAKE_LINKER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ld${TOOL_OS_SUFFIX}" CACHE PATH "linker" ) + set( CMAKE_NM "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-nm${TOOL_OS_SUFFIX}" CACHE PATH "nm" ) + set( CMAKE_OBJCOPY "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-objcopy${TOOL_OS_SUFFIX}" CACHE PATH "objcopy" ) + set( CMAKE_OBJDUMP "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-objdump${TOOL_OS_SUFFIX}" CACHE PATH "objdump" ) + set( CMAKE_RANLIB "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ranlib${TOOL_OS_SUFFIX}" CACHE PATH "ranlib" ) +endif() + +set( _CMAKE_TOOLCHAIN_PREFIX "${ANDROID_TOOLCHAIN_MACHINE_NAME}-" ) +if( CMAKE_VERSION VERSION_LESS 2.8.5 ) + set( CMAKE_ASM_COMPILER_ARG1 "-c" ) +endif() +if( APPLE ) + find_program( CMAKE_INSTALL_NAME_TOOL NAMES install_name_tool ) + if( NOT CMAKE_INSTALL_NAME_TOOL ) + message( FATAL_ERROR "Could not find install_name_tool, please check your installation." ) + endif() + mark_as_advanced( CMAKE_INSTALL_NAME_TOOL ) +endif() + +# Force set compilers because standard identification works badly for us +include( CMakeForceCompiler ) +CMAKE_FORCE_C_COMPILER( "${CMAKE_C_COMPILER}" GNU ) +if( ANDROID_COMPILER_IS_CLANG ) + set( CMAKE_C_COMPILER_ID Clang ) +endif() +set( CMAKE_C_PLATFORM_ID Linux ) +if( X86_64 OR MIPS64 OR ARM64_V8A ) + set( CMAKE_C_SIZEOF_DATA_PTR 8 ) +else() + set( CMAKE_C_SIZEOF_DATA_PTR 4 ) +endif() +set( CMAKE_C_HAS_ISYSROOT 1 ) +set( CMAKE_C_COMPILER_ABI ELF ) +CMAKE_FORCE_CXX_COMPILER( "${CMAKE_CXX_COMPILER}" GNU ) +if( ANDROID_COMPILER_IS_CLANG ) + set( CMAKE_CXX_COMPILER_ID Clang) +endif() +set( CMAKE_CXX_PLATFORM_ID Linux ) +set( CMAKE_CXX_SIZEOF_DATA_PTR ${CMAKE_C_SIZEOF_DATA_PTR} ) +set( CMAKE_CXX_HAS_ISYSROOT 1 ) +set( CMAKE_CXX_COMPILER_ABI ELF ) +set( CMAKE_CXX_SOURCE_FILE_EXTENSIONS cc cp cxx cpp CPP c++ C ) +# force ASM compiler (required for CMake < 2.8.5) +set( CMAKE_ASM_COMPILER_ID_RUN TRUE ) +set( CMAKE_ASM_COMPILER_ID GNU ) +set( CMAKE_ASM_COMPILER_WORKS TRUE ) +set( CMAKE_ASM_COMPILER_FORCED TRUE ) +set( CMAKE_COMPILER_IS_GNUASM 1) +set( CMAKE_ASM_SOURCE_FILE_EXTENSIONS s S asm ) + +foreach( lang C CXX ASM ) + if( ANDROID_COMPILER_IS_CLANG ) + set( CMAKE_${lang}_COMPILER_VERSION ${ANDROID_CLANG_VERSION} ) + else() + set( CMAKE_${lang}_COMPILER_VERSION ${ANDROID_COMPILER_VERSION} ) + endif() +endforeach() + +# flags and definitions +remove_definitions( -DANDROID ) +add_definitions( -DANDROID ) + +if( ANDROID_SYSROOT MATCHES "[ ;\"]" ) + if( CMAKE_HOST_WIN32 ) + # try to convert path to 8.3 form + file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cvt83.cmd" "@echo %~s1" ) + execute_process( COMMAND "$ENV{ComSpec}" /c "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cvt83.cmd" "${ANDROID_SYSROOT}" + OUTPUT_VARIABLE __path OUTPUT_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE __result ERROR_QUIET ) + if( __result EQUAL 0 ) + file( TO_CMAKE_PATH "${__path}" ANDROID_SYSROOT ) + set( ANDROID_CXX_FLAGS "--sysroot=${ANDROID_SYSROOT}" ) + else() + set( ANDROID_CXX_FLAGS "--sysroot=\"${ANDROID_SYSROOT}\"" ) + endif() + else() + set( ANDROID_CXX_FLAGS "'--sysroot=${ANDROID_SYSROOT}'" ) + endif() + if( NOT _CMAKE_IN_TRY_COMPILE ) + # quotes can break try_compile and compiler identification + message(WARNING "Path to your Android NDK (or toolchain) has non-alphanumeric symbols.\nThe build might be broken.\n") + endif() +else() + set( ANDROID_CXX_FLAGS "--sysroot=${ANDROID_SYSROOT}" ) +endif() + +# NDK flags +if (ARM64_V8A ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" ) + set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer -fstrict-aliasing" ) + set( ANDROID_CXX_FLAGS_DEBUG "-fno-omit-frame-pointer -fno-strict-aliasing" ) + if( NOT ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} -funswitch-loops -finline-limit=300" ) + endif() +elseif( ARMEABI OR ARMEABI_V7A) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" ) + if( NOT ANDROID_FORCE_ARM_BUILD AND NOT ARMEABI_V6 ) + set( ANDROID_CXX_FLAGS_RELEASE "-mthumb -fomit-frame-pointer -fno-strict-aliasing" ) + set( ANDROID_CXX_FLAGS_DEBUG "-marm -fno-omit-frame-pointer -fno-strict-aliasing" ) + if( NOT ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -finline-limit=64" ) + endif() + else() + # always compile ARMEABI_V6 in arm mode; otherwise there is no difference from ARMEABI + set( ANDROID_CXX_FLAGS_RELEASE "-marm -fomit-frame-pointer -fstrict-aliasing" ) + set( ANDROID_CXX_FLAGS_DEBUG "-marm -fno-omit-frame-pointer -fno-strict-aliasing" ) + if( NOT ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funswitch-loops -finline-limit=300" ) + endif() + endif() +elseif( X86 OR X86_64 ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" ) + if( NOT ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funswitch-loops -finline-limit=300" ) + endif() + set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer -fstrict-aliasing" ) + set( ANDROID_CXX_FLAGS_DEBUG "-fno-omit-frame-pointer -fno-strict-aliasing" ) +elseif( MIPS OR MIPS64 ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fno-strict-aliasing -finline-functions -funwind-tables -fmessage-length=0" ) + set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer" ) + set( ANDROID_CXX_FLAGS_DEBUG "-fno-omit-frame-pointer" ) + if( NOT ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers" ) + set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} -funswitch-loops -finline-limit=300" ) + endif() +elseif() + set( ANDROID_CXX_FLAGS_RELEASE "" ) + set( ANDROID_CXX_FLAGS_DEBUG "" ) +endif() + +set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fsigned-char" ) # good/necessary when porting desktop libraries + +if( NOT X86 AND NOT ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "-Wno-psabi ${ANDROID_CXX_FLAGS}" ) +endif() + +if( NOT ANDROID_COMPILER_VERSION VERSION_LESS "4.6" ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -no-canonical-prefixes" ) # see https://android-review.googlesource.com/#/c/47564/ +endif() + +# ABI-specific flags +if( ARMEABI_V7A ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv7-a -mfloat-abi=softfp" ) + if( NEON ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=neon" ) + elseif( VFPV3 ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=vfpv3" ) + else() + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=vfpv3-d16" ) + endif() +elseif( ARMEABI_V6 ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv6 -mfloat-abi=softfp -mfpu=vfp" ) # vfp == vfpv2 +elseif( ARMEABI ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv5te -mtune=xscale -msoft-float" ) +endif() + +if( ANDROID_STL MATCHES "gnustl" AND (EXISTS "${__libstl}" OR EXISTS "${__libsupcxx}") ) + set( CMAKE_CXX_CREATE_SHARED_LIBRARY " -o " ) + set( CMAKE_CXX_CREATE_SHARED_MODULE " -o " ) + set( CMAKE_CXX_LINK_EXECUTABLE " -o " ) +else() + set( CMAKE_CXX_CREATE_SHARED_LIBRARY " -o " ) + set( CMAKE_CXX_CREATE_SHARED_MODULE " -o " ) + set( CMAKE_CXX_LINK_EXECUTABLE " -o " ) +endif() + +# STL +if( EXISTS "${__libstl}" OR EXISTS "${__libsupcxx}" ) + if( EXISTS "${__libstl}" ) + set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${__libstl}\"" ) + set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${__libstl}\"" ) + set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} \"${__libstl}\"" ) + endif() + if( EXISTS "${__libsupcxx}" ) + set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${__libsupcxx}\"" ) + set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${__libsupcxx}\"" ) + set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} \"${__libsupcxx}\"" ) + # C objects: + set( CMAKE_C_CREATE_SHARED_LIBRARY " -o " ) + set( CMAKE_C_CREATE_SHARED_MODULE " -o " ) + set( CMAKE_C_LINK_EXECUTABLE " -o " ) + set( CMAKE_C_CREATE_SHARED_LIBRARY "${CMAKE_C_CREATE_SHARED_LIBRARY} \"${__libsupcxx}\"" ) + set( CMAKE_C_CREATE_SHARED_MODULE "${CMAKE_C_CREATE_SHARED_MODULE} \"${__libsupcxx}\"" ) + set( CMAKE_C_LINK_EXECUTABLE "${CMAKE_C_LINK_EXECUTABLE} \"${__libsupcxx}\"" ) + endif() + if( ANDROID_STL MATCHES "gnustl" ) + if( NOT EXISTS "${ANDROID_LIBM_PATH}" ) + set( ANDROID_LIBM_PATH -lm ) + endif() + set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} ${ANDROID_LIBM_PATH}" ) + set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} ${ANDROID_LIBM_PATH}" ) + set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} ${ANDROID_LIBM_PATH}" ) + endif() +endif() + +# variables controlling optional build flags +if( ANDROID_NDK_RELEASE_NUM LESS 7000 ) # before r7 + # libGLESv2.so in NDK's prior to r7 refers to missing external symbols. + # So this flag option is required for all projects using OpenGL from native. + __INIT_VARIABLE( ANDROID_SO_UNDEFINED VALUES ON ) +else() + __INIT_VARIABLE( ANDROID_SO_UNDEFINED VALUES OFF ) +endif() +__INIT_VARIABLE( ANDROID_NO_UNDEFINED VALUES ON ) +__INIT_VARIABLE( ANDROID_FUNCTION_LEVEL_LINKING VALUES ON ) +__INIT_VARIABLE( ANDROID_GOLD_LINKER VALUES ON ) +__INIT_VARIABLE( ANDROID_NOEXECSTACK VALUES ON ) +__INIT_VARIABLE( ANDROID_RELRO VALUES ON ) + +set( ANDROID_NO_UNDEFINED ${ANDROID_NO_UNDEFINED} CACHE BOOL "Show all undefined symbols as linker errors" ) +set( ANDROID_SO_UNDEFINED ${ANDROID_SO_UNDEFINED} CACHE BOOL "Allows or disallows undefined symbols in shared libraries" ) +set( ANDROID_FUNCTION_LEVEL_LINKING ${ANDROID_FUNCTION_LEVEL_LINKING} CACHE BOOL "Put each function in separate section and enable garbage collection of unused input sections at link time" ) +set( ANDROID_GOLD_LINKER ${ANDROID_GOLD_LINKER} CACHE BOOL "Enables gold linker" ) +set( ANDROID_NOEXECSTACK ${ANDROID_NOEXECSTACK} CACHE BOOL "Allows or disallows undefined symbols in shared libraries" ) +set( ANDROID_RELRO ${ANDROID_RELRO} CACHE BOOL "Enables RELRO - a memory corruption mitigation technique" ) +mark_as_advanced( ANDROID_NO_UNDEFINED ANDROID_SO_UNDEFINED ANDROID_FUNCTION_LEVEL_LINKING ANDROID_GOLD_LINKER ANDROID_NOEXECSTACK ANDROID_RELRO ) + +# linker flags +set( ANDROID_LINKER_FLAGS "" ) + +if( ARMEABI_V7A ) + # this is *required* to use the following linker flags that routes around + # a CPU bug in some Cortex-A8 implementations: + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--fix-cortex-a8" ) +endif() + +if( ANDROID_NO_UNDEFINED ) + if( MIPS ) + # there is some sysroot-related problem in mips linker... + if( NOT ANDROID_SYSROOT MATCHES "[ ;\"]" ) + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--no-undefined -Wl,-rpath-link,${ANDROID_SYSROOT}/usr/lib" ) + endif() + else() + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--no-undefined" ) + endif() +endif() + +if( ANDROID_SO_UNDEFINED ) + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-allow-shlib-undefined" ) +endif() + +if( ANDROID_FUNCTION_LEVEL_LINKING ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fdata-sections -ffunction-sections" ) + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--gc-sections" ) +endif() + +if( ANDROID_COMPILER_VERSION VERSION_EQUAL "4.6" ) + if( ANDROID_GOLD_LINKER AND (CMAKE_HOST_UNIX OR ANDROID_NDK_RELEASE_NUM GREATER 8002) AND (ARMEABI OR ARMEABI_V7A OR X86) ) + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -fuse-ld=gold" ) + elseif( ANDROID_NDK_RELEASE_NUM GREATER 8002 ) # after r8b + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -fuse-ld=bfd" ) + elseif( ANDROID_NDK_RELEASE STREQUAL "r8b" AND ARMEABI AND NOT _CMAKE_IN_TRY_COMPILE ) + message( WARNING "The default bfd linker from arm GCC 4.6 toolchain can fail with 'unresolvable R_ARM_THM_CALL relocation' error message. See https://code.google.com/p/android/issues/detail?id=35342 + On Linux and OS X host platform you can workaround this problem using gold linker (default). + Rerun cmake with -DANDROID_GOLD_LINKER=ON option in case of problems. +" ) + endif() +endif() # version 4.6 + +if( ANDROID_NOEXECSTACK ) + if( ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -Xclang -mnoexecstack" ) + else() + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -Wa,--noexecstack" ) + endif() + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-z,noexecstack" ) +endif() + +if( ANDROID_RELRO ) + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-z,relro -Wl,-z,now" ) +endif() + +if( ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "-target ${ANDROID_LLVM_TRIPLE} -Qunused-arguments ${ANDROID_CXX_FLAGS}" ) + if( BUILD_WITH_ANDROID_NDK ) + set( ANDROID_CXX_FLAGS "-gcc-toolchain ${ANDROID_TOOLCHAIN_ROOT} ${ANDROID_CXX_FLAGS}" ) + endif() +endif() + +# cache flags +set( CMAKE_CXX_FLAGS "" CACHE STRING "c++ flags" ) +set( CMAKE_C_FLAGS "" CACHE STRING "c flags" ) +set( CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG" CACHE STRING "c++ Release flags" ) +set( CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG" CACHE STRING "c Release flags" ) +set( CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DDEBUG -D_DEBUG" CACHE STRING "c++ Debug flags" ) +set( CMAKE_C_FLAGS_DEBUG "-O0 -g -DDEBUG -D_DEBUG" CACHE STRING "c Debug flags" ) +set( CMAKE_SHARED_LINKER_FLAGS "" CACHE STRING "shared linker flags" ) +set( CMAKE_MODULE_LINKER_FLAGS "" CACHE STRING "module linker flags" ) +set( CMAKE_EXE_LINKER_FLAGS "-Wl,-z,nocopyreloc" CACHE STRING "executable linker flags" ) + +# put flags to cache (for debug purpose only) +set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS}" CACHE INTERNAL "Android specific c/c++ flags" ) +set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE}" CACHE INTERNAL "Android specific c/c++ Release flags" ) +set( ANDROID_CXX_FLAGS_DEBUG "${ANDROID_CXX_FLAGS_DEBUG}" CACHE INTERNAL "Android specific c/c++ Debug flags" ) +set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS}" CACHE INTERNAL "Android specific c/c++ linker flags" ) + +# finish flags +set( CMAKE_CXX_FLAGS "${ANDROID_CXX_FLAGS} ${CMAKE_CXX_FLAGS}" ) +set( CMAKE_C_FLAGS "${ANDROID_CXX_FLAGS} ${CMAKE_C_FLAGS}" ) +set( CMAKE_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} ${CMAKE_CXX_FLAGS_RELEASE}" ) +set( CMAKE_C_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} ${CMAKE_C_FLAGS_RELEASE}" ) +set( CMAKE_CXX_FLAGS_DEBUG "${ANDROID_CXX_FLAGS_DEBUG} ${CMAKE_CXX_FLAGS_DEBUG}" ) +set( CMAKE_C_FLAGS_DEBUG "${ANDROID_CXX_FLAGS_DEBUG} ${CMAKE_C_FLAGS_DEBUG}" ) +set( CMAKE_SHARED_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}" ) +set( CMAKE_MODULE_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_MODULE_LINKER_FLAGS}" ) +set( CMAKE_EXE_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}" ) + +if( MIPS AND BUILD_WITH_ANDROID_NDK AND ANDROID_NDK_RELEASE STREQUAL "r8" ) + set( CMAKE_SHARED_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.xsc ${CMAKE_SHARED_LINKER_FLAGS}" ) + set( CMAKE_MODULE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.xsc ${CMAKE_MODULE_LINKER_FLAGS}" ) + set( CMAKE_EXE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.x ${CMAKE_EXE_LINKER_FLAGS}" ) +endif() + +# pie/pic +if( NOT (ANDROID_NATIVE_API_LEVEL LESS 16) AND (NOT DEFINED ANDROID_APP_PIE OR ANDROID_APP_PIE) AND (CMAKE_VERSION VERSION_GREATER 2.8.8) ) + set( CMAKE_POSITION_INDEPENDENT_CODE TRUE ) + set( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fPIE -pie") +else() + set( CMAKE_POSITION_INDEPENDENT_CODE FALSE ) + set( CMAKE_CXX_FLAGS "-fpic ${CMAKE_CXX_FLAGS}" ) + set( CMAKE_C_FLAGS "-fpic ${CMAKE_C_FLAGS}" ) +endif() + +# configure rtti +if( DEFINED ANDROID_RTTI AND ANDROID_STL_FORCE_FEATURES ) + if( ANDROID_RTTI ) + set( CMAKE_CXX_FLAGS "-frtti ${CMAKE_CXX_FLAGS}" ) + else() + set( CMAKE_CXX_FLAGS "-fno-rtti ${CMAKE_CXX_FLAGS}" ) + endif() +endif() + +# configure exceptios +if( DEFINED ANDROID_EXCEPTIONS AND ANDROID_STL_FORCE_FEATURES ) + if( ANDROID_EXCEPTIONS ) + set( CMAKE_CXX_FLAGS "-fexceptions ${CMAKE_CXX_FLAGS}" ) + set( CMAKE_C_FLAGS "-fexceptions ${CMAKE_C_FLAGS}" ) + else() + set( CMAKE_CXX_FLAGS "-fno-exceptions ${CMAKE_CXX_FLAGS}" ) + set( CMAKE_C_FLAGS "-fno-exceptions ${CMAKE_C_FLAGS}" ) + endif() +endif() + +# global includes and link directories +include_directories( SYSTEM "${ANDROID_SYSROOT}/usr/include" ${ANDROID_STL_INCLUDE_DIRS} ) +get_filename_component(__android_install_path "${CMAKE_INSTALL_PREFIX}/libs/${ANDROID_NDK_ABI_NAME}" ABSOLUTE) # avoid CMP0015 policy warning +link_directories( "${__android_install_path}" ) + +# detect if need link crtbegin_so.o explicitly +if( NOT DEFINED ANDROID_EXPLICIT_CRT_LINK ) + set( __cmd "${CMAKE_CXX_CREATE_SHARED_LIBRARY}" ) + string( REPLACE "" "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}" __cmd "${__cmd}" ) + string( REPLACE "" "${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}" __cmd "${__cmd}" ) + string( REPLACE "" "${CMAKE_CXX_FLAGS}" __cmd "${__cmd}" ) + string( REPLACE "" "" __cmd "${__cmd}" ) + string( REPLACE "" "${CMAKE_SHARED_LINKER_FLAGS}" __cmd "${__cmd}" ) + string( REPLACE "" "-shared" __cmd "${__cmd}" ) + string( REPLACE "" "" __cmd "${__cmd}" ) + string( REPLACE "" "" __cmd "${__cmd}" ) + string( REPLACE "" "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/toolchain_crtlink_test.so" __cmd "${__cmd}" ) + string( REPLACE "" "\"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" __cmd "${__cmd}" ) + string( REPLACE "" "" __cmd "${__cmd}" ) + separate_arguments( __cmd ) + foreach( __var ANDROID_NDK ANDROID_NDK_TOOLCHAINS_PATH ANDROID_STANDALONE_TOOLCHAIN ) + if( ${__var} ) + set( __tmp "${${__var}}" ) + separate_arguments( __tmp ) + string( REPLACE "${__tmp}" "${${__var}}" __cmd "${__cmd}") + endif() + endforeach() + string( REPLACE "'" "" __cmd "${__cmd}" ) + string( REPLACE "\"" "" __cmd "${__cmd}" ) + execute_process( COMMAND ${__cmd} RESULT_VARIABLE __cmd_result OUTPUT_QUIET ERROR_QUIET ) + if( __cmd_result EQUAL 0 ) + set( ANDROID_EXPLICIT_CRT_LINK ON ) + else() + set( ANDROID_EXPLICIT_CRT_LINK OFF ) + endif() +endif() + +if( ANDROID_EXPLICIT_CRT_LINK ) + set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" ) + set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" ) +endif() + +# setup output directories +set( CMAKE_INSTALL_PREFIX "${ANDROID_TOOLCHAIN_ROOT}/user" CACHE STRING "path for installing" ) + +if( DEFINED LIBRARY_OUTPUT_PATH_ROOT + OR EXISTS "${CMAKE_SOURCE_DIR}/AndroidManifest.xml" + OR (EXISTS "${CMAKE_SOURCE_DIR}/../AndroidManifest.xml" AND EXISTS "${CMAKE_SOURCE_DIR}/../jni/") ) + set( LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_SOURCE_DIR} CACHE PATH "Root for binaries output, set this to change where Android libs are installed to" ) + if( NOT _CMAKE_IN_TRY_COMPILE ) + if( EXISTS "${CMAKE_SOURCE_DIR}/jni/CMakeLists.txt" ) + set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin/${ANDROID_NDK_ABI_NAME}" CACHE PATH "Output directory for applications" ) + else() + set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin" CACHE PATH "Output directory for applications" ) + endif() + set( LIBRARY_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/libs/${ANDROID_NDK_ABI_NAME}" CACHE PATH "Output directory for Android libs" ) + endif() +endif() + +# copy shaed stl library to build directory +if( NOT _CMAKE_IN_TRY_COMPILE AND __libstl MATCHES "[.]so$" AND DEFINED LIBRARY_OUTPUT_PATH ) + get_filename_component( __libstlname "${__libstl}" NAME ) + execute_process( COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${__libstl}" "${LIBRARY_OUTPUT_PATH}/${__libstlname}" RESULT_VARIABLE __fileCopyProcess ) + if( NOT __fileCopyProcess EQUAL 0 OR NOT EXISTS "${LIBRARY_OUTPUT_PATH}/${__libstlname}") + message( SEND_ERROR "Failed copying of ${__libstl} to the ${LIBRARY_OUTPUT_PATH}/${__libstlname}" ) + endif() + unset( __fileCopyProcess ) + unset( __libstlname ) +endif() + + +# set these global flags for cmake client scripts to change behavior +set( ANDROID True ) +set( BUILD_ANDROID True ) + +# where is the target environment +set( CMAKE_FIND_ROOT_PATH "${ANDROID_TOOLCHAIN_ROOT}/bin" "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}" "${ANDROID_SYSROOT}" "${CMAKE_INSTALL_PREFIX}" "${CMAKE_INSTALL_PREFIX}/share" ) + +# only search for libraries and includes in the ndk toolchain +set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) +set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) +set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) + + +# macro to find packages on the host OS +macro( find_host_package ) + set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER ) + set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER ) + set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER ) + if( CMAKE_HOST_WIN32 ) + SET( WIN32 1 ) + SET( UNIX ) + elseif( CMAKE_HOST_APPLE ) + SET( APPLE 1 ) + SET( UNIX ) + endif() + find_package( ${ARGN} ) + SET( WIN32 ) + SET( APPLE ) + SET( UNIX 1 ) + set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) + set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) + set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) +endmacro() + + +# macro to find programs on the host OS +macro( find_host_program ) + set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER ) + set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER ) + set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER ) + if( CMAKE_HOST_WIN32 ) + SET( WIN32 1 ) + SET( UNIX ) + elseif( CMAKE_HOST_APPLE ) + SET( APPLE 1 ) + SET( UNIX ) + endif() + find_program( ${ARGN} ) + SET( WIN32 ) + SET( APPLE ) + SET( UNIX 1 ) + set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) + set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) + set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) +endmacro() + + +# export toolchain settings for the try_compile() command +if( NOT _CMAKE_IN_TRY_COMPILE ) + set( __toolchain_config "") + foreach( __var NDK_CCACHE LIBRARY_OUTPUT_PATH_ROOT ANDROID_FORBID_SYGWIN + ANDROID_NDK_HOST_X64 + ANDROID_NDK + ANDROID_NDK_LAYOUT + ANDROID_STANDALONE_TOOLCHAIN + ANDROID_TOOLCHAIN_NAME + ANDROID_ABI + ANDROID_NATIVE_API_LEVEL + ANDROID_STL + ANDROID_STL_FORCE_FEATURES + ANDROID_FORCE_ARM_BUILD + ANDROID_NO_UNDEFINED + ANDROID_SO_UNDEFINED + ANDROID_FUNCTION_LEVEL_LINKING + ANDROID_GOLD_LINKER + ANDROID_NOEXECSTACK + ANDROID_RELRO + ANDROID_LIBM_PATH + ANDROID_EXPLICIT_CRT_LINK + ANDROID_APP_PIE + ) + if( DEFINED ${__var} ) + if( ${__var} MATCHES " ") + set( __toolchain_config "${__toolchain_config}set( ${__var} \"${${__var}}\" CACHE INTERNAL \"\" )\n" ) + else() + set( __toolchain_config "${__toolchain_config}set( ${__var} ${${__var}} CACHE INTERNAL \"\" )\n" ) + endif() + endif() + endforeach() + file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/android.toolchain.config.cmake" "${__toolchain_config}" ) + unset( __toolchain_config ) +endif() + + +# force cmake to produce / instead of \ in build commands for Ninja generator +if( CMAKE_GENERATOR MATCHES "Ninja" AND CMAKE_HOST_WIN32 ) + # it is a bad hack after all + # CMake generates Ninja makefiles with UNIX paths only if it thinks that we are going to build with MinGW + set( CMAKE_COMPILER_IS_MINGW TRUE ) # tell CMake that we are MinGW + set( CMAKE_CROSSCOMPILING TRUE ) # stop recursion + enable_language( C ) + enable_language( CXX ) + # unset( CMAKE_COMPILER_IS_MINGW ) # can't unset because CMake does not convert back-slashes in response files without it + unset( MINGW ) +endif() + + +# Variables controlling behavior or set by cmake toolchain: +# ANDROID_ABI : "armeabi-v7a" (default), "armeabi", "armeabi-v7a with NEON", "armeabi-v7a with VFPV3", "armeabi-v6 with VFP", "x86", "mips", "arm64-v8a", "x86_64", "mips64" +# ANDROID_NATIVE_API_LEVEL : 3,4,5,8,9,14,15,16,17,18,19,21 (depends on NDK version) +# ANDROID_STL : gnustl_static/gnustl_shared/stlport_static/stlport_shared/gabi++_static/gabi++_shared/system_re/system/none +# ANDROID_FORBID_SYGWIN : ON/OFF +# ANDROID_NO_UNDEFINED : ON/OFF +# ANDROID_SO_UNDEFINED : OFF/ON (default depends on NDK version) +# ANDROID_FUNCTION_LEVEL_LINKING : ON/OFF +# ANDROID_GOLD_LINKER : ON/OFF +# ANDROID_NOEXECSTACK : ON/OFF +# ANDROID_RELRO : ON/OFF +# ANDROID_FORCE_ARM_BUILD : ON/OFF +# ANDROID_STL_FORCE_FEATURES : ON/OFF +# ANDROID_LIBM_PATH : path to libm.so (set to something like $(TOP)/out/target/product//obj/lib/libm.so) to workaround unresolved `sincos` +# Can be set only at the first run: +# ANDROID_NDK : path to your NDK install +# NDK_CCACHE : path to your ccache executable +# ANDROID_TOOLCHAIN_NAME : the NDK name of compiler toolchain +# ANDROID_NDK_HOST_X64 : try to use x86_64 toolchain (default for x64 host systems) +# ANDROID_NDK_LAYOUT : the inner NDK structure (RELEASE, LINARO, ANDROID) +# LIBRARY_OUTPUT_PATH_ROOT : +# ANDROID_STANDALONE_TOOLCHAIN +# +# Primary read-only variables: +# ANDROID : always TRUE +# ARMEABI : TRUE for arm v6 and older devices +# ARMEABI_V6 : TRUE for arm v6 +# ARMEABI_V7A : TRUE for arm v7a +# ARM64_V8A : TRUE for arm64-v8a +# NEON : TRUE if NEON unit is enabled +# VFPV3 : TRUE if VFP version 3 is enabled +# X86 : TRUE if configured for x86 +# X86_64 : TRUE if configured for x86_64 +# MIPS : TRUE if configured for mips +# MIPS64 : TRUE if configured for mips64 +# BUILD_WITH_ANDROID_NDK : TRUE if NDK is used +# BUILD_WITH_STANDALONE_TOOLCHAIN : TRUE if standalone toolchain is used +# ANDROID_NDK_HOST_SYSTEM_NAME : "windows", "linux-x86" or "darwin-x86" depending on host platform +# ANDROID_NDK_ABI_NAME : "armeabi", "armeabi-v7a", "x86", "mips", "arm64-v8a", "x86_64", "mips64" depending on ANDROID_ABI +# ANDROID_NDK_RELEASE : from r5 to r10d; set only for NDK +# ANDROID_NDK_RELEASE_NUM : numeric ANDROID_NDK_RELEASE version (1000*major+minor) +# ANDROID_ARCH_NAME : "arm", "x86", "mips", "arm64", "x86_64", "mips64" depending on ANDROID_ABI +# ANDROID_SYSROOT : path to the compiler sysroot +# TOOL_OS_SUFFIX : "" or ".exe" depending on host platform +# ANDROID_COMPILER_IS_CLANG : TRUE if clang compiler is used +# +# Secondary (less stable) read-only variables: +# ANDROID_COMPILER_VERSION : GCC version used (not Clang version) +# ANDROID_CLANG_VERSION : version of clang compiler if clang is used +# ANDROID_CXX_FLAGS : C/C++ compiler flags required by Android platform +# ANDROID_SUPPORTED_ABIS : list of currently allowed values for ANDROID_ABI +# ANDROID_TOOLCHAIN_MACHINE_NAME : "arm-linux-androideabi", "arm-eabi" or "i686-android-linux" +# ANDROID_TOOLCHAIN_ROOT : path to the top level of toolchain (standalone or placed inside NDK) +# ANDROID_CLANG_TOOLCHAIN_ROOT : path to clang tools +# ANDROID_SUPPORTED_NATIVE_API_LEVELS : list of native API levels found inside NDK +# ANDROID_STL_INCLUDE_DIRS : stl include paths +# ANDROID_RTTI : if rtti is enabled by the runtime +# ANDROID_EXCEPTIONS : if exceptions are enabled by the runtime +# ANDROID_GCC_TOOLCHAIN_NAME : read-only, differs from ANDROID_TOOLCHAIN_NAME only if clang is used +# +# Defaults: +# ANDROID_DEFAULT_NDK_API_LEVEL +# ANDROID_DEFAULT_NDK_API_LEVEL_${ARCH} +# ANDROID_NDK_SEARCH_PATHS +# ANDROID_SUPPORTED_ABIS_${ARCH} +# ANDROID_SUPPORTED_NDK_VERSIONS diff --git a/cmake/qtdeploy.json.in b/cmake/qtdeploy.json.in new file mode 100644 index 000000000..af05203bd --- /dev/null +++ b/cmake/qtdeploy.json.in @@ -0,0 +1,17 @@ +{ + "description": "This file is to be read by androiddeployqt", + "qt": "@QT_ANDROID_QT_ROOT@", + "sdk": "@QT_ANDROID_SDK_ROOT@", + "ndk": "@QT_ANDROID_NDK_ROOT@", + "sdkBuildToolsRevision": "@QT_ANDROID_SDK_BUILDTOOLS_REVISION@", + "toolchain-prefix": "@ANDROID_TOOLCHAIN_MACHINE_NAME@", + "tool-prefix": "@ANDROID_TOOLCHAIN_MACHINE_NAME@", + "toolchain-version": "@ANDROID_COMPILER_VERSION@", + "ndk-host": "@ANDROID_NDK_HOST_SYSTEM_NAME@", + "target-architecture": "@ANDROID_ABI@", + "application-binary": "@QT_ANDROID_APP_PATH@", + "android-package": "@QT_ANDROID_APP_PACKAGE_NAME@", + "android-app-name": "@QT_ANDROID_APP_NAME@", + @QT_ANDROID_APP_EXTRA_LIBS@ + "android-package-source-directory": "@QT_ANDROID_APP_PACKAGE_SOURCE_ROOT@" +} diff --git a/cmake/windows_metafile.rc.in b/cmake/windows_metafile.rc.in new file mode 100644 index 000000000..c0710e5fe --- /dev/null +++ b/cmake/windows_metafile.rc.in @@ -0,0 +1,29 @@ +#include "winver.h" + +IDI_ICON1 ICON DISCARDABLE "@ICON_FILE@" + +VS_VERSION_INFO VERSIONINFO + FILEVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,@PROJECT_VERSION_TWEAK@ + PRODUCTVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,@PROJECT_VERSION_TWEAK@ + FILEFLAGS 0x0L + FILEFLAGSMASK 0x3fL + FILEOS 0x00040004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "CompanyName", "@COMPANY@" + VALUE "FileDescription", "@PROJECT_NAME@" + VALUE "FileVersion", "@PROJECT_VERSION@" + VALUE "LegalCopyright", "@COPYRIGHT@" + VALUE "InternalName", "@PROJECT_NAME@" + VALUE "OriginalFilename", "@PROJECT_NAME@.exe" + VALUE "ProductName", "@PROJECT_NAME@" + VALUE "ProductVersion", "@PROJECT_VERSION@" + END + END +END + diff --git a/deploy/create_linux_appimage.sh b/deploy/create_linux_appimage.sh index b3809619f..24bb69456 100755 --- a/deploy/create_linux_appimage.sh +++ b/deploy/create_linux_appimage.sh @@ -1,6 +1,6 @@ #!/bin/bash -x -set +e +#set +e if [[ $# -eq 0 ]]; then echo 'create_linux_appimage.sh QGC_SRC_DIR QGC_RELEASE_DIR' @@ -56,27 +56,27 @@ dpkg -x libts-0.0-0_1.0-11_amd64.deb libts cp -L libts/usr/lib/x86_64-linux-gnu/libts-0.0.so.0 ${APPDIR}/usr/lib/x86_64-linux-gnu/ # copy QGroundControl release into appimage -cp -r ${QGC_RELEASE_DIR}/* ${APPDIR}/ +rsync -av --exclude=*.cpp --exclude=*.h --exclude=*.o --exclude="CMake*" --exclude="*.cmake" ${QGC_RELEASE_DIR}/* ${APPDIR}/ rm -rf ${APPDIR}/package -mv ${APPDIR}/qgroundcontrol-start.sh ${APPDIR}/AppRun +cp ${QGC_SRC}/deploy/qgroundcontrol-start.sh ${APPDIR}/AppRun # copy icon cp ${QGC_SRC}/resources/icons/qgroundcontrol.png ${APPDIR}/ -cat > ./qgroundcontrol.desktop <<\EOF +cat > ./QGroundControl.desktop <<\EOF [Desktop Entry] Type=Application Name=QGroundControl GenericName=Ground Control Station Comment=UAS ground control station -Icon=qgroundcontrol +Icon=QGroundControl Exec=AppRun Terminal=false Categories=Utility; Keywords=computer; EOF -VERSION=$(strings ${APPDIR}/qgroundcontrol | grep '^v[0-9*]\.[0-9*].[0-9*]' | head -n 1) +VERSION=$(strings ${APPDIR}/QGroundControl | grep '^v[0-9*]\.[0-9*].[0-9*]' | head -n 1) echo QGC Version: ${VERSION} # Go out of AppImage diff --git a/localization/qgc.ts b/localization/qgc.ts index 0d70ad527..cc777e8de 100644 --- a/localization/qgc.ts +++ b/localization/qgc.ts @@ -11139,19 +11139,6 @@ Errors: - - QGCWebView - - - Form - - - - - about:blank - - - QGCXPlaneLink diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index 0f8c82c81..8fb300a93 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -382,7 +382,7 @@ FORMS += \ !MobileBuild { FORMS += \ - src/ui/Linechart.ui \ + src/ui/linechart/Linechart.ui \ src/ui/MultiVehicleDockWidget.ui \ src/ui/QGCHilConfiguration.ui \ src/ui/QGCHilFlightGearConfiguration.ui \ diff --git a/src/AutoPilotPlugins/APM/APMPowerComponentController.cc b/src/AutoPilotPlugins/APM/APMPowerComponentController.cc deleted file mode 100644 index c26cd2772..000000000 --- a/src/AutoPilotPlugins/APM/APMPowerComponentController.cc +++ /dev/null @@ -1,161 +0,0 @@ -/**************************************************************************** - * - * (c) 2009-2016 QGROUNDCONTROL PROJECT - * - * QGroundControl is licensed according to the terms in the file - * COPYING.md in the root of the source code directory. - * - ****************************************************************************/ - - -/// @file -/// @author Don Gagne - -#include "PowerComponentController.h" -#include "QGCMAVLink.h" -#include "UAS.h" - -#include -#include - -PowerComponentController::PowerComponentController(void) -{ - -} - -PowerComponentController::~PowerComponentController() -{ - _stopCalibration(); -} - -void PowerComponentController::calibrateEsc(void) -{ - _warningMessages.clear(); - connect(_uas, &UASInterface::textMessageReceived, this, &PowerComponentController::_handleUASTextMessage); - _uas->startCalibration(UASInterface::StartCalibrationEsc); -} - -void PowerComponentController::busConfigureActuators(void) -{ - _warningMessages.clear(); - connect(_uas, &UASInterface::textMessageReceived, this, &PowerComponentController::_handleUASTextMessage); - _uas->startBusConfig(UASInterface::StartBusConfigActuators); -} - -void PowerComponentController::stopBusConfigureActuators(void) -{ - disconnect(_uas, &UASInterface::textMessageReceived, this, &PowerComponentController::_handleUASTextMessage); - _uas->startBusConfig(UASInterface::EndBusConfigActuators); -} - -void PowerComponentController::_stopCalibration(void) -{ - disconnect(_uas, &UASInterface::textMessageReceived, this, &PowerComponentController::_handleUASTextMessage); -} - -void PowerComponentController::_stopBusConfig(void) -{ - _stopCalibration(); -} - -void PowerComponentController::_handleUASTextMessage(int uasId, int compId, int severity, QString text) -{ - Q_UNUSED(compId); - Q_UNUSED(severity); - - UASInterface* uas = _autopilot->vehicle()->uas(); - Q_ASSERT(uas); - if (uasId != uas->getUASID()) { - return; - } - - // All calibration messages start with [cal] - QString calPrefix("[cal] "); - if (!text.startsWith(calPrefix)) { - return; - } - text = text.right(text.length() - calPrefix.length()); - - // Make sure we can understand this firmware rev - QString calStartPrefix("calibration started: "); - if (text.startsWith(calStartPrefix)) { - text = text.right(text.length() - calStartPrefix.length()); - - // Split version number and cal type - QStringList parts = text.split(" "); - if (parts.count() != 2) { - emit incorrectFirmwareRevReporting(); - return; - } - -#if 0 - // FIXME: Cal version check is not working. Needs to be able to cancel, calibration - - int firmwareRev = parts[0].toInt(); - if (firmwareRev < _neededFirmwareRev) { - emit oldFirmware(); - return; - } - if (firmwareRev > _neededFirmwareRev) { - emit newerFirmware(); - return; - } -#endif - } - - if (text == "Connect battery now") { - emit connectBattery(); - return; - } - - if (text == "Battery connected") { - emit batteryConnected(); - return; - } - - - QString failedPrefix("calibration failed: "); - if (text.startsWith(failedPrefix)) { - QString failureText = text.right(text.length() - failedPrefix.length()); - if (failureText.startsWith("Disconnect battery")) { - emit disconnectBattery(); - return; - } - - _stopCalibration(); - emit calibrationFailed(text.right(text.length() - failedPrefix.length())); - return; - } - - QString calCompletePrefix("calibration done:"); - if (text.startsWith(calCompletePrefix)) { - _stopCalibration(); - emit calibrationSuccess(_warningMessages); - return; - } - - QString warningPrefix("config warning: "); - if (text.startsWith(warningPrefix)) { - _warningMessages << text.right(text.length() - warningPrefix.length()); - } - - QString busFailedPrefix("bus conf fail:"); - if (text.startsWith(busFailedPrefix)) { - - _stopBusConfig(); - emit calibrationFailed(text.right(text.length() - failedPrefix.length())); - return; - } - - QString busCompletePrefix("bus conf done:"); - if (text.startsWith(calCompletePrefix)) { - _stopBusConfig(); - emit calibrationSuccess(_warningMessages); - return; - } - - QString busWarningPrefix("bus conf warn: "); - if (text.startsWith(busWarningPrefix)) { - _warningMessages << text.right(text.length() - warningPrefix.length()); - } -} diff --git a/src/AutoPilotPlugins/APM/APMPowerComponentController.h b/src/AutoPilotPlugins/APM/APMPowerComponentController.h deleted file mode 100644 index 41d95e6cd..000000000 --- a/src/AutoPilotPlugins/APM/APMPowerComponentController.h +++ /dev/null @@ -1,57 +0,0 @@ -/**************************************************************************** - * - * (c) 2009-2016 QGROUNDCONTROL PROJECT - * - * QGroundControl is licensed according to the terms in the file - * COPYING.md in the root of the source code directory. - * - ****************************************************************************/ - - -/// @file -/// @author Don Gagne - -#ifndef PowerComponentController_H -#define PowerComponentController_H - -#include -#include - -#include "UASInterface.h" -#include "FactPanelController.h" - -/// Power Component MVC Controller for PowerComponent.qml. -class PowerComponentController : public FactPanelController -{ - Q_OBJECT - -public: - PowerComponentController(void); - ~PowerComponentController(); - - Q_INVOKABLE void calibrateEsc(void); - Q_INVOKABLE void busConfigureActuators(void); - Q_INVOKABLE void stopBusConfigureActuators(void); - -signals: - void oldFirmware(void); - void newerFirmware(void); - void incorrectFirmwareRevReporting(void); - void connectBattery(void); - void disconnectBattery(void); - void batteryConnected(void); - void calibrationFailed(const QString& errorMessage); - void calibrationSuccess(const QStringList& warningMessages); - -private slots: - void _handleUASTextMessage(int uasId, int compId, int severity, QString text); - -private: - void _stopCalibration(void); - void _stopBusConfig(void); - - QStringList _warningMessages; - static const int _neededFirmwareRev = 1; -}; - -#endif diff --git a/src/Camera/QGCCameraControl.cc b/src/Camera/QGCCameraControl.cc index 6c5374c71..b6baf9ded 100644 --- a/src/Camera/QGCCameraControl.cc +++ b/src/Camera/QGCCameraControl.cc @@ -842,7 +842,7 @@ QGCCameraControl::_handleLocalization(QByteArray& bytes) } //-- Find out where we are QLocale locale = QLocale::system(); -#if defined (__macos__) +#if defined (Q_OS_MAC) locale = QLocale(locale.name()); #endif QString localeName = locale.name().toLower().replace("-", "_"); diff --git a/src/KMLFileHelper.cc b/src/KMLFileHelper.cc index 7415c4d3a..f35b72516 100644 --- a/src/KMLFileHelper.cc +++ b/src/KMLFileHelper.cc @@ -10,6 +10,7 @@ #include "KMLFileHelper.h" #include +#include QDomDocument KMLFileHelper::loadFile(const QString& kmlFile, QString& errorString) { diff --git a/src/QGCMessageBox.h b/src/QGCMessageBox.h index 7cc2d8111..2117937e0 100644 --- a/src/QGCMessageBox.h +++ b/src/QGCMessageBox.h @@ -102,7 +102,7 @@ private: } else #endif { -#ifdef __macos__ +#ifdef Q_OS_MAC QString emptyTitle; QMessageBox box(icon, emptyTitle, title, buttons, parent); box.setDefaultButton(defaultButton); diff --git a/src/QGCQuickWidget.cc b/src/QGCQuickWidget.cc index ab6609360..f61013988 100644 --- a/src/QGCQuickWidget.cc +++ b/src/QGCQuickWidget.cc @@ -25,7 +25,7 @@ QGCQuickWidget::QGCQuickWidget(QWidget* parent) : QQuickWidget(parent) { -#ifndef __macos__ +#ifndef Q_OS_MAC // The following causes the Map control to hang after doing a pinch gesture on mac trackpads. // By not turning this on for macos we lose pinch gesture, but two finger scroll still zooms the map. // So it's a decent workaround. Qt bug reported: 53634 diff --git a/src/QmlControls/ScreenToolsController.h b/src/QmlControls/ScreenToolsController.h index b9fc5e0c8..3a7d3c130 100644 --- a/src/QmlControls/ScreenToolsController.h +++ b/src/QmlControls/ScreenToolsController.h @@ -49,19 +49,19 @@ public: bool isMobile () { return qgcApp()->fakeMobile(); } #endif -#if defined (__android__) +#if defined (Q_OS_ANDROID) bool isAndroid () { return true; } bool isiOS () { return false; } bool isLinux () { return false; } bool isMacOS () { return false; } bool isWindows () { return false; } -#elif defined(__ios__) +#elif defined(Q_OS_IOS) bool isAndroid () { return false; } bool isiOS () { return true; } bool isLinux () { return false; } bool isMacOS () { return false; } bool isWindows () { return false; } -#elif defined(__macos__) +#elif defined(Q_OS_MAC) bool isAndroid () { return false; } bool isiOS () { return false; } bool isLinux () { return false; } diff --git a/src/VideoStreaming/VideoStreaming.cc b/src/VideoStreaming/VideoStreaming.cc index 87dd76d73..25f2f7f30 100644 --- a/src/VideoStreaming/VideoStreaming.cc +++ b/src/VideoStreaming/VideoStreaming.cc @@ -49,7 +49,7 @@ #endif #if defined(QGC_GST_STREAMING) -#if (defined(__macos__) && defined(QGC_INSTALL_RELEASE)) || defined(Q_OS_WIN) +#if (defined(Q_OS_MAC) && defined(QGC_INSTALL_RELEASE)) || defined(Q_OS_WIN) static void qgcputenv(const QString& key, const QString& root, const QString& path) { QString value = root + path; @@ -104,7 +104,7 @@ int start_logger(const char *app_name) void initializeVideoStreaming(int &argc, char* argv[], char* logpath, char* debuglevel) { #if defined(QGC_GST_STREAMING) - #ifdef __macos__ + #ifdef Q_OS_MAC #ifdef QGC_INSTALL_RELEASE QString currentDir = QCoreApplication::applicationDirPath(); qgcputenv("GST_PLUGIN_SCANNER", currentDir, "/../Frameworks/GStreamer.framework/Versions/1.0/libexec/gstreamer-1.0/gst-plugin-scanner"); @@ -139,7 +139,7 @@ void initializeVideoStreaming(int &argc, char* argv[], char* logpath, char* debu // Our own plugin GST_PLUGIN_STATIC_REGISTER(QGC_VIDEOSINK_PLUGIN); // The static plugins we use - #if defined(__mobile__) && !defined(__macos__) + #if defined(__mobile__) && !defined(Q_OS_MAC) GST_PLUGIN_STATIC_REGISTER(coreelements); GST_PLUGIN_STATIC_REGISTER(libav); GST_PLUGIN_STATIC_REGISTER(rtp); diff --git a/src/VideoStreaming/gstqtvideosink/utils/glutils.h b/src/VideoStreaming/gstqtvideosink/utils/glutils.h index f7de1882b..eb0d7834b 100644 --- a/src/VideoStreaming/gstqtvideosink/utils/glutils.h +++ b/src/VideoStreaming/gstqtvideosink/utils/glutils.h @@ -17,7 +17,7 @@ #ifndef GLUTILS_H #define GLUTILS_H -#if defined(__mobile__) && !defined(__macos__) +#if defined(__mobile__) && !defined(Q_OS_MAC) #include #define getQOpenGLFunctions() QOpenGLContext::currentContext()->functions() #define QOpenGLFunctionsDef QOpenGLFunctions diff --git a/src/comm/QGCFlightGearLink.cc b/src/comm/QGCFlightGearLink.cc index 890ca1e83..9bc551ef3 100644 --- a/src/comm/QGCFlightGearLink.cc +++ b/src/comm/QGCFlightGearLink.cc @@ -625,7 +625,7 @@ bool QGCFlightGearLink::connectSimulation() // Now set the FG arguments to the arguments from the UI _fgArgList = uiArgList; -#if defined __macos__ +#if defined Q_OS_MAC // Mac installs will default to the /Applications folder 99% of the time. Anything other than // that is pretty non-standard so we don't try to get fancy beyond hardcoding that path. fgAppDir.setPath("/Applications"); diff --git a/src/input/Mouse6dofInput.cpp b/src/input/Mouse6dofInput.cpp deleted file mode 100644 index 26d41620f..000000000 --- a/src/input/Mouse6dofInput.cpp +++ /dev/null @@ -1,320 +0,0 @@ -/** - * @file - * @brief 3dConnexion 3dMouse interface for QGroundControl - * - * @author Matthias Krebs - * - */ - -#include "Mouse6dofInput.h" -#include "UAS.h" -#include "MultiVehicleManager.h" -#include "QGCMessageBox.h" - -#ifdef QGC_MOUSE_ENABLED_LINUX -#include -#include -#ifdef Success -#undef Success // Eigen library doesn't work if Success is defined -#endif //Success -extern "C" -{ -#include "xdrvlib.h" -} -#endif // QGC_MOUSE_ENABLED_LINUX - -#ifdef QGC_MOUSE_ENABLED_WIN -Mouse6dofInput::Mouse6dofInput(Mouse3DInput* mouseInput) : - mouse3DMax(0.075), // TODO: check maximum value fot plugged device - uas(NULL), - done(false), - mouseActive(false), - translationActive(true), - rotationActive(true), - xValue(0.0), - yValue(0.0), - zValue(0.0), - aValue(0.0), - bValue(0.0), - cValue(0.0) -{ - connect(qgcApp()->toolbox()->multiVehicleManager(), &MultiVehicleManager::activeVehicleChanged, this, &Mouse6dofInput::_activeVehicleChanged); - - // Connect 3DxWare SDK MotionEvent - connect(mouseInput, SIGNAL(Move3d(std::vector&)), this, SLOT(motion3DMouse(std::vector&))); - connect(mouseInput, SIGNAL(On3dmouseKeyDown(int)), this, SLOT(button3DMouseDown(int))); - //connect(mouseInput, SIGNAL(On3dmouseKeyUp(int)), this, SLOT(FUNCTION(int))); - -} -#endif //QGC_MOUSE_ENABLED_WIN - -#ifdef QGC_MOUSE_ENABLED_LINUX -Mouse6dofInput::Mouse6dofInput(QWidget* parent) : - mouse3DMax(350.0), // TODO: check maximum value fot plugged device - uas(NULL), - done(false), - mouseActive(false), - translationActive(true), - rotationActive(true), - xValue(0.0), - yValue(0.0), - zValue(0.0), - aValue(0.0), - bValue(0.0), - cValue(0.0) -{ - connect(qgcApp()->toolbox()->multiVehicleManager(), &MultiVehicleManager::activeVehicleChanged, this, &Mouse6dofInput::_activeVehicleChanged); - - if (!mouseActive) - { -// // man visudo --> then you can omit giving password (success not guarantied..) -// qDebug() << "Starting 3DxWare Daemon for 3dConnexion 3dMouse"; -// QString processProgramm = "gksudo"; -// QStringList processArguments; -// processArguments << "/etc/3DxWare/daemon/3dxsrv -d usb"; -// process3dxDaemon = new QProcess(); -// process3dxDaemon->start(processProgramm, processArguments); -// // process3dxDaemon->waitForFinished(); -// // { -// // qDebug() << "... continuing without 3DxWare. May not be initialized properly!"; -// // qDebug() << "Try in terminal as user root:" << processArguments.last(); -// // } - - Display *display = QX11Info::display(); - if(!display) - { - qDebug() << "Cannot open display!" << endl; - } - if ( !MagellanInit( display, parent->winId() ) ) - { - QGCMessageBox::critical(tr("No 3DxWare driver is running."), - tr("Enter in Terminal 'sudo /etc/3DxWare/daemon/3dxsrv -d usb' and then restart QGroundControl.")); - qDebug() << "No 3DxWare driver is running!"; - return; - } - else - { - qDebug() << "Initialized 3dMouse"; - mouseActive = true; - } - } - else - { - qDebug() << "3dMouse already initialized.."; - } - -} -#endif //QGC_MOUSE_ENABLED_LINUX - - -Mouse6dofInput::~Mouse6dofInput() -{ - done = true; -} - -void Mouse6dofInput::_activeVehicleChanged(Vehicle* vehicle) -{ - if (this->uas) - { - disconnect(this, SIGNAL(mouse6dofChanged(double,double,double,double,double,double)), uas, SLOT(setManual6DOFControlCommands(double,double,double,double,double,double))); - // Todo: disconnect button mapping - uas = NULL; - } - - if (vehicle) { - uas = vehicle->uas(); - - connect(this, SIGNAL(mouse6dofChanged(double,double,double,double,double,double)), uas, SLOT(setManual6DOFControlCommands(double,double,double,double,double,double))); - // Todo: connect button mapping - } - - if (!isRunning()) - { - start(); - } -} - -void Mouse6dofInput::init() -{ - // Make sure active UAS is set - _activeVehicleChanged(qgcApp()->toolbox()->multiVehicleManager()->activeVehicle()); -} - -void Mouse6dofInput::run() -{ - init(); - - forever - { - if (done) - { - done = false; - exit(); - } - - if (mouseActive) - { - // Bound x value - if (xValue > 1.0) xValue = 1.0; - if (xValue < -1.0) xValue = -1.0; - // Bound x value - if (yValue > 1.0) yValue = 1.0; - if (yValue < -1.0) yValue = -1.0; - // Bound x value - if (zValue > 1.0) zValue = 1.0; - if (zValue < -1.0) zValue = -1.0; - // Bound x value - if (aValue > 1.0) aValue = 1.0; - if (aValue < -1.0) aValue = -1.0; - // Bound x value - if (bValue > 1.0) bValue = 1.0; - if (bValue < -1.0) bValue = -1.0; - // Bound x value - if (cValue > 1.0) cValue = 1.0; - if (cValue < -1.0) cValue = -1.0; - - emit mouse6dofChanged(xValue, yValue, zValue, aValue, bValue, cValue); - } - - // Sleep, update rate of 3d mouse is approx. 50 Hz (1000 ms / 50 = 20 ms) - QGC::SLEEP::msleep(20); - } -} - -#ifdef QGC_MOUSE_ENABLED_WIN -void Mouse6dofInput::motion3DMouse(std::vector &motionData) -{ - if (motionData.size() < 6) return; - mouseActive = true; - - if (translationActive) - { - xValue = (double)1.0e2f*motionData[ 1 ] / mouse3DMax; - yValue = (double)1.0e2f*motionData[ 0 ] / mouse3DMax; - zValue = (double)1.0e2f*motionData[ 2 ] / mouse3DMax; - }else{ - xValue = 0; - yValue = 0; - zValue = 0; - } - if (rotationActive) - { - aValue = (double)1.0e2f*motionData[ 4 ] / mouse3DMax; - bValue = (double)1.0e2f*motionData[ 3 ] / mouse3DMax; - cValue = (double)1.0e2f*motionData[ 5 ] / mouse3DMax; - }else{ - aValue = 0; - bValue = 0; - cValue = 0; - } - - //qDebug() << "NEW 3D MOUSE VALUES -- X" << xValue << " -- Y" << yValue << " -- Z" << zValue << " -- A" << aValue << " -- B" << bValue << " -- C" << cValue; -} -#endif //QGC_MOUSE_ENABLED_WIN - -#ifdef QGC_MOUSE_ENABLED_WIN -void Mouse6dofInput::button3DMouseDown(int button) -{ - switch(button) - { - case 1: - { - rotationActive = !rotationActive; - emit mouseRotationActiveChanged(rotationActive); - qDebug() << "Changed 3DMouse Rotation to " << (bool)rotationActive; - break; - } - case 2: - { - translationActive = !translationActive; - emit mouseTranslationActiveChanged(translationActive); - qDebug() << "Changed 3DMouse Translation to" << (bool)translationActive; - break; - } - default: - break; - } -} -#endif //QGC_MOUSE_ENABLED_WIN - -#ifdef QGC_MOUSE_ENABLED_LINUX -void Mouse6dofInput::handleX11Event(XEvent *event) -{ - //qDebug("XEvent occurred..."); - if (!mouseActive) - { - qDebug() << "3dMouse not initialized. Cancelled handling X11event for 3dMouse"; - return; - } - - MagellanFloatEvent MagellanEvent; - - Display *display = QX11Info::display(); - if(!display) - { - qDebug() << "Cannot open display!" << endl; - } - - switch (event->type) - { - case ClientMessage: - switch( MagellanTranslateEvent( display, event, &MagellanEvent, 1.0, 1.0 ) ) - { - case MagellanInputMotionEvent : - MagellanRemoveMotionEvents( display ); - for (int i = 0; i < 6; i++) { // Saturation - MagellanEvent.MagellanData[i] = (abs(MagellanEvent.MagellanData[i]) < mouse3DMax) ? MagellanEvent.MagellanData[i] : (mouse3DMax*MagellanEvent.MagellanData[i]/abs(MagellanEvent.MagellanData[i])); - } - - // Check whether translational motions are enabled - if (translationActive) - { - xValue = MagellanEvent.MagellanData[ MagellanZ ] / mouse3DMax; - yValue = MagellanEvent.MagellanData[ MagellanX ] / mouse3DMax; - zValue = - MagellanEvent.MagellanData[ MagellanY ] / mouse3DMax; - }else{ - xValue = 0; - yValue = 0; - zValue = 0; - } - // Check whether rotational motions are enabled - if (rotationActive) - { - aValue = MagellanEvent.MagellanData[ MagellanC ] / mouse3DMax; - bValue = MagellanEvent.MagellanData[ MagellanA ] / mouse3DMax; - cValue = - MagellanEvent.MagellanData[ MagellanB ] / mouse3DMax; - }else{ - aValue = 0; - bValue = 0; - cValue = 0; - } - //qDebug() << "NEW 3D MOUSE VALUES -- X" << xValue << " -- Y" << yValue << " -- Z" << zValue << " -- A" << aValue << " -- B" << bValue << " -- C" << cValue; - break; - - case MagellanInputButtonPressEvent : - qDebug() << "MagellanInputButtonPressEvent called with button " << MagellanEvent.MagellanButton; - switch (MagellanEvent.MagellanButton) - { - case 1: - { - rotationActive = !rotationActive; - emit mouseRotationActiveChanged(rotationActive); - qDebug() << "Changed 3DMouse Rotation to " << (bool)rotationActive; - break; - } - case 2: - { - translationActive = !translationActive; - emit mouseTranslationActiveChanged(translationActive); - qDebug() << "Changed 3DMouse Translation to" << (bool)translationActive; - break; - } - default: - break; - } - default: - break; - } - } -} -#endif //QGC_MOUSE_ENABLED_LINUX diff --git a/src/input/Mouse6dofInput.h b/src/input/Mouse6dofInput.h deleted file mode 100644 index 9fef42f1d..000000000 --- a/src/input/Mouse6dofInput.h +++ /dev/null @@ -1,96 +0,0 @@ -/** - * @file - * @brief Definition of 3dConnexion 3dMouse interface for QGroundControl - * - * @author Matthias Krebs - * - */ - -#ifndef MOUSE6DOFINPUT_H -#define MOUSE6DOFINPUT_H - -#include - -#ifdef QGC_MOUSE_ENABLED_WIN -#include "Mouse3DInput.h" -#endif //QGC_MOUSE_ENABLED_WIN - -#include "UAS.h" -#include "Vehicle.h" - -class Mouse6dofInput : public QThread -{ - Q_OBJECT - -public: -#ifdef QGC_MOUSE_ENABLED_WIN - Mouse6dofInput(Mouse3DInput* mouseInput); -#endif //QGC_MOUSE_ENABLED_WIN -#ifdef QGC_MOUSE_ENABLED_LINUX - Mouse6dofInput(QWidget* parent); -#endif //QGC_MOUSE_ENABLED_LINUX - - ~Mouse6dofInput(); - void run(); - - const double mouse3DMax; - -protected: - void init(); - - UAS* uas; - bool done; - bool mouseActive; - bool translationActive; - bool rotationActive; - - double xValue; - double yValue; - double zValue; - double aValue; - double bValue; - double cValue; - - -signals: - /** - * @brief Input of the 3d mouse has changed - * - * @param x Input x direction, range [-1, 1] - * @param y Input y direction, range [-1, 1] - * @param z Input z direction, range [-1, 1] - * @param a Input x rotation, range [-1, 1] - * @param b Input y rotation, range [-1, 1] - * @param c Input z rotation, range [-1, 1] - */ - void mouse6dofChanged(double x, double y, double z, double a, double b, double c); - - /** - * @brief Activity of translational 3DMouse inputs changed - * @param translationEnable, true: translational inputs active; false: translational inputs ingored - */ - void mouseTranslationActiveChanged(bool translationEnable); - - /** - * @brief Activity of rotational 3DMouse inputs changed - * @param rotationEnable, true: rotational inputs active; false: rotational inputs ingored - */ - void mouseRotationActiveChanged(bool rotationEnable); - -public slots: -#ifdef QGC_MOUSE_ENABLED_WIN - /** @brief Get a motion input from 3DMouse */ - void motion3DMouse(std::vector &motionData); - /** @brief Get a button input from 3DMouse */ - void button3DMouseDown(int button); -#endif //QGC_MOUSE_ENABLED_WIN -#ifdef QGC_MOUSE_ENABLED_LINUX - /** @brief Get an XEvent to check it for an 3DMouse event (motion or button) */ - void handleX11Event(XEvent* event); -#endif //QGC_MOUSE_ENABLED_LINUX - -private slots: - void _activeVehicleChanged(Vehicle* vehicle); -}; - -#endif // MOUSE6DOFINPUT_H diff --git a/src/main.cc b/src/main.cc index 8c2ff2ddc..1811b876a 100644 --- a/src/main.cc +++ b/src/main.cc @@ -60,6 +60,9 @@ #endif #ifdef Q_OS_WIN + +#include + /// @brief CRT Report Hook installed using _CrtSetReportHook. We install this hook when /// we don't want asserts to pop a dialog on windows. int WindowsCrtReportHook(int reportType, char* message, int* returnValue) diff --git a/src/ui/InputConfiguration.cc b/src/ui/InputConfiguration.cc deleted file mode 100644 index 2068b8da8..000000000 --- a/src/ui/InputConfiguration.cc +++ /dev/null @@ -1,33 +0,0 @@ -/**************************************************************************** - * - * (c) 2009-2016 QGROUNDCONTROL PROJECT - * - * QGroundControl is licensed according to the terms in the file - * COPYING.md in the root of the source code directory. - * - ****************************************************************************/ - - -/** - * @file - * @brief Brief Description - * - * @author Lorenz Meier - * - */ - -#include -#include - -#include - -InputConfigurationWidget::InputConfigurationWidget(QWidget *parent) : QWidget(parent) -{ - /* Add UI components */ - ui.setupUi(this); -} - -InputConfigurationWidget::~InputConfigurationWidget() -{ - -} diff --git a/src/ui/MainWindow.cc b/src/ui/MainWindow.cc index 931d32e4f..6a6b6110e 100644 --- a/src/ui/MainWindow.cc +++ b/src/ui/MainWindow.cc @@ -185,19 +185,6 @@ MainWindow::MainWindow() // Create actions connectCommonActions(); - // Connect user interface devices -#ifdef QGC_MOUSE_ENABLED_WIN - emit initStatusChanged(tr("Initializing 3D mouse interface"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141)); - mouseInput = new Mouse3DInput(this); - mouse = new Mouse6dofInput(mouseInput); -#endif //QGC_MOUSE_ENABLED_WIN - -#if QGC_MOUSE_ENABLED_LINUX - emit initStatusChanged(tr("Initializing 3D mouse interface"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141)); - - mouse = new Mouse6dofInput(this); - connect(this, &MainWindow::x11EventOccured, mouse, &Mouse6dofInput::handleX11Event); -#endif //QGC_MOUSE_ENABLED_LINUX // Set low power mode enableLowPowerMode(_lowPowerMode); @@ -478,14 +465,6 @@ void MainWindow::saveLastUsedConnection(const QString connection) settings.setValue(key, connection); } -#ifdef QGC_MOUSE_ENABLED_LINUX -bool MainWindow::x11Event(XEvent *event) -{ - emit x11EventOccured(event); - return false; -} -#endif // QGC_MOUSE_ENABLED_LINUX - #ifdef UNITTEST_BUILD void MainWindow::_showQmlTestWidget(void) { diff --git a/src/ui/MainWindow.h b/src/ui/MainWindow.h index 001955f9e..40ffafb45 100644 --- a/src/ui/MainWindow.h +++ b/src/ui/MainWindow.h @@ -41,10 +41,6 @@ #include "ui_MainWindow.h" -#if (defined QGC_MOUSE_ENABLED_WIN) | (defined QGC_MOUSE_ENABLED_LINUX) - #include "Mouse6dofInput.h" -#endif // QGC_MOUSE_ENABLED_WIN - class QGCStatusBar; class Linecharts; @@ -109,11 +105,6 @@ signals: // Used for unit tests to know when the main window closes void mainWindowClosed(void); -#ifdef QGC_MOUSE_ENABLED_LINUX - /** @brief Forward X11Event to catch 3DMouse inputs */ - void x11EventOccured(XEvent *event); -#endif //QGC_MOUSE_ENABLED_LINUX - public: QGCMAVLinkLogPlayer* getLogPlayer() { @@ -135,12 +126,6 @@ protected: Mouse6dofInput* mouse; ///< Implementation for 3dMouse input #endif // QGC_MOUSE_ENABLED_WIN -#ifdef QGC_MOUSE_ENABLED_LINUX - /** @brief Reimplementation of X11Event to handle 3dMouse Events (magellan) */ - bool x11Event(XEvent *event); - Mouse6dofInput* mouse; ///< Implementation for 3dMouse input -#endif // QGC_MOUSE_ENABLED_LINUX - /** User interface actions **/ QAction* connectUASAct; QAction* disconnectUASAct; diff --git a/src/ui/QGCWebView.cc b/src/ui/QGCWebView.cc deleted file mode 100644 index 7de964b90..000000000 --- a/src/ui/QGCWebView.cc +++ /dev/null @@ -1,28 +0,0 @@ -#include "QGCWebView.h" -#include "ui_QGCWebView.h" - -QGCWebView::QGCWebView(QWidget *parent) : - QWidget(parent), - ui(new Ui::QGCWebView) -{ - ui->setupUi(this); - ui->webView->settings()->setAttribute(QWebSettings::PluginsEnabled, true); - ui->webView->load(QUrl("http://qgroundcontrol.org")); -} - -QGCWebView::~QGCWebView() -{ - delete ui; -} - -void QGCWebView::changeEvent(QEvent *e) -{ - QWidget::changeEvent(e); - switch (e->type()) { - case QEvent::LanguageChange: - ui->retranslateUi(this); - break; - default: - break; - } -} diff --git a/src/ui/QGCWebView.h b/src/ui/QGCWebView.h deleted file mode 100644 index c8ca22c0c..000000000 --- a/src/ui/QGCWebView.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef QGCWEBVIEW_H -#define QGCWEBVIEW_H - -#include - -namespace Ui -{ -class QGCWebView; -} - -class QGCWebView : public QWidget -{ - Q_OBJECT - -public: - explicit QGCWebView(QWidget *parent = 0); - ~QGCWebView(); - -protected: - void changeEvent(QEvent *e); - -private: - Ui::QGCWebView *ui; -}; - -#endif // QGCWEBVIEW_H diff --git a/src/ui/QGCWebView.ui b/src/ui/QGCWebView.ui deleted file mode 100644 index d7f8a87a3..000000000 --- a/src/ui/QGCWebView.ui +++ /dev/null @@ -1,37 +0,0 @@ - - - QGCWebView - - - - 0 - 0 - 400 - 300 - - - - Form - - - - - - - about:blank - - - - - - - - - QWebView - QWidget -
QtWebKit/QWebView
-
-
- - -
diff --git a/src/ui/Linechart.ui b/src/ui/linechart/Linechart.ui similarity index 100% rename from src/ui/Linechart.ui rename to src/ui/linechart/Linechart.ui -- 2.22.0