CMake and clang_complete - cmake

I'm wanting to setup my CMakeLists.txt file so that it can generate the .clang_complete file required by the vim plugin clang_complete.
Ordinarily, you would do this by passing a parameter to the python script it supplies with the compiler and all of the parameters for compilation. Note that I am omitting the actual directory cc_args.py is in to save on space.
cc_args.py gcc test.c -o test -I~/IncludeDirs/
You can also do this during the make phase...
make CC='cc_args.py gcc' CXX='cc_args.py g++'
However, I am unsure of how to (if it is possible to) set this up within a CMakeLists.txt file. It's really annoying to have to type this in every time I want to setup clang_complete. The reason why I want to do it this way, is because I have multiple projects that I use a custom script to build the CMakeLists.txt file, so having to write a script for each one or manually place a generic one is a step I'd like to avoid.
I've tried a couple of things that have so far have come up with errors.
I've tried setting CMAKE_CC_COMPILER and CMAKE_CXX_COMPILER to lines similar to the first i.e. "cc_args.py g++". The errors that come up here say that It can't find the compiler (which is understandable).
The next thing I tried was setting the Compiler variables just to the cc_args.py and adding a flag for the actual compiler: suffice to say, that failed horribly. CMake said that it couldn't compile a test program (considering the script isn't a compiler, and the tests don't use the flags I set, I'm not surprised at this).
So without writing any other external scripts that require moving around, is there anyone that can think of a way that can do this?

The solution is to set the CXX environment variable before executing cmake. Something like that:
CXX="$HOME/.vim/bin/cc_args.py clang++" cmake ..
make
See http://www.guyrutenberg.com/2013/01/29/vim-creating-clang_complete-using-cmake/ for more details.

I know you said "without writing any other external scripts," but it seems like you just need a one-liner:
exec cc_args.py g++
And then set that file as your CMAKE_CXX_COMPILER. You could even use CMake's file() function to write the one-liner at build time if you don't want to have to distribute it.

Related

How to set CMAKE_FIND_LIBRARY_SUFFIXES to nothing

I have run into an issue when writing find scripts. For some reason, automatic appending of suffixes did not work: only library files with .dylib extension were found, however files with .a extension or no extension at all were not.
Practical experimentation lead me to setting CMAKE_FIND_LIBRARY_SUFFIXES to an empty value and restoring the value afterwards. However, this has following effect:
When cmake is run for the first time, generation fails with "CMake Error: Error required internal CMake variable not set, cmake may not be built correctly. Missing variable is CMAKE_FIND_LIBRARY_SUFFIXES".
When I run cmake second time the same way, generation succeeds.
My guess is, things that were found are saved in cache, and the script for finding them is not run the second time.
My question is, how can I work around that issue and ensure that both my framework (that does not have suffixes) is found and cmake does not stop generation?
I am generating on MacOS, for Xcode.
Not sure what is an "official" way for assign a list of a single empty extension, but you may assign a list of two empty extensions:
set(CMAKE_FIND_LIBRARY_SUFFIXES ";")
Unlike to empty value, this assignment would pass possible sanity checks like if(CMAKE_FIND_LIBRARY_SUFFIXES), which probably exists in CMake code as it reports about "Error required internal CMake variable not set".

determine whether cmake is executing from terminal or gui

In CMakeLists.txt, is there a way to know whether the file was executed from a terminal or via a gui (of some form, e.g. ccmake or cmake-gui)? CMAKE_COMMAND and CMAKE_EDIT_COMMAND are both populated regardless of whether I am running cmake or ccmake.
I was searching through the variables and these two seemed the most promising. I have become enamored with colorizing cmake output, the many wonderful answers there have their drawbacks. Namely, I can either get:
It works as expected in a terminal, but there are escape sequences in ccmake.
It works as expected in a terminal, but the ccmake terminal is overwritten by colorized output (LOL).
Just curious if there is a way to determine this in the CMakeLists.txt. There were variables for script mode (-P) that seemed potentially helpful, but I think I would first need to know which executable (cmake or ccmake) called my CMakeLists.txt in the first place.
As far as I know, there is no way to distinguish whether the code was invoked from CMake or from CMake-gui. The code should behave in the same way, everything else would be a surprise for the user.
You could try to detect whether an instance of CMake-gui is running, but this is error-prone and is not justified for real use cases.

Get build command or all compiler flags that will be used to build a target

Is there a sensible way to get a CMake variable containing the build command or all the compiler flags that CMake will associate with a target?
It doesn't seem practical to try to gather and maintain a list of all properties that could add flags. Besides, CMake must have this info somewhere, since it has to eventually generate a build system.
From the CMake docs it looks like this feature once existed and was provided by calling build_command() but this was replaced:
Note In CMake versions prior to 3.0 this command returned a command
line that directly invokes the native build tool for the current
generator.
Is there a new command that gives the old behavior of build_command()?
Is there a sensible way to get a CMake variable containing the build command or all the compiler flags that CMake will associate with a target?
The answer is no (CMake 3.23 is latest at time of writing), not during the CMake configure step.
In general, such a thing is ill-defined, which is likely why it was removed from CMake and will likely not be re-added. The complications arising from generator expressions, multi-config generators, generators that don't construct command lines (like VS/msbuild), source-file-specific properties, and the simple fact that after the command is called, relevant state might change, all make such efforts quixotic.
Honestly, this is such an odd thing to want at configure time, I wonder if this isn't an XY problem. It's unlikely that one target depends on another in such a way that the entire eventual command line is needed (rather than a particular property) to create it.
I know this is many years later now, but what were you trying to do?
CMake provides many ways post-generation to get information about the compiler command lines.
There's the CMake File API, meant for IDE integration,
The CMAKE_EXPORT_COMPILE_COMMANDS option that creates a Clang-compatible compile_commands.json, and then there's
The CMAKE_<LANG>_COMPILER_LAUNCHER variables that would let you instrument a full command line with a custom script while the build is running.
One of these might be useful. The latter is commonly used with ccache, but can be (ab)used with any arbitrary program as long as the output file is eventually generated.
Note that the latter two only work with the Makefile and Ninja generators.
If you want the final output of how the source files will actually be compiled you will want to look at the generated files. I don't really know a better way currently:
Example:
Here is an example output from Ninja Multi
build\CMakeFiles\impl-Release.ninja
This file will list all of the compile definitions, compiler flags, include directories, object directory, etc.
Under the path "cmake-build-debug/CMakeFiles/" you'll find a folder named as "TopFolderOfYourProject.dir", where the cmake generates all its build system files, including a file "build.make". In this file you can see something like this:
CMakeFiles/somepath/somesourcefile.c
#$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=xxx\cmake-build-debug\CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building C object CMakeFiles/somepath/somesourcefile.c.obj"
Besides this, you can find extra info about the flags in the file "flags.make", it contains all extra compiler flags specified by developers.
And in "includes_C.rsp/includes_CXX.rsp" you can see the including path.
Build flags are, actually, associated with source files, because you can have differrent flags for different files. On the other hand, for the most cases these flags are equivalent.
Anyways, to get all build flags for a source file you can use COMPILE_FLAGS property:
get_source_file_property(RESULT file.cpp COMPILE_FLAGS)

Extract compiler command from cmake

The various clang-based completion tools (like youcompleteme) need to be told what compiler flags a source is to be compiled with. It would be nice if the compiler options to be used could be extracted from the project files. What would be easiest way to extract the flags (automatically, not manually) from either the cmake projects or the generated result in make or ninja format?
See http://clang.llvm.org/docs/LibTooling.html
Set CMAKE_EXPORT_COMPILE_COMMANDS=ON.
Ninja is actually able to print out commands to build all or specific target. And it does it extremely fast. As in on my machine in 0.033s for 1122 commands. It can print them either as shell commands or as compilation database and ycm has utility to use the compilation database.
It is important to note that the compdb ninja tool requires a rule name as argument. That does not seem to be mentioned in documentation.
The easiest is usually to do something in essence of CC=echo CXX=echo make and extract the arguments from it.
There's already an implementation of this in the clang_complete plugin, see the cc_args.py script at https://github.com/Rip-Rip/clang_complete/blob/master/bin/cc_args.py and documented in https://github.com/Rip-Rip/clang_complete/blob/master/doc/clang_complete.txt for more informations. If I'm not mistaken YCM can read .clang_complete files.
For example in clang_complete you run it like make CC='~/.vim/bin/cc_args.py gcc' CXX='~/.vim/bin/cc_args.py g++' -B
I'd not be surprised if YCM had a similar mechanism already available out of the box.
[EDIT] Yes it has, see https://github.com/Valloric/YouCompleteMe#c-family-semantic-completion-engine-usage and the "Clang's CompilationDatabase" support from the YCM documentation. Basically, either have make generate a file with the compilation flags for YCM to use or have clang generate a compilation database and have YCM use that.

CMake and librarian operation

I'm trying to get a COTS compiler/linker suite working with CMake and for the most part everything is working well. The issue I am running into is with the librarian.
A typical call as defined in COMPILER-${lang}.cmake file would look like this:
SET(CMAKE_C_CREATE_STATIC_LIBRARY " -v -c ")
but the librarian has no specific way of being told where the object files are so I would like to prepend the object files with the binary directory so as to give the librarian a specific place to find them. However I can't come up with the right syntax to do so.
Any thoughts on how one would do this?
After much work with the compiler/linker suite, it was determined that the main problem was that the compiler did not have the ability of being told where to put the object directly - in essence it did not support the typical -o parameter.
This resulted in the compiler naming the output file whatever it wanted and not paying attention to the that was being passed to it by the make utility.
It also turns out that the main compiler executable was really just a wrapper for the preprocessor, code generator and assembler so I ended up just RE'ing it and building my own wrapper that did support the -o parameter. It was definitively easier doing that trying to get CMake to work with this non-standard approach to generating outputs. Once the compiler started supporting the -o parameter the librarian worked without any issues.