Cmake - Documentation - cmake

I use clang, gcc (and also their arm version).
is there somewhere a documentation, where i can see which values the following 2 arguments take:
set(CMAKE_SYSTEM_NAME <value>)
set(CMAKE_SYSTEM_PROCESSOR <value>)
i cannot find any doc, where cmake lists every possible input.
i just see that you have to assign a value to those, but what options do i have?
like system name: Linux is one, how about Windows?
And then what about processors, arm, x86, x86_64 (amd64)...
would be cool if someone knows a good source of documentation.
thanks

From the CMake wiki about cross compiling:
Once the system and the compiler are determined by CMake, it loads the
corresponding files in the following order:
Platform/${CMAKE_SYSTEM_NAME}.cmake (optional, but issues a stern
warning)
Platform/${CMAKE_SYSTEM_NAME}-<compiler>.cmake
(optional)
Platform/${CMAKE_SYSTEM_NAME}-<compiler>-${CMAKE_SYSTEM_PROCESSOR}.cmake
(optional)
So, for find out all possible values for variable CMAKE_SYSTEM_NAME you could check filenames under Modules/Platform and extract the first part of every filename.
As for CMAKE_SYSTEM_PROCESSOR variable, its only purpose is to include the latter file (of 3 components in the filename). From the same wiki:
This variable is not used very much except for one purpose,
it is used to load a CMAKE_SYSTEM_NAME-compiler-CMAKE_SYSTEM_PROCESSOR.cmake file,
which can be used to modify settings like compiler flags etc. for the target.
You probably only have to set this one if you are using a cross compiler
where every target hardware needs special build settings.

Related

What's the idiomatic way to compile the same file twice, with different languages?

I have a source file which is valid in (at least) two languages. Say, C and C++ or C and CUDA.
I want to compile this file in both languages, each time into a different library. What's the idiomatic way of doing this in recent versions of CMake?
Notes:
If the specific version of CMake matters, please specify which minimum version I would need.
Related: How can I configure cmake to compile a file twice with two different compilers?
This elaborates on #KamilCuk's suggestion in a comment on the OP, written before I noticed the comment.
The LANGUAGE property is set on the source file itself, which is the core of your question. The documentation for this property describes it being visible in the scope of the directory where it is set. That means that one way to have different languages is to set the property in two different directories. For example:
src/
CMakeLists.txt
common/
main.c
app1/
CMakeLists.txt
app2/
CMakeLists.txt
src/CMakeLists.txt:
add_subdirectory(app1)
add_subdirectory(app2)
app1/CMakeLists.txt:
set_property(SOURCE ../common/main.c PROPERTY LANGUAGE CXX)
add_executable(app1 ../common/main.c)
app2/CMakeLists.txt:
set_property(SOURCE ../common/main.c PROPERTY LANGUAGE C)
add_executable(app2 ../common/main.c)
This will build main.c into two different targets, with two different LANGUAGE settings.
The docs also hint at being able to set the property explicitly against other directory scopes including binary directories. I was hoping this would help make the job simpler, but I can't get it to work.
Since, indeed, LANGUAGE is a per-file property, I believe what should happen - and would allow for a proper idiom here - is to have a binary relation of language-to-use for pairs of (target, source file).
I've suggested this to KitWare in an issue report (gitlab.kitware.com).

What does the -specs argument do in arm-none-eabi-gcc?

I was having trouble with the linker for the embedded arm gcc compiler, and I found a tutorial somewhere online saying that I could fix my linker errors in arm-none-eabi-gcc by including the argument -specs=nosys.specs, which worked for me, and it was able to compile my code.
My chip is an ATSAM7SE256 microcontroller, which to my understanding is an arm7tdmi processor using the armv4t and thumb instruction sets, and I've been compiling my code using:
arm-none-eabi-gcc -march=armv4t -mtune=arm7tdmi -specs=nosys.specs -o <exe_name>.elf <input_files>
And the code compiles with no issue, but I have no idea if it's doing what I think it's doing.
What is the significance of a spec file? What other values can you set with -specs=, and in what situations would you want to? Is nosys.specs the value I want for a completely embedded arm microcontroller?
It is documented at: https://gcc.gnu.org/onlinedocs/gcc-11.1.0/gcc/Overall-Options.html#Overall-Options
It is a file containing switches to override standard defaults for various build components such as the compiler, assembler and linker. For example it can be used to replace the default C library.
I have never seen it used; typically bare-metal embedded system builds explicitly specify --nostdlib then explicitly link the required library. It could be used for environment specific build environments to link other default code such as an RTOS I guess. Personally I'd rather make all that explicit on the command line that hiding it in a file somewhere.
Essentially it applies the switches specified in the file as if they were defaults, so can be used to define defaults for specific build and execution environments.
The format of the specs file is documented at https://gcc.gnu.org/onlinedocs/gcc-11.1.0/gcc/Spec-Files.html#Spec-Files
Without seeing both the linker errors and the content of the nosys.specs file in this case it is difficult to say how or why it solved your linker problem. The alternative solution of course would be to apply whatever switches are in the specs file directly.

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)

cmake LibFindMacros set library minimum version number

In Cmake, when using LibFindMacros, is there a way to tell cmake that a library needs to have a minimum version number? The information I've found on http://www.cmake.org/Wiki/CMake:How_To_Find_Libraries doesn't say anything about that.
No... No integrated version support in finding libraries with cmake.
My guess is that in most cases each library has its own way of defining its version and therefore it makes it a daunting task to find out what that version really is. On a Linux system, you could try to query the system with a tool such as dpkg or rpm, but those would only give you the version of the installed library, not the one you're about to compile against.
There is an issue talking about that here:
http://public.kitware.com/Bug/view.php?id=8396
Now, the macros you mentioned have a function to extract a version assuming there is #define <version> <#.#.#> or something of the sort in a header file for that library.
https://github.com/Tronic/cmake-modules/blob/master/LibFindMacros.cmake
# Extracts a version #define from a version.h file, output stored to <PREFIX>_VERSION.
# Usage: libfind_version_header(Foobar foobar/version.h FOOBAR_VERSION_STR)
# Fourth argument "QUIET" may be used for silently testing different define names.
# This function does nothing if the version variable is already defined.
function (libfind_version_header PREFIX VERSION_H DEFINE_NAME)
...
So you use this macro, retrieve a #define from a .h file and then compare that value saved in ${PREFIX}_VERSION in your own way. In my libraries, I often have a set of 3 or 4 #define with the major, minor, and release version numbers. That makes it easy to compare. When you get all those numbers together, such as 3.2.4.1, it makes it harder to compare without specialized code... (again, that makes it really complicated for cmake to support a version comparison scheme.)
Note that the macro expects ${PREFIX}_INCLUDE_DIR to be set. It looks like libfind_pkg_detect() sets that variable so you need to first detect the location of the library (headers) and then you can gather the version in a header.
Update:
Note that there are specialized compare operators you can use to compare two version strings against each other:
if(${PREFIX}_VERSION VERSION_EQUAL 1.2.9)
The only problem is that it's going to be a cmake version comparison algorithm which may not match the corresponding project algorithm. That means it's limited to just numbers separated by periods. I'm not too sure when these operators were added to cmake.

Cmake not setting RPATH when adding link_library with -L

When setting link libraries in the following manner
target_link_libraries (SOME_TARGET -L/somedir -lfoo)
cmake doesn't handle RPATHs. Is using '-L' and '-l' not best practice, or actually plain wrong? When creating my own Find*.cmake I usually use find_library() but the find script I got doesn't do this and resorts to the above form using '-L' and '-l'.
The documentation doesn't really explain how RPATHs are gathered, also the documentation isn't really clear how it handles "-l" and "-L" the only pointer you get is
"Item names starting with -, but not -l or -framework, are treated as
linker flags"
Specifying toolchain-dependent flags like -l and -L is generally not recommended, as it breaks portability and might have different effects than you expect.
The correct way to set the linker path would be the link_directories command.
The idiomatic solution in CMake is to use find_library for locating the library and then pass the full path to the linker, so you do not need to worry about link directories at all.
Now, the RPATH is a different beast, as it also determines where dynamic libraries can be located at runtime. Usually, the default settings work reasonably fine here. If you ever find yourself in the unfortunate situation where it does not, there is a number of target properties and CMake variables influencing this:
There are a few properties used to specify RPATH rules. INSTALL_RPATH
is a semicolon-separated list specifying the rpath to use in installed
targets (for platforms that support it). INSTALL_RPATH_USE_LINK_PATH
is a boolean that if set to true will append directories in the linker
search path and outside the project to the INSTALL_RPATH.
SKIP_BUILD_RPATH is a boolean specifying whether to skip automatic
generation of an rpath allowing the target to run from the build tree.
BUILD_WITH_INSTALL_RPATH is a boolean specifying whether to link the
target in the build tree with the INSTALL_RPATH. This takes precedence
over SKIP_BUILD_RPATH and avoids the need for relinking before
installation. INSTALL_NAME_DIR is a string specifying the directory
portion of the “install_name” field of shared libraries on Mac OSX to
use in the installed targets. When the target is created the values of
the variables CMAKE_INSTALL_RPATH, CMAKE_INSTALL_RPATH_USE_LINK_PATH,
CMAKE_SKIP_BUILD_RPATH, CMAKE_BUILD_WITH_INSTALL_RPATH, and
CMAKE_INSTALL_NAME_DIR are used to initialize these properties.
(From the set_target_properties docs)
Also, you might want to have a look at the CMake Wiki page for RPATH handling.
The whole RPATH business is unfortunately rather complex and a thorough explanation would require far more space than is appropriate for a StackOverflow answer, but I hope this is enough to get you started.
Basically, You're using target_link_libraries() wrong. According to documentation, You should provide target, libraries and maybe some CMake specific linkage flags.
For example something like that:
target_link_libraries(my_build_target somedir/foo.so)
If You're using Your own crafted Find*.cmake solutions, it's usualy being done like this:
find_library(foo)
//build main target somewhere here
//now link it:
target_link_libraries(my_build_target ${FOO_LIBRARIES})
NOTE: I assume Your crafted Find*.cmake files follows these guidelines and fills CMake variables like SOMELIB_LIBRARIES, and/or SOMELIB_INCLUDE_DIRS, etc.
NOTE2: for my personal opinion, target_link_directories() is pain in a butt and You should avoid using it if not really needed. It's difficult to maintain and uses paths relative to current source directory.