Single Makefile to build both main.c and main.cpp - c++

I would like to make main-c to build main-c from main.c.
And make main-cpp to build main-cpp from main.cpp.
I have, all in the same folder:
main.c:
#include <stdio.h>
int main(int argc, char const *argv[]) {
printf("This ic C\n");
}
main.cpp:
#include <iostream>
int main(int argc, char const *argv[]) {
std::cout << "This is C++" << std::endl;
}
Makefile:
CFLAGS = -std=gnu11
CXXFLAGS = -std=gnu++11
CPPFLAGS = -g -Wall -O3
LDFLAGS =
LDLIBS =
OBJS = main.o
APP-C = main-c
APP-CPP = main-cpp
default:
echo "Check README.txt"
main-c: $(OBJS)
$(CC) $^ $(LDLIBS) -o $#
main-cpp: $(OBJS)
$(CXX) $^ $(LDLIBS) -o $#
clean:
-rm -Rf *.o
distclean: clean
-rm -Rf $(APP-C) $(APP-CPP)
So:
$ make main-c
cc -std=gnu11 -g -Wall -O3 -c -o main.o main.c
cc main.o -o main-c
But (also builds from .c):
$ make main-cpp
cc -std=gnu11 -g -Wall -O3 -c -o main.o main.c
c++ main.o -o main-cpp
I was expecting make main-cpp to use $(CXX) $^ $(LDLIBS) -o $# and build from .cpp. What am I missing?

I was expecting make main-cpp to use $(CXX) $^ $(LDLIBS) -o $# and build from .cpp.
It is. make main-cpp --debug will help you see what is going on.
The problem is you are relying on the default rule for making the main.o needed by both main-cpp and main-c target, but you want a different build when make-cpp target is invoked. In this case you'll need to define different non default rules to build the .o files. It's easiest if you just make make-cpp and main-c depend on a .o with a different name. Since they are different builds they should have different names anyway:
CFLAGS = -std=gnu11
CXXFLAGS = -std=gnu++11
CPPFLAGS = -g -Wall -O3
LDFLAGS =
LDLIBS =
APP-C = main-c
APP-CPP = main-cpp
default:
echo "Check README.txt"
main-c: %:%.o
$(CC) $^ $(LDLIBS) -o $#
main-cpp: %:%.o
$(CXX) $^ $(LDLIBS) -o $#
main-cpp.o: main.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $? -o $#
main-c.o: main.c
$(CC) $(CPPFLAGS) $(CFLAGS) -c $? -o $#
clean:
-rm -Rf *.o
distclean: clean
-rm -Rf $(APP-C) $(APP-CPP)

Both rules, main-c and main-cpp, require main.o to be created to complete, but you don't have a rule for creating main.o.
You're using make's implicit object file creation which is a built-in rule for creating a '.o' file from a source file. It can use either a '.c' or '.cpp/cc/C' file and will build using the appropriate variables. However, since you have both main.c and main.cpp, it looks like it defaults to using the C version.
You'd probably need to create explicit rules (and probably use different names) for each one.

Related

Im working on a makefile which should build a library and then also include that library when building the entire program

INC_DIR = ./include
SRC_DIR = ./src
OBJ_DIR = ./obj
SRC_FILES = $(wildcard $(SRC_DIR)/*.cpp))
H_FILES = $(wildcard $(INC_DIR)/*.cpp)
OBJ_FILES=$(patsubst $(SRC_DIR)/%.cc,$(OBJ_DIR)/%.o,$(SRC_FILES)
TARGET = PT3
CC = g++
CFLAGS = - fPIC -c -Wall -Werror -pedantic -std=c++11 -Wno-c++11-extensions
CPPFLAGS = $(addprefix -I, $(INC_DIR))
clean:
rm -f $(OBJECTS) $(TARGET)
all: $(TARGET)
$(TARGET): $(OBJECTS)
$(CC) $(CFLAGS) $(CPPFLAGS) -o $# $^
%.o: %.cc
$(CC) $(CFLAGS) $(CPPFLAGS) -o $# -c $<
g++ -shared -fPIC -o libtest.so $(OBJECTS)
main.o: main.cc
$(CC) $(CFLAGS) $(CPPFLAGS) -L/pt3/lib -o maintest main.cc -libtest
this is currently what I have and i know its not syntactically right or remotely working but Im getting stuck on creating the shared library so I dont even know what else wouldnt compile.**
INC_DIR = ./include
SRC_DIR = ./src
SRC_FILES = $(sort $(shell find $(SRC_DIR) -name '*.cc'))
OBJ_FILES = $(SRC_FILES:.cc=.o)
TARGET = PT3
CC = g++
CFLAGS = -fPIC -Wall -Werror -pedantic -std=c++11 -Wno-c++11-extensions
CPPFLAGS = $(addprefix -I, $(INC_DIR))
#clean:
# rm -f $(OBJECTS) $(TARGET)
all: $(TARGET)
$(TARGET): $(OBJ_FILES)
$(CC) $(CFLAGS) $(CPPFLAGS) -o $# $^
%.o: %.cc
$(CC) $(CFLAGS) $(CPPFLAGS) -o $# -c $<
libtest.so: $(OBJ_FILES)
$(CC) -shared -fPIC -o $# $^
maintest: main.o libtest.so
$(CC) $(CFLAGS) $(CPPFLAGS) -L. -o maintest main.o -libtest
this is what i rewrote the code to however Im getting a no input files error, but Im not sure if thats coming from a wrong read / failure to get into the required folders, or due to possibly missing a -o or -c?
Ive worked on the code some more following the suggestions and have come to this:
CXX = g++
CXXFLAGS := -Wall -Werror -pedantic -std=c++11 -Wno-c++11-extensions
SRC_FILES = $(wildcard $(SRC_DIR)/*.cpp)
OBJECTS=$(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(SRC_FILES))
INC_DIR = include
SRC_DIR = src
OBJ_DIR = obj
TEST_DIR = tests
LIB_DIR = lib
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
$(CXX) $(CXXFLAGS) -fPIC -Iinclude -o $# -c $<
clean:
rm -f $(OBJECTS) $(TEST_DIR)/main.o
$(LIB_DIR)/libtest.so: $(OBJECTS)
#echo frank
$(CXX) -shared -fPIC -o $# $^
$(TEST_DIR)/main.o: $(TEST_DIR)/main.cc
$(CXX) $(CXXFLAGS) -Iinclude -o $# -c $<
maintest: $(TEST_DIR)/main.o $(LIB_DIR)/libtest.so
$(CXX) $(CXXFLAGS) -Llib -Iinclude -o $# $< -ltest
everything seems to compile fine however when running the maintest program it returns an error saying: error while loading shared libraries: libtest.so: cannot open shared object file: No such file or directory
thanks for the suggestions so far I feel like Im on the verge of actually getting the makefile working as intended
You've already written the recipe for the library (which builds it in the working directory -- we can change that later if you want):
g++ -shared -fPIC -o libtest.so $(OBJECTS)
The next step is to put it into a rule:
libtest.so: $(OBJECTS)
g++ -shared -fPIC -o libtest.so $(OBJECTS)
Then clean it up:
libtest.so: $(OBJECTS)
g++ -shared -fPIC -o $# $^
It looks as if you want the executable to be maintest, so let's write a rule for that:
maintest: main.o libtest.so
$(CC) $(CFLAGS) $(CPPFLAGS) -L. -o maintest main.o -ltest
Give that a try. We can make further adjustments once that much works.
EDIT: I see that there are a few other problems in your makefile. Your variables won't work as written. Do you name your source files "foo.cc" or "foo.cpp"?
EDIT: I can see that we'll have to do this in stages.
Step 1. Try this:
CXX = g++
CXXFLAGS := -Wall -Werror -pedantic -std=c++11 -Wno-c++11-extensions
INC_DIR = include
SRC_DIR = src
OBJ_DIR = obj
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
$(CXX) $(CXXFLAGS) -Iinclude -o $# -c $<
Try to build one or two object files with this, as in make obj/foo.o.
Step 2. Add a rule for main.o, and test it:
$(OBJ_DIR)/main.o: main.cc
$(CXX) $(CXXFLAGS) -Iinclude -o $# -c $<
Step 3. Add a "do nothing" rule for the library, and verify that it builds all of the objects:
SRC_FILES = $(wildcard $(SRC_DIR)/*.cpp)
OBJECTS=$(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(SRC_FILES))
libtest.so: $(OBJECTS)
#echo doing nothing
Step 4. Change the library rule to actually build the library:
libtest.so: $(OBJECTS)
$(CXX) -shared -fPIC -o $# $^
Step 5. Add a rule to build the test:
maintest: main.o libtest.so
$(CXX) $(CXXFLAGS) -L. -o $# $< -ltest

no rule to make target 'Main.o', needed by 'Main' . Stop

Note: Unlike other Questions, this one is missing an obj file instead of a cpp file
I have a Directory called /Profiler
that got the following files:
Main.cpp
Draw.cpp
Draw.h (used in both cpp files)
Makefile
I created the following Makefile:
CC := g++
CCOPTS=-Wall -Wextra -O3 -std=c++17
Main_DEP_OBJ := Main.o Draw.o
Header:=Draw.h
all: main
%.o: %.C DEPS $(Header)
$(CC) ${CCOPTS} -c -o $# $<
Main: $(Main_DEP_OBJ)
${CC} ${CCOPTS} -o main $^
clean:
rm -f Main *.o
using the make command in Ubuntu gives me this error:
no rule to make target 'Main.o', needed by 'Main' . Stop.
You dont have a target rule for Main, or building .o file from the .cpp file.
CC := g++
CCOPTS=-Wall -Wextra -O3 -std=c++17
Main_DEP_OBJ := Main.o Draw.o
Header:=Draw.h
all: Main
%.o: %.cpp $(Header)
$(CC) ${CCOPTS} -c -o $# $<
Main: $(Main_DEP_OBJ)
${CC} ${CCOPTS} -o Main $^
clean:
rm -f Main *.o

GCC linking a static library

I have seen questions like these on SO but everyone has different answers and directory structures that aren't working for me.
My makefile:
CC = g++
DEBUG = -g -std=c++11
TARGET = main
OBJECT_FILES = BingResultSet.o main.o
INC_PATH = -I HTTPClientLib/include
LIB_PATH = -L HTTPClientLib/lib/
start: clean BingResultSet.o main.o
$(CC) $(DEBUG) $(INC_PATH) $(LIB_PATH) $(OBJECT_FILES) -o $(TARGET)
rm -f *.o
BingResultSet.o: BingResultSet.cpp BingResultSet.h
$(CC) $(DEBUG) $(INC_PATH) $(LIB_PATH) -c BingResultSet.cpp
main.o: main.cpp
$(CC) $(DEBUG) $(INC_PATH) $(LIB_PATH) -c main.cpp
clean:
rm -f $(OBJECT_FILES) $(TARGET)
My file structure:
/Desktop/DataMiner/.cpp, .h, and makefile
/Desktop/DataMiner/HTTPClientLib/include/HTTPClient.h
/Desktop/DataMiner/HTTPClientLib/lib/HTTPClient.a
What's the correct way to link my static lib in my makefile?
Here's my $0.02:
there was no static library involved. Assuming you meant the .o files
you mix dependencies and build rules, instead, avoid repeating build rules:
$(TARGET): $(OBJECT_FILES)
$(CXX) $(DEBUG) $(INC_PATH) $^ -o $# $(LIB_PATH)
%.o: %.cpp
$(CXX) $(DEBUG) $(INC_PATH) -c $< -o $#
You used CC for a C++ compiler. That's strange. Use CXX
You used LDFLAGS when you were just compiling
You hardcoded the source and destination paths. Instead use the automatic variables ($^, $< for source; $# for destination)
You tried to hardcode header dependencies. That's error-prone and messes up source specification (you don't want $^ to list .h files in your command line...). Instead, use gcc -MM¹ to generate the dependencies for you!
Next, do a conditional include of those dependencies:
.depends:
$(CXX) -MM $(CXXFLAGS) -c *.cpp > $#
-include .depends
It's usually handy to keep the .o files so you can speed up builds. Of course, this was not a good plan until you generated the header dependencies automatically. If you insist, you can comment the .PRECIOUS target. Intermediate targets are automatically deleted by GNU Make
Here's the integrated offering I ended up with:
CXX = g++
TARGET = main
OBJECT_FILES = BingResultSet.o main.o
INC_PATH = -I HTTPClientLib/include
LIB_PATH = -L HTTPClientLib/lib/
CPPFLAGS = -g -std=c++11
CPPFLAGS+= $(INC_PATH)
# standard derived flags:
CXXFLAGS+=$(CPPFLAGS)
LDFLAGS+=$(LIB_PATH)
start: .depends $(TARGET)
$(TARGET): $(OBJECT_FILES)
$(CXX) $(CXXFLAGS) $^ -o $# $(LDFLAGS)
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $#
clean:
rm -f .depends $(OBJECT_FILES) $(TARGET)
# to keep the .o files:
.PRECIOUS: $(OBJECT_FILES)
.depends:
$(CXX) -MM $(CXXFLAGS) -c *.cpp > $#
-include .depends
On a very simple sample set of files you get:
$ make clean
rm -f .depends BingResultSet.o main.o main
$ make
g++ -MM -g -std=c++11 -I HTTPClientLib/include -c *.cpp > .depends
g++ -I HTTPClientLib/include -c BingResultSet.cpp -o BingResultSet.o
g++ -I HTTPClientLib/include -c main.cpp -o main.o
g++ -I HTTPClientLib/include BingResultSet.o main.o -o main -L HTTPClientLib/lib/
$ cat .depends
BingResultSet.o: BingResultSet.cpp BingResultSet.h
main.o: main.cpp BingResultSet.h
test.o: test.cpp
¹ (or similar, see man-page)

make objects in Makefile

I have the following Makefile:
CXX = g++
CXXFLAGS = -Wall -g
SOURCES := divisor.cpp multiplier.cpp
OBJECTS := ${SOURCES:.cpp=.o}
%.o: %.cpp
$(CXX) -c $(CXXFLAGS) $< -o $#
%: %.o $(OBJECTS)
$(CXX) $(CXXFLAGS) $#.o -o $#.out
$(OBJECTS): %.o: %.cpp
$(CXX) -c $(CXXFLAGS) $< -o $#
clean:
rm -f *.o
What I want this make file is the following:
If I add a source file called 123.cpp to the working directory, I want it to generate its object file and then link the compiled sources specified in $(SOURCES), this means:
g++ -c -Wall -g 123.cpp
g++ multipler.o divisor.o 123.o -o 123
If multiplier.cpp or divisor.cpp has to be generated or updated, I want make to do it.
But I'm failing, because divisor.o and multiplier.o are not automatically generated
How may I achieve this?
Edit
Just to clarify, there are two types of source code files in the working directory: divisor.cpp, multipler.cpp is one type, and any other file, say, 123.cpp is the other type. In a sense, divisor.cpp and multiplier.cpp are requisites to the other source files.
I want to automate the process of compiling the prerequisites and link them when compiling the other files
g++ -c multiplier.cpp
g++ -c divisor.cpp
g++ -c -Wall -g 123.cpp
g++ multipler.o divisor.o 123.o -o 123
Use the wildcard function:
SOURCES := $(wildcard *.cpp)
Then, you can remove your "special" source files:
SPECIAL_SOURCES := divisor.cpp multiplier.cpp
SOURCES := $(filter-out $(SPECIAL_SOURCES),$(SOURCES))
And change your rules to build the stuff you actually want:
$(SPECIAL_OBJECTS) := $(SPECIAL_SOURCES:.cpp=.o)
$(BINARIES) := $(patsubst .cpp,,$(SOURCES))
$(SPECIAL_OBJECTS) : %.o : %.cpp
$(CXX) $(CXXFLAGS) -c -o $# $^
$(BINARIES) : % : %.cpp $(SPECIAL_OBJECTS)
$(CXX) $(CXXFLAGS) -o $# $^

Linker input file unused c++ g++ make file

I am unable to figure out what is causing this error that I keep getting upon making my project:
i686-apple-darwin11-llvm-g++-4.2: -lncurses: linker input file unused because linking not done
And my make file looks like this:
CC = g++
LIB_FLAGS = -l ncurses
FLAGS = $(LIB_FLAGS)
DEPENDENCIES = window.o element.o
# FINAL OUTPUTS
main: main.cpp $(DEPENDENCIES)
$(CC) $(FLAGS) -o main.out main.cpp $(DEPENDENCIES)
# MODULES
window.o: main.h classes/window.cpp
$(CC) $(FLAGS) -c classes/window.cpp
element.o: main.h classes/element.cpp
$(CC) $(FLAGS) -c classes/element.cpp
# CLEAN
clean:
rm -rf *.o
rm main.out
Everything compiles okay, but I'm just curious what is causing this error message and what it means..
You are passing linker options to a compiler invocation together with -c, which means that linking is not performed and thereby -l options are unused. In your case, your LIB_FLAGS should not be in FLAGS, but instead specified in the the main: ... rule:
main: main.cpp
$(CC) $(FLAGS) $(LIB_FLAGS) ...
Do not give link flags when you compile (-c flag) your source files. Take a look for this example makefile (very similar as in makefile docs)
CPP = g++
CPPFLAGS =-Wall -g
OBJECTS = main.o net.o
PREFIX = /usr/local
.SUFFIXES: .cpp .o
.cpp.o:
$(CPP) $(CPPFLAGS) -c $<
.o:
$(CPP) $(CPPFLAGS) $^ -o $#
main: $(OBJECTS)
main.o: main.cpp
net.o: net.cpp net.h
.PHONY:
install: main
mkdir -p $(PREFIX)/bin
rm -f $(PREFIX)/bin/main
cp main $(PREFIX)/bin/main
clean:
rm -f *.o main
As has been mentioned already you're passing linker-related flags at the compile stage. Usually you want different flags for compiling and linking, e.g.
CC = g++
CPPFLAGS = -Wall -g -c -o $#
LDFLAGS = -l ncurses -o $#
DEPENDENCIES = main.o window.o element.o
# FINAL OUTPUTS
main: $(DEPENDENCIES)
$(CC) $(LDFLAGS) $(DEPENDENCIES)
# MODULES
main.o: main.h main.cpp
$(CC) $(CPPFLAGS) main.cpp
window.o: main.h classes/window.cpp
$(CC) $(CPPFLAGS) classes/window.cpp
element.o: main.h classes/element.cpp
$(CC) $(CPPFLAGS) classes/element.cpp
# CLEAN
clean:
-rm main $(DEPENDENCIES)