Skip to content

Commit

Permalink
Add support for importing packages from the registry and http/https s…
Browse files Browse the repository at this point in the history
…erved files (#1049)

* Added package manager module

* Fixing Error Messages and Error handling

* Added --package-only and --pkg-list options in the compiler

* Changed Example to use the new package format

* Changed help to contain the new options

* Added a url handling library and changed the way i handle the registry url

* Added WASM compatiable code

* Batch to fix stackoverflow error in browsers

* add node support for xhr requests

* Update Downloader.cpp

* change xhr requests to fetch

* testing

* x

* xmlrequest support

* remove async debug

* Fix the versions in examples and add a test script

* update libraries

* add author in error messages

* Solve the problem with XMLHttpRequest isn't a constructor
  • Loading branch information
shehab299 authored Aug 16, 2024
1 parent c7ec49d commit dde84df
Show file tree
Hide file tree
Showing 219 changed files with 2,023 additions and 286 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,6 @@ tests/impulse-tests/ir
.idea/
### Pyenv
.python-version

## filesystem
build/wasm-filesystem
4 changes: 4 additions & 0 deletions build/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ set (LIBDIR ${CMAKE_CURRENT_SOURCE_DIR}/${LIBSDIR})

set (CMAKE_CXX_STANDARD 17)

find_package(CURL REQUIRED)

#######################################
# Output options
option ( UNIVERSAL "Compiles and combines x86_64 and arm64 architectures [MacOS]" off )
Expand Down Expand Up @@ -192,6 +194,7 @@ if (INCLUDE_EXECUTABLE)
endif()
target_include_directories (faust PRIVATE ${FAUST_INC} ${LLVM_INCLUDE_DIRS})
target_link_libraries (faust PRIVATE ${FAUST_LIBS})
target_link_libraries(faust PUBLIC ${CURL_LIBRARIES})
scan_backends (faust COMPILER)
set_target_properties(faust PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${BINDIR})
set_target_properties(faust PROPERTIES COMPILE_FLAGS -DFAUST_EXE)
Expand Down Expand Up @@ -284,6 +287,7 @@ if (${CMAKE_GENERATOR} STREQUAL Xcode OR ${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC
set (INCLUDE_EMCC off)
set (INCLUDE_WASM_GLUE off)
endif()

if (INCLUDE_EMCC)
add_subdirectory (emcc)
endif()
Expand Down
3 changes: 2 additions & 1 deletion build/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ BUILDOPT ?= --config Release
BACKENDS ?= $(shell [ -f $(BCACHE) ] && (grep BACKENDS $(BCACHE) | cut -d= -f2) || echo regular.cmake)
TARGETS ?= $(shell [ -f $(TCACHE) ] && (grep TARGETS $(TCACHE) | cut -d= -f2) || echo regular.cmake)
LIBSDIR ?= $(shell [ -f $(LCACHE) ] && (grep LIBSDIR $(LCACHE) | cut -d= -f2) || echo lib)
EMCC ?= emcc
EMCC ?= emcc

#===============================================================
ifeq ($(GENERATOR), Xcode)
Expand Down Expand Up @@ -331,6 +331,7 @@ cmake: $(FAUSTDIR)
#===============================================================
WASMFS := wasm-filesystem
WASMLIBDIR := share/faust

wasmlib: $(FAUSTDIR) $(FAUSTDIR)/Makefile
@$(MAKE) checkemcc
mkdir -p $(WASMFS)/$(WASMLIBDIR) && cp ../libraries/*.lib ../libraries/old/*.lib $(WASMFS)/$(WASMLIBDIR)
Expand Down
7 changes: 5 additions & 2 deletions build/emcc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ set ( CMAKE_OSX_SYSROOT "")
set ( CMAKE_CXX_COMPILER "emcc")
set (CMAKE_CXX_LINK_FLAGS "")



if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm64")
message (WARNING "Compiling on M1")
set (CMAKE_OSX_ARCHITECTURES " ")
Expand All @@ -25,9 +27,10 @@ file (GLOB BINDINGS ${ROOT}/compiler/generator/wasm/bindings/*.cpp)
set (SRC ${SRC} ${BINDINGS})

set (WASM_EXPORTED "\"['UTF8ToString', 'stringToUTF8', 'FS']\"")
set (WASM_TO_INCLUDE "\"['$allocate', '$ALLOC_STACK']\"")
file (GLOB LIBSNDFILE ${WASMGLUE}/*.a)

set (WASM_LINK_FLAGS "--no-heap-copy --bind -O3 --memory-init-file 0 -s LINKABLE=0 -s DYNAMIC_EXECUTION=0 -s WASM=1 -s EXPORT_NAME=\"'FaustModule'\" -s MODULARIZE=1 --preload-file ../../wasm-filesystem@usr -s ASSERTIONS=1 -s ALLOW_MEMORY_GROWTH=1 -s STACK_SIZE=8MB -s DISABLE_EXCEPTION_CATCHING=1 -s EXPORTED_RUNTIME_METHODS=${WASM_EXPORTED} ${LIBSNDFILE}")
set (WASM_LINK_FLAGS " --no-heap-copy --bind -O3 --memory-init-file 0 -s LINKABLE=0 -s DYNAMIC_EXECUTION=0 -s WASM=1 -s EXPORT_NAME=\"'FaustModule'\" -s MODULARIZE=1 --preload-file ../../wasm-filesystem@usr -s ASSERTIONS=1 -s ALLOW_MEMORY_GROWTH=1 -s STACK_SIZE=8MB -s DISABLE_EXCEPTION_CATCHING=1 -s EXPORTED_RUNTIME_METHODS=${WASM_EXPORTED} -s DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=${WASM_TO_INCLUDE}")

####################################
# Add the different targets
Expand All @@ -44,7 +47,7 @@ target_compile_definitions (wasmlib PRIVATE -DEMCC -DFAUST_LIB ${FAUST_DEFINITIO
set_target_properties (wasmlib PROPERTIES
OUTPUT_NAME libfaust-wasm
LINK_FLAGS ${WASM_LINK_FLAGS}
COMPILE_FLAGS -O3
COMPILE_FLAGS "-O3 -std=c++20"
# RUNTIME_OUTPUT_DIRECTORY ${LIBDIR} generation in a non default place prevents the data file to be found
SUFFIX ".js")

Expand Down
6 changes: 3 additions & 3 deletions build/wasmglue/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ endif()

if (WORKLET)
message(STATUS "Compile wasm glue library for worklet")
set (WASM_COMPILE_FLAGS "-O3 -DAUDIO_WORKLET")
set (WASM_COMPILE_FLAGS "-std=c++20 -O3 -DAUDIO_WORKLET ")
set (WASM_LINK_FLAGS_EXTRA "-s WASM_ASYNC_COMPILATION=0 -s SINGLE_FILE=1 -s ASSERTIONS=0")
set (LIB_NAME "libfaust-worklet-glue")
else()
message(STATUS "Compile wasm glue library")
set (WASM_COMPILE_FLAGS "-O3")
set (WASM_COMPILE_FLAGS "-O3 -std=c++20")
set (WASM_LINK_FLAGS_EXTRA "-s ASSERTIONS=1")
set (LIB_NAME "libfaust-glue")
endif()
Expand All @@ -53,7 +53,7 @@ set (FAUST_INC ${SRCDIR}
# emscripten support
set (WASM_EXPORTED "\"['FS']\"")
set (LIBSNDFILE "${ROOT}/build/wasmglue/libsndfile.a ${ROOT}/build/wasmglue/libogg.a ${ROOT}/build/wasmglue/libvorbis.a ${ROOT}/build/wasmglue/libvorbisenc.a ${ROOT}/build/wasmglue/libFLAC.a")
set (WASM_LINK_FLAGS "--bind --memory-init-file 0 -s LINKABLE=0 -s DYNAMIC_EXECUTION=0 -s WASM=1 -s EXPORT_NAME=\"'FaustModule'\" -s MODULARIZE=1 -s ASSERTIONS=0 -s ALLOW_MEMORY_GROWTH=1 -s STACK_SIZE=5MB -s DISABLE_EXCEPTION_CATCHING=1 -s EXPORTED_RUNTIME_METHODS=${WASM_EXPORTED} ${LIBSNDFILE} ${WASM_LINK_FLAGS_EXTRA}")
set (WASM_LINK_FLAGS "--bind --memory-init-file 0 -s LINKABLE=0 -s DYNAMIC_EXECUTION=0 -s WASM=1 -s EXPORT_NAME=\"'FaustModule'\" -s STACK_SIZE=8MB -s MODULARIZE=1 -s ASSERTIONS=0 -s ALLOW_MEMORY_GROWTH=1 -s DISABLE_EXCEPTION_CATCHING=1 -s EXPORTED_RUNTIME_METHODS=${WASM_EXPORTED} ${LIBSNDFILE} ${WASM_LINK_FLAGS_EXTRA}")

####################################
# Add the different targets
Expand Down
1 change: 1 addition & 0 deletions compiler/boxes/boxes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,7 @@ Tree importFile(Tree filename)
{
return tree(gGlobal->IMPORTFILE, filename);
}

bool isImportFile(Tree s, Tree& filename)
{
return isTree(s, gGlobal->IMPORTFILE, filename);
Expand Down
21 changes: 18 additions & 3 deletions compiler/global.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,7 @@ void global::reset()
gFixedPointLSB = 0;

gPrintFileListSwitch = false;
gPkgOnlySwitch = false;
gInlineArchSwitch = false;

gDSPStruct = false;
Expand Down Expand Up @@ -1154,7 +1155,7 @@ bool global::processCmdline(int argc, const char* argv[])
} else if (isCmd(argv[i], "-lang", "--language") && (i + 1 < argc)) {
gOutputLang = argv[i + 1];
i += 2;

} else if (isCmd(argv[i], "-v", "--version")) {
gVersionSwitch = true;
i += 1;
Expand Down Expand Up @@ -1437,11 +1438,15 @@ bool global::processCmdline(int argc, const char* argv[])
} else if (isCmd(argv[i], "-flist", "--file-list")) {
gPrintFileListSwitch = true;
i += 1;

} else if (isCmd(argv[i], "-plist", "--package-list")){
gPrintPackageListSwitch = true;
i += 1;
} else if(isCmd(argv[i], "-po", "--pkg-only")){
gPkgOnlySwitch = true;
i += 1;
} else if (isCmd(argv[i], "-norm", "--normalized-form")) {
gDumpNorm = 0;
i += 1;

} else if (isCmd(argv[i], "-norm1", "--normalized-form1")) {
gDumpNorm = 1;
i += 1;
Expand Down Expand Up @@ -1944,6 +1949,7 @@ void global::parseSourceFiles()
if (!gInjectFlag && gInputFiles.begin() == gInputFiles.end()) {
throw faustexception("ERROR : no files specified; for help type \"faust --help\"\n");
}

for (s = gInputFiles.begin(); s != gInputFiles.end(); s++) {
if (s == gInputFiles.begin()) {
gMasterDocument = *s;
Expand Down Expand Up @@ -2416,6 +2422,15 @@ string global::printHelp()
<< "-flist --file-list print file list (including libraries) used to "
"eval process."
<< endl;
sstr << tab
<< "-plist --package-list print packages list handled by pkgManager module used "
"to eval process."
<< endl;

sstr << tab
<< "-po --pkg-only Only compiles if the dsp code depends on faust packages"
<< endl;

sstr << tab
<< "-tg --task-graph print the internal task graph in dot format."
<< endl;
Expand Down
4 changes: 4 additions & 0 deletions compiler/global.hh
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ struct global {
bool gSimpleNames; // -sn option
bool gSimplifyDiagrams; // -sd option
bool gPrintFileListSwitch; // -flist option

bool gPrintPackageListSwitch; // -plist option
bool gPkgOnlySwitch; // --pkg-only option

bool gInlineArchSwitch; // -i option
bool gUIMacroSwitch; // -uim option
int gDumpNorm; // -norm option
Expand Down
16 changes: 16 additions & 0 deletions compiler/libcode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,22 @@ static Tree evaluateBlockDiagram(Tree expandedDefList, int& numInputs, int& numO

endTiming("evaluation");

if (gGlobal->gPrintPackageListSwitch){
cout << "---------------------------\n";
cout << "List of Package Dependencies :\n";
cout << "---------------------------\n";

// print the package used to evaluate process
vector<string> packages = gGlobal->gReader.listPackages();

for (size_t i = 0; i < packages.size(); i++) {
cout << packages[i] << endl;
}

cout << "---------------------------\n";
cout << endl;
}

if (gGlobal->gPrintFileListSwitch) {
cout << "---------------------------\n";
cout << "List of file dependencies :\n";
Expand Down
189 changes: 189 additions & 0 deletions compiler/parser/Downloader.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
#include "Downloader.hh"
#include "../errors/exception.hh"
#include <filesystem>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>





#ifndef EMCC
#include <curl/curl.h>

size_t Downloader::write_data_file(void* ptr, size_t size, size_t nmemb, void* userData) {

std::ofstream* file = static_cast<std::ofstream*>(userData);

if (!file->is_open()) {
throw faustexception("Internal Error: Couldn't Download Package");
}

file->write(static_cast<char*>(ptr), size * nmemb);

return size * nmemb;
}

size_t Downloader::write_data(void* ptr, size_t size, size_t nmemb, void* userData) {

std::string* data = static_cast<std::string*>(userData);
data->append(static_cast<char*>(ptr), size * nmemb);

return size * nmemb;
}



void Downloader::download(const std::string url,const std::string& savePath)
{

std::ofstream file(savePath, std::ios::binary);

if (!file.is_open()) {
throw faustexception("Can't open file: " + savePath);
}

curl_easy_setopt(handle, CURLOPT_URL, url.c_str());
curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, &Downloader::write_data_file);
curl_easy_setopt(handle, CURLOPT_WRITEDATA, &file);

CURLcode res = curl_easy_perform(handle);
file.close();

if (res != CURLE_OK) {
std::filesystem::remove(savePath);
throw faustexception("Download failed: " + std::string(curl_easy_strerror(res)) + "\n");
}

long http_code = 0;
curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &http_code);

if (std::to_string(http_code)[0] != '2'){
std::filesystem::remove(savePath);
throw faustexception("Unsuccessful download: HTTP code " + std::to_string(http_code) + "\n");
}
}

void Downloader::download(const std::string url,char** buffer)
{
std::string data;
curl_easy_setopt(handle, CURLOPT_URL, url.c_str());
curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, &Downloader::write_data);
curl_easy_setopt(handle, CURLOPT_WRITEDATA, &data);

CURLcode res = curl_easy_perform(handle);

if (res != CURLE_OK) {
throw faustexception("Download failed: " + std::string(curl_easy_strerror(res)) + "\n");
}

long http_code = 0;
curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &http_code);

if (std::to_string(http_code)[0] != '2'){
throw faustexception("Unsuccessful download: HTTP code " + std::to_string(http_code) + "\n");
}

*buffer = new char[data.size() + 1];
std::copy(data.begin(), data.end(), *buffer);
(*buffer)[data.size()] = '\0';
}

Downloader::Downloader(){
curl_global_init(CURL_GLOBAL_DEFAULT);
handle = curl_easy_init();
}

Downloader::~Downloader(){
curl_easy_cleanup(handle);
curl_global_cleanup();
}


#endif

#ifdef EMCC

#include <emscripten.h>

Downloader::Downloader(){
}

Downloader::~Downloader(){
}



EM_JS(char*, downloadFile, (const char* url), {
var dsp_code = "";

try {
if (typeof window !== 'undefined' && typeof window.XMLHttpRequest !== 'undefined') {
var xhr = new window.XMLHttpRequest();
xhr.open('GET', UTF8ToString(url), false);
xhr.send(null);

if (xhr.status >= 200 && xhr.status < 300) {
dsp_code = xhr.responseText;
}
} else if (typeof process != 'undefined' && process.versions != null && process.versions.node != null) {
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;
var xhr = new XMLHttpRequest();
xhr.open('GET', UTF8ToString(url), false);
xhr.send(null);
if (xhr.status >= 200 && xhr.status < 300) {
dsp_code = xhr.responseText;
}
}
} catch (error) {
console.log('Error:', error);
}

return allocate(intArrayFromString(dsp_code), ALLOC_STACK);
});





void Downloader::download(const std::string url,const std::string& savePath){

std::ofstream file(savePath, std::ios::binary);

if (!file.is_open()) {
throw faustexception("Can't open file: " + savePath);
}

char* buffer = (char*) downloadFile(url.c_str());

if(strlen(buffer) == 0){
std::filesystem::remove(savePath);
throw faustexception("Couldn't download file: " + url);
}

try{
file << buffer;
file.close();
}catch(const std::exception& e){
std::filesystem::remove(savePath);
throw faustexception("Couldn't download file: " + url);
}
}


void Downloader::download(const std::string url,char** buffer){

*buffer = (char*) downloadFile(url.c_str());

if(strlen(*buffer) == 0){
std::stringstream error;
error << "ERROR : unable to access URL '" << url << "'" << std::endl;
throw faustexception(error.str());
}
}
#endif



Loading

0 comments on commit dde84df

Please sign in to comment.