diff --git a/.gitignore b/.gitignore index 0471c9b2..a422a329 100644 --- a/.gitignore +++ b/.gitignore @@ -1,19 +1,12 @@ -# Intermediate files directory. +# Build outputs. +bin/ +lib/ +wren + +# Intermediate files. build/ .sass-cache/ -# Built files at the top level. -wren -wrend -wren-cpp -libwren.a -libwrend.a -libwren.so -libwrend.so -libwren.dylib -libwrend.dylib -libwren-cpp.a - # XCode user-specific stuff. xcuserdata/ *.xccheckout diff --git a/Makefile b/Makefile index 01de1ab8..dd210eb5 100644 --- a/Makefile +++ b/Makefile @@ -1,124 +1,56 @@ -AR := ar rcu -# Compiler flags. -CFLAGS := -std=c99 -Wall -Werror -# TODO: Add -Wextra. -CPPFLAGS := -std=c++98 -Wall -Werror -DEBUG_CFLAGS := -O0 -DDEBUG -g -RELEASE_CFLAGS := -Os +# Top-level Makefile. This has targets for various utility things. To actually +# compile Wren itself, it invokes script/wren.mk for the various configurations +# that Wren can be built with. -# Detect the OS. -TARGET_OS := $(lastword $(subst -, ,$(shell $(CC) -dumpmachine))) +# Executables are built to bin/. Libraries are built to lib/. -# Don't add -fPIC on Windows since it generates a warning which gets promoted -# to an error by -Werror. -ifeq ($(TARGET_OS),mingw32) -else ifeq ($(TARGET_OS),cygwin) - # Do nothing. -else - CFLAGS += -fPIC - CPPFLAGS += -fPIC -endif +# A normal, optimized release build for the current CPU architecture. +release: + @ $(MAKE) -f script/wren.mk + @ cp bin/wren wren # For convenience, copy the interpreter to the top level. -# Clang on Mac OS X has different flags and a different extension to build a -# shared library. -ifneq (,$(findstring darwin,$(TARGET_OS))) - SHARED_LIB_FLAGS = - SHARED_EXT = dylib -else - SHARED_LIB_FLAGS = -Wl,-soname,$@.so - SHARED_EXT = so -endif +# A debug build for the current architecture. +debug: + @ $(MAKE) -f script/wren.mk MODE=debug -# Files. -SOURCES := $(wildcard src/*.c) -HEADERS := $(wildcard src/*.h) -OBJECTS := $(SOURCES:.c=.o) - -# Don't include main.c in the libraries. -DEBUG_OBJECTS := $(addprefix build/debug/, $(notdir $(OBJECTS))) -RELEASE_OBJECTS := $(addprefix build/release/, $(notdir $(OBJECTS))) -RELEASE_CPP_OBJECTS := $(addprefix build/release-cpp/, $(notdir $(OBJECTS))) - -DEBUG_LIB_OBJECTS := $(subst build/debug/main.o,,$(DEBUG_OBJECTS)) -RELEASE_LIB_OBJECTS := $(subst build/release/main.o,,$(RELEASE_OBJECTS)) -RELEASE_CPP_LIB_OBJECTS := $(subst build/release-cpp/main.o,,$(RELEASE_CPP_OBJECTS)) - -.PHONY: all clean test builtin docs watchdocs prep - -all: release +# Build all configurations. +all: debug release + @ $(MAKE) -f script/wren.mk LANG=cpp + @ $(MAKE) -f script/wren.mk MODE=debug LANG=cpp + @ $(MAKE) -f script/wren.mk ARCH=32 + @ $(MAKE) -f script/wren.mk LANG=cpp ARCH=32 + @ $(MAKE) -f script/wren.mk MODE=debug ARCH=32 + @ $(MAKE) -f script/wren.mk MODE=debug LANG=cpp ARCH=32 + @ $(MAKE) -f script/wren.mk ARCH=64 + @ $(MAKE) -f script/wren.mk LANG=cpp ARCH=64 + @ $(MAKE) -f script/wren.mk MODE=debug ARCH=64 + @ $(MAKE) -f script/wren.mk MODE=debug LANG=cpp ARCH=64 +# Remove all build outputs and intermediate files. clean: - @rm -rf build - @rm -rf wren libwren.a libwren.so libwren.dylib - @rm -rf wrend libwrend.a libwrend.so libwrend.dylib - -prep: - @mkdir -p build/debug build/release build/release-cpp - -# Debug build. -debug: prep wrend libwrend - -# Debug static and shared libraries. -libwrend: $(DEBUG_LIB_OBJECTS) - $(AR) $@.a $^ - $(CC) $(DEBUG_CFLAGS) -shared $(SHARED_LIB_FLAGS) -o $@.$(SHARED_EXT) $^ - -# Debug command-line interpreter. -wrend: $(DEBUG_OBJECTS) - $(CC) $(CFLAGS) $(DEBUG_CFLAGS) -Iinclude -o $@ $^ -lm - -# Debug object files. -build/debug/%.o: src/%.c include/wren.h $(HEADERS) - $(CC) -c $(CFLAGS) $(DEBUG_CFLAGS) -Iinclude -o $@ $< - -# Release build. -release: prep wren libwren - -# Release static and shared libraries. -libwren: $(RELEASE_LIB_OBJECTS) - $(AR) $@.a $^ - $(CC) $(RELEASE_CFLAGS) -shared $(SHARED_LIB_FLAGS) -o $@.$(SHARED_EXT) $^ - -# Release command-line interpreter. -wren: $(RELEASE_OBJECTS) - $(CC) $(CFLAGS) $(RELEASE_CFLAGS) -Iinclude -o $@ $^ -lm - -# Release object files. -build/release/%.o: src/%.c include/wren.h $(HEADERS) - $(CC) -c $(CFLAGS) $(RELEASE_CFLAGS) -Iinclude -o $@ $< - -# Release C++ build. -release-cpp: prep wren-cpp libwren-cpp - -# Release C++ static library. -libwren-cpp: $(RELEASE_CPP_LIB_OBJECTS) - $(AR) $@.a $^ - -# Release C++ command-line interpreter. -wren-cpp: $(RELEASE_CPP_OBJECTS) - $(CC) $(CPPFLAGS) $(RELEASE_CFLAGS) -Iinclude -o $@ $^ -lm - -# Release C++ object files. -build/release-cpp/%.o: src/%.c include/wren.h $(HEADERS) - $(CC) -c $(CPPFLAGS) $(RELEASE_CFLAGS) -Iinclude -o $@ -x c++ $< + @ rm -rf bin + @ rm -rf build + @ rm -rf lib # Run the tests against the debug build of Wren. test: debug - @./script/test.py $(suite) + @ ./script/test.py $(suite) # Take the contents of the scripts under builtin/ and copy them into their # respective wren_.c source files. builtin: - @./script/generate_builtins.py + @ ./script/generate_builtins.py # Generate the Wren site. docs: - @./script/generate_docs.py + @ ./script/generate_docs.py # Continuously generate the Wren site. watchdocs: - @./script/generate_docs.py --watch + @ ./script/generate_docs.py --watch # Build the docs and copy them to a local "gh-pages" directory. gh-pages: docs - cp -r build/docs/. gh-pages + @ cp -r build/docs/. gh-pages + +.PHONY: debug release all clean test builtin docs watchdocs gh-pages diff --git a/doc/site/getting-started.markdown b/doc/site/getting-started.markdown index dc9fcc04..42e20bce 100644 --- a/doc/site/getting-started.markdown +++ b/doc/site/getting-started.markdown @@ -10,6 +10,9 @@ Mac and you can rock a command line, it's just: $ make $ ./wren +Binaries for other configurations are built to `bin/`. Static and shared +libraries for embedding Wren get built in `lib/`. + For Mac users, there is also an XCode project under `project/xcode`. For Windows brethren, `project/msvc2013` contains a Visual Studio solution. Note that these may not have the exact same build settings as the makefile. The diff --git a/script/wren.mk b/script/wren.mk new file mode 100644 index 00000000..ef77e2ad --- /dev/null +++ b/script/wren.mk @@ -0,0 +1,108 @@ +# Makefile for building a single configuration of Wren. It allows the +# following variables to be passed to it: +# +# MODE - The build mode, "debug" or "release". +# If omitted, defaults to "release". +# LANG - The language, "c" or "cpp". +# If omitted, defaults to "c". +# ARCH - The processor architecture, "32", "64", or nothing, which indicates +# the compiler's default. +# If omitted, defaults to the compiler's default. +# +# It builds a static library, shared library, and command-line interpreter for +# the given configuration. Libraries are built to "lib", and the interpreter +# is built to "bin". +# +# The output file is initially "wren". If in debug mode, "d" is appended to it. +# If the language is "cpp", then "-cpp" is appended to that. If the +# architecture is not the default then "-32" or "-64" is appended to that. +# Then, for the libraries, the correct extension is added. + +# Files. +HEADERS := include/wren.h $(wildcard src/*.h) +SOURCES := $(wildcard src/*.c) +BUILD_DIR := build + +CFLAGS := -Wall -Werror +# TODO: Add -Wextra. + +# Mode configuration. +ifeq ($(MODE),debug) + WREN := wrend + CFLAGS += -O0 -DDEBUG -g + BUILD_DIR := $(BUILD_DIR)/debug +else + WREN += wren + CFLAGS += -Os + BUILD_DIR := $(BUILD_DIR)/release +endif + +# Language configuration. +ifeq ($(LANG),cpp) + WREN := $(WREN)-cpp + CFLAGS += -std=c++98 + FILE_FLAG := -x c++ + BUILD_DIR := $(BUILD_DIR)-cpp +else + CFLAGS += -std=c99 +endif + +# Architecture configuration. +ifeq ($(ARCH),32) + CFLAGS += -m32 + WREN := $(WREN)-32 + BUILD_DIR := $(BUILD_DIR)-32 +endif + +ifeq ($(ARCH),64) + CFLAGS += -m64 + WREN := $(WREN)-64 + BUILD_DIR := $(BUILD_DIR)-64 +endif + +# Don't add -fPIC on Windows since it generates a warning which gets promoted +# to an error by -Werror. +OS := $(lastword $(subst -, ,$(shell $(CC) -dumpmachine))) +ifeq ($(OS),mingw32) +else ifeq ($(OS),cygwin) + # Do nothing. +else + CFLAGS += -fPIC +endif + +# Clang on Mac OS X has different flags and a different extension to build a +# shared library. +ifneq (,$(findstring darwin,$(OS))) + SHARED_EXT := dylib +else + SHARED_LIB_FLAGS := -Wl,-soname,$@.so + SHARED_EXT := so +endif + +# TODO: Simplify this if we mode main.c to a different directory. +OBJECTS := $(addprefix $(BUILD_DIR)/, $(notdir $(SOURCES:.c=.o))) +# Don't include main.c in the libraries. +LIB_OBJECTS := $(subst $(BUILD_DIR)/main.o,,$(OBJECTS)) + +# Targets --------------------------------------------------------------------- + +all: prep bin/$(WREN) lib/lib$(WREN).a lib/lib$(WREN).$(SHARED_EXT) + +prep: + @mkdir -p bin lib $(BUILD_DIR) + +# Command-line interpreter. +bin/$(WREN): $(OBJECTS) + $(CC) $(CFLAGS) -Iinclude -o $@ $^ -lm + +# Static library. +lib/lib$(WREN).a: $(LIB_OBJECTS) + $(AR) rcu $@ $^ + +# Shared library. +lib/lib$(WREN).$(SHARED_EXT): $(LIB_OBJECTS) + $(CC) $(CFLAGS) -shared $(SHARED_LIB_FLAGS) -o $@ $^ + +# Object files. +$(BUILD_DIR)/%.o: src/%.c $(HEADERS) + $(CC) -c $(CFLAGS) -Iinclude -o $@ $(FILE_FLAG) $< diff --git a/src/main.c b/src/main.c index 4f6e5de6..db80902e 100644 --- a/src/main.c +++ b/src/main.c @@ -56,7 +56,7 @@ static char* readModule(WrenVM* vm, const char* module) size_t rootLength = strlen(rootDirectory); size_t moduleLength = strlen(module); size_t pathLength = rootLength + moduleLength + 5; - char* path = malloc(pathLength + 1); + char* path = (char*)malloc(pathLength + 1); memcpy(path, rootDirectory, rootLength); memcpy(path + rootLength, module, moduleLength); memcpy(path + rootLength + moduleLength, ".wren", 5); @@ -107,7 +107,7 @@ static int runFile(WrenVM* vm, const char* path) // Use the directory where the file is as the root to resolve imports // relative to. char* lastSlash = strrchr(path, '/'); - rootDirectory = malloc(lastSlash - path + 2); + rootDirectory = (char*)malloc(lastSlash - path + 2); memcpy(rootDirectory, path, lastSlash - path + 1); rootDirectory[lastSlash - path + 1] = '\0'; diff --git a/src/wren_vm.c b/src/wren_vm.c index 8959650b..7605f391 100644 --- a/src/wren_vm.c +++ b/src/wren_vm.c @@ -1208,7 +1208,7 @@ WrenInterpretResult wrenInterpret(WrenVM* vm, const char* sourcePath, const char* source) { if (strlen(sourcePath) == 0) return loadIntoCore(vm, source); - + // TODO: Better module name. Value name = wrenNewString(vm, "main", 4); wrenPushRoot(vm, AS_OBJ(name)); @@ -1345,7 +1345,7 @@ static void defineMethod(WrenVM* vm, const char* className, // TODO: Need to be able to define methods in classes outside the core // module. - + // Find or create the class to bind the method to. ObjModule* coreModule = getCoreModule(vm); int classSymbol = wrenSymbolTableFind(&coreModule->variableNames, @@ -1460,7 +1460,7 @@ void wrenReturnString(WrenVM* vm, const char* text, int length) { ASSERT(vm->foreignCallSlot != NULL, "Must be in foreign call."); ASSERT(text != NULL, "String cannot be NULL."); - + size_t size = length; if (length == -1) size = strlen(text);