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.
Related
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()
In my CMake file I need to use lib.exe in custom command when building on Windows to combine multiple static libraries into one.
I tried to use find_program command to find the executable:
find_program(LIB_EXE NAMES lib.exe)
but it always sets the variable to not found. What is the right way to find lib.exe?
[EDIT] Fixed NAME->NAMES, but the program is still not found
The proper keyword is NAMES which may be omitted. Try adding the S or removing the keyword entirely.
I think you're actually searching for the program NAME
Check the file CMakeCache.txt in your build directory, and search for "lib.exe".
There you can find "lib.exe" can be located by the variable ${CMAKE_AR}.
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.
CMake documantation seems clear: unless NO_DEFAULT_PATH is specified, cmake proceeds to first search a bunch of default paths, and if the library is not found, only then it looks in the directories listed in PATHS. A few other NO_* exist, to only exclude some of cmake default paths.
I know how to overcome this behavior. E.g., I can do what's suggested here, namely, do two searches: the first with NO_DEFAULT_PATH, and the second without it. If the first succeeds, the second will be skipped. Win.
However, this question is not about how to achieve what I want (I know the hack). The question is why do I need to do that? Why doesn't cmake look first in the provided paths? It seems logic to me to use those first: if the user is specifying some hints, perhaps I should use those first, and fall back on defaults if they don't work...
Is there a good reason I am missing for the current implementation? I would assume so, I doubt folks down at cmake do things without a good reason...
Edit: when I said 'the user is specifying some hints', I was not referring to the actual HINTS argument of find_library. It was more of a generic 'hints'. However, as suggested in a comment, HINTS is indeed scanned before system paths. My concern comes from cmake's documentation:
Search the paths specified by the HINTS option. These should be paths
computed by system introspection, such as a hint provided by the
location of another item already found. Hard-coded guesses should be
specified with the PATHS option.
The fact that HINTS was not designed to receive hard coded full paths, makes me thing it may fire back in the future, so I'm not sure it is the solution. But maybe it is?
As the title stated, I want my compiler to fail when I include some header files; for example, <cmath>
Is that possible with just compiler flags? Or do I have to actually delete those headers?
#include <cmath> has nothing to do with any library, and everything to do with a header file. Assuming that you really do mean that you want compilation to fail if you include a particular header file, you should be able to leverage GCC's support for specifying include directories through environment variables.
To do so, create or edit an appropriate environment file. If you are using GNU bash on Debian, for example, you can create a file /etc/profile.d/gcc-include-dirs. Everything readable in /etc/profile.d is sourced when a shell is launched, so it will apply to all shells started after that point. (To be absolutely certain, you may want to log out and back in once, then issue env | grep INCLUDE to confirm.) Create such a file with your favorite editor and add the following to it:
export C_INCLUDE_PATH=/usr/local/include/fail:${C_INCLUDE_PATH}
export CPLUS_INCLUDE_PATH=/usr/local/include/fail:${CPLUS_INCLUDE_PATH}
Make sure the file is readable by everyone (chmod 644 /etc/profile/gcc-include-dirs) and that it is owned by root (chown root:root /etc/profile/gcc-include-dirs).
You can also put the file elsewhere and simply source it when needed, if you only need this behavior at specific times. In that case, logging out from the shell in question and logging back in will restore GCC's normal behavior (you don't need to log out from the entire session, just that particular shell instance). Starting a subshell and sourcing the file from within that subshell will also work nicely in that case; just exit when you are done.
Then create a file /usr/local/include/fail/cmath with the following content:
#error "Failing because you included 'cmath'"
Make sure that file too is readable by everyone and owned by root. #error and its evil twin #warning emit a fatal error and a compilation warning, respectively, so whenever this file gets included, GCC will encounter a #error preprocessor directive resulting in the emission of a fatal error which causes the compilation to fail.
If you want to override this behavior for a single compilation, simply use gcc's -I parameter to specify the path to the directory where the real math.h lives. Since -I takes precedence over $C_INCLUDE_PATH and $CPLUS_INCLUDE_PATH this means that you then include the C library's version. For example, cc -o mathprogram -I/usr/include mathprogram.c will use the math.h in /usr/include when you #include <math.h> regardless of what might be in /usr/local/include/fail, because it looks first in /usr/include.
Since this only affects compilation (and only compilation started through a shell), everything that is already on your system will be completely unaffected (unless they have some weird dependencies to those two environment variables).
For c* headers, you may need to also create the corresponding *.h header with content identical to the c* header. This is because e.g. cmath might simply map to math.h (the name of the same header in C). Simply make another file just like the one above, but complain about math.h instead. (GCC doesn't care, but it makes diagnostics easier.) You may also need to put files in other places (I'm not sure exactly what include directory structure GCC wants for C++ headers); in that case, find / -name cmath (or something similar) will give you an idea of the structure you need to replicate under /usr/local/include/fail.
Do note that this will not stop people simply copying the relevant parts of the header file into their own source code; there is nothing magical about the header files from the compiler's point of view. Depending on exactly what you are trying to protect against, this may be an issue.
What about simply using a pre-processor symbol to omit the library header(s)?
Compiling with the gcc option -DDONT_WANT_LIBS will fail due to the missing library declarations in the library header file.
#ifndef DONT_WANT_LIBS
#include<specific_library_header.h>
#endif
...
...