mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-08 10:23:03 +00:00
Estimated hours taken: 10
Introduce two new directories, trace and browser, containing libraries
holding the C and Mercury code of the debugger respectively. (Although
the browser directory does not have a browser in it yet, the browser
should soon become its biggest component.) Take the opportunity to
rename the existing libraries, for consistency.
After this change, the linking order becomes:
the object of the auto-generated init file
program object files
trace library (libmer_trace.a)
browser library (libmer_browser.a)
standard library (libmer_std.a)
runtime library (libmer_rt.a)
Boehm collector (libgc.a)
To avoid circularities, libraries cannot contain direct calls to
any routines that are defined in libraries (or object files) that
occur earlier in the above list. Any such calls must be made into
indirect calls via function pointers.
In particular, there was a circularity caused by the library calling
MR_trace() which invokes the tracer which in turn invokes the
library. This circularity was broken by having MR_trace(),
which is defined in the runtime, call the tracer indirectly via
a global variable named MR_trace_func_ptr. This global variable
is initialized by the auto-generated *_init.c file.
To avoid linking in the tracer even when it is not being used,
this global variable is only set to point to MR_trace_real()
if you're using a debugging grade or if c2init was invoked
with the `-t' flag. Otherwise it is set to MR_trace_fake()
which just prints an error message telling the user to
rebuild the executable with debugging enabled.
Makefile.DLLs:
Reserve random locations for the two new libraries. Whether they work
will be decided by testing on Windows.
Mmake.common.in:
Add variables naming the new directories, and create variables
naming the libraries.
Mmakefile:
Add targets for the new directories, and modify existing rules
as appropriate.
browser/Mmakefile:
Mmakefile for the new directory, modelled on library/Mmakefile.
browser/browser_library.m:
Umbrella file for the new directory, modelled on library/library.m.
{browser,library}/debugger_interface.m:
Moved this file from library to browser without change.
browser/help.m:
A new module for the help system of the debugger. Not yet used.
compiler/Mmakefile:
Update to refer to the new directories and libraries where
appropriate.
compiler/mercury_compile.m:
If we are doing tracing, then pass -t instead of -i to c2init.
compiler/modules.m:
When generating the .dep file, get the grade flags passed to c2init.
doc/Mmakefile:
Remove the special treatment of library/debugger_interface.m.
library/Mmakefile:
Update to refer to the new directories and libraries where
appropriate, and to conform to the new name of the library.
library/library.m:
Do not import debugger_interface.
profiler/Mmakefile:
Update to refer to the new directories and libraries where
appropriate.
runtime/Mmakefile:
Update to refer to the new directories and libraries where
appropriate, and to conform to the new name of the library.
Remove references to files being moved to the trace directory.
runtime/mercury_init.h:
Refer to the automatically generated dll header file by its new name
(renamed because the runtime library is renamed).
Add declarations to support the new global variable MR_trace_func_ptr.
runtime/mercury_memory_handlers.c:
runtime/mercury_memory_zones.c:
runtime/mercury_misc.c:
Remove inappropriate #includes of "mercury_trace.h", and substitute
a #include of "mercury_trace_base.h" if necessary.
{runtime,trace}/mercury_trace.[ch]:
{runtime,trace}/mercury_trace_external.[ch]:
{runtime,trace}/mercury_trace_internal.[ch]:
Move these files from the runtime to the trace directory.
The only changes are the removal from mercury_trace.h of declarations
added to runtime/mercury_trace_base.h, and the change from MR_trace
to MR_trace_real.
runtime/mercury_trace_base.[ch]:
Define MR_trace(), which does an indirect call through
MR_trace_func_ptr if the event should be traced.
Define MR_trace_fake, which just prints an error message.
Its address will be assigned to MR_trace_func_ptr if tracing
is not enabled.
Define the types needed by the signature of MR_trace.
Fix an old bug: s/MERCURY_TRACE_PERMANENT_H/MERCURY_TRACE_BASE_H/.
runtime/mercury_wrapper.[ch]:
Add the new global variable MR_trace_func_ptr.
scripts/c2init.in:
Add a new option, -t/--trace, which enables tracing by causing the
address of MR_trace_real to be assigned to MR_trace_func_ptr.
Have this option be implied by the grade. Also have the old option
-i (need initialization code) be implied by the grade, as well as by
-t.
scripts/ml.in:
Include the new libraries in the link command.
tests/debugger/Mmakefile:
Include -t instead of -i in the list of c2init options. (-t implies
-i.)
tools/bootcheck:
Copy and build the new directories as appropriate. The trace directory
is treated like the runtime, the browser directory is treated like the
library.
trace/Mmakefile:
Mmakefile for the new directory, modelled on runtime/Mmakefile.
util/mkinit.c:
Add the new option -t, as discussed above.
Mmakefile for the new directory, modelled on runtime/Mmakefile.
util/Mmakefile:
Specify -O0, since with the default optimization level, gcc on
cyclone ignores the assignment of TRUE to need_tracing when -t is
given (!!!).
198 lines
7.2 KiB
Makefile
198 lines
7.2 KiB
Makefile
#-----------------------------------------------------------------------------#
|
|
# Copyright (C) 1997-1998 The University of Melbourne.
|
|
# This file may only be copied under the terms of the GNU General
|
|
# Public Licence - see the file COPYING in the Mercury distribution.
|
|
#-----------------------------------------------------------------------------#
|
|
|
|
# Makefile.DLLs, version 0.5b.
|
|
|
|
# This Makefile contains rules for creating DLLs on Windows using gnu-win32.
|
|
|
|
#-----------------------------------------------------------------------------#
|
|
|
|
# The SYM_PREFIX is used as a prefix for the symbols in the files
|
|
# that this makefile automatically generates.
|
|
#
|
|
# The default SYM_PREFIX for libfoo.dll is `libfoo'.
|
|
# But you can override this by setting `SYM_PREFIX-libfoo = blah'.
|
|
|
|
SYM_PREFIX = $(firstword $(SYM_PREFIX-$*) $*)
|
|
|
|
GUARD_MACRO = $(SYM_PREFIX)_GLOBALS_H
|
|
DEFINE_DLL_MACRO = $(SYM_PREFIX)_DEFINE_DLL
|
|
USE_DLL_MACRO = $(SYM_PREFIX)_USE_DLL
|
|
IMP_MACRO = $(SYM_PREFIX)_IMP
|
|
GLOBAL_MACRO = $(SYM_PREFIX)_GLOBAL
|
|
IMPURE_PTR = $(SYM_PREFIX)_impure_ptr
|
|
|
|
# You should change your rule for creating `foo.a' to instead
|
|
# create `foo$(DLL_DEF_LIB).a'. Then this makefile will create
|
|
# `foo.a' from `foo_def.a'.
|
|
DLL_DEF_LIB = _def
|
|
|
|
# This rule creates a `.def' file, which lists the symbols that are exported
|
|
# from the DLL. We use `nm' to get a list of all the exported text (`T')
|
|
# symbols and data symbols -- including uninitialized data (`B'),
|
|
# initialized data (`D'), read-only data (`R'), and common blocks (`C').
|
|
# We also export `_impure_ptr', suitably renamed, so that the
|
|
# main program can do the necessary initialization of the DLL's _impure_ptr.
|
|
# (Since there can be more than one DLL, we must rename _impure_ptr as
|
|
# $(SYM_PREFIX)_impure_ptr to prevent name collisions.)
|
|
%.def: %_def.a
|
|
echo EXPORTS > $@
|
|
echo $(IMPURE_PTR) = _impure_ptr >> $@
|
|
nm $< | sed -n '/^........ [BCDRT] _/s/[^_]*_//p' >> $@
|
|
|
|
# We need to use macros to access global data:
|
|
# the user of the DLL must refer to `bar' as `(*__imp_bar)'.
|
|
# This rule creates a pair of files `foo_dll.h' and `foo_globals.h'
|
|
# which contains macros for doing this.
|
|
#
|
|
# The DLL may also contain some references to _impure_ptr
|
|
# (e.g. stdin is defined as a macro which expands to _impure_ptr.stdin).
|
|
# We need to provide a definition for this (otherwise it will link in
|
|
# the definition in libccrt.o, which causes lots of problems,
|
|
# eventually leading to undefined symbol `WinMain').
|
|
# The main program needs to initialize all the _impure_ptr variables
|
|
# for the DLLs with its _impure_ptr.
|
|
|
|
%_dll.h:
|
|
echo "/* automatically generated by Makefile.DLLs */" > $@
|
|
echo "#ifndef $(GUARD_MACRO)" >> $@
|
|
echo "#define $(GUARD_MACRO)" >> $@
|
|
echo "" >> $@
|
|
echo "#if defined(__GNUC__) && defined(__CYGWIN32__)" >> $@
|
|
echo " #if !defined($(DEFINE_DLL_MACRO))" >> $@
|
|
echo " #define $(IMP_MACRO)(name) __imp_##name" >> $@
|
|
echo " #define $(GLOBAL_MACRO)(name) (*$(IMP_MACRO)(name))" >> $@
|
|
echo " #include \"$*_globals.h\"" >> $@
|
|
echo " #endif /* $(DEFINE_DLL_MACRO) */" >> $@
|
|
echo "#endif /* __GNUC__ && __CYGWIN32__ */" >> $@
|
|
echo "" >> $@
|
|
echo "#endif /* $(GUARD_MACRO) */" >> $@
|
|
|
|
%_globals.h: %_def.a
|
|
echo "/* automatically generated by Makefile.DLLs */" > $@
|
|
for sym in $(IMPURE_PTR) \
|
|
`nm $< | grep '^........ [BCDR] _' | sed 's/[^_]*_//'`; \
|
|
do \
|
|
echo "#define $$sym $(GLOBAL_MACRO)($$sym)" >> $@; \
|
|
done
|
|
|
|
%_dll.c:
|
|
echo "/* automatically generated by Makefile.DLLs */" > $@
|
|
echo "void *_impure_ptr;" >> $@
|
|
|
|
# This rule creates the export object file (`foo.exp') which contains the
|
|
# jump table array; this export object file becomes part of the DLL.
|
|
# This rule also creates the import library (`foo.a') which contains small
|
|
# stubs for all the functions exported by the DLL which jump to them via the
|
|
# jump table. Executables that will use the DLL must be linked against this
|
|
# stub library.
|
|
%.exp %.a : %.def
|
|
dlltool $(DLLTOOLFLAGS) $(DLLTOOLFLAGS-$*) \
|
|
--def $< \
|
|
--dllname $*.dll \
|
|
--output-exp $*.exp \
|
|
--output-lib $*.a
|
|
|
|
# The `sed' commands below are to convert DOS-style `C:\foo\bar'
|
|
# pathnames into Unix-style `//c/foo/bar' pathnames.
|
|
CYGWIN32_LIBS = $(shell echo \
|
|
-L`dirname \`gcc -print-file-name=libgcc.a | \
|
|
sed -e 's@^\\\\([A-Za-z]\\\\):@//\\\\1@g' -e 's@\\\\\\\\@/@g' \` ` \
|
|
-L`dirname \`gcc -print-file-name=libcygwin.a | \
|
|
sed -e 's@^\\\\([A-Za-z]\\\\):@//\\\\1@g' -e 's@\\\\\\\\@/@g' \` ` \
|
|
-L`dirname \`gcc -print-file-name=libkernel32.a | \
|
|
sed -e 's@^\\\\([A-Za-z]\\\\):@//\\\\1@g' -e 's@\\\\\\\\@/@g' \` ` \
|
|
-lgcc -lcygwin -lkernel32 -lgcc)
|
|
|
|
# Making relocatable DLLs doesn't seem to work.
|
|
# Note quite sure why. The --image-base values below
|
|
# where chosen at random, the first two at least seem to work on my machine.
|
|
RELOCATABLE=no
|
|
LDFLAGS-libgc += --image-base=0x2345000
|
|
LDFLAGS-libmer_rt += --image-base=0x1234000
|
|
LDFLAGS-libmer_std += --image-base=0x3456000
|
|
LDFLAGS-libmer_trace += --image-base=0x4567000
|
|
LDFLAGS-libmer_browser += --image-base=0x5678000
|
|
|
|
ifeq "$(strip $(RELOCATABLE))" "yes"
|
|
|
|
# to create relocatable DLLs, we need to do two passes
|
|
# (warning: this is untested)
|
|
%.dll: %.exp %_def.a %_dll.o dll_init.o dll_fixup.o
|
|
$(LD) $(LDFLAGS) $(LDFLAGS-$*) --dll -o $*.base \
|
|
-e _dll_entry@12 \
|
|
$*.exp $*_def.a $*_dll.o \
|
|
dll_init.o dll_fixup.o \
|
|
$(LDLIBS) $(LDLIBS-$*) \
|
|
$(CYGWIN32_LIBS)
|
|
# untested
|
|
dlltool $(DLLTOOLFLAGS) $(DLLTOOLFLAGS-$*) \
|
|
--def $*.def \
|
|
--dllname $*.dll \
|
|
--base-file $*.base \
|
|
--output-exp $*.exp
|
|
$(LD) $(LDFLAGS) $(LDFLAGS-$*) --dll -o $*.base \
|
|
-e _dll_entry@12 \
|
|
$*.exp $*_def.a $*_dll.o \
|
|
dll_init.o dll_fixup.o \
|
|
$(LDLIBS) $(LDLIBS-$*) \
|
|
$(CYGWIN32_LIBS)
|
|
dlltool $(DLLTOOLFLAGS) $(DLLTOOLFLAGS-$*) \
|
|
--def $*.def \
|
|
--dllname $*.dll \
|
|
--base-file $*.base \
|
|
--output-exp $*.exp
|
|
# end untested stuff
|
|
$(LD) $(LDFLAGS) $(LDFLAGS-$*) --dll --base-file $*.base -o $@ \
|
|
-e _dll_entry@12 \
|
|
$*.exp $*_def.a $*_dll.o \
|
|
dll_init.o dll_fixup.o \
|
|
$(LDLIBS) $(LDLIBS-$*) \
|
|
$(CYGWIN32_LIBS)
|
|
rm -f $*.base
|
|
|
|
else
|
|
|
|
%.dll: %.exp %_def.a %_dll.o dll_fixup.o dll_init.o
|
|
$(LD) $(LDFLAGS) $(LDFLAGS-$*) --dll -o $@ \
|
|
-e _dll_entry@12 \
|
|
$*.exp $*_def.a $*_dll.o \
|
|
dll_init.o dll_fixup.o \
|
|
$(LDLIBS) $(LDLIBS-$*) \
|
|
$(CYGWIN32_LIBS)
|
|
|
|
endif
|
|
|
|
# This black magic piece of assembler needs to be linked in in order to
|
|
# properly terminate the list of imported DLLs.
|
|
dll_fixup.s:
|
|
echo '.section .idata$$3' > dll_fixup.s
|
|
echo '.long 0,0,0,0, 0,0,0,0' >> dll_fixup.s
|
|
|
|
dll_fixup.o: dll_fixup.s
|
|
$(AS) $(ASFLAGS) -o dll_fixup.o dll_fixup.s
|
|
|
|
# Windows requires each DLL to have an initialization function
|
|
# that is called at certain points (thread/process attach/detach).
|
|
# This one just doesn't do anything.
|
|
dll_init.c:
|
|
echo '__attribute__((stdcall))' > dll_init.c
|
|
echo 'int dll_entry(int handle, int reason, void *ptr)' >> dll_init.c
|
|
echo '{ return 1; }' >> dll_init.c
|
|
|
|
# The following rule is just there to convince gcc
|
|
# to keep otherwise unused intermediate targets around.
|
|
dont_throw_away: dll_fixup.o dll_init.o
|
|
|
|
.PHONY: clean
|
|
clean: clean_dll
|
|
|
|
.PHONY: clean_dll
|
|
clean_dll:
|
|
-rm -f dll_init.c dll_init.o dll_fixup.s dll_fixup.o
|
|
|
|
#-----------------------------------------------------------------------------#
|