Hi Yan,

Thanks for such a detailed response -- much appreciated. Your patch is in SVN
now, by the way.

On 1 December 2012 at 15:02, Yan Zhou wrote:
| Hi Dirk,
| 
| Thanks for the quick reply.
| 
| 
| > Nice, that does look indeed clean and proper.  Can you tell me a bit more
| > about the setup you have use:
| > 
| >  -- operating system and version
| I have tested the patch on Mac OS X 10.8.2 and Ubuntu 12.10. R is built from 
scratch by myself using the compilers of concern instead of the official 
binaries.

Great. We do need help with OS X, as "the world" needs help with OS X and the
mess over the silly standoff with the FSF.  Getting clang++ ready will help.

I run more Ubuntu than Debian these days, usually, but I know that over on
the Debian side it is pretty easy to get prebuilt g++ (now up to 4.8 in the
experimental repo) and 3.2 for clang.  And I do keep chroots around for quick
tests.

| >  -- compiler(s) and version(s), at least clang++ and intel's icpc (wasn't it
| >     called icc ?)
| Clang is clang 3.1 (though branded as clang 4.1 by Apple, it is actually LLVM 
3.1) on Mac OS X, and the SVN version on Linux. Intel icpc is tested with, 
12.0, 12.1 and 13.0 on Linux. icpc is the C++ compiler, icc is the C compiler. 
Just like g++ is actually gcc with another name.

Right, thanks.

| >  -- where libc++ came from
| libc++ can be obtained from http://libcxx.llvm.org

I think it is in Ubuntu now too my apt-cache foo now fails me on the embedded
regexp in libc++ ... :-/  

| It also comes with Apple Xcode 4.2 or later (maybe 4.3, not sure the oldest 
version come with libc++, I am using Xcode 4.5.2). It is a new standard C++ 
library implementation. It can only be used with clang at the time of writing. 
It is also part of the LLVM project, which clang belongs too. On Mac OS X, and 
FreeBSD, there have been an effort to replace the GCC tool chain with LLVM tool 
chain for quite a few years, mainly due to GCC 4.3 or later's GPL3 status and 
other technical considerations. Anyway, on Mac OS X and FreeBSD, the official 
build of GCC is 4.2, newer versions are not officially supported anymore. 
Currently Apple ship LLVM-GCC as a backward compatibility solution in Xcode. In 
the near future Apple will stop shipping this GCC 4.2 variant entirely, and 
leave the platform with only Clang. On FreeBSD, Clang is also set to replace 
GCC as the default tool chain in the next version. 

We are aware of this, and it is a constant issue. 
 
| libc++ is C++98 conforming and at the time of writing the only 100% feature 
complete C++11 implementation of standard library. But it does not come with 
TR1 mainly because when the project took off, C++11 is already on the horizon 
and they decided to support C++11 directly. Also this the only standard library 
one can use on Mac OS X if C++11 is desired, or otherwise one need to build a 
GCC from scratch themselves.
| 
| The situation with Clang and Intel icpc is that, they do not bind to a 
specific version of standard library. They are just compilers. Unlike GCC, say 
we are using GCC 4.7, it is not possible for G++ to include headers from or 
link to a version of libstdc++ other than the one distributed with GCC 4.7 
unless we do something tricky. With Intel icpc, at least on Linux and Mac OS X, 
icpc find whatever version of GCC on the system. For example, if the system 
comes with GCC 4.2, then icpc use libstdc++ 4.2. Even the version of icpc 
supports a lot of new C++11 features, you can not use them at all. To use C++11 
features, one not only need a new version of icpc, but also a new version of 
GCC, which comes with a new version of libstdc++. So the situation is a mess. 
Clang is similar, it can use whatever version of libstdc++ or libc++ installed 
on the system.
| > 
| >  -- in case you timed this, what performance differences do you see?
| I am not sure what kind of timing are suggested

Any, really :)   R itself has regression tests for which you can turn on
timing.  And in industry, the only time I meet people talking intel icc are
usually those who want to shave a micro or nanosecond here or there :)

You are more concerned with buildability first?

| > This is very nice news for less-standard systems.  Just so that I remain on
| > the same page, these do still generate gcc-compatible code so what you
| > generate does in fact interoperates with code on your system which may have
| > been built by gcc, correct?
| Almost YES. Clang and icpc generate GCC compatible binary code. But libc++ is 
not always libstdc++ compatible at binary level. They are mostly compatible 
except for some IO facilities. As long as <iostream> etc. are not involved, 
they are binary compatible. I don't think it will be an issue. Because if 
someone is going to built Rcpp with libc++, then the compiler flag 
-stdlib=libc++ shall be provided when buidling R itself, or he/she shall always 
remember to use this flag when incorporate other C++ code. The situation I am 
trying to solve is that, both Intel icc and clang can built R and pass all of 
R's test suites. It is better to have their corresponding C++ compiler able to 
build a popular R package. If a compiler does not built R at all, e.g., MSVC, 
we don't have to worry about if Rcpp works with it. In the case of clang++ and 
icpc, I think the cost is small, while the benefits is one can use many of 
their C++11 code while using Rcpp at the same time. We cannot possibly
  support all compilers that can build R. Besides building R only need C 
compiler while the CXXFLAGS are only captured by R build script for future use 
(for example when install.packages("Rcpp")). However, if it is not too much a 
trouble, support some C++11 implementation can be nice.

Absolutely. 

Our attitude has been that as along as CRAN does not let us set C++11 as a
build option for Rcpp, there is little point in pushing for it.

| The current patch won't pass all unit test, because some unit test use the 
tr1:: namespace explicitly, while the solution is to have Clang and other 
compilers use std::unordered_map etc while it is available. If I may suggest, 
if we are willing to make some bigger change, we can solve the situation of 
compilers other than GCC more elegant. For example, we can have the following 
in RcppCommon.h, it may make the RcppCommon.h looks a little more tedious, but 
shall hopefully cleanup all the mess. My patch in the last email only touch 
RcppCommon.h and work around the fact that other headers like sugar/sets.h also 
test and set macros about std::unordered_set or tr1::unordered_set.
| 
| #include <cmath>
| #if defined(__INTEL_COMPILER)
|     #if defined(__GLIBCXX__) && __GLIBCXX__ >= 20090421
|     #define HAS_TR1_UNORDERED_MAP
|     #define HAS_TR1_UNORDERED_SET
|     #endif
| 
|     #if __cplusplus >= 201103L
|         #if defined(__GLIBCXX__) && __GLIBCXX__ >= 20090421
|         #define HAS_CXX11_UNORDERED_MAP
|         #define HAS_CXX11_UNORDERED_SET
|     #endif
| #elif defined(__clang__)
|     #if __has_include<tr1/unordered_map>
|     #define HAS_TR1_UNORDERED_MAP
|     #endif
| 
|     #if __has_include<tr1/unordered_set>
|     #define HAS_TR1_UNORDERED_SET
|     #endif
| 
|     #if __cplusplus >= 201103L
|         #if __has_include<unordered_map>
|         #define HAS_CXX11_UNORDERED_MAP
|         #endif
| 
|         #if __has_include<unordered_set>
|         #define HAS_CXX11_UNORDERED_SET
|         #endif
|     #endif
| #elif defined(__GNUC__)
| // test GCC the last, as both clang and intel defines __GNUC__
| #define GCC_VERSION \
|     (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
|     #if GCC_VERSION >= 40201
|     #define HAS_TR1_UNORDERED_MAP
|     #define HAS_TR1_UNORDERED_SET
|     #endif
| 
|     #ifdef __GXX_EXPERIMENTAL_CXX0X__
|         #if GCC_VERSION >= 40400 // maybe another earlier version also works
|         #define HAS_CXX11_UNORDERED_MAP
|         #define HAS_CXX11_UNORDERED_SET
|         #endif
|     #endif
| 
| #endif
| 
| #if defined(HAS_CXX11_UNORDERED_MAP)
| #include <unordered_map>
| #define RCPP_MAP std::unordered_map
| #elif defined(HAS_TR1_UNORDERED_MAP)
| #include <tr1/unordered_map>
| #define RCPP_MAP tr1::unordered_map
| #else
| #include <map>
| #define RCPP_MAP tr1::map
| #endif
| 
| #if defined(HAS_CXX11_UNORDERED_SET)
| #include <unordered_set>
| #define RCPP_SET std::unordered_set
| #elif defined(HAS_TR1_UNORDERED_SET)
| #include <tr1/unordered_set>
| #define RCPP_SET tr1::unordered_set
| #else
| #include <set>
| #define RCPP_SET tr1::set
| #endif
| 
| // The rest of the library does not need to test __cplusplus etc.
| // They only need to know RCPP_MAP and RCPP_SET
| // All test are taken care inside RcppCommon.h
| 
| With the above additions, other headers and source files hall not test 
__cplusplus >= 201103L etc. They shall just used RCPP_MAP and RCPP_SET whenever 
they need them. And if later we find that some compilers version are not 
properly tested by the above code, we only need to fix it in RcppCommon.h 
without any change to other parts of the library.

I am on board. RcppCommon.h is the place to do this, and we can (and are)
pushing the defines down to good use.  If you can help with testing I am
absolutely in favour of supporting this.

This weekend is bad, but let's keep this on the agenda.  Please ping me again
if you do not hear from me.

Thanks again for all of this -- much appreciated!

Dirk


 
| Best,
| 
| Yan Zhou
| 
| > 
| > Dirk
| > 
| > | 
| > | 
| > | Best,
| > | 
| > | Yan Zhou
| > | 
| > | On Dec 1, 2012, at 12:44 PM, Yan Zhou <zhou...@me.com> wrote:
| > | 
| > | > Dear Dirk,
| > | > 
| > | > In addition to my last email which provides a path for clang++ with 
libc++, I updated the patch to also fix problems with intel icpc in C++11 mode.
| > | > 
| > | > In the RcppCommon.h, there is comments says that Intel ICPC does not 
support C++11 or TR1. That is not entirely true. Intel compiler does not come 
with its own standard library. On Linux and Mac OS X it use the libstdc++ come 
with the system. On Windows it may use others.  The current test has a problem 
when an Intel C++ compiler is used in C++11 mode. In that case, headers like 
sugar/sets.h test the C++11 macro and conclude it shall define SET to 
std::unordered_set. However, C++11 <unordered_set> is not included. So a 
compiler error happens.
| > | > 
| > | > In general, I found Rcpp does not work with compilers in C++11 mode. 
The new path, in addition to the own test Clang with libc++, also test the 
followings,
| > | > 1. If Intel compiler is used, test is it is used with libstdc++. If it 
is not, then we undef HAS_TR1_... etc. To test if libstdc++ is used, we need to 
at least include one standard library header before the testing, so I included 
<cmath>, which shall be harmless
| > | > 2. After trying to include <tr1/unodered_map> etc, we also test if we 
are using C++11. If it is, then test if we are using libstdc++ (either gcc, 
clang, intel etc). If it is case, and the libstdc++ is recent enough, we 
include <unordered_map> and <unordered_set>. Otherwise, if we are using C++11 
in Clang with libc++, we also included <unodered_map> etc.
| > | > 
| > | > After this patch, Rcpp shall work seamlessly with GCC, Intel and Clang, 
in both C++98 and C++11 modes.
| > | > <RcppCommon.h.diff>
| > | > 
| > | > Best,
| > | > 
| > | > Yan Zhou
| > | > 
| > | > 
| > | > 
| > | > On Dec 1, 2012, at 12:12 PM, Yan Zhou <zhou...@me.com> wrote:
| > | > 
| > | >> Hi Dirk,
| > | >> 
| > | >> Rcpp cannot be compiled with clang++ with libc++, even clang++  
provides very good standard conforming in both C++98 and C++11 mode, and libc++ 
provides 100% C++98/11 features. The problems is Rcpp's use of TR1 instead of 
C++11, and does not perform some compiler checks properly. I made a small patch 
to the include/RcppCommon.h header, which makes Rcpp works with Clang++ and 
libc++ in C++11 mode.
| > | >> 
| > | >> To summary the change, when macro __clang__ is defined, the header use 
clang's __has_include to check if <tr1/unordered_map> and <tr1/unordered_set> 
is present, if not, it undef HAS_TR1_UNORDERED_MAP etc. In addition, if 
__has_include<unordered_map> is tested to be true while HAS_TR1_... etc are not 
true, the C++11 header is included. So  headers like sugar/sets.h can use C++11 
header instead of TR1, since they already test __cplusplus >= 201103L.
| > | >> 
| > | >> With this patch, nothing already works will be broken. This patch only 
affects clang++ with libc++ situation. Using clang++ with libstdc++ the 
situation will be exactly the same as before.
| > | >> 
| > | >> At the end of the email is the path, it is also attached as a diff file
| > | >> 
| > | >> Best,
| > | >> 
| > | >> Yan Zhou
| > | >> <RcppCommon.h.diff>
| > | >> 
| > | >> --- Rcpp/inst/include/RcppCommon.h     2012-11-23 01:07:34.000000000 
+0000
| > | >> +++ ../Downloads/Rcpp/inst/include/RcppCommon.h        2012-12-01 
11:46:48.000000000 +0000
| > | >> @@ -107,6 +107,20 @@
| > | >> //     #endif
| > | >> // #endif
| > | >> 
| > | >> +#ifdef __clang__
| > | >> +    #if !__has_include(<tr1/unordered_map>)
| > | >> +        #undef HAS_TR1
| > | >> +        #undef HAS_TR1_UNORDERED_MAP
| > | >> +    #endif
| > | >> +    #if !__has_include(<tr1/unordered_set>)
| > | >> +        #undef HAS_TR1
| > | >> +        #undef HAS_TR1_UNORDERED_SET
| > | >> +    #endif
| > | >> +    #if !__has_feature(cxx_variadic_templates)
| > | >> +        #undef HAS_VARIADIC_TEMPLATES
| > | >> +    #endif
| > | >> +#endif
| > | >> +
| > | >> #ifdef __INTEL_COMPILER
| > | >>    // This is based on an email by Alexey Stukalov who tested 
| > | >>    // Intel Compiler 12.0 and states that is does support Cxx0x 
| > | >> @@ -149,6 +163,15 @@
| > | >> #include <tr1/unordered_set>
| > | >> #endif
| > | >> 
| > | >> +#ifdef __clang__
| > | >> +    #if !defined(HAS_TR1_UNORDERED_MAP) && 
__has_include(<unordered_map>)
| > | >> +    #include <unordered_map>
| > | >> +    #endif
| > | >> +    #if !defined(HAS_TR1_UNORDERED_SET) && 
__has_include(<unordered_set>)
| > | >> +    #include <unordered_set>
| > | >> +    #endif
| > | >> +#endif
| > | >> +
| > | >> std::string demangle( const std::string& name) ;
| > | >> #define DEMANGLE(__TYPE__) demangle( typeid(__TYPE__).name() ).c_str() 
| > | >> 
| > | >> 
| > | >> _______________________________________________
| > | >> Rcpp-devel mailing list
| > | >> Rcpp-devel@lists.r-forge.r-project.org
| > | >> https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel
| > | > 
| > | > _______________________________________________
| > | > Rcpp-devel mailing list
| > | > Rcpp-devel@lists.r-forge.r-project.org
| > | > https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel
| > | 
| > | 
| > | ----------------------------------------------------------------------
| > | _______________________________________________
| > | Rcpp-devel mailing list
| > | Rcpp-devel@lists.r-forge.r-project.org
| > | https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel
| > -- 
| > Dirk Eddelbuettel | e...@debian.org | http://dirk.eddelbuettel.com  
| 

-- 
Dirk Eddelbuettel | e...@debian.org | http://dirk.eddelbuettel.com  
_______________________________________________
Rcpp-devel mailing list
Rcpp-devel@lists.r-forge.r-project.org
https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel

Reply via email to