Makefile.in 16.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13
######################################################################
# Residual auto-configuration
######################################################################

include config.mk
MKFILES := Makefile config.mk

ifneq ($(MAKE_RESTARTS),)
CFG_INFO := $(info cfg: make restarts: $(MAKE_RESTARTS))
endif

CFG_INFO := $(info cfg: building on $(CFG_OSTYPE) $(CFG_CPUTYPE))

14 15 16 17 18 19 20 21 22 23 24
CFG_GCC_CFLAGS :=
CFG_GCC_LINK_FLAGS :=
CFG_BOOT_FLAGS := $(BOOT_FLAGS)
CFG_RUSTC_FLAGS := -nowarn

# On Darwin, we need to run dsymutil so the debugging information ends
# up in the right place.  On other platforms, it automatically gets
# embedded into the executable, so use a no-op command.
CFG_DSYMUTIL := true

ifeq ($(CFG_OSTYPE), FreeBSD)
25
  CFG_LIB_NAME=lib$(1).so
26 27 28 29 30 31 32 33 34 35
  CFG_GCC_CFLAGS += -fPIC -march=i686 -I/usr/local/include
  CFG_GCC_LINK_FLAGS += -shared -fPIC -lpthread -lrt
  ifeq ($(CFG_CPUTYPE), x86_64)
    CFG_GCC_CFLAGS += -m32
    CFG_GCC_LINK_FLAGS += -m32
  endif
  CFG_UNIXY := 1
endif

ifeq ($(CFG_OSTYPE), Linux)
36
  CFG_LIB_NAME=lib$(1).so
37 38 39 40 41 42 43 44 45 46
  CFG_GCC_CFLAGS += -fPIC -march=i686
  CFG_GCC_LINK_FLAGS += -shared -fPIC -ldl -lpthread -lrt
  ifeq ($(CFG_CPUTYPE), x86_64)
    CFG_GCC_CFLAGS += -m32
    CFG_GCC_LINK_FLAGS += -m32
  endif
  CFG_UNIXY := 1
endif

ifeq ($(CFG_OSTYPE), Darwin)
47
  CFG_LIB_NAME=lib$(1).dylib
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
  CFG_UNIXY := 1
  CFG_GCC_LINK_FLAGS += -dynamiclib -lpthread
  # Darwin has a very blurry notion of "64 bit", and claims it's running
  # "on an i386" when the whole userspace is 64-bit and the compiler
  # emits 64-bit binaries by default. So we just force -m32 here. Smarter
  # approaches welcome!
  CFG_GCC_CFLAGS += -m32
  CFG_GCC_LINK_FLAGS += -m32
  CFG_DSYMUTIL := dsymutil
endif

ifneq ($(findstring MINGW,$(CFG_OSTYPE)),)
  CFG_WINDOWSY := 1
endif

63 64 65
CFG_LDPATH :=$(CFG_BUILD_DIR)/rt
CFG_LDPATH :=$(CFG_LDPATH):$(CFG_BUILD_DIR)/llvmext

66 67 68 69 70
ifdef CFG_WINDOWSY
  CFG_INFO := $(info cfg: windows-y environment)

  CFG_EXE_SUFFIX := .exe
  CFG_LIB_NAME=$(1).dll
71 72
  CFG_LDPATH :=$(CFG_LDPATH):$(CFG_LLVM_BINDIR)
  CFG_LDPATH :=$(CFG_LDPATH):$$PATH
73
  CFG_RUN_TARG=PATH=$(CFG_LDPATH) $(1)
74

75 76 77
  CFG_PATH_MUNGE := $(strip | perl -p                  \
                           -e 's@\\(.)@/\1@go;'        \
                           -e 's@^/([a-zA-Z])/@\1:/@o;')
78 79 80 81 82 83 84 85 86 87 88
  ifdef CFG_FLEXLINK
    CFG_BOOT_NATIVE := 1
  endif
  CFG_GCC_CFLAGS += -march=i686
  CFG_GCC_LINK_FLAGS += -shared -fPIC
endif

ifdef CFG_UNIXY
  CFG_INFO := $(info cfg: unix-y environment)

  CFG_EXE_SUFFIX :=
89
  CFG_LDPATH :=$(CFG_LDPATH):$(CFG_LLVM_LIBDIR)
90
  CFG_RUN_TARG=\
91
      LD_LIBRARY_PATH=$(dir $(1)):$(CFG_LDPATH) $(CFG_VALGRIND) $(1)
92 93 94 95 96 97

  CFG_BOOT_NATIVE := 1

  ifdef MINGW_CROSS
    CFG_EXE_SUFFIX := .exe
    CFG_LIB_NAME=$(1).dll
98 99
    CFG_LDPATH :=$(CFG_LDPATH):$(CFG_LLVM_BINDIR)
    CFG_LDPATH :=$(CFG_LDPATH):$$PATH
100
    CFG_RUN_TARG=PATH=$(CFG_LDPATH) $(1)
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118

    CFG_INFO := $(info cfg: mingw-cross)
    CFG_GCC_CROSS := i586-mingw32msvc-
    CFG_BOOT_FLAGS += -t win32-x86-pe
    ifdef CFG_VALGRIND
      CFG_VALGRIND += wine
    endif
    CFG_GCC_CFLAGS := -march=i686
    CFG_GCC_LINK_FLAGS := -shared
    ifeq ($(CFG_CPUTYPE), x86_64)
      CFG_GCC_CFLAGS += -m32
      CFG_GCC_LINK_FLAGS += -m32
    endif
  endif
  ifdef CFG_VALGRIND
    CFG_VALGRIND += --leak-check=full \
                    --error-exitcode=1 \
                    --quiet --vex-iropt-level=0 \
G
Graydon Hoare 已提交
119
                    --suppressions=$(S)src/etc/x86.supp
120 121 122 123 124 125 126
  endif
endif

CFG_RUNTIME :=$(call CFG_LIB_NAME,rustrt)
CFG_LLVMEXT :=$(call CFG_LIB_NAME,llvmext)
CFG_STDLIB :=$(call CFG_LIB_NAME,std)

G
Graydon Hoare 已提交
127 128
CFG_LLC_CFLAGS := -march=x86

129 130 131 132 133 134 135 136 137 138 139
ifdef CFG_GCC
  CFG_INFO := $(info cfg: using gcc)
  CFG_GCC_CFLAGS += -Wall -Werror -fno-rtti -fno-exceptions -g
  CFG_GCC_LINK_FLAGS += -g
  CFG_COMPILE_C = $(CFG_GCC_CROSS)g++ $(CFG_GCC_CFLAGS) -c -o $(1) $(2)
  CFG_LINK_C = $(CFG_GCC_CROSS)g++ $(CFG_GCC_LINK_FLAGS) -o $(1)
  CFG_DEPEND_C = $(CFG_GCC_CROSS)g++ $(CFG_GCC_CFLAGS) -MT "$(1)" -MM $(2)
else
  CFG_ERR := $(error please try on a system with gcc)
endif

140
ifdef CFG_OCAMLC_OPT
141
  $(info cfg: have ocaml native compiler)
142 143
  OPT=.opt
else
144
  $(info cfg: have only ocaml bytecode compiler)
145 146
endif

147 148 149
ifdef BOOT_PROFILE
  $(info cfg: forcing native bootstrap compiler (BOOT_PROFILE))
  CFG_BOOT_NATIVE := 1
150 151 152
  CFG_OCAMLOPT_PROFILE_FLAGS := -p
endif

153 154 155
ifdef BOOT_DEBUG
  $(info cfg: forcing bytecode bootstrap compiler (DEBUG))
  CFG_BOOT_NATIVE :=
156 157
endif

158
ifdef CFG_BOOT_NATIVE
159 160 161 162 163 164
  $(info cfg: building native bootstrap compiler)
else
  $(info cfg: building bytecode bootstrap compiler)
endif

ifdef NO_VALGRIND
165 166 167 168 169 170 171 172 173 174 175 176 177 178
  $(info cfg: disabling valgrind (NO_VALGRIND))
  CFG_VALGRIND :=
endif

######################################################################
# Target-and-rule "utility variables"
######################################################################

ifdef VERBOSE
  Q :=
  E =
else
  Q := @
  E = echo $(1)
179 180
endif

181
R := $(CFG_RUN_TARG)
182 183 184 185 186 187 188
S := $(CFG_SRC_DIR)
X := $(CFG_EXE_SUFFIX)

# Look in doc and src dirs.
VPATH := $(S)doc $(S)src

# Compilers we build, we now know how to run.
189
BOOT := $(Q)OCAMLRUNPARAM="b1" boot/rustboot$(X) $(CFG_BOOT_FLAGS) -L stage0
190 191
STAGE0 := $(Q)$(CFG_RUN_TARG) stage0/rustc$(X) $(CFG_RUSTC_FLAGS) -L stage1
STAGE1 := $(Q)$(CFG_RUN_TARG) stage1/rustc$(X) $(CFG_RUSTC_FLAGS) -L stage2
192 193 194 195 196 197 198 199 200 201 202

# "Source" files we generate in builddir along the way.
GENERATED := boot/fe/lexer.ml boot/version.ml

# Delete the built-in rules.
.SUFFIXES:
%:: %,v
%:: RCS/%,v
%:: RCS/%
%:: s.%
%:: SCCS/s.%
203 204 205 206 207 208 209 210 211 212

######################################################################
# Bootstrap compiler variables
######################################################################

# We must list them in link order.
# Nobody calculates the link-order DAG automatically, sadly.

BOOT_MLS :=                                              \
    $(addsuffix .ml,                                     \
213 214
        boot/version                                     \
        $(addprefix boot/util/, fmt common bits)         \
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
        $(addprefix boot/driver/, session)               \
        $(addprefix boot/fe/, ast token lexer parser     \
          extfmt pexp item cexp fuzz)                    \
        $(addprefix boot/be/, asm il abi)                \
        $(addprefix boot/me/, walk semant resolve alias  \
          simplify type dead layer effect typestate      \
         loop layout transutil trans dwarf)              \
        $(addprefix boot/be/, x86 ra pe elf macho)       \
        $(addprefix boot/driver/, lib glue main))        \

BOOT_CMOS := $(BOOT_MLS:.ml=.cmo)
BOOT_CMXS := $(BOOT_MLS:.ml=.cmx)
BOOT_OBJS := $(BOOT_MLS:.ml=.o)
BOOT_CMIS := $(BOOT_MLS:.ml=.cmi)

230
BS := $(S)src/boot/
231 232 233 234 235 236 237 238

BOOT_ML_DEP_INCS := -I $(BS)/fe   -I $(BS)/me      \
                    -I $(BS)/be   -I $(BS)/driver  \
                    -I $(BS)/util -I boot

BOOT_ML_INCS    :=  -I boot/fe   -I boot/me      \
                    -I boot/be   -I boot/driver  \
                    -I boot/util -I boot
239

240 241 242
BOOT_ML_LIBS        := unix.cma  nums.cma  bigarray.cma
BOOT_ML_NATIVE_LIBS := unix.cmxa nums.cmxa bigarray.cmxa
BOOT_OCAMLC_FLAGS   := -g $(BOOT_ML_INCS) -w Ael -warn-error Ael
243 244 245 246 247
BOOT_OCAMLOPT_FLAGS := -g $(BOOT_ML_INCS) -w Ael -warn-error Ael

######################################################################
# Runtime (C++) library variables
######################################################################
248

249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308
RUNTIME_CS := rt/sync/timer.cpp \
              rt/sync/sync.cpp \
              rt/sync/lock_and_signal.cpp \
              rt/rust.cpp \
              rt/rust_builtin.cpp \
              rt/rust_run_program.cpp \
              rt/rust_crate.cpp \
              rt/rust_crate_cache.cpp \
              rt/rust_crate_reader.cpp \
              rt/rust_comm.cpp \
              rt/rust_dom.cpp \
              rt/rust_task.cpp \
              rt/rust_task_list.cpp \
              rt/rust_proxy.cpp \
              rt/rust_chan.cpp \
              rt/rust_port.cpp \
              rt/rust_upcall.cpp \
              rt/rust_log.cpp \
              rt/rust_message.cpp \
              rt/rust_timer.cpp \
              rt/circular_buffer.cpp \
              rt/isaac/randport.cpp \
              rt/rust_srv.cpp \
              rt/rust_kernel.cpp \
              rt/memory_region.cpp \
              rt/test/rust_test_harness.cpp \
              rt/test/rust_test_runtime.cpp \
              rt/test/rust_test_util.cpp

RUNTIME_HDR := rt/globals.h \
               rt/rust.h \
               rt/rust_dwarf.h \
               rt/rust_internal.h \
               rt/rust_util.h \
               rt/rust_chan.h \
               rt/rust_port.h \
               rt/rust_dom.h \
               rt/rust_task.h \
               rt/rust_task_list.h \
               rt/rust_proxy.h \
               rt/rust_log.h \
               rt/rust_message.h \
               rt/circular_buffer.h \
               rt/util/array_list.h \
               rt/util/indexed_list.h \
               rt/util/synchronized_indexed_list.h \
               rt/util/hash_map.h \
               rt/sync/sync.h \
               rt/sync/timer.h \
               rt/sync/lock_free_queue.h \
               rt/rust_srv.h \
               rt/rust_kernel.h \
               rt/memory_region.h \
               rt/memory.h \
               rt/test/rust_test_harness.h \
               rt/test/rust_test_runtime.h \
               rt/test/rust_test_util.h

RUNTIME_INCS := -I $(S)src/rt/isaac -I $(S)src/rt/uthash
RUNTIME_OBJS := $(RUNTIME_CS:.cpp=.o)
309 310

######################################################################
311
# rustc LLVM-extensions (C++) library variables
312 313
######################################################################

314 315
LLVMEXT_CS := $(addprefix llvmext/, \
                MachOObjectFile.cpp Object.cpp RustWrapper.cpp)
316

317
LLVMEXT_HDR := llvmext/include/llvm-c/Object.h
318

319
LLVMEXT_INCS := -iquote $(CFG_LLVM_INCDIR) \
320
                -iquote $(S)src/llvmext/include
321 322
LLVMEXT_OBJS := $(LLVMEXT_CS:.cpp=.o)
LLVMEXT_LIBS := $(CFG_LLVM_LDFLAGS) $(CFG_LLVM_LIBS)
323

324 325 326 327 328 329
######################################################################
# Standard library variables
######################################################################

STDLIB_CRATE := lib/std.rc
STDLIB_INPUTS := $(wildcard $(addprefix $(S)src/lib/,*.rc *.rs */*.rs))
330 331

######################################################################
332
# rustc crate variables
333 334
######################################################################

335
COMPILER_CRATE := comp/rustc.rc
336
COMPILER_INPUTS := $(wildcard $(addprefix $(S)src/comp/, \
337 338
                                rustc.rc *.rs */*.rs))

339 340 341 342 343 344 345 346 347
######################################################################
# test dependency variables
######################################################################

LREQ := rt/$(CFG_RUNTIME) llvmext/$(CFG_LLVMEXT)
BREQ := boot/rustboot$(X) boot/$(CFG_STDLIB)
SREQ0 := stage0/rustc$(X) $(LREQ)
SREQ1 := stage1/rustc$(X) $(LREQ)

348 349 350
######################################################################
# Single-target rules
######################################################################
351

352
all: boot/rustboot$(X)          \
353
     boot/$(CFG_STDLIB)         \
354 355 356
     rt/$(CFG_RUNTIME)          \
     llvmext/$(CFG_LLVMEXT)     \
     stage0/rustc$(X)           \
G
Graydon Hoare 已提交
357
     stage0/glue.o              \
358
     stage0/$(CFG_STDLIB)       \
359
     $(GENERATED)
360 361 362 363 364 365 366 367 368 369 370

rt/$(CFG_RUNTIME): $(RUNTIME_OBJS) $(MKFILES) $(RUNTIME_HDR)
	@$(call E, link: $@)
	$(Q)$(call CFG_LINK_C, $@) $(RUNTIME_OBJS)

llvmext/$(CFG_LLVMEXT): $(LLVMEXT_OBJS) $(MKFILES) $(LLVMEXT_HDR)
	@$(call E, link: $@)
	$(Q)$(call CFG_LINK_C, $@ $(LLVMEXT_OBJS) \
        $(CFG_LLVM_LIBS) $(CFG_LLVM_LDFLAGS))

ifdef CFG_BOOT_NATIVE
371
boot/rustboot$(X): $(BOOT_CMXS) $(MKFILES)
372 373
	@$(call E, link: $@)
	$(Q)ocamlopt$(OPT) -o $@ $(BOOT_OCAMLOPT_FLAGS) $(BOOT_ML_NATIVE_LIBS) \
374 375
        $(BOOT_CMXS)
else
376
boot/rustboot$(X): $(BOOT_CMOS) $(MKFILES)
377
	@$(call E, link: $@)
378
	$(Q)ocamlc$(OPT) -o $@ $(BOOT_OCAMLC_FLAGS) $(BOOT_ML_LIBS) $(BOOT_CMOS)
379 380
endif

381 382
boot/version.ml: $(MKFILES)
	@$(call E, git: $@)
383 384 385
	$(Q)git log -1 \
      --pretty=format:'let version = "prerelease (%h %ci)";;' >$@ || exit 1

G
Graydon Hoare 已提交
386

387 388
boot/$(CFG_STDLIB): $(S)src/$(STDLIB_CRATE) $(STDLIB_INPUTS) \
                    boot/rustboot$(X) $(MKFILES)
389 390 391
	@$(call E, compile: $@)
	$(BOOT) -shared -o $@ $<

392
stage0/$(CFG_STDLIB): $(S)src/$(STDLIB_CRATE) $(STDLIB_INPUTS) \
G
Graydon Hoare 已提交
393 394 395 396 397
                      stage0/rustc$(X) $(MKFILES)
	@$(call E, compile: $@)
	$(STAGE0) -shared -o $@ $<


398
stage0/rustc$(X): $(S)src/$(COMPILER_CRATE) $(COMPILER_INPUTS) \
399
                  $(BREQ)
400 401 402 403
	@$(call E, compile: $@)
	$(BOOT) -minimal -o $@ $<
	$(Q)chmod 0755 $@

G
Graydon Hoare 已提交
404
stage1/rustc$(X): $(S)src/$(COMPILER_CRATE) $(COMPILER_INPUTS) \
405
                  $(SREQ0) stage0/$(CFG_STDLIB)
G
Graydon Hoare 已提交
406 407 408 409 410
	@$(call E, compile: $@)
	$(STAGE0) -o $@ $<
	$(Q)chmod 0755 $@


G
Graydon Hoare 已提交
411 412
stage0/glue.bc: stage0/rustc$(X) stage0/$(CFG_STDLIB) \
                llvmext/$(CFG_LLVMEXT) rt/$(CFG_RUNTIME)
413 414
	@$(call E, generate: $@)
	$(STAGE0) -o $@ -glue
415

G
Graydon Hoare 已提交
416 417 418 419 420
stage1/glue.bc: stage1/rustc$(X) stage1/$(CFG_STDLIB) \
                llvmext/$(CFG_LLVMEXT) rt/$(CFG_RUNTIME)
	@$(call E, generate: $@)
	$(STAGE1) -o $@ -glue

421
######################################################################
422
# Library and boot rules
423 424 425 426 427 428 429 430
######################################################################

rt/%.o: rt/%.cpp $(MKFILES)
	@$(call E, compile: $@)
	$(Q)$(call CFG_COMPILE_C, $@, $(RUNTIME_INCS)) $<

llvmext/%.o: llvmext/%.cpp $(MKFILES)
	@$(call E, compile: $@)
431
	$(Q)$(call CFG_COMPILE_C, $@, $(CFG_LLVM_CXXFLAGS) $(LLVMEXT_INCS)) $<
432

433 434
%.cmo: %.ml $(MKFILES)
	@$(call E, compile: $@)
435
	$(Q)ocamlc$(OPT) -c -o $@ $(BOOT_OCAMLC_FLAGS) $<
436 437

%.cmo: %.cmi $(MKFILES)
438

439 440 441 442 443 444 445
%.cmx %.o: %.ml $(MKFILES)
	@$(call E, compile: $@)
	$(Q)ocamlopt$(OPT) -c -o $@ $(BOOT_OCAMLOPT_FLAGS) $<

%.ml: %.mll $(MKFILES)
	@$(call E, lex-gen: $@)
	$(Q)ocamllex$(OPT) -q -o $@ $<
446

447 448 449 450 451 452 453 454 455 456 457 458 459

######################################################################
# Testing rules
######################################################################

%.boot$(X): %.rs $(BREQ)
	@$(call E, compile [boot]: $@)
	$(BOOT) -o $@ $<

%.boot$(X): %.rc $(BREQ)
	@$(call E, compile [boot]: $@)
	$(BOOT) -o $@ $<

460
%.stage0$(X): %.stage0.o rt/$(CFG_RUNTIME) stage0/glue.o
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475
	@$(call E, link [llvm]: $@)
	$(Q)gcc $(CFG_GCC_CFLAGS) stage0/glue.o -o $@ $< -Lstage0 -lrustrt
	@# dsymutil sometimes fails or prints a warning, but the
	@# program still runs.  Since it simplifies debugging other
	@# programs, I\'ll live with the noise.
	-$(Q)$(DSYMUTIL) $@

%.stage0.bc: %.rc $(SREQ0)
	@$(call E, compile [stage0]: $@)
	$(STAGE0) -o $@ $<

%.stage0.bc: %.rs $(SREQ0)
	@$(call E, compile [stage0]: $@)
	$(STAGE0) -o $@ $<

G
Graydon Hoare 已提交
476 477 478 479 480 481 482 483 484 485 486 487
%.o: %.s
	@$(call E, assemble [llvm]: $@)
	$(Q)gcc $(CFG_GCC_CFLAGS) -o $@ -c $<

%.ll: %.bc
	@$(call E, dis [llvm]: $@)
	$(Q)$(CFG_LLVM_BINDIR)/llvm-dis -o $@ $<

%.s: %.bc
	@$(call E, compile [llvm]: $@)
	$(Q)$(CFG_LLVM_BINDIR)/llc $(CFG_LLC_CFLAGS) -o $@ $<

488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538
# Cancel the implicit .out rule in GNU make.
%.out: %

%.out: %.out.tmp
	$(Q)mv $< $@

test/run-pass/%.out.tmp: test/run-pass/%$(CFG_EXE_SUFFIX) rt/$(CFG_RUNTIME)
	$(Q)rm -f $<.tmp
	@$(call E, run: $@)
	$(Q)$(call CFG_RUN_TARG, $<) > $@

test/bench/shootout/%.out.tmp: test/bench/shootout/%$(X) \
                               rt/$(CFG_RUNTIME)
	$(Q)rm -f $<.tmp
	@$(call E, run: $@)
	$(Q)$(call CFG_RUN_TARG, $<) > $@

test/bench/99-bottles/%.out.tmp: test/bench/99-bottles/%$(X) \
                                 rt/$(CFG_RUNTIME)
	$(Q)rm -f $<.tmp
	@$(call E, run: $@)
	$(Q)$(call CFG_RUN_TARG, $<) > $@

test/run-fail/%.out.tmp: test/run-fail/%$(X) \
                         rt/$(CFG_RUNTIME)
	$(Q)rm -f $<.tmp
	@$(call E, run: $@)
	$(Q)grep -q error-pattern $(S)src/test/run-fail/$(basename $*).rs
	$(Q)rm -f $@
	$(Q)$(call CFG_RUN_TARG, $<) >$@ 2>&1 ; X=$$? ; \
      if [ $$X -eq 0 ] ; then exit 1 ; else exit 0 ; fi
	$(Q)grep --text --quiet \
      "$$(grep error-pattern $(S)src/test/run-fail/$(basename $*).rs \
        | cut -d : -f 2- | tr -d '\n\r')" $@

test/compile-fail/%.boot.out.tmp: test/compile-fail/%.rs $(BREQ)
	@$(call E, compile [boot]: $@)
	$(Q)grep -q error-pattern $<
	$(Q)rm -f $@
	$(BOOT) -o $(@:.out=$(X)) $< >$@ 2>&1; test $$? -ne 0
	$(Q)grep --text --quiet \
      "$$(grep error-pattern $< | cut -d : -f 2- | tr -d '\n\r')" $@

test/compile-fail/%.stage0.out.tmp: test/compile-fail/%.rs $(SREQ0)
	@$(call E, compile [stage0]: $@)
	$(Q)grep -q error-pattern $<
	$(Q)rm -f $@
	$(STAGE0) -o $(@:.out=$(X)) $< >$@ 2>&1; test $$? -ne 0
	$(Q)grep --text --quiet \
      "$$(grep error-pattern $< | cut -d : -f 2- | tr -d '\n\r')" $@

539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556

######################################################################
# Cleanup
######################################################################

.PHONY: clean

clean:
	@$(call E, cleaning)
	$(Q)rm -f $(foreach ext, cmx cmi cmo cma bc o a d $(X)     \
                             h cpp ml s                        \
                             out bc dSYM                       \
                             ,                                 \
                  $(wildcard     *.$(ext)                      \
                               */*.$(ext)                      \
                             */*/*.$(ext)                      \
                           */*/*/*.$(ext)                      \
                   ))