Building a C/C++ program for Windows/MacOS/Linux with dependencies - c++

I need to build a program on Windows, MacOS and Linux which relies on multiples dependencies. I tried to limit them as much as I could but I should ended up using WxWidgets, libcurl, openssl and libarchive.
I choose those dependencies because I must be able to:
compute a md5 hash (openssl)
decompress a zip archive (libarchive)
provide a GUI (WxWidgets)
use HTTPS (libcurl)
I am aware that this might be an overkill to import 5 libraries to only do those 5 things but I do not know any better solution yet. As I am writing this, I'm only using libcurl and openssl and building for Windows, MacOS and Linux is already very difficult for me.
I would like to distribute a standalone executable for each platform in addition to the source code, to build my project, I use the following Makefile :
CXX = g++
NAME = foo
SRC = $(wildcard src/*.cpp)
OBJ = $(SRC:.cpp=.o)
CXXFLAGS = -I./inc -std=c++11 -Wall -Wextra -Werror -g
all : $(NAME)
$(NAME) : $(OBJ)
$(CXX) $(CXXFLAGS) -o $# $^ -lcurl -lssl -lcrypto
clean :
rm -rf $(SRC:.cpp=.o)
fclean : clean
rm -rf $(NAME) test
re : fclean all
reclean : fclean all clean
.PHONY : all clean fclean re reclean
This worked great(even on Windows thanks to MSYS2 and MINGW) until I tried to statically linked each library to distribute a standalone binary :
$(NAME) : $(OBJ)
$(CXX) $(CXXFLAGS) -o $# $^ -lcurl -lssl -lcrypto
becamed
$(NAME) : $(OBJ)
$(CXX) $(CXXFLAGS) -o $# $^ libcurl.a libssl.a libcrypto.a
On Linux(Ubuntu 22.04), I downloaded curl and openssl source codes and built them using -static flags, copied the *.a inside my project's directory and I was done.
Now I'm trying to build curl and openssl on Windows with MSYS2, most of my attempts failed with error messages and took forever(> 30 minutes) to complete the build process. After struggling a little too much time, I finally managed to compile openssl by adding -lcrypto -lcrypt32..?
I do not think I will be able to finish this project with this "building process" as I still need to figure it out how build and link libarchive and WxWidgets. Is there anything I am missed out regarding the building process ? Should I pick others libraries ? Or It is just how it is ?
Thanks for your help.

Related

cannot find -lgtest when setting up Google Test

I'm using Google Test for C++ and trying to set it up on my linux machine.
My make file has the following code:
CC=g++
CFLAGS=-I $(GOOGLETESTDIR)/include -L $(GOOGLETESTDIR)/lib -lgtest -lpthread -Wall
DEPS=fib.h
OBJS=fib.o main.o
all: | r6
clean:
-rm -f r6 $(OBJS)
%.o: %.cpp $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
r6: $(OBJS)
$(CC) -o $# $^ $(CFLAGS)
.PHONY: all clean
I get the error when I run make:
/usr/bin/ld: cannot find -lgtest
How do I fix this? I'm new to this kind of testing and rather new to linux so I'm really lost.
I had this issue on Ubuntu 17.10 and basically what Alexander says is true.
Someone wrote a nice tutorial with explicit commands that can be found at https://www.eriksmistad.no/getting-started-with-google-test-on-ubuntu/
It boils down to:
sudo apt install libgtest-dev cmake
cd /usr/src/gtest
sudo cmake CMakeLists.txt
sudo make
sudo cp *.a /usr/lib
Personally, I would appreciate a solution that did not manually move files into /usr/lib, but on the plus side this works as-is.
As of now, Google test framework is not shipped with prebuilt binaries; you need to build them yourself. See full details on how to do that in README (for Debian, the path is /usr/src/googletest/googletest/README.md).

How to "make" an SDL project on linux?

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.

How to link google test lib (libgtest.a) depending on architecture (ARMEL or i386)?

I use Google Test in my C++ project. I build the target either for my i386 virtual machine or for the real ARMEL target. What I would like to do is have my Makefile link in the correct google test .a file for the right architecture, depending on the host system. E.g. if I am running the test target from my i386 VM, I'd like to link in the i386 built libgtest.a, and ditto when building on my ARMEL system. How do I do that? I do not cross compile the ARM build, I build it on the ARM target hardware itself. I don't really want to build libtest.a from scratch as it's pretty slow to build.
My Makefile is:
CC = g++-4.7
CXX := $(CC)
SVNDEV := -D'SVN_REV="$(shell svnversion -n .)"'
CFLAGS += -Os -Wall -Wno-write-strings $(SVNDEV) -Iinclude -I/usr/include/c++/4.7 -Llib
CXXFLAGS += --std=c++11 -D_GLIBCXX_USE_NANOSLEEP $(CFLAGS)
TARGET = connectionmanager
LIBS = -lzmq -ljansson -lpthread
objects = systeminterface.o linuxsysteminterface.o connectionmanagerutils.o connectionmanagerexception.o logger.o jsoninterface.o configuration.o diagnosticslogger.o serial.o \
modemstrategy.o lisac200modemstrategy.o maestrom1003gmodemstrategy.o
test_objects = mocksysteminterface.o mockmodemstrategy.o test/connectionmanagertest.o test/connectionmanagerutiltest.o test/jsoninterfacetest.o test/gtest_main.o
$(TARGET): connectionmanager.o $(objects) $(LIBS)
.PHONY: clean all test
all: $(TARGET)
cmmain.o: connectionmanager.cpp
$(CXX) -DUNIT_TESTING $(CPPFLAGS) $(CXXFLAGS) -c connectionmanager.cpp -o cmmain.o
connectionmanagertest : cmmain.o $(objects) $(test_objects) lib/libgtest.a $(LIBS)
$(CXX) -DUNIT_TESTING $(CPPFLAGS) $(CXXFLAGS) $(LIBS) lib/libgtest.a $^ -o $#
test: connectionmanagertest
./connectionmanagertest
clean:
rm -f $(TARGET)
rm -f $(objects)
rm -f $(test_objects)
rm -f connectionmanager.o
rm -f cmmain.o
rm -f $(test_objects)
Please, have a look here. As well your question looks like a duplicate of this. As a suggestion - you might be interested in CMake. Another good point is to parse /proc/cpuinfo for Linux, or use a sysctl call if you are on FreeBSD. Anyway the source of primary system information must be extracted either by existing utility that will return result for later processing in Makefile or using standard system tools. As a source of ideas I would also recommend to download any opensource package and look into the Makefile generators.

Makefile Issue linking Zeromq libs on Linux

I'm working on a project and trying to compile my code. I just moved this code from windows (VC++) to linux and it worked fine on windows but I can't get it to compile on linux.
The program uses zeromq for TCP connections and I am getting multiple errors when I build. Errors of the type:
/usr/local/include/zmq.hpp:372: undefined reference to `zmq_bind'
/usr/local/include/zmq.hpp:415: undefined reference to `zmq_msg_send'
I've installed zeromq via its tarball on my linux machine, and manually added zmq.hpp to the /usr/local/include folder. I suspect that I am doing something wrong in my makefile and thats why I am getting these errors.
I am somewhat weak in creating makefiles so I would greatly appreciate if someone can take a look for me and tell me if there is an obvious issue with my makefile that is causing these issues. Here is my makefile
C = g++
DEBUG = -g
CFLAGS = -g -Wall -std=c++11
LFLAGS = -L/usr/local/lib/
INCLUDES = -I/usr/local/
LIBS = -libzmq.la
SRCS = main.cpp NetworkTestServer.cpp
OBJS = $(SRCS:.cpp=.o)
EXECUTABLE = tester
all: $(SRCS) $(EXECUTABLE)
$(EXECUTABLE): $(OBJS)
$(CC) $(EXECUTABLE) -o $(EXECUTABLE) $(LIBS)
.cpp.o:
$(CC) $(CFLAGS) $< -o $#
clean:
$(RM) *.o *~ $(EXECUTABLE)
Thanks much
Looks to me like your LIBS definition is wrong.
Typically, the lib part is omitted, along with the extension. So, try something like:
LIBS = -lzmq
If that doesn't work, ensure that this library is contained in the location as specified by your LFLAGS variable.

How to use JSON-CPP?

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.