Fixes: #1547 - Implement building and testing with cmake - Download libsonic from repository (when enabled and not available as system library), ref: #650 - Migrate android native build to cmake - Migrate CI to cmake - Add windows CI TODO (might be done in separate PR): - Building as [cmake external project](https://cmake.org/cmake/help/latest/module/ExternalProject.html) - Building for package managers (deb, rpm, ...) - Strip out `vcproj` - _to be discussed_ - Strip out `autotools` after next release - Update build documentation for `cmake`master
| @@ -16,18 +16,16 @@ jobs: | |||
| config: [debug, release] | |||
| include: | |||
| - config: debug | |||
| target: assembleDebug | |||
| apkname: espeak-debug.apk | |||
| - config: release | |||
| target: assembleRelease | |||
| apkname: espeak-release-unsigned.apk | |||
| name: Build ${{ matrix.config }} APK | |||
| steps: | |||
| - uses: actions/checkout@v3 | |||
| - name: autoconf | |||
| run: ./autogen.sh ; chmod -x INSTALL m4/*.m4 | |||
| - name: configure | |||
| run: ./configure --with-gradle=$(pwd)/android/gradlew | |||
| - name: make | |||
| run: make apk-${{ matrix.config }} | |||
| run: cd android ; ./gradlew ${{ matrix.target }} | |||
| - name: upload | |||
| uses: actions/upload-artifact@v3 | |||
| with: | |||
| @@ -70,7 +70,7 @@ jobs: | |||
| - sanitizer: "memory" | |||
| configenv: "CC=clang CXX=clang++" | |||
| sanitizer_cflags: "-fsanitize=memory -fsanitize-memory-track-origins=2" | |||
| config: "--without-pcaudiolib --without-sonic" | |||
| config: "-DUSE_LIBPCAUDIO:BOOL=OFF -DUSE_LIBSONIC:BOOL=OFF" | |||
| sanitize_env: "MSAN_OPTIONS=exitcode=42" | |||
| - sanitizer: "thread" | |||
| @@ -81,7 +81,7 @@ jobs: | |||
| sanitize_env: "UBSAN_OPTIONS=halt_on_error=1" | |||
| - sanitizer: "valgrind" | |||
| sanitize_env: 'VALGRIND="libtool --mode=execute valgrind --track-origins=yes --leak-check=full --error-exitcode=1"' | |||
| sanitize_env: 'VALGRIND="valgrind --track-origins=yes --leak-check=full --error-exitcode=1"' | |||
| exclude: | |||
| - os: macos | |||
| @@ -183,7 +183,7 @@ jobs: | |||
| sudo apt-get install ronn kramdown python3 | |||
| - name: apt-arch-deps | |||
| if: matrix.os == 'ubuntu' && matrix.cross == 'no' | |||
| run: "sudo apt-get install libtool-bin valgrind g++-12-multilib linux-libc-dev:${{ matrix.arch }} libpcaudio-dev:${{ matrix.arch }} libsonic-dev:${{ matrix.arch }} libstdc++-12-dev:${{ matrix.arch }} libc6-dbg:${{ matrix.arch }}" | |||
| run: "sudo apt-get install cmake valgrind g++-12-multilib linux-libc-dev:${{ matrix.arch }} libpcaudio-dev:${{ matrix.arch }} libsonic-dev:${{ matrix.arch }} libstdc++-12-dev:${{ matrix.arch }} libc6-dbg:${{ matrix.arch }}" | |||
| - name: apt-cross-deps | |||
| if: matrix.cross == 'yes' | |||
| run: sudo apt-get install qemu-user g++-12-${{ matrix.arch }}-${{ matrix.sys }} | |||
| @@ -194,8 +194,7 @@ jobs: | |||
| # MacOS - dependencies | |||
| - name: brew-deps | |||
| if: matrix.os == 'macos' | |||
| run: brew install libtool automake ronn OJFord/homebrew-formulae/kramdown && | |||
| brew install --HEAD anarchivist/espeak-ng/waywardgeek-sonic | |||
| run: brew install cmake ronn OJFord/homebrew-formulae/kramdown | |||
| - name: brew-compile-deps | |||
| if: matrix.os == 'macos' && matrix.compiler == 'gcc' | |||
| run: brew install gcc@12 | |||
| @@ -204,11 +203,6 @@ jobs: | |||
| - uses: actions/checkout@v3 | |||
| # Configure | |||
| - name: autoconf | |||
| run: | | |||
| ./autogen.sh | |||
| chmod -x INSTALL m4/*.m4 | |||
| - name: configure | |||
| run: | | |||
| [ 'x${{ matrix.compiler }}' = 'xgcc' ] && export CC="${{ matrix.ccarch }}-${{ matrix.sys }}-gcc-12" | |||
| @@ -218,19 +212,21 @@ jobs: | |||
| [ 'x${{ matrix.cross }}' = 'xyes' ] && export LD="${{ matrix.ccarch }}-${{ matrix.sys }}-ld" | |||
| export CFLAGS="-g -Og -fno-omit-frame-pointer ${{ matrix.compiler_flags }} ${{ matrix.sanitizer_cflags }} ${{ matrix.archcflags }}" | |||
| export CXXFLAGS="-g -Og -fno-omit-frame-pointer ${{ matrix.compiler_flags }} ${{ matrix.sanitizer_cflags }} ${{ matrix.archcflags }}" | |||
| ./configure --host=${{ matrix.arch }}-${{ matrix.sys }} ${{ matrix.config }} | |||
| cmake -Bbuild ${{ matrix.config }} -DCMAKE_SYSTEM_PROCESSOR=${{ matrix.arch }} -DUSE_ASYNC:BOOL=OFF | |||
| - name: config-failed-upload | |||
| if: ${{ failure() }} | |||
| uses: actions/upload-artifact@v3 | |||
| with: | |||
| name: config-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.compiler }}-${{ matrix.sanitizer }}.log | |||
| path: config.log | |||
| name: cmake-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.compiler }}-${{ matrix.sanitizer }}-builddir | |||
| path: build | |||
| # Build and test | |||
| - name: make-binary | |||
| run: make src/speak-ng src/espeak-ng | |||
| run: cmake --build build --target espeak-ng | |||
| - name: make-data | |||
| run: ${{ matrix.sanitize_env }} ${{ matrix.runenv }} make all-am | |||
| run: ${{ matrix.sanitize_env }} ${{ matrix.runenv }} cmake --build build --target data | |||
| - name: test | |||
| run: ${{ matrix.sanitize_env }} ${{ matrix.runenv }} make check | |||
| run: | | |||
| ${{ matrix.sanitize_env }} ${{ matrix.runenv }} cmake --build build --target tests | |||
| ${{ matrix.sanitize_env }} ${{ matrix.runenv }} ctest --test-dir build -Ttest -j1 --output-on-failure | |||
| @@ -8,7 +8,7 @@ on: | |||
| branches: [ master ] | |||
| env: | |||
| deps: libpcaudio-dev libsonic-dev ronn kramdown python3 | |||
| deps: cmake libpcaudio-dev libsonic-dev ronn kramdown python3 | |||
| jobs: | |||
| @@ -37,10 +37,8 @@ jobs: | |||
| if: matrix.arch == 'x86-32' | |||
| - name: dependencies | |||
| run: sudo apt-get update && sudo apt-get install ${{ env.deps }} reprotest ${{ matrix.archdeps }} | |||
| - name: autoconf | |||
| run: ./autogen.sh ; chmod -x INSTALL m4/*.m4 | |||
| - name: run | |||
| run: reprotest 'CFLAGS="${{ matrix.archconfigflags }}" CXXFLAGS="${{ matrix.archconfigflags }}" ./configure --without-gradle && make clean && make && make check && touch success' success | |||
| run: reprotest 'CFLAGS="${{ matrix.archconfigflags }}" CXXFLAGS="${{ matrix.archconfigflags }}" rm -rf build && cmake -Bbuild -DUSE_ASYNC:BOOL=OFF && cmake --build build && ctest --test-dir build -Ttest -j1 --output-on-failure && touch success' success | |||
| distcheck: | |||
| @@ -50,21 +48,21 @@ jobs: | |||
| - uses: actions/checkout@v3 | |||
| - name: dependencies | |||
| run: sudo apt-get update && sudo apt-get install ${{ env.deps }} | |||
| - name: autoconf | |||
| run: ./autogen.sh ; chmod -x INSTALL m4/*.m4 | |||
| - name: configure | |||
| run: ./configure | |||
| run: cmake -Bbuild -DUSE_ASYNC:BOOL=OFF | |||
| - name: make | |||
| run: make | |||
| run: cmake --build build | |||
| - name: make check | |||
| run: make check | |||
| - name: make dist | |||
| run: make dist | |||
| run: ctest --test-dir build -Ttest -j1 --output-on-failure | |||
| - name: make package_source | |||
| run: cmake --build build --target package_source | |||
| - name: unpack | |||
| run: mkdir unpack && tar -C unpack -xf *.tar.gz | |||
| run: mkdir unpack && tar -C unpack -xf build/espeak-ng-*-Source.tar.bz2 | |||
| - name: re-configure | |||
| run: cd unpack/espeak-ng-* && ./configure | |||
| run: cd unpack/espeak-ng-* && cmake -Bbuild -DUSE_ASYNC:BOOL=OFF | |||
| - name: re-make | |||
| run: cd unpack/espeak-ng-* && make | |||
| run: cd unpack/espeak-ng-* && cmake --build build | |||
| - name: re-make check | |||
| run: cd unpack/espeak-ng-* && make check | |||
| run: cd unpack/espeak-ng-* && ctest --test-dir build -Ttest -j1 --output-on-failure | |||
| @@ -0,0 +1,21 @@ | |||
| name: Windows | |||
| on: | |||
| workflow_dispatch: | |||
| push: | |||
| branches: [ master ] | |||
| pull_request: | |||
| branches: [ master ] | |||
| jobs: | |||
| build: | |||
| runs-on: windows-latest | |||
| name: build | |||
| steps: | |||
| - uses: actions/checkout@v3 | |||
| - name: configure | |||
| run: cmake -Bbuild -DUSE_ASYNC:BOOL=OFF | |||
| - name: make | |||
| run: cmake --build build | |||
| - name: make check | |||
| run: ctest --test-dir build -Ttest -C Debug -j1 --output-on-failure | |||
| @@ -0,0 +1,31 @@ | |||
| cmake_minimum_required(VERSION 3.8) | |||
| project(espeak-ng | |||
| VERSION 1.52.0.1 | |||
| DESCRIPTION "open source speech synthesizer that supports more than hundred languages and accents" | |||
| HOMEPAGE_URL "https://github.com/espeak-ng/espeak-ng" | |||
| ) | |||
| include(CTest) | |||
| include(cmake/deps.cmake) | |||
| include(cmake/config.cmake) | |||
| add_subdirectory(src) | |||
| include(cmake/data.cmake) | |||
| include(cmake/package.cmake) | |||
| include(CPack) | |||
| include(CTest) | |||
| add_subdirectory(tests) | |||
| option(BUILD_SHARED_LIBS "Build shared libraries" OFF) | |||
| message(STATUS "Configuration:") | |||
| message(STATUS " shared: ${BUILD_SHARED_LIBS}") | |||
| message(STATUS " mbrola: ${USE_MBROLA} (${MBROLA_BIN})") | |||
| message(STATUS " libsonic: ${USE_LIBSONIC} (${SONIC_LIB} ${SONIC_INC})") | |||
| message(STATUS " libpcaudio: ${USE_LIBPCAUDIO} (${PCAUDIO_LIB} ${PCAUDIO_INC})") | |||
| message(STATUS " klatt: ${USE_KLATT}") | |||
| message(STATUS " speech-player: ${USE_SPEECHPLAYER}") | |||
| message(STATUS " async: ${USE_ASYNC}") | |||
| @@ -25,6 +25,49 @@ dependencies { | |||
| androidTestImplementation 'org.hamcrest:hamcrest-all:1.3' | |||
| } | |||
| android { | |||
| compileSdk 33 | |||
| ndkVersion "25.1.8937393" | |||
| namespace "com.reecedunn.espeak" | |||
| defaultConfig { | |||
| minSdk 19 | |||
| targetSdk 33 | |||
| versionCode 22 | |||
| versionName "1.52-dev" | |||
| externalNativeBuild { | |||
| cmake { | |||
| arguments "-DUSE_ASYNC:BOOL=OFF", "-DUSE_MBROLA:BOOL=OFF" | |||
| targets "ttsespeak", "espeak-data" | |||
| } | |||
| } | |||
| } | |||
| externalNativeBuild { | |||
| cmake { | |||
| path "jni/CMakeLists.txt" | |||
| version "3.22.1" | |||
| } | |||
| } | |||
| sourceSets { | |||
| main { | |||
| manifest.srcFile 'AndroidManifest.xml' | |||
| java.srcDirs = ['src'] | |||
| res.srcDirs = ['res'] | |||
| } | |||
| androidTest.setRoot('eSpeakTests') | |||
| androidTest { | |||
| java.srcDirs = ['eSpeakTests/src'] | |||
| } | |||
| } | |||
| lint { | |||
| abortOnError false | |||
| } | |||
| } | |||
| tasks.register('checkData') { | |||
| doFirst { | |||
| assert file("../espeak-ng-data/en_dict").exists() | |||
| @@ -37,13 +80,12 @@ tasks.register('checkData') { | |||
| } | |||
| tasks.register('createDataArchive', Zip) { | |||
| dependsOn tasks.checkData | |||
| preserveFileTimestamps = false | |||
| reproducibleFileOrder = true | |||
| archiveFileName = "espeakdata.zip" | |||
| destinationDirectory = file("res/raw") | |||
| from("../espeak-ng-data/") { | |||
| from("build/generated/espeak-ng-data/") { | |||
| into "espeak-ng-data" | |||
| } | |||
| } | |||
| @@ -61,40 +103,10 @@ tasks.register('createDataVersion', Copy) { | |||
| rename { return 'espeakdata_version' } | |||
| into file("./res/raw") | |||
| } | |||
| preBuild.dependsOn createDataVersion | |||
| android { | |||
| compileSdk 33 | |||
| ndkVersion "25.1.8937393" | |||
| namespace "com.reecedunn.espeak" | |||
| defaultConfig { | |||
| minSdk 19 | |||
| targetSdk 30 | |||
| versionCode 22 | |||
| versionName "1.52-dev" | |||
| } | |||
| externalNativeBuild { | |||
| ndkBuild { | |||
| path "jni/Android.mk" | |||
| } | |||
| } | |||
| sourceSets { | |||
| main { | |||
| manifest.srcFile 'AndroidManifest.xml' | |||
| java.srcDirs = ['src'] | |||
| res.srcDirs = ['res'] | |||
| } | |||
| androidTest.setRoot('eSpeakTests') | |||
| androidTest { | |||
| java.srcDirs = ['eSpeakTests/src'] | |||
| } | |||
| } | |||
| lint { | |||
| abortOnError false | |||
| } | |||
| project.afterEvaluate { | |||
| tasks.checkData.dependsOn(externalNativeBuildDebug) | |||
| tasks.createDataArchive.dependsOn(externalNativeBuildDebug) | |||
| javaPreCompileDebug.dependsOn(tasks.createDataVersion) | |||
| javaPreCompileRelease.dependsOn(tasks.createDataVersion) | |||
| } | |||
| @@ -1,83 +0,0 @@ | |||
| LOCAL_PATH:= $(call my-dir) | |||
| include $(CLEAR_VARS) | |||
| #LOCAL_CFLAGS = -std=c11 # speechplayer is c++ code | |||
| # ucd-tools wide-character compatibility support: | |||
| UCDTOOLS_SRC_PATH := ../../src/ucd-tools/src | |||
| UCDTOOLS_SRC_FILES := \ | |||
| $(subst $(LOCAL_PATH)/$(UCDTOOLS_SRC_PATH),$(UCDTOOLS_SRC_PATH),$(wildcard $(LOCAL_PATH)/$(UCDTOOLS_SRC_PATH)/*.c*)) | |||
| LOCAL_SRC_FILES += $(UCDTOOLS_SRC_FILES) | |||
| SPEECHPLAYER_SRC_FILES := \ | |||
| ../../src/speechPlayer/src/frame.cpp \ | |||
| ../../src/speechPlayer/src/speechPlayer.cpp \ | |||
| ../../src/speechPlayer/src/speechWaveGenerator.cpp | |||
| LOCAL_SRC_FILES += $(SPEECHPLAYER_SRC_FILES) | |||
| ESPEAK_SOURCES := \ | |||
| src/libespeak-ng/common.c \ | |||
| src/libespeak-ng/compiledata.c \ | |||
| src/libespeak-ng/compiledict.c \ | |||
| src/libespeak-ng/compilembrola.c \ | |||
| src/libespeak-ng/dictionary.c \ | |||
| src/libespeak-ng/encoding.c \ | |||
| src/libespeak-ng/error.c \ | |||
| src/libespeak-ng/espeak_api.c \ | |||
| src/libespeak-ng/ieee80.c \ | |||
| src/libespeak-ng/intonation.c \ | |||
| src/libespeak-ng/klatt.c \ | |||
| src/libespeak-ng/langopts.c \ | |||
| src/libespeak-ng/mnemonics.c \ | |||
| src/libespeak-ng/numbers.c \ | |||
| src/libespeak-ng/phoneme.c \ | |||
| src/libespeak-ng/phonemelist.c \ | |||
| src/libespeak-ng/readclause.c \ | |||
| src/libespeak-ng/setlengths.c \ | |||
| src/libespeak-ng/soundicon.c \ | |||
| src/libespeak-ng/spect.c \ | |||
| src/libespeak-ng/speech.c \ | |||
| src/libespeak-ng/sPlayer.c \ | |||
| src/libespeak-ng/ssml.c \ | |||
| src/libespeak-ng/synthdata.c \ | |||
| src/libespeak-ng/synthesize.c \ | |||
| src/libespeak-ng/synth_mbrola.c \ | |||
| src/libespeak-ng/translate.c \ | |||
| src/libespeak-ng/translateword.c \ | |||
| src/libespeak-ng/tr_languages.c \ | |||
| src/libespeak-ng/voices.c \ | |||
| src/libespeak-ng/wavegen.c | |||
| ESPEAK_SRC_PATH := ../../src | |||
| ESPEAK_SRC_FILES := \ | |||
| $(subst src/,$(ESPEAK_SRC_PATH)/,$(ESPEAK_SOURCES)) | |||
| LOCAL_CFLAGS += -DINCLUDE_KLATT -DINCLUDE_SPEECHPLAYER -DINCLUDE_SONIC -DHAVE_ENDIAN_H | |||
| LOCAL_SRC_FILES += \ | |||
| $(filter-out $(BLACKLIST_SRC_FILES),$(ESPEAK_SRC_FILES)) | |||
| # JNI | |||
| LOCAL_SRC_FILES += \ | |||
| $(subst $(LOCAL_PATH)/jni,jni,$(wildcard $(LOCAL_PATH)/jni/*.c)) | |||
| # Common | |||
| LOCAL_C_INCLUDES += \ | |||
| $(LOCAL_PATH)/include \ | |||
| $(LOCAL_PATH)/$(UCDTOOLS_SRC_PATH)/include \ | |||
| $(LOCAL_PATH)/../../src/speechPlayer/include \ | |||
| $(LOCAL_PATH)/$(ESPEAK_SRC_PATH)/include \ | |||
| $(LOCAL_PATH)/$(ESPEAK_SRC_PATH)/include/compat | |||
| LOCAL_LDLIBS := \ | |||
| -llog | |||
| LOCAL_MODULE := libttsespeak | |||
| LOCAL_MODULE_TAGS := optional | |||
| LOCAL_PRELINK_MODULE := false | |||
| include $(BUILD_SHARED_LIBRARY) | |||
| @@ -0,0 +1,26 @@ | |||
| cmake_minimum_required(VERSION 3.8) | |||
| project(espeak-android) | |||
| add_subdirectory(../../ espeakng) | |||
| add_custom_target( | |||
| espeak-data | |||
| COMMAND ${CMAKE_COMMAND} -B${CMAKE_CURRENT_BINARY_DIR}/../espeak-data ${CMAKE_CURRENT_SOURCE_DIR}/../../ | |||
| COMMAND ${CMAKE_COMMAND} --build ${CMAKE_CURRENT_BINARY_DIR}/../espeak-data --target data | |||
| COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_BINARY_DIR}/../espeak-data/espeak-ng-data ${CMAKE_SOURCE_DIR}/../build/generated/espeak-ng-data | |||
| ) | |||
| message(STATUS "Data: ${CMAKE_CURRENT_SOURCE_DIR}") | |||
| find_library(A_LOG log) | |||
| add_library(ttsespeak SHARED | |||
| jni/eSpeakService.c | |||
| ) | |||
| target_include_directories(ttsespeak PRIVATE | |||
| include | |||
| ) | |||
| target_link_libraries(ttsespeak PRIVATE | |||
| espeak-ng ${A_LOG} | |||
| ) | |||
| @@ -26,6 +26,7 @@ | |||
| #include <unistd.h> | |||
| #include <stdlib.h> | |||
| #include <stdbool.h> | |||
| #include <string.h> | |||
| #include <jni.h> | |||
| #include <espeak/speak_lib.h> | |||
| @@ -0,0 +1,14 @@ | |||
| include(CheckSymbolExists) | |||
| check_symbol_exists(mkstemp "stdlib.h" HAVE_MKSTEMP) | |||
| option(USE_MBROLA "Use mbrola for speech synthesis" ${HAVE_MBROLA}) | |||
| option(USE_LIBSONIC "Use libsonit for faster speech rates" ${HAVE_LIBSONIC}) | |||
| option(USE_LIBPCAUDIO "Use libPcAudio for sound output" ${HAVE_LIBPCAUDIO}) | |||
| option(USE_KLATT "Use klatt for speech synthesis" ON) | |||
| option(USE_SPEECHPLAYER "Use speech-player for speech synthesis" ON) | |||
| if (HAVE_PTHREAD) | |||
| option(USE_ASYNC "Support asynchronous speech synthesis" ON) | |||
| else() | |||
| set(USE_ASYNC OFF) | |||
| endif() | |||
| @@ -0,0 +1,168 @@ | |||
| list(APPEND _dict_compile_list | |||
| af am an ar as az | |||
| ba be bg bn bpy bs | |||
| ca chr cmn cs cv cy | |||
| da de | |||
| el en eo es et eu | |||
| fa fi fr | |||
| ga gd gn grc gu | |||
| hak haw he hi hr ht hu hy | |||
| ia id io is it | |||
| ja jbo | |||
| ka kk kl kn kok ko ku ky | |||
| la lb lfn lt lv | |||
| mi mk ml mr ms mto mt my | |||
| nci ne nl nog no | |||
| om or | |||
| pap pa piqd pl pt py | |||
| qdb quc qu qya | |||
| ro ru | |||
| sd shn si sjn sk sl smj sq sr sv sw | |||
| ta te th tk tn tr tt | |||
| ug uk ur uz | |||
| vi | |||
| yue | |||
| ) | |||
| list(APPEND _mbrola_lang_list | |||
| af1 ar1 ar2 | |||
| ca cmn cr1 cs | |||
| de2 de4 de6 de8 | |||
| ee1 en1 es es3 es4 | |||
| fr | |||
| gr1 gr2 grc-de6 | |||
| he hn1 hu1 | |||
| ic1 id1 in ir1 it1 it3 | |||
| jp | |||
| la1 lt | |||
| ma1 mx1 mx2 | |||
| nl nz1 | |||
| pl1 pt1 ptbr ptbr4 | |||
| ro1 | |||
| sv sv2 | |||
| tl1 tr1 | |||
| us us3 | |||
| vz | |||
| ) | |||
| set(DATA_DIST_ROOT ${CMAKE_CURRENT_BINARY_DIR}) | |||
| set(DATA_DIST_DIR ${DATA_DIST_ROOT}/espeak-ng-data) | |||
| set(PHONEME_TMP_DIR ${DATA_DIST_ROOT}/phsource) | |||
| set(DICT_TMP_DIR ${DATA_DIST_ROOT}/dictsource) | |||
| set(DATA_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/espeak-ng-data) | |||
| set(PHONEME_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/phsource) | |||
| set(DICT_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/dictsource) | |||
| file(MAKE_DIRECTORY "${DATA_DIST_DIR}") | |||
| file(MAKE_DIRECTORY "${DICT_TMP_DIR}") | |||
| file(COPY "${DATA_SRC_DIR}/lang" DESTINATION "${DATA_DIST_DIR}") | |||
| file(COPY "${DATA_SRC_DIR}/voices/!v" DESTINATION "${DATA_DIST_DIR}/voices") | |||
| file(COPY "${PHONEME_SRC_DIR}" DESTINATION "${DATA_DIST_ROOT}") | |||
| set(ESPEAK_RUN_ENV ${CMAKE_COMMAND} -E env "ESPEAK_DATA_PATH=${DATA_DIST_ROOT}") | |||
| set(ESPEAK_RUN_CMD ${ESPEAK_RUN_ENV} $ENV{VALGRIND} "$<TARGET_FILE:espeak-ng-bin>") | |||
| add_custom_command( | |||
| OUTPUT "${DATA_DIST_DIR}/intonations" | |||
| COMMAND ${ESPEAK_RUN_CMD} --compile-intonations | |||
| WORKING_DIRECTORY "${PHONEME_SRC_DIR}" | |||
| COMMENT "Compile intonations" | |||
| DEPENDS | |||
| "$<TARGET_FILE:espeak-ng-bin>" | |||
| "${PHONEME_SRC_DIR}/intonation" | |||
| ) | |||
| set(_phon_deps "") | |||
| function(check_phon_deps _file) | |||
| set(_file "${PHONEME_SRC_DIR}/${_file}") | |||
| list(APPEND _phon_deps "${_file}") | |||
| file(STRINGS "${_file}" _phon_incs REGEX "include .+") | |||
| list(TRANSFORM _phon_incs REPLACE "^[ \t]*include[ \t]+" "") | |||
| foreach(_inc ${_phon_incs}) | |||
| check_phon_deps(${_inc}) | |||
| endforeach(_inc) | |||
| set(_phon_deps ${_phon_deps} PARENT_SCOPE) | |||
| endfunction(check_phon_deps) | |||
| check_phon_deps("phonemes") | |||
| add_custom_command( | |||
| OUTPUT | |||
| "${DATA_DIST_DIR}/phondata" | |||
| "${DATA_DIST_DIR}/phondata-manifest" | |||
| "${DATA_DIST_DIR}/phonindex" | |||
| "${DATA_DIST_DIR}/phontab" | |||
| COMMAND ${ESPEAK_RUN_CMD} --compile-phonemes | |||
| WORKING_DIRECTORY "${PHONEME_SRC_DIR}" | |||
| COMMENT "Compile phonemes" | |||
| DEPENDS | |||
| "$<TARGET_FILE:espeak-ng-bin>" | |||
| ${_phon_deps} | |||
| ) | |||
| list(APPEND _dict_targets) | |||
| list(APPEND _mbr_targets) | |||
| foreach(_dict_name ${_dict_compile_list}) | |||
| set(_dict_target "${DATA_DIST_DIR}/${_dict_name}_dict") | |||
| set(_dict_deps "") | |||
| list(APPEND _dict_targets ${_dict_target}) | |||
| list(APPEND _dict_deps | |||
| "${DICT_SRC_DIR}/${_dict_name}_rules" | |||
| "${DICT_SRC_DIR}/${_dict_name}_list" | |||
| ) | |||
| if(EXISTS "${DICT_SRC_DIR}/extra/${_dict_name}_listx") | |||
| option(EXTRA_${_dict_name} "Compile extra ${_dict_name} dictionary" ON) | |||
| if(EXTRA_${_dict_name}) | |||
| list(APPEND _dict_deps "${DICT_SRC_DIR}/extra/${_dict_name}_listx") | |||
| else() | |||
| file(REMOVE "${DICT_TMP_DIR}/${_dict_name}_listx") | |||
| endif() | |||
| elseif(EXISTS "${DICT_SRC_DIR}/${_dict_name}_listx") | |||
| list(APPEND _dict_deps "${DICT_SRC_DIR}/${_dict_name}_listx") | |||
| endif() | |||
| if(EXISTS "${DICT_SRC_DIR}/${_dict_name}_emoji") | |||
| list(APPEND _dict_deps "${DICT_SRC_DIR}/${_dict_name}_emoji") | |||
| endif() | |||
| add_custom_command( | |||
| OUTPUT "${_dict_target}" | |||
| COMMAND ${CMAKE_COMMAND} -E copy ${_dict_deps} "${DICT_TMP_DIR}/" | |||
| COMMAND ${ESPEAK_RUN_CMD} --compile=${_dict_name} | |||
| WORKING_DIRECTORY "${DICT_TMP_DIR}" | |||
| DEPENDS | |||
| "$<TARGET_FILE:espeak-ng-bin>" | |||
| "${DATA_DIST_DIR}/phondata" | |||
| "${DATA_DIST_DIR}/intonations" | |||
| ${_dict_deps} | |||
| ) | |||
| endforeach() | |||
| if (HAVE_MBROLA AND USE_MBROLA) | |||
| file(COPY "${DATA_SRC_DIR}/voices/mb" DESTINATION "${DATA_DIST_DIR}/voices") | |||
| file(MAKE_DIRECTORY "${DATA_DIST_DIR}/mbrola_ph") | |||
| foreach(_mbl ${_mbrola_lang_list}) | |||
| set(_mbl_src "${PHONEME_SRC_DIR}/mbrola/${_mbl}") | |||
| set(_mbl_out "${DATA_DIST_DIR}/mbrola_ph/${_mbl}_phtrans") | |||
| list(APPEND _mbr_targets ${_mbl_out}) | |||
| add_custom_command( | |||
| OUTPUT "${_mbl_out}" | |||
| COMMAND ${ESPEAK_RUN_CMD} --compile-mbrola="${_mbl_src}" | |||
| DEPENDS "$<TARGET_FILE:espeak-ng-bin>" "${_mbl_src}" | |||
| ) | |||
| endforeach(_mbl) | |||
| endif() | |||
| add_custom_target( | |||
| data ALL | |||
| DEPENDS | |||
| "${DATA_DIST_DIR}/intonations" | |||
| "${DATA_DIST_DIR}/phondata" | |||
| ${_dict_targets} | |||
| ${_mbr_targets} | |||
| ) | |||
| install(DIRECTORY ${DATA_DIST_DIR} DESTINATION share) | |||
| @@ -0,0 +1,33 @@ | |||
| find_library(SONIC_LIB sonic) | |||
| find_path(SONIC_INC "sonic.h") | |||
| find_library(PCAUDIO_LIB pcaudio) | |||
| find_path(PCAUDIO_INC "pcaudiolib/audio.h") | |||
| find_library(PTHREAD_LIB pthread) | |||
| find_program(MBROLA_BIN mbrola) | |||
| include(FetchContent) | |||
| if (PTHREAD_LIB) | |||
| set(HAVE_PTHREAD ON) | |||
| endif(PTHREAD_LIB) | |||
| if (MBROLA_BIN) | |||
| set(HAVE_MBROLA ON) | |||
| endif(MBROLA_BIN) | |||
| if (SONIC_LIB AND SONIC_INC) | |||
| set(HAVE_LIBSONIC ON) | |||
| else() | |||
| FetchContent_Declare(sonic-git | |||
| GIT_REPOSITORY https://github.com/waywardgeek/sonic.git | |||
| GIT_TAG fbf75c3d6d846bad3bb3d456cbc5d07d9fd8c104 | |||
| ) | |||
| FetchContent_MakeAvailable(sonic-git) | |||
| FetchContent_GetProperties(sonic-git) | |||
| add_library(sonic OBJECT ${sonic-git_SOURCE_DIR}/sonic.c) | |||
| target_include_directories(sonic PUBLIC ${sonic-git_SOURCE_DIR}) | |||
| set(HAVE_LIBSONIC ON) | |||
| set(SONIC_LIB sonic) | |||
| set(SONIC_INC ${sonic-git_SOURCE_DIR}) | |||
| endif() | |||
| if (PCAUDIO_LIB AND PCAUDIO_INC) | |||
| set(HAVE_LIBPCAUDIO ON) | |||
| endif() | |||
| @@ -0,0 +1,17 @@ | |||
| list(APPEND CPACK_SOURCE_IGNORE_FILES | |||
| /\.git/ | |||
| /\.gitignore | |||
| /\.github/ | |||
| /\.tx/ | |||
| /\.travis.yml | |||
| /_layouts/ | |||
| /android/ | |||
| /build/ | |||
| /chromium_extension/ | |||
| /data/ | |||
| /docs/ | |||
| /emscripten/ | |||
| /fastlane/ | |||
| /tools/ | |||
| /vim/ | |||
| ) | |||
| @@ -0,0 +1,25 @@ | |||
| add_library(espeak-include INTERFACE) | |||
| target_include_directories(espeak-include INTERFACE include include/compat) | |||
| add_subdirectory(ucd-tools) | |||
| add_subdirectory(speechPlayer) | |||
| add_subdirectory(libespeak-ng) | |||
| add_executable(espeak-ng-bin espeak-ng.c) | |||
| set_target_properties(espeak-ng-bin PROPERTIES OUTPUT_NAME espeak-ng) | |||
| target_link_libraries( | |||
| espeak-ng-bin PRIVATE espeak-ng espeak-ng-config | |||
| ) | |||
| if (MSVC) | |||
| target_sources(espeak-ng-bin PRIVATE compat/getopt.c) | |||
| endif() | |||
| if (NOT WIN32) | |||
| add_custom_target( | |||
| speak-ng ALL | |||
| ${CMAKE_COMMAND} -E create_symlink espeak-ng ${CMAKE_CURRENT_BINARY_DIR}/speak-ng | |||
| COMMENT "Link espeak-ng to speak-ng" | |||
| DEPENDS espeak-ng-bin | |||
| ) | |||
| endif() | |||
| install(TARGETS espeak-ng-bin) | |||
| install(DIRECTORY include/espeak include/espeak-ng TYPE INCLUDE) | |||
| @@ -0,0 +1,105 @@ | |||
| set(ESPEAK_CONFIG_DIR ${CMAKE_CURRENT_BINARY_DIR}/include) | |||
| set(ESPEAK_CONFIG_H ${ESPEAK_CONFIG_DIR}/config.h) | |||
| configure_file(config.h.in ${ESPEAK_CONFIG_H}) | |||
| add_library(espeak-ng-config INTERFACE) | |||
| target_include_directories(espeak-ng-config INTERFACE ${ESPEAK_CONFIG_DIR}) | |||
| add_library(espeak-ng | |||
| common.c | |||
| mnemonics.c | |||
| error.c | |||
| ieee80.c | |||
| compiledata.c | |||
| compiledict.c | |||
| dictionary.c | |||
| encoding.c | |||
| intonation.c | |||
| langopts.c | |||
| numbers.c | |||
| phoneme.c | |||
| phonemelist.c | |||
| readclause.c | |||
| setlengths.c | |||
| soundicon.c | |||
| spect.c | |||
| ssml.c | |||
| synthdata.c | |||
| synthesize.c | |||
| tr_languages.c | |||
| translate.c | |||
| translateword.c | |||
| voices.c | |||
| wavegen.c | |||
| speech.c | |||
| espeak_api.c | |||
| ) | |||
| if (NOT MSVC) | |||
| target_compile_options(espeak-ng PRIVATE | |||
| "-fPIC" | |||
| "-fvisibility=hidden" | |||
| "-fno-exceptions" | |||
| "-fwrapv" | |||
| "-pedantic" | |||
| "-Wunused-parameter" | |||
| "-Wunused" | |||
| "-Wuninitialized" | |||
| "-Wreturn-type" | |||
| "-Wmissing-prototypes" | |||
| "-Wint-conversion" | |||
| "-Wimplicit" | |||
| ) | |||
| endif() | |||
| target_compile_definitions(espeak-ng PRIVATE "LIBESPEAK_NG_EXPORT=1") | |||
| if (NOT BUILD_SHARED_LIBS) | |||
| target_compile_definitions(espeak-ng INTERFACE "LIBESPEAK_NG_EXPORT=1") | |||
| endif() | |||
| if (USE_ASYNC) | |||
| target_sources(espeak-ng PRIVATE | |||
| event.c | |||
| fifo.c | |||
| espeak_command.c | |||
| ) | |||
| endif(USE_ASYNC) | |||
| if (USE_MBROLA) | |||
| target_sources(espeak-ng PRIVATE | |||
| mbrowrap.c | |||
| compilembrola.c | |||
| synth_mbrola.c | |||
| ) | |||
| endif(USE_MBROLA) | |||
| if (USE_KLATT) | |||
| target_sources(espeak-ng PRIVATE klatt.c) | |||
| endif(USE_KLATT) | |||
| if (USE_SPEECHPLAYER) | |||
| target_sources(espeak-ng PRIVATE sPlayer.c) | |||
| target_link_libraries(espeak-ng PRIVATE speechPlayer) | |||
| endif(USE_SPEECHPLAYER) | |||
| if (HAVE_LIBSONIC AND USE_LIBSONIC) | |||
| target_link_libraries(espeak-ng PRIVATE ${SONIC_LIB}) | |||
| target_include_directories(espeak-ng PRIVATE ${SONIC_INC}) | |||
| endif() | |||
| if (HAVE_LIBPCAUDIO AND USE_LIBPCAUDIO) | |||
| target_link_libraries(espeak-ng PRIVATE ${PCAUDIO_LIB}) | |||
| target_include_directories(espeak-ng PRIVATE ${PCAUDIO_INC}) | |||
| endif() | |||
| target_link_libraries(espeak-ng PRIVATE espeak-ng-config ucd) | |||
| if (NOT MSVC) | |||
| target_link_libraries(espeak-ng PRIVATE m) | |||
| endif() | |||
| target_link_libraries(espeak-ng PUBLIC espeak-include) | |||
| install(TARGETS espeak-ng LIBRARY) | |||
| @@ -0,0 +1,10 @@ | |||
| #cmakedefine01 HAVE_MKSTEMP | |||
| #cmakedefine01 USE_ASYNC | |||
| #cmakedefine01 USE_KLATT | |||
| #cmakedefine01 USE_LIBPCAUDIO | |||
| #cmakedefine01 USE_LIBSONIC | |||
| #cmakedefine01 USE_MBROLA | |||
| #cmakedefine01 USE_SPEECHPLAYER | |||
| #define PACKAGE_VERSION "${PROJECT_VERSION}" | |||
| @@ -0,0 +1,10 @@ | |||
| add_library(speechPlayer STATIC | |||
| src/frame.cpp | |||
| src/speechPlayer.cpp | |||
| src/speechWaveGenerator.cpp | |||
| ) | |||
| target_include_directories(speechPlayer PUBLIC include) | |||
| if(NOT MSVC) | |||
| target_compile_options(speechPlayer PRIVATE "-fPIC") | |||
| endif() | |||
| install(TARGETS speechPlayer ARCHIVE) | |||
| @@ -0,0 +1,10 @@ | |||
| add_library(ucd STATIC | |||
| src/case.c | |||
| src/categories.c | |||
| src/ctype.c | |||
| src/proplist.c | |||
| src/scripts.c | |||
| src/tostring.c | |||
| ) | |||
| target_include_directories(ucd PUBLIC src/include) | |||
| install(TARGETS ucd ARCHIVE) | |||
| @@ -0,0 +1,73 @@ | |||
| include(CTest) | |||
| list(APPEND _binary_tests) | |||
| macro(compiled_test _test_name) | |||
| add_executable(test_${_test_name} | |||
| $<TARGET_OBJECTS:espeak-ng> | |||
| ${_test_name}.c | |||
| ) | |||
| target_link_libraries(test_${_test_name} PRIVATE | |||
| $<TARGET_PROPERTY:espeak-ng,LINK_LIBRARIES> | |||
| ) | |||
| target_include_directories( | |||
| test_${_test_name} PRIVATE | |||
| $<TARGET_PROPERTY:espeak-ng,SOURCE_DIR> | |||
| $<TARGET_PROPERTY:espeak-ng,SOURCE_DIR>/include/compat | |||
| $<TARGET_PROPERTY:espeak-ng,INTERFACE_INCLUDE_DIRECTORIES> | |||
| $<TARGET_PROPERTY:espeak-ng-config,INTERFACE_INCLUDE_DIRECTORIES> | |||
| ) | |||
| add_dependencies(test_${_test_name} data) | |||
| add_test( | |||
| NAME ${_test_name} | |||
| COMMAND ${ESPEAK_RUN_ENV} $<TARGET_FILE:test_${_test_name}> | |||
| WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/.. | |||
| ) | |||
| list(APPEND _binary_tests test_${_test_name}) | |||
| endmacro(compiled_test) | |||
| find_program(SHELL bash) | |||
| macro(shell_test _test_name) | |||
| add_test( | |||
| NAME ${_test_name} | |||
| COMMAND ${ESPEAK_RUN_ENV} ESPEAK_BIN=$<TARGET_FILE:espeak-ng-bin> ${SHELL} ${CMAKE_CURRENT_SOURCE_DIR}/${_test_name}.test | |||
| WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/.. | |||
| ) | |||
| endmacro(shell_test) | |||
| compiled_test(api) | |||
| compiled_test(encoding) | |||
| compiled_test(ieee80) | |||
| compiled_test(readclause) | |||
| if (SHELL AND UNIX) | |||
| shell_test(bom) | |||
| shell_test(non-executable-files-with-executable-bit) | |||
| shell_test(cmd_options) | |||
| shell_test(dictionary) | |||
| shell_test(language-numbers-cardinal) | |||
| shell_test(language-numbers-ordinal) | |||
| shell_test(language-phonemes) | |||
| shell_test(language-pronunciation) | |||
| shell_test(language-replace) | |||
| shell_test(ssml) | |||
| shell_test(translate) | |||
| shell_test(variants) | |||
| shell_test(voices) | |||
| # shell_test(windows-data) | |||
| # shell_test(windows-installer) | |||
| if (USE_KLATT) | |||
| shell_test(klatt) | |||
| endif() | |||
| if (USE_MBROLA) | |||
| shell_test(mbrola) | |||
| endif() | |||
| endif() | |||
| add_custom_target(tests DEPENDS ${_binary_tests}) | |||
| @@ -8,7 +8,8 @@ echo -n "testing for Byte Order Marks in source files ... " | |||
| # TODO checking for other encodings (e.g. UTF-16, UTF-32, UTF-7) needs more elaborate search, | |||
| # otherwise it shows many false positives | |||
| grep -ErlI $'\xEF\xBB\xBF' * | tee tests/bom.check >/dev/null # UTF-8 | |||
| cd $(dirname $0)/.. | |||
| grep -ErlI $'\xEF\xBB\xBF' * | grep -v '^build/' | tee tests/bom.check >/dev/null # UTF-8 | |||
| if [ -s tests/bom.check ] ; then | |||
| echo "found:" | |||
| @@ -19,4 +20,3 @@ else | |||
| echo "none found" | |||
| true | |||
| fi | |||
| @@ -8,7 +8,7 @@ is_hash | |||
| # read column 5 (File) of espeak-ng --voices, skip the directory | |||
| echo "checking if all supported languages have phoneme tests ..." | |||
| for lang in $(ESPEAK_DATA_PATH=`pwd` LD_LIBRARY_PATH=src:${LD_LIBRARY_PATH} src/espeak-ng --voices | awk '{print $5}' | cut -d "/" -f 2-2 | tail -n+2); | |||
| do if ! grep -q "test_phwav $lang" tests/language-phonemes.test | |||
| do if ! grep -q "test_phwav $lang" $0 | |||
| then | |||
| echo "$lang missing a phoneme test in tests/language-phonemes.test"; | |||
| exit 1; | |||
| @@ -2,8 +2,10 @@ | |||
| echo -n "testing files for executable bits that shouldn't be executable ... " | |||
| cd $(dirname $0)/.. | |||
| find * -executable -type f | \ | |||
| grep -vE "compile|config\.(guess|status|sub)|configure|depcomp|install-sh|libtool|missing" | # Ignore autotools output \ | |||
| grep -vE "build" | # Ignore cmake output \ | |||
| grep -vE ".*\.test|tests/common|src(/\.libs)?/(e?speak-ng|.*\.so\..*)|src/\.libs/lt-espeak-ng|android" | # Ignore built programs and libraries \ | |||
| grep -vE ".*\.sh|tools/emoji" | # Ignore helper scripts \ | |||
| grep -vE "src/ucd-tools/tools/(.*\.py|mkencodingtable)" | # Ignore ucd-tools helper scripts \ | |||
| @@ -21,4 +23,3 @@ else | |||
| echo "none found" | |||
| true | |||
| fi | |||
| @@ -36,8 +36,8 @@ test_ssml() { | |||
| diff expected.txt actual.txt || exit 1 | |||
| } | |||
| for i in `ls tests/ssml/*.ssml` ; do test_ssml $i; done | |||
| for i in `ls tests/ssml/*.ssml2` ; do test_ssml $i punct; done | |||
| for i in `dirname $0`/ssml/*.ssml ; do test_ssml $i; done | |||
| for i in `dirname $0`/ssml/*.ssml2 ; do test_ssml $i punct; done | |||
| test_ssml_audio "<prosody>" 88fccb35536158f25f4ae44a03fb005fef95c99b "<speak><prosody rate=\"x-slow\" pitch=\"low\"> Slow and low </prosody><prosody rate=\"x-fast\" pitch=\"x-high\"> Fast and high.</prosody></speak>" | |||
| # #410 is a bug in SSML. Sentence termination causes prosody stack to misfunction. | |||