Conan: ycm generator could be more useful

Created on 13 Feb 2018  路  9Comments  路  Source: conan-io/conan

Hello,

I'm using Conan 1.0.4

Lately I've been trying to use the ycm generator for one of my projects, but the generated .ycm_extra_conf.py is not usable as-is, as one has to add the consumer project flags to it:

# .ycm_extra_conf.py
flags = [...]
flags.extend(['-I/path/to/project/include', '-std=c++14', '-D_NDEBUG', ...])

Should the generator only create a file containing the list of flags, which would then be included by .ycm_extra_conf.py?

In my case I want the .ycm_extra_conf.py to be at my project root, and the flags file in my build directory, refreshed each time I run conan install.

Maybe generating both files in the build directory would solve the issue without breaking current usage:

# on first run
$ cd build && conan install .. -g ycm
$ cp .ycm_extra_conf.py ..

# next runs
$ cd build && conan install .. -g ycm

To help us debug your issue please explain:

  • [x] I've read the CONTRIBUTING guide.
  • [x] I've specified the Conan version, operating system version and any tool that can be relevant.
  • [x] I've explained the steps to reproduce the error or the motivation/use case of the question/suggestion.

Most helpful comment

If I have some time this week-end I'll try to look into it.

All 9 comments

Honestly, I have no idea about this generator, it was mainly a contribution, the generator's code is quite easy. If you think it can be improved maybe you are the best person to know how to do it ;)

If I have some time this week-end I'll try to look into it.

This was a change that was necessary to clean some debt before 1.0: generators only have access and manage information about dependencies, but they don't have access to the current package. The original work by @skizzay implemented this, but we had to remove it.

So yes, I agree the best solution would be to have:

  • a file generated with the information of dependencies for ycm
  • the root file that can load this file, but also provide configuration for the current project (might not be a conan package at all, so this file should be under user control)

@theodelrieu I've actually had this "complaint" about this myself. Generators do not have the current build information because cpp_info doesn't become available until package_info is called. I haven't found a good way around this limitation. We cannot call package_info ourselves because the expectation in that method is that package_folder will be used when configuring directories. We'd need to distinguish calling package_info for development and package_info for packaging.

The best solution that I've found (which is actually superior to having conan itself trying to figure out all of the flags) is to use CMake's ability to export the compilation flags. If you look at the generated file, then you'll notice that it'll read in compilation flags database and use those flags instead of the default. This is more accurate since CMake actually generating the command that builds a particular file.

In your top level CMakeLists.txt file, add this somewhere set(CMAKE_EXPORT_COMIPLE_COMMANDS ON) Combined with the ycm generator, this should give you the correct set of compilation flags.

Actually, there is another use case, that is installing from conaninfo.txt, so a package_info() won't be there.
So it seems there should also be a way in which users can define their own input to ycm and include the info from the dependencies installed by conan. It seems that getting that info from cmake is a good approach, just to define how that "combination" with the generator could be automatically done.

@skizzay I tried to use YCM with compilation databse once, but relaunching CMake each time I added a file was a no-go for me.

Anyway I don't think the Conan generator can be of any help for the consumer project, as @memsharded mentioned in his previous comment.

I think that generating two files is the best we got:

# generated .ycm_extra_conf.py

flags = read_flags_from_file("conan_deps_flags_for_ycm.txt")

Then users have to copy (one time only) the .ycm_extra_conf.py from the build folder to wherever they want, and create a symlink to point to the build folder's conan_deps_flags_for_ycm.txt file.

That's a rough idea for now, if there is a better way I'll gladly take it :)

The way that I've been using this generator is that when I run conan install, I specify the generator for myself locally (conan install -g ycm ...) in my build directory since it's not needed by any client libraries. I manually tweak the default flags since most of the libraries that I'm working on at the moment are header only (which makes the CMake compilation database useless). I start my editor (good ol' vim) in my build directory, but load up its file explorer (NERDTree) in the source directory.

All of the external dependencies are resolved by the generator, which is really a good starting point. The internal flags just need a quick tweak in order to get right. I usually have multiple build directories, one for each configuration that I build. This method has been pretty good to me so far because I don't have to run conan install that often. Plus, I don't have to worry about my previous settings being overwritten with a fresh run of conan install because .ycm_extra_conf.py only gets written when I run it manually.

Both @memsharded and @theodelrieu made comments that made me think of something... We should probably have a way to pass in data to the generators. In this example, something like:

   generators = "ycm", "cmake"
   generator_config = {
      "extra_compilation_flags": "-I%s/include" % os.path.dirname(__file__),
      "some_other_flag": True
      }

The Generator base class could then have a property

class Generator(...):
   @property
   def extra_config(self):
      return self.conanfile.generator_config

The generator_config attribute would be an accumulated map, using dict.update of each config declared in a ConanFile.

Or I'm just getting too deep into something that can be solved in a much easier fashion or doesn't need to be solved at all???

This has been improved by recent work by @AlexandreBossard in #2519, so I think it might be considered solved (it will be released in 1.2), but please comment if otherwise. Thanks!

Was this page helpful?
0 / 5 - 0 ratings