Wolf 3.0.0-REL Released!
Author: thothonegan
Tags: C++ modules wolf canis
Wolf 3.0 is finally released! While this is a release, its not recommended you upgrade to it unless you're ok with all its current restrictions.
The biggest thing to note is it currently only works on Linux. Compiler support on Windows and macOS is currently behind, but we plan on supporting them as soon as possible.
However this is a massive step preparing for the future.
C++20 Module Support
Wolf 3.0 is completely converted to C++20 modules. This was a massive undertaking, requiring changes both in not just Wolf, but all the supporting tools such as Canis/Okami and Catalyst.
Converting to use it is relatively straightforward, but it will require touching a lot of files at each level of the program. Best to do it piece by piece.
Catalyst/CMake
First we start with Catalyst. Modern Catalyst functions now understand modules and provide several new file groups:
PUBLIC_MODULE
:Public/Module.cppm
andPrivate/Module.cpp
: A publicly accessible module.PUBLIC_MIU_ONLY
: Module with just the MIU file (Public/Module.cppm
) and no source filePRIVATE_MODULE
: Same asPUBLIC_MODULE
but the module is inPrivate/Module.cppm
.PRIVATE_MIU_ONLY
: Private module with just the MIU file.PRIVATE_CANIS_MODULE
: A private module that needs to be scanned with CanisPRIVATE_CANIS_MIU_ONLY
: A private module that needs to be scanned with Canis
When Canis is enabled, it automatically scans all public modules, similar to how it would scan public headers. If you have any private modules which need to be exposed only via Canis, you can use the private canis groups to enable that.
Example module:
wolf_begin_module(WolfAudioSystem CANIS)
catalyst_target_add_cppsources(WolfAudioSystem
PUBLIC_HEADER_ONLY
Macros
PUBLIC_MIU_ONLY
WolfAudioSystem
PUBLIC_MODULE
AudioSystemModuleInterface
DriverType
Module
Player
)
wolf_end_module(WolfAudioSystem)
Your wolf module needs to be marked with .cpp20
to note that its a C++20 module.
Canis will then assume the module name matches the wolf module and can be used via
import Name;
similar to how it'd look for Name/Name.hpp
before. E.g.
{
"name": "WolfAudioSystem",
"type": "wolf.cpp20",
"dependent_modules": [
"WolfAudio",
"WolfCore"
],
"optional_dependent_libraries": [
"sndio"
],
"canis_modules": [
"WolfAudioSystem"
]
}
When installing modules, your public Mius are all stored in CppMiu similar to headers so they can be used when importing from other modules. If a BMI standard ever arrises for a platform, the BMIs might be stored instead - but for now we need to MIUs to be recompiled.
Canis/Okami
While Canis itself hasn't changed much, Okami has been split out and now has some massive changes to be able to handle modules.
- Okami now can take a ton more parameters since it needs to know the entire module import chain.
- For Wolf Modules, Okami will generate and store BMIs (Clang PCMs) within the modules.
- These are locked to the Okami version, since they're very compiler dependent.
- Right now it assumes the PCMs exist, but in the future it should be able to fall back to the Mius like the compiler itself uses.
- These are locked to the Okami version, since they're very compiler dependent.
- Right now Okami does a lot of extra recompiling when using modules, this will be improved in the future to only rebuild whats needed.
- Modules need to be properly marked so it can know whether to use a child module as c++20 style or header style.
- Okami support for submodules has been dropped, since it doesn't really work with c++ modules. It pretty much was only used for WolfCore, which has now been merged into a single module.
Wolf
Using Wolf, most things just require you to switch to modules, and then import them. Anything that is a macro has been moved to a Macros header file so they can be used separately.
module;
#include <WolfAudioSystem/Macros.hpp>
export module WolfAudioSystem:AudioSystemModuleInterface;
import WolfCore;
import :Player;
export namespace WolfAudioSystem
{}
You dont have to worry about children anymore - just import each module directly and the compiler will sort out what needs to be imported.
Related to this, all WolfCore submodules have now become part of WolfCore.
A few have had name changes (namely WolfThread
which renamed things like Mutex
to ThreadMutex
),
but most of them you can just start using WolfCore
instead
(such as WolfCore::Vector
). Major types have deprecated
aliases from the old name for compatibility.
WolfDagger
now is generating module compatible views. Any views that included headers before
now can use @cppImport Module;
to import modules into your cpphtml files.
Sometimes Canis or WolfScript cant find all the stuff it needs due to the module dependencies. If it doesn't find something, you can do the following:
- For Canis, add a
CanisDependencies.hpp
file that does the imports or includes needed. Canis will pick it up and include it as part of its generated source. - For WolfScript generated modules, create a header called WolfScriptDependencies that is ignored under Okami to prevent it from being processed when it generates the module. When its compiled, it'll automatically include it and provide the import to the generated file.
#ifndef M_WolfRenderer_WolfScriptDependencies_Hpp
#define M_WolfRenderer_WolfScriptDependencies_Hpp
#if !defined(OKAMI_IS_RUNNING) || (OKAMI_IS_RUNNING == 0)
import WolfResource;
#endif
#endif // M_WolfRenderer_WolfScriptDependencies_Hpp
Future
There's still a lot of work to do related to the modules. But this is a massive step forward.
Major goals are:
- Now that we require c++20, adding more features such as coroutines to the lower level objects.
- Getting macOS and Windows support working again
- Emscripten support becoming first class.
- Module improvements - more efficient, less macros, and overall safer code.
Its going to be an exciting year ahead.
Release Notes
Breaking Changes
- Massive change: Now uses C++20 modules for everything. While the majority of APIs are still the same, all includes will need to switch to imports.
WolfCore
is the biggest change - all submodules forWolfCore
are now inWolfCore
. Mostly its just renaming them (WolfType::Vector
becomesWolfCore::Vector
), and theirs aliases to help with this.- Currently Linux is the only working platform. It does not support Windows and macOS due to compiler support on those platforms, and mobile platforms haven't been re-implemented yet. This is temporary, but its not recommended to switch yet if you need that support.
Features
All
: C++20 Modules support. Makes thing easier to import, and will potentially lead to speedups later.StageRunner
: Now supports stretchable virtual resolutionsStageRunner
: Added support for allowing the runner to control whether it wants to vsync or notWolfAnalytics
: New driver set that can record analytics events. Current support allows hooking into Umami.WolfCore
: Special directories now has specific locations for state and logging.WolfDagger
: Layouts now supports models, allowing you to pass information from a page to a layout.WolfFile
: can now pull an entire file in one call.WolfFile
: Now supports async while running on linux.WolfJSON
: Now uses UTF8 stringsWolScriptRunnerMruby
: Supportsrequire_relative
andrequire
which can use the resource system viares:///
to locate files.WolfWeb
: Can display indexes of a static file directory if you allow it to.WolfTool
's webserver enables this automatically.
Bug Fixes / Other Improvements
WolfHttp
: Default handler for errors properly escapes the error message.\- Lots of other minor updates
Deprecated in 3.0 (removal 3.4)
- All
WolfCore
submodules that have aliases. This includes modules such asWolfDebug
WolfEnv
WolfCore
WolfType
WolfCPlusPlus
WolfMath
and so on. WolfCore::URI
has been renamed toWolfCore::Uri
- Bunch of WolfCore macros have been renamed to match the current naming scheme - too many to list.
Deprecated in 2.7 (removal 3.3)
- WolfWeb had a few name changes, converting
HTTP
toHttp
. - WolfVFS has a few name changes:
Subpath
toSubPath
WolfVFS::Source::openFileAsync
now returns a task instead of a callback function.WolfVFS::Source::v_openFileSync
now returns a Result instead of an error parameter.
Deprecated in 2.6 (removal 3.2)
WolfCore::CanisSupport::stringRefFromCanisStringRef
is replaced withutf8StringRefFromCanisStringRef
.WolfSystem::Application::currentApplication()
is nowcurrent()
for simplicity.WolfResource::Resource
: Reloading is now innate to an object, so it has a bit different implementationWolfResource::Manager
: Hiding some of the internals of manager.
Removals
WolfType::StringInterface
-charData()
anducharData()
instead should just usedata()
and then interpret as the type you expect.