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 9ae20dd..c0fa0b5 100644 --- a/Makefile +++ b/Makefile @@ -8,15 +8,12 @@ all: bin/musique include scripts/debug.mk include scripts/release.mk include scripts/test.mk - -bin/bestline.o: lib/bestline/bestline.c lib/bestline/bestline.h - @echo "CC $@" - @$(CC) $< -c -O3 -o $@ +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__LINUX_ALSA__ + @$(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 c41bf54..514be89 100644 --- a/config.mk +++ b/config.mk @@ -2,11 +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=-lasound -lpthread -static-libgcc -static-libstdc++ diff --git a/musique/common.hh b/musique/common.hh index 871a74f..800b12b 100644 --- a/musique/common.hh +++ b/musique/common.hh @@ -20,6 +20,7 @@ using i64 = std::int64_t; using usize = std::size_t; using isize = std::ptrdiff_t; +using uint = unsigned int; /// Combine several lambdas into one for visiting std::variant template diff --git a/musique/main.cc b/musique/main.cc index 2d57a21..6024f8b 100644 --- a/musique/main.cc +++ b/musique/main.cc @@ -16,9 +16,15 @@ #include #include +#ifdef _WIN32 +extern "C" { +#include +} +#else extern "C" { #include } +#endif namespace fs = std::filesystem; @@ -194,6 +200,7 @@ 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}; @@ -206,11 +213,21 @@ void completion(char const* buf, bestlineCompletions *lc) } } } +#endif + +bool is_tty() +{ +#ifdef _WIN32 + return _isatty(STDOUT_FILENO); +#else + return isatty(STDOUT_FILENO); +#endif +} /// Fancy main that supports Result forwarding on error (Try macro) static std::optional Main(std::span args) { - if (isatty(STDOUT_FILENO) && getenv("NO_COLOR") == nullptr) { + if (is_tty() && getenv("NO_COLOR") == nullptr) { pretty::terminal_mode(); } @@ -314,13 +331,27 @@ 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 (;;) { - char *input_buffer = bestlineWithHistory("> ", "musique"); +#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; @@ -330,7 +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 - free(input_buffer); +#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 d7c77b6..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/bestline.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/bestline.o 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