Ambiguous documentation (until Ver 3.2) for how to define a (cached) variable in cmake from command line? - cmake

Looking at CMake documentation for the command line options, there's some ambiguity in the -D option used to define a variable.
In the command line synopsis there's
-D<var>=<value>
While in the option description we read:
-D <var>:<type>=<value>
The two entries differ by a space between -D and the variable definition, and by the presence/absence of :<type>.
Does the space make any difference? What is the difference between specifying or not the type? Is it cached in any case?
From a quick test, it seems the space is optional. While if the variable type is not specified, the variable goes in CMakeCache.txt as:
//No help, variable specified on the command line.
MYVARIABLENAME:UNINITIALIZED=MYVARIABLEVALUE
And it will not appear in the cache of cmake-gui.
Are these behaviours documented anywhere?
Edit:
I have reported an issue in CMake bug tracker. As visible in the link, it seems that some solution was already on its way, and documentation should be fixed for CMake 3.3!.

I don't believe the behaviour you're seeing is documented, but your conclusions are generally correct.
If the type is not specified, then the cached entry has type UNINITIALIZED. Since CMake isn't a strongly-typed language, you can use this variable as any type you require within the CMakeLists.txt - a string, path, list, etc. However, unless you explicitly change the type in your CMakeLists.txt (e.g. using a set call) its type will remain UNINITIALIZED as far as the cached value goes.
As far as I know, the type is really only useful if you're using the CMake GUI so it can appropriately choose which sort of input box to use for the variable, or whether to show it to the user at all or not.
As for the space - this is a more awkward situation. I have another answer which goes into this in a bit of detail, but basically, the space should have no effect, but it does under certain circumstances. I recommend not putting a space after -D arguments.

Related

Get the list of CMake configure_file calls

A bit of context first - I'm working on converting a CMake build system to an internal build system. For this I iterate BUILDSYSTEM_TARGETS and use get_property to get all the properties I need and everything works fine, except some files are missing from the build. After checking the CMakeLists.txt files from the original build system I realized configure_file is used in many and quite random places.
I assume CMake is storing configure_file calls internally. If this is the case, is it possible to access this?
Tsyvarev's answer of redefining configure_file works, but be aware that Craig Scott (one of the maintainers of CMake) has an article recommending against redefining CMake commands. Using the internal underscore-prefixed commands is relying on undocumented behaviour that can change in future versions. Using this trick can also result in infinite recursion.
While for your scenario it works fine, if you want to avoid using that trick, you can use the --trace* arguments to the cmake command.
--trace puts cmake in trace mode, which will print a trace of all calls made and from where.
--trace-expand is like --trace, but with variables expanded.
--trace-format=<format> lets you choose between human (a human readable format (the default value)), or json-v1, which prints JSON.
--trace-redirect=<file> puts cmake in trace mode and redirects trace output to a file instead of stderr.
So you could use the human format and grep for configure_file, or you could use the json-v1 format and write a script in a lanugage of your choice to search the JSON for calls to configure_file. You could also possibly use a comandline tool like jq to do the search.
You could redefine configure_file as a function (or macro) at the beginning of the project's CMakeLists.txt. That way allows you to run arbitrary code every time the function is invoked in the project.
Inside redefining function you could implement the logic which you need. For call original function in the redefining one, use underscore-prefixed name (_configure_file):
function(configure_file input output)
# ...
# Do something with the 'output' file. E.g. add it to the global list.
# ...
# After custom processing call original function with all parameters.
_configure_file(${input} ${output} ${ARGN})
endfunction()

CMake function arguments -- why are they occasionally uppercase?

I've been combing through the CMake documentation for a while now trying to figure out why some function arguments are capitalised and some aren't. I was hoping someone might be able to explain the pattern of things being capitalised, or at the very least point me in the direction of the documentation. This documentation https://cmake.org/cmake/help/v3.0/manual/cmake-language.7.html#cmake-language-7 gives very little in the way of explaining why certain things are capitalised.
From my current understanding,
uppercase arguments can be:
Keyword arguments of the function
Flags
Properties
Lowercase arguments are:
Other types of inputs to the function
Here's an example of a CMake file which you can maybe help me dissect?
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
include(SomeLib)
include_directories(include)
add_library(mylib SHARED src/main.cpp)
target_link_libraries(mylib ${boost_LIBRARIES})
install(TARGETS mylib DESTINATION lib)
VERSION I'm guessing is a keyword,
SHARED is probably also a keyword, or possibly a property,
TARGETS and DESTINATION are also keywords?
There is no some accepted style for writing CMake code so you can encounter anything. What you usually see is a historical somewhat accepted style used by the devs (Kitware) which was adopted by many others.
Usually you use lower case for CMake command, macro and function names, so to correct your code you need to lower case for the version command: cmake_minimum_required(VERSION 2.8) because it is a command.
Some commands have named arguments, some not. Usually named arguments are in upper case. In your example TARGETS, VERSION, SHARED and DESTINATION are all named arguments (which CMake calls keywords). They can be of any case but we just used to make them uppercase. Such arguments got parsed with the cmake_parse_arguments help for functions & macros. Since all commands are implemented in C++ the argument parsing is done in C++ for them (probably with the same "command").
Apart from the command names, lower case might be used in functions for local variables but that's not established and you can find any kind of mixing in the wild.
This is an addon to #ixSci's answer.
Some history of CMake.
Look at this message from 2003 asking if there were plans to allow lowercase commands.
No plans on changing this.
Much has changed. Check out this commit from 9 years ago, which changed a bunch of existing code from uppercase to lowercase. Here's a quote:
Ancient CMake versions required upper-case commands.
Later command names became case-insensitive.
Now the preferred style is lower-case.
Nowadays, CMake commands are case-insensitive and remain backwards-compatible. However, CMake variables remain case-sensitive.
Further, CMake 2.6 introduced cmake_policy, which can be used to specify a specific syntax version. Maybe you're feeling nostalgic...

Setting CMAKE_SYSROOT by generator expression

In our project we are setting CMAKE_SYSROOT depending on the selected configuration. It is so because configuration expresses (amongst others) target platform (cross-compilation - but not only, also slight behavior differences).
We would like to express this with generator expression to be friendly towards multi-configuration IDEs.
However, we haven't found a way to do so. First, you will notice that CMAKE_SYSROOT doesn't even mention such a possibility. We still tried to set it to something like this (not exact value - just a sample!):
set(CMAKE_SYSROOT $<IF:$<CONFIG:hw1>,path1,path2>)
hoping that the value is used in a context where generator expressions are supported. But apparently, it is not. Instead, it seems that the verbatim value is provided in --sysroot argument (--sysroot="\$<IF:\$<CONFIG:hw1>,path1,path2>"). Adding quotes around the value doesn't change anything.
What other options do we have?
Let me also add a note on the CMAKE_TOOLCHAIN_FILE which is mentioned in the documentation of CMAKE_SYSROOT.
I don't see the CMAKE_TOOLCHAIN_FILE being set to anything after grep-ing through files generated by cmake -DCMAKE_BUILD_TYPE=hw1 ../ and our own sources.
Apparently, the file where we set the CMAKE_SYSROOT is not pointed to by CMAKE_TOOLCHAIN_FILE. Yet, still, the --sysroot argument is being set to the expected value. (Only not by generator expression!) So, it does work somehow.
I expect we will have the same issue with other variables as well:
CMAKE_SYSTEM_NAME,
CMAKE_SYSTEM_PROCESSOR,
CMAKE_CXX_COMPILER,
CMAKE_C_COMPILER
the last two depend on the CMAKE_SYSROOT anyway (in our case).
If you really want to pass different --sysroot flags to the linker on a multi-configuration generator you'll just have to pass it via target_link_options using a generator expression. But then you might have to update rpath items yourself, but I'm not sure about that.
Variables are not used at build time and the documentation for generator expressions state:
Generator expressions are allowed in the context of many target properties...
I didn't see anything in the set command that prevents CMAKE_SYSROOT being set outside a tool-chain file. I'm guessing that the phrase This variable may only be set in a toolchain file should be This variable is normally used in a toolchain file.
It almost seems like that you are trying to use build type as a switch between two different tool chains. If that is the case then I don't see how that could work correctly with a multi-configuration generator. Most of everything you want to set is determined and used at configuration time not build time.

IDE for Go capable of refactoring: variable, function, structure and package renaming

I am interested in any IDE (or even a script) that is capable of refactoring Go source code for variable renaming. For example in Eclipse for Java, one can select a variable, an object or a class, then to rename it and it gets automatically renamed in all the files in the project. This feature is very useful if automatic string replacement may cause substring collisions.
If you're interested in a script, use gofmt with -r flag. Like this:
gofmt -w -r 'OldFoo -> Foo' foopackage
From the docs:
Without an explicit path, it processes the standard input. Given a file, it operates on that file; given a directory, it operates on all .go files in that directory, recursively. (Files starting with a period are ignored.) By default, gofmt prints the reformatted sources to standard output.
EDIT: Today there are better tools for that: gorename for renaming and eg for general refactoring.
The gorename tool performs precise type-safe renaming of identifiers in Go source code.

Log4cxx and full file paths when used with CMake

I'm using Log4Cxx for logging and I'd like to use the %l directive in order to see where is the log trace (filename and line number). The problem I have is that I'm also using CMake that provides full path names to the compiler. This causes that log columns aren't aligned any more and they are now difficult to read since the log4cxx uses the __FILE__ preprocessor macro for determining that information.
Does anyone know any workaround? I'd like to specify for instance either of getting only the "filename.cpp" or better with a nesting parameter, for instance 2 nesting will be "module/submodule/filename.cpp". It seems that by design CMake works with the full path philosophy so I think that this could be solved either by using an unknown to me preprocessor directive or to trick Log4CXX some way.
Looks like you could try using a "ConversionPattern" to at least specify a maximum width for the filename output of log4cxx:
http://logging.apache.org/log4cxx/apidocs/classlog4cxx_1_1_pattern_layout.html
Or do a "find on page" of ConversionPattern here for a config file example:
http://logging.apache.org/log4cxx/index.html
According to the docs, you should get the rightmost characters when you specify a maximum width. Maybe that's a close enough approximation to what you're seeking here.
CMake always passes full path source file names to the compiler so that debug symbols reference the correct source files (for one thing). It's simply easier to guarantee that things work everywhere on all platforms using the full path names.