Skip to content

Instantly share code, notes, and snippets.

@earl

earl/build.reb Secret

Last active August 25, 2022 15:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save earl/180d761ce5d27e411a6f to your computer and use it in GitHub Desktop.
Save earl/180d761ce5d27e411a6f to your computer and use it in GitHub Desktop.
A stand-alone Rebol 3 build script, for building Rebol 3 (only of the Ren/C flavour, for now). Save into `src/tools/build.reb` and run as `rebol3 src/tools/build.reb`.
REBOL [author: abolka date: 2015-07-22 tabs: none]
;; Current LAUNCH uses a broken system/options/boot (see CC#1892) to start
;; another process of the interpreter currently running. To give it a fighting
;; chance, we change to the working directory the user started the currently
;; running interpreter from. This should, primarily, improve things for when
;; the interpreter was started via a relative path (such as `./r3` or
;; `make/r3`).
change-dir system/options/path
;; Command-line arguments
args: protect/deep context [
project-dir: none
build-dir: none
target-id: none
quiet?: false
;; Due to a bug in Rebol's command-line argument parsing (CC#2227) the
;; common option syntax convention with hyphens (such as "-q" and
;; "--quiet") doesn't currently work reliably. As a workaround, we also
;; allow ancient-Windows-style option syntax ("/q" and "/quiet").
use [shortopt longopt unknown] [
shortopt: charset {-/}
longopt: [#"/" | "--"]
parse any [system/options/args []] [
any [
into [shortopt {b} end | longopt {build-dir} end]
set build-dir string!
(build-dir: to-file build-dir)
|
into [shortopt {p} end | longopt {project-dir} end]
set project-dir string!
(project-dir: to-file project-dir)
|
into [shortopt {q} end | longopt {quiet} end]
(quiet?: true)
|
into [shortopt {t} end | longopt {target-id} end]
set target-id string!
|
set unknown skip (
print rejoin [
{Unknown option: "} unknown {". Aborting.}
]
quit/return 1
)
]
]
]
;; Unless an explicit project root was provided, assume this script is
;; stored in src/tools/ relative to the desired project root.
if all [
none? project-dir
%{} = find/last/tail system/script/path %src/tools/
] [
project-dir: clean-path/dir system/script/path/(%../..)
]
unless project-dir [
print trim/lines {
Please either store this script in %src/tools/ in your Rebol
project tree or provide a `project-dir` command-line option.
}
quit/return 1
]
]
;; Local build environment configuration constants
build: protect/deep context [
project-dir: args/project-dir
source-dir: project-dir/(%src/)
include-dirs: reduce [
source-dir/(%include/)
source-dir/(%codecs/)
]
tool-dir: source-dir/(%tools/)
build-dir: dirize any [args/build-dir project-dir/(%make/)]
object-dir: build-dir/(%objs/)
exe-file: build-dir/(%r3)
commands: context [
cc: any [get-env {CC} %gcc] ;; TODO Split for argv, eg CC="ccache gcc"?
ld: any [get-env {LD} :cc]
]
]
;; Set up target-specific configuration constants
do build/tool-dir/(%common.r) ;; Needed by %systems.r
do build/tool-dir/(%systems.r)
config: config-system/guess args/target-id
files: context load build/tool-dir/(%file-base.r)
;; Local helpers
print-verbose: func [value [any-type!]] [
unless args/quiet? [
print :value
]
:value
]
to-def: func [word] [replace/all uppercase to-string word {-} {_}]
to-obj: func [src] [second split-path replace to-file src %.c %.o]
select-flags: func [
{Given a FLAGS object! (associating flag names with flag values), and a
NAMES block! of flag names, returns a block! of values associated with the
named flags. No value is retained for flags not found or associated with a
NONE! value.}
flags [object!]
names [block!]
] [
exclude map-each name names [select flags name] [#]
]
check-call: func [argv /local rc] [
if not zero? rc: call/wait print-verbose argv [
print [
{!!! BUILD FAILED!} newline
{--- Failed call: } newline
argv newline
{--- Exit code: } rc
]
quit/return rc
]
]
;; Target-specific overrides
target-defines: map-each def [os-base os-name] [join {-DTO_} to-def config/:def]
target-files: files/(to-word join {os-} config/os-base)
; TODO if flag? +SC [remove find target-files 'host-readline.c]
; TODO if flag? EXE [append build/exe-file %.exe]
;; BUILD!
print {=== Preparing build environment}
make-dir/deep build/object-dir
print {=== Cleaning build output}
foreach f read build/object-dir [
if %.o = suffix? f [
delete build/object-dir/:f
]
]
print {=== Generating code}
launch/wait build/tool-dir/(%make-headers.r)
launch/wait/args build/tool-dir/(%make-boot.r) mold config/id
launch/wait build/tool-dir/(%make-host-init.r)
launch/wait build/tool-dir/(%make-os-ext.r)
launch/wait build/tool-dir/(%core-ext.r)
launch/wait build/tool-dir/(%make-host-ext.r)
launch/wait build/tool-dir/(%make-reb-lib.r)
print {=== Compiling core}
core-flags: select-flags make compiler-flags [] config/build-flags
core-files: compose [(files/core)]
remove-each item core-files [item = '+] ;; Not strictly neceesary, atm.
foreach srcfile core-files [
check-call compose [
(build/commands/cc)
{-c}
(build/source-dir/(%core)/:srcfile)
(target-defines)
{-DREB_API}
(core-flags)
(map-each path build/include-dirs [join {-I} path])
{-o}
(build/object-dir/(to-obj srcfile))
]
]
print {=== Compiling host}
host-flags: select-flags make compiler-flags [PIC: NCM: none] config/build-flags
host-files: compose [(files/os) (target-files)]
remove-each item host-files [item = '+]
foreach srcfile host-files [
check-call compose [
(build/commands/cc)
{-c}
(build/source-dir/(%os)/:srcfile)
(target-defines)
{-DREB_EXE}
{-DREB_CORE}
(host-flags)
(compiler-flags/F64)
(map-each path build/include-dirs [join {-I} path])
{-o}
(build/object-dir/(to-obj srcfile))
]
]
print {=== Linking executable}
link-flags: select-flags make linker-flags [] config/build-flags
link-files: compose [(core-files) (host-files)]
check-call compose [
(build/commands/ld)
{-o}
(build/exe-file)
(map-each srcfile link-files [build/object-dir/(to-obj srcfile)])
(link-flags)
]
print {=== BUILD SUCCEEDED!}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment