How to compile a dll which needs other dlls - c

I'm trying to cross compile a piece of software I'm doing.
I'm on Linux and I'm having a pretty hard time trying to write a Makefile for compiling a DLL library using SDL2. Here is it:
#the compiler
CC = i686-w64-mingw32-gcc
#the standart ompilation flags of the project
CFLAGS = -O3 -Wall -Wno-unused-variable -Wno-unused-but-set-variable -Wno-implicit-function-declaration
#path to the folder's root, where the holy not build framework is. Relate to this Makefile
PREPATH = ..
#Path to the SDL, SDL_image and Lua includes and libs
SDL2INCLUDES = -I $(PREPATH)/SDL2/include
SDL2LIBS = $(PREPATH)/BINARIES/4windows/SDL2/64/SDL2.dll
SDLIMAGE2INCLUDES = -I $(PREPATH)/SDL2/SDL_image
SDLIMAGE2LIBS = $(PREPATH)/BINARIES/4windows/SDL2_image/64/SDL2_image.dll $(PREPATH)/BINARIES/4windows/SDL2_image/64/libjpeg-9.dll $(PREPATH)/BINARIES/4windows/SDL2_image/64/libpng16-16.dll $(PREPATH)/BINARIES/4windows/SDL2_image/64/libtiff-5.dll $(PREPATH)/BINARIES/4windows/SDL2_image/64/libwebp-4.dll $(PREPATH)/BINARIES/4windows/SDL2_image/64/zlib1.dll
#LUAINCLUDES = -I $(PREPATH)/lua/
#LUALIB = $(PREPATH)/lua/ -llua -lm
#Where to put the compiled program
COMPILEPATH = $(PREPATH)/BINARIES/
#Build options
build: NLF.o
cp ./*.o $(COMPILEPATH)
$(CC) $(CFLAGS) -shared -o $(COMPILEPATH)libNLF.dll $(SDL2LIBS) $(SDLIMAGE2LIBS) $(COMPILEPATH)*.o
NLF.o: NLF_osservice.o NLF_error.o NLF_screen.o NLF.h.gch
$(CC) -c -DBUILD_DLL $(CFLAGS) $(SDL2INCLUDES) $(SDLIMAGE2INCLUDES) NLF.c
NLF.h.gch: NLF.h
$(CC) $(CFLAGS) $(SDL2INCLUDES) $(SDLIMAGE2INCLUDES) NLF.h
NLF_osservice.o: NLF_osservice.h.gch
$(CC) -c -DBUILD_DLL $(CFLAGS) $(SDL2INCLUDES) NLF_osservice.c
NLF_osservice.h.gch:
$(CC) $(CFLAGS) $(SDL2INCLUDES) NLF_osservice.h
NLF_error.o: NLF_error.h.gch
$(CC) -c -DBUILD_DLL $(CFLAGS) $(SDL2INCLUDES) NLF_error.c
NLF_error.h.gch:
$(CC) $(CFLAGS) $(SDL2INCLUDES) NLF_error.h
NLF_screen.o: NLF_screen.h.gch
$(CC) -c -DBUILD_DLL $(CFLAGS) $(SDL2INCLUDES) $(SDLIMAGE2INCLUDES) NLF_screen.c
NLF_screen.h.gch:
$(CC) $(CFLAGS) $(SDL2INCLUDES) $(SDLIMAGE2INCLUDES) NLF_screen.h
#cleaning options
clean-build:
rm -f -v $(COMPILEPATH)*.o
clean-all:
rm -f -v ./*.o ./*.h.gch
rm -f -v $(COMPILEPATH)*.o $(COMPILEPATH)*.so
clean-soft:
rm -f -v ./*.o ./*.h.gch
rm -f -v $(COMPILEPATH)*.o
When running make all, the compilation runs fine, but when it gets to the -shared part, I get this:
../BINARIES/4windows/SDL2/64/SDL2.dll: file not recognized:
I tried to add -L before the Third Party DLL, like this:
SDL2LIBS = -L $(PREPATH)/BINARIES/4windows/SDL2/64/SDL2.dll
SDLIMAGE2LIBS = -L $(PREPATH)/BINARIES/4windows/SDL2_image/64/SDL2_image.dll -L $(PREPATH)/BINARIES/4windows/SDL2_image/64/libjpeg-9.dll -L $(PREPATH)/BINARIES/4windows/SDL2_image/64/libpng16-16.dll -L $(PREPATH)/BINARIES/4windows/SDL2_image/64/libtiff-5.dll -L $(PREPATH)/BINARIES/4windows/SDL2_image/64/libwebp-4.dll -L $(PREPATH)/BINARIES/4windows/SDL2_image/64/zlib1.dll
And then I get undefined reference errors...
The same error if I change the line:
$(CC) $(CFLAGS) -shared -o $(COMPILEPATH)libNLF.dll $(SDL2LIBS) $(SDLIMAGE2LIBS) $(COMPILEPATH)*.o
for
$(CC) $(CFLAGS) $(SDL2LIBS) $(SDLIMAGE2LIBS) -shared -o $(COMPILEPATH)libNLF.dll $(COMPILEPATH)*.o
Does anyone know what's going on?

You should not use -L before library files. -L indicates a library path. For library files, you should use -l (lowercase L).
But, if you're indicating the path to the file, and are including the file extension, you don't need to use -l, though. So the initial Makefile was correct in that sense.
You should provide the full error that you got, not just file not recognized:. I bet this is a file format not recognized error, which probably indicates that you should not be linking against a .dll file, but .lib files. Similar problem here.

I've solved!! here is how
Putting these files within the SDL path:
libSDL2.a, libSDL2.dll.a, libSDL2main.a, libSDL2_test.a, SDL2.lib, SDL2main.lib, and SDL2test.lib
And these with the SDL_image one.:
libSDL2_image.a and libSDL2_image.dll.a
And here is the Makefile:
#the compiler
CC = i686-w64-mingw32-gcc
#the standart ompilation flags of the project
CFLAGS = -O3 -Wall -Wno-unused-variable -Wno-unused-but-set-variable -Wno-implicit-function-declaration
#path to the folder's root, where the holy not build framework is. Relate to this Makefile
PREPATH = ..
#Path to the SDL, SDL_image and Lua includes and libs
SDL2INCLUDES = -I $DS(PREPATH)/SDL2/include
SDL2LIBS = -L$(PREPATH)/SDL2/4windows/SDL2/64 -lmingw32 -lSDL2main -lSDL2
SDLIMAGE2INCLUDES = -I $(PREPATH)/SDL2/SDL_image
SDLIMAGE2LIBS = -L$(PREPATH)/SDL2/4windows/SDL2_image/64 -lSDL2_image
#LUAINCLUDES = -I $(PREPATH)/lua/
#LUALIB = -L $(PREPATH)/lua/ -llua -lm
#Where to put the compiled program
COMPILEPATH = $(PREPATH)/BINARIES/
#Build options
build: NLF.o
cp ./*.o $(COMPILEPATH)
$(CC) $(CFLAGS) -shared $(COMPILEPATH)*.o $(SDL2LIBS) $(SDLIMAGE2LIBS) -o $(COMPILEPATH)libNLF.dll
NLF.o: NLF_osservice.o NLF_error.o NLF_screen.o NLF.h.gch
$(CC) -c -DBUILD_DLL $(CFLAGS) $(SDL2INCLUDES) $(SDLIMAGE2INCLUDES) NLF.c
NLF.h.gch: NLF.h
$(CC) $(CFLAGS) $(SDL2INCLUDES) $(SDLIMAGE2INCLUDES) NLF.h
NLF_osservice.o: NLF_osservice.h.gch
$(CC) -c -DBUILD_DLL $(CFLAGS) $(SDL2INCLUDES) NLF_osservice.c
NLF_osservice.h.gch:
$(CC) $(CFLAGS) $(SDL2INCLUDES) NLF_osservice.h
NLF_error.o: NLF_error.h.gch
$(CC) -c -DBUILD_DLL $(CFLAGS) $(SDL2INCLUDES) NLF_error.c
NLF_error.h.gch:
$(CC) $(CFLAGS) $(SDL2INCLUDES) NLF_error.h
NLF_screen.o: NLF_screen.h.gch
$(CC) -c -DBUILD_DLL $(CFLAGS) $(SDL2INCLUDES) $(SDLIMAGE2INCLUDES) NLF_screen.c
NLF_screen.h.gch:
$(CC) $(CFLAGS) $(SDL2INCLUDES) $(SDLIMAGE2INCLUDES) NLF_screen.h
#cleaning options
clean-build:
rm -f -v $(COMPILEPATH)*.o
clean-all:
rm -f -v ./*.o ./*.h.gch
rm -f -v $(COMPILEPATH)*.o $(COMPILEPATH)*.dll
clean-soft:
rm -f -v ./*.o ./*.h.gch
rm -f -v $(COMPILEPATH)*.o
Now my new problem is how to compile all this stuff to 32 bits windows. But it is an statement for another question.

Related

"clang: error: cannot specify -o when generating multiple output files" fix

I'm trying to compile my C project using clang (I'm on MacOS Monterry) and a Makefile, but I keep getting the same error from clang in the command line:
> make
gcc -c src/ji.c src/main.c -o src/ji.o
clang: error: cannot specify -o when generating multiple output files
make: *** [src/ji.o] Error 1
These are the only files I have in the project so far:
src/main.c
src/ji.c
include/ji.h
The Makefile looks like this:
cc = gcc
src = $(wildcard src/*.c)
obj = $(src:.c=.o)
exec = ji
$(exec): $(obj)
$(cc) -Iinclude $< -o build/$#
%.o: %.c
$(cc) -c $(src) -o $#
clean:
-rm src/*.o
-rm ji
From YouTube videos I've seen, this should be the ideal Makefile for the project but no matter what I change I get the error.
There are a few issues:
-Iinclude needs to be on the %.o: %.c rule command
In %.o: %.c, we don't want $(src) but rather $<
We want patsubst to get the .o list obj
The $(exec) target doesn't match the -o option
The clean doesn't match the placement of the executable
Here's a refactored version (e.g. one way to do this--there are others):
cc = gcc
src = $(wildcard src/*.c)
obj = $(patsubst %.c,%.o,$(src))
exec = build/ji
$(exec): $(obj)
mkdir -p build
$(cc) $^ -o $#
%.o: %.c
$(cc) -c $< -o $# -Iinclude
clean:
rm -f src/*.o
rm -fr build
Here's the output of make:
gcc -c src/ji.c -o src/ji.o -Iinclude
gcc -c src/main.c -o src/main.o -Iinclude
mkdir -p build
gcc src/ji.o src/main.o -o build/ji
Here's the output of make clean:
rm -f src/*.o
rm -fr build

make: create a test binary for each file in test directory

I have a simple structure as below for a small library I'm building.
I want make build to build the library (libproj.a) from sources under ./source
I want make build_test to build every source file under ./test prefixed with test_ into it's own binary
I can build the library libproj.a just fine, but can't figure out how to build the tests. I'm currently getting the following linker error when attempting to build /cygdrive/d/Source/proj/build/obj/test_proj.o:test_proj.c:(.text+0x15): undefined reference to 'test'.
Directory structure
+---build
| +---lib
| +---obj
| \---test
+---include
| \---proj
+---source
\---test
Makefile
PROJECT = proj
LIBNAME = lib$(PROJECT).a
CFLAGS = -Wall -Wextra -O0
DIR_ROOT = $(abspath .)
DIR_SRC_LIB = $(DIR_ROOT)/source
DIR_SRC_TEST = $(DIR_ROOT)/test
DIR_BLD_OBJ = $(DIR_ROOT)/build/obj
DIR_BLD_LIB = $(DIR_ROOT)/build/lib
DIR_BLD_TEST = $(DIR_ROOT)/build/test
LST_OBJ_LIB = $(patsubst $(DIR_SRC_LIB)/%.c, $(DIR_BLD_OBJ)/%.o, $(wildcard $(DIR_SRC_LIB)/*.c))
LST_OBJ_TEST = $(patsubst $(DIR_SRC_TEST)/%.c, $(DIR_BLD_OBJ)/%.o, $(wildcard $(DIR_SRC_TEST)/*.c))
LST_BIN_TEST = $(patsubst $(DIR_SRC_TEST)/%.c, $(DIR_BLD_TEST)/%, $(wildcard $(DIR_SRC_TEST)/test_*.c))
INCLUDES = -I $(DIR_ROOT)/include
clean:
$(RM) $(LST_OBJ_LIB)
$(RM) $(LST_OBJ_TEST)
build:
$(info build)
build-test: $(LST_BIN_TEST)
$(info build-test)
run-test:
$(info run-test)
install:
$(info install)
$(LIBNAME): $(LST_OBJ_LIB)
$(AR) rvs $(DIR_BLD_LIB)/$# $^
$(DIR_BLD_OBJ)/%.o: $(DIR_SRC_LIB)/%.c
$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $#
$(DIR_BLD_TEST)/%: $(DIR_BLD_OBJ)/%.o $(LIBNAME)
$(CC) $(LDFLAGS) -L $(DIR_BLD_LIB) -l $(PROJECT) $< -o $#
$(DIR_BLD_OBJ)/%.o: $(DIR_SRC_TEST)/%.c
$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $#
My guess is that this line:
$(CC) $(LDFLAGS) -L $(DIR_BLD_LIB) -l $(PROJECT) $< -o $#
is wrong. You're passing to the compiler (I'm assuming gcc) the libraries before the object files. If your compiler acts as gcc does, the code in the libraries is getting discarded because it hasn't been referenced yet when it parses them see -l option documentation.
It should be
$(CC) $(LDFLAGS) -L $(DIR_BLD_LIB) $< -l $(PROJECT) -o $#
(Note the changed position of $<)
Furthermore, remeber that the order of libraries is important: see this excellent explanation.

makefile exit with no reason when compile .pc and .c at the same time. very strange

I am using pro*c in AIX,I want make my .pc file compile to a .so libary. And link it. This is my directory:
ls
connect.pc func.c get_log.pc main.c makefile sql_err.pc
This is my makefile:
#Makefile
CC = cc -g -brtl
CFLAGS = -g -c
ESQL = proc
RM = rm -f
MYHOME = /home/xxx
OBJ = main.o func.o
LIBOBJ = get_log.o connect.o sql_err.o
DBINC = -I$(ORACLE_HOME)/precomp/public
DBLIB = -L$(ORACLE_HOME)/lib -lclntsh
INCLUDE = -I$(MYHOME)/include
.SUFFIXES: .pc .c .o
.pc.o:
$(ESQL) include=$(MYHOME)/include iname=$*.pc
$(CC) -o $*.o $(CFLAGS) $*.c $(INCLUDE) $(DBINC) $(DBLIB)
$(RM) $*.c
$(RM) $*.lis
libmydb.so:$(LIBOBJ)
$(CC) -qmkshrobj -o $# $(LIBOBJ) $(DBLIB)
mv $# $(MYHOME)/lib
query:$(OBJ)
cc -o $# $(OBJ) -L$(MYHOME)/lib -lmydb
mv $# $(MYHOME)/bin
func.o:func.c
$(CC) -c $(CFLAGS) $< $(INCLUDE)
main.o:main.c
$(CC) -c $(CFLAGS) $< $(INCLUDE)
clean:
rm -f *.o *.lis
when I make I get this:
.......
cc -g -brtl -o sql_err.o -g -c sql_err.c -I/home/xxx/include -I/oracle/product/10.2.0/precomp/public -L/oracle/product/10.2.0/lib -lclntsh
rm -f sql_err.c
rm -f sql_err.lis
cc -g -brtl -qmkshrobj -o libmydb.so get_log.o connect.o sql_err.o -L/oracle/product/10.2.0/lib -lclntsh
mv libmydb.so /home/xxxlib
when it done mv libmydb.so ,it exit!!!without wrong message.why?? I also need my .c to compile to .o and finally to an executable file query link libmydb.so.
when I change the squeuce like this put .c.o before .pc.o:
query:$(OBJ)
cc -o $# $(OBJ) -L$(MYHOME)/lib -lmydb
mv $# $(MYHOME)/bin
func.o:func.c
$(CC) -c $(CFLAGS) $< $(INCLUDE)
main.o:main.c
$(CC) -c $(CFLAGS) $< $(INCLUDE)
.pc.o:
$(ESQL) include=$(MYHOME)/include iname=$*.pc
$(CC) -o $*.o $(CFLAGS) $*.c $(INCLUDE) $(DBINC) $(DBLIB)
$(RM) $*.c
$(RM) $*.lis
libmydb.so:$(LIBOBJ)
$(CC) -qmkshrobj -o $# $(LIBOBJ) $(DBLIB)
mv $# $(MYHOME)/lib
it give this message,although I have libmydb.so last step:
prepaid(wmfe)/home/xxx/src>make
cc -g -brtl -c -g -c main.c -I/home/xxx/include
cc -g -brtl -c -g -c func.c -I/home/xxx/include
cc -o query main.o func.o -L/home/xxx/lib -lmydb
ld: 0706-006 Cannot find or open library file: -l mydb
ld:open(): A file or directory in the path name does not exist.
make: 1254-004 The error code from the last command is 255.
Stop.
I can't handle this ,very strange,Help!!
By default make will make the first rule in your makefile, but it must not start with a dot. So the default rule in your makefile is libmydb.so and that is being built.
That rule is only dependent on the LIBOBJ and OBJ is not a dependency so it doesn't care about those. It doesn't exit with no reason, it exits because it has done the job you defined for it. There is no error to report.
If you change the order then the default rule is changed and it tries to compile query. This has no dependencies to the library, so it doesn't try to compile that.
If you want to compile everything you should have, for example, a rule all that lists the dependencies. In this case probably libmydb.so and query at least, in correct order. If this is the first rule it will be the default and your compilation will succeed.

MakeFile: error: <jni.h>: No such file or directory

I am trying to call java from c, and I have made the following MakeFile:
include ../../Makefile.defs
auto_gen=
NAME=libproto.so
CC=gcc
CFLAGS= -g -Wall -fPIC
LIBS= -L'$(LD_LIBRARY_PATH)' -ljvm -I"/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.91.x86_64/include/" -I"/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.91.x86_64/include/linux" -I"/usr/local/lib64/kamailio/"
include ../../Makefile.modules
SOURCE=jni_wrapper.c ProtoType.c
OBJECTS=$(SOURCE:.c=.o)
all: $(SOURCE) $(NAME)
%.o: %.c
$(CC) $(CFLAGS) -c $(LIBS) $<
clean:
rm -f $(EXEC); rm -f *~; rm -f .*.swp; rm -f .*.swo; rm -f *.o
java:
javac ProtoType.java
jar cf ProtoType.jar ProtoType.class
javap -s -p ProtoType > sigs.txt
cat sigs.txt
When I compile with make I get an error like this:
error: <jni.h>: No such file or directory
I looked through many stackoverflow pages with a similar problem but they all have same solution which I already had implemented. They said you need to link the library path to jni.h.
As you can see in my MakeFile this is being done:
LIBS= -L'$(LD_LIBRARY_PATH)' -ljvm -I"/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.91.x86_64/include/" -I"/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.91.x86_64/include/linux" -I"/usr/local/lib64/kamailio/"
I triple checked the directories and the permissions and everything is fine.
Any Suggestions?
You need to add the end of your LIBS definition to the CFLAGS
CFLAGS= -g -Wall -fPIC -I"/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.91.x86_64/include/" -I"/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.91.x86_64/include/linux" -I"/usr/local/lib64/kamailio/"
LIBS= -L'$(LD_LIBRARY_PATH)' -ljvm
The -I include directories are used by the compiler not the linker. It's the compiler that can't find your .h file.
You may also want to change the targets as follows
%.o: %.c
$(CC) $(CFLAGS) -c $<
$(NAME): $(OBJECTS)
$(CC) $(OBJECTS) -o $# $(LIBS)
This will build you .so file.

Kdevelop4 path to library binaries

I'm having problem reported as below while trying to execute it. Where should I go to let it know where to find the .so lib which is under ${HOME}/projects/OpenImageIO/dist/linux64/lib?
Starting: /home/chaoren/Dropbox/hw2/hw2_3
/home/chaoren/Dropbox/hw2/hw2_3: error while loading shared libraries: libOpenImageIO.so.1.2: cannot open shared object file: No such file or directory
I built this project by importing my Makefile
OFILES = Matrix.o LinearAlgebra.o PerlinNoise.o Camera.o OIIOFiles.o Image.o Utilities.o Grid.o SparceGrid.o VolumeOperations.o Ray.o Face.o Line.o Lights.o Group.o PolySurf.o File.o OBJFile.o Vector.o
AFILES = $(OFILES)
ROOTDIR = .
LIB = $(ROOTDIR)/libVR.a
LINKS = Magick++-config --cppflags --cxxflags --ldflags --libs -lm -lOpenImageIO -L/usr/local/lib -L${HOME}/projects/OpenImageIO/dist/linux64/lib
INCLUDES = Magick++-config --cppflags --cxxflags -I${HOME}/projects/OpenImageIO/dist/linux64/include
CXX = g++ -Wall -g -O2 -D_THREAD_SAFE -pthread -fopenmp
.C.o:
$(CXX) -c $(INCLUDES) $<
all: $(AFILES)
ar rv $(LIB) $?
hw2_1: hw2_1.C
$(CXX) hw2_1.C $(INCLUDES) $(LIB) $(LINKS) -o hw2_1
hw2_2: hw2_2.C
$(CXX) hw2_2.C $(INCLUDES) $(LIB) $(LINKS) -o hw2_2
hw2_3: hw2_3.C
$(CXX) hw2_3.C $(INCLUDES) $(LIB) $(LINKS) -o hw2_3
noiseimage: noiseimage.C
$(CXX) noiseimage.C $(INCLUDES) $(LIB) $(LINKS) -o noiseimage
clean:
rm -f *.o *.gch core $(LIB) vr vrppm *~ vRender hw2_1 hw_2 hw2_3
KDevelop4 uses CMake as its default build system. In CMake all libraries and other program elements are identified in special file (CMakeLists.txt). That file then becomes the basis of the make file that actually builds the executable.

Resources