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")
Related
Introduction
I am trying to use Toulbar2 as a C++ library in my CMake project, however I am having much trouble linking it to my main executable.
I found many similar questions on this topic, both here and on other similar website, but none of them helped me with my specific issue. I tried literally everything and I did not menage to make it work, I was hoping that some of you may help me with that.
I am running Ubuntu 18.04, CMake version 3.23 and in my project I am using the standard C++11. I am a proficient programmer, but I am just an beginner/intermediate user of both C++ and CMake.
What I've already tried to do
I cannot list all my attempts, so I will only mention those I think are my best ones, to give you an idea of what I may be doing wrong.
1) In my first attempt, I tried to use the same approach I used for any non-standard library I imported, i.e. using find_package() in CMakeLists.txt to then link the found LIBRARIES and include the found INCLUDE_DIRS. However, I soon realised that Toulbar2 provides neither a Find<package>.cmake or <name>Config.cmake file. So, this approach could not work.
2) My second attempt is the one that in my opinion brought me the closest to the solution I hoped for. You can easily compile Toulbar2 as a dynamic library using the command: cmake -DLIBTB2=ON .. in an hypothetical build directory you previously created. After compiling with make you have your .so file in build/lib/Linux. After installation, you can make CMake find this library by itself using the command find_library. So, my CMakeLists.txt ended up looking like this:
[...]
find_library(TB2_LIBRARIES tb2)
if(TB2_LIBRARIES)
set(all_depends ${all_depends} ${TB2_LIBRARIES})
else(TB2_LIBRARIES)
add_compile_definitions("-DNO_TB2")
message("Compiling without Toulbar2, if you want to use it, please install it first")
endif(TB2_LIBRARIES)
[...]
target_link_libraries(main ${all_depends})
[...]
This code works to some extent, meaning that CMake correctly finds the library and runs the linking command, however if I try to #include <toulbar2lib.hpp> the header is not found. So I figured out I should have told CMake where to find that header, so I ended up adding a
include_directories(/path/to/header/file's/directory)
However, I still have another problem. The header is found, but a lot of names used in the header are not found at compilation time. The reason is that in Toulbar2 some variables/types are defined conditionally by using preprocessing directives like #ifdef or #ifndef, and in turn the global variables used in these conditions are defined through CMake at compilation time. If you are interested in an example, I can mention the Cost type that is used in the mentioned header file. I see that there's a piece missing in the puzzle here, but I cannot figure out which one. Since I pre-compiled the library those definitions should exist when I include the header file, because I am correctly linking the correspondent library that contains those definitions.
3) My third attempt is less elegant than the the other two I mentioned, but I was desperately trying to find a solution. So, I copied the whole toulbar2 cloned folder inside my project and I tried to add it as a subdirectory, meaning that my main CMakeLists.txt contains the line:
add_subdirectory(toulbar2)
It provides a CMakeLists.txt too, there should be no problem in doing it. Then I include the src directory of toulbar2, that contains the header file I need, and I should be okay. Right? Wrong. I got the same problem that I had before with (2), i.e. some variables/types conditionally defined were not actually defined when I tried to compile my project, even though the subproject toulbar2 was correctly (no errors) compiled.
I just wanted to mention that any answer is welcome, however if you could help me figure out an elegant solution (see 1 or 2) for this problem it would be way better, as this code is intended to be published soon or later. Thank you in advance for your help.
Solution 2) looks fine. You just need to add the following compilation flags -DNDEBUG -DBOOST -DLONGDOUBLE_PROB -DLONGLONG_COST when compiling your project with toulbar2lib.hpp. See github/toulbar2 README.md how to compile without cmake for those flags (except WCSPFORMATONLY that should not by used in this context).
I'm learning C now using vscode. I got curious and tried modifying the headerfiles. stdio.h to be specific and I found some really peculiar behavior. I studied the behavior using the simple Helloworld program.
infos: Windows 10 OS, VScode v1.56.0, Compiled using CL not gcc, ucrt file path:
C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\ucrt
The code:
#include<stdio.h>
int main()
{
printf("Hello world!");
}
So first I tried adding some random lines in the header file and save it. The code ran fine without any errors. I tried it after restarting. It still worked fine.
Then I commented the whole file with 2k+ and saved it and was expecting for the compiler to tell me that printf is not declared anywhere. But still again the code worked fine.
Then I reverted all changes, copied the header file to another folder and deleted the file in the ucrt folder
So. Now for the first time compiler said printf isn't declared anywhere.
I modified the headerfile outside and copied it to the urct folder and the code worked fine again.
So, as I checked into the file (in ucrt) the changes I made isn't showing here.
So I again deleted the headerfile in ucrt folder, cleared everyline added 2 3 random lines there saved it. And then pasted it in the ucrt to see that code still works really fine. And as I checked the header file.......It is the same old stdio.h that was when I installed it.
And Finally....when I copied the header file in ucrt and pasted it outside. And to my surprise It had the lines I added in No.5
There is only one explanation that I can think of...That VScode overrides any changes in the file.
So here are my questions:
How headerfiles are processed in vscode.
Can we actually modify it(The one in ucrt folder)
What is actually happening in the steps I mentioned above. Why these weird outcomes.
What is the difference between compiling with CL and with GCC.
NOTE: I know it's too lengthy I just wanted to give as much information I have.
VSCode itself doesn't do much with header files, the code explorer, intellisense and linter might have include paths but it is not responsible in any way for code-gen.
You can modify your system stdlib but I really wouldn't recommend it - my recommendation is to compile with -ffreestanding (on GCC and Clang) and then have a copy of a stdlib in your project and include it from there manually (Using -I or by using relative includes).
The most likely culprit is that your compiler & vscode's code explorer are being passed a flag which is modifying their include path, so the stdlib they are accessing is the system one, and the strange file modification behaviour can be attributed to how you are accessing the file (i.e. if you are using Go To Declaration).
Each may have a different default include setup, GCC uses the GNU Toolchain where it can - but ultimately they both follow the same preprocessing rules and its just a question of looking at what is included by default.
One last thing is that sometimes compilers will be nice and if stdio.h or the like isn't included and its a common or stdlib function, they will provide the correct prototype automatically and link as normal without the header being included - its not the case for my GCC config at least, and I'm not sure about CL
So I have below code in my file mine.cpp,
#include <iostream>
#define max INT_MAX
The identifier "INT_MAX" will be undefined if I remove "#include <iostream>". So, I know it is defined somewhere in iostream.
When I go to the definition of INT_MAX it is in limits.h file. So, I guess limits.h is nested include in iostream.
Is there a way for me to view (like mine.cpp->iostream->...->limits.h) how limits.h is included in my mine.cpp without building.
I searched and found there are other similar questions but all answers related to them include "build with some option". I have to do this without building as my build takes quite some time to complete.
That's a strange requirement:
without building.
What exactly are you trying to avoid? Building the entire project/solution? To save time?
As noted by #dxiv and #Boris, you need to at least compile that file. More strictly - run a pre-processor on it to expand macros, conditional compilation, etc.
Compiling you file with /showIncludes and /P (preprocess to a file) technically doesn't "build", as the object file is not produced.
The generated output is hierarchical, so you get a complete path of inclusion.
You didn't mention the version and edition of your Studio; this post Generate graph of include files in Visual Studio Community 2019 states that Enterprise edition of 2019 (and possible 2017) has "Generate Graph Of Include Files" feature. However, the process that it is using likely involves compiling or preprocessing :)
Don't know that it is (reliably) possible to do it without at least compiling, since in the end it's the compiler that checks the include paths and dependencies.
However, compiling a single file with #include <iostream> should suffice, as opposed to building the entire project. For example, compiling the default "C++ console" .cpp generated by the wizard produces a debug\sample.tlog\CL.read.1.tlog file which contains the following towards the top.
<vs-path>\VC\TOOLS\MSVC\14.26.28801\INCLUDE\IOSTREAM ***
<vs-path>\VC\TOOLS\MSVC\14.26.28801\INCLUDE\YVALS_CORE.H
<vs-path>\VC\TOOLS\MSVC\14.26.28801\INCLUDE\VCRUNTIME.H
<vs-path>\VC\TOOLS\MSVC\14.26.28801\INCLUDE\SAL.H
<vs-path>\VC\TOOLS\MSVC\14.26.28801\INCLUDE\CONCURRENCYSAL.H
<vs-path>\VC\TOOLS\MSVC\14.26.28801\INCLUDE\VADEFS.H
<vs-path>\VC\TOOLS\MSVC\14.26.28801\INCLUDE\XKEYCHECK.H
<vs-path>\VC\TOOLS\MSVC\14.26.28801\INCLUDE\ISTREAM ***
<vs-path>\VC\TOOLS\MSVC\14.26.28801\INCLUDE\OSTREAM ***
<vs-path>\VC\TOOLS\MSVC\14.26.28801\INCLUDE\IOS
<vs-path>\VC\TOOLS\MSVC\14.26.28801\INCLUDE\XLOCNUM ***
<vs-path>\VC\TOOLS\MSVC\14.26.28801\INCLUDE\CLIMITS ***
<vs-path>\VC\TOOLS\MSVC\14.26.28801\INCLUDE\LIMITS.H <--
<vs-path>\VC\TOOLS\MSVC\14.26.28801\INCLUDE\CMATH
The above is a superset of the #include files that lead to limits.h. An inspection of the respective headers shows that the actual path is iostream - istream - ostream - xlocnum - climits - limits.h.
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...
I'm compiling a project in XCode where MySQL++ in included and linked to. For some reason, I keep getting the following compiler error:
'assert’ was not declared in this scope
originating from cpool.h, a header file that's part of MySQL++. Does anyone know why this is being triggered?
EDIT: For reference, MySQL++ was installed via Macports.
The most obvious answer would be that "assert.h" is not being included or is not being found in your include path. Another explanation is that the assert macro has been undefined at some point after the header was included.
Edit: Since you say that assert.h is included, and we'll assume for the moment that it's being found since it's a standard header, then that leaves us with the last possibility I stated above i.e. that the macro has been undefined.
Since cpool.h itself will not be doing this it must be the case that assert.h is included earlier either by yourself or indirectly by another 3rd party header and the undefining happening between this and your inclusion of cpool.h. This can easily be tested by moving your cpool.h include to the top of your file.
In c++ adding cassert header should fix your problem.
#include <cassert>
It could be that another library in your include path has a different "assert.h" file, and you are unknowingly including that one instead of the system's standard <assert.h>.
I ran into this issue when writing an application that uses gstreamer on Mac OSX. It turns out that gstreamer's include directory (/Library/Frameworks/GStreamer.framework/Headers) includes a file "assert.h", which is non-standard and an unsuitable replacement for the real assert.h. When I added -I/Library/Frameworks/GStreamer.frameworks/Headers to my compilation command, suddenly my sources, which just said "#include <assert.h>" where including the gstreamer version. This caused my compilation to fail with the same error you were getting.