cmake check if a public field exist in class - cmake

// some_library.h
class MyLib {
public:
int field_a;
int field_b; // Only available on some versions
int field_c; // Only available on some versions
int ...;
};
A library I'm using have a variable number of public fields depending on versions.
In Cmake, is it possible to detect if a certain field from library header exists?
(perhaps similar to the CHECK_FUNCTION_EXISTS)

You can use check_symbol_exists for a C symbol.
Doc: https://cmake.org/cmake/help/latest/module/CheckSymbolExists.html
Or check_cxx_symbol_exists for a CXX symbol.
Doc: https://cmake.org/cmake/help/v3.18/module/CheckCXXSymbolExists.html
You can use check_struct_has_member from CheckStructHasMember. See https://cmake.org/cmake/help/latest/module/CheckStructHasMember.html
CMakeLists.txt
include(CheckStructHasMember)
Check_struct_has_member("class MyLib" field_a ${CMAKE_CURRENT_SOURCE_DIR}/MyLib.h HAS_FIELD_A LANGUAGE CXX)

Related

cmake CheckSymbolExists for intrinsic

I'd like to check for intel intrinsics such as _mm_popcnt_u32 or _mm_blendv_epi8 using cmake. However the function check_symbol_exists doesn't work properly depending on the compiler. (it works with Clang but not with GCC). Indeed it is documented
If the header files declare the symbol as a function or variable then the symbol must also be available for linking (so intrinsics may not be detected).
Is there a simple way to check for those ?
As the CMake documentation also states:
If the symbol is a type, enum value, or intrinsic it will not be
recognized (consider using CheckTypeSize or CheckCSourceCompiles).
So, try to compile a small example with the Intel intrinsic using CheckCSourceCompiles. E.g.:
include(CheckCSourceCompiles)
check_c_source_compiles("
int main() {
int tmp = _mm_popcnt_u32(0);
return 0;
}
"
HAVE_INTRINISC
)

Insert int variable into the class using LLVM PASS or Clang

I want to insert integer variable into all classes using LLVM PASS or Clang.
How to do this ?
For example..
class foo {
int a;
}
I want to insert new value as below.
class foo {
int a;
unsigned int b; // I want to insert this.
}
How can I do this using LLVM PASS or Clang ?
- I much prefer LLVM PASS.
Thank you very much :)
My recommendation would be to use Clang for this, as LLVM operates on bitcode (IR) and the operation you want is very much C++ related, so why not exploit Clang's knowledge about the AST?
With LibTooling you can write stand-alone tool to do exactly what you want. More specifically, use an AST Matcher to find all C++ class declarations (cxxRecordDecl). You can then insert a new FieldDecl in your callback.
More info: LibTooling and LibASTMatchers Tutorial

What compiler option/library do I need to use detect_or_t type trait?

I am trying to use std::experimental::detect_or_t from <experimental/type_traits>.
What compiler, option, version or library do I need to compile the following example from http://en.cppreference.com/w/cpp/experimental/is_detected ?
#include <experimental/type_traits>
#include <cstddef>
template<class T>
using diff_t = typename T::difference_type;
template <class Ptr>
using difference_type = std::experimental::detected_or_t<std::ptrdiff_t, diff_t, Ptr>;
struct Meow { using difference_type = int; };
struct Purr {};
int main()
{
static_assert(std::is_same<difference_type<Meow>, int>::value, "Meow's difference_type should be int!");
static_assert(std::is_same<difference_type<Purr>, std::ptrdiff_t>::value, "Purr's difference_type should be ptrdiff_t!");
}
I tried using clang++ -std=c++14 and g++ -std=c++14. Also with -std=c++1y and -std=c++17. I always get this:
main.cpp:8:44: error: 'detected_or_t' in namespace 'std::experimental' does not name a template type
Those traits were first added to libstdc++ in GCC 6.1.0, as documented in the GCC 6 release notes:
Experimental support for most features of the second version of the Library Fundamentals TS.
And the implementation status tables in the manual, at
https://gcc.gnu.org/onlinedocs/gcc-6.1.0/libstdc++/manual/manual/status.html#table.cxx1z_ts_status
I'm less sure about libc++, but they're not supported by the version in Clang 3.9.1 but are supported by the current trunk, so I think they first appeared in Clang 4.0.0

Force g++ to generate code for unused functions

By default, g++ seems to omit code for unused in-class defined methods. Example from my previous question:
struct Foo {
void bar() {}
void baz() {}
};
int main() {
Foo foo;
foo.bar();
}
When compiling this with g++ -g -O0 - c main.cpp, the resulting object file only contains references to bar and not to baz. Adding --no-deafault-inline to the computer flags does not help either. Any ideas how I can force g++ to generate code for baz as well?
Rationale
The test coverage tool gcov reports unused methods as non-executable if they are omitted from the final executable. However, to get meaningful reports I want them to be reported as executable-but-not-executed. For this, I need to find a way to achieve this without having to alter the original source code.
A portable way to do that is to add some "reference" (in the ordinary sense, not only the C++ one, of the word) to these routines.
This could be something as simple as
typedef void (Foo::*funptr_t) (void);
extern "C" const funptr_t tabfun[] = { &Foo::bar, &Foo::baz };
(I'm declaring the array tabfun as extern "C" to be sure that array is emitted, even if not used)
You might try the -fno-inline argument to GCC. You could also customize GCC (e.g. with MELT) to have such an array added automatically (without touching the source code), but this requires some work.

How to specify library dependency introduced by header file

Suppose in a CMake project, I have a source that is built into a library
// a.cpp
void f() { /* some code*/ }
And I have a header
// b.h
void f();
struct X { void g() { f(); } };
I have another file:
// main.cpp
#include "b.h"
int main() { X x; x.g(); }
The CMakeLists.txt contains:
add_library(A a.cpp)
add_executable(main main.cpp)
target_link_libraries(main A)
Now look at the last line of the CMakeLists.txt: I need to specify A as the dependencies of main explicitly. Basically, I need to specify such dependencies for every source that includes b.h. Since the includes can be indirect and go all the way down through a chain of includes. For example, a.cpp calls a class inline function of c.h, which in turns calls function in d.h, etc, and finally calls function from library A. If b.h is included by lots files, manually finding out all such dependencies is not feasible for large projects.
So my question is, is there anyway to specify that, for every source file that directly or indirectly includes a header, it needs to link against certain library?
Thanks.
To make one thing clear: You a.cpp gets compiled into a lib "A". That means that any user of A, will need to specify target_link_libraries with A. No way around it. If you have 10 little applications using A, you will need to specify target_link_libraries ten times.
My answer deals with the second issue of your question and I believe it is the more important one:
How to get rid of a chain of includes?
By including a.h in b.h and using its method in b.h you are adding a "implicit" dependency. As you noticed, any user of b.h needs a.h as well. Broadly speaking, there are two approaches.
The good approach:
This has nothing to do with CMake, but is about encapsulation. The users of your library (incl. you yourselves) should not need to worry about its internal implementation. That means: Don't include b.h in a.h.
Instead, move the include to a .cpp file. This way, you break the chain. E.g. something like
// b.h
void f();
struct X
{
void g();
};
// b.cpp
#include b.h
#include a.h
void X::g( )
{
f();
}
This way, the use of a.h is "contained" in the cpp file and anyone using you library need only include b.h and link to b.lib.
The alternative:
Now, there are situations where you have to accept such a "dependency" or where it is a conscious choice. E.g. when you have no control over A or when you conciously decided to create a library defined in terms of classes/structs internal to A.
In that case, I suggest you write a piece of CMake code, which prepares all the necessary include-dirs down the chain. E.g. define a variable "YOURLIB_INCLUDES" and "YOURLIB_LIBRARIES" in "YourLibConfig.cmake" and document that any user of your library should import "YourLibConfig.cmake". This is the approach several cmake-based projects take. E.g. OpenCV installs a OpenCVConfig.cmake file, VTK installs a VTKConfig.cmake and prepares a UseVTK.cmake file