cmake LibFindMacros set library minimum version number - cmake

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.

Related

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

Cmake - Documentation

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.

Produce static libs from tensorflow_cc and tensorflow_framework

As far as I understand using bazel I can only produce libtensorflow_cc.so and libtensorflow_framework.so.
I need to produce static libs that are position independent (-fPIC) because I'll link them to a dynamic lib of my own later.
I found this answer which suggest the use of a Makefile included in the project.
I successfully used it to replace the libtensorflow_cc.so but what can I do to replace libtensorflow_framework.so?
Not an actual answer, but too long for a comment.
I managed to do something like what you mention using Bazel on Windows. In particular, I wanted to make a single wrapper DLL with one or two headers (limited in functionality) that I could move around easily. I'll write a summary of the things that I did; it's rather convoluted an customized for our needs, but maybe you find something useful.
I pass --config=monolithic to the bazel build command (besides any other option that you need). That will avoid modularizing the library and thus remove the dependency to a libtensorflow_framework.so (see
tools/bazel.rc).
The goal that I build is not any of the ones in the TensorFlow repository. Instead, I add a very small program that uses my wrapper as a new Bazel target (a C++ file plus my headers headers and a BUILD file). So all of TensorFlow had to be compiled beforehand in order to compile this final dummy program.
When I get that done, I take advantage of the fact that Bazel does already compile every subgoal as a static library. I check a file under the bazel-bin directory generated for my dummy program goal with a name ending .params - there I find the path of all the static libraries that were used to compile it.
I copy all of these intermediate static libraries to somewhere else. Also, I copy a bunch of headers I will need to compile my final wrapper (TensorFlow own's, but also Eigen, Protobuf and Nsync now too). I put all of this in a build area I have prepared before.
I use NMake Makefile to produce my custom DLL, using the static libraries, the copied headers and my own thin wrapper.
And that's about it, I think. I have an ugly Bash script I run on MSYS2 that does everything for me. Usually with every new release I need to tweak one or two things (some option in the configure script, some additional headers I need to copy, etc.), but I do get it to work in the end. It's quite a lot of fiddling though, so I'm not necessarily saying you should use the same approach (but feel free to ask for details about any step if you want).
Using the -2.params files #jdehesa mentioned and bazel verbose output (-s switch), you can even create a link command to eventually statically link these intermediate static libraries. I automated this process for Windows/Linux/macOS and included it to the vcpkg package manager. To use it just run vcpkg install tensorflow:x64-windows-static. If you're interested in the sources, you'll find them here.

How to get cmake to find size of type in third-party header mpi.h?

I am working on a free-software project which involves high performance computing and the MPI library.
In my code, I need to know the size of the MPI_Offset type, which is defined in mpi.h.
Normally such projects would be build using autotools and this problem would be easily solved. But for my sins, I am working with a CMake build and I can't find any way to perform this simple task. But there must be a way to do - it is commonly done on autotools projects, so I assume it is also possible in CMake.
When I use:
check_type_size("MPI_Offset" SIZEOF_MPI_OFFSET)
It fails, because mpi.h is not included in the generated C code.
Is there a way to tell check_type_size() to include mpi.h?
This is done via CMAKE_EXTRA_INCLUDE_FILES:
INCLUDE (CheckTypeSize)
find_package(MPI)
include_directories(SYSTEM ${MPI_INCLUDE_PATH})
SET(CMAKE_EXTRA_INCLUDE_FILES "mpi.h")
check_type_size("MPI_Offset" SIZEOF_MPI_OFFSET)
SET(CMAKE_EXTRA_INCLUDE_FILES)
It may be more common to write platform checks with autotools, so here is some more information on how to write platform checks with CMake.
On a personal note, while CMake is certainly not the most pleasant exercise, for me autotools is reserved for the capital sins. It is really hard to me to defend CMake, but in this instance, it is even documented. Naturally, setting a separate "variable" that you even have to reset after the fact, instead of just passing it as a parameter, is clearly conforming to the surprising "design principles" of CMake.

LD_PRELOAD on AIX

Can someone here tell me if there is something similar to LD_PRELOAD on recent versions of AIX? More specifically I need to intercept calls from my binary to time(), returning a constant time, for testing purposes.
AIX 5.3 introduced the LDR_PRELOAD (for 32-bit programs) and LDR_PRELOAD64 (for 64-bit programs) variables. They are analoguous to LD_PRELOAD on Linux. Both are colon-separated lists of libraries, and symbols will be pre-emptively loaded from the listed shared objects before anything else.
For example, if you have a shared object foo.so:
LDR_PRELOAD=foo.so
If you use archives, use the AIX style to specify the object within the archive:
LDR_PRELOAD="bar.a(shr.so)"
And separate multiple entries with a colon:
LDR_PRELOAD="foo.so:bar.a(shr.so)"
AIX 5L uses the LDR_PRELOAD variable.
Not that I'm aware of. Closest thing we've done (with malloc/free for debugging) is to
create a new library file with just the functions desired (same name as original).
place it in a different directory to the original.
make a dependency from our library file to the original.
change the LD_LIBRARY_PATH (or SHLIB_PATH?) to put our library first in the search chain.
That way, our functions got picked up first by the loader, any we didn't supply were provided by the original.
This was a while ago. AIX 5L is supposed to be much more like Linux (hence the L) so it may be able to do exactly what you require.
Alternatively, if you have the source, munge the calls to time() with mytime() and provide your function. You're not testing exactly the same software but the differences for that sort of minimal change shouldn't matter.