Makefiles are quite confusing to me. I am attempting to "make" my project that I have worked on in Windows. The confusing part is actually constructing the make file from scratch. I would am trying to also link to the SDL2 library, and that is in a '.a' format.
Here is my code for the make file so far, I have tried multiple versions, and this is the latest:
CXX = gcc
OUT = Engine
SRC =Software-Rendering/src/
SDL_INCLUDE_DIR =Software-Rendering/lib/SDL2/include/SDL/
LIB_DIR =Software-Rendering/lib/SDL2/x86/linuxLib/
SDL = -l${LIB_DIR}libSDL -l${LIB_DIR}/libSDL2main
CPP_FILES =Bitmap.cpp Main.cpp Vector3.cpp Window.cpp
H_FILES =Bitmap.h ErrorReport.h Vector3.h Window.h
O_FILES = Bitmap.o ErrorReport.o Main.o Vector3.o Window.o
all: $(OUT)
$(OUT): $(O_FILES)
$(CXX) -o $# $^ ${SDL}
#Making all of the object files down
$(O_FILES): $(H_FILES)
$(CXX) -c $(CPP_FILES)
#Make sure we can easily clean up the directory
clean:
rm -f Engine ${O_FILES}
clean_obj:
rm -f ${O_FILES}
I decided to put the ".a" files in a special directoy in my project so whenever someone clones my repository on github all of the files for compiling and linking are already there.
Why isn't this working and how can I make it work?
Your library linking directive are wrong -- -l prefixes lib to the name you specify, and then searches through the libdir path set by the -L options. So what you want is something like:
SDL = -L$(LIB_DIR) -lSDL -lSDL2main
You can make it clearer/more standard by using the standard varnames for libraries:
LDFLAGS = -L$(LIB_DIR)
LDLIBS = -lSDL -lSDL2main
$(OUT): $(O_FILES)
$(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $#
Also, get rid of the explicit command to compile source files -- the default built in rule is fine and easier to use.
Related
I am trying to statically link libssh to my project which is built using a mingw/mysys makefile, however no matter what I try I get a whole bunch of undefined reference errors. I've spent hours researching this but I still can't fix it. Below is my makefile and some example output. I also compiled the libssh.a file using cmake with the WITH_STATIC_LIB option set to 1. I don't understand how I can continue to get these errors even though my linker can find the libssh.a file. Did I build it incorrectly?
Example output:
c:/mingw/bin/../lib/gcc/mingw32/8.2.0/../../../../mingw32/bin/ld.exe: build/BMU.o: in function `ZN3ssh7SessionC1Ev':
./include/libssh/libsshpp.hpp:130: undefined reference to `_imp__ssh_new'
.
.
.
Makefile
CC := g++
TARGET := "dist/target"
BUILDDIR := build
SRCDIR := src
CFLAGS := -std=c++17 -g -mconsole
SRCEXT := cpp
SOURCES := $(wildcard $(SRCDIR)/*.$(SRCEXT))
OBJECTS := $(patsubst $(SRCDIR)/%, $(BUILDDIR)/%, $(SOURCES:.$(SRCEXT)=.o))
INCLUDE := -I./include
LIB := -L./lib -lws2_32 -lssh -lmodbus -static
$(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT)
#printf "\e[33m\e[1mBuilding...\e[0m\n";
#mkdir -p $(BUILDDIR)
#echo " $(notdir $#) from $(notdir $<)"
#$(CC) $(CFLAGS) $(INCLUDE) -c -o $# $<
$(TARGET): $(OBJECTS)
#printf "\e[35m\e[1mLinking...\e[0m\n";
#mkdir -p dist
#echo " $(notdir $(OBJECTS))"
#$(CC) $(CFLAGS) -o $# $^ $(LIB)
Building Libssh:
First I did
git clone https://git.libssh.org/projects/libssh.git libssh
then using cmake-gui built it for MySys makefile with 'WITH_STATIC_LIB" set to 'ON' and 'WITH_SHARED_LIB' to 'OFF'
Then I ran make from my terminal and it created a libssh.a file which I moved to the ./lib folder in my project.
The make file was able to find the libssh.a file but I still got these errors.
Any help is appreciated and yes I looked a tons of other stackoverflow posts before posting myself.
Other things I tried
#define LIBSSH_STATIC 1 and without it
using vcpkg to install libssh, but this generates a .lib file which has the same problems as the .a file
Edit:
Including LIBSSH_STATIC causes the output to look like:
c:/mingw/bin/../lib/gcc/mingw32/8.2.0/../../../../mingw32/bin/ld.exe: ./lib\libssh.a(channels.c.obj):channels.c:(.text+0x1979): undefined reference to `_imp__ssh_buffer_add_data'
The correct CMake parameter for building static libraries (including for libssh) is -DBUILD_SHARED_LIBS:BOOL=OFF
As long as you're seeing _imp__ in the undefined reference to errors your linker is looking for the symbols exported from a shared library (DLL).
To make sure the project that uses libssh looks for the static library you must define LIBSSH_STATIC, for example by adding compiler flag -DLIBSSH_STATIC to CFLAGS in your Makefile.
I read a good tutorial about makefiles, but got a bit confused when things became more complex.
I restructured my workspace Folder and added subfolder: Here is an image of my workspace folder:
I tried to edit the makefile, but still don't succeed making it compile my files.
Do I only need to declare header files in make files or do I need both, header and cxx files?
In the makefile I declared how to build a release and a debug build. I tried to say: create the debug .o files in the debug folder and link them together in debug to an executable called exefile. Since I added the subfolders include and src this got messed up and I do not know how to edit the makefile properly now.
Here is the code of the makefile:
#Compiler Flags#
CC = g++
CFLAGS = -Wall -Werror -Wextra
HDIR = include
#Project Files#
SRCS = src/main.cxx src/ex05_01.cxx src/ex05_02.cxx
OBJS = $(SRCS:.cxx=.o)
EXE = exefile
#Debug Build Settings#
DBGDIR = debug
DBGEXE = $(DBGDIR)/$(EXE)
DBGOBJS = $(addprefix $(DBGDIR)/, $(OBJS))
DBGCFLAGS = -g -O0 -DDEBUG
#Release Build Settings#
RELDIR = Release
RELEXE = $(RELDIR)/$(EXE)
RELOBJS = $(addprefix $(RELDIR)/, $(OBJS))
RELFLAGS = -g -O0 -DNDEBUG
.PHONY: all clean debug prep release remake
#default build
debug: $(DBGEXE)
$(DBGEXE): $(DBGOBJS)
$(CC) $(CFLAGS) $(DBGCFLAGS) -o $(DBGEXE) $^
$(DBGDIR)/%.o: %.cxx
$(CC) -c $(CFLAGS) $(DBGCFLAGS) -o $# $<
# Release rules
release: $(RELEXE)
$(RELEXE): $(RELOBJS)
$(CC) $(CFLAGS) $(RELCFLAGS) -o $(RELEXE) $^
$(RELDIR)/%.o: %.cxx
$(CC) -c $(CFLAGS) $(RELCFLAGS) -o $# $<
# Other rules
prep: mkdir -p $(DBGDIR) $(RELDIR)
remake:
clean all
clean:
rm -f $(RELEXE) $(RELOBJS) $(DBGEXE) $(DBGOBJS)
Thank you for your help!
EDIT: I forgot to post the error message of make:
*** No rule to make target debug/main.o', needed bydebug/exefile'. Stop.
You should include rules for the header file dependencies as well. Assuming that main.cxx depends on ex05_01.h, when ex05_01.h changes, you would want main.cxx to be recompiled. Something like this would do the job:
main.o: ex05_01.h ... (add more headers if you have)
(repeat for all .o files)
Your debug and release builds only differ by a few things: an output folder DIR and a DEBUG/NDEBUG define flag in FLAGS. To avoid duplicating all the settings, you could refactor and make common targets, and then switch between your settings with a conditional over a variable, for example, if you run make like so:
make BUILD=REL <target>
you will get a variable BUILD defined with "REL" value, then you can use ifeq (see https://www.gnu.org/software/make/manual/html_node/Conditional-Example.html#Conditional-Example ) to set your DIR and FLAGS accordingly.
For this reason I downloaded the C++ library VTK and made a local build in the build subdirectory on a OSX environment.
I would like to compile a project using this library (particularly I am using the class vtkSmartPointer) with Makefile.
Consider for example the following source code:
#include<iostream>
#include<vtkSmartPointer.h>
#include<vtkCallbackCommand.h>
int main()
{
vtkSmartPointer<vtkCallbackCommand> keypressCallback =
vtkSmartPointer<vtkCallbackCommand>::New();
std::cout<<"hello world\n";
return 0;
}
For the Makefile I started from the second answer in this post to which I aded VTK library path:
CXX = g++
# OpenCV trunk
CXXFLAGS = -std=c++11 \
-I ../VTK/Common/Core/ -I ../VTK/build/Common/Core/ -I ../VTK/build/Utilities/KWIML/ \
-I ../VTK/Utilities/KWIML/ \
-L../VTK/build/lib \
-lvtkCommon -lvtkFiltering -lvtkImaging -lvtkGraphics -lvtkGenericFiltering -lvtkIO
SOURCES := $(wildcard *.cpp)
OBJECTS := $(patsubst %.cpp,%.o,$(SOURCES))
DEPENDS := $(patsubst %.cpp,%.d,$(SOURCES))
# ADD MORE WARNINGS!
WARNING := -Wall -Wextra
# .PHONY means these rules get executed even if
# files of those names exist.
.PHONY: all clean
# The first rule is the default, ie. "make",
# "make all" and "make parking" mean the same
all: parking
clean:
$(RM) $(OBJECTS) $(DEPENDS) parking
# Linking the executable from the object files
parking: $(OBJECTS)
$(CXX) $(WARNING) $(CXXFLAGS) $^ -o $#
-include $(DEPENDS)
%.o: %.cpp Makefile
$(CXX) $(WARNING) $(CXXFLAGS) -MMD -MP -c $< -o $#
My environment variable DYLD_LIBRARY_PATH has the value ../cmake_bin_dir/instDir/lib:../VTK/build/lib/.
When I try to compile running make, I get the following error:
ld: library not found for -lvtkCommon
clang: error: linker command failed with exit code 1 (use -v to see invocation)
What part of the Makefile or program or step in the process is not correct?
Thank you in advance.
The current VTK library does not contain libVtkCommon.so (see package contents section https://www.archlinux.org/packages/community/x86_64/vtk/). Are you looking for libVtkCommonCore.so? If that is the case you have to change -lvtkCommon to -lvtkCommonCore in your Makefile. The same seems to be the case for some of the other included libraries.
I've strictly followed this documentation to install and use jsoncpp library in my project : jsoncpp README
But I still have this problem with my compilation:
g++ -W -Wall -Werror -c -o src/ModConnection.o src/ModConnection.cpp
src/ModConnection.cpp:15:23: fatal error: json/json.h: No such file or directory
compilation terminated.
It's happen when I'm trying to use #include <json/json.h>
Here is my Linux MAKEFILE :
CXX = g++
NAME = bin/server
SRCS = ./src/ModConnection.cpp\
./src/unixNetwork.cpp
OBJS = $(SRCS:.cpp=.o)
CXXFLAGS += -W -Wall -Werror
LDFLAGS = -L ./src/jsoncpp-src-0.5.0/buildscons/linux-gcc4.5.1/src/lib_json/libjson_linux-gcc-4.5.1_libmt.a -I src/jsoncpp-src-0.5.0/include
RM = rm -f
$(NAME) : $(OBJS)
$(CXX) $(LDFLAGS) -o $(NAME) $(OBJS)
all : $(NAME)
clean :
$(RM) $(OBJS)
fclean : clean
$(RM) $(NAME)
re : fclean all
.PHONY : all clean fclean re
Thanks for you help.
You're specifying the include directory for jsoncpp in your LDFLAGS variable, but those don't get used until you've already compiled the individual cpp files. You need to put the part -I src/jsoncpp-src-0.5.0/include somewhere in the flags which get added to the compile lines, such as CXXFLAGS.
To expand a bit, you're using implicit Make rules to build your individual .cpp files, then you have a specific target for building your application out of those objects.
See the GNU Make Catalog of Rules for more info, but the one you're using is here:
Compiling C++ programs
n.o is made automatically from n.cc, n.cpp, or n.C with a recipe of the form $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c. We encourage you to use the suffix ‘.cc’ for C++ source files instead of ‘.C’.
Edit: Now for your linking errors.
You're getting these problems because the linker can't find the actual implementations of the functions you're calling.
First, your -L directive needs to point to a folder, not a library. -L sets a search path for libraries. It should be set to the folder where the library the jsoncpp build was created. Next, you must link the library itself. That library name is gigantic, but adding -l json_linux-gcc-4.5.1_libmt to LDFLAGS should do the trick. -l (that's lower ell) sets an actual library to link.
How can I link jsoncpp with a C++ program using g++? I tried:
g++ -o program program.cpp -L/path/to/library/files -ljsoncpp, -ljson, -llibjsoncpp
but g++ keeps saying:
/usr/bin/ld: cannot find -lsomething
You could also try using the new Amalgamated version of jsoncpp, which is new as of version 0.6.0.
The Amalgamated version allows you to use jsoncpp by adding just one directory with a couple of header files and one .cpp file to your project. You then can directly compile jsoncpp into your program with no worries about having to link to any jsoncpp libraries.
Look in /path/to/library/files to see what your *.a file is really named. On my system, I link with:
-ljson_linux-gcc-4.4.3_libmt
Some libraries will create a link from lib<name>.a to lib<name>-<version>.a for you, but I don't think that jsoncpp does this automatically. Therefore, you need to specify the complete name when linking.
You basically need to tell the path and the library.
jsoncpp library has pkg-config and you can use the command
`pkg-config --cflags path/to/jsoncpp/build/pkg-config/jsoncpp.pc`
for the include path and
`pkg-config --libs ../jsoncpp/build/pkg-config/jsoncpp.pc`
for linking (when running the command with g++ use the ). To see the single commands which is -L/libraryPath -ljsoncpp) run the commands above in the terminal without the ``.
It is easier to use this commands in a Makefile. As example my Makefile is:
CXX = g++
CXXFLAGS = -std=c++11
INC_PATH = `pkg-config --cflags ../jsoncpp/build/pkg-config/jsoncpp.pc`
LIBS = `pkg-config --libs ../jsoncpp/build/pkg-config/jsoncpp.pc`
SOURCES := $(wildcard *.cpp)
OBJDIR=obj
OBJECTS := $(patsubst %.cpp,$(OBJDIR)/%.o,$(SOURCES))
DEPENDS := $(patsubst %.cpp,$(OBJDIR)/%.d,$(SOURCES))
# ADD MORE WARNINGS!
WARNING := -Wall -Wextra
# .PHONY means these rules get executed even if
# files of those names exist.
.PHONY: all clean
# The first rule is the default, ie. "make",
# "make all" and "make parking" mean the same
all: yourProjectExecutableName
clean:
$(RM) $(OBJECTS) $(DEPENDS) parking
# Linking the executable from the object files
yourProjectExecutableName: $(OBJECTS)
$(CXX) $(WARNING) $(CXXFLAGS) $(INC_PATH) $^ -o $# $(LIBS)
-include $(DEPENDS)
$(OBJDIR):
mkdir -p $(OBJDIR)
$(OBJDIR)/%.o: %.cpp Makefile $(OBJDIR)
$(CXX) $(WARNING) $(CXXFLAGS) $(INC_PATH) -MMD -MP -c $< -o $#
and then in the directory of the file I run make. The final command(s) will be printed out in the Terminal