/
gozaltech
/
RHVoice2
Обзор
Документация
Войти
/
gozaltech
/
RHVoice2
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
SConstruct
389 строк
15 KB
Zvonimir Stanečić
Version bump to 1.18.2 for core with new msi installers, android app, and nvda-addon. (#1029)
11 мар 2026, 13:03
Не верифицирован
11 мар 2026, 13:03
592cbc3
Код
Авторство
О чём код?
# Copyright (C) 2010, 2011, 2012, 2013, 2014, 2018, 2020, 2022 Olga Yakovleva <olga@rhvoice.org> # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see <https://www.gnu.org/licenses/>. import sys import os import os.path import subprocess import platform import datetime import re if sys.platform=="win32": if sys.version_info[0]>=3: import winreg else: import _winreg as winreg boost_includedir=Dir("#external").Dir("libs").Dir("boost").Dir("include") def get_version(is_release): next_version="1.19.2" return next_version def passthru(env, cmd, unique=False): return cmd.rstrip() def CheckPKGConfig(context): context.Message("Checking for pkg-config... ") result=context.TryAction("pkg-config --version")[0] context.Result(result) return result def CheckPKG(context,name): context.Message("Checking for {}... ".format(name)) result=context.TryAction("pkg-config --exists '{}'".format(name))[0] context.Result(result) return result def CheckMSVC(context): context.Message("Checking for Visual C++ ... ") result=0 version=context.env.get("MSVC_VERSION",None) if version is not None: result=1 context.Result(result) return result def CheckXPCompat(context): context.Message("Checking for Windows XP compatibility ... ") result=0 if context.env.get("xp_compat_enabled",False): result=1 context.Result(result) return result def CheckNSIS(context): result=0 context.Message("Checking for NSIS") if "NSISDIR" in os.environ: context.env["makensis"]=File(os.path.join(os.environ["NSISDIR"],"makensis.exe")) result=1 else: key_name=r"SOFTWARE\NSIS" try: with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,key_name,0,winreg.KEY_READ|winreg.KEY_WOW64_32KEY) as key: context.env["makensis"]=File(os.path.join(winreg.QueryValueEx(key,None)[0],"makensis.exe")) result=1 except WindowsError: pass context.Result(result) return result def CheckWiX(context): result=0 context.Message("Checking for WiX toolset") if "WIXTOOLPATH" in os.environ or "WIX" in os.environ: if "WIXTOOLPATH"in os.environ: context.env["WIX"]=os.environ["WIXTOOLPATH"] else: context.env["WIX"]=os.path.join(os.environ["WIX"],"bin") result=1 context.Result(result) return result def get_spd_module_dir(): env = Environment() try: return env.ParseConfig("pkg-config speech-dispatcher --variable=modulebindir", passthru) except: return False def validate_spd_version(key,val,env): m=re.match(r"^\d+\.\d+",val) if m is None: raise Exception("Invalid value of spd_version: {}".format(val)) def CheckSpdVersion(ctx): ctx.Message("Checking Speech Dispatcher version ... ") ver=ctx.env.get("spd_version",None) if ver is not None: ctx.Result(ver) return ver res, ver=ctx.TryAction("pkg-config --modversion speech-dispatcher > $TARGET") ver=ver.strip() if not res: src='#include <stdio.h>\n#include <speech-dispatcher/libspeechd_version.h>\nint main() {\nint major=LIBSPEECHD_MAJOR_VERSION;\nint minor=LIBSPEECHD_MINOR_VERSION;\nprintf("%d.%d",major,minor);\nreturn 0;}' res,ver=ctx.TryRun(src,".c") if not res: ctx.Result(res) return res ctx.env["spd_version"]=ver ctx.Result(ver) return ver def convert_flags(value): return value.split() def convert_path(value): return value.split(";" if sys.platform=="win32" else ":") def setup(): if sys.platform=="win32": SetOption("warn","no-visual-c-missing") global BUILDDIR,var_cache system=platform.system().lower() BUILDDIR=os.path.join("build",system) var_cache=os.path.join(BUILDDIR,"user.conf") Execute(Mkdir(BUILDDIR)) SConsignFile(os.path.join(BUILDDIR,"scons")) def create_languages_user_var(): langs_dir=Dir("#data").Dir("languages") names=[name for name in sorted(os.listdir(langs_dir.path)) if os.path.isdir(langs_dir.Entry(name).path)] langs=[name.lower() for name in names] name_map=dict(zip(names,langs)) def_langs=langs if sys.platform!="win32": def_langs=[lang for lang in langs if lang not in["georgian"]] print("Georgian language is skipped because of non-free license") help="Which languages to install" return ListVariable("languages",help,def_langs,langs,name_map) def create_audio_libs_user_var(): libs=["pulse","libao","portaudio"] help="Which audio libraries to use if they are available" return ListVariable("audio_libs",help,libs,libs) def create_user_vars(): args={"DESTDIR":""} args.update(ARGUMENTS) vars=Variables(var_cache,args) vars.Add(BoolVariable("dev","The build will only be used for development: no global installation, run from the source directory, compile helper utilities",False)) vars.Add(create_languages_user_var()) vars.Add(BoolVariable("enable_sonic","Build with Sonic",False)) vars.Add(BoolVariable("enable_pkg","Enable package directory code",False)) vars.Add(create_audio_libs_user_var()) vars.Add(BoolVariable("release","Whether we are building a release",True)) if sys.platform=="win32": vars.Add(BoolVariable("sapi_dev_core", "Use the development version of the core in SAPI5 voice installers", False)) vars.Add(BoolVariable("enable_x64","Additionally build 64-bit versions of all the libraries",True)) vars.Add(BoolVariable("enable_xp_compat","Target Windows XP",False)) else: vars.Add(PathVariable("spd_module_dir", "Speech dispatcher module directory", get_spd_module_dir(), PathVariable.PathAccept)) vars.Add("spd_version","Speech dispatcher version",validator=validate_spd_version) vars.Add("prefix","Installation prefix","/usr/local") vars.Add("bindir","Program installation directory","$prefix/bin") vars.Add("libdir","Library installation directory","$prefix/lib") vars.Add("includedir","Header installation directory","$prefix/include") vars.Add("datadir","Data installation directory","$prefix/share") vars.Add("sysconfdir","A directory for configuration files","$prefix/etc") vars.Add("servicedir",".service file installation directory","$datadir/dbus-1/services") vars.Add("DESTDIR","Support for staged installation","") vars.Add(BoolVariable("enable_shared","Build a shared library",True)) if sys.platform=="win32": suffixes=["32","64"] else: suffixes=[""] for suffix in suffixes: vars.Add("CPPPATH"+suffix,"List of directories where to search for headers",[],converter=convert_path) vars.Add("LIBPATH"+suffix,"List of directories where to search for libraries",[],converter=convert_path) vars.Add("CPPFLAGS","C/C++ preprocessor flags",[],converter=convert_flags) vars.Add("CCFLAGS","C/C++ compiler flags",["/O2","/GL","/Gw"] if sys.platform=="win32" else ["-O2"],converter=convert_flags) vars.Add("CFLAGS","C compiler flags",[],converter=convert_flags) vars.Add("CXXFLAGS","C++ compiler flags",[],converter=convert_flags) vars.Add("LINKFLAGS","Linker flags",["/LTCG","/OPT:REF","/OPT:ICF"] if sys.platform=="win32" else [],converter=convert_flags) return vars def create_base_env(user_vars): env_args={"variables":user_vars} if sys.platform=="win32": env_args["tools"]=["newlines", "msgfmt"] else: env_args["tools"]=["default","installer"] env_args["tools"].extend(["textfile","library"]) env_args["LIBS"]=[] env_args["package_name"]="RHVoice" env_args["CPPDEFINES"]=[("RHVOICE","1")] env=Environment(**env_args) if env["dev"]: env["prefix"]=os.path.abspath("local") env["RPATH"]=env.Dir("$libdir").abspath env["package_version"]=get_version(env["release"]) env.Append(CPPDEFINES=("PACKAGE",env.subst(r'\"$package_name\"'))) if env["PLATFORM"]=="win32": env.Append(CPPDEFINES=("WIN32",1)) env.Append(CPPDEFINES=("UNICODE",1)) env.Append(CPPDEFINES=("NOMINMAX",1)) env["libcore"]="RHVoice_core" env["libaudio"]="RHVoice_audio" return env def display_help(env,vars): Help("Type 'scons' to build the package.\n") if sys.platform!="win32": Help("Then type 'scons install' to install it.\n") Help("Type 'scons --clean install' to uninstall the software.\n") Help("You may use the following configuration variables:\n") Help(vars.GenerateHelpText(env)) def clone_base_env(base_env,user_vars,arch=None): args={} if sys.platform=="win32": if arch is not None: args["TARGET_ARCH"]=arch args["tools"]=["msvc","mslink","mslib"] env=base_env.Clone(**args) user_vars.Update(env) if env["PLATFORM"]=="win32": env.AppendUnique(CCFLAGS=["/nologo","/MT"]) env.AppendUnique(LINKFLAGS=["/nologo"]) env.AppendUnique(CXXFLAGS=["/EHsc"]) if env["enable_xp_compat"]: env.Tool("xp_compat") if "gcc" in env["TOOLS"]: env.MergeFlags("-pthread") env.AppendUnique(CXXFLAGS=["-std=c++11"]) env.AppendUnique(CFLAGS=["-std=c11"]) if 'SOURCE_DATE_EPOCH' in os.environ: env['ENV']['SOURCE_DATE_EPOCH'] = os.environ['SOURCE_DATE_EPOCH'] if sys.platform=="win32": bits="64" if arch.endswith("64") else "32" env["BUILDDIR"]=os.path.join(BUILDDIR,arch) env["CPPPATH"]=env["CPPPATH"+bits] env["LIBPATH"]=env["LIBPATH"+bits] else: env["BUILDDIR"]=BUILDDIR third_party_dir=os.path.join("src","third-party") for path in Glob(os.path.join(third_party_dir,"*"),strings=True): if os.path.isdir(path): env.Prepend(CPPPATH=("#"+path)) env.Prepend(CPPPATH=boost_includedir) env.Prepend(CPPPATH=(os.path.join("#"+env["BUILDDIR"],"include"),".",os.path.join("#src","include"))) return env def configure(env): tests={"CheckPKGConfig":CheckPKGConfig,"CheckPKG":CheckPKG,"CheckSpdVersion":CheckSpdVersion} if env["PLATFORM"]=="win32": tests["CheckMSVC"]=CheckMSVC tests["CheckXPCompat"]=CheckXPCompat conf=env.Configure(conf_dir=os.path.join(env["BUILDDIR"],"configure_tests"), log_file=os.path.join(env["BUILDDIR"],"configure.log"), config_h=os.path.join(env["BUILDDIR"],"include","configure.h"), custom_tests=tests) if env["PLATFORM"]=="win32": if not conf.CheckMSVC(): print("Error: Visual C++ is not installed") exit(1) print("Visual C++ version is {}".format(env["MSVC_VERSION"])) if env["enable_xp_compat"] and not conf.CheckXPCompat(): print("Error: Windows XP compatibility cannot be enabled") exit(1) if not conf.CheckCC(): print("The C compiler is not working") exit(1) if not conf.CheckCXX(): print("The C++ compiler is not working") exit(1) # has_sox=conf.CheckLibWithHeader("sox","sox.h","C",call='sox_init();',autoadd=0) # if not has_sox: # print("Error: cannot link with libsox") # exit(1) # env.PrependUnique(LIBS="sox") has_giomm=False has_pkg_config=conf.CheckPKGConfig() if has_pkg_config: if "pulse" in env["audio_libs"] and not conf.CheckPKG("libpulse-simple"): env["audio_libs"].remove("pulse") if "libao" in env["audio_libs"] and not conf.CheckPKG("ao"): env["audio_libs"].remove("libao") if "portaudio" in env["audio_libs"] and not conf.CheckPKG("portaudio-2.0"): env["audio_libs"].remove("portaudio") if env["audio_libs"]: conf.CheckSpdVersion() else: env["audio_libs"]=[] # has_giomm=conf.CheckPKG("giomm-2.4") if env["PLATFORM"]=="win32": env.AppendUnique(LIBS="kernel32") conf.Finish() env.Prepend(LIBPATH=os.path.join("#"+env["BUILDDIR"],"core")) src_subdirs=["third-party", "pkg", "hts_engine", "core", "lib"] if env["dev"]: src_subdirs.append("utils") src_subdirs.append("audio") src_subdirs.append("test") if env["audio_libs"]: src_subdirs.append("sd_module") env.Prepend(LIBPATH=os.path.join("#"+env["BUILDDIR"],"audio")) if has_giomm: src_subdirs.append("service") if env["PLATFORM"]=="win32": src_subdirs.append("sapi") else: src_subdirs.append("include") return src_subdirs def build_binaries(base_env,user_vars,arch=None): env=clone_base_env(base_env,user_vars,arch) if env["BUILDDIR"]!=BUILDDIR: Execute(Mkdir(env["BUILDDIR"])) if arch: print("Configuring the build system for {}".format(arch)) src_subdirs=configure(env) for subdir in src_subdirs: SConscript(os.path.join("src",subdir,"SConscript"), variant_dir=os.path.join(env["BUILDDIR"],subdir), exports={"env":env}, duplicate=0) def build_for_linux(base_env,user_vars): build_binaries(base_env,user_vars) for subdir in ["data","config"]: SConscript(os.path.join(subdir,"SConscript"),exports={"env":base_env}, variant_dir=os.path.join(BUILDDIR,subdir), duplicate=0) def preconfigure_for_windows(env): conf=env.Configure(conf_dir=os.path.join(BUILDDIR,"configure_tests"), log_file=os.path.join(BUILDDIR,"configure.log"), custom_tests={"CheckNSIS":CheckNSIS,"CheckWiX":CheckWiX}) conf.CheckWiX() conf.CheckNSIS() conf.Finish() def build_for_windows(base_env,user_vars): preconfigure_for_windows(base_env) build_binaries(base_env,user_vars,"x86") if base_env["enable_x64"]: build_binaries(base_env,user_vars,"x86_64") if "WIX" in base_env: SConscript(os.path.join("src","wininst","SConscript"), variant_dir=os.path.join(BUILDDIR,"wininst"), exports={"env":base_env}, duplicate=0) SConscript(os.path.join("data","SConscript"), variant_dir=os.path.join(BUILDDIR,"data"), exports={"env":base_env}, duplicate=0) docs=["README.md"]+[os.path.join("licenses",name) for name in os.listdir("licenses") if name!="voices"] for f in docs: base_env.ConvertNewlines(os.path.join(BUILDDIR,f),f) base_env.ConvertNewlinesB(os.path.join(BUILDDIR,"RHVoice.ini"),os.path.join("config","RHVoice.conf")) # env.ConvertNewlinesB(os.path.join(BUILDDIR,"dict.txt"),os.path.join("config","dicts","example.txt")) SConscript(os.path.join("src","nvda-addon","SConscript"), variant_dir=os.path.join(BUILDDIR,"nvda-addon"), exports={"env":base_env}, duplicate=0) setup() vars=create_user_vars() base_env=create_base_env(vars) display_help(base_env,vars) vars.Save(var_cache,base_env) SConscript(dirs=boost_includedir) if sys.platform=="win32": build_for_windows(base_env,vars) else: build_for_linux(base_env,vars)