compile and run c++ program with own header files in linux - c++

This is my first go at making my own header file. I am trying to make a simple Hello World program in C++ on Ubuntu. made 3 files as follows :
//hello.h file
#ifndef HELLO_H
#define HELLO_H
//my own code
void hello();
#endif
//hello.cpp file
#include <iostream>
#include "hello.h"
using namespace std;
void hello()
{
cout << "This line is printed from header.";
}
//main.cpp file
#include <iostream>
#include "hello.h"
using namespace std;
int main()
{
cout << "in main" << endl << endl;
hello();
return 0;
}
I've tried
g++ -I /home/Desktop/hello/ -c hello.cpp -o hello.o
to compile header file and this command worked.
then, while doing
g++ -o main main.cpp
I am ending up with following error:
/tmp/ccb0DwHP.o: In function `main':
main.cpp:(.text+0x2e): undefined reference to `hello()'
collect2: error: ld returned 1 exit status
Please suggest whether changes need to be made in any file or in any command in the terminal?
thank you

You don't link to hello.o in the command below:
g++ -o main main.cpp
Try this:
g++ -o main main.cpp hello.o
Or for such simple program, just issue the command below:
g++ -o main main.cpp hello.cpp
For ease of use, create a makefile, then you just run make:
make
A simple makefile:
helloprogram: hello.h hello.cpp main.cpp
g++ -o helloprogram main.cpp hello.cpp
clean:
rm helloprogram

Put hello.h in Path2Hello;
g++ -o main -I Path2Hello main.cpp hello.cpp
ps: -I option to specify an alternate include directory (for header files).

To compile and run a C language program, you need a C compiler. To setup a C language compiler in your Computer/laptop, there are two ways:
Download a full fledged IDE like Turbo C or Microsoft Visual C++, which comes along with a C language compiler.
Or, you use any text editor to edit the program files and download the C compiler separately.

Related

How to use C++ function from header in C?

I'm writing my thesis and I have problem with using C++ function in C code. I searched solution and I found a lot of them, but it didn't work anyway. Please explain it to me one more time.
To be quick I have something like below and after gcc main.c -o main I get undefined reference to 'cppfun'
cpp.h:
#pragma once
#ifdef __cplusplus
extern "C" {
#endi
void cppfun();
#ifdef __cplusplus
}
#endif
cpp.cpp:
#include <stdio.h>
#include "cpp.h"
void cppfun()
{
printf("cpp_fun");
}
main.c:
#include <stdio.h>
#indlude "cpp.h"
int main(int argc, char *argv[])
{
cppfun();
return 0;
}
When you combine C and C++, you should compile the translation unit containing the main function, as C++. Not opposite. This is a FAQ.
An undefined reference is usually because you haven't linked in the translation unit where the missing thing is. Your stated build command is
gcc main.c -o main
while it should be e.g.
gcc -c main.c
g++ -c cpp.cpp
g++ cpp.o main.o -o main
except as mentioned, the main translation unit should be in C++.
You need to include all .cpp files after main. Something like that:
g++ main.cpp other.cpp etc.cpp -o main
Firstly you compile your cpp code without link via -c compiler switch
g++ cpp.cpp -c
and you have cpp.o file then compile and link your main.c with cpp.h and cpp.o files via gcc
gcc main.c -o main cpp.o
I tested this answer via my linux server. It is work.

Why one definition rule (ODR) is not honoured by g++ in this case ? .

As you see, there are multiple definitions of testfn symbol while linking, but the linker takes the first occurence (in linking order) and ignores the other occurances in other libraries.
This probably is the way how the linker works.
But Is there any way to enforce linker to flag error on seeing multiple symbols in different linked libraries ? Or any other options to catch such duplicate definitions ?
Content of test1.h:
#ifndef TEST1
#define TEST1
void testfn();
#endif
Content of test1.cpp
#include "test1.h"
#include <iostream>
using namespace std;
void testfn()
{
cout << "file1" << endl;
}
Content of test.h:
#ifndef TEST
#define TEST
void testfn();
#endif
Content of test.cpp:
#include "test.h"
#include <iostream>
using namespace std;
void testfn()
{
cout << "file" << endl;
}
Content of main.cpp:
#include "test.h"
#include "test1.h"
int main()
{
testfn();
return 0;
}
Created a shared libraries.
g++ -fPIC -shared libtest1.so test1.cpp
g++ -fPIC -shared libtest.so test.cpp
Created executable with library order#1
g++ -o main main.cpp -ltest -ltest1
Created executable with library order#2
g++ -o main1 main.cpp -ltest1 -ltest
Ouput of main
./main
file
Ouput of main1
./main1
file1
First of all, it is honoring the ODR, by only taking one of the methods out of the library. And that's just the way shared libraries work.
If you want to see the compiler complain about this, link them all together, without the library step.
g++ -o main1 main.cpp test1.cpp test.cpp
So your question becomes, "How do I tell if I have two libraries which both contain a indentifier with the same name?" Keep in mind that this is often not a problem and sometimes done intentionally. I'd suggest running the library tool (I'm not familiar with the g++ toolset) to get listing of the libraries, and run DIFF of them.
I don't see a way to get GNU ld to complain about multiple symbol definitions across shared libraries. However, if normal static library archives are involved, you might be able to use the --whole-archive/--no-whole-archive set of options to get what you want:
For example, after building libtest.a and libtest1.a instead of the shared library versions, I get no errors with the following link commands:
$ g++ -o main main.cpp -ltest1 -ltest -L.
$ ./main
file1
$ g++ -o main main.cpp -ltest -ltest1 -L.
$ ./main
file
But do get errors for the following:
$ g++ -o main main.cpp -Wl,--whole-archive -ltest1 -ltest -Wl,--no-whole-archive -L.
./libtest.a(test.o): In function `testfn()':
test.cpp:(.text+0x0): multiple definition of `testfn()'
./libtest1.a(test1.o):test1.cpp:(.text+0x0): first defined here
collect2: ld returned 1 exit status
I'm not sure you would want to use --whole-archive for release builds - maybe only as a sanity check for possibly name conflicts (I think that using --whole-archive normally will increase the size of your binary for no good reason).
Also, as mentioned before, this seems to have no effect on shared libraries.

Error compiling source file and header file together in C++

This is not actual code i am working on but sample code i had written to understand what i am doing wrong. So i have three files main.cpp, favourite.cpp and favourite.h. I am trying to compile main.cpp but get some weird error.
// main.cpp File
#include <iostream>
#include "favourite.h"
using namespace std;
int main()
{
favNum(12);
}
// favourite.cpp File
#include "favourite.h"
#include <iostream>
using namespace std;
void favNum(int num)
{
cout << "My Favourate number is " << num << endl;
}
// favourite.h File
#ifndef FAVOURITE_H
#define FAVOURITE_H
void favNum(int num);
#endif
This all files are in same folder and i am compiling it normally like g++ main.cpp I am not sure if i need to compile it diffrently as i am using custom header files.
If you say g++ main.cpp and this is your whole command line, the error is a linker error that it can't find favNum, right? In that case, try:
g++ main.cpp favourite.cpp
or split compilation and linking:
g++ -c main.cpp -o main.o
g++ -c favourite.cpp -o favourite.o
g++ main.o favourite.o
Where -c means: Compile only, no linking and -ofilename is required because you want to write the output to two different object files to link them with the last command.
You might also add additional flag, the most important ones are:
-Wall -Wextra -O3
Oh I guess I see the error although you should have included it in your question.
When compiling multiple source files you need to list them all on the GCC command line. Or you can use a Makefile.
So you could do this:
g++ favourite.cpp main.cpp
Or you could write a Makefile like this:
all: program
program: main.o favourite.o
And then just type:
make

Multi-file C++ compilation

(hopefully) quick question that I can't find the answer to:
I have been given a brief assignment in C++. We are to write a 3-file program. There will be a function file, a header file, and a driver file. Here's what I've got so far:
Header (test.h):
#include <iostream>
using namespace std;
#ifndef TEST_H
#define TEST_H
int foo (int bar);
#endif
Function (test.cpp):
#include <iostream>
#include "test.h"
using namespace std;
int foo (int bar){
bar++;
}
Driver (drive.cpp):
#include <iostream>
#include "test.h"
using namespace std;
int main(){
int x = foo(2);
cout << x << endl;
return x;
}
When I try to compile drive.cpp, I get the following error:
drive.cpp:(.text+0xe): undefined reference to `foo(int)'
So...what am I doing wrong?
For a small project like this, simply compile all .cpp files at once:
g++ main.cpp driver.cpp
For a larger project, you separate the compile and link steps:
compile:
g++ -c main.cpp -o main.o
g++ -c driver.cpp -o driver.o
link:
g++ main.o driver.o
Or rather, you'd have a makefile or IDE do this for you.
In drive.cpp, instead of
#include <test.h>
make it
#include "test.h"
This is the variant of #include syntax that is used for header files of your own program (not system header files). When you use this version the preprocessor searches for include files in the following order:
In the same directory as the file that contains the #include statement.
In the directories of any previously opened include files in the reverse order in which they were opened. The search starts from the directory of the include file that was opened last and continues through the directory of the include file that was opened first.
You need to do one of two things:
Compile all the files at once
# replace 'driver.exe' with what you want your executable called
g++ -Wall -ggdb -o driver.exe main.cpp driver.cpp
Compile all the files to object files and then link the object files:
# again, replace 'driver.exe' with what you want your executable called
g++ -Wall -ggdb -o main.o -c main.cpp
g++ -Wall -ggdb -o driver.o -c driver.cpp
g++ -Wall -ggdb -o driver.exe main.o driver.o
As a side note, you should probably change
#include <test.h>
to
#include "test.h"
and putting "using namespace std;" in a header file is going to cause you copious grief later on.
in test.cpp, change the return line to this:
return bar++;

Trying to compile simple c++ program in make

I am having trouble with make. I installed all of the features that come with cygwin. When I type in make command it says:
make:***No targets specified and no
makefile found. Stop.
This is really annoying as it's a very simple program.
My make file (Makefile):
# This is a sample file.
all: lab1
lab1: lab1.o
g++ -Wall lab1.o -o lab1
lab1.o: lab1.cpp
g++ -Wall -c lab1.cpp -o lab1.o
my program (lab1.cpp):
// This is a sample file written.
#include <iostream>
using namespace std;
int main() {
cout << "Welcome to CS-240!" << endl;
return 0;
}
The issue (fixed in the comments) was that there was a Makefile.mak in the directory but not an actual Makefile without an extension. Changing the name worked for the submitter.