From e8ef207ec9a657de485cbb52e13e5ca27e9f06f2 Mon Sep 17 00:00:00 2001 From: Robert Bendun Date: Sat, 8 Oct 2022 20:32:41 +0200 Subject: [PATCH] Windows support --- CHANGELOG.md | 1 + Makefile | 3 ++- README.md | 28 +++------------------- config.mk | 13 +++++++++-- musique/main.cc | 58 +++++++++++++++++++++++++++++++++++++++++----- scripts/release | 13 ++++++----- scripts/release.mk | 10 ++++++-- scripts/windows.mk | 11 +++++++++ 8 files changed, 95 insertions(+), 42 deletions(-) create mode 100644 scripts/windows.mk diff --git a/CHANGELOG.md b/CHANGELOG.md index 3410822..d06fc8b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Added `scan` builtin, which computes prefix sum of passed values when provided with addition operator * Added [rtmidi](https://github.com/thestk/rtmidi/) dependency which should provide multiplatform MIDI support +* Support for Windows (with only basic REPL) ### Changed diff --git a/Makefile b/Makefile index 72c7a07..c0fa0b5 100644 --- a/Makefile +++ b/Makefile @@ -8,11 +8,12 @@ all: bin/musique include scripts/debug.mk include scripts/release.mk include scripts/test.mk +include scripts/windows.mk # http://www.music.mcgill.ca/~gary/rtmidi/#compiling bin/rtmidi.o: lib/rtmidi/RtMidi.cpp lib/rtmidi/RtMidi.h @echo "CXX $@" - @$(CXX) $< -c -O2 -o $@ -D__WINDOWS_MM__ + @$(CXX) $< -c -O2 -o $@ $(CPPFLAGS) doc: Doxyfile musique/*.cc musique/*.hh doxygen diff --git a/README.md b/README.md index d1dfd68..2f42049 100644 --- a/README.md +++ b/README.md @@ -21,9 +21,8 @@ $ sudo apt install -y build-essential libasound2-dev ## Budowanie interpretera -```console -$ make bin/musique -``` +- Aby wybudować wersję Linux+ALSA: `make` +- Aby wybudować wersję Windows: `make os=windows` Żeby zainstalować interpreter języka Musique w systemie, należy dodatkowo wykonać polecenie: @@ -38,6 +37,7 @@ $ make bin/musique - `make` - Buduje interpreter `bin/musique` (tryb release) - `make debug` - Buduje interpreter `bin/debug/musique` (tryb debug) - `make clean` - Usuwa reprodukowalne elementy projektu (automatycznie stworzone pliki binarne czy raporty) + ### Dokumentacja - `make doc` - Tworzy `doc/build/html/` zawierający dokumentację projektu @@ -45,28 +45,6 @@ $ make bin/musique ### Testowanie - `make test` - Uruchom wszystkie dostępne testy automatyczne -- `scripts/test.py test examples` - Uruchamia testy zachowań przykładów -- `scripts/test.py record examples` - Nagrywa testy zachowań przykładów - -### Debugowanie - -- `scripts/log-function-calls.sh` - Tworzy listę wywołań funkcji używając GDB - -## Budowa projektu - -``` -. -├── bin Miejsce produkcji plików wykonywalnych -├── doc Dokumentacja języka, interpretera -│   └── build Miejsce produkcji dokumentacji -├── editor Pluginy do edytorów dodające wsparcie dla języka -├── lib Zewnętrzne zależności projektu -│   ├── expected -│   └── ut -└── include Główny katalog z plikami nagłówkowymi -├── scripts Skrypty wspierające budowanie i tworzenie -└── src Główny katalog z plikami źródłowymi -``` ## Kolorowanie składni diff --git a/config.mk b/config.mk index 40c44b2..514be89 100644 --- a/config.mk +++ b/config.mk @@ -2,12 +2,21 @@ MAKEFLAGS="-j $(grep -c ^processor /proc/cpuinfo)" CXXFLAGS:=$(CXXFLAGS) -std=c++20 -Wall -Wextra -Werror=switch -Werror=return-type -Werror=unused-result -Wno-maybe-uninitialized CPPFLAGS:=$(CPPFLAGS) -Ilib/expected/ -I. -Ilib/bestline/ -Ilib/rtmidi/ +LDFLAGS=-flto +LDLIBS= -lpthread -static-libgcc -static-libstdc++ RELEASE_FLAGS=-O2 DEBUG_FLAGS=-O0 -ggdb -fsanitize=undefined -DDebug +ifeq ($(os),windows) CC=i686-w64-mingw32-gcc CXX=i686-w64-mingw32-g++ +CPPFLAGS:=$(CPPFLAGS) -D__WINDOWS_MM__ +LDLIBS:=-lwinmm $(LDLIBS) +else +CC=gcc +CXX=g++ +CPPFLAGS:=$(CPPFLAGS) -D __LINUX_ALSA__ +LDLIBS:=-lasound $(LDLIBS) +endif -LDFLAGS=-flto -LDLIBS=-lwinmm -lpthread -static-libgcc -static-libstdc++ diff --git a/musique/main.cc b/musique/main.cc index 142873b..6024f8b 100644 --- a/musique/main.cc +++ b/musique/main.cc @@ -16,6 +16,16 @@ #include #include +#ifdef _WIN32 +extern "C" { +#include +} +#else +extern "C" { +#include +} +#endif + namespace fs = std::filesystem; static bool ast_only_mode = false; @@ -190,12 +200,27 @@ struct Runner /// some of the strings are only views into source std::vector eternal_sources; +#ifndef _WIN32 +void completion(char const* buf, bestlineCompletions *lc) +{ + std::string_view in{buf}; + + for (auto scope = Runner::the->interpreter.env.get(); scope != nullptr; scope = scope->parent.get()) { + for (auto const& [name, _] : scope->variables) { + if (name.starts_with(in)) { + bestlineAddCompletion(lc, name.c_str()); + } + } + } +} +#endif + bool is_tty() { -#ifdef __linux__ - return isatty(STDOUT_FILENO); +#ifdef _WIN32 + return _isatty(STDOUT_FILENO); #else - return true; + return isatty(STDOUT_FILENO); #endif } @@ -306,13 +331,29 @@ static std::optional Main(std::span args) if (runnables.empty() || enable_repl) { repl_line_number = 1; enable_repl = true; +#ifndef _WIN32 + bestlineSetCompletionCallback(completion); +#else + std::vector repl_source_lines; +#endif for (;;) { - std::string_view raw; - if (auto s = new std::string{}; std::getline(std::cin, *s)) { - raw = *s; +#ifndef _WIN32 + char const* input_buffer = bestlineWithHistory("> ", "musique"); + if (input_buffer == nullptr) { + break; + } +#else + std::cout << "> " << std::flush; + char const* input_buffer; + if (std::string s{}; std::getline(std::cin, s)) { + repl_source_lines.push_back(std::move(s)); + input_buffer = repl_source_lines.back().c_str(); } else { break; } +#endif + // Raw input line used for execution in language + std::string_view raw = input_buffer; // Used to recognize REPL commands std::string_view command = raw; @@ -320,6 +361,11 @@ static std::optional Main(std::span args) if (command.empty()) { // Line is empty so there is no need to execute it or parse it +#ifndef _WIN32 + free(const_cast(input_buffer)); +#else + repl_source_lines.pop_back(); +#endif continue; } diff --git a/scripts/release b/scripts/release index 8e69ea5..da4c215 100755 --- a/scripts/release +++ b/scripts/release @@ -16,13 +16,14 @@ fi mkdir -p "$Target" -if ! [ -f bin/musique ]; then - make bin/musique -fi - -echo "Copy bin/musique, examples, license and documentation" - +make clean && make bin/musique cp bin/musique "$Target"/ + +make clean && make bin/musique os=windows +cp bin/musique.exe "$Target"/ + +echo "Copy examples, license and documentation" + cp LICENSE "$Target"/LICENSE cp CHANGELOG.md "$Target/CHANGELOG.md" cp -r examples "$Target"/examples diff --git a/scripts/release.mk b/scripts/release.mk index c2916a1..01d5eb6 100644 --- a/scripts/release.mk +++ b/scripts/release.mk @@ -1,9 +1,15 @@ +ifneq ($(os),windows) Release_Obj=$(addprefix bin/,$(Obj)) +bin/bestline.o: lib/bestline/bestline.c lib/bestline/bestline.h + @echo "CC $@" + @$(CC) $< -c -O3 -o $@ + bin/%.o: musique/%.cc @echo "CXX $@" @$(CXX) $(CXXFLAGS) $(RELEASE_FLAGS) $(CPPFLAGS) -o $@ $< -c -bin/musique: $(Release_Obj) bin/main.o bin/rtmidi.o +bin/musique: $(Release_Obj) bin/main.o bin/rtmidi.o bin/bestline.o @echo "CXX $@" - @$(CXX) $(CXXFLAGS) $(RELEASE_FLAGS) $(CPPFLAGS) -o $@ $(Release_Obj) bin/rtmidi.o $(LDFLAGS) $(LDLIBS) + @$(CXX) $(CXXFLAGS) $(RELEASE_FLAGS) $(CPPFLAGS) -o $@ $(Release_Obj) bin/rtmidi.o bin/bestline.o $(LDFLAGS) $(LDLIBS) +endif diff --git a/scripts/windows.mk b/scripts/windows.mk new file mode 100644 index 0000000..d312494 --- /dev/null +++ b/scripts/windows.mk @@ -0,0 +1,11 @@ +ifeq ($(os),windows) +Release_Obj=$(addprefix bin/,$(Obj)) + +bin/%.o: musique/%.cc + @echo "CXX $@" + @$(CXX) $(CXXFLAGS) $(RELEASE_FLAGS) $(CPPFLAGS) -o $@ $< -c + +bin/musique: $(Release_Obj) bin/main.o bin/rtmidi.o + @echo "CXX $@" + @$(CXX) $(CXXFLAGS) $(RELEASE_FLAGS) $(CPPFLAGS) -o $@ $(Release_Obj) bin/rtmidi.o $(LDFLAGS) $(LDLIBS) +endif