How to upgrade lvgl v7 to v8

Hi all,
How to upgrade lvgl v7 to v8
i developed lot off screens in lvgl 7.11.0
i have cloned new changes from github. now i am facing lot of errors in lvgl functions.
is there any alternate to change v7 to v8 or changing each functions is only option?

Please help me.

Thanks in advance.

AFAIK the only way is to bite the bullet and go for it. V7 & V8 are significantly different as you are finding out. I am have been working on converting my project for ~2 weeks (on and off) and still not quite done.
Some recommendations:

  • Use an editor that supports regular expressions (I use VS code). This will make the functional changes take far less time searching across the whole project (but you will need to know some basic search and replace in regex, worth learning in my opinion since this will save you time for the rest of your working life).
  • You’ll spend a lot of time on fixing up the styling. I decided to convert to using a theme.
  • If you have created your own widgets the inheritance is blown due to re-architecture of base objects. They will probably all need refactoring.
  • The majority of your time will be on fixing the alignment. The introduction of flex & grid layout is great but completely different to the current layout lv_cont. I spent some time learning about the flex grid and how setting each of the 3 axis options work (it’s not always intuitive if you’ve never used one).

Hope this helps.
BTW I have been using V7 for over a year now and still “think” that way which is also not helpful.

@kisvegabor et al, before considering changes/new additions for the next major release I would think long and hard about keeping a backward compatible API. LVGL is an excellent library but you will severely limit adoption if you keep breaking the API every major release.

3 Likes

Not sure what the official release policy is regarding breaking changes. And it is to be expected that things will break between major (and even minor?) versions. But the sheer amount of them is rather overwhelming indeed. I have also been occupied with this challenge in the last few days…

AFAIK the only way is to bite the bullet and go for it.

I decided to temporarily use a shim or stub lv_conf.h that holds a bunch of defines to bridge some of the gaps between v7 code and v8 api in my project. It’s not possible to ‘fix’ every error this way, but it helps to get the number of errors down to a more manageable level:

Instead of resolving all these errors at once, I try to identify the changes in the api and put them into this lv_conf.h where possible. This quick fix should resolve the error wherever that code occurs without going over the whole project now. It allows me to at least get a compiled project quicker and then work through the list of define statements and wrappers one-by-one at a later time…

Some defines and wrappers are universal and could/should be added to lv_api_map.h. But I also added some placeholders that just suppress the errors for the moment… I will get to those when time comes :slight_smile:

I have also wrapped vast parts of non-critical code with #if LVGL_VERSION_MAJOR == 7 statements. That block is just skipped for now and I will remove the version check when I get to that module in my project…

you will severely limit adoption if you keep breaking the API every major release.

If I recall correctly, the move from v6 to v7 was less involved and had fewer breaking changes. Also it contained more wrapping code in lv_api_map.h to ease the transition.

I believe this time they pushed all breaking changes over a very long period into v8 and released it with a BIG BANG. I would be in favor of smaller breaking changes, even in a minor release, if it only breaks a few apis that can easily be fixed. Also a list of common wrappers and defines could be kept in lv_api_map.h, a blog post or ‘Migration’ document…

Sorry for these difficulties. I agree it’d be great to make the migration simpler. More frequent major releases with fewer breaking changes seem like a good idea!
@embeddedt do you also agree with it?

Yes. In my opinion, we should also aim to provide stubs for every breaking change so that old code still runs on the newer version. It’s not possible in every case (such as dropping the copy parameter from widget_create functions) but it should be possible for simpler changes.

An example of this is the module I made for migrating v6 styles to v7.

The good news is - it’s achievable if you persevere! I have successfully converted an extensive project (13 screens, hundreds of objects, 1000+ “errors” on first compile with v8) and it is stable, fully functional, and hard to tell apart from the V7 version after some theme modifications.

I’m not as good with regular expressions for replaces, but I significantly reduced the initial pass of fixing breaking changes to at least get something to compile with a lot of defines, some temporary replacement functions, etc. and, once I had a working version, start attacking the bulk of changes at my own pace. The biggest “manual” task I had (again, maybe because of my lack of RegEx experience) was changing the event callback signatures.

Here are just a few examples of the types of defines I did to at first get it to compile, and still function. Later, I could refine the code piece by piece.

//I don't use the copy parameter, so this was fine to implement
#define lv_img_create(X, Y) lv_img_create(X)
#define lv_btn_create(X, Y) lv_btn_create(X)
#define lv_label_create(X, Y) lv_label_create(X)
#define lv_line_create(X, Y) lv_line_create(X)
...
...
#define lv_obj_set_event_cb(X, Y) lv_obj_add_event_cb(X, Y, LV_EVENT_ALL, NULL)
...

//Renamed 100s of lv_obj_align to lv_legacy_obj_align and implemented this. Later, can go back and change them individually:

void lv_legacy_obj_align(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv_coord_t x_ofs, lv_coord_t y_ofs)
{
  if ((align == LV_ALIGN_CENTER) && (x_ofs == 0) && (y_ofs == 0) && (lv_obj_get_parent(obj) == base)) {
    lv_obj_center(obj);
  } else if (lv_obj_get_parent(obj) == base) {
    lv_obj_align(obj, align, x_ofs, y_ofs);
  } else {
    lv_obj_align_to(obj, base, align, x_ofs, y_ofs);
  }
}

...
//Lots of these to handle arbitrarily named items that were arbitrarily renamed in v8

#define LV_ALIGN_IN_TOP_LEFT LV_ALIGN_TOP_LEFT
#define LV_ALIGN_IN_TOP_MID LV_ALIGN_TOP_MID
#define LV_ALIGN_IN_TOP_RIGHT LV_ALIGN_TOP_RIGHT
#define LV_ALIGN_IN_BOTTOM_LEFT LV_ALIGN_BOTTOM_LEFT
#define LV_ALIGN_IN_BOTTOM_MID LV_ALIGN_BOTTOM_MID
#define LV_ALIGN_IN_BOTTOM_RIGHT LV_ALIGN_BOTTOM_RIGHT
#define LV_ALIGN_IN_LEFT_MID LV_ALIGN_LEFT_MID
#define LV_ALIGN_IN_RIGHT_MID LV_ALIGN_RIGHT_MID

You get the idea. As you go through the errors and look up the equivalent in v8, you can give yourself some shortcuts to getting it to compile.

I should add that I wrapped the above with #if LV_VERSION_CHECK(8, 0, 0) , and wrapped areas where I made code changes specifically for V8 with the same check and #else for the V7 code. By doing defines above for v8 instead of renaming globally, I could actually switch out the v7 and v8 library at will whilst doing this.

Good luck!

1 Like

Thanks. It’d really be doable to provide wrappers to the align functions…

We have learned from it and - as @embeddedt also agreed - we aim for more frequent major releases with fewer breaking changes.

It’s OK, I’m not complaining. I do see the reasons behind these changes and agree with most of them. I am excited to try the new v8 stuff once I get the project migrated. The new api certainly seems more consistent and concise with a smaller memory/flash footprint too.

Thanks for this, I’m doing it the same way. I have now separated my defines into a separate header and added even more defines. I’ll add yours to that list. Hopefully this can help some other developers kick-start their migration.

I’m also trying to take the idea from lv_obj_style_dec.h to create attribute wrappers, but I’m not that experienced with macro’s:

// Usage:      Search & Replace all `lv_obj_get_style_` to `lv_obj_get_v7_style_` in your source code
// Optionally: Search & Replace all `lv_obj_set_style_local_` to `lv_obj_set_v7_style_` in your source code

#define _LV_ATTRIBUTE_V7(prop_name, func_name, value_type)                                                             \
    static inline value_type lv_obj_get_v7_style_##func_name(const lv_obj_t* obj, lv_part_t part, lv_state_t state)    \
    {                                                                                                                  \
        return lv_obj_get_style_##func_name(obj, part | state);                                                        \
    }                                                                                                                  \
                                                                                                                       \
    static inline void lv_obj_set_v7_style_##func_name(lv_obj_t* obj, lv_part_t part, lv_state_t state,                \
                                                       value_type value)                                               \
    {                                                                                                                  \
        lv_obj_set_style_##func_name(obj, value, part | state);                                                        \
    }                                                                                                                  \
                                                                                                                       \
    inline void lv_obj_set_style_local_##func_name(lv_obj_t* obj, lv_part_t part, lv_state_t state, value_type value)  \
    {                                                                                                                  \
        lv_obj_set_style_##func_name(obj, value, part | state);                                                        \
    }

_LV_ATTRIBUTE_V7(ALIGN, align, lv_align_t)
...

Not yet tested, but I think you get the idea.

I like your approach of adding the old version number to the API name. That is a clean way of handling the fact that the function signature changed, but the name didn’t.

As others have mentioned, upgrading from v7 to v8 for an existing project is not a trivial task especially for large projects - you may find yourself refactoring most lines of your gui code! But there are short cuts like copy / paste / regex!

LVGL is quite amazing and the changes to the framework are for the best and I would say initially learning it from v8 would be easier. There are no more methods like “lv_cont_set_fit2”! :slight_smile:

Although I’m working on a project for a little esp32 I have the latest Visual Studio example featuring v8 (8.1.0-dev) running on the side so I can learn interactively about the changes (documentation isn’t 100% there yet and it’s often best to just dive in using an example anyway).

2 Likes