How do I try out C++ modules with clang?

Stephen Kelly wrote:

Actually I think I hit similar errors from files in /usr/include when I
tried this a few weeks ago on linux, and I think my solution was to add a
modulemap in /usr/include for a few things. I'll check that in a few days.

I checked what I was running into regarding this, and made a testcase:

$ cat include/foo.map
module foo {
  requires cplusplus
  header "foo.h"
}

$ cat include/foo.h

#include <utility>

#include <stdlib.h>

$ cat test.cpp

#include "foo.h"

int main(int, char **)
{
  return 0;
}

$ clang++-libc++ -std=c++14 -fmodules -E test.cpp -fmodule-map-
file=include/foo.map -fmodules-cache-path=cache -fPIE -I include -I .
# 1 "test.cpp"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 340 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "test.cpp" 2
While building module 'foo' imported from test.cpp:2:
In file included from <module-includes>:1:
In file included from
/home/stephen/dev/src/playground/modules/modulestry/include/foo.h:4:
In file included from /usr/include/stdlib.h:41:
/usr/include/x86_64-linux-gnu/bits/waitflags.h:52:3: error: redefinition of
enumerator 'P_ALL'
  P_ALL, /* Wait for any child. */
  ^
/usr/include/x86_64-linux-gnu/bits/waitflags.h:52:3: note: previous
definition is here
  P_ALL, /* Wait for any child. */
  ^
While building module 'foo' imported from test.cpp:2:
In file included from <module-includes>:1:
In file included from
/home/stephen/dev/src/playground/modules/modulestry/include/foo.h:4:
In file included from /usr/include/stdlib.h:41:
/usr/include/x86_64-linux-gnu/bits/waitflags.h:53:3: error: redefinition of
enumerator 'P_PID'
  P_PID, /* Wait for specified process. */
  ^
/usr/include/x86_64-linux-gnu/bits/waitflags.h:53:3: note: previous
definition is here
  P_PID, /* Wait for specified process. */
  ^
While building module 'foo' imported from test.cpp:2:
In file included from <module-includes>:1:
In file included from
/home/stephen/dev/src/playground/modules/modulestry/include/foo.h:4:
In file included from /usr/include/stdlib.h:41:
/usr/include/x86_64-linux-gnu/bits/waitflags.h:54:3: error: redefinition of
enumerator 'P_PGID'
  P_PGID /* Wait for members of process group. */
  ^
/usr/include/x86_64-linux-gnu/bits/waitflags.h:54:3: note: previous
definition is here
  P_PGID /* Wait for members of process group. */
  ^
While building module 'foo' imported from test.cpp:2:
In file included from <module-includes>:1:
In file included from
/home/stephen/dev/src/playground/modules/modulestry/include/foo.h:4:
In file included from /usr/include/stdlib.h:42:
/usr/include/x86_64-linux-gnu/bits/waitstatus.h:66:7: error: redefinition of
'wait'
union wait
      ^
/usr/include/x86_64-linux-gnu/bits/waitstatus.h:66:7: note: previous
definition is here
union wait
      ^
While building module 'foo' imported from test.cpp:2:
In file included from <module-includes>:1:
In file included from
/home/stephen/dev/src/playground/modules/modulestry/include/foo.h:4:
In file included from /usr/include/stdlib.h:235:
/usr/include/xlocale.h:27:16: error: redefinition of '__locale_struct'
typedef struct __locale_struct
               ^
/usr/include/xlocale.h:27:16: note: previous definition is here
typedef struct __locale_struct
               ^
While building module 'foo' imported from test.cpp:2:
In file included from <module-includes>:1:
In file included from
/home/stephen/dev/src/playground/modules/modulestry/include/foo.h:4:
/usr/include/stdlib.h:239:17: error: conflicting types for 'strtol_l'
extern long int strtol_l (const char *__restrict __nptr,
                ^
/usr/include/stdlib.h:239:17: note: previous declaration is here
extern long int strtol_l (const char *__restrict __nptr,
                ^
While building module 'foo' imported from test.cpp:2:
In file included from <module-includes>:1:
In file included from
/home/stephen/dev/src/playground/modules/modulestry/include/foo.h:4:
/usr/include/stdlib.h:243:26: error: conflicting types for 'strtoul_l'
extern unsigned long int strtoul_l (const char *__restrict __nptr,
                         ^
/usr/include/stdlib.h:243:26: note: previous declaration is here
extern unsigned long int strtoul_l (const char *__restrict __nptr,
                         ^
While building module 'foo' imported from test.cpp:2:
In file included from <module-includes>:1:
In file included from
/home/stephen/dev/src/playground/modules/modulestry/include/foo.h:4:
/usr/include/stdlib.h:249:22: error: conflicting types for 'strtoll_l'
extern long long int strtoll_l (const char *__restrict __nptr,
                     ^
/usr/include/stdlib.h:249:22: note: previous declaration is here
extern long long int strtoll_l (const char *__restrict __nptr,
                     ^
While building module 'foo' imported from test.cpp:2:
In file included from <module-includes>:1:
In file included from
/home/stephen/dev/src/playground/modules/modulestry/include/foo.h:4:
/usr/include/stdlib.h:255:31: error: conflicting types for 'strtoull_l'
extern unsigned long long int strtoull_l (const char *__restrict __nptr,
                              ^
/usr/include/stdlib.h:255:31: note: previous declaration is here
extern unsigned long long int strtoull_l (const char *__restrict __nptr,
                              ^
While building module 'foo' imported from test.cpp:2:
In file included from <module-includes>:1:
In file included from
/home/stephen/dev/src/playground/modules/modulestry/include/foo.h:4:
/usr/include/stdlib.h:260:15: error: conflicting types for 'strtod_l'
extern double strtod_l (const char *__restrict __nptr,
              ^
/usr/include/stdlib.h:260:15: note: previous declaration is here
extern double strtod_l (const char *__restrict __nptr,
              ^
While building module 'foo' imported from test.cpp:2:
In file included from <module-includes>:1:
In file included from
/home/stephen/dev/src/playground/modules/modulestry/include/foo.h:4:
/usr/include/stdlib.h:264:14: error: conflicting types for 'strtof_l'
extern float strtof_l (const char *__restrict __nptr,
             ^
/usr/include/stdlib.h:264:14: note: previous declaration is here
extern float strtof_l (const char *__restrict __nptr,
             ^
While building module 'foo' imported from test.cpp:2:
In file included from <module-includes>:1:
In file included from
/home/stephen/dev/src/playground/modules/modulestry/include/foo.h:4:
/usr/include/stdlib.h:268:20: error: conflicting types for 'strtold_l'
extern long double strtold_l (const char *__restrict __nptr,
                   ^
/usr/include/stdlib.h:268:20: note: previous declaration is here
extern long double strtold_l (const char *__restrict __nptr,
                   ^
While building module 'foo' imported from test.cpp:2:
In file included from <module-includes>:1:
In file included from
/home/stephen/dev/src/playground/modules/modulestry/include/foo.h:4:
In file included from /usr/include/stdlib.h:314:
In file included from /usr/include/x86_64-linux-gnu/sys/types.h:219:
In file included from /usr/include/x86_64-linux-gnu/sys/select.h:43:
/usr/include/time.h:120:8: error: redefinition of 'timespec'
struct timespec
       ^
/usr/include/time.h:120:8: note: previous definition is here
struct timespec
       ^
While building module 'foo' imported from test.cpp:2:
In file included from <module-includes>:1:
In file included from
/home/stephen/dev/src/playground/modules/modulestry/include/foo.h:4:
In file included from /usr/include/stdlib.h:314:
In file included from /usr/include/x86_64-linux-gnu/sys/types.h:219:
In file included from /usr/include/x86_64-linux-gnu/sys/select.h:45:
/usr/include/x86_64-linux-gnu/bits/time.h:30:8: error: redefinition of
'timeval'
struct timeval
       ^
/usr/include/x86_64-linux-gnu/bits/time.h:30:8: note: previous definition is
here
struct timeval
       ^
While building module 'foo' imported from test.cpp:2:
In file included from <module-includes>:1:
In file included from
/home/stephen/dev/src/playground/modules/modulestry/include/foo.h:4:
In file included from /usr/include/stdlib.h:314:
In file included from /usr/include/x86_64-linux-gnu/sys/types.h:219:
/usr/include/x86_64-linux-gnu/sys/select.h:106:12: error: conflicting types
for 'select'
extern int select (int __nfds, fd_set *__restrict __readfds,
           ^
/usr/include/x86_64-linux-gnu/sys/select.h:106:12: note: previous
declaration is here
extern int select (int __nfds, fd_set *__restrict __readfds,
           ^
While building module 'foo' imported from test.cpp:2:
In file included from <module-includes>:1:
In file included from
/home/stephen/dev/src/playground/modules/modulestry/include/foo.h:4:
In file included from /usr/include/stdlib.h:314:
In file included from /usr/include/x86_64-linux-gnu/sys/types.h:219:
/usr/include/x86_64-linux-gnu/sys/select.h:118:12: error: conflicting types
for 'pselect'
extern int pselect (int __nfds, fd_set *__restrict __readfds,
           ^
/usr/include/x86_64-linux-gnu/sys/select.h:118:12: note: previous
declaration is here
extern int pselect (int __nfds, fd_set *__restrict __readfds,
           ^
While building module 'foo' imported from test.cpp:2:
In file included from <module-includes>:1:
In file included from
/home/stephen/dev/src/playground/modules/modulestry/include/foo.h:4:
In file included from /usr/include/stdlib.h:314:
In file included from /usr/include/x86_64-linux-gnu/sys/types.h:270:
/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h:63:7: error: redefinition
of 'pthread_attr_t'
union pthread_attr_t
      ^
/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h:63:7: note: previous
definition is here
union pthread_attr_t
      ^
While building module 'foo' imported from test.cpp:2:
In file included from <module-includes>:1:
In file included from
/home/stephen/dev/src/playground/modules/modulestry/include/foo.h:4:
In file included from /usr/include/stdlib.h:314:
In file included from /usr/include/x86_64-linux-gnu/sys/types.h:270:
/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h:75:16: error: redefinition
of '__pthread_internal_list'
typedef struct __pthread_internal_list
               ^
/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h:75:16: note: previous
definition is here
typedef struct __pthread_internal_list
               ^
While building module 'foo' imported from test.cpp:2:
In file included from <module-includes>:1:
In file included from
/home/stephen/dev/src/playground/modules/modulestry/include/foo.h:4:
/usr/include/stdlib.h:343:8: error: redefinition of 'random_data'
struct random_data
       ^
/usr/include/stdlib.h:343:8: note: previous definition is here
struct random_data
       ^
fatal error: too many errors emitted, stopping now [-ferror-limit=]
test.cpp:2:10: fatal error: could not build module 'foo'
#include "foo.h"
~~~~~~~~^~~~~~~

int main(int, char **)
{
  return 0;
}
21 errors generated.

To "fix" that, I created this module.modulemap in /usr/include :

module systemheaders {
  header "stdio.h"
  header "stdlib.h"
  header "math.h"
}

After I did that, I was able to create a Qt5Core.modulemap on linux. I
expect that file to grow if I add more modules for other Qt libraries.

I do find all this very inconvenient, and I expect things like this will
hurt adoption for some time until there's a better solution in place (eg
having modulemaps already in place).

Thanks,

Steve.

Sean Silva wrote:

My experience has been that the easiest thing is to start out by just
doing a "unity module" like

module foo {
header "bar"
header "baz"
...
}

Just list every file in the directory (possibly recursively). Then just
exclude any headers that are causing problems. That should get you up and
running pretty fast.

I did this for Qt5Core and came up with

http://www.steveire.com/Qt5Core.modulemap

What is the next step?

I'd like to understand more about the modulemap language and what should be
specified there. What is the 'export *' stuff for? Qt headers define some
macros such as Q_DECL_CONSTEXPR. Do they need to be explicitly
named/exported in the modulemap file? The macro seems to work fine without
such an export.

The headers that I exclude from the include/QtCore folder are:

qatomic_armv5.h
qatomic_armv6.h
qatomic_armv7.h
qatomic_bootstrap.h
qatomic_cxx11.h
qatomic_gcc.h
qatomic_ia64.h
qatomic_mips.h
qatomic_msvc.h
qatomic_unix.h
qatomic_x86.h
qconfig-dist.h
qconfig.h
qconfig-large.h
qconfig-medium.h
qconfig-minimal.h
qconfig-nacl.h
qconfig-small.h
qobjectdefs_impl.h
qobject_impl.h
qsharedpointer_impl.h
qt_windows.h

I *could* include qatomic_x86.h to the modulemap, but that header is not
designed for users to include. Users include qatomic.h instead, which
includes the appropriate _foo header.

The _impl headers are also not designed to be included directly, so not
including those in the modulemap also makes sense to me. I suppose the
appropriate version gets compiled into the module binary file included via
the public header.

I guess on windows, qt_windows.h would need to be included in the modulemap
(assuming windows.h was in another module, probably). So, we would have to
generate the modulemap at the time of building/packaging Qt.

Thanks,

Steve.

Sean Silva wrote:

> My experience has been that the easiest thing is to start out by just
> doing a "unity module" like
>
> module foo {
> header "bar"
> header "baz"
> ...
> }
>
> Just list every file in the directory (possibly recursively). Then just
> exclude any headers that are causing problems. That should get you up and
> running pretty fast.

I did this for Qt5Core and came up with

http://www.steveire.com/Qt5Core.modulemap

What is the next step?

It depends on what your goals are. Once I got an initial module map
working, the first thing I did was to analyze build time. If you are on
Mac, then the attached patch to clang and the attached DTrace script could
prove useful. Using the instrumented clang as your compiler, the DTrace
script will print out how much total time Clang spends parsing each file,
summed across the entire build (you will probably want to redirect its
output to a file since it will be printing something for every file in the
build; it also has some PHONY_* targets that account for time not spent
parsing). With a small amount of post-processing, you can generate pie
charts like http://i.imgur.com/8eXR8rG.png or http://i.imgur.com/qNxwZhD.png
. If you aren't familiar with Dtrace or need help post-processing the
output feel free to let me know and I can help. The script can also be
tweaked to collect interesting information like the total number of times
each file is included.

The "toss them all in a single top-level module" approach causes *all* the
headers to be included if any of them is included. If this is problematic
for your use case, then the next step might be to replace every `header
"foo.h"` with

module foo_h {
  header "foo.h"
  export *
}

(still nested within the top-level module)

The `export *` just means "export declarations from any modules I depend
on", which is what you almost always want at the moment since that matches
textual inclusion semantics. I.e. if someone was including "QSubclass" and
relying on that include to bring in "QBaseclass" (or a system header or
whatever).

I'd like to understand more about the modulemap language and what should be
specified there. What is the 'export *' stuff for? Qt headers define some
macros such as Q_DECL_CONSTEXPR. Do they need to be explicitly
named/exported in the modulemap file? The macro seems to work fine without
such an export.

The headers that I exclude from the include/QtCore folder are:

qatomic_armv5.h
qatomic_armv6.h
qatomic_armv7.h
qatomic_bootstrap.h
qatomic_cxx11.h
qatomic_gcc.h
qatomic_ia64.h
qatomic_mips.h
qatomic_msvc.h
qatomic_unix.h
qatomic_x86.h
qconfig-dist.h
qconfig.h
qconfig-large.h
qconfig-medium.h
qconfig-minimal.h
qconfig-nacl.h
qconfig-small.h
qobjectdefs_impl.h
qobject_impl.h
qsharedpointer_impl.h
qt_windows.h

I *could* include qatomic_x86.h to the modulemap, but that header is not
designed for users to include. Users include qatomic.h instead, which
includes the appropriate _foo header.

This will break if multiple headers in the module map end up including
qatomic.h (whichever one comes first will include the declarations of
qatomic.h). If qatomic.h is only included from a single header in the
module map you should be fine though.

-- Sean Silva

dtraceprobes.patch (6.58 KB)

dtraceprobes.d (1.76 KB)

Any idea what's going wrong?

$ clang++ -E -fmodules test.cpp
# 1 "test.cpp"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 325 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "test.cpp" 2
While building module 'std' imported from test.cpp:6:
In file included from <module-includes>:4:
In file included from
/Users/ske/dev/prefix/bin/../include/c++/v1/ccomplex:21:
In file included from
/Users/ske/dev/prefix/bin/../include/c++/v1/complex:247:
In file included from
/Users/ske/dev/prefix/bin/../include/c++/v1/sstream:174:
In file included from
/Users/ske/dev/prefix/bin/../include/c++/v1/ostream:140:
/Users/ske/dev/prefix/bin/../include/c++/v1/locale:873:26: error: use of
undeclared identifier 'strtoll_l'; did you mean 'wcstoll_l'?
        long long __ll = strtoll_l(__a, &__p2, __base,
_LIBCPP_GET_C_LOCALE);

I ran into this too ( http://llvm.org/bugs/show_bug.cgi?id=21003 ). It went
away for me when building with -fno-exceptions. Maybe you can post the
number of the rdar you filed on that bug? With -fno-exceptions and
http://llvm.org/viewvc/llvm-project?rev=218372 (or -std=c++11), I was able
to use modules on OS X for a small program (ninja) 4 weeks ago.

(I didn't read the whole thread, sorry if this is redundant information.)

Any idea what's going wrong?

$ clang++ -E -fmodules test.cpp
# 1 "test.cpp"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 325 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "test.cpp" 2
While building module 'std' imported from test.cpp:6:
In file included from <module-includes>:4:
In file included from
/Users/ske/dev/prefix/bin/../include/c++/v1/ccomplex:21:
In file included from
/Users/ske/dev/prefix/bin/../include/c++/v1/complex:247:
In file included from
/Users/ske/dev/prefix/bin/../include/c++/v1/sstream:174:
In file included from
/Users/ske/dev/prefix/bin/../include/c++/v1/ostream:140:
/Users/ske/dev/prefix/bin/../include/c++/v1/locale:873:26: error: use of
undeclared identifier 'strtoll_l'; did you mean 'wcstoll_l'?
        long long __ll = strtoll_l(__a, &__p2, __base,
_LIBCPP_GET_C_LOCALE);

I ran into this too ( http://llvm.org/bugs/show_bug.cgi?id=21003 ). It
went away for me when building with -fno-exceptions. Maybe you can post the
number of the rdar you filed on that bug? With -fno-exceptions and
http://llvm.org/viewvc/llvm-project?rev=218372 (or -std=c++11), I was
able to use modules on OS X for a small program (ninja) 4 weeks ago.

(I didn't read the whole thread, sorry if this is redundant information.)

To summarize the root cause of the issue upthread, it was that <xlocale.h>
does some nasty non-modular things, which are intrinsically broken by
modules (basically, it makes sure that the _l functions are exported if
user code has included or will include <stdlib.h> et al.). I can't imagine
how building with -fno-exceptions would change this, so maybe the issues
are unrelated.

-- Sean Silva

Nico Weber wrote:

I ran into this too ( http://llvm.org/bugs/show_bug.cgi?id=21003 ). It
went away for me when building with -fno-exceptions. Maybe you can post
the number of the rdar you filed on that bug?

I don't know what rdar is.

(I didn't read the whole thread, sorry if this is redundant information.)

I think so :).

Thanks,

Steve.

Sean Silva wrote:

I did this for Qt5Core and came up with

http://www.steveire.com/Qt5Core.modulemap

What is the next step?

It depends on what your goals are.

My goal is to gain experience with clang modules for C++, and possibly to be
able to communicate the principles behind the design of them, the gotchas,
the limitations, the requirements and the benefits. I'm learning what I'd
need to know to write useful blogs of give a useful talk at a conference or
meetup.

So, that's why I want to get from 'this file I hacked together does not
cause explosions' to 'Here are the other things you can put in a modulemap
file and why you would want to'.

Once I got an initial module map
working, the first thing I did was to analyze build time. If you are on
Mac, then the attached patch to clang and the attached DTrace script could
prove useful.

Cool, thanks. I'll try this at some point too for sure.

The "toss them all in a single top-level module" approach causes *all* the
headers to be included if any of them is included.

Ah! Wow, that's certainly slide-worthy. So

#include <QtCore/QString>

int main(int, char **)
{
   QString s;
   QObject o;
   QStringListModel m;
   return 0;
}

compiles with -fmodules but not without it.

That's weird at least.

The `export *` just means "export declarations from any modules I depend
on", which is what you almost always want at the moment since that matches
textual inclusion semantics. I.e. if someone was including "QSubclass" and
relying on that include to bring in "QBaseclass" (or a system header or
whatever).

... ie

#include <QWidget>

int main(int, char **)
{
   QObject o;
   return 0;
}

compiles without -fmodules and fails with it, until I add export *.

I'll add that to my qmake patch for generating the modules for now. In that
patch I can be more-exact though about what to export (qmake knows which
modules are dependencies). Is there any advantage to doing that? Although I
can think of a case in the QtSql module I'd have to examine for a breakage
case (QSqlRelationalDelegate includes QtWidget classes, but qmake may not
consider that a module-dependency).

I *could* include qatomic_x86.h to the modulemap, but that header is not
designed for users to include. Users include qatomic.h instead, which
includes the appropriate _foo header.

This will break if multiple headers in the module map end up including
qatomic.h (whichever one comes first will include the declarations of
qatomic.h). If qatomic.h is only included from a single header in the
module map you should be fine though.

It is included by multiple headers. I don't understand the problem though
you're bringing up though. All TUs are expected to use the same
qatomic_foo.h.

What is the breakage case you're warning against?

Thanks,

Steve.

Stephen Kelly wrote:

To "fix" that, I created this module.modulemap in /usr/include :

module systemheaders {
header "stdio.h"
header "stdlib.h"
header "math.h"
}

After I did that, I was able to create a Qt5Core.modulemap on linux. I
expect that file to grow if I add more modules for other Qt libraries.

The Qt headers include very few external headers. Apart from the QtTest
module, it's only a few STL headers, and platform-specific opengl headers.

In order to be able to build the Qt5Test.modulemap, I had to extend the file
I hacked together in /usr/include/module.modulemap like so:

module system {
   header "stdio.h"
   header "stdlib.h"
   header "math.h"
   module system_c [extern_c] {
     header "inttypes.h"
   }
}

If I keep going like this, my /usr/include/module.modulemap will refer to
headers which come from different debian packages. This seems unacceptable
to me, but you'd have to talk to some packagers to make sure. (for modules
to be viable on linux, I'm sure you have to somehow solve the system headers
case or make it solvable).

So, a solution would be to use the new mechanism to specify multiple module
map files. However, it would be unsatisfying to have to specify many

/usr/include/{foo,bar,bat}.modulemap

files using -fmodule-map-file, because it is a system location. I can easily
think of some options for improving that situation, and I'm sure there are
more options:

1) Add option to give the clang driver a module map directory

Then packages would install their modulemap to a well-known location and all
modulemaps in that location would get loaded

${prefix}/modulemaps/{foo,bar,bat}.modulemap

and

clang -fmodules -fmodule-map-dir=${prefix}

loads all module maps in ${prefix}.

This solution has the disadvantage that authors would have to write

header "../foo.h"

and similar, unless clang had built-in logic to look up a directory.

System locations should be built-in without being specified, so I never have
to write

-fmodule-map-dir=/usr/include/modulemaps

or anything. Maybe clang should automatically look in ${dir}/modulemaps for
each -I${dir} passed on the command line (and each built-in dir) and load
any modulemaps found in those directories.

2) Clang could load *.modulemap, not only module.modulemap from each dir

This seems like a simple solution and doesn't require '..' paths.

3) Files in ${dir}/modulemaps/* are redirects to '..'

Ie, packages would install

/usr/include/foo.modulemap
/usr/include/foo.h
/usr/include/modulemaps/foo.redirect

and foo.redirect would contain some syntax to make clang behave as if

-fmodule-map-file=/usr/include/foo.modulemap

was passed. Eg, foo.redirect might contain only

../foo.modulemap

and then foo.modulemap would not need '..' paths.

Thanks,

Steve.

(sorry for the delay, the dev meeting has been keeping me busy from sun-up to sun-down for the last two days)

Stephen Kelly wrote:

> To "fix" that, I created this module.modulemap in /usr/include :
>
> module systemheaders {
> header "stdio.h"
> header "stdlib.h"
> header "math.h"
> }
>
> After I did that, I was able to create a Qt5Core.modulemap on linux. I
> expect that file to grow if I add more modules for other Qt libraries.

The Qt headers include very few external headers. Apart from the QtTest
module, it's only a few STL headers, and platform-specific opengl headers.

In order to be able to build the Qt5Test.modulemap, I had to extend the
file
I hacked together in /usr/include/module.modulemap like so:

module system {
   header "stdio.h"
   header "stdlib.h"
   header "math.h"
   module system_c [extern_c] {
     header "inttypes.h"
   }
}

If I keep going like this, my /usr/include/module.modulemap will refer to
headers which come from different debian packages. This seems unacceptable
to me, but you'd have to talk to some packagers to make sure. (for modules
to be viable on linux, I'm sure you have to somehow solve the system
headers
case or make it solvable).

You might want to try using the `extern module foo "foo.modulemap"` syntax
in the root module map. This doesn't solve the installation problem, but it
might simplify things for now. I think that the typical package-based Linux
platform (with end-users installing and uninstalling headers into the same
directories) is currently a poorly-represented use case. If you can find a
system that seems to work well for that use case in practice, I think we
would take a patch to support it; unfortunately I don't think there is
anybody working on modules right now that has this use case as a priority,
so it really is "patches welcome".

-- Sean Silva

Sean Silva wrote:

You might want to try using the `extern module foo "foo.modulemap"` syntax
in the root module map.

I filed a bug to track this:

http://llvm.org/bugs/show_bug.cgi?id=21593

so it really is "patches welcome".

It isn't really.

First, the solution needs to be decided/designed.

After that patches will be welcome.

Thanks,

Steve.

Sean Silva wrote:
>
> You might want to try using the `extern module foo "foo.modulemap"`
syntax
> in the root module map.

I filed a bug to track this:

http://llvm.org/bugs/show_bug.cgi?id=21593

Thanks. I'm not sure how much attention it will get in bugzilla. You may
want to start a discussion on cfe-dev.

> so it really is "patches welcome".

It isn't really.

First, the solution needs to be decided/designed.

After that patches will be welcome.

I meant "patches welcome" in the more general sense of "involvement from
someone who has this as a priority and is willing to champion for it is
needed".

-- Sean Silva