Open cbeck88 opened 8 years ago
Have you tried using conda
? I could be totally wrong, but it sounds like you want a fast package manager with more modern packages than the system one. This would be a great way to do just that. If you need more packages, there is always conda-forge. Newer compilers are in the works. Though things like boost
1.60.0 are already available. Feel free to ask questions.
@jakirkham: That looks really helpful -- I'm going to look into it and try to figure out if it works for me. Thank you. :+1:
So, let me come back and try to make a constructive suggestion.
In a thread from 3 years ago on this, people suggested many different ways to have compiler: foo-5.5
and how it would work, what symlinks, or have different options language: cpp11
, and so on.
IMO the way it really should work, is just like the online C++ compilers do it.
For instance take a look at coliru. In this system, you type the source code of a simple program in the top, and a build command in the bottom. In that build command window, the environment is very similar to travis -- it's just some ubuntu image, except that it has all compilers installed. If I type g++ -v
in there, I see that gcc 6 is their current default version. But if I type g++-4.8
I get gcc 4.8. If I type g++-4.9
I get that. If I type g++-5.0
I get that. And so on. All the compilers, side by side. And the same for clang. And they are all configured to use the proper version of the C++ standard library that they were released with! Amazing.
As far as I'm concerned, travis-ci could just drop the compiler:
option or make it do nothing. It doesn't even really do anything anyways. It should just start with a nice image set up to do modern C++ development like described. If I could find a CI system that gives me an image as nice as the one that colriu or godbolt gives me I would jump ship for that in a heartbeat. I can't even bring myself to tell you how many hours I have struggled over the past year trying to install different versions of C++ compilers inside a travis image via some dinky little travis.yml file.
@cbeck88 Thank you very much for opening this issue and articulating your issues with Travis. They mirror mine identically. Its gotten so complex now that I am not capable of maintaining the scripts on my own. We have a similar hodge-podge of apt repositories where we try to work around the languishing C++ support in Travis builds.
My workaround for this is to use Docker. Example:
https://github.com/mapbox/route-annotator/blob/master/.travis.yml
The build environment is then specified with a Dockerfile, like so:
https://github.com/mapbox/route-annotator/blob/master/Dockerfile
Of course, this doesn't support building on OSX, but at least it's fairly easy to use whatever base Linux OS you need. It would be fairly simple to supply multiple Dockerfile
s to test different compilers/libstdc++ versions, etc.
I am the author of Boost.Hana mentioned above. I can't tell you how many hours I spent (and am still spending every day) to tweak my Travis file; it is insane. I am incredibly tired of doing so, but I have no other solution because other CIs are even worse AFAIK. Travis, please take this burden off your users.
Also, we're taking an insane amount of compute time for downloading and building all these packages. This has to be costing you something, no? Why not make our life easier and make your system more efficient?
If you need boost 1.60, then afaik you need to download it manually from sourceforge as part of your script, and build it if you need that.
You can download it using conan.io (@memsharded) or Hunter (@ruslo). Conan.io provide pre-build binaries for some platforms/compilers https://www.conan.io/source/Boost/1.57.0/lasote/stable, Hunter only can cache already compiled Boost on Travis (conan can do this too)
You can find Boost 1.60 in conan here: https://www.conan.io/source/Boost/1.60.0/lasote/stable If you use conan just create a conanfile.txt file:
[requires]
Boost/1.60.0@lasote/stable
[generators]
cmake
and execute "conan install". If you don't use cmake there is also available other generators. Take a look to conan docs: docs.conan.io
The CI integration is also smooth, we generate thousand of packages with travis and appveyor.
Hunter only can cache already compiled Boost on Travis
Hunter support binaries from server: https://docs.hunter.sh/en/latest/overview/binaries.html
Linux, OSX, iOS, Android: https://travis-ci.org/ingenue/hunter/builds/140317830 Visual Studio 9-14 + mingw: https://ci.appveyor.com/project/ingenue/hunter/build/1.0.665
As you can see it takes about 1 minutes to compile because pre-build Boost binaries downloaded from server.
Really, all this talk about package managers is besides the point. The point is that we should have this pre-installed in the image.
Having it pre-installed is also a problem, as the number of combinations quickly explodes. And I do want to test different versions of Clang with different versions of libstdc++, Boost, ...
Looking at the larger picture, I think Repositories are the way to go. It does give you a lot of options and you can define the combinations you want to test yourself. See http://stackoverflow.com/a/32127147/2073257
It is not perfect, yes. If a new compiler/version is released, I need to add it manually. It has other issues, but it's manageable. What I miss is similar sources and packages for Boost versions and for some other libraries. Plus some kind of "*-last-stable-release", which is available for some packages, but not all.
From Travis' perspective, they should automatically set up caches/mirrors for all white-listed sources. That might save them and others lots of bandwidth and time. The LLVM-Repo-disaster, if they really caused it, should not have happened in the first place.
Since the YAML-Files (see my above link) are then also available, and they directly expose which sources and packages are used, they could also pre-build the containers with the most frequent combinations and realize even more benefits to reduce their own costs. And the pre-build container might contain only 8 of the packages I listed and then each run adds another package and I would not even know. They could even measure which installation from which package takes up the most resources and use this to determine the set of pre-build containers. All of that would be transparent to the users and simply an optimization in the background.
EDIT: Oh, and another benefit: It would "force" the projects to provide those repositories - which would benefit all users outside of TravisCI.
My 2 cents.
@d-frey Your solution is not a solution, it's exactly what Hana does (except Hana now installs pre-built Clang binary instead of using apt since the disaster). It's cumbersome and leads to a gigantic Travis file that's hard to understand. Sure once you've spent 25 hours setting it up you understand it and you're able to maintain it (mostly), but that's a huge time investment in the first place.
Having it pre-installed is also a problem, as the number of combinations quickly explodes.
Yeah, well we're doing it anyway right now, except we're making LLVM blow up and taking hundreds of hours of Travis compute time, instead of having it set up properly once.
And I do want to test different versions of Clang with different versions of libstdc++, Boost, ...
The image can have the packages pre-installed and coexisting, so that you can pick what you want from the image but the image already contains all you need.
I think what we really want is something like this:
compiler:
clang:
- 3.5
- 3.6
- 3.7
- 3.8
- trunk
gcc:
- 4.9
- 5.0
- 6.0
- trunk
stdlib:
- libc++
- stdlibc++
boost:
- 1.59.0
- 1.60.0
- 1.61.0
- trunk
Given the above, I would expect the right packages to be available in the image, and the following environment variables to be set:
BOOST_ROOT=/path/to/boost/installation
CXX=/path/to/requested/compiler
Furthermore, the compiler should be using the requested standard library. I guess it should also be possible to specify versions of the standard library, but I'm not sure. In any case, I'd be satisfied with just being able to use a compiler with the standard library it is shipped with by default (libc++ for Clang, and libstdc++ for GCC), and drop support for custom standard libraries altogether.
@ldionne The funny thing is, I agree with what you are going for. I just think that what I want is taking a step-by-step approach to enable it. Considering your:
compiler:
clang:
- 3.5
- 3.6
- 3.7
- 3.8
- trunk
gcc:
- 4.9
- 5.0
- 6.0
- trunk
stdlib:
- libc++
- stdlibc++
boost:
- 1.59.0
- 1.60.0
- 1.61.0
- trunk
I'd also add:
std:
- c++03
- c++11
- c++14
- c++17
- c++-latest
This is the final goal, but what does it mean? Each combination needs a pre-build container? Maybe not, as the standard is only an environment variable. And each of the above could be just a short-cut for a list of sources, packages and environment variables. Plus some combinations do not exist, e.g. old GCC with C++17.
From Travis' POV having the repositories would decouple things, auto-detecting the containers that need to be pre-build is also more flexible and scalable. Why would they want to manually maintain all this? And why only for C++?
Another advantage: Each step would be easier to debug. And you need to start somewhere, caching repositories should not be too hard and it will have immediate benefits. Then pre-build container, also an immediate benefit. Then extend the YAMLs :)
std:
- c++03
- c++11
- c++14
- c++17
- c++-latest
In my opinion this goes too far and is not necessary. That's a compiler flag and can be treated as such and be left up to the user what (s)he wants to test and what not.
@patrikhuber It's optional, not mandatory. But it is more than just setting a flag, as some combinations of compiler+STL+standard are not available. Plus that when c++-lastest is c++14 for some compiler, I don't want the matrix to do this twice. Or when a new compiler supports C++20, C++42, whatever, with the default (c++-lastest) I get a better test coverage.
It goes further: For all options, I'd like to provide a minimum. Say, GCC 4.7+, Clang 3.4+, C++11 or better, Boost 1.59.0 or better. I don't want to list all versions manually, especially since I want the list to automatically extend in the future and the availability of a new compiler, etc. should trigger another (incremental!?) build.
From the list of the above YAML snippets to the actual sources, packages and environment variables is complicated enough, so let's create the basis for it first and then get this part right. Again: It's not just a simple matrix where you can build all combinations and be done with it. That's not going to work.
@d-frey Agreed. Especially the part that a simple matrix of all combinations probably won't cut it.
What I'm saying is that these compilers and version of Boost may all be installed in a single image at the same time. This way, Travis does not have to maintain all combinations (which doesn't make sense). Then, only the proper environment variables have to be exported.
As for combinations that do no make sense, we can exclude them from the matrix. Using matrix.exclude
or something (I forgot the exact syntax).
Regardless, I think the first step towards anything is to know whether the folks at Travis are even interested in giving better support for their C++ users. If not (and there could be many valid reasons for this), then we could get organized and maintain a single script to install C++-specific stuff from Travis ourselves. Not ideal, but better than what we have right now.
It may be that, in lieu of actual support, which would be great, what we need is more guidance.
It sounds like, actually, Travis provides many different options that can do all these things we want to be able to do with cached builds and containers and so on. There's the sudo: false
containerization option. There's the docker containerization option. There's the cache:
parameter. All of these things were carefully developed by travis-ci, and they are continuing to maintain them after they introduced them, to avoid breaking anyone's builds, which is great. And there are many different third-party package managers to help us install the things that we need.
But, we are sort of suffering from proliferation of options. In my case for instance, I am vaguely familiar with Docker, but I've never used it. I've read a few articles about it. I read the wikipedia page about chroot
. I understand that Docker has become a very important technology and that I need to learn how to use it -- it's on my to-do list, just like everything else.
So the result is that I have many different ways to approach this problem of setting up my build environment, but I'm only prepared to properly evaluate some of them.
And usually when I'm making this decision, it's like, suddenly my CI has broken because of something that I did, and my goal is to fix it as fast as possible and go back to what I was doing.
So it's not that likely that in that situation, I'm going to sit down and take potentially an hour or two (?) to learn Docker and rewrite my CI for each of my projects. Even if that's in fact exactly what I should do. It's more likely that I'll google around briefly, and maybe decide to copy off of someone else.
However, when I copy off of someone else, I take a risk that they are doing something that is really only appropriate for their project, for some undocumented reasons.
If the answer is that, for now, we should all be using Docker, then it would be really great if in the travis-ci C++ docs page there was a section explaining this and maybe giving an example.
For instance, anyone who follows those instructions today, is very likely to try it, get a bunch of errors because of gcc 4.6.3, and then have this time-travelling barbarian "WHAT YEAR IS IT?!?!?" reaction, like this guy: http://genbattle.bitbucket.org/blog/2016/01/17/c++-travis-ci/
So you could change the instructions to say something like this:
If your project builds with gcc 4.6 and clang 3.4, then you can do this: ...
If your project reqiures C++11, here is an example that shows how you can use Docker to make a really nice C++11 build-environment that doesn't involve bankrupting the LLVM foundation. This method has the travis-CI seal of approval.
If there were examples like that, where the author is implying that the instructions are appropriate for a generic C++11 project, and not just some particular project, I would likely switch all my projects to use that method.
Faced with the same frustration that a lot of you guys have had with C++11 and up on Travis, I've gone ahead and opened travis-ci/docs-travis-ci-com#746 with example matrix includes that allow for specific GCC and LLVM versioning control. If anyone has anything to add, I'd love to hear feedback.
What would be nice is if they shipped with clang 3.9 and latest gcc by defailt and not only that but latest linux than the trusty 14.04 LTS
there is already like v16.04 stable of that OS even. Bad enough I can barely compile Python 3.6 on travis on trusty (And python is written in C).
At the moment I'm setting up the build machine in this way:
addons:
apt:
sources:
- sourceline: 'ppa:ubuntu-toolchain-r/test'
packages:
- gcc-5
- g++-5
- clang-3.6
# [...]
before_install:
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 60 --slave /usr/bin/g++ g++ /usr/bin/g++-5; fi
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 40 --slave /usr/bin/g++ g++ /usr/bin/g++-4.8; fi
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then export PATH=`echo $PATH | sed -e 's/\/usr\/local\/clang-3.5.0\/bin://'`; fi
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo update-alternatives --install /usr/bin/clang clang /usr/lib/llvm-3.6/bin/clang 60 --slave /usr/bin/clang++ clang++ /usr/lib/llvm-3.6/bin/clang++; fi
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo update-alternatives --install /usr/bin/clang clang /usr/local/clang-3.5.0/bin/clang 40 --slave /usr/bin/clang++ clang++ /usr/local/clang-3.5.0/bin/clang++; fi
Then, depending on some environment variable I can change the gcc/clang version using sudo update-alternatives --set
.
It's not as easy as having support for different compiler versions in the matrix, but it works...
@drdanz it's a good approach, but it has a problem, the system libc
is the same in spite of upgrading the compiler, so binary generated in the CI servers could be incompatible with a modern distribution with a newer libc
. Without binary reusing maybe it's good enough.
Sound like my issue where my stuff requires at minimum g++ 6, and clang 3.9. However it requires those because of the <experimental/filesystem>
header. And not only building for linux but for mac which is sadly worse than linux.
@drdanz there are other things installed with gcc like gcov and others which need to be updated this way too. It would be better if gcc6 family was installed by default so we don't need to reconfigure everything.
Is it really difficult for travis CI to keep 10 versions of Boost and 10 version of gcc ? I need to build with boost >= 1.58 and gcc >= 4.9 Anyone know who maintains Launchpad with all those goodies , I can't imagine it wasn't already shipped by someone.
Tbh it is hardly that of much any effort. Even then they could also install local versions of the gcc's or clang versions they need and then allow you to use them if you absolutely need them.
I spent 3 days figuring out and finally fixed all problems with the build ( custom version of Boost, cmake ) ... to find out today about the outage with almost everything that Travis CI has to offer :-( I have used most of ideas from ldionne to achieve single successful build , but the frustration is so high , that I almost wrote a blog , but before I did I found someone else was ahead of me: http://continuousfailure.com/post/github_travis_gce_nope/
Found this thread after having the same issues as everyone else here. :)
@sxlijin: I've just looked at your doc PR https://github.com/travis-ci/docs-travis-ci-com/pull/746, and I'm wondering if the approach described there still has the same STL version issue (New compiler but old std lib)
@Kimundi I would suspect that the answer is yes, the issue persists, since upgrading the onboard libc version is probably somewhat unsafe, at least in terms of binary dependencies.
Is there a good solution for using C++14 with a recent version of clang?
We have clang 4.0.0 in conda-forge. Just download Miniconda on Travis CI in .travis.yml
. Then add the conda-forge channel and run conda install -y clangdev libcxx
and you should be good to go. Could add it in a separate environment if you wish to instead.
Installing a separate 3rd party package manager was not my idea of a good solution, but thanks.
@ioquatix Our current solution allows Clang 4.0 with C++14, C++1z, etc. - check out our .travis.yml at https://github.com/taocpp/PEGTL
what if I want to try out clang 5 using that manager though to try out full c++ 17 anf the rrvisions to the filesystem header now that it is merged with the standard and no longer experimental?
Instead of installing a third-party repository I recommend to install a newer Ubuntu repository and install just the packages, which needs to be newer, from the newer repository.
@Croydon I could not agree with you more. Or if you want C++ 17 maybe use Doozer.io temporarily until travis fixes their C++ stuff?
@ioquatix @AraHaan I added instructions for working with more recent versions of clang (including clang 5) in travis-ci/docs-travis-ci-com#746; you can see them in the clang section of the C++ page.
Here is what I ended up with and I'm using it on quite a few projects:
Config: https://github.com/kurocha/concurrent/blob/master/.travis.yml
Example text matrix: https://travis-ci.org/kurocha/concurrent
See also https://github.com/jbeder/yaml-cpp/issues/528 for another incidence of the Travis-provided clang being broken due to incompatibility with libstdc++ 4.6 headers.
Neither clang-5 nor clang-4 (which worked a week ago), work now.
https://travis-ci.org/acgetchell/CDT-plusplus/builds/272178585
https://travis-ci.org/acgetchell/CDT-plusplus/builds/271863428
I've documented this here:
https://github.com/travis-ci/travis-ci/issues/8346
And created a pull request for the documentation here:
https://github.com/travis-ci/docs-travis-ci-com/pull/1431
Clang 3.9 still works.
Complete C++17 support from Clang 5 sure would be nice.
For reference, apt.llvm.org was down for 2 days this week because of this... Also a note from a few months ago in the mailing list about the absurd fact that travis doesn't allow to cache apt : http://lists.llvm.org/pipermail/llvm-dev/2017-May/113269.html
I also would really like to see direct support for modern compilers in the toolchain.
Also, I think it would be helpful, if travis could switch faster to the next Ubuntu LTS (18.04). I'm not sure when 14.04 was introduced, but afaik more than a year after it became available. Of course that still doesn't give us the latest and greatest, but in many cases it is actually more than good enough because projects tend not to depend on libraries that arend brodly available anyway.
Another option would be to allow running your own (cached) docker images. Then a project hast to set up its environment with all compilers and dependencies only once and it could be easily shared between projects.
It's still not possible to compile with a specific version of the stdlib++? It's very troublesome to setup
Someone mentioned using a docker image as a work around, but the link is dead, is there any example out of there?
@Dllieu If you're referring to my earlier comment, you can browse back in that repo's history to get the example.
Here are some permalinks:
https://github.com/mapbox/route-annotator/blob/d4aa6ea7631accc595951e9c37cb30aecbdca5ea/.travis.yml
https://github.com/mapbox/route-annotator/blob/d4aa6ea7631accc595951e9c37cb30aecbdca5ea/Dockerfile
In this setup, Travis basically just executes "docker run" - you have full control over what goes into your docker image that performs the build.
We're no longer using this setup, but it should work just fine, and you can use whatever tools you want inside the docker image you use.
@danpat I'm curious, why did you move away from using travis with docker?
@patrikhuber We have an internal team here at Mapbox that's working on build tools - we use https://github.com/mapbox/mason now as a way to install versions of tools we want as part of the build process, rather than using system-provided packages.
Either approach works, but it's helpful for us to have internally consistent build processes, so we stopped using the docker method.
Got bitten by this attempting to use Boost 1.66, which is the minimum version supported by our project. Everything has to be built manually, because the repository boost-nightly
on Ubuntu only has versions up to 1.55
. Appveyor has Boost 1.66
already installed by default, and that's for Windows, where dependency management is supposed to be hard. I really feel like this should be a solved problem.
@Ruin0x11 As someone mentioned earlier (https://github.com/travis-ci/travis-ci/issues/6300#issuecomment-232888090) you could look into using conan.io to manage your Boost dependency (and other C/C++ dependencies).
Thanks for contributing to this issue. As it has been 90 days since the last activity, we are automatically closing the issue in 24 hours. This is often because the request was already solved in some way and it just wasn't updated or it's no longer applicable. If that's not the case, please do feel free to either reopen this issue or open a new one. We'll gladly take a look again! You can read more here: https://blog.travis-ci.com/2018-03-09-closing-old-issues
Many C++ projects on github now use travis-CI. It is integrated very easily with github, and in the past, it was relatively easy to get started.
Especially, it was easy if you started a few years ago and your project did not require C++11. Then, the compilers which were available in ubuntu-precise were good enough, so your .travis.yml was only a few lines.
At some point you might have done something that needs gcc-4.8 or 4.9, and there was an easy way to get these:
and you would be good to go.
Over the last two years or so as I have transitioned to modern C++, I have watched it just become slowly and steadily more difficult to use travis, and watched the scripts of all of my projects grow vastly in complexity.
ubuntu-toolchain-r-test
apt repository and use it to install better compilers.boost 1.60
, then afaik you need to download it manually from sourceforge as part of your script, and build it if you need that.boost.hana
.travis.yml file, which is very meticulously maintained. https://github.com/boostorg/hana/blob/master/.travis.yml#L37 But this script is also super long and complicated and does a huge amount of work.What I am thinking that I should do now is, make a new repository containing my current up-to-date travis-CI install-modern-c++-on-ubuntu-precise scripts. And each project's .travis.yml should clone that repo and get the scripts from there, so that they are all in sync and updated as that repo gets updated.
But of course what that actually means is, I am thinking of making my own jerry-rigged package manager for compilers and boost versions. To install all the software that I need for C++ which I need to install in travis.
If you think about it, I'm pretty sure that the
.travis.yml
in boost.hana doesn't actually use anything enabled bylanguage: cpp
. It probably could be changed tolanguage: python
and still work fine, since none of the standard tools that are brought in bylanguage: cpp
are used, since they are all way too old to be useful and everything needs to be installed in the home directory.It just doesn't make sense for each individual C++ developer to have to essentially package all the compilers and standard libraries for their use in each project, and figure out exactly what are the right and most stable URLs to use for each of these different things and what are the correct build instructions for each of these compilers. Anyone except a professional or aspiring professional C++ programmer isn't going to be able to handle that anyways and it would take them hours and hours to read about it and get it right.
So, what I am asking for is some sort of feature to help me out here, or some advice about what I should do.
What I really want to be able to do is just write
compiler: gcc-5.3
orcompiler: gcc-5.4
orcompiler: gcc-6
, and specifyboost: 1.60
orboost: 1.61
somewhere in the yaml header and for these to get installed. Whether it's via some ubuntu apt package, or from source distributions from the developers in my home directory, I don't really care -- if travis can just tell me where it was installed via a variable or something, that's all that is needed to build with any build-system that I'm aware of.Is there another package-manager option that I can use, separately from ubuntu apt-get, to just install packages into my home directory? I thought about installing "linux brew" and using that to install gcc and boost, since homebrew always builds the latest versions of any software that are available. But this would not get me access to clang unfortunately, and there are some other drawbacks I won't go into.
I mean the ideal thing from my point of view would be if travis would maintain "core" build scripts for getting different versions of gcc and clang, and of boost. I realize that travis does not want to maintain a package manager itself, but these are really core language technologies for C++ programmers, and the way it stands now, every C++ programmer using travis needs to figure it out themselves.
What I am convinced of is that if the idea is that everyone trying to use modern C++, tested against an "old" gcc and a new gcc, and an "old" clang and a new clang", will have to maintain their own personal .travis.yml files that look like this one, https://github.com/boostorg/hana/blob/master/.travis.yml then it's just a massive duplication of some pretty tedious work that should properly be handled by a single common automated system, and that most likely I will end up looking for a CI system that has better support for the technologies that I need, despite my many years of positive experience with travis-CI.