Makefile VPath force prerequisite compile - makefile

I'm trying to link a bunch of object files into a shared object. I specify the location of some of the object files which are located in a different directory using VPATH. If the .o file exists in that directory, then I get an error message that g++ cannot find the .o file. If I delete the object files in the other directory, then GNU Make / GCC compiles the .o in the current directory from the .c in the other directory specified by the VPATH. So how can I change my makefile so that the pre-requisite object files are always built in the current directory even if the object file exists in the other directory specified by the VPATH?
Here's my main make rule:
LD = g++ -g -shared
ALGOBJ = <a bunch of object files>
$(PROGRAM): $(ALGOBJ)
$(LD) -Wl,-soname -Wl,.so -Wl,--no-undefined $(LDPTHS) -o $(PROGRAM) $(ALGOBJ)

Related

Including a header from a parent directory

I have a situation where I am given a link to source directory which goes under the parent dir. The contents of the link cannot be modified. The link has a header and .c file. The header file includes a "Config.h" file. The Config.h can only reside in the parent dir because I cannot modify anything under the link. I have to use the sources in the link and compile the parent dir. Here is the directory structure.
ParentDir
|-TestSrc.c
|-TestSrc.h
|-Config.h
|-Makefile
|-LinkToSrcDir
|-Src.c
|-Src.h(#include "Config.h")
My makefile is very straightforward
CC = gcc
INC_DIR = -IParentDir -IParentDir/LinkToSrcDir
CFLAGS = -Wall -Wextra $(INC_DIR)
all: mybin
mybin: TestSrc.o Src.o
$(CC) $(CFLAGS) -o TestSrc.o Src.o
TestSrc.o: TestSrc.c
$(CC) $(CFLAGS) -c TestSrc.c
--- similar code for Src.o ----
Phony: clean (all the usual rm -f)
My problem is, since I cannot modify src.h, the make always complains that Config.h is not found(tried a few different ways). How do I write the Makefile to make src.h look for Config.h in parent dir?
The simplest way is to use a fully-qualified path for the compiler flags:
INC_DIR = -I$(CURDIR)/ParentDir -I$(CURDIR)/ParentDir/LinkToSrcDir
Just to be clear, when the compiler searches for header files using a relative path it always starts with the directory the source file appears in. It doesn't start with the working directory where the compiler is invoked.
From the GCC manual for example:
the preprocessor looks for header files included ... first relative to the directory of the current file
In your case, the current file is LinkToSrcDir/Src.h so all paths will be expanded relative to the directory LinkToSrcDir.
When you say a link above I assume you mean a symbolic link. In that case you may not be able to use something like -I.. because that will give you the parent of the directory linked to.
You pretty much have no alternative but to use a fully-qualified path in your -I options.

Run two instances of the same C++ program simultaneously

I've got a C++ program with a Makefile, building (g++) and running on Windows cmd. Thing is, sometimes it takes a while to run and save the results, and I want to run it with different parameters at the same time so that I can do something else while I wait for the first instance to finish. It doesn't work though, because of the executable I guess:
>make
g++ -c -o main.o main.cpp
Assembler messages:
Fatal error: can't create main.o: Permission denied
make: *** [main.o] Error 1
You have two problems: The one you ask about, and the reason you ask this question in the first place.
Lets start with the problem you have...
Judging by the Makefile you show, you have it all wrong.
Rules are in the format
target: sources_the_target_depend_on
The target is usually a file that need to be created. For an object file that is the name of the actual object file itself. The source files that the object files then depend on should be on the right-hand side.
To take an example from you Makefile (before you edited it away):
graph2: graph2.o
g++ -g -c graph.cpp -o graph2.o
Here you tell make that the file graph2 depends on the file graph2.o, and then it creates the graph2.o file. That's wrong. The rule should be that the file graph2.o depends om the file graph.cpp and go on to generate the file graph2.o:
graph2.o: graph.cpp
g++ -g -c graph.cpp -o graph2.o
This indirectly leads to the problem you have, with this line (deduced from your error and the Makefile):
main: main.o utils.o graph.o heuristics.o
g++ -g main.cpp -o main.o utils.o graph.o heuristics.o
This contains the same error as discussed above: You say that the file main depends on main.o and then the rule create main.o. Your rule should be
main: main.cpp utils.o graph.o heuristics.o
g++ -g main.cpp -o main utils.o graph.o heuristics.o
Note also how I no longer name the executable file main.o, as that is supposed to be used for object files.
Now lets continue with the reason you have the problem in the first place: That you need to edit the code to change data or values.
This is a problem that you need to solve. One common way to solve it is through command line arguments. If your program parses the command line arguments passed to your program you can pass it the values that could change from run to run.
How to do this is whole chapter on its own, so I wont give you any more details. There are plenty of tutorials online.
Lastly, you can simplify your Makefile considerably, by using implicit rules and variables.
I would simply create the Makefile to look something like this
# The compiler to use
CXX = g++
# Flags to pass to the compiler (add warnings when building)
CXXFLAGS = -Wall
# The main executable file to generate
TARGET = main
# List the object files needed to generate the main executable file
OBJECTS = main.o utils.o graph.o heuristics.o
# The all target depends on your main executable file
# Also as the first target in the Makefile, if no specific target is specified
# this will be the one that is used (it's the "default" target for the Makefile)
all: $(TARGET)
# The main executable file depends on the object files
$(TARGET): $(OBJECTS)
This is really it. the object files will be built automatically from their respective source files, and then the executable program will be linked using the object files listed.

GNU make in newly created subdirectory

First - I know there are a lot of discussions similar to this, but I've spent hours without them working for me.
My makefile first creates a directory named by the current date and time. I then have the makefile append to a header file a line which creates a string with this directory name. For this reason, I first need to copy all the source files (including the header) into the newly created subdirectory, so that I can preserve the original header and only modify the header (in the subdirectory) which will be used for compilation. I would then like to build in that new directory.
My trouble is getting make to properly build the .o files in the new subdirectory. The solution I've found is to have
$(NOW)%.o: $(NOW)%.cpp
$(CC) -c $(FLAGS) $<
where $(NOW)$ is the subdirectory name. The issue is that my $(FLAGS) seem to be ignored: the output is, roughly
g++ -c -o <.o file> <.cpp file>
(Yes, there is actually extra introduced space between g++ and -c.) Whereas building in the top level directory a la
%.o: %.cpp
$(CC) -c $(FLAGS) $<
correctly outputs
g++ -c <my flags> -o <.o file> <.cpp file>
To summarize, I am unable to compile normally by transferring the source files to a newly-created subdirectory and building the .o files in that directory. TYIA.
Ad John points out, there's no way to definitively diagnose your problem with the tiny bit of makefile you provided, because the error is not in the code you provided, it's in some other part of your makefile. You need to provide a SSCCE ideally, but if not that then at least we need to see how the NOW variable is set and the linker rule so we know what make is trying to build.
I should also point out that by convention you should not use CC to hold the C++ compiler; the CC variable holds the C compiler. Use CXX for the C++ compiler and CXXFLAGS for the C++ compiler flags.
One possibility is that you are assigning the NOW variable using a recursive assignment so that the timestamp is recreated every time the variable is evaluated; it could be that the timestamp changes over the lifetime of the makefile.
The other very common problem is that you created the pattern rule, but make is not using it because the targets make wants to build don't match the pattern.
So for example, if your link line looks like this:
SRCS = foo.cpp
OBJS = $(SRC:.cpp=.o)
myprog: $(OBJS)
$(CXX) ...
$(NOW)%.o : $(NOW)%.cpp
$(CXX) ...
then your pattern will not be matched because make is trying to build the file foo.o and your rule tells it how to build $(NOW)foo.o which are not the same thing.

Including custom header files (ANSI C)

I have made some header files and placed them in the same folder as the main program, but the compilation command gcc -ansi -Wall *.c cannot find those files. Do I have to include the full directory path of the header files or am I doing something else wrong?
First of all you have to include the header files into the relevant C-files if you haven't already done so as such:
#include "path/to/file.h"
You also have to tell the compiler to compile the .h-files so if your .h-files are in the same foder as you .c-files and you want to include all the present .h-files your compiler command would look like this:
gcc -ansi -Wall *.h *.c

makefile how can I generate obj files in a subfolder?

I want to generate my obj files in a subfolder, I have tried this:
lib/*.o: source/*.cpp
clang++ $(CC_FLAGS) -c -Iinclude source/*.cpp
But it still generates the obj files in the project root and not in the lib/
The project tree that I'm trying to have:
Project/
source/(cpp files)
include/(header files)
lib/(obj files)
You don't show your current makefile, but my suspicion is that it's wrong. However as we can't see it, we'll leave that alone.
The compiler does not support writing multiple object files to a different directory. If you pass multiple source files along with the -c flag then it will write out multiple object files but only to the current directory... as you've discovered the -o flag can't be specified on compile lines which generate multiple output files.
You can change your recipe to look like this:
cd lib && clang++ $(CC_FLAGS) -c -I../include ../source/*.cpp
this will cause all the object files to be written to the lib directory because it's now the current directory.
However, putting this into a makefile is not simple, because make itself is designed to have a single recipe create a single target. However you have this problem with your existing makefile which you don't show, as well.

Resources