How to properly compile and link against C program? - c++

I have a logger that I wrote in C, and have included it in a C++ project I am working on. It works fine, but I get a deprecated warning from Clang++: "Treating C input as C++ when in C++ mode, this behaviour is deprecated."
In hopes of doing away with this warning, I moved the compilation of the logger into its own step in the make file and compiled the object file with Clang. Then I added a reference to that object file to my Clang++ rule to link against. Now it fails to link properly: "Linker command failed with exit code 1"
My makefile is below. How would I properly go about compiling and linking this C logger so as to do away with that warning in Clang++?
CC= clang++
PROG= ./bin/tetris
OBJS= ./src/main.o ./src/Tetris.o ./src/states/BaseState.o ./src/states/MenuState.o \
./src/states/GameState.o ./src/entities/Block.o ./src/entities/Tetromino.o \
./src/entities/Grid.o
LIBS= allegro-5.0 allegro_dialog-5.0 allegro_font-5.0 allegro_ttf-5.0 allegro_color-5.0 \
allegro_primitives-5.0 allegro_main-5.0 allegro_image-5.0 allegro_audio-5.0 allegro_memfile-5.0
CXXFLAGS= -g -Wall -std=c++11 $(shell pkg-config --cflags ${LIBS})
LDFLAGS= $(shell pkg-config --static --libs ${LIBS})
all: logger $(PROG)
$(PROG): $(OBJS)
mkdir -p ./bin
$(CC) -v -o $(PROG) $(LDFLAGS) $(OBJS) ./src/util/SimpleLogger/simplog.o
rm -f $(OBJS)
logger:
clang -c -Wall ./src/util/SimpleLogger/simplog.c -o ./src/util/SimpleLogger/simplog.o
clean:
rm -f $(PROG) $(OBJS)

This may not be what you are looking for, but you could include it in your C++ file by:
#ifdef __cplusplus
extern "C" {
#endif
// C code
#ifdef __cplusplus
}
#endif

Related

math.h not found when using llvm

I'm trying to build a python wrapper using the following Makefile:
CC=/usr/local/opt/llvm/bin/clang
OS_NAME=$(shell uname -s)
ifeq ($(OS_NAME),Linux)
LAPACKLDFLAGS=/usr/lib64/atlas/libsatlas.so # single-threaded blas
#LAPACKLDFLAGS=/usr/lib64/atlas/libtatlas.so # multi-threaded blas
#BLAS_THREADING=-D MULTITHREADED_BLAS # remove this if wrong
endif
ifeq ($(OS_NAME),Darwin) # Mac OS X
LAPACKLDFLAGS=-framework Accelerate # for OS X
endif
LAPACKCFLAGS=-Dinteger=int $(BLAS_THREADING)
STATICLAPACKLDFLAGS=-fPIC -Wall -g -fopenmp -static -static-libstdc++ /home/lear/douze/tmp/jpeg-6b/libjpeg.a /usr/lib64/libpng.a /usr/lib64/libz.a /usr/lib64/libblas.a /usr/lib/gcc/x86_64-redhat-linux/4.9.2/libgfortran.a /usr/lib/gcc/x86_64-redhat-linux/4.9.2/libquadmath.a # statically linked version
CFLAGS= -fPIC -Wall -g -std=c++11 $(LAPACKCFLAGS) -fopenmp -DUSE_OPENMP -O3
LDFLAGS=-fPIC -Wall -g -ljpeg -lpng -fopenmp
CPYTHONFLAGS=-I/usr/include/python2.7
SOURCES := $(shell find . -name '*.cpp' ! -name 'deepmatching_matlab.cpp')
OBJ := $(SOURCES:%.cpp=%.o)
HEADERS := $(shell find . -name '*.h')
all: deepmatching
.cpp.o: %.cpp %.h
$(CC) -o $# $(CFLAGS) -c $+
deepmatching: $(HEADERS) $(OBJ)
$(CC) -o $# $^ $(LDFLAGS) $(LAPACKLDFLAGS)
deepmatching-static: $(HEADERS) $(OBJ)
$(CC) -o $# $^ $(STATICLAPACKLDFLAGS)
python: $(HEADERS) $(OBJ)
# swig -python $(CPYTHONFLAGS) deepmatching.i # not necessary, only do if you have swig compiler
/usr/local/opt/llvm/bin/clang $(CFLAGS) -c deepmatching_wrap.c $(CPYTHONFLAGS)
/usr/local/opt/llvm/bin/clang -shared $(LDFLAGS) $(LAPACKLDFLAGS) deepmatching_wrap.o $(OBJ) -o _deepmatching.so $(LIBFLAGS)
clean:
rm -f $(OBJ) deepmatching *~ *.pyc .gdb_history deepmatching_wrap.o _deepmatching.so deepmatching.mex???
Previously, CC was set to g++, however, when I tried to build it like this, I'd get "ERROR: clang: error: unsupported option '-fopenmp".
Now I installed "brew install llvm" as this comes with the -fopenmp option. The unsupported error is resolved for now, but now the compiler doesn't seem to find a header file:
(base) MacBook-Pro-van-Brent:deepmatching BrentDeHauwere$ make python
/usr/local/opt/llvm/bin/clang -o hog.o -fPIC -Wall -g -std=c++11 -Dinteger=int -fopenmp -DUSE_OPENMP -O3 -I/usr/local/opt/llvm/include -c hog.cpp
In file included from hog.cpp:18:
In file included from ./std.h:20:
/usr/local/opt/llvm/bin/../include/c++/v1/math.h:300:15: fatal error: 'math.h' file not found
#include_next <math.h>
^~~~~~~~
1 error generated.
make: *** [hog.o] Error 1
I've tried setting options (I might have set them incorrectly) like -L/usr/local/opt/llvm/lib and -I/usr/local/opt/llvm/include, but no result so far. Any idea how I could point the compiler to the right direction for the header files?
Try running xcode-select —install in your terminal. This installs the xcode command line tools which should also install system headers files (as part of the macos sdk) and set your system include paths.

Makefile leads to compilation error

I'm trying to compile a program (which isn't mine):
make -f makefile
... using the following makefile:
# Compiler for .cpp files
CPP = g++
# Use nvcc to compile .cu files
NVCC = nvcc
NVCCFLAGS = -arch sm_20 # For fermi's in keeneland
# Add CUDA Paths
ICUDA = /usr/lib/nvidia-cuda-toolkit/include
LCUDA = /usr/lib/nvidia-cuda-toolkit/lib64
# Add CUDA libraries to the link line
LFLAGS += -lcuda -lcudart -L$(LCUDA) -lgomp
# Include standard optimization flags
CPPFLAGS = -O3 -c -I $(ICUDA) -Xcompiler -fopenmp -DTHRUST_DEVICE_BACKEND=THRUST_DEVICE_BACKEND_OMP
# List of all the objects you need
OBJECTS = timer.o ar1.o kGrid.o vfInit.o parameters.o
# Rule that tells make how to make the program from the objects
main : main.o $(OBJECTS)
$(CPP) -o main main.o $(OBJECTS) $(LFLAGS)
# Rule that tells make how to turn a .cu file into a .o
%.o: %.cu
$(NVCC) ${NVCCFLAGS} $(CPPFLAGS) -c $<
# How does make know how to turn a .cpp into a .o? It's built-in!
# but if you wanted to type it out it would look like:
# %.o: %.cpp
# $(CPP) $(CPPFLAGS) -c $<
clean :
rm -f *.o
rm -f core core.*
veryclean :
rm -f *.o
rm -f core core.*
rm -f main
Which results in the following commands:
nvcc -arch sm_20 -O3 -c -I /usr/lib/nvidia-cuda-toolkit/include -Xcompiler -fopenmp -DTHRUST_DEVICE_BACKEND=THRUST_DEVICE_BACKEND_OMP -c main.cu
g++ -O3 -c -I /usr/lib/nvidia-cuda-toolkit/include -Xcompiler -fopenmp -DTHRUST_DEVICE_BACKEND=THRUST_DEVICE_BACKEND_OMP -c -o timer.o timer.cpp
g++: error: unrecognized command line option â-Xcompilerâ
make: *** [timer.o] Error 1
I don't understand the makefile: the -xCompiler flag (in the variable CPPFLAGS) should be used only by the nvcc compiler, not g++. Therefore, I understand why I am getting an error. However, I don't understand, from my basic understanding of the makefile above, why at some point the variable CPPFLAGS follows g++ (variable CPP). I don't see any such sequence in the makefile.
Your main rule requires timer.o. There is no explicit rule for timer.o so make uses a built in implicit rule (as mentioned in the comment at the end of your makefile). The implicit rule for converting .cpp files into .o files has the form
$(CPP) $(CPPFLAGS) -c $<
So it's compiling using the options in CPPFLAGS which contains -Xcompiler. You probably want the -Xcompiler flag to be in NVCCFLAGS and not CPPFLAGS.

Linkage error using shared dll with minimal C++/SWIG/Lua code

This is a really specific compilation problem involving C++, SWIG and Lua.
I have a really simple base code :
[AClass.hpp]
class AClass {
public:
AClass();
};
[AClass.cpp]
#include "AClass.hpp"
AClass::AClass() {}
[main.cpp]
#include "AClass.hpp"
int main() {
AClass my_a;
}
At this point, there is no matter with compilation.
I first compile the class in libengine.dll and then use the shared library to build the executable.
Let's introduce a SWIG module, and add it to the dll :
[AClass.i]
%module M_AClass
%{
#include "AClass.hpp"
%}
%include "AClass.hpp"
Henceforth, when linking everything in an executable, I got the following error :
g++ -c main.cpp
g++ -c AClass.cpp
swig.exe -c++ -lua AClass.i
g++ -Iinclude -c AClass_wrap.cxx
g++ AClass.o AClass_wrap.o -shared -o libengine.dll -Wl,--out-implib,libengine.dll.a -L. -llua5.1
Creating library file: libengine.dll.a
g++ main.o libengine.dll.a -o main.exe
main.o:main.cpp:(.text+0x16): undefined reference to `AClass::AClass()'
collect2: ld returned 1 exit status
Would anyone have a clue ? I tried looking into the dll with nm but I can't figure how adding another .o to the shared library can "hide" a method (this isn't specific to constructors).
To reproduce the context, here are the necessary files to put in a directory to build the test :
include/ # Contains "lauxlib.h", "lua.h" & "luaconf.h"
liblua5.1.dll
AClass.hpp
AClass.cpp
AClass.i
main.cpp
Makefile
And finally, here is the Makefile content :
ifneq (,$(findstring Linux,$(shell uname -o)))
EXEC := main
LIB := libengine.so
LIB_FLAGS := -o $(LIB)
else
EXEC := main.exe
LIB := libengine.dll.a
LIB_FLAGS := -o libengine.dll -Wl,--out-implib,$(LIB)
#NO DIFFERENCE using ".dll.a" as in CMake (option: -Wl,--out-implib,) or only ".dll"
ifdef SystemRoot
# Pure Windows, no Cygwin
RM := del /Q
endif
endif
LANG_LIB := -L. -llua5.1
LANG_INC := include
LANG_SWIG := -lua
all: clean $(EXEC)
clean:
$(RM) main *.exe *_wrap.cxx *.o libengine.*
$(EXEC): main.o $(LIB)
g++ $^ -o $#
main.o: main.cpp
g++ -c $<
#NO PB without dependency to AClass_wrap.o
$(LIB): AClass.o AClass_wrap.o
g++ $^ -shared $(LANG_LIB) $(LIB_FLAGS)
AClass.o: AClass.cpp
g++ -fPIC -c $<
AClass_wrap.o: AClass_wrap.cxx
g++ -fPIC -I$(LANG_INC) -c $<
AClass_wrap.cxx: AClass.i
swig -c++ $(LANG_SWIG) $<
This was tested under Windows Seven, with MingGW g++ v4.5.2, SWIG 2.0.2 and Lua5.1.
EDIT: The problem also appear when SWIG-exporting to tcl. However, there is absolutely no problem compiling under Linux. I compared the generated AClass_wrap.cxx, they are similar.
g++ under mingw might require __declspec(dllimport/export)

Can someone explain this makefile to me?

I've been using c++ casually for a couple of months with a makefile I don't even remember where I got or if I did it myself (the actual structure it has. I know I've added some libraries and flags though):
SRC = filename.cpp
TARG = filename
CC = g++
CPPFLAGS = -g -Wall -Werror -Wextra -pipe -pedantic -Weffc++ -std=c++0x -O2 -Wno-unused-function `pkg-config --cflags opencv`
LDFLAGS = `pkg-config --libs opencv` -lboost_regex -lboost_filesystem
OBJ = $(SRC:.cpp=.o)
all: $(TARG)
clean:
rm -f *~ *.o $(TARG)
I wanted to use it to compile a class, but first I have to understand what is going on since I have to modify it a bit. Also, are there any bad practices in it?
If you want to compile a class instead of a program, you need to do a little surgery on the file. I'm assuming that you want an object file, not a library; the rules for libraries are more complex. But this should do the trick.
SRC = class.cpp
OBJ = $(SRC:.cpp=.o)
CC = g++
CPPFLAGS = -g -Wall -Werror -Wextra -pipe -pedantic -Weffc++ -std=c++0x -O2 \
-Wno-unused-function `pkg-config --cflags opencv`
LDFLAGS = `pkg-config --libs opencv` -lboost_regex -lboost_filesystem
DEBRIS = core a.out *~
all: $(OBJ)
class.o: class.h
clean:
rm -f $(DEBRIS) $(OBJ)
It is not immediately clear whether $(CPPFLAGS) will automatically appear in the compilation or linking commands.
If you end up wanting to build the program from two files, then you use a hybrid:
SRC = filename.cpp class.cpp
OBJ = $(SRC:.cpp=.o)
PROGRAM = program
CXX = g++
CXXFLAGS = -g -Wall -Werror -Wextra -pipe -pedantic -Weffc++ -std=c++0x -O2 \
-Wno-unused-function `pkg-config --cflags opencv`
LDFLAGS = `pkg-config --libs opencv` -lboost_regex -lboost_filesystem
DEBRIS = core a.out *~
all: $(PROGRAM)
$(PROGRAM): $(OBJ)
$(CXX) $(CXXFLAGS) -o $# $(OBJ) $(LDFLAGS)
class.o: class.h
filename.cpp: class.h
clean:
rm -f $(DEBRIS) $(OBJ) $(PROGRAM)
Note that I've changed the macro for the C++ compiler from CC to CXX. The standards are not clear on the name for the C++ compiler. POSIX doesn't mention C++ in its description of make. However, CC is clearly intended for compiling C rather than C++. That needn't stop your version of make from using CC for C++ compilation, but it would be a little unusual. (GNU Make 3.81 on MacOS X 10.6.8 uses CXX for the C++ compilation.) The link line now uses $(CXXFLAGS) (thanks to eriktous); it is still not clear whether the C++ source to object file compilation would do so. Ultimately, that's why you end up seeing makefiles with rules such as:
class.o: class.h
$(CXX) -c $(CXXFLAGS) $*.cpp
This guarantees that the compilation rule is what you see for this object file. You might write that as an old-fashioned but portable suffix rule (.cpp.o:) instead; the POSIX specification for make supports these. Or you might use the more modern but not necessarily quite as portable %.o : %.o notation instead (not required by POSIX). Either of these replaces any previous (built-in) definition of how to compile an object file from C++ source.
.cpp.o:
$(CXX) -c $(CXXFLAGS) $*.cpp
%.o : %.cpp
$(CXX) -c $(CXXFLAGS) $*.cpp
I assume you are using opencv (and some of Boost); if not, your compilation and linking flags include irrelevant options. The dependencies are guessed; make will infer the dependency of the object file on the C++ source code, so I only listed header dependencies. But you may have many more if you're using opencv and Boost.
(Makefiles not formally tested.)
when you type "make" with no args, it looks for the first recipe, something that starts in the first column with a colon after it. that would be all, which tells it to build TARG. TARG is filename. Make is already configured on many systems to know what to do with .cpp files, so there is no specific recipe in this Makefile to do that. The OBJ construct is unused here, so no need to explain that; but what it means is "replace .cpp in SRC with .o", so OBJ would be filename.o.
It already looks good. You defined the proper variables, the file is short and readable, what else do you want?
In the clean target, you could only remove $(OBJ) instead of *.o. And you should not remove your editor's backup files as part of the build process. I suggest this instead:
clean:
rm -f $(TARG) $(OBJ)
clean-all: clean
rm -f *~
# mark these targets as non-files.
.PHONY: all clean clean-all

How to link jsoncpp?

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