Andersbakken / rtags

A client/server indexer for c/c++/objc[++] with integration for Emacs based on clang.
http://www.rtags.net
GNU General Public License v3.0
1.83k stars 253 forks source link

Rtags with builds inside a Docker #1085

Open nickjmeyer opened 6 years ago

nickjmeyer commented 6 years ago

Please mark appropriate

Problem description

One of the projects I work on builds everything in a docker container. Thus all the compile commands have paths relative to the container and not the actual disk. Is there a way to use rtags in this scenario that doesn't require me running emacs and rtags inside the docker?

pedro-esteves-pinto commented 6 years ago

Interestingly enough, I do exactly that, i.e. run rtags and emacs inside the container and this is pretty seamless. If that doesn't work for you, could you perhaps mount your HOME directory inside the container?

nickjmeyer commented 6 years ago

Mounting the home directory would make it much more convenient. That way I wouldn't need two emacs instances.

Though, I'm wondering, would it be possible to have rtags run inside a docker? Customize the emacs bindings so any rtags call actually runs rtags in a docker. That way I could have it run inside my docker build image. This would allow you to run emacs as normal, but still get proper completion.

Do you think that's possible? I'm going to try to dig in and see if I can get something working. Ideally, you'd be able to indicate the "wrapper command" in a .dir-locals.el file.

pedro-esteves-pinto commented 6 years ago

Yes, its definitely possible to run rtags inside docker - but in that case I think you would start docker as an interactive long-living session and just run rdm inside. I run emacs in there as well but you wouldn't have to do that. Here's my docker launch command:

!/bin/bash

nohup docker run \ --rm \ --net host \ -h $(hostname)_docker \ -v /etc/passwd:/etc/passwd \ --security-opt seccomp=unconfined \ -v /var/log/syslog:/var/log/syslog \ -v /etc/group:/etc/group \ -v /tmp/.X11-unix:/tmp/.X11-unix \ -u $UID \ -v /home:/home \ -e DISPLAY=$DISPLAY \ -t my_container \ sh -c 'rdm --daemon -L ~/temp/rtags_log & emacs' &

nickjmeyer commented 6 years ago

Thanks for passing along the docker command. Much appreciated.

If I only run rtags in the docker, I'll probably have to expose the port right? I don't see that in your docker command, but that makes sense because you have emacs inside the docker as well.

I'm guessing I'll also have to run rc in a docker too right?

I'll give this a shot some time this week.

pedro-esteves-pinto commented 6 years ago

If the file system is shared then your paths will all align and I don't think you would absolutely need to run anithing inside docker. However if you want to make sure the clang version is the same inside and outside the container and that all your system libraries are the same then you could probably just run rdm inside and rc outside, exposing the rdm port in the docker command line as you mention.

nicber commented 6 years ago

I have the same problem at work. I solved it with a script that copies the compile_commands.json file from the docker filesystem, patches the paths in it and then calls rc. I ran clang++4.0 -v -E -dM a_test_file.cpp inside the docker container, then I pass the system include paths to rdm alongside the --no-libclang-includes flag. I need to mount the docker container filesystem in a directory using sshfs and then change each system include by prefixing it with the directory where I mounted the container's filesystem.

It is quite a lot of work, but I can run rdm and emacs on the host machine.

mcraveiro commented 6 years ago

Hi guys,

joining the discussion a bit late, but got exactly the same problem as described by @nickjmeyer. I quite like the idea of mounting home in the docker container, but I'd like to keep rtags also within the container so that everyone has exactly the same setup. This means we do not have to install any dev tools at all in the host [1].

As far as I can see from the discussion above, the only snag is just rc [2]. Presumably, one would have to copy rc into the host and expose the port in the container right? I will give this a go and report back.

[1] Other than emacs that is. [2] I'm assuming one can compile via tramp/ssh into the container, so compilation is not an issue. Let me know if this is not the case.

nicber commented 6 years ago

rdm creates the socket file inside the home dir, so if you mount the home dir directly in the container it should be in the correct location for rc to find it.

samwise commented 6 years ago

Hi Mario,

I have gone to a few iterations of this type of setup. If you do not mind running emacs in the container that is the simplest, most deterministic way to go about it, you just run rc, rtags, etc all from the same environment and everything is ready to go as soon as you enter the container. If you want to run emacs outside, then I think you have to run rc outside as well, or at least with out of the box rtags I wasn't able to persuade emacs to use the rc inside the container. As you mention you also have to trigger the build inside the container from emacs, I use something like this:

cid=docker ps | grep <my_docker_image>| awk '{print $1}' docker exec $cid /bin/bash -c "cd && make"

ssh and tramp probably work as well.

mcraveiro commented 6 years ago

Thanks @nicber, this is all sounding quite promising. And now I found docker-tramp [1] too, so no need for SSH methinks

[1] https://github.com/emacs-pe/docker-tramp.el

nickjmeyer commented 6 years ago

Well I finally got around to trying this out. I'm running rdm and rc inside the docker I use to build my code. When I initialize the database, everything runs fine. However, if I restart rdm I see a bunch of errors that look like FileSystemWatcher::watch() watch failed for <file_name>.

Anyone have an idea why I might see that error?

nickjmeyer commented 6 years ago

I posted another issue #1143 for this error.