I'm trying to create a Makefile which compiles a specific program.
I have 1x .cpp file and 2x .h files.
So I would go
g++ source.cpp header1.h header2.h -o programOut
The thing is i'm getting an error.
Mainly in the second header file where Appointments is a class defined in the first header file.
The second header file mainly contains (function prototypes?) I just got the other functions that I used, removed the implementation and placed it in there.
error: ‘Appointments’ does not name a type
error: ISO C++ forbids declaration of ‘left’ with no type
error: ‘Appointments’ does not name a type
error: ISO C++ forbids declaration of ‘right’ with no type
error: ‘string’ does not name a type
error: ‘time_t’ does not name a type
It compiles fine if I go g++ source.cpp -o programOut
however when I added the .h files when i type g++, it gives me the error shown above.
Any ideas why?
Typically, you should not include header files in your list of files to compile. Rather, your source files (like source.cpp) will already #include the headers they need. If you actually have non-prototype code in your headers that you need compiled into their own .o files, you're doing it wrong.
g++ expects the files passed on the command line to be compilation units. Header files are not compilation units, and as such should not be passed on the command line in the first place.
g++ -Wall -Werror source.cpp
but you have to be in the same directory where the code is present.
Related
I have a template class of a binary tree, tree.tpp and tree.h. I have done a test with the class but I can't compile it
#include <cstdlib>
#include <iostream>
#include "arbolbinario.h"
using namespace std;
int main(int argc, char** argv) {
ArbolBinario<int> pila(45);
return 0;
}
And I'm having the following error when I do: g++ -c -o ./tree.o ./tree.tpp -I ./tree.h
g++: warning: ./tree.tpp: linker input file unused because linking not done
(I'm working with netbeans)
.tpp is not one of the file endings recognized by g++, see its documentation.
Therefore g++ assumes that you want the file to be passed to the linker directly. But since you used the -c flag, which indicates that you want g++ to only compile, but not invoke the linker, you get that error message.
The solution is to tell g++ what kind of file it is that you are passing it explicitly:
g++ -c -o ./tree.o -x c++ ./tree.tpp -I ./tree.h
or, better, rename your C++ source file use one of the common file endings for C++ source files, e.g. .cpp, .cc, .cxx, etc. That would result in less trouble with build tools and less confusion for others looking at your project.
As noted in the question comments -I ./tree.h also is clearly wrong, but not the cause of this particular error (and probably it just doesn't belong there at all).
However:
If your .tpp contains the implementation of methods of a class template, then you should not rename it (.tpp is appropriate in that case), but you also should not compile it as translation unit at all. That means it should not appear in any g++ command.
.tpp files implementing a template classes methods need to be included in the .h file with the class template definition, instead. Otherwise you will get linker errors later when you try to link your files, see Why can templates only be implemented in the header file?.
The -c flag tells GCC to only compile the input source files, not to do any linking.
If you want the compiler to link the object files into an executable binary, you need to remove the -c flag.
The official docs state how precompiled headers are to be used through the -cc1 interface, like so to generate them:
$ clang -cc1 test.h -emit-pch -o test.h.pch
And to use them:
$ clang -cc1 -include-pch test.h.pch test.c -o test.s
The problem is that the -cc1 interface is way too low-level to be used by developers from the CLI. In fact, the regular high-level interface ultimately calls into the low-level -cc1 interface by supplying it with a very large set of arguments that are necessary for its correct operation, for example the include paths appropriate for the compile time system. Without these arguments, the -cc1 interface has no prayer of working:
$ clang++ -cc1 /usr/include/x86_64-linux-gnu/c++/7/bits/stdc++.h -emit-pch -o std.pch
/usr/include/x86_64-linux-gnu/c++/7/bits/stdc++.h:33:10: fatal error: 'cassert' file not found
#include <cassert>
^~~~~~~~~
1 error generated.
Is there a way to use precompiled headers from the high-level interface, such that a developer may conveniently tap into this feature during their daily work?
I don't know why the clang docs do not explain this, but indeed as #selbie surmises, it is possible to use Clang precompiled headers (PCH) without using -cc1.
To generate a PCH file:
$ clang -c -o big-header.hh.pch big-header.hh <other options>
This is the normal compile command, except the input file has the .hh (C++ header) extension. clang will recognize that means to generate a PCH. Alternatively, pass -xc++-header before the header file name if you do not want to use that extension (or another, like .H or .hpp, that is unambiguously C++).
You can tell that big-header.hh.pch is not object code (despite the -c on the command line) because file will say it is "data" (at least my version does) rather than object code. To be extra sure, run strings big-header.hh.pch | head. The first line should be "CPCH" (meaning "Clang PCH").
To use the PCH file:
$ clang -c -include-pch big-header.hh.pch <other compile options>
The addition of -include-pch big-header.hh.pch is the key step that is different compared to gcc. Clang will not automatically pick up PCH files just due their name.
The above was tested with Clang+LLVM-14.0.0 on Linux.
I think the root of your problem is that your filename is test.h and clang thinks you are compiling C code, not C++ code. Hence, when you include <cassert>, clang doesn't know it should be looking at the C++ include path. Try naming your file test.hpp. You only have to name the file you want as the precomp header with .hpp. You can keep all your header files with .h extensions.
In any case, I might be getting this confused with gcc/g++, but Clang follows the same behavior whenever I compile my code on Mac. This is how I make use of precompiled headers. Read on...
If you've got a C++ header file you want to precompile, just compile it as any other .cpp file. Notice that I'm using .hpp as the file extension so the compiler picks it up as a C++ header file.
clang -c precomp.hpp
This will produce precomp.hpp.gch
Now to use the precomp by any other ordinary C++ file, just include the ordinary .hpp file:
// main.cpp
#include "precomp.hpp"
void func1() {...}
void main() {...}
The compiler will automatically use the corresponding .gch file if its present in place of the original .hpp file.
It seems to me that gcc can deal with both c and c++ projects,so why is g++/gcc-c++ needed?
What's the difference between g++ and gcc-c++?
gcc will compile C source files as C and C++ source files as C++ if the file has an appropriate extension; however it will not link in the C++ library automatically.
g++ will automatically include the C++ library; by default it will also compile files with extensions that indicate they are C source as C++, instead of as C.
From http://gcc.gnu.org/onlinedocs/gcc/Invoking-G_002b_002b.html#Invoking-G_002b_002b:
C++ source files conventionally use one of the suffixes .C, .cc, .cpp, .CPP, .c++, .cp, or .cxx; C++ header files often use .hh, .hpp, .H, or (for shared template code) .tcc; and preprocessed C++ files use the suffix .ii. GCC recognizes files with these names and compiles them as C++ programs even if you call the compiler the same way as for compiling C programs (usually with the name gcc).
However, the use of gcc does not add the C++ library. g++ is a program that calls GCC and treats .c, .h and .i files as C++ source files instead of C source files unless -x is used, and automatically specifies linking against the C++ library. This program is also useful when precompiling a C header file with a .h extension for use in C++ compilations.
For example, to compile a simple C++ program that writes to the std::cout stream, I can use either (MinGW on Windows):
g++ -o test.exe test.cpp
gcc -o test.exe test.cpp -lstdc++
But if I try:
gcc -o test.exe test.cpp
I get undefined references at link time.
And for the other difference, the following C program:
#include <stdlib.h>
#include <stdio.h>
int main()
{
int* new;
int* p = malloc(sizeof(int));
*p = 42;
new = p;
printf("The answer: %d\n", *new);
return 0;
}
compiles and runs fine using:
gcc -o test.exe test.c
But gives several errors when compiled using:
g++ -o test.exe test.c
Errors:
test.c: In function 'int main()':
test.c:6:10: error: expected unqualified-id before 'new'
test.c:6:10: error: expected initializer before 'new'
test.c:7:32: error: invalid conversion from 'void*' to 'int*'
test.c:10:9: error: expected type-specifier before '=' token
test.c:10:11: error: lvalue required as left operand of assignment
test.c:12:36: error: expected type-specifier before ')' token
As far as I know, g++ uses the correct C++ linker options whereas gcc uses the C linker options (so you may get undefined references, etc.).
I've got simple program in c++ which include two standard headers
stdio.h and iostream. When I type
gcc main.c
I got error: fatal error: iostream: There is no file or directory
even if I rewrite iostream to iostream.h
But when I type:
g++ main.c
everything works fine.
I have to fix this problem cause my IDE(CodeLite) probably use gcc command
That's how you'd compile a C source file. If you're compiling C++ rather than C, then
rename the file extension to something GCC recognises as C++, such as .cpp, .cxx or .cc
invoke the compiler as g++ rather than gcc
I am writing a Rcpp code that include two library RcppArmadillo and trng4. However, when I include two header files (RcppArmadillo.h and trng/gamma_dist.hpp) it gives compilation error.
trng/special_functions.hpp:47:39: error: declaration of ‘float lgammaf(float) throw ()’ has a different exception specifier
extern "C" float lgammaf(float) throw();
include-fixed/math.h:476:14: error: from previous declaration ‘float lgammaf(float)’
extern float lgammaf(float);
Full compilation options are
-fopenmp -lgomp -DUSE_R -DNDEBUG -DDISABLE_SINGLE -DNTHROW -DDISABLE_FIO -I/usr/local/include -I"/Users/avi/Library/R/3.0/library/Rcpp/include" -I"/Users/avi/Library/R/3.0/library/RcppArmadillo/include" -fPIC -pipe -std=c++0x -Wall -pedantic -c
Seems like the lgammaf is declared in both header files. I tried using -E with g++ option but that give ld warning " .o, file was built for unsupported file format" and give error function in not available in .Call when I try it to after loading in R. What am I doing wrong?
Perhaps out of context I am using trng4 package to develop a thread gibbs sampler (in openmp) that sample from gamma distribution. I am currently running this MacOS. But eventual it will run in linux server.
It sounds like you do have a problem between Armadillo and trng4. Maybe you should try to, if possible, separate your interface so that you do not need to include from both in the same file.
Someone can correct me if I'm wrong, but I believe you prevent this issue by using #ifndef in each header file so that it's not defined a second time even if it's included a second time. But I guess these aren't your files are they...?
#ifndef __your_unique_header_name__
blah blah
#endif