#!/usr/bin/perl # # Description: Compile script for the JavaScript toolkit version of verovio. # # Changes from bash script version: # Allow for excluding specific fonts. # Example: ./buildToolkit -x "Gootville,Bravura" # Long Example: ./buildToolkit --exclude "Gootville,Bravura" # Allow exclusion of specific importers (only works with PAE and Humdrum for now). # Example: ./buildToolkit -P # Long Example: ./buildToolkit --no-pae # Made VEROVIO_ROOT selectable from the command-line in case it or this directory needs to move. # Example: ./buildToolkit -r ../.. # Long Example: ./buildToolkit --root ../.. # Automated generation of source code filelist. # Note: # VERSION_NAME not significantly used so removed. # For smallest toolkit footprint use these options: # ./buildToolkit -x "Gootville,Bravura" -DHPX # (no Gootville or Bravura fonts; no importers) # use strict; use Getopt::Long; sub print_help { print <<"EOT"; Options: -c Chatty mode: display compiler progress -l Light version with no increased memory allocation -r DIR Verovio root directory -v N Version number (e.g., 1.0.0); no number by default -w Webassembly version -x Font exclusion list (case-sensitive) -D Disable DARMS importer -H Disable Humdrum importer -P Disable PAE importer -X Disable MusicXML importer -M Clean existing makefile EOT } chomp (my $EMCC = `which em++`); chomp (my $EMCMAKE = `which emcmake`); chomp (my $EMMAKE = `which emmake`); die "ERROR: emscripten compiler (emcc) not found.\n" unless $EMCC; die "ERROR: emscripten cmake (emcmake) not found.\n" unless $EMCMAKE; die "ERROR: emscripten make (emmake) not found.\n" unless $EMMAKE; # Parse command-line options my ($lightQ, $version, $chattyQ, $helpQ, $exclusion, $wasmQ, $makeQ); my ($nopae, $nohumdrum, $nomusicxml, $nodarms); my ($FLAGS_NAME, $VERSION, $CHATTY); my $cpp = 17; # c++ version to compile (11, 14, 17) my $VEROVIO_ROOT = ".."; Getopt::Long::Configure("bundling"); GetOptions ( 'C|cpp=s' => \$cpp, 'c|chatty' => \$chattyQ, 'h|?|help' => \$helpQ, 'l|light' => \$lightQ, 'r|root=s' => \$VEROVIO_ROOT, 'v|version=s' => \$VERSION, 'x|exclusion=s' => \$exclusion, 'w|wasm' => \$wasmQ, 'D|no-darms' => \$nodarms, 'H|no-humdrum' => \$nohumdrum, 'P|no-pae' => \$nopae, 'X|no-musicxml' => \$nomusicxml, 'M|make' => \$makeQ ); # Default compiling uses ASM and large file support. # Memory is increased (TOTAL_STACK) for processing large files (tested up to 7MB) # Empirically, the memory amount required is roughly 5 times the file size. # This can be disabled in the light version, which uses the default memory settings. my $FLAGS = "-O3"; $FLAGS .= " -DNDEBUG"; $FLAGS .= " --memory-init-file 0"; $FLAGS .= " -std=c++$cpp"; my $LFLAGS = " -s ASM_JS=1"; $LFLAGS .= " -s INITIAL_MEMORY=256MB"; $LFLAGS .= " -s TOTAL_STACK=128MB"; $LFLAGS .= " -s WASM=0"; # Process command-line options: if ($wasmQ) { print "Creating WASM toolkit version\n"; # We can try to find the cause of integer overflow runtime errors with # $FLAGS = " -g4 -O0 --emit-symbol-map"; # For now, trapping them (followign option does not work with Safari) #$FLAGS .= " -mnontrapping-fptoint"; $FLAGS .= " -s STRICT=1"; # Linker flags $LFLAGS = " -s WASM=1"; $LFLAGS .= " -s INITIAL_MEMORY=512MB"; $LFLAGS .= " -s TOTAL_STACK=256MB"; $LFLAGS .= " -s SINGLE_FILE=1"; $FLAGS_NAME = "-wasm"; } if ($lightQ) { print "Creating low-memory (light) toolkit version\n"; $LFLAGS = " -s ASM_JS=1 -s WASM=0"; $FLAGS_NAME = "-light"; } if ($chattyQ) { $CHATTY = "-v"; } if (!$nohumdrum) { $FLAGS_NAME .= "-hum"; } if ($helpQ) { print_help(); exit 2; } my $FILENAME = "verovio-toolkit$FLAGS_NAME.js"; my $DATA_DIR = "data"; my $BUILD_DIR = "build"; $BUILD_DIR .= "/$VERSION" if $VERSION; my $NPM = "npm"; $NPM .= "-dev" if not($VERSION); print "Compiled files will be written to $BUILD_DIR\n"; `mkdir -p $BUILD_DIR`; `mkdir -p $DATA_DIR`; syncSvgResources($exclusion); # Generate the git commit file print "Creating commit version header file...\n"; `$VEROVIO_ROOT/tools/get_git_commit.sh`; my $defines = "-DUSE_EMSCRIPTEN"; my $cmake = "-DBUILD_AS_WASM=ON"; $cmake .= " -DNO_PAE_SUPPORT=ON" if ($nopae); $cmake .= " -DNO_DARMS_SUPPORT=ON" if ($nodarms); $cmake .= " -DNO_HUMDRUM_SUPPORT=ON" if ($nohumdrum); $cmake .= " -DNO_MUSICXML_SUPPORT=ON" if ($nomusicxml); my $embed = "--embed-file $DATA_DIR/"; my $output = "-o $BUILD_DIR/verovio.js"; my $exports = "-s EXPORTED_FUNCTIONS=\"["; $exports .= "'_vrvToolkit_constructor',"; $exports .= "'_vrvToolkit_destructor',"; $exports .= "'_vrvToolkit_edit',"; $exports .= "'_vrvToolkit_editInfo',"; $exports .= "'_vrvToolkit_getAvailableOptions',"; $exports .= "'_vrvToolkit_getElementAttr',"; $exports .= "'_vrvToolkit_getElementsAtTime',"; $exports .= "'_vrvToolkit_getExpansionIdsForElement',"; $exports .= "'_vrvToolkit_getHumdrum',"; $exports .= "'_vrvToolkit_convertHumdrumToHumdrum',"; $exports .= "'_vrvToolkit_convertMEIToHumdrum',"; $exports .= "'_vrvToolkit_getLog',"; $exports .= "'_vrvToolkit_getMEI',"; $exports .= "'_vrvToolkit_getMIDIValuesForElement',"; $exports .= "'_vrvToolkit_getNotatedIdForElement',"; $exports .= "'_vrvToolkit_getOptions',"; $exports .= "'_vrvToolkit_getPageCount',"; $exports .= "'_vrvToolkit_getPageWithElement',"; $exports .= "'_vrvToolkit_getTimeForElement',"; $exports .= "'_vrvToolkit_getTimesForElement',"; $exports .= "'_vrvToolkit_getVersion',"; $exports .= "'_vrvToolkit_loadData',"; $exports .= "'_vrvToolkit_loadZipDataBase64',"; $exports .= "'_vrvToolkit_loadZipDataBuffer',"; $exports .= "'_vrvToolkit_redoLayout',"; $exports .= "'_vrvToolkit_redoPagePitchPosLayout',"; $exports .= "'_vrvToolkit_renderData',"; $exports .= "'_vrvToolkit_renderToMIDI',"; $exports .= "'_vrvToolkit_renderToPAE',"; $exports .= "'_vrvToolkit_renderToSVG',"; $exports .= "'_vrvToolkit_renderToTimemap',"; $exports .= "'_vrvToolkit_setOptions',"; $exports .= "'_malloc',"; $exports .= "'_free'"; $exports .= "]\""; my $extra_exports = "-s EXPORTED_RUNTIME_METHODS='[\"cwrap\"]'"; if ($makeQ) { system("rm -rf CMakeFiles/"); system("rm CMakeCache.txt"); } print "*************\nBuilding makefile...\n"; my $cmakeCmd = "$EMCMAKE cmake ../cmake $cmake -DCMAKE_CXX_FLAGS=\"$FLAGS\""; system($cmakeCmd); print "*************\nCompiling...\n"; my $makeCmd = "$EMMAKE make -j 8"; system($makeCmd); print "*************\nLinking...\n"; my $ccCmd = "$EMCC $CHATTY libverovio.a $LFLAGS $FLAGS $embed $exports $extra_exports $output"; print "$ccCmd\n" if $CHATTY; system($ccCmd); if ($? == 0) { print " Done.\n"; # the wrapper is necessary with closure 1 for avoiding to conflict with globals `cat $BUILD_DIR/verovio.js verovio-js-start.js verovio-proxy.js > $BUILD_DIR/$FILENAME`; # wrap the npm package (but not with wasm build and without humdrum for now) if ($wasmQ && !$lightQ && $nohumdrum) { print "Building $NPM package\n"; # the cat order is different for the npm package because we want to wrap the Module in the init function `cat verovio-npm-start.js $BUILD_DIR/verovio.js verovio-proxy.js verovio-npm-end.js > $NPM/index.js`; } # create a gzip version `(cd $BUILD_DIR && gzip -c $FILENAME > $FILENAME.gz)`; print "$BUILD_DIR/$FILENAME.gz was created\n"; # all good print "$BUILD_DIR/$FILENAME was created\n"; # create also a zip file if version name is given if ($VERSION) { `(cd $BUILD_DIR && zip $FILENAME.zip $FILENAME)`; print "$BUILD_DIR/$FILENAME.zip was created\n"; } } else { print " Failed.\n"; } exit 0; ########################################################################### ############################## ## ## syncSvgResources -- copy SVG resources for embedding in toolkit. ## sub syncSvgResources { my ($exclusion) = @_; print "Syncing SVG resources...\n"; # First clear old contents of data directory `rm -rf $DATA_DIR/*` if $DATA_DIR; # Then copy data directory contents `cp -r $VEROVIO_ROOT/data/* $DATA_DIR/`; # Remove .DS_Store from the data directory `find $DATA_DIR/ -name '.DS_Store' -type f -delete`; return unless $exclusion; my @list = split /[^A-Za-z0-9_]+/, $exclusion; foreach my $item (@list) { next unless $item; my @matches = glob "$DATA_DIR/$item*"; if (@matches) { print "\tRemoving $item from embedded resources\n"; `rm -rf $DATA_DIR/$item*`; } } }