I am trying to use Google Test framework: https://github.com/google/googletest/tree/master/googletest .
I have 4 files:
factorial.cpp:
#include "factorial.h"
int factorial(int n) { [some code here] }
facotrial.h:
int factorial(int n);
test_factorial.cpp
#include "gtest/gtest.h"
#include "factorial.h"
[some tests here]
gtest_main.cpp:
#include <stdio.h>
#include "gtest/gtest.h"
GTEST_API_ int main(int argc, char **argv) {
printf("Running main() from gtest_main.cc\n");
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
Also I have a makefile which contains (among other things):
INCLUDES = -I/home/my_username/Documents/gtest/googletest/googletest/include
[...]
$(MAIN): $(OBJS)
$(CC) $(CFLAGS) $(INCLUDES) -o $(MAIN) $(OBJS) $(LFLAGS) $(LIBS)
After writing make in terminal I get:
test_factorial.cpp:1:25: fatal error: gtest/gtest.h: No such file or directory
compilation terminated.
makefile:27: recipe for target 'test_factorial.o' failed
What is the issue?
In the README file on googletest they say:
g++ -isystem ${GTEST_DIR}/include -pthread path/to/your_test.cc libgtest.a \
-o your_test
So here it's -isystem instead of -I but I had problems with -isystem as well.
You've added your includes to the link command, but not to the compile command. This rule:
$(MAIN): $(OBJS)
$(CC) $(CFLAGS) $(INCLUDES) -o $(MAIN) $(OBJS) $(LFLAGS) $(LIBS)
tells how to link the main program from the object files. This rule isn't used to compile the object files: assuming that your [...] doesn't elide a compile rule, you're using the built-in compiler rule which doesn't know anything about the INCLUDES variable.
If you would have shown us the compile command make printed when you got that error for test_factorial.cpp it would have been clear that the flag was missing.
If you don't make up your own variable to hold these flags and instead use the CPPFLAGS variable which is the standard variable for C preprocessor flags like -I, it will just work.
CPPFLAGS = -I/home/my_username/Documents/gtest/googletest/googletest/include
it may just work.
Related
I have created simple C++ Makefile Eclipse project in Ubuntu. Eclipse has created default Makefile:
PROJECT_ROOT = $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
OBJS = cpp_makefile.o
ifeq ($(BUILD_MODE),debug)
CFLAGS += -g
else ifeq ($(BUILD_MODE),run)
CFLAGS += -O2
else ifeq ($(BUILD_MODE),linuxtools)
CFLAGS += -g -pg -fprofile-arcs -ftest-coverage
LDFLAGS += -pg -fprofile-arcs -ftest-coverage
else
$(error Build mode $(BUILD_MODE) not supported by this Makefile)
endif
all: cpp_makefile
cpp_makefile: $(OBJS)
$(CXX) $(LDFLAGS) -o $# $^
%.o: $(PROJECT_ROOT)%.cpp
$(CXX) -c $(CFLAGS) $(CXXFLAGS) $(CPPFLAGS) -o $# $<
%.o: $(PROJECT_ROOT)%.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $# $<
clean:
rm -fr cpp_makefile $(OBJS)
Everything goes fine in case I have only one source file. In case I create class TestMe with it's header and cpp file and add include header to main cpp file build fails. Looks like system can't find TestMe.cpp.
Error:
Building in: /home/a/cpp-workspace2/cpp_makefile/build/default
make -f ../../Makefile
g++ -c -O2 -o cpp_makefile.o /home/a/cpp-workspace2/cpp_makefile/cpp_makefile.cpp
g++ -o cpp_makefile cpp_makefile.o
/usr/bin/ld: cpp_makefile.o: in function `main':
cpp_makefile.cpp:(.text.startup+0x1c): undefined reference to `TestMe::TestMe()'
collect2: error: ld returned 1 exit status
make: *** [../../Makefile:19: cpp_makefile] Error 1
Build complete (3 errors, 0 warnings): /home/a/cpp-workspace2/cpp_makefile/build/default
In case I use same source in Eclipse C++ Managed build project everything goes fine. How to solve this problem in right way In Eclipse Makefile project?
cpp_makefile.cpp
#include "TestMe.h"
int main(int argc, char **argv)
{
TestMe testMe = TestMe();
return 0;
}
TestMe.h:
class TestMe {
public:
TestMe();
virtual ~TestMe(){};
};
TestMe.cpp:
#include "TestMe.h"
TestMe::TestMe() {
}
Eclipse will create a default Makefile for you, but it does not manage the Makefile(s) in a makefile-based project. It cannot really do so while also allowing you to make your own makefile changes or supporting makefiles it did not generate itself. If you want the build configuration to be completely managed by Eclipse then you should choose a different project type.
With a makefile-based project, then, you need to make appropriate changes to the Makefile yourself when you add sources to the project. In this particular case, it looks like you should change
OBJS = cpp_makefile.o
to
OBJS = cpp_makefile.o TestMe.o
#include <iostream>
#include <string>
#include <fstream>
int main (void)
{
// Nothing here.
}
I am using Makefile to compile.
CXXFLAGS = -std=c++11 -O2 -g -Wall -fmessage-length=0
OBJS = ProgramEntry.o
LIBS =
TARGET = Reading
$(TARGET): $(OBJS)
$(CXX) -o $(TARGET) $(OBJS) $(LIBS)
all: $(TARGET)
clean:
rm -f $(OBJS) $(TARGET)
Resulting in undefined reference.
undefined reference to --
I think makefile is not using any header file. May I know how to fix the make file, in case if I add a directory for header files.
It is using the headers, or you'd get a compiler error, not a linkage error.
Change the following line to this:
OBJS = ProgramEntry.o GetNodes.o GetElements.o MeshData.o
Or
OBJS = *.o
To add all objects in the current directory.
You're only linking in one of your object files, so the functions defined in the others don't make it into your program.
Add all your .os to OBJS. That appears to be the point of that variable, after all?
I've been learning c++ and encountered the following question:
I have a directory structure like:
- current directory
- Makefile
- include
- header.h
- src
- main.cpp
my header.h :
#include <iostream>
using namespace std;
void print_hello();
my main.cpp:
#include "header.h"
int main(int argc, char const *argv[])
{
print_hello();
return 0;
}
void print_hello()
{
cout<<"hello world"<<endl;
}
my Makefile:
CC = g++
OBJ = main.o
HEADER = include/header.h
CFLAGS = -c -Wall
hello: $(OBJ)
$(CC) $(OBJ) -o $#
main.o: src/main.cpp $(HEADER)
$(CC) $(CFLAGS) $< -o $#
clean:
rm -rf *o hello
And the output of make is:
g++ -c -Wall src/main.cpp -o main.o
src/main.cpp:1:20: fatal error: header.h: No such file or directory
compilation terminated.
Makefile:10: recipe for target 'main.o' failed
make: *** [main.o] Error 1
What mistakes I have made in here. It's frustrating. Really appreciate any advice!
You told the Makefile that include/header.h must be present, and you told the C++ source file that it needs header.h … but you did not tell the compiler where such headers live (i.e. in the "include" directory).
Do this:
CFLAGS = -c -Wall -Iinclude
You can either add a -I option to the command line to tell the compiler to look there for header files. If you have header files in include/ directory, then this command should work for you.
gcc -Iinclude/
Since, you are using makefile, you can include this option in CFLAGS macro in your makefile.
CFLAGS = -Iinclude/ -c -Wall
OR
You can include header files using #include "../include/header.h".
Perhaps change your include line:
#include "include/header.h"
Assuming that's where your header exists - I'm making that assumption from your makefile
I am trying to use Sublime Text 2 as my IDE. I am setting up a project but having difficulty understanding how to properly link files. When I build off of assn1.cpp, I get the following error:
C:\Users\..\AppData\Local\Temp\ccEffTCN.o:assn1.cpp:(.text+0xdd): undefined reference to `SceneData::SceneData(int)'
collect2.exe: error: ld returned 1 exit status
Here is my main cpp file. I remove the code that isn't causing the problem for the sake of clarity. I do not get a build error if I comment out where I instantiate a new Scene Data object.
#include "SceneData.h"
using namespace std;
int main(int argc, char* argv[]){
SceneData sc = SceneData(1);
return 0;
}
For reference, here is my h and cpp file for SceneData.
// SceneData.cpp
#include "SceneData.h"
SceneData::SceneData(int x){
temp = x;
}
int SceneData::publicTemp(){
return 0;
}
#ifndef SCENEDATA_H
#define SCENEDATA_H
class SceneData{
int temp;
public:
SceneData(int x);
int publicTemp();
};
#endif // SCENEDATA_H
I am using the sublime provided c++ build config. mingw and g++ are installed. I have all of the files saved in the correct project directory. My specific question is what am I missing to ensure files are linked when I create the o files that end up in the executable?
** Edits Below *******
This is my make file
OBJS = $(patsubst %.c, %.o, $(wildcard *.c)) \
$(patsubst %.cpp, %.o, $(wildcard *.cpp)) \
$(patsubst %.cxx, %.o, $(wildcard *.cxx))
CFLAGS = -Wall
CXXFLAGS = -Wall
OPT = -O4
balls2.png:
%.png: %.ppm
convert $< $#
%.ppm: %.nff trace
./trace < $*.nff
mv trace.ppm $#
trace: $(OBJS)
$(CXX) $(OPT) -o $# $(OBJS) $(LDFLAGS) $(LDLIBS)
%.o: %.c
$(CC) $(OPT) -c -o $# $(CFLAGS) $<
%.o: %.cxx
$(CXX) $(OPT) -c -o $# $(CXXFLAGS) $<
%.o: %.cxx
$(CXX) $(OPT) -c -o $# $(CXXFLAGS) $<
clean:
rm -f *.o
clobber: clean
rm -f trace *.ppm *.png
assn1.o: assn1.cpp SceneData.h
SceneData.o: SceneData.cpp SceneData.h
I had no problem compiling your code with g++, using Sublime as my text editor. Are you using a make file when compiling? If so, please post your make file code. Without a make file, I just needed to enter:
g++ *.cpp
And then ./a.out gave me the output '0' as expected.
Perhaps the following thread may be of assistance to you: Can't build C++ program using Sublime Text 2
I SOLVED THIS ISSUE BY MYSELF
The problem was the linkage of the library.
I copied the libmywrapper.so(i renamed it) file to /usr/lib and linked with -mywrapper
That's it :-)
Original post:
I'm writing a wrapper library that allows to call C++ functions out of C-code.
Unfortnuately it doesn't link...
wrapper.h:
#ifdef __cplusplus
extern "C"
{
#endif
extern char* (keygen) ();
#ifdef __cplusplus
}
#endif
wrapper.cpp:
#include "wrapper.h"
#include <someincludes>
char* keygen ()
{
urandom u;
Makefile:
TARGET := ./mywrapperlib.so
CXXFLAGS := -fPIC -shared -g -Wall -std=c++0x -I../someincludes -I.
CXX := g++
LIB := -lsomelibs
EXT := cpp
BUILDDIR := build
override BUILDDIR := $(strip $(BUILDDIR))
SOURCES := $(wildcard *.$(EXT))
OBJECTS := $(patsubst %.$(EXT), $(BUILDDIR)/%.o, $(SOURCES))
DEPS := $(patsubst %.$(EXT), $(BUILDDIR)/%.dep, $(SOURCES))
.PHONY: all
all: $(TARGET)
$(TARGET): $(OBJECTS) $(DEPS)
$(CXX) $(CXXFLAGS) -o $(TARGET) $(OBJECTS) $(LIBS)
ifneq ($(MAKECMDGOALS), clean)
-include $(DEPS)
endif
$(OBJECTS): $(BUILDDIR)/%.o: %.$(EXT) $(BUILDDIR)/%.dep $(BUILDDIR)/.tag
$(CXX) $(CXXFLAGS) -c $< -o $#
$(DEPS): $(BUILDDIR)/%.dep: %.$(EXT) $(BUILDDIR)/.tag
mkdir -p $(dir $(#))
$(CXX) $(CXXFLAGS) -MM $< -MT $# -MT $(<:.$(EXT)=.o) -o $#
%.tag:
mkdir -p $(dir $(#))
touch $#
.PHONY: clean
clean:
$(RM) -r $(BUILDDIR)
A test file that should use the library:
test.c:
#include <wrapper.h>
int main()
{
char* test = keygen();
}
When i try to compile it with
gcc -o test.a -g -Iinclude -Llib/mywrapperlib.so test.c
I get
/tmp/ccB9bEot.o: In function `main':
/some/paths/test.c:7: undefined reference to `keygen'
Im very unexperienced with mixing C & C++ code and writing libraries.
Now im stuck and hope that someone can help me with this problem.
EDIT:
I checked the lib with nm:
nm lib/cryptdbwrapperlib.so | grep keygen
0000000000006935 T keygen
So, i guess that the problem is the linkage...
It's to do with the order of your flags to gcc.
Do this:
gcc -o test.a -g -Iinclude test.c -Llib/mywrapperlib.so
# ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^
# first second
GCC reads libraries and objects left-to-right and (basically) ignores any that aren't needed "yet". With my proposed change, test.c goes first so GCC knows that it's going to be looking for a symbol keygen; then, when it finally sees -Llib/mywrapperlib.so it scans it for keygen, finds it, and knows that this library is required.
Change the function's signature in wrapper.cpp to
extern "C" char* keygen ()
Otherwise it will be compiled with a C++ style name, and hence be a different function than the one declared in the header.
I SOLVED THIS ISSUE BY MYSELF
The problem was the linkage of the library. I copied the libmywrapper.so(i renamed it) file to /usr/lib and linked with -mywrapper That's it :-)