diff --git a/pkgs/racket-doc/scribblings/guide/performance.scrbl b/pkgs/racket-doc/scribblings/guide/performance.scrbl index a4095a5eaf..c8a780a660 100644 --- a/pkgs/racket-doc/scribblings/guide/performance.scrbl +++ b/pkgs/racket-doc/scribblings/guide/performance.scrbl @@ -87,13 +87,16 @@ Racket is available in three implementation variants: @deftech{3m}, ] +The @tech{3m} and @tech{CGC} variants are collectively known as the +@deftech{BC} (``before CS'') variant. + In general, Racket programs should run the same in all variants. Furthermore, the performance characteristics of Racket program should be similar in the @tech{3m} and @tech{CS} variants. The cases where a program may depends on the variant will typically involve interactions with foreign libraries; in particular, the Racket C API described in -@other-doc[inside-doc] is available only for the virtual machine of -the @tech{3m} and @tech{CGC} variants. +@other-doc[inside-doc] is different for the @tech{3m} and @tech{CGC} +variants versus the @tech{CS} variant. @; ---------------------------------------------------------------------- diff --git a/pkgs/racket-doc/scribblings/inside/bc.scrbl b/pkgs/racket-doc/scribblings/inside/bc.scrbl new file mode 100644 index 0000000000..a5d14e4d82 --- /dev/null +++ b/pkgs/racket-doc/scribblings/inside/bc.scrbl @@ -0,0 +1,30 @@ +#lang scribble/base + +@title[#:style '(toc grouper) #:tag "bc"]{Inside Racket BC (3m and CGC)} + +The Racket BC API was originally designed for a tight integration with +C code. As a result, the BC API is considerably larger than the Racket +CS API. + +@local-table-of-contents[] + +@include-section["overview.scrbl"] +@include-section["embedding.scrbl"] +@include-section["extensions.scrbl"] +@include-section["values.scrbl"] +@include-section["memory.scrbl"] +@include-section["namespaces.scrbl"] +@include-section["procedures.scrbl"] +@include-section["eval.scrbl"] +@include-section["exns.scrbl"] +@include-section["threads.scrbl"] +@include-section["params.scrbl"] +@include-section["contmarks.scrbl"] +@include-section["strings.scrbl"] +@include-section["numbers.scrbl"] +@include-section["ports.scrbl"] +@include-section["structures.scrbl"] +@include-section["security.scrbl"] +@include-section["custodians.scrbl"] +@include-section["subprocesses.scrbl"] +@include-section["misc.scrbl"] diff --git a/pkgs/racket-doc/scribblings/inside/cs-embedding.scrbl b/pkgs/racket-doc/scribblings/inside/cs-embedding.scrbl new file mode 100644 index 0000000000..2cef334579 --- /dev/null +++ b/pkgs/racket-doc/scribblings/inside/cs-embedding.scrbl @@ -0,0 +1,254 @@ +#lang scribble/doc +@(require "utils.rkt" + scribble/bnf) + +@title[#:tag "cs-embedding"]{Embedding into a Program} + +@section-index["embedding Racket CS"] + +To embed Racket CS in a program, follow these steps: + +@itemize[ + + @item{Locate or build the Racket CS library. + + On Unix, the library is @as-index{@filepath{libracketcs.a}}. + Building from source and installing places the libraries into the + installation's @filepath{lib} directory. + + On Windows, link to @filepath{libracketcs@italic{x}.dll} (where + @italic{x} represents the version number). At run time, either + @filepath{libracketcs@italic{x}.dll} must be moved to a location in + the standard DLL search path, or your embedding application must + ``delayload'' link the DLLs and explicitly load them before use. + (@filepath{Racket.exe} uses the latter strategy.) + + On Mac OS, besides @as-index{@filepath{libracketcs.a}} for static + linking, a dynamic library is provided by the @filepath{Racket} + framework, which is typically installed in @filepath{lib} + sub-directory of the installation. Supply @exec{-framework Racket} + to @exec{gcc} when linking, along with @exec{-F} and a path to the + @filepath{lib} directory. At run time, either + @filepath{Racket.framework} must be moved to a location in the + standard framework search path, or your embedding executable must + provide a specific path to the framework (possibly an + executable-relative path using the Mach-O @tt["@executable_path"] + prefix).} + + @item{For each C file that uses Racket library functions, + @cpp{#include} the files @as-index{@filepath{chezscheme.h}} + and @as-index{@filepath{racketcs.h}}. + + The @filepath{chezscheme.h} and @filepath{racketcs.h} files are + distributed with the Racket software in the installation's + @filepath{include} directory. Building and installing from source + also places this file in the installation's @filepath{include} + directory.} + + @item{In your program, call @cppi{racket_boot}. The + @cppi{racket_boot} function takes a pointer to a + @cpp{racket_boot_arguments_t} for configuring the Racket instance. + After zeroing out the @cpp{racket_boot_arguments_t} value + (typicially with @cpp{memset}), only the following fields are + required to be set: + + @itemlist[ + + @item{@cpp{exec_file} --- a path to be reported by + @racket[(find-system-path 'exec-file)], usually + @cpp{argv[0]} for the @cpp{argv} received by your program's + @cpp{main}.} + + @item{@cpp{boot1_path} --- a path to @filepath{petite.boot}. Use + a path that includes at least one directory separator.} + + @item{@cpp{boot2_path} --- a path to @filepath{scheme.boot} (with + a separator).} + + @item{@cpp{boot3_path} --- a path to @filepath{racket.boot} + (which a separator).} + + ] + + The @filepath{petite.boot}, @filepath{scheme.boot}, and + @filepath{racket.boot} files are distributed with the Racket + software in the installation's @filepath{lib} directory. These files + can be combined into a single file---or even embedded into the + executable---as long as the @cpp{boot1_offset}, @cpp{boot2_offset}, + and @cpp{boot3_offset} fields of @cpp{racket_boot_arguments_t} are + set to identify the starting offset of each boot image in the file.} + + @item{Configure the main thread's namespace by adding module + declarations. The initial namespace contains declarations only for a + few primitive modules, such as @racket['#%kernel], and no bindings + are imported into the top-level environment. + + To embed a module like @racketmodname[racket/base] (along with all + its dependencies), use + @seclink["c-mods" #:doc raco-doc]{@exec{raco ctool --c-mods @nonterm{dest}}}, + which generates a C file @nonterm{dest} + that contains modules in bytecode form as encapsulated in a static + array. The generated C file defines a @cppi{declare_modules} + function that takes no arguments and installs the modules into + the environment, and it adjusts the module name resolver to access the + embedded declarations. If embedded modules refer to runtime files + that need to be carried along, supply @DFlag{runtime} to + @exec{raco ctool --c-mods} to collect the runtime files into a + directory; see @secref[#:doc raco-doc "c-mods"] for more information. + + Alternatively, set fields like @cpp{collects_dir}, @cpp{config_dir}, + and/or @cpp{argv} in the @cpp{racket_boot_arguments_t} passed to + @cppi{scheme_boot} to locate collections/packages and initialize the + namespace the same way as when running the @exec{racket} executable. + + On Windows, @exec{raco ctool --c-mods @nonterm{dest} --runtime + @nonterm{dest-dir}} includes in @nonterm{dest-dir} optional DLLs + that are referenced by the Racket library to support + @racket[bytes-open-converter]. Set @cpp{dll_dir} in + @cpp{racket_boot_arguments_t} to register @nonterm{dest-dir} so that + those DLLs can be found at run time.} + + @item{Access Racket through @cppi{racket_dynamic_require}, + @cppi{racket_eval}, and/or other functions described in this manual. + + If the embedding program configures built-in parameters in a way + that should be considered part of the default configuration, then + call the @racketidfont{seal} function provided by the primitive + @racketidfont{#%boot} module afterward. The snapshot of parameter + values taken by @cpp{scheme_seal_parameters} is used for certain + privileged operations, such as installing a @|PLaneT| package.} + + @item{Compile the program and link it with the Racket libraries.} + +] + +@index['("allocation")]{Racket} values may be moved or garbage +collected any time that @cpp{racket_...} functions are used to run +Racket code. Do not retain a reference to any Racket value across such +a call. + +For example, the following is a simple embedding program that runs a +module @filepath{run.rkt}, assuming that @filepath{run.c} is created +as + +@commandline{raco ctool --c-mods run.c "run.rkt"} + +to generate @filepath{run.c}, which encapsulates the compiled form of +@filepath{run.rkt} and all of its transitive imports (so that they +need not be found separately a run time). Copies of +@filepath{petite.boot}, @filepath{scheme.boot}, and +@filepath{racket.boot} must be in the current directory on startup. + +@filebox["main.c"]{ +@verbatim[#:indent 2]{ +#include +#include "chezscheme.h" +#include "racketcs.h" + +#include "run.c" + +int main(int argc, char *argv[]) +{ + racket_boot_arguments_t ba; + + memset(&ba, 0, sizeof(ba)); + + ba.boot1_path = "./petite.boot"; + ba.boot2_path = "./scheme.boot"; + ba.boot3_path = "./racket.boot"; + + ba.exec_file = argv[0]; + + racket_boot(&ba); + + declare_modules(); + + ptr mod = Scons(Sstring_to_symbol("quote"), + Scons(Sstring_to_symbol("run"), + Snil)); + + racket_dynamic_require(mod, Sfalse); + + return 0; +} +}} + +As another example, the following is a simple embedding program that +evaluates all expressions provided on the command line and displays +the results, then runs a @racket[read]-@racket[eval]-@racket[print] +loop, all using @racketmodname[racket/base]. Run + +@commandline{raco ctool --c-mods base.c ++lib racket/base} + +to generate @filepath{base.c}, which encapsulates @racket[racket/base] +and all of its transitive imports. + +@filebox["main.c"]{ +@verbatim[#:indent 2]{ +#include +#include "chezscheme.h" +#include "racketcs.h" + +#include "base.c" + +static ptr to_bytevector(char *s); + +int main(int argc, char *argv[]) +{ + racket_boot_arguments_t ba; + + memset(&ba, 0, sizeof(ba)); + + ba.boot1_path = "./petite.boot"; + ba.boot2_path = "./scheme.boot"; + ba.boot3_path = "./racket.boot"; + + ba.exec_file = argv[0]; + + racket_boot(&ba); + + declare_modules(); + + racket_namespace_require(Sstring_to_symbol("racket/base")); + + { + int i; + for (i = 1; i < argc; i++) { + ptr e = to_bytevector(argv[i]); + e = Scons(Sstring_to_symbol("open-input-bytes"), + Scons(e, Snil)); + e = Scons(Sstring_to_symbol("read"), Scons(e, Snil)); + e = Scons(Sstring_to_symbol("eval"), Scons(e, Snil)); + e = Scons(Sstring_to_symbol("println"), Scons(e, Snil)); + + racket_eval(e); + } + } + + { + ptr rbase_sym = Sstring_to_symbol("racket/base"); + ptr repl_sym = Sstring_to_symbol("read-eval-print-loop"); + + racket_apply(Scar(racket_dynamic_require(rbase_sym, + repl_sym)), + Snil); + } + + return 0; +} + +static ptr to_bytevector(char *s) +{ + iptr len = strlen(s); + ptr bv = Smake_bytevector(len, 0); + memcpy(Sbytevector_data(bv), s, len); + return bv; +} +}} + +If modules embedded in the executable need to access runtime files +(via @racketmodname[racket/runtime-path] forms), supply the +@DFlag{runtime} flag to @seclink["ctool" #:doc raco-doc]{@exec{raco ctool}}, specifying a directory +where the runtime files are to be gathered. The modules in the +generated @filepath{.c} file will then refer to the files in that +directory. diff --git a/pkgs/racket-doc/scribblings/inside/cs-eval.scrbl b/pkgs/racket-doc/scribblings/inside/cs-eval.scrbl new file mode 100644 index 0000000000..11833fe3ed --- /dev/null +++ b/pkgs/racket-doc/scribblings/inside/cs-eval.scrbl @@ -0,0 +1,40 @@ +#lang scribble/doc +@(require "utils.rkt" + (for-label ffi/unsafe/vm)) + +@title[#:tag "cs-eval"]{Evaluation and Running Modules} + +The @cppi{racket_apply} function provides basic evaluation support, +but @cppi{racket_eval}, @cppi{racket_dynamic_require}, and +@cppi{racket_namespace_require} provide higher-level support for the +most common evaluation tasks. + +@function[(ptr racket_eval [ptr s_expr])]{ + +Evaluates @var{s_expr} in the initial Racket thread using its current +@tech[#:doc reference-doc]{namespace}, the same as calling +@racket[eval]. The @var{s_expr} can be an S-expression constructed +with pairs, symbols, etc., or it can be a @tech[#:doc +reference-doc]{syntax object}. + +Use @cppi{racket_namespace_require} to initialize a namespace, or use +@cppi{racket_dynamic_require} to access functionality without going +through a top-level namespace. Although those functions are the same +as using @racket[namespace-require] and @racket[dynamic-require], they +work without having those identifiers bound in a namespace already.} + +@function[(ptr racket_dynamic_require [ptr module_path] [ptr sym_or_false])]{ + +The same as calling @racket[dynamic-require] in the initial Racket +thread using its current namespace. See also @cppi{racket_eval}.} + + +@function[(ptr racket_namespace_require [ptr module_path])]{ + +The same as calling @racket[namespace-require] in the initial Racket +thread using its current namespace. See also @cppi{racket_eval}.} + +@function[(ptr racket_primitive [const-char* name])]{ + +Accesses a primitive function in the same sense as +@racket[vm-primitive] from @racketmodname[ffi/unsafe/vm].} diff --git a/pkgs/racket-doc/scribblings/inside/cs-overview.scrbl b/pkgs/racket-doc/scribblings/inside/cs-overview.scrbl new file mode 100644 index 0000000000..40ae6e8758 --- /dev/null +++ b/pkgs/racket-doc/scribblings/inside/cs-overview.scrbl @@ -0,0 +1,96 @@ +#lang scribble/doc +@(require "utils.rkt") + +@title[#:tag "cs-overview"]{Overview} + +The Racket CS run-time system is implemented by a wrapper around the +Chez Scheme kernel. The wrapper implements additional glue to the +operating system (e.g., for I/O and networking) and provides entry +points into the Racket layer's evaluator. + +@; ---------------------------------------------------------------------- + +@section{``S'' versus ``Racket''} + +In the C API for Racket CS, names that start with @cpp{S} are from the +Chez Scheme layer, while names that start with @cpp{racket_} are from +the Racket wrapper. + +@; ---------------------------------------------------------------------- + +@section{Building Racket CS from Source} + +The normal Racket distribution includes @filepath{.rkt} sources for +collection-based libraries. After modifying library files, run +@exec{raco setup} (see @secref[#:doc '(lib +"scribblings/raco/raco.scrbl") "setup"]) to rebuild installed +libraries. + +The normal Racket distribution does not include the C sources for +Racket's run-time system. To build Racket from scratch, download a +source distribution from @url{http://download.racket-lang.org}; +detailed build instructions are in the @filepath{README} file in the +top-level @filepath{src} directory. You can also get the latest +sources from the @tt{git} repository at +@url{https://github.com/racket/racket}, but beware that the repository is +one step away from a normal source distribution, and it provides build +modes that are more suitable for developing Racket itself; see +@filepath{INSTALL.txt} in the @tt{git} repository for more +information. + +@; ---------------------------------------------------------------------- + +@section[#:tag "cs-memory"]{Racket CS Memory Management} + +@index['("allocation")]{Racket} values may be moved or garbage +collected any time that @cpp{racket_...} functions are used to run +Racket code. Do not retain a reference to any Racket value across such +a call. This requirement contrasts with the 3m and CGC variants of +Racket, which provide a way for C code to more directly cooperate with +the memory manager. + +API functions that start with @cpp{S} do not collect or move objects +unless noted otherwise, so references to Racket values across such +calls is safe. + +@; ---------------------------------------------------------------------- + +@section[#:tag "cs-places"]{Racket CS and Places} + +Each Racket @|tech-place| corresponds to a Chez Scheme thread, which +also corresponds to an OS-implemented thread. Chez Scheme threads +share a global allocation space, so GC-managed objects can be safely +be communicated from one place to another. Beware, however, that Chez +Scheme threads are unsafe; any synchronization needed to safely share +a value across places is must be implemented explicitly. Racket-level +functions for places will only share values across places when they +can be safely used in both places. + +In an @seclink["cs-embedding"]{embedding application}, the OS thread +that originally calls @cpp{racket_boot} is the OS thread of the +original place. + +@; ---------------------------------------------------------------------- + +@section{Racket CS and Threads} + +Racket implements threads for Racket programs without aid from the +operating system or Chez Scheme's threads, so that Racket threads are +cooperative from the perspective of C code. Stand-alone Racket uses a +few private OS-implemented threads for background tasks, but these +OS-implemented threads are never exposed by the Racket API. + +Racket can co-exist with additional OS-implemented threads, but care +must be taken when calling @cpp{S} functions, and additional OS or +Chez Scheme threads must not call any @cpp{racket_} function. For +other OS threads to call @cpp{S} functions, the thread must be first +activated as a Chez Scheme thread using @cppi{Sactivate_thread}. + + +@; ---------------------------------------------------------------------- + +@section[#:tag "cs-intsize"]{Racket CS Integers} + +The C type @cpp{iptr} is defined by Racket CS headers to be an integer +type that is big enough to hold a pointer value. In other words, it is +an alias for @cpp{intptr_t}. The @cpp{uptr} type is the unsigned variant. diff --git a/pkgs/racket-doc/scribblings/inside/cs-procs.scrbl b/pkgs/racket-doc/scribblings/inside/cs-procs.scrbl new file mode 100644 index 0000000000..c5c3f56c9c --- /dev/null +++ b/pkgs/racket-doc/scribblings/inside/cs-procs.scrbl @@ -0,0 +1,60 @@ +#lang scribble/doc +@(require "utils.rkt") + +@title[#:tag "cs-procs"]{Calling Procedures} + +Normally, C programs should call Racket procedures by using +@cppi{racket_apply}, which calls the procedure in the initial Racket +thread of the main Racket place. Chez Scheme entry points such as +@cppi{Scall0} and @cppi{Scall} directly call a procedure outside of +any Racket thread, which will not work correctly with Racket +facilities such as threads, parameters, continuations, or continuation +marks. + +@; ---------------------------------------------------------------------- + +@function[(ptr racket_apply [ptr proc] [ptr arg_list])]{ + +Applies the Racket procedure @var{proc} to the list of arguments +@var{arg_list}. The procedure is called in the original Racket thread +of the main Racket place. Applying @var{proc} must not raise an +exception or otherwise escape from the call to @var{proc}. + +The result is a list of result values, where a single result from +@var{proc} causes @cpp{racket_apply} to return a list of length one. + +Other Racket threads can run during the call to @var{proc}. At the +point that @var{proc} results, all Racket thread scheduling in the +main Racket place is suspended. No garbage collections will occur, so +other Racket places can block waiting for garbage collection.} + +@together[( +@function[(ptr Scall0 [ptr proc])] +@function[(ptr Scall1 [ptr proc] [ptr arg1])] +@function[(ptr Scall2 [ptr proc] [ptr arg1] [ptr arg2])] +@function[(ptr Scall3 [ptr proc] [ptr arg1] [ptr arg2] [ptr arg3])] +)]{ + +Applies the Chez Scheme procedure @var{proc} to zero, one, two, or +three arguments. Beware that not all Racket procedures are Chez Scheme +procedures. (For example, an instance of a structure type that has +@racket[prop:procedure] is not a Chez Scheme procedure.) + +The procedure is called outside of any Racket thread, and other Racket +threads are not scheduled during the call to @var{proc}. A garbage +collection may occur.} + +@together[( +@function[(void Sinitframe [iptr num_args])] +@function[(void Sput_arg [iptr i] [ptr arg])] +@function[(ptr Scall [ptr proc] [iptr num_args])] +)]{ + +Similar to @cppi{Scall0}, but these functions are used in sequence to +apply a Chez Scheme procedure to an arbitrary number of arguments. +First, @cppi{Sinitframe} is called with the number of arguments. Then, +each argument is installed with @cppi{Sput_arg}, where the @var{i} +argument indicates the argumenrt position and @var{arg} is the +argument value. Finally, @cppi{Scall} is called with the procedure and +the number of arguments (which must match the number provided to +@cppi{Sinitframe}).} diff --git a/pkgs/racket-doc/scribblings/inside/cs-start.scrbl b/pkgs/racket-doc/scribblings/inside/cs-start.scrbl new file mode 100644 index 0000000000..0274111995 --- /dev/null +++ b/pkgs/racket-doc/scribblings/inside/cs-start.scrbl @@ -0,0 +1,116 @@ +#lang scribble/doc +@(require "utils.rkt") + +@title[#:tag "cs-start"]{Starting and Declaring Initial Modules} + +As sketched in @secref["cs-embedding"], and embedded instance of +Racket CS is started with @cppi{racket_boot}. Functions such as +@cppi{racket_embedded_load_bytes} help to initialize a Racket +namespace with already-compiled modules. + +For functions and struct fields that contain a path in @cpp{char*} +form, the path is treated as UTF-8 encoded on Windows. + +@section[#:tag "cs-boot-arguments"]{Boot and Configuration} + +@function[(void racket_boot [racket_boot_arguments_t* boot_args])]{ + +Initializes a Racket CS instance. A main thread is created and then +suspended, waiting for further evaluation via @cppi{racket_apply}, +@cppi{racket_eval}, and similar functions. + +A @cpp{racket_boot_arguments_t} struct contains fields to specify how +@cppi{racket_boot} should initialize a Racket instance. New fields may +be added in the future, but in that case, a @cpp{0} or @cpp{NULL} +value for a field will imply backward-compatible default. + +Fields in @cppdef{racket_boot_arguments_t}: + +@itemlist[ + + @item{@cpp{const char *} @cppdef{boot1_path} --- a path to a file + containing a Chez Scheme image file with base functionality. + Normally, the file is called @filepath{petite.boot}. The path + should contain a directory separator, otherwise Chez Scheme + will consult its own search path.} + + @item{@cpp{long} @cppdef{boot1_offset} --- an offset into + @cpp{boot1_path} to read for the first boot image, which allows + boot images to be combined with other data in a single file. + The image as distributed is self-terminating, so no size or + ending offset is needed.} + + @item{@cpp{const char *} @cppdef{boot2_path} --- like + @cpp{boot1_path}, but for the image that contains compiler + functionality, normally called @filepath{scheme.boot}.} + + @item{@cpp{long} @cppdef{boot2_offset} --- an offset into + @cpp{boot2_path} to read for the second boot image.} + + @item{@cpp{const char *} @cppdef{boot3_path} --- like + @cpp{boot1_path}, but for the image that contains Racket + functionality, normally called @filepath{racket.boot}.} + + @item{@cpp{long} @cppdef{boot3_offset} --- an offset into + @cpp{boot2_path} to read for the thirf boot image.} + + @item{@cpp{int} @cpp{argc} and @cpp{char **} @cpp{argv} --- + command-line arguments to be processed the same as for a + stand-alone @exec{racket} invocation. If @var{argv} is + @cpp{NULL}, the command line @exec{-n} is used, which loads + boot files without taking any further action.} + + @item{@cpp{const char *} @cppdef{exec_file} --- a path to use for + @racket[(system-type 'exec-file)], usually @cpp{argv[0]} using + the @cpp{argv} delivered to a program's @cpp{main}. This + field must not be @cpp{NULL}.} + + @item{@cpp{const char *} @cppdef{run_file} --- a path to use for + @racket[(system-type 'run-file)]. If the field is @cpp{NULL}, + the value of @cppi{exec_file} is used.} + + @item{@cpp{const char *} @cppdef{collects_dir} --- a path to use as + the main @filepath{collects} directory for locating library + collections. If this field holds @cpp{NULL} or @cpp{""}, then + the library-collection search path is initialized as empty.} + + @item{@cpp{const char *} @cppdef{config_dir} --- a path to used as an + @filepath{etc} directory that holds configuration information, + including information about installed packages. If the value if + @cpp{NULL}, @cpp{"etc"} is used.} + + @item{@cpp{wchar_t *} @cppdef{dll_dir} --- a path used to find DLLs, + such as @exec{iconv} support. Note that this path uses wide + characters, not a UTF-8 byte encoding.} + + @item{@cpp{int} @cppdef{cs_compiled_subdir} --- A true value indicates + that the @racket[use-compiled-file-paths] parameter should be + initialized to have a platform-specific subdirectory of + @filepath{compiled}, which is used for a Racket CS installation + that overlays a Racket BC installation.} + +]} + +@; ---------------------------------------------------------------------- + +@section[#:tag "cs-embedded-load"]{Loading Racket Modules} + +@together[( +@function[(void racket_embedded_load_bytes [const-char* code] [uptr len] [int as_predefined])] +@function[(void racket_embedded_load_file [const-char* path] [int as_predefined])] +@function[(void racket_embedded_load_file_region [const-char* path] [uptr start] [uptr end] [int as_predefined])] +)]{ + +These functions evaluate Racket code, either in memory as @var{code} +or loaded from @var{path}, in the initial Racket thread. The intent is +that the code is already compiled. Normally, also, the contains module +declarations. The @seclink["c-mods" #:doc raco-doc]{@exec{raco ctool +--c-mods}} and @seclink["c-mods" #:doc raco-doc]{@exec{raco ctool +--mods}} commands generate code suitable for loading with these +functions, and @DFlag{c-mods} mode generates C code that calls +@cppi{racket_embedded_load_bytes}. + +If @var{as_predefined} is true, then the code is loaded during the +creation of any new Racket @tech[#:doc reference-doc]{place} in the +new place, so that modules declared by the code are loaded in the new +place, too.} diff --git a/pkgs/racket-doc/scribblings/inside/cs-thread.scrbl b/pkgs/racket-doc/scribblings/inside/cs-thread.scrbl new file mode 100644 index 0000000000..ce0c36da89 --- /dev/null +++ b/pkgs/racket-doc/scribblings/inside/cs-thread.scrbl @@ -0,0 +1,34 @@ +#lang scribble/doc +@(require "utils.rkt") + +@title[#:tag "cs-thread"]{Managing OS-Level Threads} + +Chez Scheme functionality can only be accessed from OS-level threads +that are known to the Chez Scheme runtime system. Otherwise, there's a +race condition between such an access and a garbage collection that is +triggered by other threads. + +A thread not created by Chez Scheme can be made known to the runtime +system by activating it with @cppi{Sactivate_thread}. As long as a +thread is active by not running Chez Scheme code, the thread prevents +garbage collection in all other running threads. Deactivate a thread +using @cppi{Sdeactivate_thread}. When a deactivated thread + +@function[(int Sactivate_thread)]{ + +Activates the current OS-level thread. An already-activated thread can +be activated again, but each activating must be balanced by a +decativation. The result is @cpp{0} if the thread was previously +activated @cpp{1} otherwise.} + +@function[(void Sdeactivate_thread)]{ + +Deactivates the current OS-level thread---or, at least, balances on +activation, making the thread deactive if there are no remaining +activations to balance with deactivation.} + +@function[(int Sdestroy_thread)]{ + +Releases any Chez Scheme resources associated with the current OS +thread, which must have been previously activated by which must not be +activated still.} diff --git a/pkgs/racket-doc/scribblings/inside/cs-values.scrbl b/pkgs/racket-doc/scribblings/inside/cs-values.scrbl new file mode 100644 index 0000000000..7a1dddf409 --- /dev/null +++ b/pkgs/racket-doc/scribblings/inside/cs-values.scrbl @@ -0,0 +1,266 @@ +#lang scribble/doc +@(require "utils.rkt") + +@title[#:tag "cs-values+types"]{Values and Types} + +A Racket value is represented by a pointer-sized value. The low bits +of the value indicate the encoding that it uses. For example, two (on +32-bit platform) or three (on 64-bit platforms) low bits indicates a +fixnum encoding, while a one low bit and zero second-lowest bit +indicates a pair whose address in memory is specified by the other +bits. + +The C type for a Racket value is @tt{ptr}. For most Racket types, a +constructor is provided for creating values of the type. For example, +@cpp{Scons} takes two @cpp{ptr} values and returns the @racket[cons] +of the values as a new @cpp{ptr} value. In addition to providing +constructors, Racket defines several global constant Racket values, +such as @cppi{Strue} for @racket[#t]. + +@; ---------------------------------------------------------------------- + +@section[#:tag "cs-constants"]{Global Constants} + +There are six global constants: + +@itemize[ + + @item{@cppdef{Strue} --- @racket[#t]} + + @item{@cppdef{Sfalse} --- @racket[#f]} + + @item{@cppdef{Snil} --- @racket[null]} + + @item{@cppdef{Seof-object} --- @racket[eof-object]} + + @item{@cppdef{Svoid} --- @racket[(void)]} + +] + +@; ---------------------------------------------------------------------- + +@section[#:tag "cs-value-funcs"]{Value Functions} + +Many of these functions are actually macros. + +@(define-syntax-rule (predicates (name ...) desc ...) + (together + (@function[(int name [ptr v])] ...) + desc ...)) + +@predicates[(Sfixnump + Scharp + Snullp + Seof_objectp + Sbooleanp + Spairp + Ssymbolp + Sprocedurep + Sflonump + Svectorp + Sfxvectorp + Sbytevectorp + Sstringp + Sbignump + Sboxp + Sinexactnump + Sexactnump + Sratnump + Srecordp)]{ + +Predicates to recognize different kinds of Racket values, such as +fixnums, characters, the empty list, etc. The @cpp{Srecord} predicate +recognizes structures, but some built-in Racket datatypes are also +implemented as records.} + +@function[(ptr Sfixnum [int i])]{ + +Returns a Racket integer value, where @var{i} must fit in a fixnum.} + +@together[( +@function[(ptr Sinteger [iptr i])] +@function[(ptr Sunsigned [uptr i])] +@function[(ptr Sinteger32 [int i])] +@function[(ptr Sunsigned32 [unsigned-int i])] +@function[(ptr Sinteger64 [long i])] +@function[(ptr Sunsigned64 [unsigned-long i])] +)]{ + +Returns an integer value for different conversions from C, where the +result is allocated as a bignum if necessary to hold the value.} + +@function[(iptr Sfixnum_value [ptr v])]{ + +Converts a Racket fixnum to a C integer.} + +@together[( +@function[(iptr Sinteger_value [ptr v])] +@function[(uptr Sunsigned_value [ptr v])] +@function[(int Sinteger32_value [ptr v])] +@function[(long Sunsigned32_value [ptr v])] +@function[(long Sinteger64_value [ptr v])] +@function[(unsigned-long Sunsigned64_value [ptr v])] +)]{ + +Converts a Racket integer (possibly a bignum) to a C integer, assuming +that the integer fits in the return type.} + +@function[(ptr Sflonum [double f])]{ + +Returns a Racket flonum value.} + +@function[(double Sflonum_value [ptr v])]{ + +Converts a Racket flonum value to a C floating-point number.} + + +@function[(ptr Schar [int ch])]{ + +Returns a Racket character value. The @var{ch} value must be a legal +Unicode code point (and not a surrogate, for example). All characters +are represented by constant values.} + + +@function[(ptr Schar_value [ptr ch])]{ + +Returns the Unicode code point for the Racket character @var{ch}.} + + +@function[(ptr Sboolean [int bool])]{ + +Returns @cppi{Strue} or @cppi{Sfalse}.} + + +@function[(ptr Scons [ptr car] [ptr cdr])]{ + +Makes a @racket[cons] pair.} + +@together[( +@function[(ptr Scar [ptr pr])] +@function[(ptr Scdr [ptr pr])] +)]{ + +Extracts the @racket[car] or @racket[cdr] of a pair.} + +@function[(ptr Sstring_to_symbol [const-char* str])]{ + +Returns the interned symbol whose name matches @var{str}.} + +@function[(ptr Ssymbol_to_string [ptr sym])]{ + +Returns the Racket immutable string value for the Racket symbol +@var{sym}.} + +@together[( +@function[(ptr Smake_string [iptr len] [int ch])] +@function[(ptr Smake_uninitialized_string [iptr len])] +)]{ + +Allocates a fresh Racket mutable string with @var{len} characters. The +content of the string is either all @var{ch}s when @var{ch} is +provided or unspecified otherwise.} + +@together[( +@function[(ptr Sstring [const-char* str])] +@function[(ptr Sstring_of_length [const-char* str] [iptr len])] +@function[(ptr Sstring_utf8 [const-char* str] [iptr len])] +)]{ + +Allocates a fresh Racket mutable string with the content of @var{str}. +If @var{len} is not provided, @var{str} must be nul-terminated. +In the case of @cppi{Sstring_utf8}, @var{str} is decoded as +UTF-8, otherwise it is decided as Latin-1.} + + +@function[(uptr string_length [ptr str])]{ + +Returns the length of the string @var{str}.} + +@function[(ptr Sstring_ref [ptr str] [i uptr])]{ + +Returns the @var{i}th Racket character of the string @var{str}.} + +@function[(int Sstring_set [ptr str] [i uptr] [ptr ch])]{ + +Installs @var{ch} as the @var{i}th Racket character of the string @var{str}.} + + + +@function[(ptr Smake_vector [iptr len] [ptr v])]{ + +Allocates a fresh mutable @tech[#:doc reference-doc]{vector} of length +@var{len} and with @var{v} initially in every slot.} + + +@function[(uptr Svector_length [ptr vec])]{ + +Returns the length of the vector @var{vec}.} + + +@function[(uptr Svector_ref [ptr vec] [i uptr])]{ + +Returns the @var{i}th element of the vector @var{vec}.} + + +@function[(void Svector_set [ptr vec] [i uptr] [ptr v])]{ + +Installs @var{v} as the @var{i}th element of the vector @var{vec}.} + + +@function[(ptr Smake_fxvector [iptr len] [ptr v])]{ + +Allocates a fresh mutable @tech[#:doc reference-doc]{fxvector} of +length @var{len} and with @var{v} initially in every slot.} + + +@function[(uptr Sfxvector_length [ptr vec])]{ + +Returns the length of the fxvector @var{vec}.} + + +@function[(uptr Sfxvector_ref [ptr vec] [i uptr])]{ + +Returns the @var{i}th fixnum of the fxvector @var{vec}.} + + +@function[(void Sfxvector_set [ptr vec] [i uptr] [ptr v])]{ + +Installs the fixnum @var{v} as the @var{i}th element of the fxvector +@var{vec}.} + + + +@function[(ptr Smake_bytevector [iptr len] [int byte])]{ + +Allocates a fresh mutable @tech[#:doc reference-doc]{byte string} of +length @var{len} and with @var{byte} initially in every slot.} + +@function[(uptr Sbytevector_length [ptr bstr])]{ + +Returns the length of the byte string @var{bstr}.} + +@function[(int Sbytevector_u8_ref [ptr bstr] [i uptr])]{ + +Returns the @var{i}th byte of the byte string @var{bstr}.} + +@function[(int Sbytevector_u8_set [ptr bstr] [i uptr] [int byte])]{ + +Installs @var{byte} as the @var{i}th byte of the byte string @var{bstr}.} + +@function[(char* Sbytevector_data [ptr vec])]{ + +Returns a pointer to the start of the bytes for the byte string @var{bstr}.} + + +@function[(ptr Sbox [ptr v])]{ + +Allocates a fresh mutable @tech[#:doc reference-doc]{box} containing +@var{v}.} + +@function[(ptr Sunbox [ptr bx])]{ + +Extract the content of the box @var{bx}.} + +@function[(ptr Sset_box [ptr bx] [ptr v])]{ + +Installs @var{v} as the content of the box @var{bx}.} diff --git a/pkgs/racket-doc/scribblings/inside/cs.scrbl b/pkgs/racket-doc/scribblings/inside/cs.scrbl new file mode 100644 index 0000000000..465716e0d2 --- /dev/null +++ b/pkgs/racket-doc/scribblings/inside/cs.scrbl @@ -0,0 +1,16 @@ +#lang scribble/base + +@title[#:style '(grouper toc) #:tag "cs"]{Inside Racket CS} + +The Racket CS API is a small extension of the Chez Scheme C API as +described in @italic{The Chez Scheme User's Guide}. + +@local-table-of-contents[] + +@include-section["cs-overview.scrbl"] +@include-section["cs-embedding.scrbl"] +@include-section["cs-values.scrbl"] +@include-section["cs-procs.scrbl"] +@include-section["cs-start.scrbl"] +@include-section["cs-eval.scrbl"] +@include-section["cs-thread.scrbl"] diff --git a/pkgs/racket-doc/scribblings/inside/embedding.scrbl b/pkgs/racket-doc/scribblings/inside/embedding.scrbl index 9828eb4b15..fe204f1c99 100644 --- a/pkgs/racket-doc/scribblings/inside/embedding.scrbl +++ b/pkgs/racket-doc/scribblings/inside/embedding.scrbl @@ -6,7 +6,7 @@ @title[#:tag "embedding"]{Embedding into a Program} -@section-index["embedding Racket"] +@section-index["embedding Racket BC"] The Racket run-time system can be embedded into a larger program. The embedding process for Racket CGC or Racket 3m (see @secref[cgc-v-3m]) @@ -66,7 +66,7 @@ To embed Racket CGC in a program, follow these steps: an executable-relative path using the Mach-O @tt["@executable_path"] prefix).} - @item{For each C/C++ file that uses Racket library functions, + @item{For each C file that uses Racket library functions, @cpp{#include} the file @as-index{@filepath{scheme.h}}. The C preprocessor symbol @cppi{SCHEME_DIRECT_EMBEDDED} is defined @@ -122,7 +122,7 @@ To embed Racket CGC in a program, follow these steps: that contains modules in bytecode form as encapsulated in a static array. The generated C file defines a @cppi{declare_modules} function that takes a @cpp{Scheme_Env*}, installs the modules into - the environment, and adjusts the module name resolver to access the + the environment, and it adjusts the module name resolver to access the embedded declarations. If embedded modules refer to runtime files that need to be carried along, supply @DFlag{runtime} to @exec{raco ctool --c-mods} to collect the runtime files into a diff --git a/pkgs/racket-doc/scribblings/inside/extensions.scrbl b/pkgs/racket-doc/scribblings/inside/extensions.scrbl index d31af9ec60..d80f9184d0 100644 --- a/pkgs/racket-doc/scribblings/inside/extensions.scrbl +++ b/pkgs/racket-doc/scribblings/inside/extensions.scrbl @@ -11,6 +11,7 @@ and using the @seclink["top" #:doc '(lib usually a better option than writing an extension to Racket, but Racket also supports C-implemented extensions that plug more directly into the run-time system. +(Racket CS does not have a similar extension interface.) The process of creating an extension for Racket 3m or Racket CGC (see @secref["CGC versus 3m"]) is essentially the same, but the process for diff --git a/pkgs/racket-doc/scribblings/inside/inside.scrbl b/pkgs/racket-doc/scribblings/inside/inside.scrbl index bc2e08683e..7918e56c81 100644 --- a/pkgs/racket-doc/scribblings/inside/inside.scrbl +++ b/pkgs/racket-doc/scribblings/inside/inside.scrbl @@ -6,13 +6,15 @@ @author["Matthew Flatt"] -This manual describes the C interface of Racket's runtime system for -the 3m and CGC variants of Racket (but not the CS variant; see -@secref[#:doc '(lib "scribblings/guide/guide.scrbl") -"virtual-machines"]). The C -interface is relevant primarily when interacting with foreign -libraries as described in @other-manual['(lib -"scribblings/foreign/foreign.scrbl")]; even though interactions with +This manual describes the C interface of Racket's runtime system, +which varies depending on the variant of Racket (see @secref[#:doc +'(lib "scribblings/guide/guide.scrbl") "virtual-machines"]): the CS +variant of Racket has one interface, while the BC (3m and CGC) +variants of Racket have another. + +The C interface is relevant to some degree when interacting with +foreign libraries as described in @other-manual['(lib +"scribblings/foreign/foreign.scrbl")]. Even though interactions with foreign code are constructed in pure Racket using the @racketmodname[ffi/unsafe] module, many details of representations, memory management, and concurrency are described here. This manual @@ -23,26 +25,8 @@ and extending Racket directly with C-implemented libraries. @; ------------------------------------------------------------------------ -@include-section["overview.scrbl"] -@include-section["embedding.scrbl"] -@include-section["extensions.scrbl"] -@include-section["values.scrbl"] -@include-section["memory.scrbl"] -@include-section["namespaces.scrbl"] -@include-section["procedures.scrbl"] -@include-section["eval.scrbl"] -@include-section["exns.scrbl"] -@include-section["threads.scrbl"] -@include-section["params.scrbl"] -@include-section["contmarks.scrbl"] -@include-section["strings.scrbl"] -@include-section["numbers.scrbl"] -@include-section["ports.scrbl"] -@include-section["structures.scrbl"] -@include-section["security.scrbl"] -@include-section["custodians.scrbl"] -@include-section["subprocesses.scrbl"] -@include-section["misc.scrbl"] +@include-section["cs.scrbl"] +@include-section["bc.scrbl"] @; ------------------------------------------------------------------------ diff --git a/pkgs/racket-doc/scribblings/inside/overview.scrbl b/pkgs/racket-doc/scribblings/inside/overview.scrbl index 40d6f9e849..09c8862a53 100644 --- a/pkgs/racket-doc/scribblings/inside/overview.scrbl +++ b/pkgs/racket-doc/scribblings/inside/overview.scrbl @@ -20,7 +20,7 @@ all should be renamed to start @cpp{racket_}. @; ---------------------------------------------------------------------- -@section{Building Racket from Source} +@section{Building Racket BC from Source} The normal Racket distribution includes @filepath{.rkt} sources for collection-based libraries. After modifying library files, run @@ -93,7 +93,7 @@ to call the library. @; ---------------------------------------------------------------------- -@section[#:tag "places"]{Racket and Places} +@section[#:tag "places"]{Racket BC and Places} Each Racket @|tech-place| corresponds to a separate OS-implemented thread. Each place has its own memory manager. Pointers to GC-managed @@ -118,15 +118,13 @@ for the original place. @; ---------------------------------------------------------------------- -@section{Racket and Threads} +@section{Racket BC and Threads} Racket implements threads for Racket programs without aid from the operating system, so that Racket threads are cooperative from the -perspective of C code. On Unix, stand-alone Racket uses a single -OS-implemented thread. On Windows and Mac OS, stand-alone -Racket uses a few private OS-implemented threads for background -tasks, but these OS-implemented threads are never exposed by the -Racket API. +perspective of C code. Stand-alone Racket may uses a few private +OS-implemented threads for background tasks, but these OS-implemented +threads are never exposed by the Racket API. Racket can co-exist with additional OS-implemented threads, but the additional OS threads must not call any @cpp{scheme_} function. Only @@ -146,7 +144,7 @@ and embedding C code. @; ---------------------------------------------------------------------- -@section[#:tag "im:unicode"]{Racket, Unicode, Characters, and Strings} +@section[#:tag "im:unicode"]{Racket BC, Unicode, Characters, and Strings} A character in Racket is a Unicode code point. In C, a character value has type @cppi{mzchar}, which is an alias for @cpp{unsigned} --- @@ -163,7 +161,7 @@ See also @secref["im:strings"] and @secref["im:encodings"]. @; ---------------------------------------------------------------------- -@section[#:tag "im:intsize"]{Integers} +@section[#:tag "im:intsize"]{Racket BC Integers} Racket expects to be compiled in a mode where @cppi{short} is a 16-bit integer, @cppi{int} is a 32-bit integer, and @cppi{intptr_t} has diff --git a/pkgs/racket-doc/scribblings/inside/utils.rkt b/pkgs/racket-doc/scribblings/inside/utils.rkt index 50e99dfbe4..6ced0e7ca8 100644 --- a/pkgs/racket-doc/scribblings/inside/utils.rkt +++ b/pkgs/racket-doc/scribblings/inside/utils.rkt @@ -9,7 +9,7 @@ (provide Racket mzc cpp cppi cppdef (rename-out [*var var]) - function subfunction + function subfunction together FormatD tech-place reference-doc raco-doc @@ -121,6 +121,19 @@ (loop (cdr types) (cdr args))))))))) (rest-thunk))))) +(define-syntax-rule (together (func ...) expl ...) + (together* + (list func ...) + (lambda () (list expl ...)))) + +(define (together* funcs body-thunk) + (make-splice + (cons + (make-table + 'boxed + (map table-blockss (map car (map splice-run funcs)))) + (body-thunk)))) + (define (boxed t) (make-table 'boxed diff --git a/pkgs/racket-doc/scribblings/raco/c-mods.scrbl b/pkgs/racket-doc/scribblings/raco/c-mods.scrbl index 75bafae2a0..6915c10866 100644 --- a/pkgs/racket-doc/scribblings/raco/c-mods.scrbl +++ b/pkgs/racket-doc/scribblings/raco/c-mods.scrbl @@ -10,15 +10,18 @@ The @DFlag{c-mods} mode for @exec{raco ctool} takes a set of Racket modules and generates a C source file that can be used as part of -program that embeds the Racket run-time system. See @secref[#:doc +program that embeds the Racket runtime system. See @secref[#:doc inside-doc "embedding"] in @other-manual[inside-doc] for an -explanation of embedding programs. +explanation of embedding programs. The @DFlag{mods} mode is similar, but +it generates the raw bytes for the compiled module without encoding +the bytes in C declarations. -The generated source file embeds the specified modules, and it defines -a @tt{declare_modules} function that puts the module declarations into -a namespace. Thus, using the output of @exec{raco ctool --c-mods}, a -program can embed Racket with a set of modules so that it does not -need a @filepath{collects} directory to load modules at run time. +The generated source or compiled file embeds the specified modules. +Generated C source defines a @tt{declare_modules} function that puts +the module declarations into a namespace. Thus, using the output of +@exec{raco ctool --c-mods}, a program can embed Racket with a set of +modules so that it does not need a @filepath{collects} directory to +load modules at run time. If the embedded modules refer to runtime files, the files can be gathered by supplying the @DFlag{runtime} argument to @exec{raco ctool diff --git a/racket/collects/setup/winstrip.rkt b/racket/collects/setup/winstrip.rkt index a11671b3f3..8e802d585a 100644 --- a/racket/collects/setup/winstrip.rkt +++ b/racket/collects/setup/winstrip.rkt @@ -57,7 +57,7 @@ (let ([b (path-element->bytes (let-values ([(base name dir?) (split-path f)]) name))]) - (or (regexp-match? #rx#"[.](?i:pdb|ilk|manifest)$" b) + (or (regexp-match? #rx#"[.](?i:pdb|ilk|manifest|ipdb|iobj)$" b) (and (not keep-cgc?) (regexp-match? #rx#"(?i:CGC[.](?:dll|exe))$" b)) (and (not keep-3m?) diff --git a/racket/src/ac/instlib.m4 b/racket/src/ac/instlib.m4 new file mode 100644 index 0000000000..1ed431e1bb --- /dev/null +++ b/racket/src/ac/instlib.m4 @@ -0,0 +1,9 @@ +show_explicitly_enabled "${enable_libs}" "Installation of static libraries (if any)" +show_explicitly_disabled "${enable_libs}" "Installation of static libraries (if any)" + +INSTALL_LIBS_ENABLE=no-install + +if test "${enable_libs}" != "no" ; then + # Intended to be canceled for some platforms: + INSTALL_LIBS_ENABLE=install +fi diff --git a/racket/src/ac/instlib_arg.m4 b/racket/src/ac/instlib_arg.m4 new file mode 100644 index 0000000000..1da9a6ebb4 --- /dev/null +++ b/racket/src/ac/instlib_arg.m4 @@ -0,0 +1 @@ +AC_ARG_ENABLE(libs, [ --enable-libs install static libraries (enabled by default for Unix)]) diff --git a/racket/src/cfg-racket b/racket/src/cfg-racket index 23c812ecde..fa17fc2b33 100755 --- a/racket/src/cfg-racket +++ b/racket/src/cfg-racket @@ -2734,6 +2734,7 @@ if test "${enable_libs+set}" = set; then : fi + # Check whether --enable-libffi was given. if test "${enable_libffi+set}" = set; then : enableval=$enable_libffi; @@ -3284,6 +3285,14 @@ show_explicitly_disabled "${enable_strip}" "Debug-symbol stripping" show_explicitly_enabled "${enable_libs}" "Installation of static libraries (if any)" show_explicitly_disabled "${enable_libs}" "Installation of static libraries (if any)" +INSTALL_LIBS_ENABLE=no-install + +if test "${enable_libs}" != "no" ; then + # Intended to be canceled for some platforms: + INSTALL_LIBS_ENABLE=install +fi + + show_explicitly_disabled "${enable_mac64}" "64-bit Mac OS" show_explicitly_enabled "${enable_libfw}" "Frameworks-to-system" @@ -3419,8 +3428,6 @@ MAIN_VARIANT=3m INSTALL_SETUP_FLAGS= INSTALL_SETUP_RACKET_FLAGS= -INSTALL_LIBS_ENABLE=no-install - use_flag_pthread=yes use_flag_posix_pthread=no mzrt_needs_pthread=yes @@ -4804,11 +4811,6 @@ if test "${enable_jit}" = "yes" ; then check_for_mprotect=yes fi -if test "${enable_libs}" != "no" ; then - # Canceled for some platforms below: - INSTALL_LIBS_ENABLE=install -fi - ############## platform tests ################ # for flags we don't want to use in config tests: diff --git a/racket/src/cs/Makefile b/racket/src/cs/Makefile index 1236b8d654..435f2ea49c 100644 --- a/racket/src/cs/Makefile +++ b/racket/src/cs/Makefile @@ -22,7 +22,7 @@ CROSS_COMP = COMPILE_FILE = $(SCHEME) --script compile-file.ss $(UNSAFE_COMP) $(COMPRESS_COMP) $(DEBUG_COMP) $(CROSS_COMP) --dest "$(BUILDDIR)" COMPILE_FILE_DEPS = compile-file.ss include.ss place-register.ss -RACKET_SETUP_ARGS = ../../bin/racket ../../bin/racket ../collects ../etc 0 true false 0 "" +RACKET_SETUP_ARGS = false ../../bin/racket ../../bin/racket ../collects ../etc 0 true false 0 "" PRIMITIVES_TABLES = primitive/kernel.ss primitive/unsafe.ss primitive/flfxnum.ss \ primitive/paramz.ss primitive/extfl.ss primitive/network.ss \ diff --git a/racket/src/cs/c/Makefile.in b/racket/src/cs/c/Makefile.in index c73533659c..49e5430452 100644 --- a/racket/src/cs/c/Makefile.in +++ b/racket/src/cs/c/Makefile.in @@ -26,6 +26,9 @@ WINDRES = @WINDRES@ STRIP_DEBUG = @STRIP_DEBUG@ STRIP_LIB_DEBUG = @STRIP_LIB_DEBUG@ +ICP=@ICP@ +ICP_LIB=@ICP_LIB@ + DEFAULT_RACKET = ../../racket/racket3m RACKET = @RACKET@ @@ -61,6 +64,7 @@ cs: $(MAKE) check-racketcs@CROSS_MODE@ $(MAKE) gracketcs $(MAKE) starter + $(MAKE) repack-@INSTALL_LIBS_ENABLE@-libs SETUP_BOOT_MODE = @SETUP_BOOT_MODE@ SETUP_COMMON_BOOT = -l- setup $(SETUP_BOOT_MODE) $(srcdir)/../../setup-go.rkt $(builddir)/compiled @@ -344,6 +348,7 @@ install@MINGW@: plain-install@MINGW@: $(MAKE) plain-install-upcased CS_INSTALLED=`echo $(CS_INSTALLED) | awk '{print toupper($0)}'` + $(MAKE) unix-install-boot-files plain-install-upcased: $(ICP) libracketcsxxxxxxx.dll $(libdir)/libracketcsxxxxxxx.dll @@ -395,11 +400,25 @@ boot.o: $(srcdir)/boot.c $(srcdir)/../../rktio/rktio.inc $(srcdir)/boot.h starter@NOT_MINGW@: $(srcdir)/../../start/ustart.c $(CC) $(CFLAGS) -o starter $(srcdir)/../../start/ustart.c + +repack-install-libs: + make libracketcs.a SCHEME_SRC="$(ABS_SCHEME_SRC)" + +libracketcs.a: $(SCHEME_LIB_DEPS) rktio/librktio.a boot.o + mkdir -p repack + rm -f repack/* + cd repack && @Z_LIB_UNPACK@ + cd repack && @LZ4_LIB_UNPACK@ + cd repack && $(AR) x ../rktio/librktio.a + cd repack && $(AR) x $(SCHEME_TARGET_INC)/libkernel.a + $(AR) $(ARFLAGS) libracketcs.a repack/*.o boot.o + +repack-no-install-libs: + $(NOOP) + # ---------------------------------------- # Install -ICP=@ICP@ - install@NOT_MINGW@: $(MAKE) plain-install $(MAKE) setup-install @@ -438,16 +457,39 @@ common-install: $(ICP) $(srcdir)/../../start/starter-sh "$(DESTDIR)$(libpltdir)/starter-sh" $(RACKET) -cu "$(srcdir)/../../racket/collects-path.rkt" "$(DESTDIR)$(libpltdir)/starter" $(DESTDIR)@COLLECTS_PATH@ $(DESTDIR)@CONFIG_PATH@ $(MAKE) system-install + $(ICP) $(srcdir)/api.h $(includepltdir)/racketcs.h + $(ICP) $(srcdir)/boot.h $(includepltdir)/racketcsboot.h + $(ICP) $(SCHEME_INC)/scheme.h $(includepltdir)/chezscheme.h + $(MAKE) common-@INSTALL_LIBS_ENABLE@-libs system-install: $(RACKET) -cu "$(srcdir)/gen-system.rkt" $(DESTDIR)$(libpltdir)/system$(CS_INSTALLED).rktd $(TARGET_MACH) @CROSS_COMPILE_TARGET_KIND@ +common-install-libs: + $(ICP_LIB) libracketcs.a "$(DESTDIR)$(libdir)/libracketcs.a" + $(STRIP_LIB_DEBUG) "$(DESTDIR)$(libdir)/libracketcs.a" + +common-no-install-libs: + $(NOOP) + unix-install: $(MAKE) common-install rm -f "$(DESTDIR)$(libpltdir)/gracket$(CS_INSTALLED)" $(ICP) gracketcs "$(DESTDIR)$(libpltdir)/gracket$(CS_INSTALLED)" $(RACKET) -cu "$(srcdir)/../../racket/collects-path.rkt" "$(DESTDIR)$(bindir)/racket$(CS_INSTALLED)" $(DESTDIR)@COLLECTS_PATH@ $(DESTDIR)@CONFIG_PATH@ $(RACKET) -cu "$(srcdir)/../../racket/collects-path.rkt" "$(DESTDIR)$(libpltdir)/gracket$(CS_INSTALLED)" $(DESTDIR)@COLLECTS_PATH@ $(DESTDIR)@CONFIG_PATH@ + $(MAKE) unix-@INSTALL_LIBS_ENABLE@-libs + +unix-install-libs: + $(MAKE) unix-install-boot-files + +unix-install-boot-files: + $(BOOTSTRAP_RACKET) $(srcdir)/add-terminator.rkt petite-v.boot "$(DESTDIR)$(libpltdir)/petite.boot" + $(BOOTSTRAP_RACKET) $(srcdir)/add-terminator.rkt scheme-v.boot "$(DESTDIR)$(libpltdir)/scheme.boot" + $(BOOTSTRAP_RACKET) $(srcdir)/add-terminator.rkt racket-v.boot "$(DESTDIR)$(libpltdir)/racket.boot" + +unix-no-install-libs: + $(NOOP) RKTFWDEST = @FRAMEWORK_INSTALL_DIR@/Racket.framework FRAMEWORK_REL_PREFIX = "@executable_path/../$(libpltdir_rel)/" @@ -469,6 +511,7 @@ macos-install: cp $(RKTFWDIR)/boot/racket.boot $(DESTDIR)$(RKTFWDEST)/Versions/$(FWVERSION)_CS/boot/ $(RACKET) -cu "$(srcdir)/../../racket/collects-path.rkt" "$(DESTDIR)$(bindir)/racket$(CS_INSTALLED)" $(DESTDIR)@COLLECTS_PATH@ $(DESTDIR)@CONFIG_PATH@ $(MAKE) macos-install-gracket CS_GR_INSTALLED="`echo $(CS_INSTALLED) | tr a-z A-Z`" + $(MAKE) macos-@INSTALL_LIBS_ENABLE@-libs macos-install-gracket: /usr/bin/install_name_tool -change "@executable_path/Racket.framework/Versions/$(FWVERSION)_CS/Racket" "@FRAMEWORK_PREFIX@Racket.framework/Versions/$(FWVERSION)_CS/Racket" $(DESTDIR)"$(bindir)/racket$(CS_INSTALLED)" @@ -481,6 +524,14 @@ macos-install-gracket: rm -rf $(DESTDIR)"$(libpltdir)/Starter.app" $(ICP) -r Starter.app $(DESTDIR)"$(libpltdir)/." +macos-install-libs: + $(BOOTSTRAP_RACKET) $(srcdir)/add-terminator.rkt $(RKTFWDIR)/boot/petite.boot "$(DESTDIR)$(libpltdir)/petite.boot" + $(BOOTSTRAP_RACKET) $(srcdir)/add-terminator.rkt $(RKTFWDIR)/boot/scheme.boot "$(DESTDIR)$(libpltdir)/scheme.boot" + $(BOOTSTRAP_RACKET) $(srcdir)/add-terminator.rkt $(RKTFWDIR)/boot/racket.boot "$(DESTDIR)$(libpltdir)/racket.boot" + +macos-no-install-libs: + $(NOOP) + # ---------------------------------------- # Check diff --git a/racket/src/cs/c/add-terminator.rkt b/racket/src/cs/c/add-terminator.rkt new file mode 100644 index 0000000000..c5b24d0c13 --- /dev/null +++ b/racket/src/cs/c/add-terminator.rkt @@ -0,0 +1,28 @@ +#lang racket/base +(require racket/cmdline) + +(command-line + #:args + (src dest) + + (copy-file src dest #t) + + (define terminator + (cond + [(equal? #"\0\0\0\0chez" (call-with-input-file* + dest + (lambda (i) (read-bytes 8 i)))) + ;; Not compressed + #"\177"] + [else + ;; Compressed + #"\0"])) + + (call-with-output-file* + dest + #:exists 'update + (lambda (o) + (file-position o (file-size dest)) + (write-bytes terminator o))) + + (void)) diff --git a/racket/src/cs/c/api.h b/racket/src/cs/c/api.h new file mode 100644 index 0000000000..c3026a08f3 --- /dev/null +++ b/racket/src/cs/c/api.h @@ -0,0 +1,27 @@ +/* include "chezscheme.h" before this file */ + +#ifndef RACKETCS_H +#define RACKETCS_H + +#ifndef RACKET_API_EXTERN +# define RACKET_API_EXTERN EXPORT +#endif + +#ifndef RACKETCS_BOOT_H +# define BOOT_EXTERN EXPORT +# include "racketcsboot.h" +#endif + +RACKET_API_EXTERN ptr racket_apply(ptr proc, ptr arg_list); + +RACKET_API_EXTERN ptr racket_primitive(const char *name); + +RACKET_API_EXTERN ptr racket_eval(ptr s_expr); +RACKET_API_EXTERN ptr racket_dynamic_require(ptr module_path, ptr sym_or_false); +RACKET_API_EXTERN void racket_namespace_require(ptr module_path); + +RACKET_API_EXTERN void racket_embedded_load_bytes(const char *code, uptr len, int as_predefined); +RACKET_API_EXTERN void racket_embedded_load_file(const char *path, int as_predefined); +RACKET_API_EXTERN void racket_embedded_load_file_region(const char *path, uptr start, uptr end, int as_predefined); + +#endif diff --git a/racket/src/cs/c/boot.c b/racket/src/cs/c/boot.c index d0364d8800..909bd322b4 100644 --- a/racket/src/cs/c/boot.c +++ b/racket/src/cs/c/boot.c @@ -10,11 +10,13 @@ #include "rktio.h" #ifdef WIN32 -# define BOOT_EXTERN __declspec(dllexport) +# define RACKET_API_EXTERN __declspec(dllexport) #else -# define BOOT_EXTERN extern +# define RACKET_API_EXTERN extern #endif +#define BOOT_EXTERN RACKET_API_EXTERN #include "boot.h" +#include "api.h" #define RACKET_AS_BOOT @@ -26,45 +28,6 @@ # define BOOT_O_BINARY 0 #endif -#if defined(OS_X) && !defined(RACKET_XONX) - -# include -# define RACKET_USE_FRAMEWORK - -const char *get_framework_path() { - int i, c, len; - const char *s; - - c = _dyld_image_count(); - for (i = 0; i < c; i++) { - s = _dyld_get_image_name(i); - len = strlen(s); - if ((len > 7) && !strcmp("/Racket", s + len - 7)) { - char *s2; - s2 = strdup(s); - strcpy(s2 + len - 6, "boot"); - return s2; - } - } - - return "???"; -} - -char *path_append(const char *p1, char *p2) { - int l1, l2; - char *s; - l1 = strlen(p1); - l2 = strlen(p2); - s = malloc(l1 + l2 + 2); - memcpy(s, p1, l1); - s[l1] = '/'; - memcpy(s + l1 + 1, p2, l2); - s[l1+l2+1] = 0; - return s; -} - -#endif - static ptr Sbytevector(char *s) { iptr len = strlen(s); @@ -135,75 +98,42 @@ static void init_foreign() Sforeign_symbol("racket_errno", (void *)racket_errno); } -void racket_boot(int argc, char **argv, char *exec_file, char *run_file, - char *boot_exe, long segment_offset, - char *coldir, char *configdir, /* wchar_t * */void *dlldir, - int is_embedded, int pos1, int pos2, int pos3, - int cs_compiled_subdir, int is_gui, - int wm_is_gracket_or_x11_arg_count, - char *gracket_guid_or_x11_args, - void *dll_open, void *dll_find_object, void *dll_close) -/* exe argument already stripped from argv */ +void racket_boot(racket_boot_arguments_t *ba) { - int fd; -#ifdef RACKET_AS_BOOT - int skip_racket_boot = 0; -#endif -#ifdef RACKET_USE_FRAMEWORK - const char *fw_path; -#endif int cross_server = 0; #ifdef WIN32 - if (dlldir) - rktio_set_dll_path((wchar_t *)dlldir); - if (dll_open) - rktio_set_dll_procs(dll_open, dll_find_object, dll_close); + if (ba->dll_dir) + rktio_set_dll_path((wchar_t *)ba->dll_dir); + if (ba->dll_open) + rktio_set_dll_procs(ba->dll_open, ba->dll_find_object, ba->dll_close); #endif Sscheme_init(NULL); - if ((argc == 4) && !strcmp(argv[0], "--cross-server")) { + if ((ba->argc == 4) && !strcmp(ba->argv[0], "--cross-server")) cross_server = 1; -#ifdef RACKET_AS_BOOT - skip_racket_boot = 1; -#endif - } -#ifdef RACKET_USE_FRAMEWORK - if (!is_embedded) { - fw_path = get_framework_path(); - Sregister_boot_file(path_append(fw_path, "petite.boot")); - Sregister_boot_file(path_append(fw_path, "scheme.boot")); -# ifdef RACKET_AS_BOOT - if (!skip_racket_boot) - Sregister_boot_file(path_append(fw_path, "racket.boot")); -# endif - } -#endif + { + int fd1, fd2; - if (is_embedded) { - fd = open(boot_exe, O_RDONLY | BOOT_O_BINARY); - - { - int fd1, fd2; - - fd1 = dup(fd); - lseek(fd1, pos1, SEEK_SET); - Sregister_boot_file_fd("petite", fd1); + fd1 = open(ba->boot1_path, O_RDONLY | BOOT_O_BINARY); + lseek(fd1, ba->boot1_offset, SEEK_SET); + Sregister_boot_file_fd("petite", fd1); - fd2 = open(boot_exe, O_RDONLY | BOOT_O_BINARY); - lseek(fd2, pos2, SEEK_SET); - Sregister_boot_file_fd("scheme", fd2); + fd2 = open(ba->boot2_path, O_RDONLY | BOOT_O_BINARY); + lseek(fd2, ba->boot2_offset, SEEK_SET); + Sregister_boot_file_fd("scheme", fd2); # ifdef RACKET_AS_BOOT - if (!skip_racket_boot) { - fd = open(boot_exe, O_RDONLY | BOOT_O_BINARY); - lseek(fd, pos3, SEEK_SET); - Sregister_boot_file_fd("racket", fd); - } -# endif + if (!cross_server) { + int fd3; + + fd3 = open(ba->boot3_path, O_RDONLY | BOOT_O_BINARY); + lseek(fd3, ba->boot3_offset, SEEK_SET); + Sregister_boot_file_fd("racket", fd3); } +# endif } Sbuild_heap(NULL, init_foreign); @@ -211,7 +141,7 @@ void racket_boot(int argc, char **argv, char *exec_file, char *run_file, if (cross_server) { /* Don't run Racket as usual. Instead, load the patch file and run `serve-cross-compile` */ - run_cross_server(argv); + run_cross_server(ba->argv); racket_exit(0); } @@ -220,20 +150,25 @@ void racket_boot(int argc, char **argv, char *exec_file, char *run_file, int i; char segment_offset_s[32], wm_is_gracket_s[32]; - for (i = argc; i--; ) { - l = Scons(Sbytevector(argv[i]), l); + if (ba->argv) { + for (i = ba->argc; i--; ) { + l = Scons(Sbytevector(ba->argv[i]), l); + } + } else { + l = Scons(Sbytevector("-n"), l); } - l = Scons(Sbytevector(gracket_guid_or_x11_args), l); - sprintf(wm_is_gracket_s, "%d", wm_is_gracket_or_x11_arg_count); + l = Scons(Sbytevector(ba->gracket_guid_or_x11_args ? ba->gracket_guid_or_x11_args : ""), l); + sprintf(wm_is_gracket_s, "%d", ba->wm_is_gracket_or_x11_arg_count); l = Scons(Sbytevector(wm_is_gracket_s), l); - l = Scons(Sbytevector(is_gui ? "true" : "false"), l); - l = Scons(Sbytevector(cs_compiled_subdir ? "true" : "false"), l); - sprintf(segment_offset_s, "%ld", segment_offset); + l = Scons(Sbytevector(ba->is_gui ? "true" : "false"), l); + l = Scons(Sbytevector(ba->cs_compiled_subdir ? "true" : "false"), l); + sprintf(segment_offset_s, "%ld", ba->segment_offset); l = Scons(Sbytevector(segment_offset_s), l); - l = Scons(Sbytevector(configdir), l); - l = Scons(parse_coldirs(coldir), l); - l = Scons(Sbytevector(run_file), l); - l = Scons(Sbytevector(exec_file), l); + l = Scons(Sbytevector(ba->config_dir ? ba->config_dir : "etc"), l); + l = Scons(parse_coldirs(ba->collects_dir ? ba->collects_dir : ""), l); + l = Scons(Sbytevector(ba->run_file ? ba->run_file : ba->exec_file ), l); + l = Scons(Sbytevector(ba->exec_file), l); + l = Scons(Sbytevector(ba->exit_after ? "false" : "true"), l); #ifdef RACKET_AS_BOOT { @@ -249,19 +184,14 @@ void racket_boot(int argc, char **argv, char *exec_file, char *run_file, } #ifndef RACKET_AS_BOOT -# ifdef RACKET_USE_FRAMEWORK - if (!is_embedded) { - fd = open(path_append(fw_path, "racket.so"), O_RDONLY); - pos3 = 0; - } -# endif - { ptr c, p; + int f3; - if (pos3) lseek(fd, pos3, SEEK_SET); + fd3 = open(ba->boot3_path, O_RDONLY | BOOT_O_BINARY); + if (boot3_offset) lseek(fd3, ba->boot3_offset, SEEK_SET); c = Stop_level_value(Sstring_to_symbol("open-fd-input-port")); - p = Scall1(c, Sfixnum(fd)); + p = Scall1(c, Sfixnum(fd3)); Slock_object(p); c = Stop_level_value(Sstring_to_symbol("port-file-compressed!")); Scall1(c, p); @@ -271,3 +201,83 @@ void racket_boot(int argc, char **argv, char *exec_file, char *run_file, } #endif } + +/* **************************************** */ + +enum { + EMBEDDED_ENTRY_APPLY, + EMBEDDED_ENTRY_PRIMITIVE_LOOKUP, + EMBEDDED_ENTRY_EVAL, + EMBEDDED_ENTRY_DYNAMIC_REQUIRE, + EMBEDDED_ENTRY_NAMESPACE_REQUIRE, + EMBEDDED_ENTRY_EMBEDDED_LOAD +}; + +static ptr get_embedded_entry(int index) +{ + ptr vec; + + vec = Stop_level_value(Sstring_to_symbol("embedded-racket-entry-info")); + return Svector_ref(vec, index); +} + +ptr racket_apply(ptr proc, ptr arg_list) +{ + ptr app = get_embedded_entry(EMBEDDED_ENTRY_APPLY); + + return Scall2(app, proc, arg_list); +} + +ptr racket_primitive(const char *name) +{ + ptr prim_lookup = get_embedded_entry(EMBEDDED_ENTRY_PRIMITIVE_LOOKUP); + + return Scall1(prim_lookup, Sstring_to_symbol(name)); +} + +ptr racket_eval(ptr s_expr) +{ + ptr eval = get_embedded_entry(EMBEDDED_ENTRY_EVAL); + + return racket_apply(eval, Scons(s_expr, Snil)); +} + +ptr racket_dynamic_require(ptr module_path, ptr sym_or_false) +{ + ptr dy_req = get_embedded_entry(EMBEDDED_ENTRY_DYNAMIC_REQUIRE); + + return racket_apply(dy_req, Scons(module_path, Scons(sym_or_false, Snil))); +} + +void racket_namespace_require(ptr module_path) +{ + ptr ns_req = get_embedded_entry(EMBEDDED_ENTRY_NAMESPACE_REQUIRE); + + (void)racket_apply(ns_req, Scons(module_path, Snil)); +} + +static void embedded_load(ptr path, ptr start, ptr end, ptr bstr, int as_predefined) +{ + ptr load = get_embedded_entry(EMBEDDED_ENTRY_EMBEDDED_LOAD); + ptr pre = (as_predefined ? Strue : Sfalse); + + (void)racket_apply(load, Scons(path, Scons(start, Scons(end, Scons(bstr, Scons(pre, Snil)))))); +} + +void racket_embedded_load_bytes(const char *code, uptr len, int as_predefined) +{ + ptr bstr = Smake_bytevector(len, 0); + memcpy(Sbytevector_data(bstr), code, len); + + embedded_load(Sfalse, Sfalse, Sfalse, bstr, as_predefined); +} + +void racket_embedded_load_file(const char *path, int as_predefined) +{ + embedded_load(Sbytevector((char *)path), Sfixnum(0), Sfalse, Sfalse, as_predefined); +} + +void racket_embedded_load_file_region(const char *path, uptr start, uptr end, int as_predefined) +{ + embedded_load(Sbytevector((char *)path), Sfixnum(start), Sfixnum(end), Sfalse, as_predefined); +} diff --git a/racket/src/cs/c/boot.h b/racket/src/cs/c/boot.h index 84017e5987..c441f5c214 100644 --- a/racket/src/cs/c/boot.h +++ b/racket/src/cs/c/boot.h @@ -1,15 +1,57 @@ -BOOT_EXTERN void racket_boot(int argc, char **argv, char *exec_file, char *run_file, - char *boot_exe, long segment_offset, - char *coldir, char *configdir, /* wchar_t * */void *dlldir, - int is_embedded, int pos1, int pos2, int pos3, - int cs_compiled_subdir, int is_gui, - int wm_is_gracket_or_x11_arg_count, char *gracket_guid_or_x11_args, - void *ddll_open, void *dll_find_object, void *dll_close); +#ifndef RACKETCS_BOOT_H +#define RACKETCS_BOOT_H -typedef void (*racket_boot_t)(int argc, char **argv, char *exec_file, char *run_file, - char* boot_exe, long segment_offset, - char *coldir, char *configdir, /* wchar_t * */void *dlldir, - int is_embedded, int pos1, int pos2, int pos3, - int cs_compiled_subdir, int is_gui, - int wm_is_gracket_or_x11_arg_count, char *gracket_guid_or_x11_args, - void *ddll_open, void *dll_find_object, void *dll_close); +/* This structure type can change, but NULL/0 will be supported as a + default for any new field that is added. */ +typedef struct racket_boot_arguments_t { + /* Boot files --- potentially the same path with different offsets. + If a boot image is embedded in a larger file, it must be + terminated with "\0 if the boot image is compressed or "\177" if + the boot image is uncompressed. */ + const char *boot1_path; /* REQUIRED; path to "petite.boot" */ + long boot1_offset; + const char *boot2_path; /* REQUIRED; path to "scheme.boot" */ + long boot2_offset; + const char *boot3_path; /* REQUIRED; path to "racket.boot" */ + long boot3_offset; + + /* Command-line arguments are handled in the same way as the + `racket` exectuable. The `argv` array should *not* include the + executable name like `argv` passed to `main`. */ + int argc; + char **argv; /* NULL => "-n", which does nothing after booting */ + + /* Racket path configuration, mostly setting the results of + `(find-system-path ...)`: */ + const char *exec_file; /* REQUIRED; usually the original argv[0] */ + const char *run_file; /* can be NULL to mean the same as `exec_file` */ + const char *collects_dir; /* can be NULL or "" to disable collection path */ + const char *config_dir; /* use NULL or "etc" if you don't care */ + /* wchar_t * */void *dll_dir; /* can be NULL for default */ + + /* How to initialize `use-compiled-file-paths`: */ + int cs_compiled_subdir; /* true => subdirectory of "compiled" */ + + /* Embedded-code offset, which is added to any `-k` argument. */ + long segment_offset; /* use 0 if no `-k` embedding */ + + /* For embedded DLLs on Windows, if non-NULL: */ + void *dll_open; + void *dll_find_object; + void *dll_close; + + /* Whether to run as command-line Racket or in embedded mode: */ + int exit_after; /* 1 => exit after handling the command-line */ + + /* For GUI applications; use 0 and "" as defaults: */ + int is_gui; + int wm_is_gracket_or_x11_arg_count; + char *gracket_guid_or_x11_args; +} racket_boot_arguments_t; + +BOOT_EXTERN void racket_boot(racket_boot_arguments_t *boot_args); + +/* Same as `racket_boot` prototype; but in type form: */ +typedef void (*racket_boot_t)(racket_boot_arguments_t *boot_args); + +#endif diff --git a/racket/src/cs/c/configure b/racket/src/cs/c/configure index 596514d8cd..331c72ae8f 100755 --- a/racket/src/cs/c/configure +++ b/racket/src/cs/c/configure @@ -622,6 +622,7 @@ ac_includes_default="\ ac_subst_vars='LTLIBOBJS LIBOBJS +INSTALL_LIBS_ENABLE INSTALL_SETUP_RACKET_FLAGS INSTALL_SETUP_FLAGS RUN_RACKET @@ -640,8 +641,10 @@ ELF_COMP BOOT_COMPRESS_COMP COMPRESS_COMP CONFIGURE_RACKET_SO_COMPILE +LZ4_LIB_UNPACK LZ4_LIB LZ4_LIB_DEP +Z_LIB_UNPACK Z_LIB Z_LIB_DEP NOT_MINGW @@ -664,6 +667,7 @@ POST_LINKER RKTLINKER STRIP_LIB_DEBUG STRIP_DEBUG +ICP_LIB ICP WINDRES STATIC_AR @@ -789,6 +793,7 @@ enable_libfw enable_userfw enable_embedfw enable_mac64 +enable_libs enable_noopt enable_ubsan enable_csdefault @@ -1438,6 +1443,7 @@ Optional Features: --enable-userfw install Mac OS frameworks to ~/Library/Frameworks --enable-embedfw embed Mac OS framework content in executables --enable-mac64 allow 64-bit Mac OS build (enabled by default) + --enable-libs install static libraries (enabled by default for Unix) --enable-strip strip debug on install (usually enabled by default) --enable-ubsan compile with -fsanitize=undefined --enable-csdefault use CS as default build @@ -2648,6 +2654,12 @@ else fi +# Check whether --enable-libs was given. +if test "${enable_libs+set}" = set; then : + enableval=$enable_libs; +fi + + # Check whether --enable-noopt was given. if test "${enable_noopt+set}" = set; then : enableval=$enable_noopt; @@ -2785,6 +2797,16 @@ if test "${enable_csonly}" = "yes" ; then fi show_explicitly_enabled "${enable_csdefault}" "executables without suffix" +show_explicitly_enabled "${enable_libs}" "Installation of static libraries (if any)" +show_explicitly_disabled "${enable_libs}" "Installation of static libraries (if any)" + +INSTALL_LIBS_ENABLE=no-install + +if test "${enable_libs}" != "no" ; then + # Intended to be canceled for some platforms: + INSTALL_LIBS_ENABLE=install +fi + show_explicitly_disabled "${enable_mac64}" "64-bit Mac OS" show_explicitly_enabled "${enable_libfw}" "Frameworks-to-system" @@ -3096,8 +3118,10 @@ INSTALL_SETUP_RACKET_FLAGS= Z_LIB_DEP='$(OWN_Z_LIB)' Z_LIB='$(OWN_Z_LIB)' +Z_LIB_UNPACK='$(AR) x $(OWN_Z_LIB)' LZ4_LIB_DEP='$(OWN_LZ4_LIB)' LZ4_LIB='$(OWN_LZ4_LIB)' +LZ4_LIB_UNPACK='$(AR) x $(OWN_LZ4_LIB)' enable_pthread_by_default=yes @@ -4603,6 +4627,10 @@ fi if `which ${host}-windres > /dev/null` ; then WINDRES="${host}-windres" fi + # ".a" is typically not useful, since we always build a DLL: + if test "${enable_libs}" = "" ; then + INSTALL_LIBS_ENABLE=no-install + fi ;; cygwin*) ;; @@ -5239,6 +5267,7 @@ $as_echo "$have_zlib" >&6; } else Z_LIB_DEP="" Z_LIB="-lz" + Z_LIB_UNPACK="$(NOOP)" extra_scheme_config_args="${extra_scheme_config_args} ZLIB=-lz" fi fi @@ -5276,6 +5305,7 @@ $as_echo "$have_lz4" >&6; } else LZ4_LIB_DEP="" LZ4_LIB="-llz4" + LZ4_LIB_UNPACK="$(NOOP)" extra_scheme_config_args="${extra_scheme_config_args} LZ4=-llz4" fi fi @@ -5474,6 +5504,10 @@ SCHEME_CROSS_CONFIG_ARGS="--machine=${TARGET_MACH} --disable-x11 ${disable_curse + + + + diff --git a/racket/src/cs/c/configure.ac b/racket/src/cs/c/configure.ac index b6fd8aafba..849bfb81e1 100644 --- a/racket/src/cs/c/configure.ac +++ b/racket/src/cs/c/configure.ac @@ -25,6 +25,7 @@ AC_ARG_ENABLE(mach, [ --enable-mach= Use Chez Scheme machine typ AC_ARG_ENABLE(target, [ --enable-target= Cross-build for Chez Scheme machine type ]) m4_include(../ac/natipkg_arg.m4) m4_include(../ac/sdk_arg.m4) +m4_include(../ac/instlib_arg.m4) m4_include(../ac/strip_arg.m4) m4_include(../ac/ubsan_arg.m4) AC_ARG_ENABLE(csdefault, [ --enable-csdefault use CS as default build]) @@ -86,6 +87,7 @@ if test "${enable_csonly}" = "yes" ; then fi show_explicitly_enabled "${enable_csdefault}" "executables without suffix" +m4_include(../ac/instlib.m4) m4_include(../ac/sdk_show.m4) m4_include(../ac/strip_show.m4) @@ -151,8 +153,10 @@ INSTALL_SETUP_RACKET_FLAGS= Z_LIB_DEP='$(OWN_Z_LIB)' Z_LIB='$(OWN_Z_LIB)' +Z_LIB_UNPACK='$(AR) x $(OWN_Z_LIB)' LZ4_LIB_DEP='$(OWN_LZ4_LIB)' LZ4_LIB='$(OWN_LZ4_LIB)' +LZ4_LIB_UNPACK='$(AR) x $(OWN_LZ4_LIB)' enable_pthread_by_default=yes @@ -249,6 +253,10 @@ case "$host_os" in if `which ${host}-windres > /dev/null` ; then WINDRES="${host}-windres" fi + # ".a" is typically not useful, since we always build a DLL: + if test "${enable_libs}" = "" ; then + INSTALL_LIBS_ENABLE=no-install + fi ;; cygwin*) ;; @@ -542,6 +550,7 @@ if test "${enable_libz}" = "yes" ; then else Z_LIB_DEP="" Z_LIB="-lz" + Z_LIB_UNPACK="$(NOOP)" extra_scheme_config_args="${extra_scheme_config_args} ZLIB=-lz" fi fi @@ -563,6 +572,7 @@ if test "${enable_liblz4}" = "yes" ; then else LZ4_LIB_DEP="" LZ4_LIB="-llz4" + LZ4_LIB_UNPACK="$(NOOP)" extra_scheme_config_args="${extra_scheme_config_args} LZ4=-llz4" fi fi @@ -685,6 +695,7 @@ AC_SUBST(RANLIB) AC_SUBST(STATIC_AR) AC_SUBST(WINDRES) AC_SUBST(ICP) +AC_SUBST(ICP_LIB) AC_SUBST(STRIP_DEBUG) AC_SUBST(STRIP_LIB_DEBUG) AC_SUBST(RKTLINKER) @@ -707,8 +718,10 @@ AC_SUBST(MINGW) AC_SUBST(NOT_MINGW) AC_SUBST(Z_LIB_DEP) AC_SUBST(Z_LIB) +AC_SUBST(Z_LIB_UNPACK) AC_SUBST(LZ4_LIB_DEP) AC_SUBST(LZ4_LIB) +AC_SUBST(LZ4_LIB_UNPACK) AC_SUBST(CONFIGURE_RACKET_SO_COMPILE) AC_SUBST(COMPRESS_COMP) AC_SUBST(BOOT_COMPRESS_COMP) @@ -727,6 +740,7 @@ AC_SUBST(CROSS_COMPILE_TARGET_KIND) AC_SUBST(RUN_RACKET) AC_SUBST(INSTALL_SETUP_FLAGS) AC_SUBST(INSTALL_SETUP_RACKET_FLAGS) +AC_SUBST(INSTALL_LIBS_ENABLE) makefiles="Makefile" diff --git a/racket/src/cs/c/embed-boot.rkt b/racket/src/cs/c/embed-boot.rkt index cb33a13742..196fe0a102 100644 --- a/racket/src/cs/c/embed-boot.rkt +++ b/racket/src/cs/c/embed-boot.rkt @@ -48,8 +48,8 @@ (if (compress-enabled?) ;; zero byte stops a gzip-read sequence #"\0" - ;; #!eof encoding stops(!) a fasl-read sequence - #"\44\26\2\f6")) + ;; A 127 byte teriminates a fasl-read sequence + #"\177")) (define data (bytes-append bstr1 terminator bstr2 terminator diff --git a/racket/src/cs/c/main.c b/racket/src/cs/c/main.c index ce2566fcea..8e428a5396 100644 --- a/racket/src/cs/c/main.c +++ b/racket/src/cs/c/main.c @@ -107,6 +107,45 @@ static long find_rktboot_section(char *me) } #endif +#if defined(OS_X) && !defined(RACKET_XONX) + +# include +# define RACKET_USE_FRAMEWORK 1 + +static const char *get_framework_path() { + int i, c, len; + const char *s; + + c = _dyld_image_count(); + for (i = 0; i < c; i++) { + s = _dyld_get_image_name(i); + len = strlen(s); + if ((len > 7) && !strcmp("/Racket", s + len - 7)) { + char *s2; + s2 = strdup(s); + strcpy(s2 + len - 6, "boot"); + return s2; + } + } + + return "???"; +} + +static char *path_append(const char *p1, char *p2) { + int l1, l2; + char *s; + l1 = strlen(p1); + l2 = strlen(p2); + s = malloc(l1 + l2 + 2); + memcpy(s, p1, l1); + s[l1] = '/'; + memcpy(s + l1 + 1, p2, l2); + s[l1+l2+1] = 0; + return s; +} + +#endif + #if defined(__linux__) # include static char *get_self_path(char *exec_file) @@ -375,8 +414,13 @@ static int bytes_main(int argc, char **argv, /* for Windows and X11 GUI modes */ int wm_is_gracket_or_x11_arg_count, char *gracket_guid_or_x11_args) { - char *boot_exe, *exec_file = argv[0], *run_file = NULL; - int is_embedded = 1, pos1, pos2, pos3; + char *boot_exe; + char *exec_file = argv[0], *run_file = NULL; + char *boot1_path, *boot2_path, *boot3_path; + int boot1_offset, boot2_offset, boot3_offset; +#ifdef OS_X + int boot_images_in_exe = 1; +#endif long boot_offset; long segment_offset; #ifdef WIN32 @@ -392,6 +436,16 @@ static int bytes_main(int argc, char **argv, argv++; } + extract_built_in_arguments(&exec_file, &run_file, &argc, &argv); + if (!run_file) + run_file = exec_file; + + segment_offset = get_segment_offset(); + + memcpy(&boot1_offset, boot_file_data + boot_file_offset, sizeof(boot1_offset)); + memcpy(&boot2_offset, boot_file_data + boot_file_offset + 4, sizeof(boot2_offset)); + memcpy(&boot3_offset, boot_file_data + boot_file_offset + 8, sizeof(boot3_offset)); + #ifdef WIN32 parse_embedded_dlls(); register_embedded_dll_hooks(); @@ -412,39 +466,70 @@ static int bytes_main(int argc, char **argv, boot_exe = get_self_path(exec_file); #endif - extract_built_in_arguments(&exec_file, &run_file, &argc, &argv); - if (!run_file) - run_file = exec_file; - - segment_offset = get_segment_offset(); - - memcpy(&pos1, boot_file_data + boot_file_offset, sizeof(pos1)); - memcpy(&pos2, boot_file_data + boot_file_offset + 4, sizeof(pos2)); - memcpy(&pos3, boot_file_data + boot_file_offset + 8, sizeof(pos2)); - #ifdef ELF_FIND_BOOT_SECTION boot_offset = find_boot_section(boot_exe); -#elif OS_X +#elif defined(OS_X) boot_offset = find_rktboot_section(boot_exe); - if (!boot_offset) is_embedded = 0; + if (!boot_offset) boot_images_in_exe = 0; #elif WIN32 boot_offset = find_resource_offset(dll_path, 259, boot_rsrc_offset); #else boot_offset = 0; #endif - pos1 += boot_offset; - pos2 += boot_offset; - pos3 += boot_offset; + boot1_offset += boot_offset; + boot2_offset += boot_offset; + boot3_offset += boot_offset; + + boot1_path = boot2_path = boot3_path = boot_exe; + +#if defined(OS_X) && !defined(RACKET_XONX) + if (!boot_images_in_exe) { + const char *fw_path = get_framework_path(); + boot1_path = path_append(fw_path, "petite.boot"); + boot2_path = path_append(fw_path, "scheme.boot"); + boot3_path = path_append(fw_path, "racket.boot"); + boot1_offset = boot2_offset = boot3_offset = 0; + } +#endif + + { + racket_boot_arguments_t ba; + + memset(&ba, 0, sizeof(ba)); + + ba.boot1_path = boot1_path; + ba.boot1_offset = boot1_offset; + ba.boot2_path = boot2_path; + ba.boot2_offset = boot2_offset; + ba.boot3_path = boot3_path; + ba.boot3_offset = boot3_offset; + + ba.argc = argc; + ba.argv = argv; + ba.exec_file = exec_file; + ba.run_file = run_file; + ba.collects_dir = extract_coldir(); + ba.config_dir = extract_configdir(); + ba.dll_dir = extract_dlldir(); + + ba.cs_compiled_subdir = CS_COMPILED_SUBDIR; + + ba.segment_offset = segment_offset; + + ba.dll_open = embedded_dll_open; + ba.dll_find_object = scheme_dll_find_object; + ba.dll_close = embedded_dll_close; + + ba.exit_after = 1; + + ba.is_gui = RACKET_IS_GUI; + ba.wm_is_gracket_or_x11_arg_count = wm_is_gracket_or_x11_arg_count; + ba.gracket_guid_or_x11_args = gracket_guid_or_x11_args; + + racket_boot(&ba); + } - racket_boot(argc, argv, exec_file, run_file, - boot_exe, segment_offset, - extract_coldir(), extract_configdir(), extract_dlldir(), - is_embedded, pos1, pos2, pos3, - CS_COMPILED_SUBDIR, RACKET_IS_GUI, - wm_is_gracket_or_x11_arg_count, gracket_guid_or_x11_args, - embedded_dll_open, scheme_dll_find_object, embedded_dll_close); - return 0; } diff --git a/racket/src/cs/main.sps b/racket/src/cs/main.sps index 7c0eb2830f..24f8494303 100644 --- a/racket/src/cs/main.sps +++ b/racket/src/cs/main.sps @@ -46,7 +46,8 @@ linklet-performance-report! current-compile-target-machine compile-target-machine? - add-cross-compiler!)) + add-cross-compiler! + primitive-lookup)) (linklet-performance-init!) (unless omit-debugging? @@ -78,18 +79,20 @@ (define (getenv-bytes str) (environment-variables-ref (current-environment-variables) (string->utf8 str))) - (define builtin-argc 9) + (define builtin-argc 10) (seq (unless (>= (length the-command-line-arguments) builtin-argc) (error 'racket (string-append - "expected `exec-file`, `run-file`, `collects`, and `etc` paths" + "expected `embedded-interactive-mode?`," + " `exec-file`, `run-file`, `collects`, and `etc` paths" " plus `segment-offset`, `cs-compiled-subdir?`, `is-gui?`," " `wm-is-gracket-or-x11-arg-count`, and `gracket-guid-or-x11-args`" " to start"))) - (set-exec-file! (->path (list-ref the-command-line-arguments/maybe-bytes 0))) - (set-run-file! (->path (list-ref the-command-line-arguments/maybe-bytes 1)))) + (set-exec-file! (->path (list-ref the-command-line-arguments/maybe-bytes 1))) + (set-run-file! (->path (list-ref the-command-line-arguments/maybe-bytes 2)))) + (define embedded-interactive-mode? (string=? "true" (list-ref the-command-line-arguments 0))) (define-values (init-collects-dir collects-pre-extra) - (let ([s (list-ref the-command-line-arguments/maybe-bytes 2)]) + (let ([s (list-ref the-command-line-arguments/maybe-bytes 3)]) (cond [(or (equal? s "") (equal? s '#vu8())) @@ -99,12 +102,12 @@ (values (->path (car s)) (map ->path (cdr s))))]))) (define init-config-dir (->path (or (getenv-bytes "PLTCONFIGDIR") - (list-ref the-command-line-arguments/maybe-bytes 3)))) - (define segment-offset (#%string->number (list-ref the-command-line-arguments 4))) - (define cs-compiled-subdir? (string=? "true" (list-ref the-command-line-arguments 5))) - (define gracket? (string=? "true" (list-ref the-command-line-arguments 6))) - (define wm-is-gracket-or-x11-arg-count (string->number (list-ref the-command-line-arguments 7))) - (define gracket-guid-or-x11-args (list-ref the-command-line-arguments 8)) + (list-ref the-command-line-arguments/maybe-bytes 4)))) + (define segment-offset (#%string->number (list-ref the-command-line-arguments 5))) + (define cs-compiled-subdir? (string=? "true" (list-ref the-command-line-arguments 6))) + (define gracket? (string=? "true" (list-ref the-command-line-arguments 7))) + (define wm-is-gracket-or-x11-arg-count (string->number (list-ref the-command-line-arguments 8))) + (define gracket-guid-or-x11-args (list-ref the-command-line-arguments 9)) (seq (when (foreign-entry? "racket_exit") @@ -146,7 +149,7 @@ #f (machine-type))) (define compiled-roots-path-list-string (getenv "PLTCOMPILEDROOTS")) - (define embedded-load-in-places #f) + (define embedded-load-in-places '()) (define (see saw . args) (let loop ([saw saw] [args args]) @@ -410,7 +413,7 @@ (set! loads (cons (lambda () - (set! embedded-load-in-places (list n m)) + (set! embedded-load-in-places (cons (list #f n m #f) embedded-load-in-places)) (embedded-load n m #f #t) (embedded-load m p #f #f)) loads))) @@ -760,6 +763,44 @@ (version))]) (path-list-string->path-list s (list (build-path 'same))))))) + ;; Called when Racket is embedded in a larger application: + (define (register-embedded-entry-info! escape) + (let ([resume-k #f]) ;; to get back to Racket thread; expects a thunk + ((call/cc ;; Scheme-level `call/cc` to escape Racket's thread-engine loop + (lambda (init-resume-k) + (set! resume-k init-resume-k) + (set-top-level-value! + 'embedded-racket-entry-info + ;; A vector of specific functions: + (vector + ;; Resume the main Racket thread to apply `proc` to `args`, + ;; and return a list of result values; no exception handling + ;; or other such protections + (lambda (proc args) + (call/cc ;; Scheme-level `call/cc` to escape engine loop + (lambda (entry-point-k) + (resume-k + (lambda () + (let-values ([vals (apply proc args)]) + ((call/cc + (lambda (latest-resume-k) + (set! resume-k init-resume-k) + (entry-point-k vals)))))))))) + ;; Functions that are useful to apply and that + ;; provide access to everything else: + primitive-lookup + eval + dynamic-require + namespace-require + ;; bstr as #f => use path, start, and end + ;; path as #f => find executable + ;; end as #f => use file size + (lambda (path start end bstr as-predefined?) + (embedded-load start end bstr as-predefined? path) + (when as-predefined? + (set! embedded-load-in-places (cons (list path start end bstr) embedded-load-in-places)))))) + (escape)))))) + (set-make-place-ports+fds! make-place-ports+fds) (set-start-place! @@ -768,9 +809,11 @@ (regexp-place-init!) (expander-place-init!) (initialize-place!) - (when embedded-load-in-places - (let-values ([(n m) (apply values embedded-load-in-places)]) - (embedded-load n m #f #t))) + (let loop ([l (reverse embedded-load-in-places)]) + (unless (null? l) + (let-values ([(path n m bstr) (apply values (car l))]) + (embedded-load n m bstr #t path)) + (loop (cdr l)))) (lambda () (let ([f (dynamic-require mod sym)]) (f pch))))) @@ -789,45 +832,53 @@ (when version? (display (banner))) - (call-in-main-thread - (lambda () - (initialize-place!) - - (when init-library - (namespace-require+ init-library)) - - (call-with-continuation-prompt + (call/cc ; Chez Scheme's `call/cc`, used here to escape from the Racket-thread engine loop + (lambda (entry-point-k) + (call-in-main-thread (lambda () - (for-each (lambda (ld) (ld)) - (reverse loads))) - (default-continuation-prompt-tag) - ;; If any load escapes, then set the exit value and - ;; stop running loads (but maybe continue with the REPL) - (lambda (proc) - (set! exit-value 1) - ;; Let the actual default handler report an arity mismatch, etc. + (initialize-place!) + + (when init-library + (namespace-require+ init-library)) + (call-with-continuation-prompt - (lambda () (abort-current-continuation (default-continuation-prompt-tag) proc))))) + (lambda () + (for-each (lambda (ld) (ld)) + (reverse loads))) + (default-continuation-prompt-tag) + ;; If any load escapes, then set the exit value and + ;; stop running loads (but maybe continue with the REPL) + (lambda (proc) + (set! exit-value 1) + ;; Let the actual default handler report an arity mismatch, etc. + (call-with-continuation-prompt + (lambda () (abort-current-continuation (default-continuation-prompt-tag) proc))))) + + (when repl? + (set! exit-value 0) + (when repl-init? + (let ([m (get-repl-init-filename)]) + (when m + (call-with-continuation-prompt + (lambda () (dynamic-require m 0)) + (default-continuation-prompt-tag) + (lambda args (set! exit-value 1)))))) + (|#%app| (if text-repl? + (dynamic-require 'racket/base 'read-eval-print-loop) + (dynamic-require 'racket/gui/init 'graphical-read-eval-print-loop))) + (when text-repl? + (newline))) - (when repl? - (set! exit-value 0) - (when repl-init? - (let ([m (get-repl-init-filename)]) - (when m - (call-with-continuation-prompt - (lambda () (dynamic-require m 0)) - (default-continuation-prompt-tag) - (lambda args (set! exit-value 1)))))) - (|#%app| (if text-repl? - (dynamic-require 'racket/base 'read-eval-print-loop) - (dynamic-require 'racket/gui/init 'graphical-read-eval-print-loop))) - (when text-repl? - (newline))) + (when yield? + (|#%app| (executable-yield-handler) exit-value)) - (when yield? - (|#%app| (executable-yield-handler) exit-value)) - - (exit exit-value)))) + (cond + [embedded-interactive-mode? + (register-embedded-entry-info! + (lambda () + (entry-point-k exit-value)))] + [else + (exit exit-value)])))))) (define the-command-line-arguments (or (and (top-level-bound? 'bytes-command-line-arguments) diff --git a/racket/src/expander/eval/load.rkt b/racket/src/expander/eval/load.rkt index 1c8592385a..6ccc8df5f6 100644 --- a/racket/src/expander/eval/load.rkt +++ b/racket/src/expander/eval/load.rkt @@ -41,14 +41,21 @@ ((current-load/use-compiled) p #f)) ;; used for the -k command-line argument: -(define (embedded-load start end str as-predefined?) - (let* ([s (if str - str - (let* ([sp (find-system-path 'exec-file)] - [exe (find-executable-path sp #f)] - [start (or (string->number start) 0)] - [end (or (string->number end) 0)]) - (with-input-from-file exe +(define (embedded-load start end bstr as-predefined? [in-path #f]) + (let* ([s (if bstr + bstr + (let* ([path (cond + [(bytes? in-path) (bytes->path in-path)] + [(string? in-path) in-path] + [else + (find-executable-path (find-system-path 'exec-file) #f)])] + [start (if (string? start) + (or (string->number start) 0) + start)] + [end (if (string? end) + (or (string->number end) 0) + (or end (file-size path)))]) + (with-input-from-file path (lambda () (file-position (current-input-port) start) (read-bytes (max 0 (- end start)))))))] diff --git a/racket/src/racket/configure.ac b/racket/src/racket/configure.ac index 560b9b8898..eec4e369f0 100644 --- a/racket/src/racket/configure.ac +++ b/racket/src/racket/configure.ac @@ -50,7 +50,7 @@ m4_include(../ac/natipkg_arg.m4) AC_ARG_ENABLE(shared, [ --enable-shared create shared libraries (ok, but not recommended)]) AC_ARG_ENABLE(dynlib, [ --enable-dynlib same as --enable-shared]) AC_ARG_ENABLE(lt, [ --enable-lt= use instead of libtool; disable to use bundled], LIBTOOLPROG="$enableval", enable_lt=default) -AC_ARG_ENABLE(libs, [ --enable-libs install static libraries (enabled by default for Unix)]) +m4_include(../ac/instlib_arg.m4) AC_ARG_ENABLE(libffi, [ --enable-libffi use installed libffi (enabled by default for Unix)], , enable_libffi=default) @@ -231,8 +231,7 @@ show_explicitly_enabled "${enable_jitframe}" "jitframe" show_explicitly_enabled "${enable_noopt}" "No-optimization" "Note that this mode is intended only for debugging purposes" m4_include(../ac/strip_show.m4) -show_explicitly_enabled "${enable_libs}" "Installation of static libraries (if any)" -show_explicitly_disabled "${enable_libs}" "Installation of static libraries (if any)" +m4_include(../ac/instlib.m4) m4_include(../ac/sdk_show.m4) @@ -299,8 +298,6 @@ MAIN_VARIANT=3m INSTALL_SETUP_FLAGS= INSTALL_SETUP_RACKET_FLAGS= -INSTALL_LIBS_ENABLE=no-install - use_flag_pthread=yes use_flag_posix_pthread=no mzrt_needs_pthread=yes @@ -539,11 +536,6 @@ if test "${enable_jit}" = "yes" ; then check_for_mprotect=yes fi -if test "${enable_libs}" != "no" ; then - # Canceled for some platforms below: - INSTALL_LIBS_ENABLE=install -fi - ############## platform tests ################ # for flags we don't want to use in config tests: diff --git a/racket/src/worksp/csbuild.rkt b/racket/src/worksp/csbuild.rkt index 99a2af4fd5..f1ab20fa57 100644 --- a/racket/src/worksp/csbuild.rkt +++ b/racket/src/worksp/csbuild.rkt @@ -253,17 +253,20 @@ "petite" "scheme") -(system*! (find-exe) - "-O" "info@compiler/cm" - "-l-" "setup" boot-mode "../setup-go.rkt" "..//build/compiled" - "ignored" "../build/ignored.d" - "../cs/c/embed-boot.rkt" - "++exe" "../build/raw_racketcs.exe" (format "../../Racket~a.exe" cs-suffix) - "++exe" "../build/raw_gracketcs.exe" (format "../../lib/GRacket~a.exe" cs-suffix) - "../build/raw_libracketcs.dll" "../../lib/libracketcsxxxxxxx.dll" - "../build/petite-v.boot" - "../build/scheme-v.boot" - "../build/racket-v.boot") +(define (bootstrap-racket! . args) + (apply system*! (find-exe) + "-O" "info@compiler/cm" + "-l-" "setup" boot-mode "../setup-go.rkt" "../build/compiled" + "ignored" "../build/ignored.d" + args)) + +(bootstrap-racket! "../cs/c/embed-boot.rkt" + "++exe" "../build/raw_racketcs.exe" (format "../../Racket~a.exe" cs-suffix) + "++exe" "../build/raw_gracketcs.exe" (format "../../lib/GRacket~a.exe" cs-suffix) + "../build/raw_libracketcs.dll" "../../lib/libracketcsxxxxxxx.dll" + "../build/petite-v.boot" + "../build/scheme-v.boot" + "../build/racket-v.boot") (system*! "mt" "-manifest" "racket/racket.manifest" @@ -325,3 +328,15 @@ (format "../../lib/system~a.rktd" cs-suffix) machine "machine") + +(bootstrap-racket! "../cs/c/add-terminator.rkt" + "../build/petite-v.boot" + "../../lib/petite.boot") + +(bootstrap-racket! "../cs/c/add-terminator.rkt" + "../build/scheme-v.boot" + "../../lib/scheme.boot") + +(bootstrap-racket! "../cs/c/add-terminator.rkt" + "../build/racket-v.boot" + "../../lib/racket.boot")