First version of OCCT without WOK and CDL

Forums: 

Hello,

We are steadily progressing in the refactoring tasks, and now have the first version of OCCT without WOK and CDL ready for review: see Git branch CR0_noCDL.
Note that this is the first experimental version, thus please do not try to use it in your project!

Here is some detail on the changes made in this branch.

Removal of generic classes

TCollection instances have been converted to NCollection templates, except a few instances found in nested generic classes -- these are to be converted manually later. Note that this led to revision of implementation of both collections to have them synchronized, and STL-like iterators have been added in NCollection classes. These changes, as well as removal of many non-collection generics, are already in OCCT master and will be included in 6.8.0

Refactored type system

OCCT type system has been changed to use templates instead of plain C functions defined by macros. The implementation follows the same approach as before: we still use static instances of Standard_Type class to provide meta-data for a class. It is also still necessary to use macro DEFINE_STANDARD_RTTI within the class declaration to have its base class and non-mangled name known to the type system.

Removal of CDLs

CDL files have been removed. The files generated by WOK from CDL (headers and some cxx) have been moved to relevant packages in src. Sub-folders .adm, inc, and drv created by WOK will not be used any more. Note that header files are now included with package prefix, e.g.: #include <gp/gp_Pnt.hxx>

Build system

Tools for building with Visual Studio projects is ready. To generate project files, run genproj.bat This command does the same job as wgenproj command in WOK. Note that you still need to have file custom.bat to define version of Visual Studio and other build options. The build time on my machine has decreased to 30 min from 37 min in master branch (yet not accounting additional time needed for WOK extraction).

Further steps

The targets we are going to address during August are:

  • Implement new build system based on CMake
  • Clean up old OCCT persistence -- either remove it completely, or at least get rid of the code generated by WOK, replacing it by more compact and maintainable code
  • Finalize revamping of Handle classes by converting them to templates
  • Prepare guide and tools for migration to the new OCCT

You are welcome to share your opinion and comment on this Andrey

Denis's picture

Hello Andrey,

Since header files are moved, there is an opportunity to put them under a single hierarchy, say occ/ for instance. Many projects have adopted this convention (boost for instance). This is very convenient to avoid name clashes (this is already mitigated by your described change), but also makes 3rd-party code more readable because someone not familiar with OCCT immediately knows that an header file belongs to OCCT.

By the way, do you plan to provide symlinks, or another scheme to help users upgrading their code?

Denis

Pavel Durandin's picture

Hello Denis,

Your idea sounds good. We plan to keep include files once without copying together with the sources. So, inc directory will be not necessary and moreover, the name ‘src’ will not reflect the content.

I think that the following structure will can be proposed:
occt/Package_name/. In the binary distribution of OCCT the libraries will be added and sources files will be just filtered.

Pavel.

Denis's picture

Hello,

http://dev.opencascade.org/index.php?q=node/960
and the current discussion seem to focus on OCCT developers' point of view. But IMHO you should first consider how your library is being used. Users will be told to replace all their #include "Foo_Bar.hxx" by #include "Foo/Foo_Bar.hxx" (I replaced angle brackets by quotes to avoid HTML problems). You should provide a good reason for this change, otherwise users will complain about it.

Andrey BETENEV's picture

Hello Denis,

For upgrade, we are going to develop a tool (Tcl script, see #24816) to update client code when porting to new version of OCCT. In particular, to upgrade for changed layout of includes it will add prefix of package name (and "occt/", if we adopt your idea), to names of OCCT header files.

Andrey

Roman Lygin's picture

Hi Andrey,

As you encouraged let me put a few comments here on the forum.

I'm slightly concerned about the headers location and the need to have #include and alike. This can be too tedious thing to do to migrate big source trees. Perhaps you could consider an approach used by Qt - they have includes in common directories per module but including headers located in package-like directories.
For instance in the global Qt's include directory the files are grouped per modules, for instance QtCore/QString, so you write #include . And the latter just contains:
#include "../../src/corelib/tools/qstring.h"

The Denis' idea above of using symlinks may not be working on Windows unfortunately.

Also searching for headers in /src can be less convenient (or taking longer times) than in single /inc. But that is minor concern.

Thank you,
Roman

Kirill Gavrilov's picture

I'm slightly concerned about the headers location and the need to have #include and alike.

Please see original description of three proposed solutions:
http://dev.opencascade.org/index.php?q=node/960
Chosen approach has been considered as most convenient from both development and distribution point of views.

The Denis' idea above of using symlinks may not be working on Windows unfortunately.

The symlinks work well in Windows 7+ on NTFS. But their usage is still not as simple and natural as on Unix systems.

This can be too tedious thing to do to migrate big source trees.

This is not so much an issue using porting TCL-script described above.
OCCT 7.0.0 will introduce many other significant changes.
And if project would try to be source-compatible with older and newer releases, it's code will be be extremely bloated anyway.

One-way conversion is the preferred migration choice, and OCCT 6.8.0 would allow big inertial projects to delay this procedure.

Roman Lygin's picture

Hi Kirill,

Thanks for your comments and the link to the post of April. I seem to have missed that post - either because it was before the general subscription mechanism was introduced (in June?) or for any other reason.

Regardless of the way you would finally choose please consider that the same source code of the client will be used to build with *multiple* OCC versions. This is the case for CAD Exchanger (which maintains 2-3 recent OCC versions) and other OCC customers I know of. This may be your own case for your customer projects and SALOME.

So having a TCL script that would convert all #include's may be not a sufficient option (even though it would certainly be helpful for those users who decide to jump over to the new version at once).

Please anticipate that dropping compilation for the pre-7.0 may take years. Therefore old convention #include will still need to work. Therefore I think combining (b) and (c) would be a reasonable way to go.

As for symlinks - I really have mixed feelings. Whether you decide to adopt it or not please try to anticipate different scenarios, for instance tar'ing on one OS and untar'ing on the other.

Thanks again,
Roman

Kirill Gavrilov's picture

As for symlinks - I really have mixed feelings. Whether you decide to adopt it or not please try to anticipate different scenarios, for instance tar'ing on one OS and untar'ing on the other.

This is exactly how the problem appears - links supported by the system, but not by 3rd-party software like archivers, installers and even Windows Explorer (save the arrow icon) making their everyday usage non-trivial without extra tools.

But when such tools have been found - symlinks save a lot of time and make many operations more intuitive and simple.

Roman Lygin's picture

(Comment #2 of 3).

Hi Andrey,

Could you elaborate on the new handle syntax and provide some examples ?
Hopefully source compatibility for handles (for downcasts, RTTI, type hierarchy) will be preserved. Migrating to something different can be prohibitively expensive.

Thank you,
Roman

Roman Lygin's picture

Kirill's link to Andrey's post of April helped to discover some trackers related to Handles redesign.

To avoid duplicates I added a couple of notes directly there at
http://tracker.dev.opencascade.org/view.php?id=24023.

Roman Lygin's picture

(Comment #3 of 3).

Hi Andrey,

Good to see elimination of TCollection.
Have also you considered to get rid of NCollections in favor STL collections whenever there is equivalent (e.g. lists, queues, datamaps, sets) altogether ? Maybe as a next step ?

Thank you,
Roman

Kirill Gavrilov's picture

Have also you considered to get rid of NCollections in favor STL collections whenever there is equivalent (e.g. lists, queues, datamaps, sets) altogether ? Maybe as a next step ?

This question appeared many times in discussions.
For now there are several reasons to keep using own collections:
- STL syntax is terrifying and contradicts to OCCT coding rules.
- A lot of code in OCCT and in projects as well uses these collections. Dropping them would lead to significant porting issues. Wrapping STL collection into NCollection does not make much sense.
- STL collections show no benefit from performance point of view (several benchmarks has been performed in the near past).
- Such classes like unordered_map have appeared recently in standard C++11, which is still not completely supported by modern compilers (and even worst by older compilers, and this is a serious issue for multi-platform framework).

So another direction has been recently taken - adopting NCollection classes to be STL-compatible. And as first step - STL-compatible iterators:
http://tracker.dev.opencascade.org/view.php?id=24831

Roman Lygin's picture

Hi Kirill,

Thank you for offering your comments.
Among the three sub-topics in this thread (Handles, headers, NCollection & STL) this one has the least impact to the OCC users, so you have the most flexibility to eventually decide.

The major point I see in adopting STL vs home-made collections is reduced source code and hence maintenance efforts. For instance, instead of spending your efforts on designing "STL-compatible iterators" you could invest into something OCC-specific. In the past, lack of a hasher argument in the DataMap led to impossibility to mix various shape maps in one compilation unit. Lack of allocator in the array class does not allow to use IncAllocator. To retrieve an object from a map you have to ask twice (e.g. IsBound() and operator()), where you would retrieve an iterator from STL std::unordered_map just once. And so on and so forth. So you have to spend your precious time on this generic stuff.

Secondly, using STL machinery you could write more compact code (e.g. using std::find, ::count_if, ::for_each,...).

Breaking the source compatibility (your point #2) is indeed the greatest argument why NCollection will likely stay for foreseeable future.

The compiler support (your point #4) is also valid, although all supported compilers (http://www.opencascade.org/getocc/require/) seem to support all or most relevant containers (not certain about VS2005 though).

Performance is certainly likely on par, indeed. Unless you write a linked list implementation is some weird way, all implementations should be good ;-). However the above point on search in the DataMap vs unordered_map can be an example where STL usage might be more efficient.

I don't get the point on 'terrifying syntax' and compliance to OCC coding conventions. The former is subjective (many people will unlikely share your observation). The latter just does not apply - STL is *the* international standard, it does not need to obey to any proprietary coding styles.

Anyway, as stated in the beginning - this is rather your internal matter. So please consider all this with grain of salt. Just my 2 cents.

Thank you,
Roman

Kirill Gavrilov's picture

The major point I see in adopting STL vs home-made collections is reduced source code and hence maintenance efforts.

To be honest - NCollection maintenance and evolution is just a drop in the ocean.

Secondly, using STL machinery you could write more compact code (e.g. using std::find, ::count_if, ::for_each,...).

These instruments are already available through STL-iterators for main NCollection classes.

  NCollection_Vector aVec;
  aVec.Append (new AIS_Shape (TopoDS_Shape()));
  aVec.Append (new AIS_Shape (TopoDS_Shape()));
  for (auto aPrsIter : aVec)
  {
    std::cout << "Prs: " << aPrsIter->Type() << "\n";
  }
To retrieve an object from a map you have to ask twice (e.g. IsBound() and operator())

No you need not in case of values as small primitives (integers/doubles) or handles. See method NCollection_DataMap::Find

  Standard_Boolean NCollection_DataMap::Find (const TheKeyType& theKey,
                                              TheItemType&      theValue) const;
The compiler support (your point #4) is also valid, although all supported compilers seem to support all or most relevant containers (not certain about VS2005 though).

This almost is very confusing. Last time I have tried to use nice C++11 feature I have found that exactly this feature is still NOT implemented by my fresh compiler.
Also Microsoft now publishes updated compilers with more C++11 features independently from VS. I've thought that these updates should be included in "Update #N" packages for VS but it seems I have been wrong - and this would complicate code support.