Skip to content

Commit

Permalink
Replace Unix with custom stubs
Browse files Browse the repository at this point in the history
These are required for macOS anyway, might as well remove `Unix` again.
  • Loading branch information
Leonidas-from-XIV committed Mar 14, 2024
1 parent d3d2731 commit 061afee
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 15 deletions.
4 changes: 2 additions & 2 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -723,8 +723,8 @@ fi
# Write Makefile.config

parts="findlib"
ocamlfind_ocamlflags="-I +dynlink"
ocamlfind_archives="findlib.cma"
ocamlfind_ocamlflags="-I +unix -I +dynlink"
ocamlfind_archives="findlib.cma unix.cma"
if [ $with_toolbox -gt 0 ]; then
parts="$parts findlib-toolbox"
fi
Expand Down
24 changes: 14 additions & 10 deletions src/findlib/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,17 @@ OCAMLLEX = ocamllex
#CAMLP4O = camlp4 pa_o.cmo pa_op.cmo pr_dump.cmo --


OBJECTS = fl_compat.cmo fl_split.cmo findlib_config.cmo \
OBJECTS = fl_compat.cmo fl_split.cmo fl_bindings.cmo findlib_config.cmo \
fl_metatoken.cmo fl_meta.cmo fl_metascanner.cmo fl_topo.cmo \
fl_package_base.cmo findlib.cmo fl_args.cmo fl_lint.cmo
COBJECTS = fl_stubs.o
TOBJECTS = topfind.cmo

XOBJECTS = $(OBJECTS:.cmo=.cmx)
TXOBJECTS = topfind.cmx
TXOBJECTS = $(TOBJECTS:.cmo=.cmx)

OCAMLFIND_OBJECTS = ocaml_args.cmo frontend.cmo
OCAMLFIND_XOBJECTS = ocaml_args.cmx frontend.cmx
OCAMLFIND_XOBJECTS = $(OCAMLFIND_OBJECTS:.cmo=.cmx)

# OCAMLFIND_ARCHIVES: set in Makefile.config
OCAMLFIND_XARCHIVES = $(OCAMLFIND_ARCHIVES:.cma=.cmxa)
Expand All @@ -55,22 +56,22 @@ ocamlfind$(EXEC_SUFFIX): findlib.cma $(OCAMLFIND_OBJECTS)
$(OCAMLC_FLAGS) $(OCAMLFIND_OCAMLFLAGS) $(OCAMLFIND_OBJECTS)

ocamlfind_opt$(EXEC_SUFFIX): findlib.cmxa $(OCAMLFIND_XOBJECTS)
$(OCAMLOPT) -o ocamlfind_opt$(EXEC_SUFFIX) unix.cmxa $(OCAMLFIND_XARCHIVES) \
$(OCAMLOPT) -o ocamlfind_opt$(EXEC_SUFFIX) $(OCAMLFIND_XARCHIVES) \
$(OCAMLOPT_FLAGS) $(OCAMLFIND_OCAMLFLAGS) $(OCAMLFIND_XOBJECTS)

test_parser$(EXEC_SUFFIX): fl_metascanner.cmx test_parser.cmx fl_metatoken.cmx fl_meta.cmx
$(OCAMLOPT) -o test_parser$(EXEC_SUFFIX) fl_meta.cmx fl_metatoken.cmx fl_metascanner.cmx test_parser.cmx

findlib.cma: $(OBJECTS)
$(OCAMLC) -a -o findlib.cma unix.cma $(OBJECTS)
findlib.cma: $(OBJECTS) $(COBJECTS)
$(OCAMLC) -a -o findlib.cma $(OBJECTS) $(COBJECTS)

findlib_top.cma: $(TOBJECTS)
$(OCAMLC) -a -o findlib_top.cma $(TOBJECTS)

findlib.cmxa: $(XOBJECTS)
$(OCAMLOPT) -a -o findlib.cmxa $(XOBJECTS)
findlib.cmxa: $(XOBJECTS) $(COBJECTS)
$(OCAMLOPT) -a -o findlib.cmxa $(XOBJECTS) $(COBJECTS)
if [ $(HAVE_NATDYNLINK) -gt 0 ]; then \
$(OCAMLOPT_SHARED) -shared -o findlib.cmxs $(XOBJECTS); \
$(OCAMLOPT_SHARED) -shared -o findlib.cmxs $(XOBJECTS) $(COBJECTS); \
fi

findlib_top.cmxa: $(TXOBJECTS)
Expand Down Expand Up @@ -162,7 +163,7 @@ depend: *.ml *.mli fl_meta.ml fl_metascanner.ml findlib_config.ml topfind.ml

# Some 'make' implementations require that .SUFFIXES must occur before
# the first suffix rule. (E.g. AIX)
.SUFFIXES: .mll .cmo .cmi .cmx .ml .mli .mml
.SUFFIXES: .mll .cmo .cmi .cmx .ml .mli .mml .o
# .src

.mml.cmo:
Expand All @@ -180,6 +181,9 @@ depend: *.ml *.mli fl_meta.ml fl_metascanner.ml findlib_config.ml topfind.ml
.mli.cmi:
$(OCAMLC) $(OPAQUE) $(OCAMLC_FLAGS) $(OCAMLFIND_OCAMLFLAGS) -c $<

.c.o:
$(OCAMLC) $(OPAQUE) $(OCAMLC_FLAGS) $(OCAMLFIND_OCAMLFLAGS) -c $<

#.src.ml:
# $(CAMLP4O) -impl $< -o $@

Expand Down
8 changes: 5 additions & 3 deletions src/findlib/findlib_config.mlp
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,11 @@ let location = lazy (
let base = Filename.basename command_name in
match base with
| "ocamlfind" as name -> (
let exe_location = Unix.readlink "/proc/self/exe" in
match install_dir_from_binary exe_location with
| Some install_dir -> Some install_dir
match Lazy.force Fl_bindings.executable_path with
| Some exe_location -> (
match install_dir_from_binary exe_location with
| Some install_dir -> Some install_dir
| None -> find_in_path name)
| None -> find_in_path name)
| _ ->
try_vars [
Expand Down
3 changes: 3 additions & 0 deletions src/findlib/fl_bindings.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
external get_executable_path : unit -> string option = "fl_executable_path"

let executable_path = lazy (get_executable_path ())
80 changes: 80 additions & 0 deletions src/findlib/fl_stubs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#include <unistd.h>
#include <sys/stat.h>
#include <caml/mlvalues.h>
#include <caml/alloc.h>
#include <caml/memory.h>

/* caml_executable_name exists but doesn't support macOS on all compiler versions */
char* fl_caml_executable_name(void) {
#if defined(__linux__)
int namelen, retcode;
char * name;
struct stat st;

/* lstat("/proc/self/exe") returns st_size == 0 so we cannot use it
to determine the size of the buffer. Instead, we guess and adjust. */
namelen = 256;
while (1) {
name = caml_stat_alloc(namelen);
retcode = readlink("/proc/self/exe", name, namelen);
if (retcode == -1) { caml_stat_free(name); return NULL; }
if (retcode < namelen) break;
caml_stat_free(name);
if (namelen >= 1024*1024) return NULL; /* avoid runaway and overflow */
namelen *= 2;
}
/* readlink() does not zero-terminate its result.
There is room for a final zero since retcode < namelen. */
name[retcode] = 0;
/* Make sure that the contents of /proc/self/exe is a regular file.
(Old Linux kernels return an inode number instead.) */
if (stat(name, &st) == -1 || ! S_ISREG(st.st_mode)) {
caml_stat_free(name); return NULL;
}
return name;

#elif defined(__APPLE__)
unsigned int namelen;
char * name;

namelen = 256;
name = caml_stat_alloc(namelen);
if (_NSGetExecutablePath(name, &namelen) == 0) return name;
caml_stat_free(name);
/* Buffer is too small, but namelen now contains the size needed */
name = caml_stat_alloc(namelen);
if (_NSGetExecutablePath(name, &namelen) == 0) return name;
caml_stat_free(name);
return NULL;

#else
return NULL;

#endif
}

/* redefinitions of macros and helpers from newer ocaml */
#define Fl_Tag_some 0
#define Fl_Val_none Val_int(0)

CAMLprim value fl_caml_alloc_some(value v)
{
CAMLparam1(v);
value some = caml_alloc_small(1, Fl_Tag_some);
Field(some, 0) = v;
CAMLreturn(some);
}

CAMLprim value fl_executable_path(value unit) {
CAMLparam1(unit);
CAMLlocal2(caml_path, caml_result);
char* path = fl_caml_executable_name();
if (path != NULL) {
caml_path = caml_copy_string(path);
caml_result = fl_caml_alloc_some(caml_path);
caml_stat_free(path);
} else {
caml_result = Fl_Val_none;
}
CAMLreturn(caml_result);
}

0 comments on commit 061afee

Please sign in to comment.