I am trying to compile an example program to use HDF-EOS. The example code is taken from the HDF-EOS website (I will therefore only post the top section):
/* This example shows how to read a data field in HDF-EOS2 grid data. */
#include <mfhdf.h>
#include <hdf.h>
#include <HdfEosDef.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
int32 gridfile1;
int32 grid1;
int32 datafield1rank;
int32 datafield1dimsize[32];
int32 datafield1type;
char datafield1dimname[512];
float32 *datafield1data;
int32 i, j;
/* Open 'AMSR_E_L3_RainGrid_B05_200707.hdf' using grid API */
if ((gridfile1 = GDopen("AMSR_E_L3_RainGrid_B05_200707.hdf", DFACC_RDONLY)) == -1) {
fprintf(stderr, "error: cannot open grid 'AMSR_E_L3_RainGrid_B05_200707.hdf'\n");
return -1;
}
return 0;
The corresponding make file looks like this:
HDF4_DIR=<hdf4_path>
HDFEOS2_DIR=<hdfeos2_path>
CC=$(HDF4_DIR)/bin/h4cc
CFLAGS=-I$(HDFEOS2_DIR)/include
LDFLAGS=-L$(HDFEOS2_DIR)/lib
LIBS=-lhdfeos -lGctp
read_grid: read_grid.c
$(CC) $(CFLAGS) $(LDFLAGS) $< $(LIBS) -o $#
In addition to the above mentioned paths I have also added links to the hdf5 library, so my make file looks like this:
HDF4_DIR=<hdf4_path>
HDFEOS2_DIR=<hdfeos2_path>
HDF5_DIR=<hdf5_path>
CC=$(HDF4_DIR)/bin/h4cc
CFLAGS=-I$(HDFEOS2_DIR)/include -I$(HDF4_DIR)/include -I$(HDF5_DIR)/include
LDFLAGS=-L$(HDFEOS2_DIR)/lib64 -L$(HDF4_DIR)/lib64 -L$(HDF5_DIR)/lib64
LIBS=-lhdfeos -lGctp
read_grid: read_grid.c
$(CC) read_hdf_eos.c $(CFLAGS) $(LDFLAGS) $(LIBS) -o $#
The problem now is that it does not compile, throwing linking errors such like this:
<hdfeos2_path>/lib64/libhdfeos.a(GDapi.o): In function `lamazDxDtheta':
<hdfeos2_path>/src/GDapi.c:9579: undefined reference to `sin'
<hdfeos2_path>/src/GDapi.c:9580: undefined reference to `sin'
...
collect2: error: ld returned 1 exit status
So for me this looks like a linking problem, however I have no idea why.
To add to the confusion I get another error:
read_grid.o: In function `main':
read_grid.c:(.text.startup+0x0): multiple definition of `main'
read_grid.o:read_grid.c:(.text.startup+0x0): first defined here
Of course I have not defined main more than once. In a second example program that throws the same linking errors I do not get this error.
So if some one would have an idea on the first problem, the linking, I would be very happy.
SOLUTION:
add -lm at the end of the compile statement in the, removes the linking problem
remove the read_hdf_eos.c in the compile statement, that caused the multiple main issue
Thanks for the comments and hints.
Related
I am getting undefined reference error while trying to compile main that refers to two libraries. I have two files lib1/func1.c and lib2/func2.c in separate folders. Those files contain two functions print1() and print2(), function print1() is calling print2().
I am compiling those separately into two libraries libfunc1.a and libfunc2.a.
But when I am trying to compile main which is calling print1(), I get the following error:
/usr/bin/ld: /home/sv/ztest2/lib1/libfunc1.a(func1.o): in function print1:
/home/sv/ztest2/lib1/func1.c:7: undefined reference to print2
collect2: error: ld returned 1 exit status
make: *** [Makefile:21: DP] Error 1
Here is the code and Makefiles:
Makefile:
TARGET = DP
HOME = /home/slav/FORECAST/ztest2
INCDIRS = -I./ \
-I$(HOME)/lib1 \
-I$(HOME)/lib2
LIBDIRS = -L$(HOME)/lib1 \
-L$(HOME)/lib2
SRCFILES = DP.c
OBJFILES = DP.o
CFLAGS = -g -O3 $(INCDIRS)
all: $(TARGET)
$(TARGET): $(OBJFILES)
cc $(CFLAGS) -o $(TARGET) $(OBJFILES) $(LIBDIRS) -lfunc2 -lfunc1
clean:
-rm *.o $(TARGET)
DP.c:
#include "func1.h"
int main()
{
print1();
return 0;
}
func1.h:
void print1();
func1.c:
#include <stdio.h>
void print1()
{
printf("print1 is called!\n");
print2();
}
func2.h:
extern void print2();
func2.c:
#include <stdio.h>
void print2()
{
printf("print2 is called!\n");
}
Libraries must be listed in the order their symbols are needed.
The command cc $(CFLAGS) -o $(TARGET) $(OBJFILES) $(LIBDIRS) -lfunc2 -lfunc1 tells the linker to first use the func2 library to resolve any pending references in the executable it is building and then to use the func1 library.
Since the linker processes func2 first, and, at the time it does so, there is no pending reference to print2, the linker does not include the module with print2 in the executable.
Later, when the linker is processing func1, it includes the module with print1 in the executable because main uses it. That module print1 uses print2, so including that module adds a new reference to print2. Then, when the linker is done processing func1, it has an unresolved reference. The linker does not go back to func2 to check it again.
Since the func1 library depends on func2, change the link command to cc $(CFLAGS) -o $(TARGET) $(OBJFILES) $(LIBDIRS) -lfunc1 -lfunc2.
(If the func2 library also depends on func1, that is a bad design and should be reconsidered. If it is not changed, asking the linker to reconsider the libraries multiple times, as with -lfunc1 -lfunc2 -lfunc1, might fix the immediate problem, but others can arise.)
I have simplified the code to the minimum
#include "frozen.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
int main()
{
char *json = "{ \"a\": 123, \"b\": \"hi\", c: true }";
int value = 0;
json_scanf(json, strlen(json), "{c: %B}", &value);
printf("Hello World\n");
// assert( json != NULL );
printf( "json: %s\n", json );
printf( "json.c: %s\n", value );
// free( json );
return 0;
}
directory structure:
/home/projects/json-test/main.c
/home/projects/json-test/frozen/{contents of https://github.com/cesanta/frozen repo}
What I do:
gcc main.c -Ifrozen -o main
What is being displayed in output:
main /tmp/ccsYWNAP.o: In function `main': main.c:(.text+0x43):
undefined reference to `json_scanf' collect2: error: ld returned 1
exit status
I have very limited knowledge in C, thus I may be missing some steps, so take into account that I literally did not do anything else than written above, maybe I should have. I am used to loosely typed php/js/python kind of languages, but I was reading that just including file does not tell gcc that "you should search for json_scanf inside frozen.h". Should there be some sort of a "glue", or "linking" step I am missing?
UPDATE: Based on responses, I have created this Makefile:
CC = gcc
FLAGS = -std=c99
DEST_DIR = ./bin
DEST_PATH = "$(DEST_DIR)/main"
BUILD_DIR = ./build
all: clean directories json main.o
$(CC) $(BUILD_DIR)/*.o -o $(DEST_PATH) $(FLAGS)
main.o: src/main.c $(BUILD_DIR)/frozen.o
$(CC) src/main.c -c -o $(BUILD_DIR)/main.o $(FLAGS)
json: json.o
json.o: src/frozen/frozen.c src/frozen/frozen.h
$(CC) src/frozen/frozen.c -c -o $(BUILD_DIR)/frozen.o $(FLAGS)
clean:
rm -rf $(BUILD_DIR)
directories:
mkdir -p $(DEST_DIR)/
mkdir -p $(BUILD_DIR)/
And changing #include "frozen.h" to #include "frozen/frozen.h", and running make, creates build/main file that can be successfully ran with ./bin/main command. Thank you!
Ugh. You don't have a mistake. The library developer has some really bad coding practices. Basically, for whatever reason, his header is not sufficient for compilation. If you look at the unit_test.c in the repository of frozen, you will see he's actually including frozen.c instead of frozen.h. If you change your #include "frozen.h" to #include "frozen.c" it will work fine. The other option is to provide the .c file explicitly:
gcc frozen/frozen.c main.c -Ifrozen
Normally, you'd put everything in the header, or require the library to be compiled, as a .a file and then linked when you use it, but he hasn't provided a makefile that does that.
EDIT: You can also compile frozen.o beforehand, but the library's author should've really provided a makefile to do that...
gcc -c frozen.c -o ../frozen.o
cd ..
gcc main.c frozen.o -Ifrozen
I made a shared library as the follow:
gcc -c output.c
gcc -shared -fPIC -o liboutput.so output.o
When output.c is the follow, it could work.
//#include "output.h"
#include <stdio.h>
int output(const char* st) {
return 1+2;
}
But, when output.c changed as the follow, a error occur.
//#include "output.h"
#include <stdio.h>
int output(const char* st) {
printf("%s\n", st);
return 1+2;
}
This is error message:
/usr/bin/ld: output.o: relocation R_X86_64_PC32 against undefined 符号 `puts##GLIBC_2.2.5' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: 最后的链结失败: 错误的值
collect2: error: ld returned 1 exit status
I want to know why and how to deal it. Thanks in advance.
You need to compile output.c as position independent code.
gcc -c -fPIC output.c
In the first version you have not called any library function. But in second one printf is being called. In general, compile all sources with -fPIC if you intend to build a shared library later.
im new to writing makefile. Now im trying to use pjsip c-library, which i installed in my home-directory. I took a little snipped and tried to compile it. Had some errors and so i searched for an solution, so i found out i had to include this library's to the search path. Further there is a possibility to declare them in the makefile, so i tried the 2nd solution.
Here my makefile:
pjpath=home/pi/pjproject-2.4.5
LIB=-L/$(pjpath)/pjlib/lib -L/$(pjpath)/pjlib-util/lib -L/$(pjpath)/pjnath/lib -L/$(pjpath)/pjmedia/lib -L/$(pjpath)/pjsip/lib
INC=-I/$(pjpath)/pjlib/include -I/$(pjpath)/pjlib-util/include -I/$(pjpath)/pjnath/include -I/$(pjpath)/pjmedia/include -I/$(pjpath)/pjsip/include
all:
gcc -o test $(INC) simple_pjsua.c $(LIB) -lpj -lpjlib -lpjnath -lpjmedia -lpjmedia-audiodev -lpjmedia-codec -lpjmedia-videodev -lpjsdp -lpjsip -lpjsip-simple -lpjsip-ua -lpjsua -lpjsua2
clean:
rm simple_pjsua.o test
and here my c-file simple_pjsua.c:
#define PJ_IS_LITTLE_ENDIAN 1
#define PJ_IS_BIG_ENDIAN 0
#include <pjsua-lib/pjsua.h>
#define THIS_FILE "App"
#define SIP_USER "demo-user2"
#define SIP_DOMAIN "sip:192.168.2.59"
#define SIP_PASSWD "123456"
static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id, pjsip_rx_data *rdata);
static void on_call_state(pjsua_call_id call_id, pjsip_event *e);
static void on_call_media_state(pjsua_call_id call_id);
static void error_exit(const char *title, pj_status_t status);
int main(int argc, char *argv[]){
printf("Hello World");
return 0;
}
static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id, pjsip_rx_data *rdata){
pjsua_call_info ci;
PJ_UNUSED_ARG(acc_id);
PJ_UNUSED_ARG(rdata);
pjsua_call_get_info(call_id, &ci);
PJ_LOG(3,(THIS_FILE, "Incoming call from %.*s!!", (int) ci.remote_info.slen, ci.remote_info.ptr));
/* Automatically answer incoming calls with 200/OK */
pjsua_call_answer(call_id, 200, NULL, NULL);
}
static void on_call_state(pjsua_call_id call_id, pjsip_event *e){
pjsua_call_info ci;
PJ_UNUSED_ARG(e);
pjsua_call_get_info(call_id, &ci);
PJ_LOG(3,(THIS_FILE, "Call %d state=%.*s", call_id, (int) ci.state_text.slen, ci.state_text.ptr));
}
static void on_call_media_state(pjsua_call_id call_id){
pjsua_call_info ci;
pjsua_call_get_info(call_id, &ci);
if (ci.media_status == PJSUA_CALL_MEDIA_ACTIVE) {
pjsua_conf_connect(ci.conf_slot, 0);
pjsua_conf_connect(0, ci.conf_slot);
}
}
static void error_exit(const char *title, pj_status_t status){
pjsua_perror(THIS_FILE, title, status);
pjsua_destroy();
exit(1);
}
and this is my output of the makefile:
gcc -o test -I/home/pi/pjproject-2.4.5/pjlib/include -I/home/pi/pjproject-2.4.5/pjlib-util/include -I/home/pi/pjproject-2.4.5/pjnath/include -I/home/pi/pjproject-2.4.5/pjmedia/include -I/home/pi/pjproject-2.4.5/pjsip/include simple_pjsua.c -L/home/pi/pjproject-2.4.5/pjlib/lib -L/home/pi/pjproject-2.4.5/pjlib-util/lib -L/home/pi/pjproject-2.4.5/pjnath/lib -L/home/pi/pjproject-2.4.5/pjmedia/lib -L/home/pi/pjproject-2.4.5/pjsip/lib -lpj -lpjlib -lpjnath -lpjmedia -lpjmedia-audiodev -lpjmedia-codec -lpjmedia-videodev -lpjsdp -lpjsip -lpjsip-simple -lpjsip-ua -lpjsua -lpjsua2
In file included from /home/pi/pjproject-2.4.5/pjlib/include/pj/config.h:288:0,
from /home/pi/pjproject-2.4.5/pjlib/include/pj/types.h:33,
from /home/pi/pjproject-2.4.5/pjsip/include/pjsip/sip_config.h:27,
from /home/pi/pjproject-2.4.5/pjsip/include/pjsip/sip_types.h:34,
from /home/pi/pjproject-2.4.5/pjsip/include/pjsip.h:24,
from /home/pi/pjproject-2.4.5/pjsip/include/pjsua-lib/pjsua.h:30,
from simple_pjsua.c:3:
/home/pi/pjproject-2.4.5/pjlib/include/pj/config_site.h:3:35: warning: extra tokens at end of #include directive [enabled by default]
/usr/bin/ld: cannot find -lpj
/usr/bin/ld: cannot find -lpjlib
/usr/bin/ld: cannot find -lpjnath
/usr/bin/ld: cannot find -lpjmedia
/usr/bin/ld: cannot find -lpjmedia-audiodev
/usr/bin/ld: cannot find -lpjmedia-codec
/usr/bin/ld: cannot find -lpjmedia-videodev
/usr/bin/ld: cannot find -lpjsdp
/usr/bin/ld: cannot find -lpjsip
/usr/bin/ld: cannot find -lpjsip-simple
/usr/bin/ld: cannot find -lpjsip-ua
/usr/bin/ld: cannot find -lpjsua
/usr/bin/ld: cannot find -lpjsua2
collect2: ld returned 1 exit status
makefile:6: recipe for target 'all' failed
make: *** [all] Error 1
I also found a useful site which explains how it's done, although i couldn't yet figure it out.
First of all, the first warning is from the library code, your code isn't guilty.
Then, always specify link libraries after all of your source or object files. By default GNU linker doesn't remember the symbols from libraries which haven't been referenced yet, so it simply drops out all of your -lsomelib if that somelib hasn't been referenced by a previous object or library.
So, I bet, the line
gcc -o test $(INC) simple_pjsua.c $(LIB)
would help you (or at least this particular error would be resolved).
so i found the the simplest solution at this Site, in the section makefile with version 1.6 or later.
# If your application is in a file named myapp.cpp or myapp.c
# this is the line you will need to build the binary.
all: myapp
myapp: myapp.cpp
$(CC) -o $# $< `pkg-config --cflags --libs libpjproject`
clean:
rm -f myapp.o myop
Worked for me, but there was one clue which i stumble over.
This is important and is also described at the bottom of the page i linked. If you notice there are spaces towards the bottom of the file (before $(CC) and rm, these are a single tab, not spaces. This is important, or otherwise make command will fail with "missing separator" error.
I'm trying to compile a program using mixed C and Ocaml sources, with the main of the application in C calling some pieces of OCaml code.
All right, no problem here, It's seems to be a common operation, fully documented, easy to do with the standard Ocaml tools.
Let me explain a bit, this kind of compilation is divided in 4 steps : Caml compiling to Caml objects, then compiling the Caml to C objects, then compiling the C files, and lastly compiling all the C objects together and getting the executable.
The theory is, the Ocaml compiler will embed the Caml runtime, GC, and all its stuff automatically, and we just have to indicate if we use whichever the ocaml bytecode (referencing -lcamlrun) or the native binary (referencing -lasmrun).
So, it seems to be quite simple, let's do it. Steps 1, 2 and 3 went as expected, good!
Only the 4th step is problematic. Just take a look:
cc -o /home/thomas/Documents/projects/ocaml/GogoGame/bin/GogoPlayer.exe \
-L/usr/lib/ocaml -lcamlrun \
/home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o \
/home/thomas/Documents/projects/ocaml/GogoGame/src/init.o \
/home/thomas/Documents/projects/ocaml/GogoGame/src/interface.o \
/home/thomas/Documents/projects/ocaml/GogoGame/src/caml_func.oo
/home/thomas/Documents/projects/ocaml/GogoGame/src/interface.o: In function `main':
interface.c:(.text+0x0): multiple definition of `main'
/usr/lib/ocaml/libcamlrun.a(main.o):(.text+0x0): first defined here
/usr/lib/ocaml/libcamlrun.a(floats.o): In function `caml_exp_float':
(.text+0x488): undefined reference to `exp'
/usr/lib/ocaml/libcamlrun.a(floats.o): In function `caml_fmod_float':
(.text+0x4f9): undefined reference to `fmod'
/usr/lib/ocaml/libcamlrun.a(floats.o): In function `caml_log_float':
(…)
/usr/lib/ocaml/libcamlrun.a(unix.o): In function `caml_dlopen':
(.text+0x2ed): undefined reference to `dlopen'
/usr/lib/ocaml/libcamlrun.a(unix.o): In function `caml_dlclose':
(.text+0x300): undefined reference to `dlclose'
/usr/lib/ocaml/libcamlrun.a(unix.o): In function `caml_dlsym':
(.text+0x31b): undefined reference to `dlsym'
/usr/lib/ocaml/libcamlrun.a(unix.o): In function `caml_dlerror':
(.text+0x342): undefined reference to `dlerror'
/home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o:(.data.rel+0xc): undefined reference to `caml_array_get_addr'
/home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o:(.data.rel+0x10): undefined reference to `caml_array_get_float'
(...)
/home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o:(.data.rel+0x31c): undefined reference to `caml_lazy_make_forward'
/home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o:(.data.rel+0x320): undefined reference to `caml_get_public_method'
/home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o:(.data.rel+0x3ac): undefined reference to `caml_terminfo_setup'
/home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o:(.data.rel+0x3b0): undefined reference to `caml_terminfo_backup'
/home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o:(.data.rel+0x3b4): undefined reference to `caml_terminfo_standout'
/home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o:(.data.rel+0x3b8): undefined reference to `caml_terminfo_resume'
/home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__f_1030':
(.text+0xc): undefined reference to `camlPervasives'
/home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__f_1030':
(.text+0x11): undefined reference to `camlPervasives__output_string_1191'
/home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__f_1030':
(.text+0x19): undefined reference to `camlPervasives__string_of_int_1130'
/home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__f_1030':
(.text+0x20): undefined reference to `camlPervasives'
/home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__f_1030':
(.text+0x25): undefined reference to `camlPervasives__output_string_1191'
/home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__format_result_1034':
(.text+0x9c): undefined reference to `camlPrintf__sprintf_1414'
/home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__entry':
(.text+0xe1): undefined reference to `caml_c_call'
/home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__entry':
(.text+0xfb): undefined reference to `caml_c_call'
/home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__entry':
(.text+0x115): undefined reference to `caml_c_call'
/home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__f_1030':
(.text+0x32): undefined reference to `camlPervasives__print_newline_1276'
collect2: ld returned 1 exit status
make: *** [GogoPlayer] Error 1
IMHO, it seems that there is two errors:
Multiple definitions of main
The linker doesn't find the module Pervasive
I have really no idea how to fix that, maybe I have to link an other file.
Does someone have an idea ?
As asked, I put the code that give these errors. It will be quite simple because there is very little code, most of it was given in an example in the documentation.
init.ml
let f x = print_string "f is applied to "; print_int x; print_newline()
let rec fib n = if n < 2 then 1 else fib(n-1) + fib(n-2)
let format_result n = Printf.sprintf "Result is: %d\n"
let _ =
Callback.register "Arbitrary Name" f;
Callback.register "fib" fib;
Callback.register "format_result" format_result
caml_func.c
#include <stdio.h>
#include <string.h>
#include <caml/mlvalues.h>
#include <caml/callback.h>
void call_caml_f(int x)
{
static value * closure_f = NULL;
if (closure_f == NULL) /* First time around, look up by name */
closure_f = caml_named_value("Arbitrary Name");
caml_callback(*closure_f, Val_int(x));
}
int fib(int n)
{
static value * fib_closure = NULL;
if (fib_closure == NULL) fib_closure = caml_named_value("fib");
return Int_val(caml_callback(*fib_closure, Val_int(n)));
}
char * format_result(int n)
{
static value * format_result_closure = NULL;
if (format_result_closure == NULL)
format_result_closure = caml_named_value("format_result");
return strdup(String_val(caml_callback(*format_result_closure, Val_int(n))));
/* We copy the C string returned by String_val to the C heap
so that it remains valid after garbage collection. */
}
interface.c
#include <stdio.h>
#include "caml_func.c"
#define BYTECODE
int main(int argc, char **argv)
{
#ifdef BYTECODE
caml_startup(argv);
#else
caml_main(argv);
#endif
/* Make sure that stdout is not block buffered. */
setbuf(stdout, NULL);
/* Process GTP commands. */
//gtp_main_loop(commands, stdin, NULL);
// CAML code here ?
return 0;
}
And this is all. Obviously, I skipped all the meaningless stuff as this simple example should work and does not. It must be my Makefile, which follows.
By the way, it's quite ugly. If you have proposals for this kind of application (Caml inside C), or refactoring suggestions, I'll take them all.
Makefile.ocaml
.PHONY: all clean mrproper
# RULES and EXEC are magically set in Makefile.magic
all: depend $(RULES) $(EXE)
#echo [DONE]
mli: $(CAML_ONLY:.ml=.mli)
ml-byte: $(CAML_ONLY:.ml=.cmo)
ml-called-byte: $(CAML_CALLED_BY_C:.ml=.$(OBJ))
ml-nativ: $(CAML_ONLY:.ml=.cmx)
ml-called-nativ: $(CAML_CALLED_BY_C:.ml=.$(OBJ))
c-wrapper: $(C_WRAPPERS:.c=.oo)
c-only: $(C_ONLY:.c=.o)
$(EXE):
$(CC) -o $(BIN)/$(EXE).exe \
$(FLAGS) \
-L$(OCAMLLIB) $(LINKED) -l$(RUNLIB) \
$(wildcard $(SRC)/*.$(OBJ)) $(wildcard $(SRC)/*.oo) # */
%.o: %.c
$(CC) $(FLAGS_C) -c $< -o $(SRC)/$(*F).o
%.mli: %.ml
$(OCAMLC) $(FLAGS_ML) -i $< > $(SRC)/$(*F).mli
%.cmi: %.mli
$(OCAMLC) $(FLAGS_ML) -c $< -o $(SRC)/$(*F).cmi
%.cmo: %.ml
$(CAMLC) $(FLAGS_ML) -c $< -o $(SRC)/$(*F).cmo
%.cmx: %.ml
$(CAMLOPT) $(FLAGSOPT) -c $< -o $(SRC)/$(*F).cmx
# native
%.o: %.ml
$(cd $(SRC))
$(OCAMLC) -output-obj -o $(*F)_camlcode.o \
$(FLAGS_MLC) \
$<
# bytecode
%.ob: %.ml
$(cd $(SRC))
$(OCAMLOPT) -output-obj -o $(*F)_camlcode.ob \
$(FLAGS_MLC) \
$<
%.oo: %.c
$(CC) $(FLAGS_WRAP) -c $< -o $(SRC)/$(*F).oo
clean_mli:
rm -f $(SRC)/*.mli # */
clean:
rm -f $(BIN)/*.{a,o,oo,cmi,cmo,cmx} # */
rm -f $(SRC)/*.{a,o,oo,cmi,cmo,cmx} # */
mrproper: clean, clean_mli
rm -f $(BIN)/$(EXE)
depend:
$(OCAMLDEP) $(INCLUDES) $(SRC)/*.ml $(SRC)/*.mli > .depend # */
include .depend
Your link command is incorrect in two ways:
You need to link with -ldl for dlopen, etc.
You must put libraries after objects that reference them (i.e. your -lcamlrun arguments is in the wrong place on the link line). The order of arguments on the link line matters.