Unverified Commit 676ed7c1 authored by Martin Weinelt's avatar Martin Weinelt
Browse files
parent bc541d82
Loading
Loading
Loading
Loading
+201 −0
Original line number Diff line number Diff line
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2db7493..c8464ff 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -4,93 +4,129 @@
 cmake_minimum_required(VERSION 3.26)
 project(piper LANGUAGES C CXX)
 
+set(UCD_STATIC_LIB "" CACHE FILEPATH "Path to libucd.a if built with system espeak-ng")
+
 include(ExternalProject)
 
 # scikit-build-core will forward Python_* variables
 find_package(Python COMPONENTS Development.Module Development.SABIModule REQUIRED)
 
-# Install location for espeak-ng
-set(ESPEAKNG_BUILD_DIR ${CMAKE_BINARY_DIR}/espeak_ng)
-set(ESPEAKNG_INSTALL_DIR ${CMAKE_BINARY_DIR}/espeak_ng-install)
+# Try to find espeak-ng using pkg-config, if available
+find_package(PkgConfig QUIET)
 
-if(WIN32)
-    # Special handling for Windows
-    set(ESPEAKNG_STATIC_LIB ${ESPEAKNG_INSTALL_DIR}/lib/espeak-ng.lib)
-    set(UCD_STATIC_LIB ${ESPEAKNG_BUILD_DIR}/src/espeak_ng_external-build/src/ucd-tools/ucd.lib)
-else()
-    set(ESPEAKNG_STATIC_LIB ${ESPEAKNG_INSTALL_DIR}/lib/libespeak-ng.a)
-    set(UCD_STATIC_LIB ${ESPEAKNG_BUILD_DIR}/src/espeak_ng_external-build/src/ucd-tools/libucd.a)
+if (PKG_CONFIG_FOUND)
+    pkg_check_modules(ESPEAKNG QUIET espeak-ng)
 endif()
 
-ExternalProject_Add(espeak_ng_external
-    GIT_REPOSITORY https://github.com/espeak-ng/espeak-ng.git
-    GIT_TAG 212928b394a96e8fd2096616bfd54e17845c48f6  # 2025-Mar-22
-    PREFIX ${ESPEAKNG_BUILD_DIR}
-    CMAKE_ARGS
-        -DCMAKE_INSTALL_PREFIX=${ESPEAKNG_INSTALL_DIR}
-        -DBUILD_SHARED_LIBS:BOOL=OFF
-        -DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=ON
-        -DUSE_ASYNC:BOOL=OFF
-        -DUSE_MBROLA:BOOL=OFF
-        -DUSE_LIBSONIC:BOOL=OFF
-        -DUSE_LIBPCAUDIO:BOOL=OFF
-        -DUSE_KLATT:BOOL=OFF
-        -DUSE_SPEECHPLAYER:BOOL=OFF
-        -DEXTRA_cmn:BOOL=ON
-        -DEXTRA_ru:BOOL=ON
-        # Need to explicitly add ucd include directory for CI
-        "-DCMAKE_C_FLAGS=-D_FILE_OFFSET_BITS=64 -I${ESPEAKNG_BUILD_DIR}/src/espeak_ng_external/src/ucd-tools/src/include"
-    BUILD_BYPRODUCTS
-        ${ESPEAKNG_STATIC_LIB}
-        ${UCD_STATIC_LIB}
-    UPDATE_DISCONNECTED TRUE
-)
-
-include_directories(
-    ${ESPEAKNG_INSTALL_DIR}/include
-)
-
 # espeak bridge
 add_library(espeakbridge MODULE
     src/piper/espeakbridge.c
 )
 
-add_dependencies(espeakbridge espeak_ng_external)
-target_link_libraries(espeakbridge
-    ${ESPEAKNG_STATIC_LIB}
-    ${UCD_STATIC_LIB}
+# scikit-build-core forwards this
+target_link_libraries(espeakbridge PRIVATE
     Python::SABIModule
 )
-target_include_directories(espeakbridge PRIVATE
-    ${ESPEAKNG_INSTALL_DIR}/include
-)
 
-if(WIN32)
-    # Fix dll thunk issue (__imp_SYMBOL not found)
-    target_compile_definitions(espeakbridge PRIVATE LIBESPEAK_NG_EXPORT)
 
-    # Fix .dll suffix
-    set_target_properties(espeakbridge PROPERTIES
-        PREFIX ""
-        SUFFIX ".pyd"
+if (ESPEAKNG_FOUND)
+    message(STATUS "Found system espeak-ng via pkg-config")
+
+    target_include_directories(espeakbridge PRIVATE
+        ${ESPEAKNG_INCLUDE_DIRS}
+    )
+    target_link_directories(espeakbridge PRIVATE
+        ${ESPEAKNG_LIBRARY_DIRS}
+    )
+    target_link_libraries(espeakbridge PRIVATE
+        ${ESPEAKNG_LIBRARIES}
+        ${UCD_STATIC_LIB}
     )
+
+    install(TARGETS espeakbridge
+        LIBRARY DESTINATION .
+        RUNTIME DESTINATION .
+    )
+
 else()
-    set_target_properties(espeakbridge PROPERTIES
-        PREFIX ""
+    # Install location for espeak-ng
+    set(ESPEAKNG_BUILD_DIR ${CMAKE_BINARY_DIR}/espeak_ng)
+    set(ESPEAKNG_INSTALL_DIR ${CMAKE_BINARY_DIR}/espeak_ng-install)
+
+    if(WIN32)
+        # Special handling for Windows
+        set(ESPEAKNG_STATIC_LIB ${ESPEAKNG_INSTALL_DIR}/lib/espeak-ng.lib)
+        set(UCD_STATIC_LIB ${ESPEAKNG_BUILD_DIR}/src/espeak_ng_external-build/src/ucd-tools/ucd.lib)
+    else()
+        set(ESPEAKNG_STATIC_LIB ${ESPEAKNG_INSTALL_DIR}/lib/libespeak-ng.a)
+        set(UCD_STATIC_LIB ${ESPEAKNG_BUILD_DIR}/src/espeak_ng_external-build/src/ucd-tools/libucd.a)
+    endif()
+
+    ExternalProject_Add(espeak_ng_external
+        GIT_REPOSITORY https://github.com/espeak-ng/espeak-ng.git
+        GIT_TAG 212928b394a96e8fd2096616bfd54e17845c48f6  # 2025-Mar-22
+        PREFIX ${ESPEAKNG_BUILD_DIR}
+        CMAKE_ARGS
+            -DCMAKE_INSTALL_PREFIX=${ESPEAKNG_INSTALL_DIR}
+            -DBUILD_SHARED_LIBS:BOOL=OFF
+            -DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=ON
+            -DUSE_ASYNC:BOOL=OFF
+            -DUSE_MBROLA:BOOL=OFF
+            -DUSE_LIBSONIC:BOOL=OFF
+            -DUSE_LIBPCAUDIO:BOOL=OFF
+            -DUSE_KLATT:BOOL=OFF
+            -DUSE_SPEECHPLAYER:BOOL=OFF
+            -DEXTRA_cmn:BOOL=ON
+            -DEXTRA_ru:BOOL=ON
+            # Need to explicitly add ucd include directory for CI
+            "-DCMAKE_C_FLAGS=-D_FILE_OFFSET_BITS=64 -I${ESPEAKNG_BUILD_DIR}/src/espeak_ng_external/src/ucd-tools/src/include"
+        BUILD_BYPRODUCTS
+            ${ESPEAKNG_STATIC_LIB}
+            ${UCD_STATIC_LIB}
+        UPDATE_DISCONNECTED TRUE
     )
-endif()
 
-install(TARGETS espeakbridge
-    LIBRARY DESTINATION .
-    RUNTIME DESTINATION .
-)
+    include_directories(
+        ${ESPEAKNG_INSTALL_DIR}/include
+    )
+
+    add_dependencies(espeakbridge espeak_ng_external)
+    target_link_libraries(espeakbridge
+        ${ESPEAKNG_STATIC_LIB}
+        ${UCD_STATIC_LIB}
+        Python::SABIModule
+    )
+    target_include_directories(espeakbridge PRIVATE
+        ${ESPEAKNG_INSTALL_DIR}/include
+    )
 
-# Copy espeak-ng-data
-set(DATA_SRC ${CMAKE_BINARY_DIR}/espeak_ng-install/share/espeak-ng-data)
-set(DATA_DST ${CMAKE_CURRENT_SOURCE_DIR}/src/piper/espeak-ng-data)
+    if(WIN32)
+        # Fix dll thunk issue (__imp_SYMBOL not found)
+        target_compile_definitions(espeakbridge PRIVATE LIBESPEAK_NG_EXPORT)
 
-add_custom_target(copy_espeak_ng_data ALL
-    COMMAND ${CMAKE_COMMAND} -E copy_directory ${DATA_SRC} ${DATA_DST}
-    DEPENDS espeak_ng_external
-    COMMENT "Copying espeak-ng-data after espeak-ng external project builds"
-)
+        # Fix .dll suffix
+        set_target_properties(espeakbridge PROPERTIES
+            PREFIX ""
+            SUFFIX ".pyd"
+        )
+    else()
+        set_target_properties(espeakbridge PROPERTIES
+            PREFIX ""
+        )
+    endif()
+
+    install(TARGETS espeakbridge
+        LIBRARY DESTINATION .
+        RUNTIME DESTINATION .
+    )
+
+    # Copy espeak-ng-data
+    set(DATA_SRC ${CMAKE_BINARY_DIR}/espeak_ng-install/share/espeak-ng-data)
+    set(DATA_DST ${CMAKE_CURRENT_SOURCE_DIR}/src/piper/espeak-ng-data)
+
+    add_custom_target(copy_espeak_ng_data ALL
+        COMMAND ${CMAKE_COMMAND} -E copy_directory ${DATA_SRC} ${DATA_DST}
+        DEPENDS espeak_ng_external
+        COMMENT "Copying espeak-ng-data after espeak-ng external project builds"
+    )
+endif()
+90 −42
Original line number Diff line number Diff line
{
  lib,
  stdenv,
  python3Packages,
  fetchFromGitHub,

  # build time
  cmake,
  pkg-config,

  # runtime
  fmt,
  onnxruntime,
  pcaudiolib,
  piper-phonemize,
  spdlog,

  # tests
  piper-train,
  espeak-ng,

  # extras
  withTrain ? true,
  withHTTP ? true,
  withAlignment ? true,
}:

stdenv.mkDerivation (finalAttrs: {
let
  # https://github.com/OHF-Voice/piper1-gpl/blob/v1.3.0/CMakeLists.txt#L33-L40
  espeak-ng' = espeak-ng.override {
    asyncSupport = false;
    klattSupport = false;
    mbrolaSupport = false;
    pcaudiolibSupport = false;
    sonicSupport = false;
    speechPlayerSupport = false;
  };
in

python3Packages.buildPythonApplication rec {
  pname = "piper-tts";
  version = "2023.11.14-2";
  version = "1.3.0";
  pyproject = true;

  src = fetchFromGitHub {
    owner = "rhasspy";
    repo = "piper";
    tag = finalAttrs.version;
    hash = "sha256-3ynWyNcdf1ffU3VoDqrEMrm5Jo5Zc5YJcVqwLreRCsI=";
    owner = "OHF-Voice";
    repo = "piper1-gpl";
    tag = "v${version}";
    hash = "sha256-WDMIXsbUzJ5XnA/KUVUPQKZzkqrXagzAOrhFtLR4fGk=";
  };

  nativeBuildInputs = [
  patches = [
    # https://github.com/OHF-Voice/piper1-gpl/pull/17
    ./cmake-system-libs.patch
  ];

  build-system =
    with python3Packages;
    [
      cmake
      ninja
      scikit-build
      setuptools
    ]
    ++ lib.optionals withTrain [
      cython
      distutils
    ];

  nativeBuildInputs = [
    pkg-config
  ];

  cmakeFlags = [
    "-DFMT_DIR=${fmt}"
    "-DSPDLOG_DIR=${spdlog.src}"
    "-DPIPER_PHONEMIZE_DIR=${piper-phonemize}"
  dontUseCmakeConfigure = true;

  env.CMAKE_ARGS = toString [
    (lib.cmakeFeature "UCD_STATIC_LIB" "${espeak-ng'.ucd-tools}/libucd.a")
  ];

  buildInputs = [
    onnxruntime
    pcaudiolib
    piper-phonemize
    piper-phonemize.espeak-ng
    spdlog
    espeak-ng'
  ];

  env.NIX_CFLAGS_COMPILE = builtins.toString [
    "-isystem ${lib.getDev piper-phonemize}/include/piper-phonemize"
  ];
  postBuild = lib.optionalString withTrain ''
    cythonize --inplace src/piper/train/vits/monotonic_align/core.pyx
  '';

  installPhase = ''
    runHook preInstall
  dependencies = [
    python3Packages.onnxruntime
  ]
  ++ lib.optionals withTrain optional-dependencies.train
  ++ lib.optionals withHTTP optional-dependencies.http
  ++ lib.optionals withAlignment optional-dependencies.alignment;

    mkdir -p $out/bin
    install -m 0755 piper $out/bin
  optional-dependencies = {
    train =
      with python3Packages;
      [
        jsonargparse
        librosa
        lightning
        pathvalidate
        pysilero-vad
        tensorboard
        tensorboardx
        torch
      ]
      ++ jsonargparse.optional-dependencies.signatures;
    http = with python3Packages; [
      flask
    ];
    alignment = with python3Packages; [
      onnx
    ];
  };

    runHook postInstall
  postInstall = ''
    ln -s ${espeak-ng'}/share/espeak-ng-data $out/${python3Packages.python.sitePackages}/piper/
  ''
  + lib.optionalString withTrain ''
    train=$out/${python3Packages.python.sitePackages}/piper/train/vits
    rm -v src/piper/train/vits/monotonic_align/{Makefile,setup.py,core.c,core.pyx}
    cp -Rv src/piper/train/vits $train/
  '';

  passthru.tests = {
    inherit piper-train;
  };

  meta = {
    changelog = "https://github.com/rhasspy/piper/releases/tag/v${finalAttrs.version}";
    changelog = "https://github.com/OHF-Voice/piper1-gpl/releases/tag/v${version}";
    description = "Fast, local neural text to speech system";
    homepage = "https://github.com/rhasspy/piper";
    license = lib.licenses.mit;
    homepage = "https://github.com/OHF-Voice/piper1-gpl";
    license = lib.licenses.gpl3Only;
    maintainers = with lib.maintainers; [ hexa ];
    mainProgram = "piper";
  };
})
}