Deleting *.cpp file after compiling with wrong flag order? - c++

I really need your help on this one!
I had a problem with my makefile. The error was very common:
makefile:11: recipe for target 'exec' failed
My makefile looks like this:
CC = g++
PY = python
FLAGS = -std=c++11 -O3
all: main exec data
main: main.cpp
$(CC) $(FLAGS) -o $# $<
exec: main
time ./$<
data: plot.py main
$(PY) $<
As far as im concerned there is no mistake but I still got the error, maybe main.cpp was not compiled?
Anyway I then tried (out of curiosity):
g++ -std=c++11 -O3 -o main.cpp main
And then I got this error:
main: In function `_start':
(.text+0x1360): multiple definition of `_start'
/usr/lib/gcc/x86_64-redhat-linux/6.3.1/../../../../lib64/crt1.o:(.text+0x0): first defined here
main: In function `_fini':
(.fini+0x0): multiple definition of `_fini'
/usr/lib/gcc/x86_64-redhat-linux/6.3.1/../../../../lib64/crti.o:(.fini+0x0): first defined here
main:(.rodata+0x0): multiple definition of `_IO_stdin_used'
/usr/lib/gcc/x86_64-redhat-linux/6.3.1/../../../../lib64/crt1.o:(.rodata.cst4+0x0): first defined here
main: In function `data_start':
(.data+0x0): multiple definition of `__data_start'
/usr/lib/gcc/x86_64-redhat-linux/6.3.1/../../../../lib64/crt1.o:(.data+0x0): first defined here
main:(.rodata+0x8): multiple definition of `__dso_handle'
/usr/lib/gcc/x86_64-redhat-linux/6.3.1/crtbegin.o:(.rodata+0x0): first defined here
main: In function `_init':
(.init+0x0): multiple definition of `_init'
/usr/lib/gcc/x86_64-redhat-linux/6.3.1/../../../../lib64/crti.o:(.init+0x0): first defined here
/usr/lib/gcc/x86_64-redhat-linux/6.3.1/crtend.o:(.tm_clone_table+0x0): multiple definition of `__TMC_END__'
main:(.data+0x8): first defined here
/usr/bin/ld: error in main(.eh_frame); no .eh_frame_hdr table will be created.
collect2: error: ld returned 1 exit status
And now my main.cpp is gone. What the actual.. How can I recover it? I have an older version of it because I'm using git, but its rather unfinished and I really need this version.

The error was very common
That's the make error. What did it show before that? Did it run the compiler at all? Was there a compile error? What was it?
I addressed your proximate problem below, but the original issue is the compile error. You're fixating on the fact that a build target failed, rather than on understanding why it failed.
Builds fail all the time: very commonly because there's a mistake in the code, and very rarely because of an error in a previously-working makefile. As a consequence, you usually want to worry about understanding and fixing the compiler error, before you start changing your makefile or running the compiler manually.
And now my main.cpp is gone. What the actual..
Well, in
g++ -std=c++11 -O3 -o main.cpp main
the option -o filename tells g++ to use filename for output. So, it opened main.cpp for output and clobbered the contents.
You meant
g++ -std=c++11 -O3 -o main main.cpp
It's an easy mistake to make, which is why we have build systems to do this stuff for us. And backups. And version control.
In future, you can just type make main to select a single target, and make should tell you what it's doing.
How can I recover it?
From your editor, or version control, or backup, or filesystem-level snapshotting if you have a fancy SAN or, in extremis, from memory.
Nothing teaches good source control and backup habits like having to rewrite something from scratch.
there is no main.cpp file anymore. why exactly is that?
When the build failed, the incomplete output file was deleted.
Consider, for reference, how make works. You have a target called main, so it checks whether a file called main exists.
if main exists, it looks at the dependencies, and sees if any of those files are newer then main
if it thinks main should be (re-)generated (either it doesn't exist or is older than a dependency), it runs the rule you gave it
Now if g++ left an empty (or incomplete) version of main lying around after a failed compilation, how would make know to re-generate it the next time you built?
It's essential that the output file be deleted when compilation fails, because otherwise make wouldn't work correctly. You'd also have a directory full of empty or corrupt partly-compiled executables and object files, which doesn't sound like such a great idea.
In other news, your exec target doesn't create a file called exec. This should be a .PHONY rule. So, probably, should data.

The problem is:
g++ -std=c++11 -O3 -o main.cpp main
Where you specify that the output should be placed in main.cpp. You try to compile main and store the result in main.cpp. Since the compile failed, the output file is removed after compilation stopped. So no main.cpp.

It's simple: Just save the file again in your editor.
To do so, press C-x C-w and type the filename again.

Related

Makefile not working when changing function argument to const

I have a strange problem when compiling a C++ code using a makefile. The code first compiles perfectly. Then I change one function argument to "const". If I then compile, I will receive the error message when the code tries to use the function in which I changed the argument to const. This can be resolved by removing all .o files and then compiling again, but I am curious as to what causes this issue in the first place. My files are:
MyClass.h
class MyClass {
public:
void fun(double*const c);
};
MyClass.cpp
#include "MyClass.h"
void MyClass::fun(double *const c){
};
Main.cpp
#include "MyClass.h"
int main(int argc,char* argv[]) {
MyClass foo;
double *bar=new double[2];
foo.fun(bar);
};
Makefile
all: main
main: Main.o MyClass.o
g++ -o a.out Main.o MyClass.o
Main.o: Main.cpp
g++ -c Main.cpp
MyClass.o: MyClass.cpp
g++ -c MyClass.cpp
If I now first run make, everything works. But then I change the signature of fun to fun(const double *const c), I receive the error message
Main.cpp:(.text+0x3b): undefined reference to `MyClass::fun(double*)'
collect2: error: ld returned 1 exit status
Makefile:6: recipe for target 'main' failed
make: *** [main] Error 1
However, if I remove all the .o files and then run make again, it compiles.
The rule
main.o: Main.cpp
says thay the main.o object file only depend on the Main.cpp source file. But it actually depends on another file: The MyClass.h header file.
There's also an error in the capitalization of the name of the target.
The above two problems means that when you change the header file MyClass.h to update the function signature, the Main.o object file will not be recreated and still reference the old function.
So the rule should be
Main.o: Main.cpp MyClass.h
That addition will cause the Main.o object file to be recompiled when you change the header file.
This change should also be done for the MyClass.o target.
Also note that the main target uses MyClass.o as a dependency, but then you use the MyClass.cpp source file when linking, instead of the object file.
The name of the target should also be the name of the generated file (i.e. a.out in your case).
The problem is, that your Makefile is broken: It ignores the fact that a .o file does not only depend on the corresponding .cpp file, but also on the .h files it includes. A correct Makefile rule must include all dependencies, including the directly, or even indirectly included .h files.
Since you Makefile is incomplete, make did not recompile the calling site of your function when its definition changed, so the stale object still references the non-const function. Due to C++ name-mangling, the linker caught it in the act, the error would have gone unnoticed in C!
To fix this situation for good, I recommend spending an hour or two reading this article on automatic dependency generation, and implementing some of the solutions it offers into your Makefile. Once you have done this, you will likely just copy-cat your existing solution into the Makefiles of future projects, and otherwise forget about the problem.

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 :).

SOLVED - Makefile: Multiple Definition of Function (Actually a C++ lesson)

I'm trying to write more sophisticated makefiles, but my explorations have gotten me into a multiple definition issue.
The program is meant to brute-force a marble maze, so I have a class for the game board declared in marbleBoard.h, with its implementation written in marbleBoard.cpp. The .cpp file #includes the .h file. The main program is written in marble.cpp. The Variables NORTH, SOUTH, EAST, and WEST refer to bit masks that symbolize walls, and are defined in marbleBoard.h outside of the class.
I based my makefile on MrBook's tutorial Makefiles.
Here is the Makefile code:
#!/bin/bash
COMPILER=g++
CFLAGS=-c -g -std=c++14
all: marble
marble: marble.o marbleBoard.o
$(COMPILER) marble.o marbleBoard.o -o marble
marble.o: marble.cpp
$(COMPILER) $(CFLAGS) marble.cpp
marbleBoard.o: marbleBoard.cpp marbleBoard.h
$(COMPILER) $(CFLAGS) marbleBoard.cpp marbleBoard.h
clean:
rm *o marble
This is the output I recieve:
[uthranuil#Palantir marble]$ make
g++ -c -g -std=c++14 marbleBoard.cpp marbleBoard.h
g++ marble.o marbleBoard.o -o marble
marbleBoard.o:(.data+0x0): multiple definition of `NORTH'
marble.o:(.data+0x0): first defined here
marbleBoard.o: In function `marbleBoard::marbleBoard()':
/home/uthranuil/csci242/marble/marbleBoard.cpp:6: multiple definition of `EAST'
marble.o:(.data+0x1): first defined here
marbleBoard.o: In function `marbleBoard::marbleBoard()':
/home/uthranuil/csci242/marble/marbleBoard.cpp:6: multiple definition of `SOUTH'
marble.o:(.data+0x2): first defined here
marbleBoard.o: In function `marbleBoard::marbleBoard()':
/home/uthranuil/csci242/marble/marbleBoard.cpp:6: multiple definition of `WEST'
marble.o:(.data+0x3): first defined here
collect2: error: ld returned 1 exit status
make: *** [makefile:10: marble] Error 1
I have spent a lot of time looking for answers and trying different solutions. Here is a list of Q/As I have read:
Function multiple definition linker error building on GCC - Makefile issueMakefile: multiple definition and undefined reference errorMakefile: multiple definition of TMC_ENDError in makefile: multiple definition of _startmultiple definition errors when using makefile
Any help is greatly appreciated. Thank you for your time and attention.

make not executing correct Makefile

I should preface this by saying I am very new to Makefiles.
I created the following Makefile:
all: tiling_graph.o
g++ -o tiling_graph tiling_graph.o -L/usr/local/lib -ligraph
I am trying to make sure that -ligraph is included. However, when I type "make", I get the following output: "c++ -c -o tiling_graph.o tiling_graph.cpp"
Why is it not using the Makefile that I created in the current directory? I have tried using "make -f Makefile" and "make --file=Makefile" but none of these are working.
Also, right after I first made the Makefile, it worked correctly. The output after typing make was
"g++ -o tiling_graph tiling_graph.o -L/usr/local/lib -ligraph"
I executed ./tiling_graph and it was successful.
Then I edited tiling_graph.cpp, ran make again, and the output was "c++ -c -o tiling_graph.o tiling_graph.cpp" and has been ever since.
I would really appreciate any help. Thanks!
A simple way to think about a make rule:
target: dependency list
commands to make the target
is that it is a recipe for making the file called target from the list of files in the dependency list. Since make can see the file system, it can tell whether any file in the dependency list is newer than the file named target, which is its signal for recreating target. After all, if none of the dependencies have changed, the target must be up-to-date.
Note that make knows quite a lot about how to build files. In particular, it has a lot of built-in "pattern" rules, so it knows, for example, how to make an object file (prog.o) from a C++ source file (prog.cpp) or from a C source file (prog.c) or many other things. So you only need to actually write a makefile when you have other requirements, like a library (and even then you could just add that to an environment variable, but the makefile is better).
Now, you don't actually want to build a file called all. You want to build a file called tiling_graph. So the correct make rule would be:
tiling_graph: tiling_graph.o
g++ -o tiling_graph tiling_graph.o -L/usr/local/lib -ligraph
Since make already knows how to create tiling_graph.o, it can actually figure out how to make tiling_graph from tiling_graph.cpp.
So where does this all come from? The usual way to use all is:
all: program1 program2 program3
which tells make that the all target requires program1, program2 and program3. So if you need to build all three of those programs, the all rule would let you just do one make command. Since there is no file named all, that's a "phony" target and (with gnu make, at least) it should be declared as a phony target:
all: tiling_graph
.PHONY: all
But you really don't need that if you just want to build one program.
When you just type make (as opposed to make target), make chooses the first target in the makefile. So if you put the thing you usually want to build first, you'll save some typing.

include class and compile with g++

Im a beginner in C++ and working with unix. So here is my question.
I`ve written few lines in the main-function, and i needed a function, that is defined in the c_lib - library.
main.cpp:
#include <iostream>
#include "c_lib.cpp"
int main()
{
return 0;
}
i want to execute it on the terminal, so i wrote
g++ -c c_lib.cpp
g++ -c main.cpp
g++ -o run c_lib.o main.o
Until here, there is no error report.
Then
./run
I get the error
error: ./run: No such file or directory
What's wrong?
Including a .cpp is not usually done, usually only headers are included. Headers usually contain the declarations that define the interface to the code in the other .cpp
Can you show us the source of c_lib? That may help.
As the source of c_lib is #included, there is no need to compile it seperately. In fact this can/will cause errors (multiple definitions being the first to come to mind). You should only need to do:
g++ -o run main.cpp
to compile your code in this case.
(When using a header (.h), you will need to compile the implementation (.cpp) seperately)
Compile with warnings turned on:
g++ -Wall -Wextra -o run main.cpp
and you will get more output if there are problems with your code.
Is the run file being output by gcc? You can test by calling ls in the terminal (or ls run to only show the executable if it is present).
If the executable is present, it could be that it isn't marked as runnable. I'll go into that if it is a problem as it is outside the general scope of the site (though still related)
First of all you should not include source file into another source. You should create a header file and put declarations there (that allows main() to call functions from c_lib.cpp or use global variables if any)
When you run g++ you have to look into it's output, if operation succeed or not. In your case it failed so executable run was not created.
Usually you do not call compiler manually but write a makefile and let make utility to call g++.