[cmake-developers] Generating buildsystem metadata from CMake

Anton Makeev Anton.Makeev at jetbrains.com
Mon Mar 30 12:51:22 EDT 2015


> On 21 Mar 2015, at 09:41, Stephen Kelly <steveire at gmail.com> wrote:
> 
> Anton Makeev wrote:
> 
>> The other thing that seems troubling to me is that since file, target,
>> language compiler options are split into different parts of metadata, the
>> IDE need to know exactly how to assemble them back into the compiler’s
>> command line (e.g. what flags go first file’s or language’s), duplicating
>> CMake's logic that may be different from version to version and from
>> compiler to compiler. The exact command line is needed to get the actual
>> and precise defines, include search paths etc. from the compiler.
> 
> Yes. I previously proposed the <lang>_compile_command to contain information 
> about how to built it:
> 
> http://www.steveire.com/cmake-future/manual/cmake-metadata-generation.7.html#optional-properties

Thanks for pointing, I missed the purpose of that property.
If we are after a compact form, this should work, I guess.

> However, I think it might be better to generate something similar to what is 
> currently generated in compile-commands.json into cmake-metadata.json. That 
> is, we would generate (in some context)
> 
> "include_directories" : ["/foo", "/opt"]
> "compile_definitions" : ["DEF=\"Foo\"", "OTHER_DEF=1"]
> "compile_command": "-c -DDEF=\"Foo\" -DOTHER_DEF=1 -I/foo -I/opt"
> 
> So, "compile_command" contains approximately what you can currently get from 
> compile-commands.json.
> 
> The other properties contain things which are specifically known to be 
> include directories or compile definitions, as javascript arrays. These 
> properties are obviously redundant information, so I wonder if they should 
> be generated at all? Is the compile command I wrote above easy to parse? Or 
> is it sufficiently difficult to parse that this redundant information should 
> be provided?

Agree, I don’t see any point in having this redundant info. I’d better not have it to avoid confusion:
the include_directories lists is incomplete (it doesn’t contain compiler-defined search paths) and should not be used for any purpose.

>> This would be really helpful indeed, currently, we have to introspect
>> CMakeLists.txt files in order to find the most probably place where new
>> files should be placed (works only in basic cases now). And being able to
>> do so correctly is also crucial for refactoring (e.g. extract class).
> 
> Given the backtrace, you can navigate up the scope from the most recent 
> frame to get out of any functions, macros or loops. You can then add a 
> target_sources() line directly after that. 
> 
> That algorithm will work for every case (not just basic cases) as far as I 
> can tell and is available with CMake 3.1.

OK, it’s definitely better than nothing, so we can start with the target backtraces.

>>> * I didn't document the location or directory.  I'm not clear on whether
>>> it is supposed to be the build location, or the install location(s!),
>>> or all of those.
>> 
>> It would be useful, though, to have a location of generated files for each
>> target: in case metadata misses some information (and I think it won’t
>> cover every possible need anytime soon), IDE will be able to get if from
>> generated makefiles.
> 
> Yes, we can at least provide the build location in an obvious way. We can 
> discuss install locations eventually.

OK

>>> * I don't generate 'dependencies' (actually the list of files which the
>>> buildsystem re-generation depends on) as Aleix did, because there is no
>>> well-defined usefulness for that list yet.
>> 
>> As Tobias pointed, we at least need to know what files are the part of
>> CMake project, that is, the list of all CMakeLists.txt and *.cmake files,
>> used for generation (ideally, including missing ones, since in that case
>> IDE could be able to tell when missing file is created and refresh the
>> project)
> 
> As I wrote to Tobias, I'm apprehensive about this, and it would require 
> other work to make cmake parallel safe first. 
> 
> I think if the IDE does not have focus it should not be running 'cmake .' on 
> my behalf. I think if the IDE newly gets focus you can maybe run 'cmake .' 
> at *that* point (after the user is done with their rebase or whatever). That 
> doesn't require giving you a list of files to watch. Maybe I'm missing 
> something though.

Agree, the IDE should not do any automatic stuff, when user doesn’t expect it.
Though, the use-case here is quite different:
Consider a project that have 'add_directory(missing_dir)’ in one of the CMakeLists files.
If IDE were aware that missing_dir/CMakeLists.txt is a required file, it might then automatically 
trigger update, when the user creates this file inside the IDE (not externally). 
Or it may even have a quick-fix ‘Create missing CMakeList.txt’.

Also, files updated and created during VCS (called from the IDE) should be automatically recognized, of course.


>>> * Some more information from project() may be relevant, but it's not
>>> clear
>>> yet. We will likely know more when we have decided the file format and
>>> generated some 'interesting' metadata files.
>> 
>> Project name, list of the configurations are most needed ones.
>> We also use CMAKE_<lang>_SOURCEFILE_EXTENSIONS to determine if a given
>> file is potentially source file or not.
> 
> As CMake already knows which files are 'object sources', the metadata will 
> provide that. Also, the <lang> extensions is not enough. See the unit test I 
> created and in particular the compiled_as_cxx.c file.

For the existing files we indeed have all the necessary info in the proposed format.
Though, it’s about newly-created files: when a user creates a new file ‘foo.zxy', IDE should decide,
wether to add it  (or suggest to) to a target or not. The list of source files extensions is what 
may help here.

>> This has already been discussed but I give our usage scenario:
>> 
>> in CLion we retrieve the list of all build types (aka configurations,
>> Debug, Release etc) 
> 
> From where do you currently retrieve this list? I guess you look at all 
> cache keys named 
> 
> CMAKE_.*_FLAGS_(.*)
> 
> and list the matches?
> and list the matches?

It comes from CMAKE_CONFIGURATION_TYPES, if project defined such a variable.
With default of Debug/Release/RelWithDebInfo/MinSizeRel

>> and then generate project using Makefiles generator
>> for each of them. This is necessary because of several reasons: 1) To be
>> able to correctly build language model, we need to know, when a file is
>> used in several configurations, which means, it's compiler settings and
>> macros are different.
>>    E.g. some branches of code may not be available in Debug or Release
>>    and we give user an option to quickly switch between them in the
>>    editor.
> 
> This seems similar to what Tobias talked about.
> 
>> I don’t know if it’s possible at all, but it would be great if we could
>> have info for all configurations generated in one go (not only for
>> multi-config, but for single-config generators as well like Ninja and
>> Makefiles).
> 
> I can think of two ways to make that possible:
> 
> 1) Create new mulit-config generators, or add options for the existing ones.
> 2) Add a generic multi-configuration mode to cmake:
> http://thread.gmane.org/gmane.comp.programming.tools.cmake.devel/10873/focus=10912
> http://public.kitware.com/Bug/view.php?id=14539
> 
> I consider both out of scope for this thread though.

Agree, and thanks for opening the discussion.

>>> * Generating metadata only (without generating buildsystem files) is not
>>> currently in scope.  This was requested several times, but it is not
>>> clear why.
>> 
>> It’s simply to be able to get this the information as quickly as possible.
>> I’m not sure which part is most slow, but, say, InsightToolKit 4.5
>> (http://www.itk.org/Wiki/ITK/Source <http://www.itk.org/Wiki/ITK/Source>),
>> generates in couple of minutes. 
> 
> CMake has a 'configure' step followed by a 'generate step'. Your count of 
> minutes must be the sum of both. The information determined during those 
> steps is exactly what the metadata file should contain. Avoiding all of it 
> would leave you with no metadata.

I see, you’re most likely right.
Anyway, optimization is out of scope, I just wanted to clarify why this could be desirable.

>> The regeneration, even when nothing was
>> changes, a few dozens of seconds.
> 
> This cost is mostly the 'generation step', as everything from the 'configure 
> step' was cached and available for re-generation.
> 
>> Plus, we’d prefer being able to open the project without any questions to
>> user, e.g. not asking, which generator he/she prefers. If we generate
>> using ‘wrong’ default generator we’ll need to regenerate everything again
>> when user decides to change it.
> 
> It seems like you can use a throwaway temp directory until the user chooses 
> a generator. I am sympathetic to the idea of 'not breaking the users flow', 
> but I don't currently have any idea how to avoid it.
> 
> Everything does indeed have to be re-generated if the generator is changed, 
> and cmake currently issues an error if you use a different -G option than 
> was originally used in a build dir. If you really want to change that 
> behavior, I suggest a separate bug report to track the idea. As I said I am 
> sympathetic to the idea, but I don't see a way. If you file a bug, maybe 
> Brad will have an idea or can say it's fundamentally out of scope.
> 

>> Another benefit of skipping actual generation is possibly better error
>> recoverability. That is, some generators may fail here and there if the
>> project is incorrectly configured (e.g. source files are missing).
>> Skipping the generation phase will (probably) help getting the project
>> metadata even in that case.
> 
> I don't think that's the case. The 'generate step' is the point where the 
> metadata is generated, and that step begins strictly after the 'configure 
> step' ends. The scenario you describe is errors during the 'configure step'. 
> That means no metadata for you.
> 
> If this is possible to change, it's out of scope of this current design 
> work. I'd suggest a separate bug report.

OK, let’s put aside this part for now.

> 
>> But anyway, it seems a little outside of the scope of the discussion.
> 
> Yep :).
> 
> Thanks,
> 
> Steve.
> 


Regards,
Anton Makeev
JetBrains
http://www.jetbrains.com
"Develop with pleasure!"

-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 2856 bytes
Desc: not available
URL: <http://public.kitware.com/pipermail/cmake-developers/attachments/20150330/1a883900/attachment.bin>


More information about the cmake-developers mailing list