Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CMake: add option to build with Qt6 #4051

Merged
merged 1 commit into from
Sep 19, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
301 changes: 163 additions & 138 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,18 @@ if(NOT CMAKE_CONFIGURATION_TYPES)
endif()
endif()

option(QT6 "Build with Qt6" OFF)

if(APPLE)
# Minimum macOS version supported by Qt 5.12
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.12 CACHE STRING "Minimum macOS version the build will be able to run on" FORCE)
# Needed for deployment target < 10.14
add_compile_options(-fno-aligned-allocation)
if(QT6)
# Minimum macOS version supported by Qt 6
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.14 CACHE STRING "Minimum macOS version the build will be able to run on" FORCE)
else()
# Minimum macOS version supported by Qt 5.12
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.12 CACHE STRING "Minimum macOS version the build will be able to run on" FORCE)
# Needed for deployment target < 10.14
add_compile_options(-fno-aligned-allocation)
endif()
endif()

project(mixxx VERSION 2.4.0)
Expand Down Expand Up @@ -798,14 +805,6 @@ add_library(mixxx-lib STATIC EXCLUDE_FROM_ALL
src/preferences/settingsmanager.cpp
src/preferences/upgrade.cpp
src/recording/recordingmanager.cpp
src/skin/legacy/colorschemeparser.cpp
src/skin/legacy/imgcolor.cpp
src/skin/legacy/imginvert.cpp
src/skin/legacy/imgloader.cpp
src/skin/legacy/launchimage.cpp
src/skin/legacy/legacyskinparser.cpp
src/skin/legacy/pixmapsource.cpp
src/skin/legacy/legacyskin.cpp
src/skin/qml/asyncimageprovider.cpp
src/skin/qml/qmlcontrolproxy.cpp
src/skin/qml/qmlconfigproxy.cpp
Expand Down Expand Up @@ -932,125 +931,137 @@ add_library(mixxx-lib STATIC EXCLUDE_FROM_ALL
src/util/workerthread.cpp
src/util/workerthreadscheduler.cpp
src/util/xml.cpp
src/waveform/guitick.cpp
src/waveform/renderers/glslwaveformrenderersignal.cpp
src/waveform/renderers/glvsynctestrenderer.cpp
src/waveform/renderers/glwaveformrendererfilteredsignal.cpp
src/waveform/renderers/glwaveformrendererrgb.cpp
src/waveform/renderers/glwaveformrenderersimplesignal.cpp
src/waveform/renderers/qtvsynctestrenderer.cpp
src/waveform/renderers/qtwaveformrendererfilteredsignal.cpp
src/waveform/renderers/qtwaveformrenderersimplesignal.cpp
src/waveform/renderers/waveformmark.cpp
src/waveform/renderers/waveformmarkrange.cpp
src/waveform/renderers/waveformmarkset.cpp
src/waveform/renderers/waveformrenderbackground.cpp
src/waveform/renderers/waveformrenderbeat.cpp
src/waveform/renderers/waveformrendererabstract.cpp
src/waveform/renderers/waveformrendererendoftrack.cpp
src/waveform/renderers/waveformrendererfilteredsignal.cpp
src/waveform/renderers/waveformrendererhsv.cpp
src/waveform/renderers/waveformrendererpreroll.cpp
src/waveform/renderers/waveformrendererrgb.cpp
src/waveform/renderers/waveformrenderersignalbase.cpp
src/waveform/renderers/waveformrendermark.cpp
src/waveform/renderers/waveformrendermarkrange.cpp
src/waveform/renderers/waveformsignalcolors.cpp
src/waveform/renderers/waveformwidgetrenderer.cpp
src/waveform/sharedglcontext.cpp
src/waveform/visualplayposition.cpp
src/waveform/visualsmanager.cpp
src/waveform/vsyncthread.cpp
src/waveform/waveform.cpp
src/waveform/waveformfactory.cpp
src/waveform/waveformmarklabel.cpp
src/waveform/waveformwidgetfactory.cpp
src/waveform/widgets/emptywaveformwidget.cpp
src/waveform/widgets/glrgbwaveformwidget.cpp
src/waveform/widgets/glsimplewaveformwidget.cpp
src/waveform/widgets/glslwaveformwidget.cpp
src/waveform/widgets/glvsynctestwidget.cpp
src/waveform/widgets/glwaveformwidget.cpp
src/waveform/widgets/hsvwaveformwidget.cpp
src/waveform/widgets/qthsvwaveformwidget.cpp
src/waveform/widgets/qtrgbwaveformwidget.cpp
src/waveform/widgets/qtsimplewaveformwidget.cpp
src/waveform/widgets/qtvsynctestwidget.cpp
src/waveform/widgets/qtwaveformwidget.cpp
src/waveform/widgets/rgbwaveformwidget.cpp
src/waveform/widgets/softwarewaveformwidget.cpp
src/waveform/widgets/waveformwidgetabstract.cpp
src/widget/controlwidgetconnection.cpp
src/widget/hexspinbox.cpp
src/widget/paintable.cpp
src/widget/wanalysislibrarytableview.cpp
src/widget/wbasewidget.cpp
src/widget/wbattery.cpp
src/widget/wbeatspinbox.cpp
src/widget/wcolorpicker.cpp
src/widget/wcolorpickeraction.cpp
src/widget/wcombobox.cpp
src/widget/wcoverart.cpp
src/widget/wcoverartlabel.cpp
src/widget/wcoverartmenu.cpp
src/widget/wcuemenupopup.cpp
src/widget/wdisplay.cpp
src/widget/weffect.cpp
src/widget/weffectbuttonparameter.cpp
src/widget/weffectchain.cpp
src/widget/weffectparameter.cpp
src/widget/weffectparameterbase.cpp
src/widget/weffectparameterknob.cpp
src/widget/weffectparameterknobcomposed.cpp
src/widget/weffectpushbutton.cpp
src/widget/weffectselector.cpp
src/widget/whotcuebutton.cpp
src/widget/wimagestore.cpp
src/widget/wkey.cpp
src/widget/wknob.cpp
src/widget/wknobcomposed.cpp
src/widget/wlabel.cpp
src/widget/wlibrary.cpp
src/widget/wlibrarysidebar.cpp
src/widget/wlibrarytableview.cpp
src/widget/wlibrarytextbrowser.cpp
src/widget/wmainmenubar.cpp
src/widget/wnumber.cpp
src/widget/wnumberdb.cpp
src/widget/wnumberpos.cpp
src/widget/wnumberrate.cpp
src/widget/woverview.cpp
src/widget/woverviewhsv.cpp
src/widget/woverviewlmh.cpp
src/widget/woverviewrgb.cpp
src/widget/wpixmapstore.cpp
src/widget/wpushbutton.cpp
src/widget/wrecordingduration.cpp
src/widget/wscrollable.cpp
src/widget/wsearchlineedit.cpp
src/widget/wsearchrelatedtracksmenu.cpp
src/widget/wsingletoncontainer.cpp
src/widget/wsizeawarestack.cpp
src/widget/wskincolor.cpp
src/widget/wslidercomposed.cpp
src/widget/wspinny.cpp
src/widget/wsplitter.cpp
src/widget/wstarrating.cpp
src/widget/wstatuslight.cpp
src/widget/wtime.cpp
src/widget/wtrackmenu.cpp
src/widget/wtrackproperty.cpp
src/widget/wtracktableview.cpp
src/widget/wtracktableviewheader.cpp
src/widget/wtracktext.cpp
src/widget/wtrackwidgetgroup.cpp
src/widget/wvumeter.cpp
src/widget/wwaveformviewer.cpp
src/widget/wwidget.cpp
src/widget/wwidgetgroup.cpp
src/widget/wwidgetstack.cpp
src/widget/wraterange.cpp
)
if(NOT QT6)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need to remove all these files? Can't we keep everything except QGLWidget?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also suggest to keep everything that builds fine with Qt5 and only remove files conditionally if incompatibilities arise or if they become obsolete.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, there is no point trying to get the legacy skin system to build with Qt6 because essential features cannot work with Qt6. That would probably require lots more preprocessor Qt version checks scattered around the legacy code.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which ones won't work? I though only QOpenGLWidget?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The legacy skin system uses QGLWidget, not QOpenGLWidget, which is the reason it needs to be replaced.

Copy link
Contributor Author

@Be-ing Be-ing Jul 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you consider it feasible to start with this radical switch and then gradually try to re-enable the legacy skin components for Qt6?

Yes, I advocated for this approach with the library but @Holzhaus was against it. Since @Holzhaus is doing the work on that and I am minimally familiar with the library code, I trust that his approach is a good way to proceed. I ask that trust be reciprocated here. From my experiences redesigning Deere, implementing the effects system, following #1974, and struggling for months with every idea I could think of to improve macOS performance with the legacy skin system, I judge that the legacy skin system is a dead end that we should abandon as soon as possible. macOS performance is still only kinda passable now and we have no idea how to fix it without starting from scratch with Qt Quick. I want to implement a new feature on top of #2618 for one big effect chain with more effects, but just the thought of adding more complexity with the legacy skin system -- and repeating that four times! -- is making me reconsider whether that is worthwhile at this time. I will not put any work into backtracking by putting QQuickWidgets into legacy skins. We know from the Qt documentation such an approach would have major performance limitations and it might not even solve our persistent macOS troubles.

Mixxx's CPU usage at baseline, which is due to the hugely inefficient GUI, is terrible. I have never gotten Mixxx to run without my computer's fans turning on. This is should not happen. Mixxx is not a fancy schmancy 3D game. Our fanciest graphics are just drawing a waveform. This should not be difficult at all for my fancy schmancy laptop, yet it is. Mixxx should be able to run easily on hardware as weak as a PinePhone, but we won't get there if we cling to very inefficient legacy GUI technology. The skin system dates from before Qt had any comparable solution. It essentially does what Qt did with the XML GUI layouts for Qt Designer, but badly. Qt's current solution with Qt Quick is much, much better both for performance and maintainability. Let's embrace it without hesitation and drop the legacy code ASAP.

Copy link
Member

@Holzhaus Holzhaus Jul 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We cannot drop legacy code until the new code works fine. That's my whole point. Otherwise we'll have a broken mixxx main branch and cannot do a mixxx release in years.

I know this is just for Qt6 support and I'm okay with merging initial Qt6 support without the legacy skin system, but we should not burn bridges unless we need to.

I want to implement a new feature on top of #2618 for one big effect chain with more effects, but just the thought of adding more complexity with the legacy skin system -- and repeating that four times! -- is making me reconsider whether that is worthwhile at this time.

I have no objections against a new hidden feature that is not accessible from the legacy skins, just from QML. But if that feature breaks legacy skins, we cannot merge at this time. QML skin feature parity is probably still years away, and I'd like to do more releases until then.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to ensure that we are all in a position to make progress. No one is forced to work on features that they do not support. Nevertheless we need to coordinate our work and be aware of the differing goals to prevent conflicts and frustration.

I guess we all agree that we want and need to replace the legacy skins with QML asap. If it turns out that keeping the legacy skins alive imposes too much work or would pollute the code base unacceptably we can decide to stop this maintenance effort at any time and shift focus. If we could agree to proceed with the intent to defer this decision until it becomes inevitable instead of giving up recklessly this would help.

How about extracting Qt6-only components/modules into separate files if needed, e.g. the new QML UI based on #2618? This will hopefully prevent to mix conflicting Qt5/Qt6 code in the same file when managing the differences becomes inconvenient. Not sure how to deal with the split at the QML-level where we also have backwards compatible components that are not even using all the features available in Qt 5.15, mainly due to outdated Ubuntu dependencies.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We cannot drop legacy code until the new code works fine.

I fully agree. But wasting effort on maintaining legacy code with Qt6 does nothing to help us get there, it only puts obstacles in the way.

I know this is just for Qt6 support and I'm okay with merging initial Qt6 support without the legacy skin system, but we should not burn bridges unless we need to.

The point of this approach is that it does not touch the legacy code at all. It just doesn't build the old code with Qt6. No bridges were harmed in the making of this PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure how to deal with the split at the QML-level where we also have backwards compatible components that are not even using all the features available in Qt 5.15, mainly due to outdated Ubuntu dependencies.

When we get CI setup for Qt6 we could make QML build for only Qt6 and not worry about old Qt5 versions. Here is a PR to start that:
mixxxdj/vcpkg#19

After we get vcpkg working on macOS, it should be easy to use vcpkg for Linux CI as well.

target_sources(mixxx-lib PRIVATE
src/skin/legacy/colorschemeparser.cpp
src/skin/legacy/imgcolor.cpp
src/skin/legacy/imginvert.cpp
src/skin/legacy/imgloader.cpp
src/skin/legacy/launchimage.cpp
src/skin/legacy/legacyskinparser.cpp
src/skin/legacy/pixmapsource.cpp
src/skin/legacy/legacyskin.cpp
src/waveform/guitick.cpp
src/waveform/renderers/glslwaveformrenderersignal.cpp
src/waveform/renderers/glvsynctestrenderer.cpp
src/waveform/renderers/glwaveformrendererfilteredsignal.cpp
src/waveform/renderers/glwaveformrendererrgb.cpp
src/waveform/renderers/glwaveformrenderersimplesignal.cpp
src/waveform/renderers/qtvsynctestrenderer.cpp
src/waveform/renderers/qtwaveformrendererfilteredsignal.cpp
src/waveform/renderers/qtwaveformrenderersimplesignal.cpp
src/waveform/renderers/waveformmark.cpp
src/waveform/renderers/waveformmarkrange.cpp
src/waveform/renderers/waveformmarkset.cpp
src/waveform/renderers/waveformrenderbackground.cpp
src/waveform/renderers/waveformrenderbeat.cpp
src/waveform/renderers/waveformrendererabstract.cpp
src/waveform/renderers/waveformrendererendoftrack.cpp
src/waveform/renderers/waveformrendererfilteredsignal.cpp
src/waveform/renderers/waveformrendererhsv.cpp
src/waveform/renderers/waveformrendererpreroll.cpp
src/waveform/renderers/waveformrendererrgb.cpp
src/waveform/renderers/waveformrenderersignalbase.cpp
src/waveform/renderers/waveformrendermark.cpp
src/waveform/renderers/waveformrendermarkrange.cpp
src/waveform/renderers/waveformsignalcolors.cpp
src/waveform/renderers/waveformwidgetrenderer.cpp
src/waveform/sharedglcontext.cpp
src/waveform/visualplayposition.cpp
src/waveform/visualsmanager.cpp
src/waveform/vsyncthread.cpp
src/waveform/waveform.cpp
src/waveform/waveformfactory.cpp
src/waveform/waveformmarklabel.cpp
src/waveform/waveformwidgetfactory.cpp
src/waveform/widgets/emptywaveformwidget.cpp
src/waveform/widgets/glrgbwaveformwidget.cpp
src/waveform/widgets/glsimplewaveformwidget.cpp
src/waveform/widgets/glslwaveformwidget.cpp
src/waveform/widgets/glvsynctestwidget.cpp
src/waveform/widgets/glwaveformwidget.cpp
src/waveform/widgets/hsvwaveformwidget.cpp
src/waveform/widgets/qthsvwaveformwidget.cpp
src/waveform/widgets/qtrgbwaveformwidget.cpp
src/waveform/widgets/qtsimplewaveformwidget.cpp
src/waveform/widgets/qtvsynctestwidget.cpp
src/waveform/widgets/qtwaveformwidget.cpp
src/waveform/widgets/rgbwaveformwidget.cpp
src/waveform/widgets/softwarewaveformwidget.cpp
src/waveform/widgets/waveformwidgetabstract.cpp
src/widget/controlwidgetconnection.cpp
src/widget/hexspinbox.cpp
src/widget/paintable.cpp
src/widget/wanalysislibrarytableview.cpp
src/widget/wbasewidget.cpp
src/widget/wbattery.cpp
src/widget/wbeatspinbox.cpp
src/widget/wcolorpicker.cpp
src/widget/wcolorpickeraction.cpp
src/widget/wcombobox.cpp
src/widget/wcoverart.cpp
src/widget/wcoverartlabel.cpp
src/widget/wcoverartmenu.cpp
src/widget/wcuemenupopup.cpp
src/widget/wdisplay.cpp
src/widget/weffect.cpp
src/widget/weffectbuttonparameter.cpp
src/widget/weffectchain.cpp
src/widget/weffectparameter.cpp
src/widget/weffectparameterbase.cpp
src/widget/weffectparameterknob.cpp
src/widget/weffectparameterknobcomposed.cpp
src/widget/weffectpushbutton.cpp
src/widget/weffectselector.cpp
src/widget/whotcuebutton.cpp
src/widget/wimagestore.cpp
src/widget/wkey.cpp
src/widget/wknob.cpp
src/widget/wknobcomposed.cpp
src/widget/wlabel.cpp
src/widget/wlibrary.cpp
src/widget/wlibrarysidebar.cpp
src/widget/wlibrarytableview.cpp
src/widget/wlibrarytextbrowser.cpp
src/widget/wmainmenubar.cpp
src/widget/wnumber.cpp
src/widget/wnumberdb.cpp
src/widget/wnumberpos.cpp
src/widget/wnumberrate.cpp
src/widget/woverview.cpp
src/widget/woverviewhsv.cpp
src/widget/woverviewlmh.cpp
src/widget/woverviewrgb.cpp
src/widget/wpixmapstore.cpp
src/widget/wpushbutton.cpp
src/widget/wrecordingduration.cpp
src/widget/wscrollable.cpp
src/widget/wsearchlineedit.cpp
src/widget/wsearchrelatedtracksmenu.cpp
src/widget/wsingletoncontainer.cpp
src/widget/wsizeawarestack.cpp
src/widget/wskincolor.cpp
src/widget/wslidercomposed.cpp
src/widget/wspinny.cpp
src/widget/wsplitter.cpp
src/widget/wstarrating.cpp
src/widget/wstatuslight.cpp
src/widget/wtime.cpp
src/widget/wtrackmenu.cpp
src/widget/wtrackproperty.cpp
src/widget/wtracktableview.cpp
src/widget/wtracktableviewheader.cpp
src/widget/wtracktext.cpp
src/widget/wtrackwidgetgroup.cpp
src/widget/wvumeter.cpp
src/widget/wwaveformviewer.cpp
src/widget/wwidget.cpp
src/widget/wwidgetgroup.cpp
src/widget/wwidgetstack.cpp
src/widget/wraterange.cpp
)
endif()
set_target_properties(mixxx-lib PROPERTIES AUTOMOC ON AUTOUIC ON CXX_CLANG_TIDY "${CLANG_TIDY}")
target_include_directories(mixxx-lib PUBLIC src "${CMAKE_CURRENT_BINARY_DIR}/src")
if(UNIX AND NOT APPLE)
Expand Down Expand Up @@ -2096,7 +2107,12 @@ target_link_libraries(mixxx-lib PRIVATE mixxx-proto)
target_include_directories(mixxx-lib SYSTEM PUBLIC lib/rigtorp/SPSCQueue/include)

# Qt
find_package(QT NAMES Qt5 COMPONENTS Core REQUIRED)
if(QT6)
find_package(QT NAMES Qt6 COMPONENTS Core REQUIRED)
set(QT6_NEW_COMPONENTS "SvgWidgets;Core5Compat")
Holzhaus marked this conversation as resolved.
Show resolved Hide resolved
else()
find_package(QT NAMES Qt5 COMPONENTS Core REQUIRED)
endif()
find_package(Qt${QT_VERSION_MAJOR}
COMPONENTS
Concurrent
Expand All @@ -2112,6 +2128,7 @@ find_package(Qt${QT_VERSION_MAJOR}
Test
Widgets
Xml
${QT6_NEW_COMPONENTS}
REQUIRED
)
# PUBLIC is required below to find included headers
Expand All @@ -2129,6 +2146,12 @@ target_link_libraries(mixxx-lib PUBLIC
Qt${QT_VERSION_MAJOR}::Test
Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::Xml)
if(QT6)
foreach(COMPONENT ${QT6_NEW_COMPONENTS})
target_link_libraries(mixxx-lib PUBLIC Qt6::${COMPONENT})
endforeach()
endif()

target_compile_definitions(mixxx-lib PUBLIC QT_TABLET_SUPPORT QT_USE_QSTRINGBUILDER)
is_static_library(Qt_IS_STATIC Qt${QT_VERSION_MAJOR}::Core)
if(Qt_IS_STATIC)
Expand Down Expand Up @@ -2195,13 +2218,15 @@ if(APPLE)
"-weak_framework IOKit"
)
endif()
elseif(UNIX)
find_package(X11 REQUIRED)
find_package(Qt5 COMPONENTS X11Extras DBus REQUIRED)
target_include_directories(mixxx-lib SYSTEM PUBLIC "${X11_INCLUDE_DIR}")
elseif(UNIX AND NOT APPLE)
if(NOT QT6)
find_package(X11 REQUIRED)
find_package(Qt5 COMPONENTS X11Extras REQUIRED)
target_include_directories(mixxx-lib SYSTEM PUBLIC "${X11_INCLUDE_DIR}")
target_link_libraries(mixxx-lib PRIVATE "${X11_LIBRARIES}" Qt5::X11Extras)
endif()
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS DBus REQUIRED)
target_link_libraries(mixxx-lib PRIVATE
"${X11_LIBRARIES}"
Qt${QT_VERSION_MAJOR}::X11Extras
Qt${QT_VERSION_MAJOR}::DBus
)
elseif(WIN32)
Expand Down Expand Up @@ -2718,7 +2743,7 @@ endif()
# QtKeychain
option(QTKEYCHAIN "Secure credentials storage support for Live Broadcasting profiles" ON)
if(QTKEYCHAIN)
find_package(Qt5Keychain REQUIRED)
find_package(Qt${QT_VERSION_MAJOR}Keychain REQUIRED)
target_compile_definitions(mixxx-lib PUBLIC __QTKEYCHAIN__)
target_link_libraries(mixxx-lib PRIVATE ${QTKEYCHAIN_LIBRARIES})
target_include_directories(mixxx-lib SYSTEM PUBLIC ${QTKEYCHAIN_INCLUDE_DIRS})
Expand Down