I have written the following makefile:
CC=g++
all: happy
happy: happy.o HappyLetter.o
$(CC) -o happy happy.o HappyLetter.o
happy.o: happy.cpp
$(CC) -c happy.cpp
HappyLetter.o: HappyLetter.cpp
$(CC) -c HappyLetter.cpp
clean:
rm -rf *.o happy
and am working with the files HappyLetter.cpp and happy.cpp (which includes the former) to create an executable named happy.
I can build the code successfully using make. However, when I modify HappyLetter.cpp and type 'make' again, the change is not reflected. It only works when I type 'make clean' and then 'make'. The update of the object file that I expect to take place is echoed to the command line:
$ make
g++ -c HappyLetter.cpp
g++ -o happy happy.o HappyLetter.o
However, the update to HappyLetter.cpp is not being reflected in happy.
The problem does not work in the other direction. That is, if I modify happy.cpp, the change is reflected immediately after I type 'make'.
I have replicated this problem with three make binaries on my Mac OS X, and also on an Ubuntu machine. So I must be doing something wrong in the coding. Here is the text of the files, which are in the same directory as the makefile:
happy.cpp
#include "HappyLetter.cpp"
int main()
{
printf("Hello from happy.cpp!\n");
HappyLetter *myObj = new HappyLetter();
myObj->speak();
return 0;
}
HappyLetter.cpp
#include <cstdio>
class HappyLetter {
public:
void speak()
{
printf("Hello from HappyLetter.cpp!\n");
}
};
I believe the problem is something simple, but I have no more ideas about what to check. One assumption I have is that the ordering of the rules and dependencies does not matter.
As I commented:
First, you should (conventionally) not #include "HappyLetter.cpp" in your happy.cpp (even if that is doable but poor taste). You should have a separate header file (with the conventional include guard)
#ifndef HAPPY_INCLUDED
//// file happy.h
#define HAPPY_INCLUDED
class HappyLetter {
public:
void speak();
};
#endif /*HAPPY_INCLUDED*/
(You may -or not- decide to e.g. #include <cstdio> in your happy.h before the class HappyLetter; there are good reasons to do both ways!)
Then you should have a first source file:
// file happy.cpp
#include <cstdio>
#include "happy.h"
int main() {
printf("Hello from happy.cpp!\n");
HappyLetter *myObj = new HappyLetter();
myObj->speak();
delete myObj;
return 0;
}
BTW, you should use smart pointers!
Then you have your second source file:
// file happyletter.cpp
#include <cstdio>
#include "happy.h"
void HappyLetter::speak() {
printf("Hello from HappyLetter.cpp!\n");
}
At last, a Makefile (see here for inspiration), like:
# file Makefile
CXX= g++
CXXFLAGS= -std=c++11 -Wall -Wextra -g
RM= rm -f
.PHONY: all clean
all: happy-prog
clean:
$(RM) *.o *~ happy-prog
happy-prog: happy.o happyletter.o
happy.o: happy.cpp happy.h
happyletter.o: happyletter.cpp happy.h
Notice the explicit dependency on happy.h header
As I commented, consider using remake-x or make --trace to debug your Makefile. Notice that GNU make has a lot of built-in rules, run make -p to get them.
Read more about C++11, notably a tutorial, a good programming in C++ book, have a glance into the standard (e.g. n3337 draft). Read also about make, notably GNU make.
Study the source code of some existing free software coded in C++ (see sourceforge or github etc... to find one).
(so you got both your C++ source files and your Makefile wrong!)
Related
I'm building a project with a structure like this:
- Makefile
- main.cpp
- util.h
- subsrc/
- one.cpp
- two.cpp
And I have my Makefile set up to output to a build directory:
all: $(BIN_FILE)
$(BIN_FILE): $(OBJ_FILES)
mkdir -p $(BIN_DIR)
g++ $^ -o $#
$(OBJ_DIR)/%.o: %.cpp
mkdir -p $(OBJ_DIR)
g++ -c $^ -o $#
$(OBJ_DIR)/subsrc/%.o: subsrc/%.cpp
mkdir -p $(OBJ_DIR)/subsrc
g++ -c $^ -o $#
clean:
rm -rf $(BUILD_DIR)/*
However, I'm seeing this issue when I run g++ manually as well, so I don't think it's related to the Makefile.
I can build from clean and everything works fine. The issue is when I change one of the subsrc files and try to recompile, via make or by running these commands myself:
g++ -c subsrc/one.cpp -o build/obj/subsrc/one.o
g++ build/obj/main.o build/obj/subsrc/one.o build/obj/subsrc/two.o -o build/bin/prog
If I do this, changes made in one.cpp are not reflected in the binary output. If I recompile main.cpp (or, of course, the entire project), it works fine. This is not an issue of g++ not properly overwriting files, since even if I rm build/obj/subsrc/one.o and/or rm build/bin/prog before running the above commands, I still don't see the changes. That makes no sense to me and I have no idea what's happening.
EDIT: I have uploaded a minimum reproducible example here. https://github.com/scatter-dev/so_70242118_min_repro
Reproduction instructions:
Build using make or by running the g++ commands above.
Run the program to ensure it has built correctly.
Change the output of the doWork function in one.cpp. Save to disk.
Rerun make and note that the one.o file is recompiled and prog is recreated with the linker.
Run the program again and see that the output has not changed.
At the suggestion of a commenter, I checked the md5sum of one.o and prog between steps 1 and 4 and they are indeed both the same. This remains the case even if I delete one.o before recompiling. Yes, I am sure that one.cpp is being saved to disk (its md5sum does change, along with the fact that make clean && make will compile using the new changes).
Your problem is that your code is weirdly written and as a result, your makefile is incomplete.
In your main.cpp you have:
#include "subsrc/derived.h"
which is fine but in that header you have:
#include "one.cpp"
#include "two.cpp"
which is extremely bizarre. You pretty much never want to include .cpp files in other source files (or in header files). It's just a bad idea.
In this situation, ALL the content of your program is included into main.cpp and thus appears in your main.o file. Linking in the other objects (one.o and two.o) is useless and unnecessary: they are ignored.
In your makefile, however, you don't list one.cpp or two.cpp as prerequisites of main.o, which means that when you modify these source files main.o is not updated, and so nothing changes. If you remove main.o, then it is recompiled and you get the new behavior.
ETA
You have two options:
You can either put the declaration of the classes into derived.h and put the definition of the doWork() method into the .cpp files. That would look like this:
$ cat main.cpp
#include "subsrc/derived.h"
...
$ cat subsrc/derived.h
#include "../base.h"
class Derived1 : public Base {
public:
void doWork();
};
class Derived2 : public Base {
public:
void doWork();
};
$ cat subsrc/one.cpp
#include <iostream>
#include "derived.h"
void Derived1::doWork() {
std::cout << "I'm Derived1" << std::endl;
}
$ cat subsrc/two.cpp
#include <iostream>
#include "derived.h"
void Derived2::doWork()
{
std::cout << "I'm Derived2" << std::endl;
}
$ cat Makefile
...
$(OBJ_DIR)/main.o : base.h subsrc/derived.h
$(OBJ_DIR)/subsrc/one.o: base.h subsrc/derived.h
$(OBJ_DIR)/subsrc/two.o: base.h subsrc/derived.h
Or you can inline everything in a header file the way you're doing (but you really don't want to name these files with .cpp extensions, if they contain class declarations). Or you can just have one derived.h and throw away one.cpp and two.cpp altogether.
But you need to add the prerequisites in the makefile: if you keep multiple headers then main.o must depend on them.
I'm trying to compile a C++ test file, which is supposed to compile from files that are in adjacent folders in the project file structure. I have the following:
Project/TestFiles/makefile
Project/TestFiles/test.cpp
Project/OtherFiles/my_stuff.cpp
Project/OtherFiles/my_stuff.hpp
For the compile, I'm trying to leave the my_stuff.o file in the OtherFiles folder, so if I have other makefiles, they dont have to recompile separate versions each.
My makefile looks as follows:
CC = g++
CFLAGS = -std=c++11 -Wall -Wcomment -Werror -Wextra -Weffc++ -pedantic
run: test.out
test.out: test.cpp catchMain.cpp ../OtherFiles/my_stuff.o
$(CC) $(CFLAGS) $^ -o $#
my_stuff.o: ../OtherFiles/my_stuff.cpp ../OtherFiles/my_stuff.hpp
$(CC) $(CFLAGS) -c $<
I thought for a while that this setup worked, but then I started getting some weird problems and couldn't compile. For instance, having a static const map produced error: expected ';' after top level declarator. At first, Internet seemed to indicate that Mac compilers sometimes aren't able to compile static const maps with member initialisation lists (which it also complained about, if I removed the static const part). However, when I commented out everything to do with the std::map (leaving the makefile as described above) OR placed all files in the same folder (rewriting both the makefile as well as the #includes in test.cpp), everything is ok, but I'd like to use both std::maps AND the chosen file structure. Oh, and removing the extra warning flags doesn't work either.
Any ideas how I could do that?
Edit
my_stuff.hpp:
namespace my_stuff {
void function();
}
my_stuff.cpp:
#include "my_stuff.hpp"
#include <map>
namespace my_stuff {
static const std::map<char, char> the_map {{'a', 'b'}, {'c', 'd'}};
void my_function() {
// map stuff
}
}
The test part is both a vanilla catchMain.cpp:
#define CATCH_CONFIG_MAIN
#include "../../Catch2/catch.hpp" //which is outside the project specifics
and the actual tests, my_tests.cpp:
#include "../../Catch2/catch.hpp"
#include "../OtherFiles/my_stuff.hpp"
#include <map>
SCENARIO("", "") {
GIVEN("") {
WHEN("") {
THEN("") {
my_function();
// Other stuff
}
}
}
}
As #S.M. pointed out, you must change the my_stuff.o rule, but you must change the recipe as well as the target, so that it will actually build the thing you want:
../OtherFiles/my_stuff.o: ../OtherFiles/my_stuff.cpp ../OtherFiles/my_stuff.hpp
$(CC) $(CFLAGS) -c $< -o $#
More generally, you must understand the language before you attempt to manipulate it. Swapping patches in and out to see what works is a very inefficient way to write code.
So I have a straightforward problem.
I have files List.hpp, List.h, and test_list.cpp
List.hpp contains function definitions for the List.h file.
The List.h file includes "List.hpp" in the 3rd to last line.
test_list.cpp runs the program and includes "List.h" at the top.
I need a makefile that will compile these into an executable "project.x".
So far have this:
proj2: List.o test_list.o
gcc -o proj2.x List.o test_list.o
List.o:
gcc -c List.hpp
test_list.o:
gcc -c test_list.cpp
clean:
rm *.o proj2.x
However, it results in all kinds of errors, all dealing with lines that have List <T> in them, stating that List does not name a type. I think this is because I am not properly including the header file.
How would I make this makefile?
Judging by the filename extensions and your description, you're compiling C++ code.
You should thus use a C++ compiler: g++. gcc is a C compiler and doesn't know about C++.
You should really just let make compile your code for you, it knows what to do:
proj2: test_list.o
$(CXX) $(LDFLAGS) $(LDLIBS) -o $#
clean:
rm *.o proj2
You don't normally want to compile a header in isolation. It's intended to be included in a source file, and the source file is what you compile.
Given the implicit dependencies in a typical make utility, you can reduce your Makefile a little bit:
proj2.x: test_list.o
g++ -o proj2.x test_list.o
test_list.o: test_list.cpp List.hpp
clean:
-rm *.o proj2.x
At least assuming a reasonably recent version of Make, it'll already know how to compile a .cpp file to get a .o file.
If you're having compiler errors, chances are at least pretty fair that they stem from problems in the code, not in the Makefile. The obvious exceptions would be things like your C++ code failing to link properly, because you used gcc instead of g++ to link it.
As an aside, the header dependency shown in:
test_list.o: test_list.cpp List.hpp
...is something that gcc can generate automatically with the -MM flag. For a tiny Makefile like this one, it's probably not worthwhile to mess with generating dependencies automatically, but for a large one it can be worthwhile. You can even include this as a step in the Makefile itself by running gcc with -MM to generate the dependencies (directing the output to a file) and including that file into a Makefile that does the real work).
More about dependency generation and how to use it in a Makefile:
http://scottmcpeak.com/autodepend/autodepend.html
You don't compile .h or .hpp files. You only compile .c or .cpp files. You probably want something like(Indenting with tabs, not spaces, spaces is a SO and python thing, tabs are a makefile thing):
proj2: list.cpp list.hpp list.h
g++ -o proj2.x list.cpp
clean:
rm proj2.x
Also, in your C file, you will need:
#include "List.h" /* Note the quotes: *
#include <list.h> * won't work */
And likewise for your #include "List.hpp".
I've been given a package of files (one .cpp, and some .c and .h) and want to make some modifications. But right now I'm just trying to get the original version to compile (in Linux).
Here's a (really) minimal working example:
mainfile.cpp
extern "C"{
#include "auxfile.h"
}
int main(int argc, char * argv[]){
getfoo(temperature);
return 0;}
auxfile.h
#define PUBLIC
#define PRIVATE static
extern int temperature;
int getfoo( int inputint);
auxfile.c
#include "auxfile.h"
int temperature = 37;
PUBLIC int getfoo( int inputint){
return 7;
}
When I type
g++ mainfile.cpp
I get
mainfile.cpp(.text+0x11): undefined reference to `temperature'
mainfile.cpp(.text+0x18): undefined reference to `getfoo'
collect2: ld returned 1 exit status
For what it's worth, I've looked through numerous "undefined reference" questions and spent dozens of hours working on my own. The above code presents the essence of the problem. Any help would be massively appreciated. Thanks.
At the time of linking, all symbols (except those for dynamic linking, aka shared libraries) have to be defined. To create an object file with possibly unresolved symbols for later linking, there is the -c flag, that means just compile, do not link.
So, the following would work:
g++ -c -omainfile.o mainfile.cpp
gcc -c -oauxfile.o auxfile.c
g++ -o mainfile mainfile.o auxfile.o
Only the last line actually invokes the linker and as you have both object files, all symbols are found.
Just for completeness, in a real-world scenario you'd handle compiling and linking using make. Create a Makefile with the following contents:
OBJS:= mainfile.o auxfile.o
all: mainfile
# $# means what to build (in this case "mainfile"), $^ is replaced by all
# dependencies (here the contents of the variable OBJS)
mainfile: $(OBJS)
g++ -o$# $^
# pattern for *.cpp -> create a *.o file with same name using g++
%.o: %.cpp
g++ -c -o$# $<
# the same for *.c, but using gcc here
%.o: %.c
gcc -c -o$# $<
clean:
rm -f $(OBJS)
# "PHONY" are targets, that are not actually the names of output files
.PHONY: all clean
Then just type make and see the "magic" happening. Of course this is just for starters, no dependencies are tracked etc...
I'm trying to modify and compile uvccapture on the Raspberry Pi. I got the source from here (it's just a few files).
(I think) the only external files it needs are those of jpeglib which I downloaded from here.
When compiling, where do I put the jpeglib source files? UVCCapture has the following line:
#include <jpeglib.h>
Does that mean I should put the jpeglib source files in the same directory as the UVCCapture source files? That seems messy. How can I set up the compiler (modify the Makefile?), and where should I put the jpeglib files so that I don't need to change the uvccapture include file lines?
And a side question, how come it only includes the .h file and not the .c file? (I'm pretty new to C/C++)
Here is the Makefile:
CC=gcc
CPP=g++
APP_BINARY=uvccapture
VERSION = 0.4
PREFIX=/usr/local/bin
WARNINGS = -Wall
CFLAGS = -std=gnu99 -O2 -DLINUX -DVERSION=\"$(VERSION)\" $(WARNINGS)
CPPFLAGS = $(CFLAGS)
OBJECTS= uvccapture.o v4l2uvc.o
all: uvccapture
clean:
#echo "Cleaning up directory."
rm -f *.a *.o $(APP_BINARY) core *~ log errlog
install:
install $(APP_BINARY) $(PREFIX)
# Applications:
uvccapture: $(OBJECTS)
$(CC) $(OBJECTS) $(XPM_LIB) $(MATH_LIB) -ljpeg -o $(APP_BINARY)
Thanks
The source file (uvccapture.c) doesn't care where the header file (jpeglib.h) is -- at least it shouldn't. The compiler must be told where to look for header files; traditionally, the header files go in some directory like inc_files/, and the compiler is invoked with a command like
gcc -blah -blah -blah -Iinc_files -c -o uvccapture.o uvccapture.c
If you use Make, then Make should execute a command like that. So either edit the makefile, or put the header files in the current directory.
The sane way to use #include in C/C++ is to have source files and header files include header files. That is, in foo.c there will be a couple of lines like:
#include <bar>
#include "baz.h"
and in baz.h there might be a few lines like:
#include <vector>
#include "qux.h"
You almost never see #include foo.c, because it's almost never a good idea.