Project

General

Profile

Upgrade from Wt3 to Wt4

Added by Diego Villalpando over 2 years ago

Hi,
I was wondering if there is a guide/best practices on how to upgrade a Wt3 project to Wt4.
In the next couple of months, Im planning on upgrading one large project that I have been working on since version 3.2.1.

Currently Im running version 3.3.12 wondering if it makes more sense to upgrade first to the latest 3.7.1 version before upgrading to 4.5.1.

Also, will Wt3 stream support ever stop?
Any tips/advice is greatly appreciated.

Thanks!
Diego Villalpando


Replies (2)

RE: Upgrade from Wt3 to Wt4 - Added by Roel Standaert over 2 years ago

We already no longer support Wt 3. It's been EOL since January.

I think you won't have to change much if anything if you update to 3.7.1 first. I think it may be worth doing, though. If you do encounter regressions with 3.7.1 you may want to check the release notes for 4.5.1 to see if it hasn't been fixed in the meantime. The release notes for Wt 4.0.0 and the blog post already contain some information about what has changed in Wt 3.

Firstly I would recommend that you get up to speed with recent C++ versions and move semantics if you aren't already. Wt 4 expresses ownership according to the C++ Core Guidelines:

  • std::unique_ptr<Object> expresses unique ownership (used for most widgets in the widget tree)
  • std::shared_ptr<Object> expresses shared ownership (used e.g. for WButtonGroup, WAbstractItemModel,...)
  • Object* and Object& are non-owning.
  • No "naked new" or delete: use std::unique_ptr<T>(new T(...)), std::make_unique<T>(...), std::shared_ptr<T>(new T(...)), or std::make_shared<T>(...).

Big changes you will notice:

Header files

Wt's header files now have a .h extension. There's a Python script in Wt's source tree: wt4_add_h_to_includes.py, which will change the includes of all the files in the current working directory. This will probably be the first thing you need to fix.

Smart pointers

As I mentioned before, Wt 4 uses smart pointers to express ownership, so here are some likely changes you will have to make:

// Given some Widget type, and a WContainerWidget *container
Widget *w = new Widget(..., container);

Will become:

Widget *w = container->addNew<Widget>(...);

This is a shorthand for:

Widget *w = container->addWidget(std::make_unique<Widget>(...));

If the adding of a widget and its creation are split up:

Widget *w = new Widget(...);
...
container->addWidget(w);

Then it will be:

auto w = std::make_unique<Widget>(...);
...
container->addWidget(std::move(w));

Note that w will be null after the call to addWidget. You may want to save the result of addWidget, or call w.get() if you want to still refer to the widget you just added.

If we encountered the above situation when porting, we would usually either reorder things so that the addWidget calls happens first rather than last, or write it as such:

auto wPtr = std::make_unique<Widget>(...);
auto w = wPtr.get();
...
container->addWidget(std::move(w));

WTemplate similarly has a bindWidget that returns a raw (non-owning) pointer, and a bindNew. The layouts also have addWidget functions that return a raw pointer.

Enums

In Wt 4 we changed most enums to scoped enums (enum class). Many things that were prefixed now no longer use a prefix, and many enums that were in a class's scope have been moved to the namespace, e.g. Wt::WContainerWidget::OverflowAuto becomes Wt::Overflow::Auto. The search function in Wt's documentation may help you find the correct substitution.


Your code will likely not compile before you fixed all of these issues. I recommend that you turn on as many compiler warnings as you can. I also recommend using static analysis tools like clang-tidy. This will help you catch common issues like dereferencing unique_ptr after a move. Once you've resolved compilation errors and warnings you should be most of the way there.

RE: Upgrade from Wt3 to Wt4 - Added by Diego Villalpando over 2 years ago

This is great, thanks!

    (1-2/2)