C++: Including an external library in Makefile - makefile

So, I have some trouble including the ncurses-library in a C++ program.
It seems my Makefile isn't set correctly and the library-functions can't be found.
I installed the library with "sudo apt-get install libncurses5-dev libncursesw5-dev" and I'm able to compile my code manually via "g++ -o output src/main.cpp -lncurses".
The compiler settings in my Makefile looked like this:
CC = g++
CXXFLAGS = -std=c++11 -Wall`
LDFLAGS =
LDLIBS = -lncurses
I'm using the "C/C++ Makefile Project" Plugin within Visual Studios Code on ubuntu.

Edit: As MadScientist explained, the second option follows the convention.
So, I found two solutions and I'm not sure which one or if any of them is the desired way of doing it:
Set LDFLAGS = -lncurses
Add $(LDLIBS) to a line in the Makefile:
# Builds the app
$(APPNAME): $(OBJ)
$(CC) $(CXXFLAGS) -o $# $^ $(LDFLAGS) $(LDLIBS)

Related

How to configure a dynamic library using a macro / variable in a makefile?

I'm writing a small study project in C. I need to create a dynamic library and configure its use with macros. First, I create object files with the command:
$gcc -fPIC -c ../data_module/data_process.c
$gcc -fPIC -c ../data_libs/data_stat.c
Then I create a dynamic library like this:
$gcc -shared -o data_process.so data_process.o data_stat.o
And finally I build an executable file using this library:
$gcc main_executable_module.o ../data_libs/data_io.o ../yet_another_decision_module/decision.o -L. data_process.so -o test_main
It works and the executable works correctly. But there is a task to configure the library using macros:
Make the necessary changes to the code of the main_executable_module, configuring the use of the dynamic library using macros.
That is, if I understand correctly, you need to add macros to the main_executable_module.o so that you do not use the -L flags during assembly. But I can't find information anywhere on how to do it. Can you please tell me how to implement this or where can I read about it?
UPD: John Bollinger says
It is possible that the word "macros" is intended to be interpreted as makefile macros, which many people instead call (makefile) "variables". That would make this a question about make / makefiles, not about C.
My Makefile:
CC=gcc
LDFLAGS=
CFLAGS=-c -Wall -Wextra -Werror
SOURCES=main_executable_module.c ../data_libs/data_stat.c ../data_libs/data_io.c ../yet_another_decision_module/decision.c ../data_module/data_process.c
DYNLIB=../data_module/data_process.c
STAT=../data_libs/data_stat.c
BUILDDYN=main_executable_module.c ../data_libs/data_io.c ../yet_another_decision_module/decision.c
OBJECTS=$(SOURCES:.c=.o)
OBJBUILDDYN=$(BUILDDYN:.c=.o)
OBJDYNLIB=data_process.o
OBJDATASTAT=data_stat.o
EXECUTABLE=../../build/main
DEXECUTABLE=../../build/Quest_6
DLIBS=data_process.so
all: $(SOURCES) $(EXECUTABLE)
data_stat.a: $(OBJLIB) $(LIBS)
ar -rcs $(LIBS) $(OBJLIB)
data_process.so: $(OBJDYNLIB) $(OBJDATASTAT)
$(CC) -shared -o $(DLIBS) $(OBJDYNLIB) $(OBJDATASTAT)
$(OBJDYNLIB): $(DYNLIB)
$(CC) -fPIC -c $(DYNLIB)
$(OBJDATASTAT): $(STAT)
$(CC) -fPIC -c $(STAT)
build_with_dynamic:$(OBJECTS) $(EXECUTABLE)
$(CC) $(OBJBUILDDYN) -L. $(DLIBS) -o $(DEXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $#
.c.o:
$(CC) $(CFLAGS) $< -o $#
clean:
rm -rf $(EXECUTABLE) $(OBJECTS)
lclean:
rm -rf $(LEXECUTABLE) $(OBJECTS) $(LIBS) $(DEXECUTABLE)
rebuild: clean $(SOURCES) $(EXECUTABLE)
The results of the checks revealed nothing. There are two opinions about this task.
Leave everything as above. And in the file itself, add a header process.h. Then everything is assembled and working. And at the same time, if you change the code in the library, rebuild it, and do not rebuild the executable file, then the changes will be taken into account. That is, the idea of ​​a dynamic library is respected.
Implement in such a way that there is no need to include headers in the main_executable_module.c. Then a special library is used for working with dynamic libraries, which allows you to write the path to the library and take individual functions from it. More about it here.
What was meant when it was said about macros, I still did not understand ...

Compiling SDL project on Raspberry Pi

I am trying to build a project with make (gcc on Raspbian)
Here is the makefile (I removed some unnecessary parts):
objects = 3d.o Affichage.o [...]
cflags = -I/usr/local/include/SDL2 -L/usr/local/lib -lSDL2
poly : %(objects)
gcc $(cflags) $(objects) -o poly
($objects) : types.h
[...]
When running Make, I got:
cc -c -o Affichage.o Affichage.c
fatal error: SDL.h: No such file or directory
#include <SDL.h>
I checked the folders, everything seems ok. SDL.h is indeed in /usr/local/include/SDL2. I tried to remove options one by one in cflags, no luck...
What am I missing?
Make told you exact command it tried to execute:
cc -c -o Affichage.o Affichage.c
This don't have -I path, which is the source of an error.
You have target for your resulting executable but not for object files. Make have builtin rule to compile object files from C sources, but it isn't aware of your cflags variable. So far your options are:
Define your own pattern rule
e.g:
%.o: %.c
gcc $(cflags) -c $< -o $#
However, your cflags contains -lSDL2, which is linking flag, which should be specified only on linking phase (so technically it isn't cflag). Move it to separate variable (usually LIBS, which may then be enfolded into make's semi-standard LDFLAGS).
Use variables that make is aware of
In that case, it is CFLAGS:
CC:=gcc
CFLAGS:=-I/usr/local/include/SDL2
LIBS:=-lSDL2
LDFLAGS:=-L/usr/local/lib $(LIBS)
objects:=3d.o Affichage.o
poly: $(objects)
$(CC) $^ -o $# $(LDFLAGS)
$(objects): types.h
The rest will be done by implicit rules.

extra CFLAGs with Makefile

I'm reading through Foundations of GTK+ and in so doing decided to write a simple makefile that would let me run "make " to compile the example program I'd just written. I also stumbled upon a list of compiler directives here that the Gnome team specified will help moving from GTK2 to GTK3, so I wanted to include those.
I'm a make noob for all intents and purposes, so this is what I came up with:
CC = gcc
CFLAGS += -Wall
GTK_DFLAGS = -DGTK_DISABLE_SINGLE_INCLUDES -DGDK_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED -DGSEAL_ENABLE
GTK_CFLAGS = $(shell pkg-config --cflags gtk+-3.0)
GTK_LDFLAGS = $(shell pkg-config --libs gtk+-3.0)
%.o: %.c
$(CC) $(CFLAGS) $(GTK_DFLAGS) $(GTK_CFLAGS) -c -o $# $<
%: %.o
$(CC) $(CFLAGS) $(GTK_DFLAGS) $(GTK_CFLAGS) $(GTK_LDFLAGS) -o $# $<
.PHONY: clean
clean:
rm -f *.o *~
And as you might guess, it doesn't work quite right. I know running pkg-config from inside the makefile isn't an ideal solution, but this is for my small-scale learning projects and not for deployment of any sort. That said, the output is weird to me; it seems like make just ignores any variables after CFLAGS.
Something like:
[patrick#blackbox ch2]$ make helloworld
gcc -Wall helloworld.c -o helloworld
helloworld.c:1:21: fatal error: gtk/gtk.h: No such file or directory
#include <gtk/gtk.h>
^
compilation terminated.
<builtin>: recipe for target 'helloworld' failed
make: *** [helloworld] Error 1
If I add have the contents of GTK_DFLAGS simply tacked onto the end of CFLAGS, they appear on the command line, but the pkg-config variables are still missing.
It's obvious to me that I messed something simple up, but after an hour of vaguely worded Googling, I'm fresh out of ideas as to what it is.
Found the answer, and of course the vocabulary I was missing when asking this question/doing earlier searches.
CC = gcc
CFLAGS += -Wall -std=c11
GTK_DFLAGS = -DGTK_DISABLE_SINGLE_INCLUDES -DGDK_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED -DGSEAL_ENABLE
GTK_CFLAGS := $(shell pkg-config --cflags gtk+-3.0)
GTK_LDFLAGS := $(shell pkg-config --libs gtk+-3.0)
%: %.c
$(CC) $(CFLAGS) $(GTK_DFLAGS) $(GTK_CFLAGS) $(GTK_LDFLAGS) -o $* $*.c
.PHONY: clean
clean:
rm -f *~
This does what I want, which is to compile a single .c file of any name into a program of the same name with the GTK flags I was looking to use.
Thanks to those who contributed!
You need a target for helloworld in your Makefile. Something like this:
helloworld: helloworld.o
$(CC) -o helloworld helloworld.o $(LDFLAGS) $(GTK_LDFLAGS)

How to compile c99-to-c89 convertor with clang?

I'm trying to compile ffmpeg in windows for VisualStudio and one of the step is to compile c99-to-c89 code with clang according to this post. I managed to create clang.exe but how I compile c99-to-c89 code with it?
I changed a little bit the makefile in c99-to-c89 so CC variable points now to clang.exe compiler and not cl.exe
EXT=.exe
all: c99conv$(EXT) c99wrap$(EXT)
CLANGDIR=C:/build
CC=C:/build/bin/Release/clang.exe
CFLAGS=-nologo -Z7 -D_CRT_SECURE_NO_WARNINGS=1 -Dpopen=_popen -Dunlink=_unlink -Dstrdup=_strdup -Dsnprintf=_snprintf -I. -I$(CLANGDIR)/tools/clang/include
LDFLAGS=-nologo -Z7 $(CLANGDIR)/lib/Release/libclang.lib
clean:
rm -f c99conv$(EXT) c99wrap$(EXT) convert.o compilewrap.o
rm -f unit.c.c unit2.c.c
test1: c99conv$(EXT)
$(CC) -P unit.c -Fiunit.prev.c
./c99conv unit.prev.c unit.post.c
diff -u unit.{prev,post}.c
test2: c99conv$(EXT)
$(CC) -P unit2.c -Fiunit2.prev.c
./c99conv unit2.prev.c unit2.post.c
diff -u unit2.{prev,post}.c
test3: c99conv$(EXT)
$(CC) $(CFLAGS) -P -Ficonvert.prev.c convert.c
./c99conv convert.prev.c convert.post.c
diff -u convert.{prev,post}.c
c99conv$(EXT): convert.o
$(CC) -Fe$# $< $(LDFLAGS) $(LIBS)
c99wrap$(EXT): compilewrap.o
$(CC) -Fe$# $< $(LDFLAGS)
%.o: %.c
$(CC) $(CFLAGS) -Fo$# -c $<
but when I run make command I get clang: error: unsupported use of internal gcc -Z option '-Z7'. I guess the problem in CFLAGS and LDFLAGS but I don't know how to fix it because the lack of knowledge in makefile and clang.
If someone still needs, the guys from libav provided me with this link to download the binaries c99conv.exe, c99wrap.exe, makedef
c99conv wust be compilled with msvc compiller, but it uses libraries from LLVM. Actualy, converter uses clang as a parser C99 sources.
Therefore clang needs to be compilled with MSVC (because MSVC will link libclang with c99conv).
So, just lead the build instructions from article you link.
Run visual studio command promt.
Run msys shell from mingw.
Tune Makefile.w32 for your environment
Compile c99conv with Makefile.w32
make -f Makefile.w32

Recompile with -fPIC option, but the option is already in the makefile

I get this error when I do the make:
relocation R_X86_64_32 against `vtable for Torch::MemoryDataSet' can not be used
when making a shared object; recompile with -fPIC
It says that I should recompile with the -fPIC option. I did that, adding
the -fPIC option to CFLAGS and CXXFLAGS, but I still get the same error. Is there any way to solve this? I have seen that this problem is related with the use of a 64-bit machine, and it is true that I am using one.
I had this problem quite a while back and if I remember correctly, the fix was moving the placement of -fPIC just after gcc in the command line. Made absolutely no sense, and less so now, but as I remember, that fixed it.
I encountered the same problem, but it had an extra twist. The answer by #clintm solved it, but I thought I would describe my variation of the problem here for future reference...
Makefile on 32-bit machine:
CXX=g++
CXXFLAGS= -O3 -Wall
...
...
%.o: %.c
$(CXX) $(CXXFLAGS) -fpic -c $<
libmylibrary.so: $(OBJECTS)
$(CXX) -shared -Wl,-soname,$# -o $# $(OBJECTS)
This compiled correctly. But the same Makefile failed when I tried it on a 64-bit machine. I changed "-fpic" to "-fPIC" and it still failed. I changed the object rule to:
%.o: %.c
$(CXX) -fPIC $(CXXFLAGS) -c $<
and it still failed.
Finally, I placed "-fPIC" in the actual compiler variable (so that now "-fPIC" appears in the rule for each object and the rule for the shared library):
CXX=g++ -fPIC
CXXFLAGS= -g -O3 -Wall
...
%.o: %.c
$(CXX) $(CXXFLAGS) -c -o $# $<
libalglib.so: $(OBJECTS)
$(CXX) -shared -Wl,-soname,$# -o $# $(OBJECTS)
And it worked!
Let's say you have some makefile like:
CFLAGS = -g -Wall
SOURCES = $(wildcard *.c)
OBJECTS = ...
TARGET = libmyawesomelib.a
all: $(TARGET) main
just add the -fPIC flag like so:
$(TARGET): CFLAGS += -fPIC
$(TARGET): $(OBJECTS)
.
.
.
so on so forth with the rest of the makefile.
I ran into this problem cross-compiling with the android-ndk toolchain. I ended up having to use
CC="$CROSS/bin/arm-linux-androideabi-gcc -pie --sysroot=$SYSROOT"
Neither -fPIC nor -fPIE worked for me in this situation.
I was cross compiling shadowsocks-libev on a CentOS 7 machine, the same problem happened to me, it works perfectly on my laptop with
CC=mipsel-unknown-linux-uclibc-gcc CXX=mipsel-unknown-linux-uclibc-g++ AR=mipsel-unknown-linux-uclibc-ar RANLIB=mipsel-unknown-linux-uclibc-ranlib make SHARED=1 CFLAGS=-fPIC
but on travis ci, it did not work, I have to add -fPIC to CC and CXX in order to get it to work
CC="mipsel-unknown-linux-uclibc-gcc -fPIC" CXX="mipsel-unknown-linux-uclibc-g++ -fPIC" AR=mipsel-unknown-linux-uclibc-ar RANLIB=mipsel-unknown-linux-uclibc-ranlib make SHARED=1
I had this issue after I upgraded gcc. I had one .o file (sqlite) that hadn't been cleaned by the Makefile and as a result I had this issue (assuming because it was compiled with an older version of gcc). After removing that file and rebuilding this error went away.
if the project you'd like to compile has a correct configure script use like this:
$ ./configure 'CFLAGS=-g -O2 -fPIC ....' --enable-some-thing
so the flag will be all the Makefile's rule ...
few days before i've need an elder ver. of VLC to compile on an x64 machine, it has a nice configure script ;-)

Resources