Wednesday, August 13, 2014

Quick Test Needed for Boost.TypeIndex under Clang

I don't have Clang here (Windows ghetto, sorry), and I haven't been able to find an online Clang compiler that has the Boost headers available, so I'd be grateful if somebody would run the following program under Clang with the latest Boost and let me know (as a blog comment, so that people will know that the work has already been done) what the output is.

Thanks.

Scott


#include <iostream>
#include <vector>
#include <boost/type_index.hpp>

template<typename T>
void f(const T& param)
{
  using std::cout;
  using boost::typeindex::type_id_with_cvr;
  // show T
  cout << "T = "
       << type_id_with_cvr<T>().pretty_name()
       << '\n';
  // show param's type
  cout << "param = "
       << type_id_with_cvr<decltype(param)>().pretty_name()
       << '\n';

}

class Widget {};

std::vector<Widget> createVec()
{
  return std::vector<Widget>(5);
}

int main()
{
  const auto vw = createVec();
  if (!vw.empty()) {
    f(&vw[0]);
  }
} 

38 comments:

Rapptz said...

Some good online compilers:

- http://coliru.stacked-crooked.com/
- http://melpon.org/wandbox/

Scott Meyers said...

@Rapptz: I tried Coliru before posting. The Boost headers aren't available there, at least not by default. I had not heard of Wandbox, but the Boost version they have there is 1.55, and Boost.TypeIndex is new to 1.56, hence my request to run the code with the latest Boost.

Rapptz said...

@Scott Yeah I realised that after posting. Sorry. Unfortunately I don't have Boost 1.56, just Boost 1.55 and it seems like the folks I know share the same limitations.

godbyk said...

Running clang++ version 3.5.0-svn213717 under Ubuntu 14.04, your program outputs the following:

T = Widget const*

param = Widget const* const&

Scott Meyers said...

@godbyk: That's the kind of output I was hoping for. Thanks very much!

alfC said...

This type_index library looks like a good replacement for std::type_info, typeid, demanglers and company. Is it so?

İsmail Dönmez said...

clang does run on Windows and currently it can compile a lot of C++ code, see http://llvm.org/builds/

iss lam said...

hi İsmail Dönmez
i tried to use the llvm on windows as you said but it always generate erreur like this
cannot compile this try statement yet

Anonymous said...

Even Windows ghetto's can run VirtualBox.

Joe said...

Clang 3.4.1 is available for Windows:

http://llvm.org/releases/download.html#3.4.1

Scott Meyers said...

@İsmail Dönmez and Joe: I downloaded and installed Clang for Windows, but clang can't find any system include files. My searching for a way to specify the include search path has come up empty. Can you point me to information on how to specify the path to the system include files?

Scott Meyers said...

@alfc: That looks to be the goal of the library.

Klaim - Joel Lamotte said...

Clang on windows don't allow exceptions yet, so it's not useful anyway.

Seth said...

-isystem is used to manually specify system header paths. However I believe your issue is actually the default target. Clang appears to target mingw by default on Windows. (You can use the -v option to get verbose information, including the target and the search paths, or the -### option to see the exact compiler command invoked by the compiler driver.)

You can change the target with the -target option. You (probably) want the target "i686-pc-windows-msvc". This worked for me from the VS2013 dev command prompt:

clang++ -target i686-pc-windows-msvc main.cpp

Of course as noted by others exceptions are not yet supported, which limits its usefulness for trying things out.

melpon said...

I'm Wandbox developer.
We installed Boost-1.56 to Wandbox.

- http://melpon.org/wandbox/permlink/TCFAiod3SrW7NakD

Wandbox is running on Ubuntu 12.04 LTS.

Scott Meyers said...

@melpon: Thanks for upgrading Boost and for running my test!

Scott Meyers said...

@Seth: It looks like the binary I installed doesn't include any C++ headers. http://clang.llvm.org/get_started.html suggests I need to find a way to tell it where my gcc headers are (though I'd hoped to be able to try using libc++).

If anybody has any ideas how I can configure clang++ so that it knows where my gcc headers are (other than using -I directives for every compilation), please chime in!

Seth said...

I don't think libc++ supports WIndows well yet. You could probably get it working in a mingw or cygwin environment, using whatever the gcc c++abi library is in those environments.

Clang intends to be ABI compatible with the platform, which means using the platform's C++ library implementation. On Windows it supports mingw, cygwin, and visual studio. The corresponding targets are i686-pc-windows-[gnu|cygnus|msvc].

You can use the -v flag to list the places clang looks for headers (including places it checks that don't exist) and then make sure whatever you have installed is installed in one of those places. Clang should be checking the default install locations.

If you've installed things in another location you can use the --sysroot option. I think command line options are the only built-in way to configure it, but you can set up a makefile or other script that sets the option for you.

Also, I've found that defining _HAS_EXCEPTIONS=0 allows clang to compile a lot of code using the MSVC++ headers, so it's more useful than I last indicated.

Seth said...

In order to get the list of header search paths from the -v option you actually have to be compiling something. -v without an input file will just show the version and target.

Scott Meyers said...

@Seth: I found the right -I incantations to get compilation to succeed. Linking is a separate problem, of course, but one thing at a time. It's too bad that there doesn't seem to be a way to configure the environment so that I don't have to specify three -I options for each compilation.

Seth said...

Yeah, it really shouldn't take that much. Can you tell why the default configuration isn't working for you? What does the verbose output say?

Scott Meyers said...

@Seth: My guess is that the default configuration isn't working for me, because I don't have MinGW installed in the default location. That's probably why I have to compile with -IC:\Users\Scott\Apps\MinGW\include\c++\4.9.1 -IC:\Users\Scott\Apps\MinGW\include\c++\4.9.1\x86_6
4-w64-mingw32 -IC:\Users\Scott\Apps\MinGW\x86_64-w64-mingw32\include. It seems silly that there's no easy way to tell clang (or LLVM--I'm not sure) where MinGW is installed.

Oh well, I'll figure it out.

Seth said...

It looks like a different directory structure is expected for a sysroot than MinGW provides, so that's why that option won't work for you. Instead the default configuration still relies on hard-coded paths to work with MinGW.

The easiest solution is probably to create a symbolic link from C:\MinGW to your C:\Users\Scott\Apps\MinGW

From an elevated command prompt, run:

mklink /D C:\MinGW C:\Users\Scott\Apps\MinGW

Additionally you need to ensure that C:\MinGW\bin is in your PATH.

From the command prompt where you'll run clang:

PATH=%PATH%;C:\MinGW\bin

After these two steps clang is able to produce executables from source for me using a MinGW install at a non-standard location. Just:

clang++ main.cpp

Scott Meyers said...

Adding the symlink doesn't help. If you're interested in seeing what clang is saying, I've uploaded the relevant output to https://drive.google.com/file/d/0B9Rd8ysNU0pXUmdPNkdCelA4RjA/edit?usp=sharing .

Seth said...

Looks like the issue is that the default paths don't support gcc 4.9.1.

The options at this point I think are to install an earlier version of gcc, or if you're building clang from source you can update the paths in InitHeaderSearch.cpp, or you can try using VS headers instead of gcc (run clang from within a VS dev command prompt and set the target for msvc).

Seth said...

Oh, actually there is another way; the include environment variables.

set CPLUS_INCLUDE_PATH=C:\Users\Scott\Apps\MinGW\include\c++\4.9.1;C:\Users\Scott\Apps\MinGW\include\c++\4.9.1\x86_64-w64-mingw32;C:\Users\Scott\Apps\MinGW\x86_64-w64-mingw32\include

And for linking, etc:

PATH=%PATH%;C:\Users\Scott\Apps\MinGW\bin

Scott Meyers said...

@Seth: Thanks for your continuing help. I'll try the CPLUS_INCLUDE_PATH approach when I have a chance to get back to this in a few days.

How did you find out that Clang supports CPLUS_INCLUDE_PATH? I know it works for gcc, but I can't find any mention of it in conjunction with Clang.

DLed said...

Just in case you get trapped again, I'd recommend github+travis-ci. I'll try to create an example in a sec

DLed said...

Ready: https://travis-ci.org/d-led/test_newest_boost
Simply forkable and editable from the browser: https://github.com/d-led/test_newest_boost

Scott Meyers said...

@DLed: Thanks for your help, but you'll have to give me a hint about how to use what you're making available.

DLed said...

@Scott, indeed. Sorry for leaving out the crucial details. You'll need a github.com account first. Once you have one and you're logged in, you can directly go to test.cpp and click the edit pencil. Github will automatically fork the repository for you and will open an editor. Once you commit your changes, travis-ci will trigger a build event, which you can then trace in the Build History.

For even more control you can then
log into travis-ci.org with your github account and enable your repository for a travis-ci trigger (in the account settings). You can then clone the project on windows (i.e. using github for windows), edit it locally and then push it to github, which should then trigger a ci build for your account.

I hope it helps and am willing to help further :).

I usually keep a meta-build config so that I can compile on windows locally and on linux remotely using easy premake4 patterns.

Here's an example travis config:
.travis.yml and the corresponding meta-build config premake4.lua

As for the results of the compilation in that particular project, the boost unpacking log is quite long, so that the compile output gets truncated. But it can be found at the bottom of the raw log of each build (the 3 bars icon): log.txt, outputting at the end:

Running post-build commands
./linux/bin/Debug/test
T = Widget const*
param = Widget const* const&

DLed said...

P.S. I've suppressed the unpacking output, now it's easier to get to the compilation result, just look directly at the build output

Scott Meyers said...

@DLed: Thanks for the additional information. I don't know if I'll have time to try your stuff for a while, as I'm both swimming upstream against a blizzard of deadlines and mixing my metaphors in horrible ways.

Craig said...

theres's a certain humor in seeing scott meyers struggle to get a C++ compiler to work. this isn't a situation unique to clang on windows.

there's a special frustration being a newer programmer that enjoys coding C++ but is a normal human (uses windows). every misc. task like importing 3rd party libraries or experimenting with non-visualstudio environment comes with a 5 hour trainwreck where you exclaim to yourself 'i just want to code for fucks sake'

DLed said...

@Scott, @Craig: :). I guess the troubles we are having are unfortunately ubiquitous.

There are jobs descriptions for doing that kind of impediment removal: building customized toolchains, managing custom build systems, managing 3rd party libraries with a multidimensional customization matrix for different runtimes, architectures, platforms, and whatever other config. Praise to header-only or self-configuring library authors!

There are also many great open source c++ libraries, but if you just want to try them out, you'll spend hours figuring out how to make them work on your platform.

Meta-build systems may be quite useful for managing the complexity. Outside the c++ world there are also quite a lot of tools that make programmer's life easier: nuget (can be used for c++ projects too, if only for other toolchains...), LuaDist, homebrew, rvm, gem, virtualenv, and so on. If only could someone concentrate on exactly that: hassle-free single-command bootstrapping of c++ projects for a chosen platform and toolchain with flexible dependencies and the ability to grow.

Too many ellipses

Scott Meyers said...

Currently, the gold standard in terms of a compiler that's drop-dead simple to install is the nuwen mingw distro. Unpack, and you're ready to compile with a full standard library and the current Boost (plus, I believe, some other libraries). In terms of a painless way to get started, it's hard to beat.

Seth said...

Scott asked "How did you find out that Clang supports CPLUS_INCLUDE_PATH?"

I believe I ran across mention of it in a bug report in clang's bug database. I follow clang's development closely so I'm fairly familiar with some of these things. (In fact I've done a bit of non-trivial work on it. It's been a while but I still follow the mailing lists and keep my llvm development area up to date.)

These environment variables are also mentioned in the man page: http://linux.die.net/man/1/clang. It is odd that the online 'User Manual' for clang doesn't mention them.

Clang seeks to be mostly drop-in compatible with gcc. Trying whatever works for gcc will often work with clang. (Come to think of it, that's probably why clang.exe targets mingw by default on Windows. The clang-cl.exe driver, which seeks similar drop-in compatibility with Microsoft's cl.exe will be the one that targets MSVC by default.)

Scott Meyers said...

@Seth: Thanks for the hint: "When in doubt about what works with Clang, try what works with gcc :-)"