C++ Wrapper for C library as shared library - c++

I SOLVED THIS ISSUE BY MYSELF
The problem was the linkage of the library.
I copied the libmywrapper.so(i renamed it) file to /usr/lib and linked with -mywrapper
That's it :-)
Original post:
I'm writing a wrapper library that allows to call C++ functions out of C-code.
Unfortnuately it doesn't link...
wrapper.h:
#ifdef __cplusplus
extern "C"
{
#endif
extern char* (keygen) ();
#ifdef __cplusplus
}
#endif
wrapper.cpp:
#include "wrapper.h"
#include <someincludes>
char* keygen ()
{
urandom u;
Makefile:
TARGET := ./mywrapperlib.so
CXXFLAGS := -fPIC -shared -g -Wall -std=c++0x -I../someincludes -I.
CXX := g++
LIB := -lsomelibs
EXT := cpp
BUILDDIR := build
override BUILDDIR := $(strip $(BUILDDIR))
SOURCES := $(wildcard *.$(EXT))
OBJECTS := $(patsubst %.$(EXT), $(BUILDDIR)/%.o, $(SOURCES))
DEPS := $(patsubst %.$(EXT), $(BUILDDIR)/%.dep, $(SOURCES))
.PHONY: all
all: $(TARGET)
$(TARGET): $(OBJECTS) $(DEPS)
$(CXX) $(CXXFLAGS) -o $(TARGET) $(OBJECTS) $(LIBS)
ifneq ($(MAKECMDGOALS), clean)
-include $(DEPS)
endif
$(OBJECTS): $(BUILDDIR)/%.o: %.$(EXT) $(BUILDDIR)/%.dep $(BUILDDIR)/.tag
$(CXX) $(CXXFLAGS) -c $< -o $#
$(DEPS): $(BUILDDIR)/%.dep: %.$(EXT) $(BUILDDIR)/.tag
mkdir -p $(dir $(#))
$(CXX) $(CXXFLAGS) -MM $< -MT $# -MT $(<:.$(EXT)=.o) -o $#
%.tag:
mkdir -p $(dir $(#))
touch $#
.PHONY: clean
clean:
$(RM) -r $(BUILDDIR)
A test file that should use the library:
test.c:
#include <wrapper.h>
int main()
{
char* test = keygen();
}
When i try to compile it with
gcc -o test.a -g -Iinclude -Llib/mywrapperlib.so test.c
I get
/tmp/ccB9bEot.o: In function `main':
/some/paths/test.c:7: undefined reference to `keygen'
Im very unexperienced with mixing C & C++ code and writing libraries.
Now im stuck and hope that someone can help me with this problem.
EDIT:
I checked the lib with nm:
nm lib/cryptdbwrapperlib.so | grep keygen
0000000000006935 T keygen
So, i guess that the problem is the linkage...

It's to do with the order of your flags to gcc.
Do this:
gcc -o test.a -g -Iinclude test.c -Llib/mywrapperlib.so
# ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^
# first second
GCC reads libraries and objects left-to-right and (basically) ignores any that aren't needed "yet". With my proposed change, test.c goes first so GCC knows that it's going to be looking for a symbol keygen; then, when it finally sees -Llib/mywrapperlib.so it scans it for keygen, finds it, and knows that this library is required.

Change the function's signature in wrapper.cpp to
extern "C" char* keygen ()
Otherwise it will be compiled with a C++ style name, and hence be a different function than the one declared in the header.

I SOLVED THIS ISSUE BY MYSELF
The problem was the linkage of the library. I copied the libmywrapper.so(i renamed it) file to /usr/lib and linked with -mywrapper That's it :-)

Related

Compile each cpp file in separate directory

The results for this topic strangely all did not work.
Finally I found a variant that is logical for me and works from the same order.
CC := g++
CFLAGS := -g -Wall
objects = test helloworld
all: $(objects)
$(objects): %: %.cpp
$(CC) $(CFLAGS) -o $# $<
I have tried a lot and probably fail to fully understand the line %: %.cpp.
My interpretation is: I take from every object the dependency which in turn is based on a file which is then traceable to a .cpp file.
My theory is test expects test.o and then test.cpp.
How do I rewrite this to directory?
I have already read some things with wildcards and a pattern replace.
Like
SRC_DIR := src
OBJ_DIR := obj
SRC_FILES := $(wildcard $(SRC_DIR)/*.cpp)
OBJ_FILES := $(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(SRC_FILES))
LDFLAGS := ...
CPPFLAGS := ...
CXXFLAGS := ...
main.exe: $(OBJ_FILES)
g++ $(LDFLAGS) -o $# $^
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
g++ $(CPPFLAGS) $(CXXFLAGS) -c -o $# $<
But the behavior was not the expected.
When 2 cpp files were in the folder the result was
g++ -o helloworld.o helloworld.cpp
g++ -o helloworld.o test.cpp
Or vice versa that only the cpp file was always the same.
I have the feeling to miss something extremely.
Update:
The make version is
GNU Make 4.3
Built for aarch64-unknown-linux-android
The Goal
What I would like to achieve is
src/
Test.cpp
Helloworld.cpp
Obj/
Make :
Obj/
Helloworld.out
Test.out
Try this:
CXX := g++
CXXFLAGS := -g -Wall
TARGETS=obj/test.out obj/helloworld.out
all:$(TARGETS)
obj/%.out:src/%.cpp
$(CXX) $(CXXFLAGS) -o $# $^
clean:
rm obj/*

Makefile not giving the expected compilation results

I am quite new to Make. I am attempting to write a Makefile to build a medium-sized Linux C/C++ application as below.
Making a simple Makefile by having all source files in one location and explicitly listing the source files works ok for me but I would like it to be more generic.
I have all my source files (C and C++) in the src folder in different subdirectories. I have header files inside an inc and inc/common folder, and then libs inside a lib folder.
The Makefile is run on the same level :
SRC_DIR := src
OBJ_DIR := obj
BIN_DIR := bin
CXX := /bin/arm-linux-gnueabi-g++
EXE := $(BIN_DIR)/runfile
SRC := $(shell find $(SRC_DIR) -name *.cpp -or -name *.c)
OBJ := $(patsubst $(SRC_DIR)/%,$(OBJ_DIR)/%,$(addsuffix .o,$(basename $(SRC))))
CPPFLAGS := -Iinc -Iinc/common -MMD -MP
CXXFLAGS := -std=c++11 -Wall
LDFLAGS := -Llib
LDLIBS :=
.PHONY: all clean
all: $(EXE)
$(EXE): $(OBJ) | $(BIN_DIR)
$(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $#
$(OBJ_DIR)/%.o: $(SRC) | $(OBJ_DIR)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $#
$(BIN_DIR) $(OBJ_DIR):
mkdir -p $#
clean:
#$(RM) -rv $(BIN_DIR) $(OBJ_DIR)
-include $(OBJ:.o=.d)
I get lots of errors such as below when I run it, including problems opening dependency files. I think i'm almost there, but can't see my error exactly :
compilation terminated.
/bin/arm-linux-gnueabi-g++ -Iinc -Iinc/common -MMD -MP -std=c++11 -Wall -c -o obj/main.d.o
cc -Llib obj/main.d.o -o obj/main.d
/usr/bin/ld: obj/main.d.o: relocations in generic ELF (EM: 40)
/usr/bin/ld: obj/main.d.o: relocations in generic ELF (EM: 40)
/usr/bin/ld: obj/main.d.o: error adding symbols: file in wrong format
I don't see how the output you show can be generated from the makefile you show here but anyway.
This is not right:
$(OBJ_DIR)/%.o: $(SRC) | $(OBJ_DIR)
A pattern rule is a template that tells make "if you want to build a target that matches this pattern, then you can build it from the prerequisites that match this pattern".
Here you are listing ALL your source files as a prerequisite for EVERY object file. Suppose SRC is set to foo.c bar.c biz.c baz.c, then this expands to:
obj/%.o : foo.c bar.c biz.c baz.c | obj
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $#
You're telling make that every single .o target depends on ALL the source files, not just the one for that object file. Further, the automatic variable $< always expands to the first prerequisite, which here will always be foo.c. So, you're compiling foo.c four times, creating each of the object files.
The very first important rule when debugging makefiles is to look carefully at the output (command lines) that make prints. If they are not right, then your makefile is not right. If you do that you'll see all the compile lines are compiling the same source, like:
g++ -c foo.c -o obj/foo.o
g++ -c foo.c -o obj/bar.o
g++ -c foo.c -o obj/biz.o
g++ -c foo.c -o obj/baz.o
That clearly cannot work and it's why you get link errors trying to link together all these object files: they all have the same content.
You need this:
$(OBJ_DIR)/%.o : $(SRC_DIR)/%.cpp
#mkdir -p $(#D)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $#
which tells make how to build an object file from a single source file.
You also need to create the actual output directory that the object file will go into. Just creating $(OBJ_DIR) is not enough, if the object file appears in a subdirectory.

Makefile first rule target

I am trying to learn make using simply three files.
foo.h
#ifndef __foo_H_
#define __foo_H_
void print();
#endif
foo.c
#include <stdio.h>
#include "foo.h"
void print()
{
printf("Hello World !");
}
main.c
#include "foo.h"
int main()
{
print();
return 0;
}
When I use the following makefile, everything runs fine
makefile
CC = gcc
CFLAGS = -I.
DEPS = foo.h
OBJ = foo.o main.o
.PHONY: clean
main: $(OBJ)
gcc -o $# $^ $(CFLAGS)
%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
clean:
rm *.o
The above works because make by default runs the first target(Which I read basically everywhere).
If I use the below makefile
CC = gcc
CFLAGS = -I.
DEPS = foo.h
OBJ = foo.o main.o
.PHONY: clean
clean:
rm *.o
main: $(OBJ)
gcc -o $# $^ $(CFLAGS)
%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
Calling make on the above makefile runs only make clean because make by default runs the first rule.
The problem is with this makefile
CC = gcc
CFLAGS = -I.
DEPS = foo.h
OBJ = foo.o main.o
.PHONY: clean
%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
main: $(OBJ)
gcc -o $# $^ $(CFLAGS)
clean:
rm *.o
In the above makefile using make I get
gcc -c -o foo.o foo.c -I.
gcc -c -o main.o main.c -I.
gcc -o main foo.o main.o -I.
Why doesn't make just build the .o files and stop since it is the first target, why does it go on to build main as well? There is no where that I've specified in the first rule to build main.
The "first target" rule only counts explicit targets. It doesn't count implicit targets, such as suffix rules or pattern rules.
Consider: how would make determine that it should build the .o files? Which .o files should it build? How would make understand that it should build the ones in the variable OBJ, versus any other variable?
I was looking for a good section of the manual to point you at but haven't found anything specific and concrete to use. The answer to the question, as far as I know, is that a pattern rule is not a target and the default target must, as its name indicates, be a target.
Were you using a static pattern rule (which does define targets) then your expectation would almost be correct as make would pick the first such file and build just that in this case (not all as you might expect just the first).

cygwin g++ Linker doesn't find shared library

I have been creating a library. When I compile it as a static library, it works fine. Now I want to turn it into a shared library. The library is created and in the proper place, but when I try to compile the client code, the linking phase says that it can't find the library.
I already tried to rename it to al or dylib but that doesn't help either. When I put the -v flag on the linking, I can see that my library path is there. I also tried different paths. I used a relative path, but even with a full path it doesn't find it.
The Makefile from the library:
.SUFFIXES:
.SUFFIXES: .o .cpp
.SUFFIXES: .o .d
CC := g++
LNK:= g++
CXXFLAGS_RELEASE = -fPIC -shared -O2 -Wall -fmessage-length=0
CXXFLAGS_DEBUG = -fPIC -shared -g -Wall -fmessage-length=0 -D _DEBUG
CXXFLAGS = $(CXXFLAGS_DEBUG)
OBJDIR:= obj
SRCDIR:= src
HDIR:= include
INCLUDE_PATHS:= -Iinclude -Iinclude/interfaces -Iinclude/support
CPP_FILES := propertyfile/propertyfile.cpp \
propertyfile/propertyitem.cpp \
propertyfile/propertyfactory.cpp \
helper/string_helper.cpp
OBJ := $(patsubst %.cpp,$(OBJDIR)/%.o, $(CPP_FILES))
SRC := $(patsubst %.cpp,$(SRCDIR)/%.o, $(CPP_FILES))
LIBS:=
TARGET:= libsupport.so
all: $(TARGET)
$(TARGET): $(OBJ)
$(LNK) -o $(TARGET) $(OBJ) -shared
#cp $(TARGET) ../lib
#cp -r include ..
clean:
rm -f $(OBJ) $(ASM) $(TARGET)
-include $(patsubst %.cpp,$(OBJDIR)/%.d, $(CPP_FILES))
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp $(OBJDIR)/%.d
#mkdir -p `dirname $#`
$(CC) $(CXXFLAGS) -c $< -o $# $(INCLUDE_PATHS)
$(OBJDIR)/%.d: $(SRCDIR)/%.cpp
#mkdir -p `dirname $#`
$(CC) $(CXXFLAGS) -MM -MT $# -MF $(OBJDIR)/$*.d -c $< $(INCLUDE_PATHS)
And here is the Makefile for the application:
.SUFFIXES:
.SUFFIXES: .o .cpp
CC := g++
LD := g++
CXXFLAGS_RELEASE = -O2 -Wall -fmessage-length=0
CXXFLAGS_DEBUG = -g -Wall -fmessage-length=0 -D _DEBUG
CXXFLAGS = $(CXXFLAGS_DEBUG)
OBJDIR:= obj
SRCDIR:= src
INCLUDE_PATHS:= -Iinclude -I../include
LIBS:= -L /cygdrive/d/src/c/lib -lsupport
CPP_FILES := nohupshd.cpp \
daemon.cpp \
task.cpp
OBJ := $(patsubst %.cpp,$(OBJDIR)/%.o, $(CPP_FILES))
SRC := $(patsubst %.cpp,$(SRCDIR)/%.o, $(CPP_FILES))
TARGET:= nohupshd
all: $(TARGET)
$(TARGET): $(OBJ)
$(LD) -o $(TARGET) $(OBJ) $(LIBS)
clean:
rm -f $(OBJ) $(ASM) $(TARGET)
-include $(patsubst %.cpp,$(OBJDIR)/%.d, $(CPP_FILES))
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp $(OBJDIR)/%.d
#mkdir -p `dirname $#`
$(CC) $(CXXFLAGS) -c $< -o $# $(INCLUDE_PATHS)
$(OBJDIR)/%.d: $(SRCDIR)/%.cpp
#mkdir -p `dirname $#`
$(CC) $(CXXFLAGS) -MM -MT $# -MF $(OBJDIR)/$*.d -c $< $(INCLUDE_PATHS)
After some experimenting I found a solution on how to compile a shared library under cygwin.
Apparently the compiler is looking for a DLL file even though it is inside cygwin. so the first step is to add your path, where the library is going to be to the PATH variable.
export PATH=$PATH:/cygdrive/d/src/c/lib
Apparently when linking against a shared library, the linker seems to look for a DLL file by default. I don't know why, because inside cygwin I would expect it to look for a .so file just like on other UNIX systems.
However, there are two solutions to this, which both work.
First, you can create a link to your .so library with the name .dll
ln -s /cygdrive/d/src/lib/libsupport.so libsupport.dll
In this case the makefile doesn't have to be changed and -lsupport will find the library while linking. I prefer this solution.
Second, you can specify the linker option with the full name.
LIBS:= -L /cygdrive/d/src/c/lib -l:libsupport.so
then you don't have to create a link.
So the crucial thing seems to be that the shared library must be in the PATH under cygwin. Using LD_LIBRARY_PATH doesn't help in that case as you can link the executable, but when trying to run it, it will not find it.
ldd nohupshd.exe
libsupport.so => not found
UPDATE: For some reason when I checked with ldd, my library was suddenly gone from the list. I found out that cygwin uses the name to differentiate between MS Windows and Unix shared libraries. So in order to make it work, the name of the library must be cyg.so to make it work, otherwise the exectuable seems to be some Windows build. In this case you don't need to create the link named x.dll as the shared library stays inside the Unix environment.
$(LNK) -o cyg$(TARGET).so $(OBJ) -shared
When using eclipse for debugging, the path to the shared library must also be in the windows path environment variable. Otherwise the debug session immediately terminates without an error.

Makefile with different rules for .o generation

If I have a rule like this in my make file:
CC = g++
CFLAGS = -Wall
COMPILE = $(CC) $(CFLAGS) -c
src = A.cpp \
main.cpp
test_src = Test.cpp
test = testAll
OBJFILES := $(patsubst %.cpp,%.o,$(src))
TEST_OBJS := $(patsubst %.cpp,%.o,$(test_src))
%.o: %.cpp
$(COMPILE) -I UnitTest++/src -LUnitTest++/ -l UnitTest++ -o $# $<
I end up including and linking UnitTest++ to non test files such as main and A.cpp
How can I make only make Test classes link with the test libraries?
Specify which files your rule applies to:
$(TEST_OBJS): %.o: %.cpp
$(COMPILE) -I UnitTest++/src -LUnitTest++/ -l UnitTest++ -o $# $<