gcc and clang under msys2 cannot resolve includes with absolute paths - c++

I try to get tests generated by the cxxtest framework working under a MinGW environment managed by mysys2. The tool generates C++ files with absolute paths. However, gcc seems to be unable to resolve this absolute paths.
Here is a minimal example to demonstrate the problem:
// file1.h
#include <iostream>
inline void hallo() { std::cout << "Hallo\n"; }
// main.cpp
#include "/home/phil/example/file1.h"
int main()
{
hallo();
return 0;
}
The file exists (at least the msys2 shell resolves the path):
$ ls /home/phil/example/file1.h
/home/phil/example/file1.h
... but calling g++ results in this error:
$ g++ main.cpp
main.cpp:1:38: fatal error: /home/phil/example/file1.h: No such file or directory
#include "/home/phil/example/file1.h"
^
compilation terminated.
Same error with clang.
Under a full Linux environment, the example works. It also works if I replace the absolute path by a relative one (#include "file1.h").
So, I assume the problem lies in the layer over Windows that is responsible to resolve paths. Not sure whether I should report it as a bug to the msys2 project, or whether it is a known problem. If it is a known problem, are there any workarounds (like setting -I options)?
(If possible, I would like to avoid replace the absolute paths, as they are in generated code by the cxxtest framework. Technically, running a postprocessing step on the generated files would be possible but seems like a hack in the long run.)

Since you are running compilers that use MinGW-w64 as their runtime environment, they don't recognize POSIX-style paths like that. I think they actually interpret the root directory "/" to be "C:\". Other than that, they would only recognize native Windows-style paths.
I recommend that you pass the argument -I/home/phil/example to your compiler from some program running in the msys-2.0.dll POSIX emulation runtime environment (e.g. /usr/bin/bash or /usr/bin/make). The msys-2.0.dll runtime will then convert that argument to use a native Windows path so the compiler can understand it, and statements like #include <file1.h> will work. Alternatively, you might try putting a Windows-style path in your source code, e.g. the path should start with C:\.
Note however that having absolute paths in source code or build scripts is a bad idea since it makes it harder to build the code on a different computer. You could consider using environment variables or relative paths.

Try using the MinGW compiler that Cygwin provides as a package. (In other words, forget the MSYS environment; work under Cygwin, but build the code as before, in the MinGW style.)
Then you should be able to have include references /home/phil; it will just resolve to C:\Cygwin\home\phil or wherever your Cygwin root is.
Actually, it might be possible under MSYS also (which, after all, is just the descendant of an old for of Cygwin). You just have to figure out what /home/phil is referring to, create that tree and work under there.

Related

Undefined Reference to `pcap_init' - Libpcap

I'm currently trying to set up a simple packet sniffer with libpcap and facing a lot of confusion over this linker error.
I cloned the most recent version from github (1.11.0-PRE-GIT) and successfully did the configure, make and make install steps outlined in the installation instructions.
My script is as follows:
#include <iostream>
#include <pcap/pcap.h>
#include <string>
#include <cstdlib>
using namespace std;
int main(int argc, char *argv[])
{
//Set up error buffer
char errbuf[PCAP_ERRBUF_SIZE];
// Check Libpcap version number
cout << pcap_lib_version() << endl << endl;
//Initialize the library for local charactr encoding
pcap_init(PCAP_CHAR_ENC_LOCAL, errbuf);
return 0;
}
But when I try to compile with the command below I get the error:
g++ csniff.cc -o csniff -lpcap
/usr/bin/ld: /tmp/ccAPLFoh.o: in function `main':
csniff.cc:(.text+0x79): undefined reference to `pcap_init'
collect2: error: ld returned 1 exit status
I've also checked the pcap.h files present in both usr/include and usr/local/include and they both contain a prototype for the pcap_init function that looks like this:
#define PCAP_CHAR_ENC_LOCAL 0x00000000U /* strings are in the local
character encoding */
#define PCAP_CHAR_ENC_UTF_8 0x00000001U /* strings are in UTF-8 */
PCAP_AVAILABLE_1_10
PCAP_API int pcap_init(unsigned int, char *);
One thing I have noticed though is that when I comment out the line with pcap_init and use the script to print the version number I get
libpcap version 1.9.1 (with TPACKET_V3)
Any pointers would be much appreciated!
Edit: runnning Ubuntu 20.04.3 LTS
Your operating system already comes with libpcap - version 1.9.1. Most Linux distributions do, as do the *BSDs, macOS, and some commercial UN*Xes.
You compiled and installed a newer version of libpcap, so you had two versions of the library file - the 1.9.1 that comes with the system, in the system library directory, because it comes with the OS, and the 1.11.0-PRE-GIT and you compiled and installed, probably in /usr/local/lib.
You also had one version of the libpcap header files - the 1.11.0-PRE-GIT version - in /usr/local/include/pcap, because you installed it. You did not have the 1.9.1 version of the header files, because, like many Linux distributions, a separate "development" package has to be installed in order to get the header files.
When you compiled your program, you didn't tell it where to look for header files or libraries. It found the header files in /usr/local/include/pcap - i.e., the 1.11.0-PRE-GIT header files - and found the library in the system library directory - i.e., the 1.9.1 library.
This causes problems, because the header files included a declaration of pcap_init(), so the compiler didn't print a warning about pcap_init() not being declared, but the library file doesn't include the pcap_init() function, so the linker printed an error about pcap_init() not being found in libpcap.
Removing the call to pcap_init() meant that the linker didn't try to find pcap_init(), and thus didn't fail.
If you hadn't built and installed libpcap 1.11.0-PRE-GIT, and you had installed the libpcap-dev package, your system would have the headers and library for 1.9.1, and compiling your program - without the call to pcap_init() - would find the headers for 1.9.1, so it can compile, and the library for 1.9.1, so it will link.
If, however, you want to build with 1.11.0-PRE-GIT, then you will need to tell the compiler where to find the libraries; you might also have to tell it where to find the headers.
If you don't have the libpcap-dev package installed, then you don't need to tell it where to find the headers, as it will find the 1.11.0-PRE-GIT ones you installed; however, if the libpcap-dev package is installed, you may have to add the flag -I /usr/local/include to the compiler command, to make sure it finds the headers in /usr/local/include rather than the system include directory.
To make sure it finds the 1.11.0-PRE-GIT version of the libraries, you will have to add the flag -L /usr/local/lib to the compiler command as well - or set LD_LIBRARY_PATH so that the linker finds the 1.11.0-PRE-GIT version.
If you build with 1.11.0-PRE-GIT, you can use pcap_init(). You don't need to use pcap_init() unless you want to run the program on some UN*X and on Windows and you want all strings to be in UTF-8 (on Windows, strings would, by default, be treated as being in the "local code page"). To quote the DESCRIPTION section of the pcap_init() man page:
pcap_init() is used to initialize the Packet Capture library. opts
specifies options for the library; currently, the options are:
PCAP_CHAR_ENC_LOCAL
Treat all strings supplied as arguments, and return all strings
to the caller, as being in the local character encoding.
PCAP_CHAR_ENC_UTF_8
Treat all strings supplied as arguments, and return all strings
to the caller, as being in UTF‐8.
On UNIX‐like systems, the local character encoding is assumed to be
UTF‐8, so no character encoding transformations are done.
On Windows, the local character encoding is the local ANSI code page.
If pcap_init() is not called, strings are treated as being in the local
ANSI code page on Windows, pcap_lookupdev(3PCAP) will succeed if there
is a device on which to capture, and pcap_create(3PCAP) makes an
attempt to check whether the string passed as an argument is a UTF‐16LE
string ‐ note that this attempt is unsafe, as it may run past the end
of the string ‐ to handle pcap_lookupdev() returning a UTF‐16LE string.
Programs that don’t call pcap_init() should, on Windows, call
pcap_wsockinit() to initialize Winsock; this is not necessary if
pcap_init() is called, as pcap_init() will initialize Winsock itself on
Windows.

Compiled C executable is detected as a virus by windows defender

I had compiled a simple hello world program in C with the MinGW compiler using the command line. As it had finished compiling, windows defender popped up and detected a virus (Trojan:Win32/Fuery.C!cl).
#include <stdio.h>
#include <stdlib.h>
int main() {
printf("Hello World");
return 0;
}
https://imgur.com/a/05yDjw5
I had taken action on this (Removed) as windows defender suggested, but when I compile again the same happened, multiple times.
I had downloaded an AntiVirus (Malwarebytes) and scanned my whole system and it detected some registry key errors, but not this.
I've tried compiling C++ files too, but windows defender did not detect any virus there. This only happens when I compile in C.
I've also tried checking the compiled executable at VirusTotal.
https://www.virustotal.com/gui/file/476d47215dad80db49c9fd508ab5e10e5aeb5b623248ca156830a28b70affe5f/detection
I tried CodeBlock's MinGW compiler and 0 engines detected it. (Same C file)
https://www.virustotal.com/gui/file/8ba4b0fa24b1b6b69152acce2353fcca8447bbecbfc4e5ec48d33cc75d94f2f1/detection
EDIT: I deleted the path variable of C:/MinGW and added CodeBlock's MinGW compiler. I then used the command line to compile the same C file again and had uploaded the .exe file to VirusTotal. This time, 0 engines detected. So I have come to the conclusion that, the MinGW compiler that I had installed was creating this problem.
https://www.virustotal.com/gui/file/34d383f6c09f897d8c9a44ed0e7850574320e50fdf439eeb1f06705fdcc95386/detection
I don't know why this happens. Is there a malware in my computer that affects my C programs or is this a false detection?
There is no malware, it is a false positive. The executable generated by your version of MinGW looks very similar to a particular virus.
To avoid the problem, add the directory where you build your code to the list of exclusion in the antivirus.
Also consider using mingw-w64 instead of mingw.org .
I came across with the same problem, compiler tdm gcc v9.2.
The following compilation triggers a warning (kaspersky).
gcc temp.c -o temp.exe
The following does not
gcc -O3 temp.c -o temp.exe
Where temp.c is
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
int main() {
int a, b;
scanf("%d %d", &a, &b);
printf("mod %4d, %4d is %4d\n", a, b, a%b);
return 0;
}
The same code with g++ passes the test with both compilations. The antivirus software does not detect the same virus elsewhere but only in temp.exe (first compilation).
I may have solved my problem.
This is what I did: I removed the PATH Variable of C:\MinGW and added CodeBlock's MinGW compiler (CodeBlocks/MinGW/bin). I used the command line to compile the same C file, and had uploaded the .exe to VirusTotal. No engines detected this file!
https://www.virustotal.com/gui/file/34d383f6c09f897d8c9a44ed0e7850574320e50fdf439eeb1f06705fdcc95386/detection
So I have come to a conclusion that, MinGW was the compiler that was causing this problem. I have removed it.
However, I am not quite sure if this problem is FULLY solved. There is still a possibility of malware affecting my executable (or perhaps not). I cannot be sure.
If anyone has any answers, please comment or answer
I ran into this after installing MinGW on 01-08-20(dd-mm-yy).
For me it was also Windows Defender, the way to - hopefully temporarily- get rid of this is to add an exception for the folder your compilation output will reside in.
The Microsoft website states these steps to add an exclusion:
Go to Start > Settings > Update & Security > Windows Security > Virus & threat protection.
Under Virus & threat protection settings, select Manage settings, and then under Exclusions, select Add or remove exclusions
I had a similar problem. I figured out that the following dll was missing: mingw32-libmingwex-dll. Once I installed it via "MinGW Installation Package", I didn't have the problem anymore.
I hope this can help others.
Since you wrote that program and you know it isn't actually a Trojan, it's obviously a false positive. You should submit the file to them at https://www.microsoft.com/wdsi/filesubmission so they can figure out why it's triggering the false positive and fix it. (If it happens with everything you compile, just sending them one will suffice.) In the meantime, you should add an exclusion to Windows Defender for the folder that you compile your executables in.

Compilation error: "stddef.h: No such file or directory"

Whenever I try to compile this code it always ends up with this error:
In file included from /usr/include/wchar.h:6:0,
from /usr/lib/gcc/i686-pc-cygwin/4.9.2/include/c++/cwchar:44,
from /usr/lib/gcc/i686-pc-cygwin/4.9.2/include/c++/bits/postypes.h:40,
from /usr/lib/gcc/i686-pc-cygwin/4.9.2/include/c++/iosfwd:40,
from /usr/lib/gcc/i686-pc-cygwin/4.9.2/include/c++/ios:38,
from /usr/lib/gcc/i686-pc-cygwin/4.9.2/include/c++/ostream:38,
from /usr/lib/gcc/i686-pc-cygwin/4.9.2/include/c++/iostream:39,
from test.cpp:1:
/usr/include/sys/reent.h:14:20: fatal error: stddef.h: No such file or directory
#include <stddef.h>
^
compilation terminated.
The code I was trying to compile is:
#include <iostream>
using namespace std;
int main()
{
cout << "Hello World! :D";
return 0;
}
The error is because your gcc-core package and gcc-g++ are not of the same version. Either downgrade one of them to solve the problem or update both the libraries. Updating both the libraries is the recommended way.
I had this error on a fresh MinGW install, it had nothing to do with the installed packages mentioned in the current accepted answer by "Prasanth Karri". In my case the issue was caused by -nostdinc in my Makefile. I actually only needed that compiler flag when building for a different target platform (not when using MinGW) so I fixed the issue by removing that flag from MinGW builds.
When I was incorporating a software library written in C into an existing demo project(used a C++ mbed library) I encountered this problem. The demo project would compile just fine, but after I replaced the existing main file by my own, this error occurred.
At this point I hadn't yet thought about the fact that the mbed library that I needed was written in C++. My own main file was a .c file that #include the mbed header file. As a result I used my normal C source as if it was a C++ source. Therefore the compiler that was used to compile my main file was the C compiler.
This C compiler then encountered a #include of a module that actually does not exist (within its scope), as it's not a C++ compiler.
Only after I inspected the output of the build log I realised the various source C and C++ files were compiled by more that 1 compiler(the c++ compiler). The project used used compilers arm-none-eabi-c++ and arm-none-eabi-gcc (for embedded systems) as seen below.
Compile log:
Building file: ../anyfile.cpp
Invoking: MCU C++ Compiler
arm-none-eabi-c++ <A lot of arguments> "../anyfile.cpp"
Finished building: ../anyfile.cpp
Building file: ../main.c
Invoking: MCU C Compiler
arm-none-eabi-gcc <A lot of arguments> "../main.c"
In file included from <Project directory>\mbed/mbed.h:21:0,
from ../main.c:16:
<Project directory>\mbed/platform.h:25:19: fatal error: cstddef: No such file or directory
compilation terminated.
Of course in a C++ environment cstddef exists, but in a C environment cstddef doesn't exist, in stead it's just C's implementation of stddef.
In other words, cstddef does not exist in the C compiler.
I resolved this problem by renaming my main.c file to main.cpp and the rest of the code compiled smoothly too.
TLDR/Conclusion: When building a C++ project, avoid mixing C files with C++ files(sources and headers). If possible rename .c files to .cpp files to use the C++ compiler in stead of the C compiler where required.
In order to update it, follow below.
If you are on Windows, just run these on command prompt or powershell
Update the package list: mingw-get update
After updating the package list, run: mingw-get upgrade
Source: How to update GCC in MinGW on Windows?
This problem was solved for me as I installed codeblocks with mingw compiler then I copied the mingw folder from codeblocks to C drive and added
C\mingw\bin to the environment variables.
If you try to compile and see a message like, "fatal error: stddef.h: No such file or directory", the error is because your gcc-core and gcc-g++ packages are not of the same version. Rerun the Cygwin install and make sure that you select the highest numbered versions of gcc-core and gcc-g++.
After installing the C++ compiler with MinGW I encountered this problem as well. Apparently, you have to also install mingw32-base. Go to C:/MinGW/bin/mingw-get.exe (my path) and check it for installation at the Basic Setup tab.

How to use standard library with Clang and LibTooling

I want to use Clang and LibTooling to create some C++ source analysis and transformation tools. I've built Clang and LibTooling following this tutorial, and I've been able to run and create some analysis tools and compile C++ programs using the Clang binary I built. However, if I include headers from the standard library (in either source files or my tools), I run into issues when compiling or running the source files/tools. For instance, if I run clang-check on the following C++ source file:
#include <iostream>
int main() {
std::cout << "Hello";
return 0;
}
I get "fatal error: 'iostream' file not found". (Note: I can compile C++ programs, e.g. ones with user-defined classes, just not C++ programs using the standard library.) In an attempt to resolve the issue, I built libc++ (following this guide, building it in the llvm/project directory where I built LLVM and Clang), but I'm still having trouble getting Clang and the tools to use libc++. Now, if I try to compile a test file using:
export CPLUS_INCLUDE_PATH="~/clang-llvm/llvm/projects/libcxx/include"
export LD_LIBRARY_PATH="~/clang-llvm/llvm/projects/libcxx/lib"
~/clang-llvm/llvm/build/bin/clang++ ~/Documents/main.cpp
Then I get "fatal error: 'unistd.h' file not found". So my question is this: how do I properly point Clang and my tools to use libc++?
I am running OS X Yosemite 10.10 and using Clang 3.6.0.
Clang comes with some custom includes. So usually you have clang in
/usr/bin/clang++
and the includes in
/usr/lib/clang/3.6.1/include
but clang looks for them as a relative path:
../lib/clang/3.6.1/include
so make sure this relative path is accessible from either the clang++ binary, or your libtooling application.
Include your tool into this:
#include "clang/Tooling/CommonOptionsParser.h" // For reading compiler switches from the command line
#include "clang/Tooling/Tooling.h"
static cl::OptionCategory MyToolCategory("SearchGlobalSymbols");
static cl::extrahelp MoreHelp("\nMore help text..."); // Text that will be appended to the help text. You can leave out this line.
/* Your code (definition of your custom RecursiveASTVisitor and ASTConsumer) */
/* Define class MyASTFrontendAction here, derived from ASTFrontendAction */
int main(int argc, const char **argv)
{
/* Your code */
CommonOptionsParser op(argc, argv, MyToolCategory); // Parse the command-line arguments
ClangTool Tool(op.getCompilations(), op.getSourcePathList()); // Create a new Clang Tool instance (a LibTooling environment)
return Tool.run(newFrontendActionFactory<MyASTFrontendAction>().get()); // Run custom Frontendaction
}
The CommonOptionsParser allows you to read commands from the command line that are passed to the compiler.
For example, you can now call your tool like this:
your-tool yoursourcefile.c -- -nostdinc -I"path/to/your/standardlibrary"
Everything after the double dash will be passed to the compiler. Possible flags are described here:
http://clang.llvm.org/docs/CommandGuide/clang.html
-nostdinc tells the Preprocessor not to look for standard include paths. You can specify you own paths instead after -I.
Hope it helped someone :) Ask me if I wasn't specific enough.
Did you move/rename any of the parent directories after building/installing? The compiler should have been configured to know where to look for its standard libraries without having to specify the environment variable paths.
Use homebrew and install llvm using the command
brew install llvm
Your problem should be solved.

Strange error when adding #include <string>

I have the following very simple application that compiles and runs fine:
EDIT: changed the example to be simpilar to end confusion of the real issue
int main() {
return 0;
}
As soon as I add #include <string> (and not even reference std::string), it fails to compile and I get the following error:
/usr/include/c++/4.1.2/bits/allocator.h:82 error: expected template-name before '<' token
Along with about 456 other, similar errors.
Any ideas? Thanks!
UPDATE:
Line 82 of /usr/include/c++/4.1.2/bits/allocator.h references the template __glibcxx_base_allocator at the location of the error. That template is defined in bits/c++allocator.h. When I search the system for that file, I get 3 hits, but none of them are in /usr/include/c++/4.1.2/bits/ as one would expect.
I have version 3.1.6, 4.1.1, and 4.3.2, but not 4.1.2 as the rest of the includes I am using. I am not sure which one is being used (if any, however, I don't get any error for an unknown file), but it seems the problem may stem from this.
The problem appears to be the installed development packages are not correct or incomplete (not to be confused with corrupt). Forcing g++ to use different include versions corrects that:
g++ -nostdic++ hello.cc -o hello -I/usr/include/c++/3.4.6
All the alternative directories (4.1.1, 4.1.2 and 4.3.2) are incomplete causing inappropriate files to be included causing the unusually errors. For example:
/usr/include/c++/4.1.2/bits/allocator.h requires __glibcxx_base_allocator located in bits/c++allocator.h which is being included from either /usr/include/c++/4.1.1 or /usr/include/c++/4.3.2 and appear to be incompatible. Forcing the compiler to use the only complete set of includes rectifies this.
Almost certainly g++ is detecting .cc as a C source file, not C++ and passes it through to gcc instead of compiling as C++. You can easily test by renaming your file to hello.C. There's also a language parameter to g++ you can use.
EDIT: This seems to work fine in g++ 4.2 with a .cc extension so that might not be it. Do you have any other headers included you aren't showing us? They could be interfering with <string>.
EDIT2: Alternatively your headers might not be set up right. Does this work:
#include <string>
int main()
{
return 0;
}
Errors like this have been heard of to occur when the C++ standard library headers are corrupted/not fully installed – maybe there is even a message referring to a missing include among your 456 other errors.
In any case, make sure that libstdc++-devel, resp. the package containing the C++ standard library header files of your distribution, is properly installed.
Check your include path. The paths can be specified as environment variables or specified on the command line. You could be using an include file from a different compiler or different version of the same compiler.
Also, try using <cstdio> rather than <stdio.h>.
Another suggestion: change <> to "".
This could be error caused at preprocess stage. Just preprocess your cpp file by passing flag -E to gcc and Look at the place the compiler complains.