Embed Julia in C -- cflags and ldflags - makefile

How does one portably find cflags and ldflags of a julia install to pass to a C compiler?
I am trying to embed Julia in a C application. Right now I can hardcode julia libraries in the compile line, but I would prefer to find a mechanism that is a bit more portable.
Here is my current Makefile which require the julia executable to be pointing into the source directory.
JULIA_BIN = $(shell dirname `which julia`)
JULIA_PATH = $(JULIA_BIN)/../..
JULIA_LIBDIR = $(JULIA_PATH)/usr/lib
JULIA_CFLAGS = -I$(JULIA_PATH)/src -I$(JULIA_PATH)/src/support I$(JULIA_PATH)/include/julia -I$(JULIA_PATH)/usr/include
JULIA_LDFLAGS = -L$(JULIA_LIBDIR) -Wl,-rpath -Wl,$(JULIA_LIBDIR) -ljulia
$(LIBTD_JULIA): td.h td_julia.c $(LIBTD)
$(CC) $(DEBUG) -fPIC -c td_julia.c -o td_julia.o $(JULIA_CFLAGS)
$(CC) $(DEBUG) -shared -fPIC td_julia.o -o $# $(JULIA_LDFLAGS) ./$(LIBTD)

Related

How to create targets into specific directory with make?

My path:
./folder1/folder2/
My makefile is located in folder1.
My makefile:
CC = g++
FLAGS = -o3 -std=c++11
all: prng.o exec
prng.o: ./folder2/prng.cpp
$(CC) $(FLAGS) -o $# $<
exec: prng.o
/$<
prng.o is generated in folder1. I want it to be generated in folder2. How to do that?
CC = g++
FLAGS = -o3 -std=c++11
all: folder1/prng.o exec
folder1/prng.o: folder2/prng.cpp
$(CC) $(FLAGS) -o $# $<
exec: prng.o
/$<
BTW, your C compiler should have a C11 binary, something like /usr/bin/c11. That would let you say,
CC = c11
CFLAGS = -o3
Also, by using CFLAGS (instead of FLAGS), you shouldn't have to mention it in the recipe.

Link static library using gcc with gnu make

I'm following Zed Shaw's tutorial "Learn C the Hard Way" and trying to teach myself c programming language.
On my ubuntu desktop, I encountered the linking problem he mentioned in the note of this post.
That is, when linking a static library with gcc, using a command like this:
gcc -Wall -g -DNDEBUG -lmylib ex29.c -o ex29
The linker fails to find the functions in the lib. To link correctly, I have to change the order of source file and lib to this:
gcc -Wall -g -DNDEBUG ex29.c -lmylib -o ex29
And I'm trying to use the makefile offered by Zed to automate unit test. The makefile looks like this:
TEST_SRC=$(wildcard tests/*_tests.c)
TESTS=$(patsubst %.c,%,$(TEST_SRC))
TARGET=build/libYOUR_LIBRARY.a
tests: CFLAGS += $(TARGET)
tests: $(TESTS)
sh ./tests/runtests.sh
The rest part of the makefile that isn't listed here can build the $(TARGET) lib flawlessly.
The problem is Zed append the lib to the $(CFLAGS) and use the implicit rule to compile the test files which leads to a command like this:
gcc -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG tests/hashmap_tests.c build/mylib.a -o tests/list_tests
The command fails because of the link problem mentioned before as expected.
The solution I came up with was to write the compilation command explicitly like this so I can change the order:
$(TESTS): $(TARGET)
$(CC) $(CFLAGS) $^ $(TARGET) -o $#
This works fine if there is only one main source file. Unfortunately, I have several out there under the ./tests directory, and a command like this is a total disaster.
My question is, how should I change my makefile to make it work or is there any other way I can do the same work as elegant as expected?
CFLAGS holds compiler flags, like -g -O2. You should not add linker flags to it. CPPFLAGS holds preprocessor flags like -Isrc -DNDEBUG. LDFLAGS holds linker flags, which would include things like -L (capital L) if you need it to find libraries, and -rdynamic. And the LDLIBS variable holds libraries, so you should do this:
CPPFLAGS = -Isrc -DNDEBUG
CFLAGS = -g -O2 -Wall -Wextra
LDFLAGS = -rdynamic
LDLIBS = -lmylib
Now you can use the built-in rules for GNU make to build your program. You can see a list of the build-in rules by running make -p -f/dev/null.
Of course the above are just the default variables make defines and uses with its default rules. You don't have to use them, but in general it's better to follow conventions rather than flaunt them.

adding shared library path to Makefile

I want to add the shared library path to my Makefile. I have put in the export command in the makefile, it even gets called, but I still have to manually export it again.
What is the correct approach?
Makefile:
SOURCES = kwest_main.c fusefunc.c dbfuse.c logging.c dbbasic.c dbinit.c dbkey.c metadata_extract.c plugins_extraction.c import.c
LIBS = -L$(LIB) -lfuse -lsqlite3 -lkw_taglib -ltag_c -ltag -Wl,-rpath=.
INCLUDE = ../include
LIB = ../lib
EXE = kwest
CC = gcc
CCFLAGS = -g -Wall -Wextra -std=gnu99 -pedantic-errors -I$(INCLUDE)
OFLAGS = -c
ARCH = $(shell getconf LONG_BIT)
X = -D_FILE_OFFSET_BITS=$(ARCH)
OBJECTS = $(SOURCES:.c=.o)
$(EXE) : $(OBJECTS)
$(CC) -o $(EXE) $(OBJECTS) $(LIBS)
%.o: %.c
$(CC) $(OFLAGS) $(CCFLAGS) $<
fusefunc.o: fusefunc.c
$(CC) $(OFLAGS) $(CCFLAGS) $< $X
kwest_libs: kw_taglib
--->export LD_LIBRARY_PATH=$(LIB):$LD_LIBRARY_PATH
kw_taglib: plugin_taglib
plugin_taglib: plugin_taglib.o kwt_upd_meta.o
gcc -g -shared -I$(INCLUDE) -Wl,-soname,libkw_taglib.so -o $(LIB)/libkw_taglib.so -ltag -ltag_c plugin_taglib.o kwt_upd_meta.o
plugin_taglib.o:
gcc -c -g -I$(INCLUDE) -Wall -Wextra -pedantic-errors -std=gnu99 -fPIC -ltag_c -c plugin_taglib.c
kwt_upd_meta.o:
g++ -c -g -I$(INCLUDE) -Wall -Wextra -pedantic-errors -fPIC -ltag kwt_upd_meta.cpp
c: clean
clean:
rm -rf *.o
rm -rf *.db
ca: cleanall
cleanall: clean
rm -rf $(EXE)
ob: cleanall
rm -rf ~/.config/$(EXE)/
Execution:
$ ./kwest mnt
./kwest: error while loading shared libraries: libkw_taglib.so: cannot open shared object file: No such file or directory
$ export LD_LIBRARY_PATH=../lib:D_LIBRARY_PATH
$ ./kwest mnt
"executes correctly"
The usual way is to copy the dynamic library during the default make and to one of the standard library path
/usr/local/bin
or one of your project library path and add the library to executable using
-L/project/specific/path
during make install.
As already mentioned here, the thing you probably want is the linker option -rpath.
Like that, you can set a default search path for the binary. Looks like you even already use -rpath in your makefile, but you specify the wrong path:
LIBS = -L$(LIB) -lfuse -lsqlite3 -lkw_taglib -ltag_c -ltag -Wl,-rpath=.
So the binary will search in the current directory for dyn-libraries.
However, you add ../lib to your LD_LIBRARY_PATH later, for execution of the binary, so the given path . seems to be wrong.
Please take a try for the following fix:
LIBS = -L$(LIB) -lfuse -lsqlite3 -lkw_taglib -ltag_c -ltag -Wl,-rpath=../lib
Like that you should not need to specify a LD_LIBRARY_PATH for execution.

compile with gsl with an existing makefile

i have a makefile for some code library i'm using and now i've added to that code some code that uses gsl. i'm not so sure how and what to add to the makefile (which i wat to keep since it's invoking boost as well) that would invoke gsl.
This is my makefile:
CXX = g++
ARCH = -mtune=generic
# ARCH = -march=core2
# ARCH = -march=native
COFLAGS = $(ARCH) -O3 -pipe
CXXFLAGS = -Wall $(COFLAGS)
PROGRAMS = getData analyzeData
BOOSTFLAGS = -I .
OPENMP = -fopenmp -DSUPPORT_OPENMP
all: $(PROGRAMS)
getData: getData.cpp common.o parse.o common.h
$(CXX) $(CXXFLAGS) getData.cpp common.o parse.o -o getData
analyzeData: analyzeData.cpp common.o parse.o parameters.o
$(CXX) $(CXXFLAGS) $(BOOSTFLAGS) $(OPENMP) estimateCrossReplicatesExpression.cpp common.o parse.o parameters.o -o analyzeData
parameters.o: parameters.cpp parameters.h
parse.o: parse.cpp parse.h
common.o: common.cpp common.h
clean:
rm *.o $(PROGRAMS)
In case GSL is installed on the default path (/usr/local/include/gsl) on your system, the compilation command for a source file "example.c" would be
gcc -Wall -I/usr/local/include -c example.c
The library is installed as a single file, libgsl.a. A shared version of the library libgsl.so is also installed on systems that support shared libraries. The default location of these files is /usr/local/lib. If this directory is not on the standard search path of your linker you will also need to provide its location as a command line flag.
To link against the library you need to specify both the main library and a supporting cblas library, which provides standard basic linear algebra subroutines. A suitable cblas implementation is provided in the library libgslcblas.a if your system does not provide one. The following example shows how to link an application with the library,
$ gcc -L/usr/local/lib example.o -lgsl -lgslcblas -lm
The option -lm links with the system math library. On some systems it is not needed.
Thus, you need to specify the gsl specific flags in your compile command. Update the Makefile accordingly.

How should a very simple Makefile look like for Cuda compiling under linux

I want to compile a very basic hello world level Cuda program under Linux. I have three files:
the kernel: helloWorld.cu
main method: helloWorld.cpp
common header: helloWorld.h
Could you write me a simple Makefile to compile this with nvcc and g++?
Thanks,
Gabor
I've never heard of Cuda before, but from the online documentation it looks as if X.cu is supposed to be compiled into X.o, so having helloWorld.cu and helloWorld.cpp is not a good idea. With your permission I'll rename the "kernel" helloKernel.cu, then this should work:
NVCC = nvcc
helloWorld.o: helloWorld.cpp helloWorld.h
$(NVCC) -c %&lt -o $#
helloKernel.o: helloKernel.cu
$(NVCC) -c %&lt -o $#
helloWorld: helloWorld.o helloKernel.o
$(NVCC) %^ -o $#
(Note that those leading spaces are tabs.)
If that works, try a slicker version:
NVCC = nvcc
helloWorld.o: %.o : %.cpp %.h
helloKernel.o: %.o : %.cu
%.o:
$(NVCC) -c %&lt -o $#
helloWorld: helloWorld.o helloKernel.o
$(NVCC) %^ -o $#
Just in case, here's my variant. I use it to compile CUDA projects on Mac, but I think it will suit Linux too. It requires CUDA SDK.
BINDIR = ./ # places compiled binary in current directory
EXECUTABLE := helloWorld
CCFILES := helloWorld.cpp
CUFILES := helloWorld.cu
# an ugly part - setting rootdir for CUDA SDK makefile
# look for common.mk - I don't know where SDK installs it on Linux -
# and change ROOTDIR accordingly
ROOTDIR := /Developer/GPU\ Computing/C/common
include $(ROOTDIR)/../common/common.mk
My version, verbose but transparent:
myapp: myapp.o
g++ -fPIC -o $# $< -L /usr/local/cuda/lib -lcudart
myapp.o: myapp.cu
/usr/local/cuda/bin/nvcc --compiler-options -fno-strict-aliasing \
-I/usr/local/cuda/include \
-DUNIX -O2 -o $# -c $<
matrixMul: matrixMul.o
g++ -fPIC -o $# $< -L /usr/local/cuda/lib -lcudart
# It MUST be named .cu or nvcc compiles as regular C !!! (no __global__)
matrixMul.o: matrixMul.cu
/usr/local/cuda/bin/nvcc --compiler-options -fno-strict-aliasing \
-I/usr/local/cuda/include \
-DUNIX -O2 -o $# -c $<
Here is an example what my current project looks like. As you can see there is a few OpenGL libraries
ce : cudaExample.c cudaExample.h
cp cudaExample.c cudaExample.cu
/usr/local/cuda/bin/nvcc -arch=sm_20 -o ce -lglut -lGL -lGLU -lXext -lXmu -lX11 -lm cudaExample.cu
then run make ce
and ./ce

Resources