How to compile this C++ code on Linux with relevant header files? - c++

I am trying to compile this C++ code in my Linux box using g++ but it fails with the following error:
enigma/Enigma# g++ -I . main.cpp -o main
In file included from machine.h:14:0,
from tests.h:13,
from main.cpp:10:
plug.h:13:2: warning: #import is a deprecated GCC extension [-Wdeprecated]
#import "util.h"
^~~~~~
/tmp/ccxyoEC2.o: In function `main':
main.cpp:(.text+0x10): undefined reference to `test_machine_encode_decode()'
collect2: error: ld returned 1 exit status
The error indicates that the compiler cannot find the tests.h file present in the same folder. How can I compile and run this code?
I now understand that I needed to link the object files together, I did so using:
g++ -c *.cpp
g++ *.o -o enig
It still does not work though, the resulting binary executes with ./enig but is broken and does not function as intended:
Entire encoded message: TZQA
Decoding now...
Entire decoded message: AHOJ
Entire encoded message: HBIU
Decoding now...
Entire decoded message: AHOJ
Entire encoded message: ZSNE
Decoding now...
Entire decoded message: AHOJ
Entire encoded message: ICRH
It just keeps encoding and decoding those random texts as opposed to the functionality mentioned on the git page I shared above.
Anything I'm missing?

The error indicates that the compiler cannot find the tests.h file present in the same folder.
No, it doesn't. In fact, the compiler successfully compiled main.cpp.
The error indicates that the linker cannot find test_machine_encode_decode. This is hardly surprising, since test_machine_encode_decode is defined in test.cpp. You have to link the object files of main.cpp and test.cpp to get a complete executable.

If you look at the actual code, you'll see that main only calls the test_machine_encode_decode() Unit-test. You'll have to implement the functionality from the readme yourself or you search through the git history and try to find out, if the program actually worked in the past.

Related

g++ failing to link statically when compiling to binary format: "skipping incompatible libm.a when searching for -lm"

While attempting to write a kernel in C++, I've run into a peculiar issue.
When prompting g++ to compile even a very basic C++ file statically and to binary, it simply keeps skipping over the static math library (libm.a), ultimately failing to compile.
Attempting to compile a simple C++ file:
test.cpp
int main() {
return 0;
}
using this g++ command:
g++ -static test.cpp -Wl,--oformat=binary
I receive the following error output:
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/libm.a when searching for -lm
/usr/bin/ld: skipping incompatible /lib/x86_64-linux-gnu/libm.a when searching for -lm
/usr/bin/ld: skipping incompatible /usr/lib/x86_64-linux-gnu/libm.a when searching for -lm
/usr/bin/ld: skipping incompatible /lib/x86_64-linux-gnu/libm.a when searching for -lm
/usr/bin/ld: skipping incompatible /usr/lib/x86_64-linux-gnu/libm.a when searching for -lm
/usr/bin/ld: cannot find -lm: No such file or directory
I am running Linux Mint Cinnamon V. 21 (Vanessa) on a VirtualBox VM.
In my attempt to narrow down the issue, I have also attempted to exclude the -static flag:
g++ test.cpp -Wl,--oformat=binary
Which results in a different error entirely:
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/11/libstdc++.so: error adding symbols: file in wrong format
collect2: error: ld returned 1 exit status
After thorough research, I was made aware that this could be caused by an incompatibility between 32-bit libraries and 64-bit files. Everything is supposed to be in 64 bit.
I did attempt to determine bitness of libm.a using file.
When using the file command on /usr/lib/x86_64-linux-gnu/libm.a, I receive the following output:
libm.a: ASCII text
indicating neither bitness. This led me to conclude that perhaps the library is damaged and needs updating. After running sudo apt-get install libc6-dev, the issue persists, however.
I'm not sure what to do at this point.
Update:
I've opened libm.a in a text editor and the entire contents of the file are:
/* GNU ld script
*/
OUTPUT_FORMAT(elf64-x86-64)
GROUP ( /usr/lib/x86_64-linux-gnu/libm-2.35.a /usr/lib/x86_64-linux-gnu/libmvec.a )
Update 2: apparently this is a linker script. Both referenced files libm-2.35.a and libmvec.a are present in my directory and are, according to objdump, 64-bit-versions.
Based on the compiler's error output, it seems that in my case, for whatever reason, g++ (or more specifically, ld) fails to use this linker script. What could possibly cause this?
I have come to the conclusion that it is not normally possible to statically link C++ code involving object oriented features into a fully functional binary file, as libm.a can apparently be linked to ELF only.
besides: even the static version of glibc, which is also required, references other dynamic libraries, making it useless for kernel code.
there might be some sort of workaround, but it seems that g++ does not support this functionality by default.

I can't run gcov on visual studio code on my cpp project; .gcda file not generating

I want to use gcov and I can't seem to get the .gcda file anywhere. I followed the official gnu guide (link) on how to use it but whenever I run g++ --coverage test.o it pops the quoted message as an error. I assume this is because the file is already created? Upon using g++ -coverage test.cpp -c it creates an .o and .gcno of the test file, not the .gcda one though:
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../lib/libmingw32.a(lib64_libmingw32_a-crt0_c.o): in function main': C:/M/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/crt0_c.c:18: undefined reference to WinMain'
collect2.exe: error: ld returned 1 exit status
. I have to mention that this also happens with the a.out command

Input File format not recognized (c++)

I'm writing some code for an assignment for a CS class at my university. This program is supposed to read in a .DAT file from the command line, assign the values in the file to an array, and then take that array and compute its average. The only issue I have is that I keep getting this error when I try to compile my code:
/usr/bin/ld:seven.dat: file format not recognized; treating as linker script
/usr/bin/ld:seven.dat:1: syntax error
collect2: error: ld returned 1 exit status
I've tried looking around on Google/StackOverflow a bit, but my programming knowledge is too limited to really understand what's going on, so I have no idea where my errors are. I'm compiling the program with this command:
g++ lab5.1.cpp seven.dat -Wall -o myprog
I can post some/all of the code if needed also.
The problem is that you are trying to compile the .dat file as part of the build process when creating your myprog executable. That is wrong. Build the executable first, then pass the .dat file to your program when you run it, eg:
g++ lab5.1.cpp -Wall -o myprog
myprog seven.dat
Inside your code, you will receive the seven.dat filename in your main() function's argv[] parameter. You can then open the .dat file and read its content as needed.

Error message while compiling a program

I’m a newbie to C++ and Linux. There is this code I’m playing with that requires me to install the HElib (Homomorphic encryption library and other libraries - GMP, NTL) which I did. I want to compile the code (main.cpp) that has a header file (FHE.h) in HElib. My problem is how can I link FHE.h (in HElib folder) and main.cpp (in another folder) together so that I can compile them. I have tried some commands
g++ -I/Home/HElib/src/FHE.h main.cpp -o main
Error message
main.cpp:1:17: fatal error: FHE.h: No such file or directory
compilation terminated.
Another command line
g++ -I/Home/HElib/Src/FHE.h -I/Home/SimpleFHESum-master/SimpleFHESum-master/main.cpp -o main]
Error Message
g++: fatal error: no input files
compilation terminated.
What's wrong and how can I fix this?
The -I flag adds the following directory to the include path of the compiler. This enables you to write e.g. #include "FHE.h" even though that file is not located in the same folder as the source file you're trying to compile.
Have you tried just removing the 'FHE.h' part from your -I directive?
g++ -I/Home/HElib/src ...

Compiling an external library on Linux

Good Day Everyone,
N.B - This problem has been solved - I have provided my own solution in the answer section however the solution provided by Jonathan is much shorter. Nevertheless, this was the following question I originally posted:
I am basically trying to compile a serial library (for UART communication) on Linux however I am not really sure how to correctly compile (I have mentioned what I have done so far below), any suggestions would be highly valuable. I am using the serialib library - which is composed of 2 main files (serialib.h and serialib.cpp) , you may directly view the source code of these files here (scroll all the way to the bottom and view the files in new tabs): http://serialib.free.fr/html/classserialib.html
I transferred these files (serialib.h and serialib.cpp) to my BeagleBone Black micro-controller which is running Debian (Wheezy) , g++/gcc (Debian 4.6.3-14) 4.6.3. I wrote my own program (uart.cpp is my file name) to access the functions provided by this library, this is what I wrote:
#include <iostream>
#include "serialib.h"
#ifdef __linux__
#define DEVICE_PORT "/dev/ttyO1"
#endif
int main()
{
serialib LS;
return 0;
}
So as you can see I am trying to access the 'seriallib' class. serialib.h, serialib.cpp and uart.cpp are all in the home directory. I also manually added the iostream library in serialib.cpp as I did not see it being declared in the original source code.
Now I am really unsure of how to compile such external libraries but so far I tried the following steps:
g++ -c -Wall -Werror -fPIC serialib.c to convert to PIC which gives the following error:
distcc[3142] (dcc_parse_hosts) Warning: /home/debian/.distcc/zeroconf/hosts contained no hosts; can't distribute work
distcc[3142] (dcc_zeroconf_add_hosts) CRITICAL! failed to parse host file.
distcc[3142] (dcc_build_somewhere) Warning: failed to distribute, running locally instead
g++ serialib.cpp -L /home/debian/serialib.h which gives the following error:
/usr/lib/gcc/arm-linux-gnueabihf/4.6/../../../arm-linux-gnueabihf/crt1.o: In function _start':
(.text+0x30): undefined reference tomain'
collect2: ld returned 1 exit status
distcc[3210] ERROR: compile serialib.cpp on localhost failed
As of now I am still finding out how to compile this and if I manage to work this out then I'll post my solution here too. Once again any suggestion will be highly valuable. Thank you all :) .
g++ -c -Wall -Werror -fPIC serialib.c to convert to PIC which gives the following error:
The "error" is not an error, it's a warning, telling you that your distcc setup is broken, but that it compiled locally.
That command doesn't "convert to PIC", it compiles the file serialib.c and produces a compiled object file, serialib.o
g++ serialib.cpp -L /home/debian/serialib.h
This is just nonsense. It tries to build a program from serialib.cpp and use the directory /home/debian/serialib.h (which isn't a directory!) to find libraries.
You don't need to "compile a library" you can just compile both the source files and link them together into a program. Either:
g++ -c serialib.cpp
g++ -c uart.cpp
g++ serialib.o uart.o -o uart
Or all in one command:
g++ serialib.cpp uart.cpp -o uart
You should read An Introduction to GCC to understand the commands, not just enter bogus commands without understanding them.
I have found a solution to this problem, hope this helps for all the future readers with similar problems. I have my own source code uart.cpp (Given in the question) which I want to compile, the external library is serialib that contains two main files (serialib.h and serialib.cpp), you will want to replace the following commands with respect to the files you have
Step 1: Compiling with position independent code
g++ -c -Wall -Werror -fpic serialib.cpp
Step 2: Creating a shared library
g++ -shared -o libserialib.so serialib.o , here the library is libserialib.so.
Step 3: Linking your source code with library
g++ -L /home/debian -lserialib uart.cpp -o uart
g++ -L /home/debian -Wall -o test uart.cpp -lserialib
You may save the library at a different path and you may have a different name of course. Suppose you have a library called libabc.so at the directory /home/user/myDir then the commands will be like:
g++ -L /home/user/myDir -labc your_code.cpp -o your_code
g++ -L /home/user/myDir -Wall -o test your_code.cpp -labc
test is out own program, lserialib is actually looking for libserialib.so and not serialib.o as gcc/g++ assumes all libraries start with lib and end with .so or .a and you can see the same goes for labc as it will look for libabc.so thus it is important to make sure your library name begins with lib and ends with .so or .a
Step 4: Making library available at run time
Here we provide the path where the library is actually stored, I saved it in the directory /home/debian which is why my command looks like:
export LD_LIBRARY_PATH=/home/debian:$LD_LIBRARY_PATH
if your library is saved at /path/to/file then the command will look like:
export LD_LIBRARY_PATH=/path/to/file:$LD_LIBRARY_PATH
This is to help the loader find the shared library and to view this path: echo $LD_LIBRARY_PATH and to unset this: unset LD_LIBRARY_PATH
To execute the program type either ./test or ./uart and in case of any modification to the main source code (uart.cpp in this case) , simply repeat step 3. I found the following link very useful: http://www.cprogramming.com/tutorial/shared-libraries-linux-gcc.html . Thank you to all of you who took time to read this question and especially those who gave me suggestions. If anyone has more or better solutions, feel free to post them here to assist future readers :).