How to set CMAKE_FIND_LIBRARY_SUFFIXES to nothing - cmake

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".

Related

How to keep CMake generated files?

I'm using add_custom_command() to generate some files. ninja clean removes them, as it should. One of the files is intended as a default/example implementation, to be modified by the user. It is only generated if it does not already exist. I would like for ninja clean not to remove this file.
I have tried a number of things but without success:
add_custom_target(): CMake complains about the missing file unless I name it in BYPRODUCTS, but doing this also leads to removal on clean
set_file_properties(... GENERATED FALSE) doesn't work because CMake complains about the file missing.
set_directory_properties() failed in a similar way: "folder doesn't exist or not yet processed" (it does exist)
I previously generated the example implementation and just let the user copy it or model their code on it. This works, but isn't entirely satisfactory. Is my use-case so unlikely that CMake doesn't support it?
I am afraid you requirment (conceptually, have make create something which make clean does not remove) is rather unusual. I can think of two potential solutions/workarounds.
One, move the file's generation to CMake time. That is, create it using execute_process() instead of add_custom_command(). This may or may not be possible, based on whether the file-generation process (the current custom command) depends on the rest of the build or not.
Two, totally hide the example file's existence from CMake. That is, have the custom command also generate some other file (maybe just a timestamp file) and have its driving custom target depend on that one instead. Do not list the example file as ither the custom command's dependency, output, or byproduct. That way, nothing will depend on it and neither CMake nor Ninja should not care whether it exists or not, so they will not complain or try to clean it up.
If it is an example for the user, it should not be in your build folder, but in the install folder. I don't see why you would need add_custom_command or the other commands you listed.
Therefore, you have to provide install() instructions.
You can then call make install. Cleaning will not remove those and only installing again will overwrite them if necessary.
For those, who come here a long time after the original question was asked (like me), I'll write my solution:
The tool called in add_custom_command generates two files with identical content:
one that is saved in sources, never mentioned anywhere
and one that's marked as byproduct, and then is depended on
So the first one is the file we wanted in the first place.
And the second one is actually used in build process, and gets deleted on clean.
For me the issue is that I actually want to save generated files in VCS so I can track changes. And this approach gives ne what I need.

cmake: stop if a manually specified variable is not used by the project

if I give as an input parameter an undefined variable to CMake, it will simply warn me about the fact that this variable is not used by the project.
So, I wonder whether one can tell cmake to stop in case of undefined variables given by the user.
The only approach I came so far to, was to parse the cmake output log and search for strings like:
CMake Warning:
Manually-specified variables were not used by the project
I had a look at the man of cmake, without finding something which could do the job.
so how can i tell cmake, that instead of a simple warning, that I may miss, it should stop on CMake Warning about unknown variables?
The solution, if any, should not involve modifying the CMakeList.txt files.
Of course, I can download the cmake sources and change in the
cmake::RunCheckForUnusedVariables()
method:
this->IssueMessage(cmake::WARNING, msg.str());
by:
this->IssueMessage(cmake::FATAL_ERROR, msg.str());
but if i could avoid doing that hack, I will be grateful!
thanks for your help.

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)

Use generator expression to set build type specific flags

I'd like to set some specific compile flags based on my current build configuration in cmake. I thought generator expressions would allow me to do this, but they don't appear to be working the way I expected.
I'm using the following command to set compile options to my main target. Both the expressions appear to always evaluate true as --debug and -Oh are passed to compiler no matter what CMAKE_BUILD_TYPE is set to.
target_compile_options(${PROJECT_NAME}
PUBLIC
${COMMON_COMPILER_FLAGS}
$<$<CONFIG:Debug>:--debug>
$<$<CONFIG:Release>:-Oh>
)
I'm using cmake 3.4.1 on Windows and I'm cross-compiling with the IAR toolchain. To be more specific, I'm executing cmake from the bash shell in Cygwin, but its still the Windows executable. I'm using the Unix Makefile generator.
It looks like the second flag is getting picked up from somewhere and just so happens to be ordered at the right spot to give me the above impression.
I can update with an explanation for that when I determine it, but the generator expressions appear to have always been working. I inserted some keyboard-smash in for both and it became apparent only one was getting through to command line.
EDIT:
The unwanted optimization flag was coming from target_compile_options calls on a couple libraries that are linked to my main target. I had the scope options set to PUBLIC, which means the options populate INTERFACE_COMPILE_OPTIONS. I changed the scopes to PRIVATE and it got rid of the unwanted flag.

CMake and clang_complete

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.