Issue with Boost.Json library - c++

Could somebody help me with error I am getting when including:
#include <boost/json/src.hpp>
Error is:
In file included from /usr/local/include/boost/json/src.hpp:27:
In file included from /usr/local/include/boost/json.hpp:15:
In file included from /usr/local/include/boost/json/array.hpp:16:
In file included from /usr/local/include/boost/json/storage_ptr.hpp:14:
In file included from /usr/local/include/boost/json/memory_resource.hpp:16:
/usr/local/include/boost/container/pmr/polymorphic_allocator.hpp:132:23: error: expected a class name after '~' to name a destructor
{ (void)p; p->~U(); }
My CMake config has:
find_package(Boost 1.80.0 REQUIRED COMPONENTS timer json)
and
target_link_libraries(device_monitor
Boost::timer
Boost::json
)

Apparently somewhere you have defined U as something else. Preprocessor macros are unsanitary like that, so avoid it.
My guesses are that you are on some kind of Windows platform and U() is a macro that "smart" wraps a string literal of some kind (e.g. to do some UNICODE-depedent stuff or translation).
You could easily show us that in a minimal self-contained example, or go ahead and figure it out by using CMake to precompile the translation unit for you, e.g. something like cmake --build build test.cpp.i. You will find out what the compiler sees instead of the intended code.
You can also demonstrate this effect by
moving the boost include to the top
disabling precompiled headers if you are using them

Related

How to handle library's function files (not header files) in autotools?

So recently I've been trying out autotools to build a C++ Library. Originally I was just working on pure custom classes, which is quite easy to just #include and then compile with g++. But when I want to write some custom functions for the library, I've learnt that it's a bad practice to write functions within header file, but rather I should declare it in header then wrote it in a separate .cpp file. Which later I've tried and successfully compiled with g++ ./lib/**/*.cpp src/main.cpp.
So basically my project structure is that codes are put under src/, headers are under include/ and functions are put under lib/. And following is my src/Makefile.am
AUTOMAKE_OPTIONS = subdir-objects foreign
bin_PROGRAMS = main
include_HEADERS = -I../include/**/*.hpp
main_SOURCES = -I../lib/**/*.cpp main.cpp
And for the endpoints' directory (under lib/) I have something like following
main_SOURCES = stdout.cpp
But it gave me error that no program named main, so I figured maybe all those function files has to be compiled first, so I changed them into
noinst_PROGRAMS = stdout
stdout_SOURCES = stdout.cpp
But then they gave me the following error
/usr/sbin/ld: /usr/lib/gcc/x86_64-pc-linux-gnu/11.1.0/../../../../lib/Scrt1.o: in function `_start':
(.text+0x24): undefined reference to `main'
collect2: error: ld returned 1 exit status
I know that the error meant that there's no main() written in the file, but since it's a library function file, it doesn't meant to have a main(), it's meant to be called by other file (like main.cpp). And to here I'm stuck.
I've tried to find documentation online, but it seems that most of them are targeted at C programs instead of C++, which I'm not sure if those steps are compatible. And I remember C++ libraries are compiled into .so or .o file while most tutorials seems to be using .la files.
MWE
src/main.cpp
#include"../include/conn/bash/stdout.hpp"
#include<string>
#include<iostream>
int main() {
std::string o=d::conn::bash::exec("ls");
std::cout << o << std::endl;
return 0;
}
include/conn/bash/stdout.hpp
#ifndef __CONN_BASH_O__
#define __CONN_BASH_O__
#include<string>
namespace d { namespace conn { namespace bash {
std::string exec(const char*);
}}}
#endif
lib/conn/bash/stdout.cpp
#include"../../../include/conn/bash/stdout.hpp"
#include <cstdio>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
#include <array>
std::string d::conn::bash::exec(const char* cmd) {
std::array<char, 128> buffer;
std::string result;
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd, "r"), pclose);
if (!pipe) {
throw std::runtime_error("popen() failed!");
}
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
result += buffer.data();
}
return result;
}
// https://stackoverflow.com/a/478960/8460574
Compiled and tested with g++ ./lib/**/*.cpp src/main.cpp
I've tried to find documentation online, but it seems that most of
them are targeted at C programs instead of C++,
"Most of them" suggests that you are searching out tutorials. Documentation would be the Automake manual, which you would be well advised to read. It covers these topics and many more that you will want to know about as you continue with the Autotools, and with Automake in particular. At minimum, you should know how to find the manual so as to consult it at need. Tutorials and guides can be helpful, but they should be regarded as supplements to the manual, not primary sources.
which I'm not sure if
those steps are compatible.
They mostly are. The main thing to be aware of is that command-line options for the C compiler are specified via a CFLAGS primary (see below), whereas those for the C++ compiler are specified via a CXXFLAGS primary.
And I remember C++ libraries are compiled
into .so or .o file while most tutorials seems to be using .la files.
You seem to be confused. The formats associated with those extensions are not language-specific, and .o does not designate a library at all.
.o is the conventional extension for the object file arising from compiling a single source file. These can be linked into an executable, or they can be gathered together into a library, but they are not libraries themselves.
Conventional UNIX library extensions are .a for static libraries and .so for shared libraries. This applies to any language that can be used to build general-purpose link libraries, including C, C++, Fortran, and a variety of others.
The .la extension is something else. It designates a libtool library. Libtool is another of the autotools, focused on abstracting system-specific details of building and using libraries. This is again language independent. Building a libtool library will cause either a corresponding static library, a corresponding shared library, or both to be built and installed, depending the options specified in the Autotooling and / or on the configure command line.
You should use libtool if you are building shared libraries with the Autotools. You may also use it if you are building only static libraries (.a), but it is a bit simpler in that case to leave libtool out of the picture.
As for the specific question posed, you write:
And for the endpoints' directory (under lib/) I have something like
following
main_SOURCES = stdout.cpp
But it gave me error that no program named main,
Always present the actual text of the error message (as text), rather than a paraphrase. If you have to ask a question about it here, then there is a significant risk that your understanding of the message is incomplete or wrong, and therefore that your paraphrase is misleading.
In this case, I am relatively confident that Automake's complaint was that there is no target named "main". The line you've given specifies a source list for such a target, but Automake does not find that target defined in that Makefile.am file. The difference between "program" and "target" is a bit subtle, but significant.
Supposing that you are trying to build a convenience library -- that is, one that groups functions for compile-time use in building other targets, but is not intended to be installed as a standalone library* -- you could get it with something like:
noinst_LIBRARIES = libendpoints.a
That consists of thee main pieces:
LIBRARIES is the "primary", specifying what kind of definition is being given. In this case, it is the definition of a list of static library targets included in the project.
libendpoints.a specifies the name of a (static library) target. This is an external name: the build will generate a file by this name in the build tree. Do make a habit of using standard naming conventions for this, such as I demonstrate.
noinst specifies where the built target will be installed by make install. This particular value is a special one indicating that the target will not be installed at all. If you wanted it installed in the configured libdir then you would instead say lib.
The properties of that target must be given by other definitions, based on a munged form of its name. For instance, its source list might look like this:
libendpoints_a_SOURCES = stdout.cpp
That again consists of three pieces:
SOURCES is again the primary. In this case, it says that the definition provides a source list for some target.
libendpoints_a identifies the target whose source list is being given. It is a munged form of the target name, with characters that cannot appear in variable names replaced by '_' characters.
stdout.cpp is the (single-element) source list.
To use that, the main program's properties would also need to specify that the library should be linked. That would mean something along these lines in the Makefile.am in which the main program target is defined:
main_LDADD = lib/endpoints/libendpoints.a
That is again a three-part definition, whose interpretation I leave as an exercise.
*And if you wanted a static library that does get installed to the system then you would swap out the "noinst" for a prefix that identifies the installation location, such as "lib". And there is a slightly different form for libtool-mediated libraries, including shared libaries.
If you're just defining a convenience target for you library, you should be able to do so by declaring it as noinst_LIBRARIES = libmine.a and then declaring it as a stdout_LIBADD.
But most likely, if you don't want this as an installed library, you just want to list the sources directly in a single, non-recursive Makefile.am file, see https://autotools.io/automake/nonrecursive.html
If you do want your library to be installable, then you want to use libtool: https://autotools.io/libtool/index.html

How to check each header file includes required include files?

I'm developing my application using C++ and cmake.
I'd like to check each C++ header file includes required include files correctly.
Here is an example:
a.hpp
inline void func_a() {
}
b.hpp
// #include "a.hpp" is missing
inline void func_b() {
func_a();
}
main.cpp
#include "a.hpp"
#include "b.hpp"
int main() {}
Demo: https://wandbox.org/permlink/kZqoNHMYARIB3bc1
b.hpp should include a.hpp. Let's say b.hpp missing include a.hpp. If main.cpp include a.hpp before b.hpp, no compile error is occurred. If include order is opposite, compile error is occurred.
I'd like to check this kind of problem.
I'm using fly-check on emacs. It checks this problem well. I'd like to some checking mechanism into my cmake build system.
For example, if I execute make depcheck, then compile error is detected.
I think that if I setup a cmake target that compiles all header files individually but not link, the expected compile error would be reported.
I couldn't find how to setup that, so far.
Is there any way to do that? Or other ways to achieve the goal ?
my header file inclusion policy
Each header file should include header files that contain required element. In other words, each header file should compile individually.
What I want to achieve
I want to know the way to automatically detect b.hpp is missing `#include "a.hpp" by tool assist. The tool means not editor. I guess that cmake could do that. I'm trying to find the way.
Conventional wisdom is to add source files to every header. Even if b.cpp includes only this line:
include "b.hpp" // Note, this should be the first include
That way, you can compile every cpp file in isolation, and a successful compilation means the corresponding header is self-contained.
Of course, if you have an implementation file already, then moving the corresponding header to be included first goes towards ensuring that.
#StoryTeller 's answer
Conventional wisdom is to add source files to every header.
is appropriate way to achieve the goal. It requires adding many source files. It is annoying work especially I develop a header only library.
How to automate that process?
I found a way to check missing include file on cmake. The strategy is compile each header files individually and directly.
Here is CMakeLists.txt
cmake_minimum_required(VERSION 3.8.2)
project(test_checker)
add_custom_target(chkdeps)
file(GLOB HDR_ROOT "*.hpp")
FOREACH (HDR ${HDR_ROOT})
message(STATUS "${HDR}")
get_filename_component(HDR_WE ${HDR} NAME_WE)
SET(CHK_TARGET "${HDR_WE}.chk")
add_custom_target(
${CHK_TARGET}
COMMAND ${CMAKE_CXX_COMPILER} -c ${HDR}
VERBATIM
)
add_dependencies(chkdeps ${CHK_TARGET})
ENDFOREACH ()
To check missing include files, execute make chkdeps.
In order to do only compile, I use add_custom_target. The custom target name is chkdeps (check dependencies). This is the target for all header files dependency checking.
I get the list of *.hpp using file(GLOB HDR_ROOT "*.hpp"). For each got files, I add custom target for only compile using add_custom_target.
I add the extension .chk to avoid conflict. For example if the file name is a.hpp then the target name is a.chk.
I execute the COMMAND ${CMAKE_CXX_COMPILER} with -c option. The -c option is for only compile. I only tested the cmake on Linux. I know setting compile option directly is not good for cross platform development. cmake might provides compile only cross platform mechanism. But I couldn't find it, so far.
Then I add dependency to chkdeps using add_dependencies. Due to this dependency, when I execute make chkdeps, all custom targets (a.chk and b.chk) run.
When I run make chkdeps, then I got the expected error "'func_a' was not declared in this scope" as follows.
make chkdeps
Built target a.chk
/home/kondo/work/tmp/fly_check/b.hpp: In function 'void func_b()':
/home/kondo/work/tmp/fly_check/b.hpp:3:5: error: 'func_a' was not declared in this scope; did you mean 'func_b'?
3 | func_a();
| ^~~~~~
| func_b
make[3]: *** [CMakeFiles/b.chk.dir/build.make:57: CMakeFiles/b.chk] Error 1
make[2]: *** [CMakeFiles/Makefile2:78: CMakeFiles/b.chk.dir/all] Error 2
make[1]: *** [CMakeFiles/Makefile2:113: CMakeFiles/chkdeps.dir/rule] Error 2
make: *** [Makefile:131: chkdeps] Error 2

CMake/make apply -D flags on header files

I'm (cross-)compiling a shared C library with support for many different platforms which is handled by an hierarchy of CMakeLists files. In those files, several platform specific compiler flags are conditionally produced (with add_definitions()). I can successfully compile and link the source code leading to an appropriate .so file.
But to use the library in any project, I need to provide the right header files, too. The following install command of CMake selects the right header files to copy but does not apply the replacement of preprocessor defines/includes:
install(FILES ${headers} DESTINATION include/mylibrary)
So how can I generate/install the "post-compiled" header files?
What I thought of so far:
As add_definitions() should stack my -D's in the COMPILE_DEFINITIONS variable, maybe running a foreach loop on the copied raw headers and replace the define/include placeholders?
Using add_custom_command() to apply some logic before copying?
Edit: As pointed out by Tsyvarev, there is an answer quite near to my needs here, but unfortunately not quite it. In summary, the answer gives 2 options:
Include a special 'config' header in all of the library's headers and leverage the cmakedefine command to call configure_file() on this header. I can't use this approach because I don't want to alter the library headers.
Create a target-specific .cmake file which helps external projects in including the right headers together with all necessary -D defines. I can't use this approach either, because my external projects do not use cmake for building. Plus, I wish to create a library that is as easy to include as possible.
Any other thoughts?
Edit 2: I may have to elaborate on my statement, that the install command of CMake is not replacing defines. Take the following example:
//sampleheader.hpp
#ifndef SAMPLEHEADER_HPP_
#define SAMPLEHEADER_HPP_
#include OS_SPECIFIC_HEADER
//...
Now I have a CMakeLists.txt file that does something like this:
# ...
if (${OS} MATCHES "arm-emblinux")
add_definitions(-DOS_SPECIFIC_HEADER="emblinuxHeader.hpp")
elseif (${OS} MATCHES "linux")
add_definitions(-DOS_SPECIFIC_HEADER="linuxHeader.hpp")
endif()
# ...
Everything compiles fine, but when the install command above gets called, I have a header file in my ../include/ directory still with OS_SPECIFIC_HEADER placeholder in it. And of course, this cannot be properly included in any development project.

Header file not found only in specific translation unit

I'm currently stuck on a compilation problem on Android for my app.
I get the following error during the compilation of my native library with ndk-build:
BackgroundDisplayConfiguration.h:12:23: fatal error: glm/glm.hpp:
No such file or directory
#include <glm/glm.hpp>
^
What puzzles me is that I have specified a path for this header only library in my Android.mk the following way:
LOCAL_CPPFLAGS += -I../../glm/include
and this path exists and is correct, but moreover if I mess up this path I get the same error in other files that include glm.hpp. When the path is correct, only this file yields an error, and I don't understand why. Any pointers?
EDIT: Okay, this is even more puzzling. The include option appear in every compiler command for each file, but not on the compiler command for the big wrapper generated by swig (that outputs my library_native_wrap.o), and that's where it yields an error... Well, it at least explains the observed behavior.
So I found a workaround for this, even though it doesn't feel quite right.
Indeed, I found out that when compiling every source of my library, the compiler command actually had the include option, but then, when compiling the output of swig (that big unique c++ wrapper file), the option wasn't there anymore.
I found a way to correct this by adding my include path to the LOCAL_EXPORT_C_INCLUDES.
For some reason, the LOCAL_CPPFLAGS aren't used when compiling the wrapper...

Cmake CHECK_INCLUDE_FILES not finding header file

I'm trying to have Cmake check if the file cxxabi.h is available. This file is from the c++ standard library, at least with g++. My current cmake commands look like this:
include(CheckIncludeFiles)
...
check_include_files(cxxabi.h HAVE_CXXABI)
if(HAVE_CXXABI)
...
else(HAVE_CXXABI)
...
endif(HAVE_CXXABI)
When this is executed, I get:
-- Looking for include files HAVE_CXXABI
-- Looking for include files HAVE_CXXABI - not found.
Although the file is available in /usr/include/c++/4.6.4/ and can properly be found by g++ when I compile a c++ code.
I suspect the macro check_include_files uses the C compiler instead of the C++ one to compile a small program that includes the required file, which of course fails since cxxabi.h is a C++ file.
Any idea how to solve that? (i.e. making the macro use the C++ compiler instead of the C one)
As edited in my original question:
Problem solved. There is a different macro for C++ headers, check_include_file_cxx, located in CheckIncludeFileCXX.
There exists another problem with CHECK_INCLUDE_FILES that I recently discovered with MinGW. The file tested was "ddk/ntapi.h". In the CMakeErr.log for this header I got a multiply messages like "DWORD - does not name a type" and so on for all MS types used in this header. Because of this reason the compilation fails and a requested header appears as "not found", whereas it is not true.
This happens because CheckIncludeFile.cxx contains only the requested header, and some headers in MinGW (and probably in the other APIs) does not include in its body all the list of required headers to be compiled in a standalone program that CMake creates.
The solution for this problem is to add absent basic includes into the CMAKE_REQURED_FLAGS, or as a third variable of CHECK_INCLUDE_FILE_CXX:
CHECK_INCLUDE_FILE_CXX("ddk/ntapi.h" VAR "-include windows.h")