Developers guide
Checklists for developing new things in Magnum itself.
This guide is meant mainly for core Magnum developers to avoid forgetting about things. If you are contributing a pull-request, you can use these checklists as a guide and save the maintainers a bit of work — but you are not strictly required to follow them to the point.
Checklist for adding / removing a library
- Add a
MAGNUM_WITH_LIBRARYNAME
CMake option to:- root
CMakeLists.txt
(if it has some inter-library dependencies, update the others / convert them tocmake_dependent_option()
, addingNOT MAGNUM_WITH_LIBRARYNAME
to their condition — note the conditions are ANDed so they need to be specified in reverse) - the list in
doc/building.dox
(and similar files in other repos)
- root
- Update
FindMagnum.cmake
(or similar in other repos):- mention the new lib in the list of components in the docs
- if it has some inter-library dependencies, add a corresponding
_MAGNUM_Component_DEPENDENCIES
entry - add its name to the
_MAGNUM_LIBRARY_COMPONENT_LIST
list - add a new
elseif(_component STREQUAL LibraryName)
section with special setup of includes or dependencies or explicitly say# No special setup for LibraryName library
- Add the library to the list in
doc/cmake.dox
(or similar files in other repos) - Add a conditional
add_subdirectory()
tosrc/Magnum/CMakeLists.txt
- Create a new
src/Magnum/LibraryName/CMakeLists.txt
, copy over up-to-date license header from other CMake files, add your name to it and populate it:- add source files to
MagnumLibraryName_SRCS
variable - add installable headers to
MagnumLibraryName_HEADERS
variable - add private headers to
MagnumLibraryName_PRIVATE_HEADERS
variable (if any) - if the test needs some extra setup (such as e.g.
CORRADE_NO_ASSERT
enabled for particular files), create a newMagnumLibraryNameObjects
OBJECT
library with files that can be compiled the same way in both cases to speed up compilation - verify that the
add_library()
command references all input files (needed so QtCreator lists all project files properly) - verify that debug postfix is set (
set_target_properties(MagnumLibraryName PROPERTIES DEBUG_POSTFIX "-d")
) - verify that folder is correctly set for the
CMakeLists.txt
file (set(CMAKE_FOLDER "Magnum/LibraryName")
) - verify that target installation is done in proper places (separate
RUNTIME
/LIBRARY
/ARCHIVE
destinations) - verify that
set_target_properties(MagnumLibraryName PROPERTIES VERSION ${MAGNUM_LIBRARY_VERSION} SOVERSION ${MAGNUM_LIBRARY_SOVERSION})
is done in caseMAGNUM_BUILD_STATIC
is not set - verify that
set_target_properties(MagnumLibraryName PROPERTIES POSITION_INDEPENDENT_CODE ON)
is done in caseMAGNUM_BUILD_STATIC_PIC
is set - verify that
add_library(Magnum::LibraryName ALIAS MagnumLibraryName)
(or equivalent) is added to make the library visible for CMake subprojects
- add source files to
- Create a new
src/Magnum/LibraryName/Test/
directory:- add a
CMakeLists.txt
with pre-populated license header, add your name to it - verify that folder is correctly set for the
CMakeLists.txt
file (set(CMAKE_FOLDER "Magnum/LibraryName/Test")
) - conditionally
add_subdirectory()
it ifMAGNUM_BUILD_TESTS
is enabled
- add a
- Create a new
src/Magnum/LibraryName/LibraryName.h
header for forward declarations (if needed), add a file-level doc block withForward declarations for the @ref Magnum::LibraryName namespace
as brief docs- reference it from
doc/compilation-speedup.dox
- reference it from
- Create a new
src/Magnum/LibraryName/visibility.h
header withMAGNUM_LIBRARYNAME_EXPORT
andMAGNUM_LIBRARYNAME_LOCAL
macros by copypasting it from another library:- adapt
#ifdef MagnumLibraryName_EXPORTS
so it matches CMake target name - if the library is combined from an
OBJECT
library, add its name to the above#ifdef
as well (and then explicitly addtarget_compile_definitions(MagnumLibraryNameObjects PRIVATE "MagnumLibraryNameObjects_EXPORTS")
toCMakeLists.txt
in caseMAGNUM_BUILD_STATIC
is not set) - the macro does not contain the full namespace path but rather mirrors the library file name
- adapt
- Mention the directory and namespace in
doc/namespaces.dox
, basically copy-pasting the following from existing documentation:- directory-level doc block referencing the namespace
- namespace-level doc block mentioning the
MAGNUM_WITH_LIBRARYNAME
option, dependencies (if any) and a code snippet showing how to use it with CMake
- Code and test the rest of the library, see Checklist for adding / removing a new source / header file and Checklist for adding / removing a symbol for more information
- Add the
MAGNUM_WITH_LIBRARYNAME
option to all files in thepackage/ci
directory, explicitly saying eitherON
orOFF
based on platform support and whether it makes sense to enable it for given job if it's off by default, or disable it for given job if it's enabled by default:- all
package/ci/appveyor-*.bat
files (^
is a line continuation) - all
package/ci/
*.sh
files (\
is a line continuation)
- all
- Add the
MAGNUM_WITH_LIBRARYNAME
option to other files inpackage/
directory if it's off by default but it makes sense to include it in given package (such as, say, Audio which is off by default because it relies on OpenAL, but makes sense to be included on Linux and macOS because there it's easy to get OpenAL):- all
package/archlinux/PKGBUILD*
files (and the AUR package(s)) - all
package/msys/PKGBUILD*
files (and the AUR package(s)) - the
package/debian/rules
file (watch out, tabs!) - the
package/gentoo/
*.ebuild
file - the
package/homebrew/
*.rb
file (watch out, Ruby!)
- all
- If the library is enabled by default, disable it in
package/ci/
of depending projects if not needed for a particular job to save CI times - If the library has dependencies:
- make sure they are mentioned in the library documentation
- make sure they are mentioned in building and CMake docs
- make sure they are mentioned in
CREDITS.md
- make sure AppVeyor and CircleCI downloads them (based on platform support)
- Add the library to the graph in
doc/custom-buildsystem-order.dot
, listing also its depdendencies to the rest of the project - Mention the library in
doc/changelog.dox
(or similar files in other repos) - Build documentation:
- run doxygen.py on
Doxyfile-mcss
and verify there are no new warnings - eyeball the namespace and directory docs, fix suspicious things, look also in the building and cmake docs
- run doxygen.py on
- Build a coverage build (
package/archlinux/PKGBUILD-coverage
), or abuse the CI for that later - Push to a temporary branch (e.g.,
next
) - Iterate until the CIs are green and the code coverage is good enough
- Merge to
master
In order to remove a library, be sure to touch all places mentioned above, only in inverse — but usually deprecate first.
Checklist for adding / removing an application library
Similarly to Checklist for adding / removing a library except points 2 and 5, with:
- Update
FindMagnum.cmake
(replaces point 2 in Checklist for adding / removing a library):- mention the new lib in the list of components in the docs
- add its name to the
_MAGNUM_LIBRARY_COMPONENTS
regex - add a new
elseif(_component STREQUAL ApplicationName)
section with special setup of includes or dependencies or explicitly say# Name application has no additional dependencies
- Add a condition to
src/Magnum/Platform/CMakeLists.txt
:- add the source file to
MagnumApplicationName_SRCS
variable - add the installable header to
MagnumApplicationName_HEADERS
variable - add a
STATIC
MagnumApplicationName
library, verify that theadd_library()
command references all input files (needed so QtCreator lists all project files properly) - verify that debug postfix is set (
set_target_properties(MagnumApplicationName PROPERTIES DEBUG_POSTFIX "-d")
) - verify that folder is set to avoid cluttering project tree view in IDEs (
set_target_properties(MagnumApplicationName PROPERTIES FOLDER "Magnum/Platform")
) - verify that target installation is done in proper places (separate
RUNTIME
/LIBRARY
/ARCHIVE
destinations) - verify that
add_library(Magnum::ApplicationName ALIAS MagnumApplicationName)
is added to make the application visible for CMake subprojects
- add the source file to
- If desired, provide a new bootstrap project:
- new
base-applicationname
branch, forked from some_modules_*
branch, with the rest copied from a subset of e.g. thebase
branch - update
README.md
in master, mentioning this - update
package/ci
files to build this project (probably a new matrix entry)
- new
- Mention the bootstrap project in the class documentation
- Mention all extra files and setup in the class documentation
In order to remove an application library, be sure to touch all places mentioned above, only in inverse — but usually deprecate first.
Checklist for adding / removing a plugin
Similarly to Checklist for adding / removing a library except points 2 and 5, with:
- Update
FindMagnumPlugins.cmake
(orFindMagnum.cmake
in the core repo) (replaces point 2 in Checklist for adding / removing a library):- mention the new plugin in the list of components in the docs
- add its name to the
_MAGNUMPLUGINS_PLUGIN_COMPONENT_LIST
list - add a new
elseif(_component STREQUAL PluginName)
section with special setup of includes or dependencies or explicitly say# PluginName has no dependencies
- Create
PluginName.conf
and list all plugin dependencies (if any). The file has to be present even if empty. - Create
importStaticPlugin.cpp
by copypasting it from another plugin and adapting plugin name. This will get installed along with plugin headers to aid with automatic import. - Create
configure.h.cmake
for plugin-specific information about whether the library was built as static or not - Create a new
src/MagnumPlugins/PluginName/CMakeLists.txt
, copy over up-to-date license header from other CMake files and populate it (replaces point 5 in Checklist for adding / removing a library):- add source files to
PluginName_SRCS
variable - add installable headers to
PluginName_HEADERS
variable - add private headers to
PluginName_PRIVATE_HEADERS
variable (if any) - use
add_plugin()
command (which is aliased to either corrade_add_ plugin() or corrade_ add_ static_ plugin()) to create the PluginName
library, use${MAGNUM_PLUGINS_*_DEBUG_BINARY_INSTALL_DIR}
/${MAGNUM_PLUGINS_*_RELEASE_BINARY_INSTALL_DIR}
and${MAGNUM_PLUGINS_*_DEBUG_LIBRARY_INSTALL_DIR}
/${MAGNUM_PLUGINS_*_RELEASE_LIBRARY_INSTALL_DIR}
variables that correspond to given plugin interface - verify that both
add_library()
andadd_plugin()
commands reference all input files (needed so QtCreator lists all project files properly) - verify that folder is set for all other targets to avoid cluttering project tree view in IDEs (
set_target_properties(PluginExtraTarget PROPERTIES FOLDER "MagnumPlugins/PluginName")
) — for the plugin library it's done automatically insideadd_plugin()
- verify that
set_target_properties(PluginName PROPERTIES POSITION_INDEPENDENT_CODE ON)
is done in caseMAGNUM_BUILD_STATIC_PIC
is set - verify that in case of
MAGNUM_BUILD_PLUGINS_STATIC
theimportStaticPlugin.cpp
file is installed is set and that an absolute* path to it is added totarget_sources()
- verify that
add_library(MagnumPlugins::PluginName ALIAS PluginName)
(or equivalent) is added to make the library visible for CMake subprojects
- add source files to
- If there is more than one interface header (other than just
PluginName.h
being installed), add a newvisibility.h
header. Otherwise put the visibility macros directly inPluginName.h
. - If the plugin handles a new format:
- if the plugin is not named directly after the format, add an alias to it (for example the MiniExrImageConverter plugin is aliased to
OpenExrImageConverter
) - update the AnyImageImporter, AnySceneImporter, AnyImageConverter or AnyAudioImporter plugins to delegate to this plugin (or its alias) upon encountering corresponding file extension
- if the plugin is not named directly after the format, add an alias to it (for example the MiniExrImageConverter plugin is aliased to
In order to remove a plugin, be sure to touch all places mentioned above, only in inverse — but usually deprecate first.
Checklist for adding / removing a plugin interface
In order to remove a plugin interface, be sure to touch all places mentioned above, only in inverse — but usually deprecate first.
Checklist for updating a plugin interface
When updating a plugin interface, the interface string (and thus also the interface string in all plugin implementations) should be updated if any of the following cases apply:
- Bump major version if the plugin usage changes significantly (and thus most user code changes as well), for example when renaming a "open file" method
- Bump only the minor version if signature of some methods change, potentially requiring changes in user code, for example when porting from std::
string to Containers:: StringView - Bump only the patch version if the change doesn't affect existing user code but breaks ABI, for example when adding a new virtual function — this is mainly to prevent crashes when loading of plugins built against an older interface. A rather exhaustive list of ABI-affecting changes is in the KDE Community Wiki: https://community.kde.org/Policies/Binary_
Compatibility_ Issues_ With_ C%2B%2B
Checklist for updating the <tt>Trade::AbstractImporter</tt> plugin interface
- Newly added
do*()
APIs need to be also handled in all proxies: - Newly added data types need to be reflected in all APIs operating with whole importers:
- Newly added Trade::
ImporterFlag values need to be reflected in: - All plugins that may make use of them, together with documenting if they're recognized
- New command-line options in magnum-sceneconverter / magnum-imageconverter
- It's highly likely that APIs added to / changed in the importer will also need a corresponding change in Trade::
AbstractImageConverter and Trade:: AbstractSceneConverter
Checklist for updating the <tt>Trade::AbstractImageConverter</tt> plugin interface
- Newly added
do*()
APIs need to be also handled in all proxies: - Corresponding changes in magnum-imageconverter and possibly also magnum-sceneconverter
- Newly added Trade::
ImageConverterFlag values need to be reflected in: - All plugins that may make use of them, together with documenting if they're recognized
- New command-line options in magnum-sceneconverter / magnum-imageconverter
- It's highly likely that APIs added to / changed in the image converter will also need a corresponding change in Trade::
AbstractSceneConverter
Checklist for updating the <tt>Trade::AbstractSceneConverter</tt> plugin interface
- Newly added
do*()
APIs need to be also handled in all proxies: - Corresponding changes in magnum-sceneconverter
- Newly added Trade::
SceneConverterFlag values need to be reflected in: - All plugins that may make use of them, together with documenting if they're recognized
- New command-line options in magnum-sceneconverter
- Translation to Trade::
ImageConverterFlag in plugins that proxy image conversion to image converter plugins
Checklist for adding / removing a tool
In order to remove a tool, be sure to touch all places mentioned above, only in inverse — but usually deprecate first.
Checklist for adding / removing an example
- Add a
MAGNUM_WITH_EXAMPLENAME_EXAMPLE
CMake option to:- root
CMakeLists.txt
- the list in
doc/building-examples.dox
- root
- Add a new
src/example-name
directory, copy up-to-date UNLICENSE headers from other files in the repo - Verify that
src/example-name/CMakeLists.txt
containscmake_minimum_required()
,project()
and allcmake_policy()
commands so it can be used as a top-level project level - If the example needs extra code to run on non-desktop platforms (and running on non-desktop platforms is not the primary goal), consider moving them to the
ports
branch to keep code inmaster
as simple as possible - Add a new
doc/example-name.dox
page with@brief
,@m_footernavigation
and@page
name equivalent to filename - Add a new
doc/example-name.png
image, scaled down to 400x300 from 800x600, reference it as@image html example-name.png
from the*.dox
file - In case there's a web demo, add a button link to it (copy over other example pages and adapt)
- Add a new
examples-examplename-source
section with:- link to GitHub
- referencing all textual example sources as
- @ref example-name/file.ext "file.ext"
- breadcrumb and navigation setup for all example sources as
@example example-name/file.ext @m_examplenavigation{examples-example-name,example-name/} @m_footernavigation
- Update
doc/example-index.dox
and list the example there, optionally adding a badge to advertise the web demo - Mention the example in
doc/changelog-examples.dox
- Push to a temporary branch (e.g.,
next
orports-next
) - Iterate until the CIs are green
- Merge to
master
/ports
In order to remove an example, be sure to touch all places mentioned above, but in inverse.
Checklist for adding / removing a new source / header file
- Copy over a up-to-date license header (note that example code uses UNLICENSE instead of MIT) and add your name + year to it, if not already there
- Add a
@file
-level documentation block, with@brief
listing all classes, functions, typedefs, enums, macros etc. that are in the file - Annotate it with a correct variant of the
@m_since_latest
command for given repository - Add the file to corresponding
*_SRCS
,*_HEADERS
,*_PRIVATE_HEADERS
list inCMakeLists.txt
- If applicable, add a new test class file in the
Test/
directory- name it
FileNameTest.cpp
, put a class namedFileNameTest
inside, wrapped in aTest
subnamespace of the original file namespace - use
corrade_add_test()
to add it to tests - if some tests need GL context, add a separate test with
GLTest
suffix, wrapping the correspondingcorrade_add_test()
inif(MAGNUM_BUILD_GL_TESTS)
- name it
- Populate the file, see Checklist for adding / removing a symbol and Coding style for more information.
- Mention the new functionality in
doc/changelog.dox
(and similar files in other repos) - Build documentation:
- run doxygen.py on
Doxyfile-mcss
and verify there are no new warnings - eyeball the relevant docs and fix suspicious things
- run doxygen.py on
- Build a coverage build (
package/archlinux/PKGBUILD-coverage
), or abuse the CI for that later - Push to a temporary branch (e.g.,
next
) - Iterate until the CIs are green and the code coverage is good enough
- Merge to
master
In order to remove a file, be sure to touch all places mentioned above, only in inverse — but usually deprecate first.
Checklist for adding / removing a symbol
- If the symbol is standalone (i.e., not member of a class), list it in the
@file
-level@brief
docs - Document it
- Annotate it with a correct variant of the
@m_since_latest
command for given repository - Add a test for it to corresponding file, verify the test gets actually run
- Mention the new functionality in
doc/changelog.dox
(and similar files in other repos) - Build documentation:
- run doxygen.py on
Doxyfile-mcss
and verify there are no new warnings - eyeball the relevant docs and fix suspicious things
- run doxygen.py on
- Build a coverage build (
package/archlinux/PKGBUILD-coverage
), or abuse the CI for that later - Push to a temporary branch (e.g.,
next
) - Iterate until the CIs are green and the code coverage is good enough
- Merge to
master
In order to remove a symbol, be sure to touch all places mentioned above, only in inverse — but usually deprecate first.
Checklist for adding a new CMake documentation page
- Add a
doc/pagename.dox
file, copy up-to-date license header and add your name + year to it, if not already there - If the page is top-level, list it in
doc/00-page-order.dox
to ensure it gets listed at a proper place - If the page is not top-level, list it using
@subpage
in its parent page and add@m_footernavigation
for automatic linking to parent and prev/next pages - Add a
@brief
documentation, if applicable - Populate it, see Coding style for more information
- Mention the new page in
doc/changelog.dox
(and similar files in other repos) - Build documentation:
- run doxygen.py on
Doxyfile-mcss
and verify there are no new warnings - eyeball the relevant docs and fix suspicious things
- run doxygen.py on
- Push to
master
Checklist for deprecating a feature
- If the feature is publicly exposed, think about the best way of deprecation that preserves source compatibility:
- Add a compatibility
typedef
/using
for a renamed symbol, marking it with CORRADE_DEPRECATED() / CORRADE_ DEPRECATED_ ALIAS() - Add a compatibility header for a renamed include, including the original file from it and marking it with CORRADE_
DEPRECATED_ FILE(). Ensure the file is not included from anywhere else anymore, since that would mean the user then gets spammed with more than just one warning per included file. This macro also can't easily be disabled on most platforms. - Add a compatibility inline function for a function that got renamed or its arguments changed, mark it with CORRADE_
DEPRECATED() - Add a compatibility enum value for a value that got renamed or deleted, mark it with CORRADE_
DEPRECATED_ ENUM() - Don't ever change semantics of function arguments without changing the function signature. That would silently break with no possibility to let the user know.
- Function return type changes are hard. One possibility is working around that by returning a wrapper type that's implicitly convertible to both the old and new type, another is introducing a differently named function instead. The last resort is breaking the API without preserving backwards compatibility — but that makes people angry, so avoid that if possible.
- Add a compatibility
- Add just a
@brief @copybrief
from the replacement functionality together with a@deprecated
line to the deprecated feature - Reference the replacement functionality in both the deprecation macro and in the
@deprecated
line to make porting easier - Ensure the deprecated symbol is wrapped in
#ifndef MAGNUM_BUILD_DEPRECATED
, - Ensure deprecated files
#error
in case they get used in non-deprecated build, ensure they are not installed in non-deprecated builds - Build all tests and dependent projects and verify that:
- using the old functionality still compiles and works as intended
- deprecation warnings are emitted in proper places
- Upon verifying the above, start updating dependent code
- Mention the deprecated API in the deprecation section of
doc/changelog.dox
(and similar files in other repos) - Build documentation:
- run doxygen.py on
Doxyfile-mcss
and verify there are no new warnings - eyeball the relevant docs and fix suspicious things
- run doxygen.py on
- Push to a temporary branch (e.g.,
next
) - Iterate until the CIs are green
- Merge to
master
- If possible, trigger builds of dependent projects (where they are still using the old API) and verify they are still green (and red in non-deprecated build)
- Update dependent projects
Checklist for deprecating a whole library
- If there's no compatible replacement (for example when removing support for an outdated toolkit), think about possible alternatives, external libraries or other ways to reach the same goal.
- Add deprecation notes, listing alternatives
- to docs of the whole namespace and all its members
- to docs of the directory and all files inside
- to all feature overview pages
- to each symbol using one of the CORRADE_
DEPRECATED() macros, with a shorter note mentioning alternatives - ensure each public headers (transitively) contains exactly one CORRADE_
DEPRECATED_ FILE() macro to warn the user exactly once about including a deprecated header — in particular, putting it in every file would spam the user way too much - since the files are still compiled and included by the library, wrap it in
#ifndef _MAGNUM_DO_NOT_WARN_DEPRECATED_LIBRARYNAME
and#define
this macro in all*.cpp
files and tests to avoid spamming the compiler log - an
#error
to each header file in case MAGNUM_BUILD_ DEPRECATED is not enabled - wrap contents of every header, source and test file in CORRADE_
IGNORE_ DEPRECATED_ PUSH and CORRADE_ IGNORE_ DEPRECATED_ POP to avoid warnings when compiling the library itself (no, this doesn't disable warnings for library users) - a
message(FATAL_ERROR)
to correspondingCMakeLists.txt
in case MAGNUM_BUILD_ DEPRECATED is not enabled - a deprecated label next to the
MAGNUM_WITH_*
CMake option in the correspondingdoc/building.dox
page and next to the CMake component name in the correspondingdoc/cmake.dox
page (and similar files in other repos), possibly also to all pages that list it (if any)
- If the library was enabled by default, make it disabled by default. Update relevant sections in
doc/building.dox
anddoc/cmake.dox
. - Include the library component in the corresponding
Find
module component list only if MAGNUM_BUILD_ DEPRECATED is enabled. - Remove the deprecated library from all packages except developer
PKGBUILD
s and CIs, remove also its no-longer-needed dependencies from these packages - Verify no other libraries, projects or examples depend on given library anymore. If they do:
- rework examples to not use the deprecated functionality anymore
- if there are dependencies in other libraries or projects, make the related features deprecated in the same manner, building them only if MAGNUM_
BUILD_ DEPRECATED is enabled - update corresponding
Find
modules to require dependency on this library only if MAGNUM_BUILD_ DEPRECATED is enabled
- Verify no CIs in dependent projects have this library enabled. If they do, it should be only if MAGNUM_
BUILD_ DEPRECATED is enabled and only if there is a (deprecated) feature depending on this library. - Mention the deprecated library in the deprecation section of
doc/changelog.dox
(and similar files in other repos), note the alternatives and note that it's no longer built by default or included in any packages (in case it was before)
Checklist for removing a feature
- Check that it was in deprecated state for more than a year with at least one release in between. Check that no important clients depend on it anymore. If not, wait a bit more.
- Remove relevant blocks wrapped in
#ifndef MAGNUM_BUILD_DEPRECATED
, remove relevant deprecated files and updateCMakeLists.txt
- Mention the removed API in the compatibility section of
doc/changelog.dox
(or similar files in other repos) - Build documentation:
- run doxygen.py on
Doxyfile-mcss
and verify there are no new warnings — sometimes it happens that a deprecated API is still being referenced
- run doxygen.py on
- Push to a temporary branch (e.g.,
next
) - Iterate until the CIs are green
- Merge to
master
- If possible, trigger builds of dependent projects and verify they are still green (or wait for the scheduled builds)
Checklist for adding a new mesh attribute
- Extend Trade::
MeshAttribute with the new entry - Add a corresponding reserved type to Shaders::
GenericGL, if not there already - Also update
src/Magnum/Shaders/generic.glsl
with the reserved ID
- Also update
- Update the type assertion in the Trade::
MeshAttributeData constructor to account for the new type - Add a pair of convenience getters to Trade::
MeshData similar to e.g. Trade:: MeshData:: normalsInto() / Trade:: MeshData:: normalsAsArray() with a type that's the same as the one used in the Shaders:: GenericGL definition, test that it does the right thing for every supported type - Update Trade::
operator<<(Debug&, MeshAttribute) for the new entry - Update MeshTools::
compile() to recognize the new attribute. If there is already a builtin shader capable of using this attribute, add new test to MeshToolsCompileGLTest
. - Push to a temporary branch (e.g.,
next
) - Iterate until the CIs are green
- Merge to
master
Checklist for adding a new vertex format
- Extend VertexFormat with the new entry, if it's not there already, document mapping to GL, Vulkan, D3D and Metal (if exists)
- Update docs of Trade::
MeshAttribute to mention where the format can be newly used - Appropriately relax the assertion in the Trade::
MeshAttributeData constructor
- Extend
Trade::Implementation::vertexFormatFor()
, add a mapping between this entry and a C++ type, optionally alsoisVertexFormatCompatibleWithAttribute()
if there's more than one entry corresponding to a particular C++ type. If the mapping is unconventional, be sure to mention it in the Trade::MeshAttributeData:: MeshAttributeData(MeshAttribute, const Containers:: StridedArrayView1D<T>&, Int) constructor docs. - Update corresponding
Trade::MeshData::*Into()
convenience getters to ensure they can handle this type - Update
src/Magnum/Implementation/vertexFormatMapping.hpp
andsrc/Magnum/Vk/Implementation/vertexFormatMapping.hpp
with the new entry - Update vertexFormatSize(), vertexFormatComponentFormat(), vertexFormatComponentCount() and isVertexFormatNormalized() to handle this format
- Update the GL::
hasVertexFormat() utility and GL:: DynamicAttribute:: DynamicAttribute(Kind, UnsignedInt, VertexFormat) constructor to provide mapping of the new type to GL; add a test for the new type, if it's special in some way, otherwise the all-catching loop will check it - Update MeshTools::
compile() to recognize the new type (if anything extra needs to be done, usually doesn't as everything is handled by GL:: DynamicAttribute already); add corresponding new test(s) to MeshToolsCompileGLTest
. - Push to a temporary branch (e.g.,
next
) - Iterate until the CIs are green
- Merge to
master
Checklist for adding / removing GL extensions
- Add new extensions to the GL, GLES and WebGL sections of
src/Magnum/GL/Extensions.h
- Order them by extension ID that is mentioned in every extension spec file. If the extension isn't in the official Khronos registry (such as various ANGLE extensions), at it at the end of the range.
- Update the numbering to stay monotonic and unique, round up start index of next section to nearest ten to make the updates bearable
- In case there's a lot of new extensions,
Implementation::ExtensionCount
might needed to be increased.
- Add them alphabetically ordered to the correct list in
src/magnum/GL/Context.cpp
- run GL, ES2, ES3, WebGL1 and WebGL2 build of
GLContextTest
to verify everything is still okay - run GL, ES2, ES3, WebGL1 and WebGL2 build of
magnum-gl-info
- the extension should be listed unless it's not available on given GL flavor
- and also marked as supported unless the machine doesn't support it (cross-check with
--extension-strings
)
- run GL, ES2, ES3, WebGL1 and WebGL2 build of
- Get flextGL and go to
src/MagnumExternal/OpenGL/
:- Add/remove extensions in
GL/extensions.txt
,GLES2/extensions.txt
,GLES2/Emscripten/extensions.txt
,GLES3/extensions.txt
,GLES3/Emscripten/extensions.txt
, in the same order as insrc/Magnum/GL/Extensions.h
- For GLES and WebGL extensions, if they aren't in the official Khronos registry (such as various ANGLE extensions), check if they're in ANGLE's gl_
angle_ ext.xml at least. If not, like with core WebGL functionality that has no match in the base GLES spec, you may need to craft your own XML file. See src/MagnumExternal/OpenGL/GLES3/webgl.xml
for an example. - WebGL extensions usually have a GLES extension as a base, but then may remove certains entrypoints from it. If that's the case, add it to the function blacklist at the end of the Emscripten-specific files.
- Run
./update-flextgl.sh
to update everything. Reason there is so many variants of the files are the following:- Desktop GLES on Windows still links to the ancient
opengl32.dll
which exports only OpenGL 1.1 symbols, so we have a special set of headers that queries pointers for everything above OpenGL 1.1 (instead of everything above OpenGL ES 2.0). - iOS, on the other hand, doesn't have any extension loader mechanism and all supported entrypoints are exported from the library, so we set the function pointers to those exported symbols in case the system GL header defines them.
- Emscripten doesn't have the ability to manually load extension pointers either, thus it has only header files.
- Desktop GLES on Windows still links to the ancient
- Add/remove extensions in
- Check
git diff
for suspicious changes and whitespace-at-EOL- If any extensions don't add any useful symbols, comment them out in the
extensions.txt
files and regenerate to avoid needless bloat
- If any extensions don't add any useful symbols, comment them out in the
- For every new function that appeared in the regenerated extension headers, add an entry to
doc/opengl-mapping.dox
- For every new added limit query that appeared in the regenerated extension headers (various
GL_MIN_*
andGL_MAX_*
macros etc.), add an entry to the bottom ofdoc/opengl-mapping.dox
- Add new extensions to the general GL, GLES and WebGL lists in
doc/opengl-support.dox
, again matching the order inExtensions.h
— grouped by prefix, but then ordered by extension number
In order to remove GL functionality, be sure to touch all places mentioned above, only in inverse — but usually deprecate first, unless it doesn't affect public API at all.
Checklist for adding / removing GL versions
- Add new version enum value:
- to
src/Magnum/GL/Version.h
- to debug output in
src/Magnum/GL/Version.cpp
- to
GL::Extension::extensions()
insrc/Magnum/GL/Context.cpp
- to
GL::Context::tryCreate()
insrc/Magnum/GL/Context.cpp
- to specify GLSL version in
src/Magnum/GL/Shader.cpp
- to the list in
src/Magnum/Platform/gl-info.cpp
- to the test in
src/Magnum/GL/Test/ContextTest.cpp
- to
- Update existing extensions with version in which they became core (last parameter of the
_extension()
macro insrc/Magnum/GL/Extensions.h
) - Go to
src/MagnumExternal/OpenGL/
, bump versions inGL/extensions.txt
,GLES2/extensions.txt
,GLES2/Emscripten/extensions.txt
,GLES3/extensions.txt
,GLES3/Emscripten/extensions.txt
- Continue with Checklist for adding / removing GL extensions for all extensions that were added by the new version and were not already present
- For all existing extensions APIs that lose their suffix in the new version, update doc references to be without the suffix
- Add a table listing the new version and all new extensions in it to
doc/opengl-support.dox
(take a list of them from the changelog in the official spec PDF). Some extensions might be already present in the general extension list, move them out of there. - Add a new
requires-glXY
,requires-glesXY
orrequires-webglXY
page with@m_footernavigation
todoc/opengl-support.dox
, mention it as a@subpage
at a correct position in the list - Add a new
requires-glXY
,requires-glesXY
orrequires-webglXY
alias toDoxyfile
,Doxyfile-mcss
andDoxyfile-public
, copypaste it from existing and change the numbers
In order to remove GL functionality, be sure to touch all places mentioned above, only in inverse — but usually deprecate first, unless it doesn't affect public API at all.
Checklist for adding / removing GL functionality
- Check if given desktop functionality has equivalent in ES or WebGL:
- check for similarly named APIs in
MagnumExternal/OpenGL/GLES2/flextGL.h
and others - if not there or if there only in a core version and not an extension, the extension may not be included — check the cached
spec/gl.xml
file inside the flextGL clone - for WebGL it might also be ANGLE-only, look for it in https:/
/ chromium.googlesource.com/ angle/ angle/ +/ refs/ heads/ main/ extensions - add missing extensions as described in Checklist for adding / removing GL extensions
- check for similarly named APIs in
- Check if there's a DSA / non-DSA way to do the thing. Omit the non-DSA way if all drivers that support given functionality support DSA as well (i.e., the functionality was not introduced before DSA became core) and there's no corresponding non-DSA functionality in ES or WebGL.
- If the functionality uses different entry points / defines on desktop and ES / WebGL platforms, use
#ifdef MAGNUM_TARGET_GLES
,#ifdef MAGNUM_TARGET_GLES2
and#ifdef MAGNUM_TARGET_WEBGL
to cover the differences - If the functionality can use different entry points based on driver capabilities on the same platform (DSA / non-DSA is one of them), add separate code paths:
- new private and
MAGNUM_LOCAL
thingImplementation*()
functions, each implementing one code path, preferablystatic
- ideally make the signature in a way that makes it possible to just call the GL API directly via a function pointer and have
thingImplementation*()
only for fallbackse - a
thingImplementation
(member) function pointer insrc/Magnum/Implementation/SomeState.h
that gets populated insrc/Magnum/GL/Implementation/SomeState.cpp
based on extension / version availability - a public function, dispatching to
Context::current().state().some->thingImplementation
in the implementation
- new private and
- If the functionality is a limit query, add a cache for it:
- a member variable that's either set to
0
or Corrade::Containers:: NullOpt in src/Magnum/Implementation/SomeState.cpp
- the query first checks for presence of cached value and queries it only if not cached yet
- in case the limit query depends on some extension which might not be available, return some reasonable value (
0
) in that case
- a member variable that's either set to
- Implement the functionality (see Checklist for adding / removing a new source / header file, Checklist for adding / removing a symbol)
- Document the functionality
- if important, describe the different code paths (DSA / non-DSA) or functionality fallbacks
- list the DSA / non-DSA distinction among function list in the class-level docs
- a
@see
block listing GL APIs used with@fn_gl{}
,@def_gl{}
etc., use@fn_gl_keyword{}
etc. to expose them in search if desired (see Links to related OpenGL, Vulkan, OpenAL functions and definitions) - list version / extension requirements using
@requires_glXY
etc. (see Classes and functions requiring specific OpenGL, Vulkan, OpenAL version or extensions), check how similar requirements are listed elsewhere and try to match that
- Add the function or limit query to the mapping table in
doc/opengl-mapping.dox
, possibly to multiple places - Update relevant extension support in tables in
doc/opengl-support.dox
- Mention the new stuff in
doc/changelog.dox
- Build documentation:
- run doxygen.py on
Doxyfile-mcss
and verify there are no new warnings - eyeball the relevant docs and fix suspicious things
- make sure links to GL APIs and extensions are working
- run doxygen.py on
- Build and test for relevant platforms locally (as the public CI can't test GL things in full, only the ES subset)
- Push to a temporary branch (e.g.,
next
) - Iterate until the CIs are green
- Merge to
master
In order to remove GL functionality, be sure to touch all places mentioned above, only in inverse — but usually deprecate first, unless it doesn't affect public API at all.
Checklist for adding / removing a driver workaround
- Put a descriptive string with even more descriptive comment into the
KnownWorkarounds
array insrc/Magnum/GL/Implementation/driverSpecific.cpp
, ideally reuse some of the already existing vendor prefixes - If the workaround can be tied down to a particular platform / target, add appropriate
#ifdef
around it - Create (or extend) a pair of (member)
private
MAGNUM_LOCAL
*Implementation*()
functions in the affected class,*ImplementationDefault()
having the optimistic default behavior, the other having the workaround. Add the appropriate#ifdef
around, if any. - Add a new (member) function pointer in
src/GL/Implementation/SomeState.h
and call it from the affected class instead of executing the implementation directly. Add the appropriate#ifdef
around, if any. - Add a branch into
src/GL/Implementation/SomeState.cpp
(with appropriate#ifdef
around, if any). First check for driver and other circumstances and call the!context.isDriverWorkaroundDisabled("the-workaround-string")
last after you are really sure you need to use it — calling this function will append the workaround string to the engine startup log and it's not desirable to list workarounds that weren't used. - Test the affected functionality with the workaround enabled and verify it works
- Disable the workaround using
--magnum-disable-workarounds
on command-line and verify it's still broken — if not, there's something off! - Add a changelog entry.
- Verify the driver workaround is listed in the snippet in Driver workarounds
Removeing a workaround is simply a matter of searching for its string, removing all occurrences of that string and removing all *Implementation*()
functions that were used only if the workaround was in place. No need to deprecate anything, users explicitly disabling given workaround will only be informed that such workaround does not exist anymore.
Checklist for adding / removing OpenAL versions and extensions
In order to remove OpenAL functionality, be sure to touch all places mentioned above, only in inverse — but usually deprecate first, unless it doesn't affect public API at all.
Checklist for adding / removing OpenAL functionality
In order to remove OpenAL functionality, be sure to touch all places mentioned above, only in inverse — but usually deprecate first, unless it doesn't affect public API at all.
Checklist for adding / removing Vulkan extensions
- Add new extensions to
src/Magnum/Vk/Extensions.h
- there's a separate list for instance and device extensions, ensure each is in the right list
- order them by extension ID that is mentioned on every extension spec page
- update the numbering to stay monotonic and unique, round up start index of next section to nearest ten to make the updates bearable
- in case there's a lot of new extensions,
Implementation::InstanceExtensionCount
inInstance.h
/Implementation::DeviceExtensionCount
inDevice.h
might need to be increased
- Add them alphabetically ordered to the correct list in
src/Magnum/Vk/Extensions.cpp
- run
VkExtensionsTest
to verify everything is still okay - run
magnum-vk-info
, the extension should be listed and also marked as supported, unless the machine doesn't support it (cross-check with--extension-strings
)
- run
- Get flextGL and go to
src/MagnumExternal/Vulkan/
:- Add/remove extensions in
extensions.txt
, in the same order as insrc/Magnum/Vk/Extensions.h
- Run
./update-flexgl.sh
to update everything
- Add/remove extensions in
- Check
git diff
for suspicious changes and whitespace-at-EOL- If any extensions don't add any useful symbols, comment them out in the
extensions.txt
file and regenerate to avoid needless bloat
- If any extensions don't add any useful symbols, comment them out in the
- For every new added function and structure, add an entry to
doc/vulkan-mapping.dox
- For every new
*Feature
structure, expand the Vk::DeviceFeatures enum according to Checklist for adding Vulkan features - Add new extensions to the general list in
doc/vulkan-support.dox
, again matching the order inExtensions.h
— grouped by prefix, but then ordered by extension number
In order to remove Vulkan functionality, be sure to touch all places mentioned above, only in inverse — but usually deprecate first, unless it doesn't affect public API at all.
Checklist for adding / removing Vulkan versions
- Add new version enum value:
- to
src/Magnum/Vk/Version.h
- to the list in
src/Magnum/Vk/vk-info.cpp
- to
Vk::InstanceExtension::extensions()
andVk::Extension::extensions()
insrc/Magnum/Vk/Extensions.cpp
- to
- Update existing extensions with version in which they became core (last parameter of the
_extension()
macro) - Continue with Checklist for adding / removing Vulkan extensions for all extensions that were added by the new version and were not already present
- For all existing extensions APIs that lose their suffix in the new version, update doc references to be without the suffix
- Add a table listing the new version and all new extensions in it to
doc/vulkan-support.dox
(take a list of them from the changelog in the official spec). Some extensions might be already present in the general extension list, move them out of there. - Add a new
requires-vkXY
page with@m_footernavigation
todoc/vulkan-support.dox
, mention it as a@subpage
at a correct position in the list - Add a new
requires-vkXY
alias toDoxyfile
,Doxyfile-mcss
andDoxyfile-public
, copypaste it from existing and change the numbers
In order to remove Vulkan functionality, be sure to touch all places mentioned above, only in inverse — but usually deprecate first, unless it doesn't affect public API at all.
Checklist for adding / removing Vulkan functionality
In order to remove Vulkan functionality, be sure to touch all places mentioned above, only in inverse — but usually deprecate first, unless it doesn't affect public API at all.
Checklist for Vulkan CreateInfo wrappers
- A
ThingCreateInfo
structure and its dependencies that aren't needed byThing
itself should be in a dedicatedThingCreateInfo.h
header, and including theThing.h
at the end for convenience - Every class should have a
Flag
andFlags
members even if the spec lists no usable flags, exception is the rare structures that don't have anyflags
member (Vk::MemoryAllocateInfo, until Vulkan 1.1 at least) - The main constructor(s) should explicitly list what structure fields are filled to which value, and if the constructor isn't enough to get a working state, it should also clearly mention what needs to be done next
- For everything non-essential or what isn't practical to be set in constructor a setter should be added. If applicable, document what subsequent calls to the same function result in (for example when a list gets cleared while all other functions append to lists). The docs should again list what underlying structure fields are set to which value.
- Every class should have a NoInitT constructor, which keeps the structure uninitialized and doesn't allocate any internal state
- Every class should have a constructor taking the underlying Vulkan structure, it should not allocate either but instead reference the original data
- Every class should provide a set of
operator*()
,operator->()
and their const variants providing direct access to the underlying Vulkan structure - Every class should have a
operator const VkThing*() const
that returns a pointer to the underlying Vulkan structure for convenient use directly invkCreate*()
APIs (or alternatively returning a reference, if the structure is commonly used in arrays as is the case with Vk::AttachmentReference for example) - Classes should be implicitly copyable, with no copy/move constructors, destructor or copy/move assignments listed. If a class needs to store some heap-allocated state (such as Vk::
FramebufferCreateInfo image view handles), it should be made move-only with the other._info
members pointing to the stolen state cleared so the old instance doesn't reference state that's owned by something else after the move.- Additionally, if a move-only class needs to be itself moved into a containing structure (such as Vk::
SubpassDescription inside a Vk:: RenderPassCreateInfo), all its setters should have &
and&&
overloads so it can be set up completely and passed to its destination in a single expression without any explicit std::move(). The overloads can be tested for correctness rather easily, see RenderPassTest::subpassDescriptionRvalue()
for an example.
- Additionally, if a move-only class needs to be itself moved into a containing structure (such as Vk::
Checklist for Vulkan extension-dependent code paths
Every time an extension-dependent code path is expected to be used several times (such as render pass creation, but not one-time device property query, for example), it should be implemented through a *Implementation*()
function pointers on a class that needs them:
- The
*Implementation()
functions should be suffixed depending on version / extension that adds them (so e.g.ImplementationDefault
,ImplementationKHR
,Implementation12
) - The implementation should be
MAGNUM_VK_LOCAL
andstatic
, taking the class viaType& self
if necessary. This avoids extra overhead coming from member function pointers and doesn't require an#include
of the full type on MSVC in order to avoid ABI issues (as insane as it sounds, MSVC member function pointer size is different depending if the type is incomplete or not, causing hard-to-debug crashes). - Their API should match the latest functionality and doing compatibility steps for previous versions, not the other way around (so for example extracting "version 1" structures from "version 2" in order to call the default functionality)
- The return value of the concrete Vulkan call should be always propagated upwards with a
return
, even if the call returnsvoid
, and the call site should be wrapping it in a MAGNUM_VK_ INTERNAL_ ASSERT_ SUCCESS(). This is preferred over having the assert repeated for each code path, as it generates less code. Implementation::InstanceState
/Implementation::DeviceState
then contains the dispatching function pointer, choosing the appropriate version based on what version and extensions are available.- Finally, the extension should be implicitly enabled during instance / device creation as appropriate — for example, if the extension is core in 1.2, the extension should be enabled only on 1.1 and below.
Checklist for adding Vulkan features
- For every new
VkPhysicalDevice*Features
structure, add its boolean members to the Vk::DeviceFeature enum. There are headings referring the full VkPhysicalDevice*Features
structure name and either the version or extension number, put the new members under a new heading at a correct place. - Formulate the documentation to start with "Whether" and replace verbose phrases like "the implementation supports ..." from the spec with "... is supported".
- Add a
@see
block, referencing related features if applicable, crossreference the newly added value from the values it refers to as well - Reference the extension / version it was added in via
@requires_vkXY
- If APIs depending on this feature are already exposed, reference the feature from those
- Add the new members to
Magnum/Vk/Implementation/deviceFeatureMapping.hpp
to the correct place with a_cver()
or_cext()
macro as appropriate - Extend
Magnum/Vk/Implementation/DeviceFeatures.h
with the new feature struct, added to relatively the same place as in the enum header - Extend Vk::
DeviceProperties:: features(): - connecting the new structure to the chain, insert to the correct place again,
- expand the function docs to mention the new structure (again correct order),
- verify that the features were fetched correctly (and especially that a correct structure type was set) with magnum-vk-info — (a subset) the new features should be shown as supported and especially everything after still looks the same as it looked before. For some reason the Khronos validation layer doesn't check
sType
fields in this query so it's easy to make a hard-to-discover error
- Extend Vk::
DeviceCreateInfo:: setEnabledFeatures(): - a similar addition as above, connecting the structure to the chain at correct place,
- to the correct place in the structureChainDisconnect() call,
- and function documentation again
- Add a link to the new Feature structure in
doc/vulkan-mapping.dox
Checklist for adding, removing or updating a dependency
- Verify that there are no important clients stuck on the old version with no easy way to upgrade
- Corrade's root
CMakeLists.txt
(andUseCorrade.cmake
) contains checks for minimal CMake and compiler version, together with a comment explaining which distribution / system has the minimal version.
- Corrade's root
- In case of CMake:
- it's usually possible to jump more than one version, check what's the version on the oldest supported system
- bump all
cmake_minimum_required()
in all repos - remove
cmake_policy()
calls that are not needed anymore - remove old workarounds, check changelogs for functionality that can be used now
- update building docs to say what version is required now
- add an entry to the dependencies section in
doc/changelog.dox
- update
package/ci/
*.yml
to download a newer version, possibly removing 32-bit compat libraries
- In case of a compiler:
- remove everything related to
CORRADE_GCCXY_COMPATIBILITY
of the old version, if applicable - update building docs to say what version is required now
- add an entry to the dependencies section in
doc/changelog.dox
- update files in
package/ci/
to use a newer version
- remove everything related to
- In case given dependency is external:
- Create a dedicated
Find*.cmake
module and does not have a builtin one in CMake - update packages in
package/
to depend on the new library - update files in
package/ci/
to install it
- Create a dedicated
- In case given dependency is single-file:
- verify it's reasonably small (<50kB is okay,
nlohmann/json
is a prime example of not okay) - add it to
src/external/
without any modifications except for trailing whitespace cleanup - add it in a separate Git commit, mentioning its version (or Git hash) for easier upgrades later
- verify it's reasonably small (<50kB is okay,
- Update
CREDITS.md
of affected repo to mention the added/removed dependency, its homepage and its license
In order to remove a dependency, be sure to touch all places mentioned above, only in inverse.
Checklist for adding or removing a port
- Add a new
TARGET_*
variable:- to root
CMakeLists.txt
, which either gets enabled automatically based on system introspection or is exposed through anoption()
command - to the list of variables extracted out of
configure.h
inmodules/FindMagnum.cmake
- to root
- Add a
MAGNUM_TARGET_*
variable:- set it in root
CMakeLists.txt
in caseTARGET_*
is enabled - add it as a
#cmakedefine
macro tosrc/Magnum/configure.h.cmake
- add documentation for it to
src/Magnum/Magnum.h
- mention it in
modules/FindMagnum.cmake
docs - mention it in
doc/cmake.dox
anddoc/building.dox
- set it in root
- Add a new Travis / AppVeyor matrix build for this port (or update existing)
- Add a new
PKGBUILD-*
file inpackage/archlinux
for testing (or update existing) - Enable or disable functionality using
if(MAGNUM_TARGET_*)
in CMake and#ifdef MAGNUM_TARGET_*
in C++ - Mention the new stuff in
doc/changelog.dox
- Push to a temporary branch (e.g.,
next
) - Iterate until the CIs are green
- Merge to
master
In order to remove a port, be sure to touch all places mentioned above, only in inverse.
Checklist for updating the bootstrap repo
- Check out the
_modules_
branch and update files inmodules/
- Check out the
_modules_sdl2_
branch, merge_modules_
to it, update remaining files inmodules/
- Check out the
_modules_es_
branch, merge_modules_sdl2_
to it, update remaining files inmodules/
- Check out all other (non-underscored) branches one by one
- use
git branch --list -v
to keep track - merge proper
_modules_*
branches to them, fix potential file deletion conflicts - update
toolchain
submodule, if present
- use
- Push all branches
- Trigger build on
master
, update theREADME.md
or files inpackage/ci
if necessary
Checklist for updating copyright year
- Verify there are no uncommitted changes in any repos, as that would significantly complicate reverting a potential fuck-up
- Use msrp to batch replace copyright info in all files, replacing existing
Copyright © ...
withCopyright © ..., 20XZ
in the root directory of every project, so nothing gets left out- If the line gets over 79 characters, wrap the name on the new line where the first letter is aligned under the
©
- If the line gets over 79 characters, wrap the name on the new line where the first letter is aligned under the
- Examples use partially MIT (mainly in docs) and partially UNLICENSE, replace
... —
with..., 20XZ —
there as well - Copy all
Find*.cmake
modules to dependent projects to update the copyright year in these as well - Update other occurrences by hand:
COPYING
doc/conf.py
doc/mainpage.dox
package/debian/copyright
- All flextGL
*.template
files insrc/external/OpenGL
andsrc/external/Vulkan
because wheezy template needs the@
escaped to@@
- Use
git diff
to verify the change went well and the new year is specified exactly once everywhere - Do a local verification build, push to
master
Checklist for uploading documentation
- (Optionally) remove
build/doc-public
to get rid of stale files - Verify there are no untracked files, modifications or branches different than
master
checked out that could mess up the docs - Run doxygen.py on
Doxyfile-public
, look for suspicious warnings - Upload contents of
build/doc-public/html/
todoc/magnum-new/
and removedoc/magnum-old/
if any - Once the upload is finished, rename
doc/magnum/
todoc/magnum-old/
anddoc/magnum-new/
todoc/magnum/
- Quickly check that the docs still look as they should, if not, revert the backup and try again
Checklist for merging a PR
- After the public round of review, pull the changes locally to a temporary branch (i.e.,
next
) - Verify a coverage build, verify that there are no compiler warnings
- Go over and fix issues that slipped through cracks in the public review
- Verify the contributor is mentioned in all relevant license headers, add if necessary
- Add the contributor to
CREDITS.md
, if not already there - Update
doc/changelog.dox
(and similar files in other repos), if not already done - Build documentation:
- run doxygen.py on
Doxyfile-mcss
and verify there are no new warnings - eyeball the relevant docs and fix suspicious things
- run doxygen.py on
- Push to a temporary branch (e.g.,
next
) - Iterate until the CIs are green
- Merge to
master
, put a "thank you" comment to the PR, explaining additional changes if necessary
Checklist for making a release
- Open a new
20XY.ac
milestone - Verify that there are no blocking issues in the current (
20XY.ab
) milestone, either fix them or move to the next milestone - Verify that all CIs are green
- Go through
doc/changelog.dox
and update it, in case it doesn't contain all changes (usegitk
to check when it was last updated) - Go through fixed issues and merged PRs and add either a changelog mention added (and add a mention to the changelog), scrapped or no action needed label to wrap them up
- Don't forget about the bootstrap repository and toolchains as well
- Go through merged PRs (and the most important issues) and add new people to
dox/credits.md
(and similar files in other repositories) and https:// magnum.graphics/ about/ , if they are not there yet - Update changelog for the next release:
- change section names for the latest release from
latest
to20XY-ab
- change the title from
Changes since 20XY.aa
to20XY.ab
- add a paragraph stating date of release and referencing the to-be-added tag on GitHub
- add a temporary
@anchor changelog-latest
(and equivalent in other repos) on top so the links from main page work properly
- change section names for the latest release from
- Convert all occurrences of
@m_since_latest_{thing}
to@m_since_{thing,20XY,ab}
@m_since_latest
to@m_since{20XY,ab}
@m_deprecated_since_latest_{thing}
to@m_deprecated_since_{thing,20XY,ab}
@m_deprecated_since_latest
to@m_deprecated_since{20XY,ab}
- Bump
MAGNUM*_LIBRARY_VERSION
,MAGNUM*_LIBRARY_SOVERSION
MAGNUM*_VERSION_YEAR
andMAGNUM*_VERSION_MONTH
in all projects. Ensure all projects have the exact same version. - Rebuild all projects with the new shared library version numbers, verify all tools and examples still behave properly
- Build and upload public docs (see Checklist for uploading documentation), verify that there are no new warnings and the changelog looks correct
- Push all new changes to a temporary branch (e.g.,
next
), don't forget theports
branch in examples - Wait for the CIs to get green
- Update
conanfile.py
in all projects that have it with a new version — this has to be done before the version is tagged. - Update Debian package changelog in
package/debian/changelog
, copypasting the last entry, updating it and usingdate -R
for a date — again, this should be done before the version is tagged so stable releases in PPAs can be done directly from the tag with no extra patching - Tag a new version using
git tag -a v20XY.ab
, say justVersion 20XY.ab
as a message - Push the tag, verify that the CIs are still green; if not, retry and tag again
- to GitLab as well
- Regenerate singles with changelogs for what changed and only then commit the changelog updates so the generated singles refer to the actual tag
- Update the Corrade and Magnum tagfiles on the website using the freshly-built public docs
- Write a release announcement for the blog
- highlight the most prominent features, mention detailed blog posts about them, if any
- reference detailed changelogs for all projects at the end
- don't forget to say thanks to significant contributors
- create some fancy eye-catchy cover image featuring nice screenshots of new functionality
- add release annoucement link under the button on front page
- Publish the release announcement, verify it looks correct
- Advertise the release announcement, preferably Monday 5 PM, never Friday or weekends
- come up with some 100-character-long extended title
- Twitter (extended title + url and some hashtags), first dry-run the link on https:/
/ cards-dev.twitter.com/ validator to ensure the cover image gets displayed - GitHub Release Radar (releaseradar@github.com)
- Reddit
r/cpp
,r/gamedev
,r/webassembly
,r/vulkan
,r/webgl
,r/gltf
; Hacker News (extended title + url) - summarize the release to mailing list
- summarize the release highlighting GL- and Vulkan-related functionality and submit that to Khronos, with a 500x500 downsized cover image
- send an e-mail to companies and universities on the private list
- add a message to the Gitter chat (title as heading, cover image, summary in a blockquote and "read more" link,
@
contributors)
- Reference Twitter, Reddit, Hacker News and mailing list in a "Discussion" note at the end of the article, reupload that change
- Update versions of ArchLinux AUR packages:
- run
makepkg
inpackage/archlinux/magnum*-git
, verify it builds and says correct version, ideally withr0
at the end - copy the updated
PKGBUILD
to the AUR package repo, runmakepkg --printsrcinfo > .SRCINFO
there - commit the updated
PKGBUILD
and.SRCINFO
, push - after pushing all, verify that the version is updated in the AUR web interface as well
- run
- Update Homebrew package versions
- Ask someone to update the Ubuntu PPA
- Ask someone to update Vcpkg packages
- Close the 20XY.ab GitHub milestone
- Add link to the release notes to the tag on GitHub
- Have a drink and take two days off