Hi Martin,
I'm sending you a research/progress file I've written so far that documents
my progress.
It includes information on the things I have already done, possible porting
sources, discussion
of the portability of the different modules (i.e. standard headers) and
section 6 contains a few
questions I wanted to ask you (mostly regarding the direction you'd like
this thesis to take - if you
do have preference).
PS. Since HelenOS is a community project, I decided to CC the helenos-devel
mailing list in the
case somebody else would be interested (or would want to voice their
preference in the matters
discussed). (Although I'm not sure how that'd be incorporated into the
thesis.)
If you prefer to meet in person to discuss this, let me know and I'll come
to MS.
S pozdravem,
Jaroslav Jindrak
Porting C++ to HelenOS
======================
- portability observed mainly on libc++,
partially on libstdc++
0. Current progress (aka TL;DR)
===============================
> repo: https://code.launchpad.net/~dzejrou/helenos/cpp
> cross-g++ is now part of the build system
- detects .cpp files and compiles them as C++
- makedepend uses a temporary hack which injects libcpp
include path to CFLAGS
> implemented wrappers of libc headers that are
a common subset of C++ standard and HelenOS native
API (several headers were not found), see section 6.10
> also implemented <new> and parts of <exception> in terms
of C++11 (i.e. no aligned new etc) to test dynamic
memory allocation
- although e.g. "new" does not throw std::bad_alloc at the
moment because we still lack runtime support code (unwinding)
- testes allocation of objects and arrays, placement new should
theoretically work (as compiler should translate it to regular
new afaik) but this still needs testing
> compiled several simple C++ programs
- io using libc wrapper header <cstdio>
- std::printf, std::puts, std::fprintf, std::fopen, std::fclose, ...
- classes, inheritance, virtual/pure virtual member functions
- RAII (constructors/destructors)
1. Build system
===============
> Makefile macro determining that the project is written in C++
- problem: does not allow both C and C++ in one project
- is this a problem? such project should be split anyway
and use extern "C" linkage
- easy to follow and implement
- but requires work from app implementers
> Detect .hpp and .cpp files
- no work from app implementers
- allows both C and C++ in one project
- probably simpler? just add "%.o: %.cpp" rule to Makefile.common in uspace?
- NOTE: currently going with this, seems the easiest, but causes problems with
makedepend
2. Modules & portability
========================
- NOTE: at the moment disregarding headers that were introduced
after C++11
2.1 Written from scratch/Ported with vast modifications
=======================================================
- TOTAL: 8
> fstream
> iostream
> istream
> ostream
- parts of the streams not actually using IO
should be portable
> thread (C++11)
> mutex (C++11)
> shared_mutex (C++11)
> condition_variable (C++11)
- almost all oss implementations use pthread, we gotta use fibrils
2.2 To be decided
=================
- TOTAL: 10
> limits
- based on system specific limits
- TODO: might be implemented with limits.h (and then portable?)
> chrono (C++11)
- durations, casts, timepoints etc. are mostly portable
- but in e.g. libstdc++ depend on e.g. <limits>, so we
would need to make sure the HelenOS <limits> header is
compatible
- system_clock, steady_clock, ... might be problematic
- the best precision I found is usec from gettimeofday in sys/time.h
> random (C++11)
- libc++ random devices seem to use /dev/random etc.,
which might be a problem on HelenOS
> system_error (C++11)
- seems to create type strong error codes
- i.e. enum class with EPIPE, ENOTSUP, ...
- provides way more error codes than HelenOS seems to provide
- implement a subset vs. add additional error codes to HelenOS
vs implement them in C++ and not add them to C?
> valarray
- the container itself might be portable, but it requires overloads
for many mathematical functions
> future (C++11)
- most of the code should be portable, but waiting would need
to be reimplemented
> atomic (TODO, gotta check out what HelenOS offers in this regard)
> new (TODO, should be using malloc in most implementations)
> sstream (TODO, requires i/o stream)
> locale (TODO, afaik HelenOS offers only a dummy)
2.3 Can be ported with no or very small modifications
=====================================================
- TOTAL: 36
- mostly depend on <cstdint>, <cstddef>, <limits> and C++ headers
> vector
> bitset
> map
> unordered_map
> set
> unordered_set
> algorithm
> tuple (C++11)
> pair
> typeinfo
> typeindex (C++11)
> type_traits (C++11)
> iomanip
> memory
> functional
> utility
> initializer_list (C++11)
> scoped_allocator
> exception
> stdexcept
> string
> array
> deque
> list
> forward_list
> stack
> queue
> iterator
> complex
> numeric
> ratio (C++11)
> iosfwd (just forward declaration of IO types, but depends on wchar.h)
> ios (might have problems with locale)
> streambuf
> iomanip (many things rely on locale, but are not that important)
> regex (heavy use os strcmp, easy to patch, rest should be portable)
2.4 C stdlib
============
- TOTAL: 21
> C++ stdlib contains headers <cstdio>, <cstdlib>, ... these
are generally included and wrapped in the std namespace
- might be problematic due to the non-standard C API,
we could use libposix or macros (? would cause problem
when only signatures differ, but names are the same e.g. ftell)
- another option is to simply provide the HelenOS API here
and ignore the C standard
> cstdlib
> csignal
> csetjmp
> cstdarg
> ctime
> cstddef
> climits
> cfloat
> cstdint (C++11)
> cinttypes (C++11)
> cassert
> cerrno
> cctype
> cwctype (TODO: are wide chars supported in HelenOS C lib?)
> cstring
> cwchar
> cuchar (C++11)
> cmath (TODO: HelenOS math lib?)
> cfenv (C++11, TODO: does HelenOS have anything for this?)
> cstdio
> clocale (TODO: afaik HelenOS has only dummy)
3. Modules & their contents
===========================
- TODO
4. Features required by compiler
================================
> from osdev wiki
- pure virtual functions (single empty function)
- global objects (TODO?)
- local static variables (GCC specific)
- RTTI (TODO?)
- exception support (stack unwinding)
- many of these can be taken from https://github.com/pathscale/libcxxrt
- uses pthreads mostly for locking, can be changed to fibrils
- small, does not require much
- TODO: research their guard implementation
- problem: only arm and itanium implementation of some features
- BSD license
> note: libstdc++ provides its own code for this, libc++ as far as I'm concerned
does not
> idea: get inspired by some implementation (like the one mentioned above)
and rewrite it with the generic mechanisms libc in HelenOS already
provides (mainly typedefs to suitable native types).
5. Existing implementations
===========================
> libstdc++ (GNU)
- one of the largest
- actively worked on
- GPL license (afaik incompatible with BSD)
> libc++ (LLVM)
- one of the largest
- actively worked on
- dual licensed unter MIT and a BSD-like license
- unsure about compatibility
> stlport
- license https://sourceforge.net/p/stlport/code/ci/master/tree/LICENSE
- last commits in 2012 and before that very sparse
> ustl
- MIT licensed
- only partial implementation (according to their README.md)
- does stuff different to save memory, e.g. all containers are
implemented over vector
> Apache stdcxx
- last release 2008
- seems to be dead (or in their terms "dormant") for several years
and efforts for forking/moving the project failed
- Apache license, don't know about its compatibility with BSD
6. Questions & thoughts
=======================
6.1 Standard API compatibility?
===============================
Since HelenOS uses the "not using old/bad APIs" doctrine, do we want
to change the API like in the C library or shall we use the C++ standard
wherever possible and suitable?
6.2 Parts of vs. whole stdlib?
==============================
My idea was to find the best implementation to port and to port as much
as we can (without making the process too easy :), however, picking parts
of different implementations is possible too, though it would increase the
complexity of the project due to different macros etc. the implementations
use (+ it would be quite inconsistent). If libc++ is the only viable
option (like it seems to me right now seeing as libstdc++ is GPL and
the other implementations are old/no longer developed) this question
becomes irrelevant and we would simply port everything from it directly.
6.3 Libposix vs. native API?
============================
As far as I know libposix is just for initial ports of applications
and Vojta is thinking abour rewriting it, so I assume using the
HelenOS native C API would be preferable? (This also ties to the
<c*> headers, which wrap the C library - shall we use native API?)
6.4 Mainline or coastline?
==========================
Where would libcpp be? I'm asking because of the potential
license conflicts with the existing C++ stdlibs listed in section 5.
6.5 Version of the standard?
============================
My thoughts were to first aim for C++11 standard so that we don't
have parts of C++11, C++14 and C++17 and the implementation can be
considered complete in the context of the standard (i.e. a specific
version of it). Is that feasible thinking?
Note that by this I don't mean the ported stuff (it would be stupid
to discard parts of the ported library :), but the stuff that would be
written from scratch - is there a pool for optional work similarly to
the software project (i.e. if we have enough time we'd implement this
newer functionality)?
6.6 Copying files
=================
Some implementations (e.g. libc++) include conditionally compiled
code (#ifdef WIN, ...). Since these are completely irrelevant to us,
should we remove all of them? This would mean that HelenOS versions
of those files would be incompatible with the upstream, however that
is already caused if we use its native API.
6.7 Demonstrator
================
I was trying to find a suitable demonstrator C++ program (mostly on github),
however most suitable programs use 3rd party libraries or are very limited
in their scope (e.g. just vector/map, IO and language builtins) and don't seem
to cover much of the standard. Would writing an artificial application for this
(or even a set of unit tests) be suitable?
6.8 Compilers
=============
In my implementation, I modified the build system (primarily tools/autotool.py)
to use the GNU C++ compiler and disregarded clang/native/etc. as lower priority
goal (as I assume most people compile HelenOS with gcc). Are these other
compilers
still maintained (i.e. should I somehow implement those too)?
6.9 C++ Style
=============
After already writing several files in the library, I noticed that my HelenOS
vim settings only apply to C, not C++ (e.g. the library contains expanded tabs
with width of 4 spaces) and out of habit I used my C++ coding style. I can
refactor
this with little to no effor, however if we decide to go with libc++, which uses
a coding style that is very similar to my own, wouldn't it be smarter to just
have the entire library unified under this coding style (which would then
differ from most of HelenOS C code - but would be 100% consistent with
HelenOS C++ code :)?
6.10 Libc wrappers
==================
While several C++ standard C headers are missing from HelenOS, the HelenOS
native API provides a plethora of additional headers. Do we want those included?
It would mean they would be available in C++ with C linkage in the form of
<cexample> if they are names <example.h>. If so, all of them? Or should we
cherry pick (e.g. a poll amongst the HelenOS devs)?
7. Roadmap
==========
- TODO
8. Dev diary (for easier thesis writing)
========================================
> 2017-10-08
- added cross-g++ stuff to uspace/Makefile.common, but CPP macro is defined
by hand in the root Makefile.common, need to modify autotool.py somehow so
that
it generates the macro along with CC
- created the uspace/lib/cpp directory and added it to makefile
- created testing application in uspace/app/test_cpp
- created include/cstdio in the standard library that imports printf to
namespace
std
- struggled with linkage, we need extern "C" {} here around
libc includes (libc++ does not use it? maybe it compiles it itself in c++)
- created first ever c++ app on HelenOS: https://i.imgur.com/v34pFzM.png
- makedepend causes problems as it uses CFLAGS and only includes libc,
we'd need to detect the .cpp extension and add cpp stdlib into that macro
- tested inheritance, virtual member function and pure virtual member
functions,
all work: <3 compiler
> 2017-10-09
- instead of using ::<NAME>, cstdio (and all further C header wrappers)
include
the header within the std namespace
- this means that any addition to libc will immediately be available in
libcpp
without the need for any modification of libcpp
- started implementing the rest of libc wrapper headers (as per C++ standard)
- libc headers not found (TODO: find alternatives):
signal.h
float.h
wctype.h
wchar.h
uchar.h
math.h (found imath.h and libmath, combine them and autolink libmath?)
fenv.h
locale.h
- libc headers ported:
stdlib.h
setjmp.h
stdarg.h
time.h
stddef.h
limits.h
stdint.h
inttypes.h
assert.h
errno.h
ctype.h
string.h (well, actually str.h in HelenOS)
- in ctime, before including time.h, I had to define restrict as __restrict__
since it appears that cross-g++ does not support restrict c99 keyword by
itself
- added basic implementations of <new> and <exception> that provide us with
the
simplest form of new and delete operators
- note that apps need to define "void _Unwind_Resume = 0;" at the top of
the source
because of the lack of stack unwinding code
- moved macros that ensure compatibility with libc to "internal/common.hpp"
so that they are
declared only in one place (ifndef would possibly collide with libc in the
future)
- C++ compiler macro now generated by tools/autotool.py for gcc (no clang
support atm)
_______________________________________________
HelenOS-devel mailing list
[email protected]
http://lists.modry.cz/listinfo/helenos-devel