diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2016-10-27 16:29:52 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2016-10-27 16:29:52 -0700 |
commit | 53ab016bcb85e1b8924440907309b7b89449ca6f (patch) | |
tree | 865db22e13e478b06fccf9d164df803e9562390c | |
parent | dbbf8084e8e4d6c30bf38d649c6cbbb2c86c0134 (diff) | |
download | clink-master.tar.gz clink-master.tar.bz2 clink-master.zip |
This is old code developed in 2005 to replace the "clisp-link" script in
the CLISP project with GNU Makefile rules.
* Makefile: New file.
* binding.lisp: New file.
* call-in.lisp: New file.
* call-out.c: New file.
* clink.mk: New file.
* main.lisp: New file.
-rw-r--r-- | Makefile | 66 | ||||
-rw-r--r-- | binding.lisp | 15 | ||||
-rw-r--r-- | call-in.lisp | 2 | ||||
-rw-r--r-- | call-out.c | 9 | ||||
-rw-r--r-- | clink.mk | 253 | ||||
-rw-r--r-- | main.lisp | 2 |
6 files changed, 347 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c60caae --- /dev/null +++ b/Makefile @@ -0,0 +1,66 @@ +CFLAGS = $(CPPFLAGS) + +# +# Set up namespace for clink.mk +# + +CLK = CFOO_ + +# +# Set up input variables for clink.mk +# + +CFOO_SOURCE_LS := full +CFOO_TARGET_DIR := new/ +CFOO_MODULES := binding +CFOO_OBJECTS := call-out.o +CFOO_PRELOAD := call-in +CFOO_LOAD := main + +# +# all target should be the first one so make with no arguments +# does "make all" +# + +.PHONY all: + +all: + +# +# bring in the magic! +# + +include clink.mk + +# +# a clean target which includes the output variable produces by +# clink.mk, which expands to all of the targets and intermediate +# files produced by the rules therein. +# + +clean: + $(RM) $(CFOO_CLEAN) call-out.o + +# +# Phony target all depends on the Lisp executable and memory +# image, forcing them to be updated. +# + +all: new/$(CFOO_LISPRUN) new/lispinit.mem + +# +# Compiling the extra object files is outside of the responsibility +# of clink.mk, but clink.mk does take care of Lisp -> FAS compiling +# of all of the files mentioned in $(CLK)MODULES, $(CLK)PRELOAD and +# $(CLK)LOAD. +# + +call-out.o: call-out.c + $(CC) $(CFLAGS) -c -o $@ $< + +# +# A kind of test: after all the rules are read, if we switch the +# namespace, it should not screw up any of the rule bodies. +# + +CLK = BAR_ diff --git a/binding.lisp b/binding.lisp new file mode 100644 index 0000000..a1c1e21 --- /dev/null +++ b/binding.lisp @@ -0,0 +1,15 @@ +(eval-when (:compile-toplevel :load-toplevel :execute) + (setf ffi:*output-c-functions* t) + (setf ffi:*output-c-variables* t)) + +(ffi:def-call-out call-out + (:language :stdc) + (:name "call_out") + (:arguments (value ffi:c-string)) + (:return-type)) + +(ffi:def-call-in call-in + (:language :stdc) + (:name "call_in") + (:arguments (value ffi:c-string)) + (:return-type)) diff --git a/call-in.lisp b/call-in.lisp new file mode 100644 index 0000000..e6b82b3 --- /dev/null +++ b/call-in.lisp @@ -0,0 +1,2 @@ +(defun call-in (x) + (format t "(call-in ~a)~%" x)) diff --git a/call-out.c b/call-out.c new file mode 100644 index 0000000..42279a4 --- /dev/null +++ b/call-out.c @@ -0,0 +1,9 @@ +#include <stdio.h> + +extern void call_in(const char *); + +void call_out(const char *string) +{ + printf("call_out(\"%s\");\n", string); + call_in(string); +} diff --git a/clink.mk b/clink.mk new file mode 100644 index 0000000..e9582ac --- /dev/null +++ b/clink.mk @@ -0,0 +1,253 @@ +# +# clink.mk +# written by Kaz Kylheku +# June 2005 +# +# This a GNU Make include file that provides a system for creating a new CLISP +# linking set by adding modules to an existing one. These rules meet several +# objectives. They: +# +# - replace the arcane old 'clisp-link add-module-set' script; +# - create a lisp image directly, without file copying, symbolic +# links, generated shell scripts and other such things; +# - do not require the added module to be located in a particular +# directory setup with a link.sh script; all the files and dependencies +# are handled by these rules; +# - eliminate the use of clumsy symbolic links, since the new Lisp image +# is linked directly out of the source directory, using relative paths. +# +# This makefile is intended to be included into another Makefile. It requires +# certain inputs in the form of certain variables being set prior to the +# inclusion. It produces outputs by assigning to variables. +# +# Input variables: +# +# CLK A string serving as the namespace for all internal +# variables. This allows multiple independent instantiations +# of the rules within a single GNU make process. If +# you leave out this variable, it's set to CLINK_, +# and so all the $(CLK)X variables become just CLINK_X. +# $(CLK)SOURCE_LS The name of the existing CLISP linking set, such as +# "base" or "full" (without the quotes). This makefile +# will find the linking set by itself, provided that the +# clisp executable is in the executable search path. +# If this variable is not set, it takes on the default +# value "base". +# $(CLK)TARGET_DIR The directory where to place the resulting lisp.run +# and lispinit.mem, with trailing slash! +# $(CLK)MODULES Names of FFI modules with no .c or .lisp suffix. +# It's assumed that for each of these, there is a .lisp +# file containing CLISP FFI definitions, and is compiled +# compiled to produce a .c file and a .fas file. +# It's possible, but pointless, to leave this variable unset. +# $(CLK)OBJECTS Optional names of additional object files and libraries to +# load into the new CLISP executable. +# $(CLK)PRELOAD If this is not empty, then the boostrapping process +# will use an intermediate lispinit.mem, which will be +# stuffed with the specified Lisp modules. Probably the +# biggest use for this is to set up packages. If you are +# using DEF-CALL-OUT to make Lisp functions callable from C, +# and those functions are named by packaged symbols, then +# the package has to exist in the lispinit.mem, otherwise +# the lisp.run will fail to run at all. It will iterate +# over its global linked list of modules and bail when +# it sees references to nonexistent packages. But at this +# point we haven't had a chance to build our lispinit.mem. +# The way out of this chicken-egg problem is to build +# an intermediate lispinit.mem. +# $(CLK)LOAD List of Lisp modules to load into the final memory image, +# not including those listed in $(CLK)MODULES. +# +# Output variables: +# +# $(CLK)CLEAN List of intermediate files to be blown away by +# a "make clean". +# + +# -- internals start here -- + +# +# Set up a default namespace +# + +ifeq ($(CLK),) +CLK := CLINK_ +endif + +ifeq ($($(CLK)SOURCE_LS),) +$(CLK)SOURCE_LS := base +endif + +# +# $(CLK)CLISP_DIR holds the CLISP library directory, underneath which +# one finds the linkkit and linking sets. E.g. /usr/local/lib/clisp +# + +$(CLK)CLISP_DIR := $(shell clisp -q -norc -x \ + '(progn (princ *lib-directory*) (values))') + +# +# $(CLK)SOURCE_DIR is the source linking set, e.g. /usr/local/lib/clisp/full +# + +$(CLK)SOURCE_DIR := $($(CLK)CLISP_DIR)$($(CLK)SOURCE_LS)/ + +# +# $(CLK)SOURCE_RUN is the Lisp executable in the source linking set. +# It could be lisp.run, or lisp.exe on Cygwin. So we just get it +# using wildcard expansion. (The GNU Make $(wildcard) function +# doesn't expand variables in the pattern, so we use shell echo). +# + +$(CLK)SOURCE_RUN := $(filter-out %lisp.a,\ + $(shell echo $($(CLK)SOURCE_DIR)lisp.*)) + +$(CLK)LISPRUN := $(notdir $($(CLK)SOURCE_RUN)) + +# +# $(CLK)RUN_TGT is the target lisp.run that we want to build. +# $(CLK)MEM_TGT is the target lispinit.mem that we want to build. +# The rules in this makefile update that target, as well as the memory image. +# It's up to the parent makefile to hook these targets as dependencies in its +# own set of rules, so that these targets actually get updated. +# + +$(CLK)RUN_TGT := $($(CLK)TARGET_DIR)$($(CLK)LISPRUN) +$(CLK)MEM_TGT := $($(CLK)TARGET_DIR)lispinit.mem +$(CLK)MOD_TABLE_TGT := $($(CLK)TARGET_DIR)modules.o +$(CLK)MOD_HEADER_TGT := $($(CLK)TARGET_DIR)modules.h +$(CLK)PRELOAD_FAS_TGTS := $(addsuffix .fas,$($(CLK)PRELOAD)) +$(CLK)PRELOAD_LIB_TGTS := $(addsuffix .lib,$($(CLK)PRELOAD)) +$(CLK)LOAD_FAS_TGTS := $(addsuffix .fas,$($(CLK)LOAD)) +$(CLK)LOAD_LIB_TGTS := $(addsuffix .lib,$($(CLK)LOAD)) +$(CLK)FAS_TGTS := $(addsuffix .fas,$($(CLK)MODULES)) +$(CLK)C_TGTS := $(addsuffix .c,$($(CLK)MODULES)) +$(CLK)OBJ_TGTS := $(addsuffix .o,$($(CLK)MODULES)) +$(CLK)LIB_TGTS := $(addsuffix .lib,$($(CLK)MODULES)) +$(CLK)VARS_MKF := $($(CLK)TARGET_DIR)vars.mk +$(CLK)CLEAN := $($(CLK)RUN_TGT) $($(CLK)MEM_TGT) $($(CLK)MOD_TABLE_TGT) \ + $($(CLK)VARS_MKF) $($(CLK)FAS_TGTS) $($(CLK)C_TGTS) \ + $($(CLK)OBJ_TGTS) $($(CLK)LIB_TGTS) $($(CLK)MOD_HEADER_TGT) \ + $($(CLK)PRELOAD_FAS_TGTS) $($(CLK)PRELOAD_LIB_TGTS) \ + $($(CLK)LOAD_FAS_TGTS) $($(CLK)LOAD_LIB_TGTS) +$(CLK)ALL_OBJ_TGTS := $($(CLK)OBJ_TGTS) $($(CLK)MOD_TABLE_TGT) + +# +# Rule to create the vars.mk file in the target directory. +# This rule also creates the target directory, if it does +# not exist. Since vars.mk is a dependency of this makefile +# itself by way of include, this rule is processed first, +# and so ensures that the target directory exist. +# + + +$($(CLK)VARS_MKF): + mkdir -p $(CLINK_TARGET_DIR) + . $(CLINK_SOURCE_DIR)makevars ; \ + echo "\$$(\$$(CLK)RUN_TGT): CFLAGS += $$CFLAGS" > $@ ; \ + echo "\$$(\$$(CLK)ALL_OBJ_TGTS): CPPFLAGS += $$CPPFLAGS" >> $@ ; \ + echo "\$$(\$$(CLK)RUN_TGT): CLFLAGS += $$CLFLAGS" >> $@ ; \ + echo "\$$(CLK)LIBS := $$LIBS" >> $@ + +$($(CLK)MOD_TABLE_TGT): CFLAGS += -I$(CLINK_TARGET_DIR) + +$($(CLK)MOD_TABLE_TGT): $($(CLK)CLISP_DIR)linkkit/modules.c \ + $($(CLK)MOD_HEADER_TGT) + $(CC) $(CFLAGS) -c -o $@ $< + +$($(CLK)MOD_HEADER_TGT): + $(RM) $@ + for mod in $(CLINK_MODULES) ; do echo "MODULE($$mod)" >> $@ ; done + +ifneq ($(MAKECMDGOALS),clean) +include $($(CLK)VARS_MKF) +endif + +# +# $(CLK)SOURCE_ARS is the list of archive files in the source linking +# set. We get this by way of the $(CLK)LIBS variable in the makevars file +# in that directory, rather than by wildcard globbing. The reason for +# that is that we don't want to mistakenly include libnoreadline.a. +# + +$(CLK)SOURCE_ARS := $(foreach LIB,$($(CLK)LIBS),\ + $(if $(filter -%,$(LIB)),,$($(CLK)SOURCE_DIR)$(LIB))) + +# +# $(CLK)SOURCE_LIBS is a list of additional libraries that need +# to be linked. Like $(CLK)SOURCE_ARS, this comes from the $(CLK)LIBS variable +# in the makevars file of the source linking set. +# + +$(CLK)SOURCE_LIBS := $(foreach LIB,$($(CLK)LIBS),\ + $(if $(filter -%,$(LIB)),\ + $(LIB),)) + +$($(CLK)RUN_TGT): $($(CLK)SOURCE_ARS) $($(CLK)MOD_TABLE_TGT) \ + $($(CLK)OBJ_TGTS) $($(CLK)OBJECTS) + $(CC) $(CFLAGS) $(CLFLAGS) -o $@ $^ $(CLINK_SOURCE_LIBS) + +$($(CLK)OBJ_TGTS): $($(CLK)C_TGTS) + $(CC) $(CFLAGS) -I$(CLINK_CLISP_DIR)linkkit -o $@ $^ -c + +$($(CLK)C_TGTS): %.c: %.lisp + "$(CLINK_SOURCE_RUN)" -B "$(CLINK_CLISP_DIR)" \ + -M "$(CLINK_SOURCE_DIR)lispinit.mem" -q -c $< + +$($(CLK)PRELOAD_FAS_TGTS): %.fas: %.lisp + "$(CLINK_SOURCE_RUN)" -B "$(CLINK_CLISP_DIR)" \ + -M "$(CLINK_SOURCE_DIR)lispinit.mem" -q -c $< + +$($(CLK)LOAD_FAS_TGTS): %.fas: %.lisp + "$(CLINK_RUN_TGT)" -B "$(CLINK_CLISP_DIR)" \ + -M "$(CLINK_INTERMEDIATE_MEM)" -q -c $< + +# +# If $(CLK)PRELOAD contains something, then we need to set up rules that +# make an intermediate memory image by loading these files using the original +# linking set. The new CLISP binary is then used in conjunction with this +# intermediate image to load more Lisp code and dump the final image. +# + +ifeq ($($(CLK)PRELOAD),) +$(CLK)INTERMEDIATE_MEM := $($(CLK)SOURCE_DIR)lispinit.mem +else +$(CLK)INTERMEDIATE_MEM := $($(CLK)TARGET_DIR)intermediate.mem + +$(CLK)CLEAN += $($(CLK)INTERMEDIATE_MEM) + +$($(CLK)INTERMEDIATE_MEM): $($(CLK)PRELOAD_FAS_TGTS) + "$(CLINK_SOURCE_RUN)" -B "$(CLINK_CLISP_DIR)" \ + -M "$(CLINK_SOURCE_DIR)lispinit.mem" -norc -q -i \ + $(CLINK_PRELOAD) -x "(saveinitmem \"$@\")" +endif + +$($(CLK)MEM_TGT): $($(CLK)RUN_TGT) $($(CLK)INTERMEDIATE_MEM) \ + $($(CLK)FAS_TGTS) $($(CLK)LOAD_FAS_TGTS) + "$(CLINK_RUN_TGT)" -B "$(CLINK_CLISP_DIR)" \ + -M "$(CLINK_INTERMEDIATE_MEM)" -norc -q -i \ + $(CLINK_MODULES) $(CLINK_LOAD) -x "(saveinitmem \"$@\")" + +# +# Hack: GNU Make has a problem. Variables that occur in +# rule action bodies are expanded when those rules are run, not when +# they are defined, and there doesn't appear to be a way to change +# the behavior. So the namespace trick $($(CLK)VAR) won't work +# within rule bodies; the value of the global variable CLK will be taken at the +# time the rule is run to update its target, not at the time the makefile is +# read out. The target-specific-assignment mechanism, however, gives us a kind +# of dynamic scoping namespace surrounding a target, so here we exploit that to +# create target-local ``bindings'' of all our global namespaced variables. We +# use those bindings in rule bodies. +# + +$($(CLK)CLEAN): CLINK_TARGET_DIR := $($(CLK)TARGET_DIR) +$($(CLK)CLEAN): CLINK_CLISP_DIR := $($(CLK)CLISP_DIR) +$($(CLK)CLEAN): CLINK_SOURCE_DIR := $($(CLK)SOURCE_DIR) +$($(CLK)CLEAN): CLINK_SOURCE_RUN := $($(CLK)SOURCE_RUN) +$($(CLK)CLEAN): CLINK_MODULES := $($(CLK)MODULES) +$($(CLK)CLEAN): CLINK_SOURCE_LIBS := $($(CLK)SOURCE_LIBS) +$($(CLK)CLEAN): CLINK_PRELOAD := $($(CLK)PRELOAD) +$($(CLK)CLEAN): CLINK_LOAD := $($(CLK)LOAD) +$($(CLK)CLEAN): CLINK_INTERMEDIATE_MEM := $($(CLK)INTERMEDIATE_MEM) +$($(CLK)CLEAN): CLINK_RUN_TGT := $($(CLK)RUN_TGT) diff --git a/main.lisp b/main.lisp new file mode 100644 index 0000000..75ffce3 --- /dev/null +++ b/main.lisp @@ -0,0 +1,2 @@ +(defun main () + (call-out "hello")) |