mirror of
https://gitlab.com/mbunkus/mkvtoolnix.git
synced 2024-12-29 06:15:24 +00:00
1232 lines
45 KiB
Ruby
1232 lines
45 KiB
Ruby
$build_start = Time.now
|
|
|
|
if Signal.list.key?('ALRM')
|
|
Signal.trap('ALRM') { |signo| }
|
|
end
|
|
|
|
version = RUBY_VERSION.gsub(/[^0-9\.]+/, "").split(/\./).collect(&:to_i)
|
|
version << 0 while version.size < 3
|
|
if (version[0] < 2) && (version[1] < 9)
|
|
fail "Ruby 1.9.x or newer is required for building"
|
|
end
|
|
|
|
# Change to base directory before doing anything
|
|
$source_dir = File.absolute_path(File.dirname(__FILE__))
|
|
$build_dir = $source_dir
|
|
|
|
if FileUtils.pwd != File.dirname(__FILE__)
|
|
puts "Entering directory `#{$source_dir}'"
|
|
Dir.chdir $source_dir
|
|
end
|
|
|
|
# Set number of threads to use if it is unset and we're running with
|
|
# drake.
|
|
if Rake.application.options.respond_to?(:threads) && [nil, 0, 1].include?(Rake.application.options.threads) && !ENV['DRAKETHREADS'].nil?
|
|
Rake.application.options.threads = ENV['DRAKETHREADS'].to_i
|
|
end
|
|
|
|
# For newer rake turn on parallel processing, too. Newer rake versions
|
|
# use an OpenStruct, though, so testing with responds_to? won't work.
|
|
version = Rake::VERSION.gsub(%r{[^0-9\.]+}, "").split(%r{\.}).map(&:to_i)
|
|
if (version[0] > 10) || ((version[0] == 10) && (version[1] >= 3))
|
|
Rake.application.options.always_multitask = true
|
|
end
|
|
|
|
module Mtx
|
|
end
|
|
|
|
require_relative "rake.d/requirements"
|
|
require_relative "rake.d/extensions"
|
|
require_relative "rake.d/config"
|
|
|
|
$config = read_build_config
|
|
$verbose = ENV['V'].to_bool
|
|
$run_show_start_stop = !$verbose && c?('RUN_SHOW_START_STOP')
|
|
$build_system_modules = {}
|
|
$have_gtest = (c(:GTEST_TYPE) == "system") || (c(:GTEST_TYPE) == "internal")
|
|
$gtest_apps = []
|
|
|
|
require_relative "rake.d/digest"
|
|
require_relative "rake.d/helpers"
|
|
require_relative "rake.d/target"
|
|
require_relative "rake.d/application"
|
|
require_relative "rake.d/iana_language_subtag_registry"
|
|
require_relative "rake.d/installer"
|
|
require_relative "rake.d/iso639"
|
|
require_relative "rake.d/iso3166"
|
|
require_relative "rake.d/iso15924"
|
|
require_relative "rake.d/library"
|
|
require_relative "rake.d/compilation_database"
|
|
require_relative "rake.d/format_string_verifier"
|
|
require_relative "rake.d/pch"
|
|
require_relative "rake.d/online_file"
|
|
require_relative "rake.d/po"
|
|
require_relative "rake.d/source_tests"
|
|
require_relative "rake.d/tarball"
|
|
require_relative 'rake.d/gtest' if $have_gtest
|
|
|
|
def setup_globals
|
|
$building_for = {
|
|
:linux => %r{linux}i.match(c(:host)),
|
|
:macos => %r{darwin}i.match(c(:host)),
|
|
:windows => %r{mingw}i.match(c(:host)),
|
|
}
|
|
|
|
$build_mkvtoolnix_gui ||= c?(:BUILD_GUI)
|
|
|
|
$programs = %w{mkvmerge mkvinfo mkvextract mkvpropedit}
|
|
$programs << "mkvtoolnix-gui" if $build_mkvtoolnix_gui
|
|
$tools = %w{ac3parser base64tool bluray_dump checksum diracparser ebml_validator hevcc_dump pgs_dump vc1parser xvc_dump}
|
|
|
|
$application_subdirs = { "mkvtoolnix-gui" => "mkvtoolnix-gui/" }
|
|
$applications = $programs.map { |name| "src/#{$application_subdirs[name]}#{name}" + c(:EXEEXT) }
|
|
$manpages = $programs.map { |name| "doc/man/#{name}.1" }
|
|
$manpages << "doc/man/mkvtoolnix-gui.1" if $build_mkvtoolnix_gui
|
|
|
|
$system_includes = "-I. -Ilib -Ilib/avilib-0.6.10 -Isrc"
|
|
$system_includes += " -Ilib/utf8-cpp/source" if c?(:UTF8CPP_INTERNAL)
|
|
$system_includes += " -Ilib/pugixml/src" if c?(:PUGIXML_INTERNAL)
|
|
$system_libdirs = "-Llib/avilib-0.6.10 -Llib/librmff -Lsrc/common"
|
|
|
|
$source_directories = %w{lib/avilib-0.6.10 lib/librmff src/common src/extract src/info src/input src/merge src/mkvtoolnix-gui src/mpegparser src/output src/propedit}
|
|
$all_sources = $source_directories.collect { |dir| FileList[ "#{dir}/**/*.c", "#{dir}/**/*.cpp" ].to_a }.flatten.sort
|
|
$all_headers = $source_directories.collect { |dir| FileList[ "#{dir}/**/*.h", ].to_a }.flatten.sort
|
|
$all_objects = $all_sources.collect { |file| file.ext('o') }
|
|
$all_app_po_files = FileList["po/*.po"].to_a.sort
|
|
$all_man_po_files = FileList["doc/man/po4a/po/*.po"].to_a.sort
|
|
$all_po_files = $all_app_po_files + $all_man_po_files
|
|
|
|
$gui_ui_files = FileList["src/mkvtoolnix-gui/forms/**/*.ui"].to_a
|
|
$gui_ui_h_files = $gui_ui_files.collect { |file| file.ext 'h' }
|
|
|
|
$dependency_dir = "#{$source_dir}/rake.d/dependency.d"
|
|
$dependency_tmp_dir = "#{$dependency_dir}/tmp"
|
|
|
|
$version_header_name = "#{$build_dir}/src/common/mkvtoolnix_version.h"
|
|
|
|
$languages = {
|
|
:programs => c(:TRANSLATIONS).split(/\s+/),
|
|
:manpages => c(:MANPAGES_TRANSLATIONS).split(/\s+/),
|
|
}
|
|
|
|
$translations = {
|
|
:programs => $languages[:programs].collect { |language| "po/#{language}.mo" },
|
|
:manpages => !c?(:PO4A_WORKS) ? [] : $languages[:manpages].collect { |language| $manpages.collect { |manpage| manpage.gsub(/man\//, "man/#{language}/") } }.flatten,
|
|
}
|
|
|
|
$available_languages = {
|
|
:programs => FileList[ "#{$source_dir }/po/*.po" ].collect { |name| File.basename name, '.po' },
|
|
:manpages => FileList[ "#{$source_dir }/doc/man/po4a/po/*.po" ].collect { |name| File.basename name, '.po' },
|
|
}
|
|
|
|
$unwrapped_po = %{ca es eu it nl uk pl sr_RS@latin tr}
|
|
$po_multiple_sources = %{sv}
|
|
|
|
$benchmark_sources = FileList["src/benchmark/*.cpp"].to_a if c?(:GOOGLE_BENCHMARK)
|
|
|
|
$libmtxcommon_as_dll = $building_for[:windows] && %r{shared}i.match(c(:host))
|
|
|
|
cflags_common = "-Wall -Wno-comment -Wfatal-errors #{c(:WLOGICAL_OP)} #{c(:WNO_MISMATCHED_TAGS)} #{c(:WNO_SELF_ASSIGN)} #{c(:QUNUSED_ARGUMENTS)}"
|
|
cflags_common += " #{c(:WNO_INCONSISTENT_MISSING_OVERRIDE)} #{c(:WNO_POTENTIALLY_EVALUATED_EXPRESSION)}"
|
|
cflags_common += " #{c(:OPTIMIZATION_CFLAGS)} -D_FILE_OFFSET_BITS=64"
|
|
cflags_common += " -DQT_NO_KEYWORDS"
|
|
cflags_common += " -DMTX_LOCALE_DIR=\\\"#{c(:localedir)}\\\" -DMTX_PKG_DATA_DIR=\\\"#{c(:pkgdatadir)}\\\" -DMTX_DOC_DIR=\\\"#{c(:docdir)}\\\""
|
|
cflags_common += determine_stack_protector_flags
|
|
cflags_common += determine_optimization_cflags
|
|
cflags_common += " -g3 -DDEBUG" if c?(:USE_DEBUG)
|
|
cflags_common += " -pg" if c?(:USE_PROFILING)
|
|
cflags_common += " -fsanitize=undefined" if c?(:USE_UBSAN)
|
|
cflags_common += " -fsanitize=address -fno-omit-frame-pointer" if c?(:USE_ADDRSAN)
|
|
cflags_common += " -Ilib/libebml -Ilib/libmatroska" if c?(:EBML_MATROSKA_INTERNAL)
|
|
cflags_common += " -Ilib/nlohmann-json/include" if c?(:NLOHMANN_JSON_INTERNAL)
|
|
cflags_common += " -Ilib/fmt/include" if c?(:FMT_INTERNAL)
|
|
cflags_common += " #{c(:MATROSKA_CFLAGS)} #{c(:EBML_CFLAGS)} #{c(:PUGIXML_CFLAGS)} #{c(:CMARK_CFLAGS)} #{c(:DVDREAD_CFLAGS)} #{c(:EXTRA_CFLAGS)} #{c(:USER_CPPFLAGS)}"
|
|
cflags_common += " -mno-ms-bitfields -DWINVER=0x0601 -D_WIN32_WINNT=0x0601 " if $building_for[:windows] # 0x0601 = Windows 7/Server 2008 R2
|
|
cflags_common += " -march=i686" if $building_for[:windows] && /i686/.match(c(:host))
|
|
cflags_common += " -fPIC " if !$building_for[:windows]
|
|
cflags_common += " -DQT_STATICPLUGIN" if $building_for[:windows]
|
|
cflags_common += " -DUSE_DRMINGW -I#{c(:DRMINGW_PATH)}/include" if c?(:USE_DRMINGW) && $building_for[:windows]
|
|
|
|
cflags = "#{cflags_common} #{c(:USER_CFLAGS)}"
|
|
|
|
cxxflags = "#{cflags_common} #{c(:STD_CXX)}"
|
|
cxxflags += " -Wnon-virtual-dtor -Wextra -Wno-missing-field-initializers -Wunused -Wpedantic"
|
|
cxxflags += " -Woverloaded-virtual" if is_clang? # too many false positives in EbmlElement.h on g++ 8
|
|
cxxflags += " -Wno-maybe-uninitialized -Wlogical-op" if is_gcc?
|
|
cxxflags += " -Wshadow -Qunused-arguments -Wno-self-assign -Wno-mismatched-tags" if is_clang?
|
|
cxxflags += " -Wno-inconsistent-missing-override -Wno-potentially-evaluated-expression" if is_clang?
|
|
cxxflags += " -Wno-extra-semi" if is_clang? || check_compiler_version("gcc", "8.0.0")
|
|
cxxflags += " -Wmisleading-indentation -Wduplicated-cond" if check_compiler_version("gcc", "6.0.0")
|
|
cxxflags += " -Wshadow-compatible-local -Wduplicated-branches" if check_compiler_version("gcc", "7.0.0")
|
|
cxxflags += " -Wno-deprecated-copy" if check_compiler_version("gcc", "9.0.0")
|
|
cxxflags += " #{c(:QT_CFLAGS)} #{c(:BOOST_CPPFLAGS)} #{c(:USER_CXXFLAGS)}"
|
|
|
|
ldflags = ""
|
|
ldflags += determine_stack_protector_flags
|
|
ldflags += " -pg" if c?(:USE_PROFILING)
|
|
ldflags += " -fuse-ld=lld" if is_clang? && !c(:LLVM_LLD).empty? && !$building_for[:macos]
|
|
ldflags += " -Llib/libebml/src -Llib/libmatroska/src" if c?(:EBML_MATROSKA_INTERNAL)
|
|
ldflags += " -Llib/fmt/src" if c?(:FMT_INTERNAL)
|
|
ldflags += " #{c(:EXTRA_LDFLAGS)} #{c(:USER_LDFLAGS)} #{c(:LDFLAGS_RPATHS)} #{c(:BOOST_LDFLAGS)}"
|
|
ldflags += " -Wl,--dynamicbase,--nxcompat" if $building_for[:windows]
|
|
ldflags += " -L#{c(:DRMINGW_PATH)}/lib" if c?(:USE_DRMINGW) && $building_for[:windows]
|
|
ldflags += " -fsanitize=undefined" if c?(:USE_UBSAN)
|
|
ldflags += " -fsanitize=address -fno-omit-frame-pointer" if c?(:USE_ADDRSAN)
|
|
ldflags += " -headerpad_max_install_names" if $building_for[:macos]
|
|
|
|
windres = ""
|
|
windres += " -DMINGW_PROCESSOR_ARCH_AMD64=1" if c(:MINGW_PROCESSOR_ARCH) == 'amd64'
|
|
|
|
mocflags = c(:QT_CFLAGS).gsub(%r{ +}, '').split(' ').select { |opt| %r{^-[DI]}.match(opt) }.join(' ')
|
|
mocflags += $building_for[:macos] ? " -DSYS_APPLE" : $building_for[:windows] ? " -DSYS_WINDOWS" : ""
|
|
|
|
ranlibflags = $building_for[:macos] ? "-no_warning_for_no_symbols" : ""
|
|
|
|
$flags = {
|
|
:cflags => cflags,
|
|
:cxxflags => cxxflags,
|
|
:ldflags => ldflags,
|
|
:windres => windres,
|
|
:moc => mocflags,
|
|
:ranlib => ranlibflags,
|
|
}
|
|
|
|
setup_macos_specifics if $building_for[:macos]
|
|
setup_compiler_specifics
|
|
|
|
$build_system_modules.values.each { |bsm| bsm[:setup].call if bsm[:setup] }
|
|
end
|
|
|
|
def setup_overrides
|
|
[ :programs, :manpages ].each do |type|
|
|
value = c("AVAILABLE_LANGUAGES_#{type.to_s.upcase}")
|
|
$available_languages[type] = value.split(/\s+/) unless value.empty?
|
|
end
|
|
end
|
|
|
|
def setup_macos_specifics
|
|
$macos_config = read_config_file("packaging/macos/config.sh")
|
|
|
|
if ENV['MACOSX_DEPLOYMENT_TARGET'].to_s.empty? && !$macos_config[:MACOSX_DEPLOYMENT_TARGET].to_s.empty?
|
|
ENV['MACOSX_DEPLOYMENT_TARGET'] = $macos_config[:MACOSX_DEPLOYMENT_TARGET]
|
|
end
|
|
end
|
|
|
|
def setup_compiler_specifics
|
|
if %r{zapcc}.match(c(:CXX) + c(:CC))
|
|
# ccache and certain versions of zapcc don't seem to be playing well
|
|
# together. As zapcc's servers do the caching already, disable
|
|
# ccache if compiling with zapcc.
|
|
ENV['CCACHE_DISABLE'] = "1"
|
|
|
|
# zapcc doesn't support pre-compiled headers.
|
|
ENV['USE_PRECOMPILED_HEADERS'] = "0"
|
|
end
|
|
end
|
|
|
|
def determine_optimization_cflags
|
|
return "" if !c?(:USE_OPTIMIZATION)
|
|
return " -O1" if is_clang? && !check_compiler_version("clang", "3.8.0") # LLVM bug 11962
|
|
return " -O2 -fno-ipa-icf" if $building_for[:windows] && check_compiler_version("gcc", "5.1.0") && !check_compiler_version("gcc", "7.2.0")
|
|
return " -O3"
|
|
end
|
|
|
|
def determine_stack_protector_flags
|
|
return " -fstack-protector" if is_gcc? && !check_compiler_version("gcc", "4.9.0")
|
|
return " -fstack-protector-strong" if check_compiler_version("gcc", "4.9.0") || check_compiler_version("clang", "3.5.0")
|
|
return ""
|
|
end
|
|
|
|
def generate_helper_files
|
|
return unless c?(:EBML_MATROSKA_INTERNAL)
|
|
|
|
ensure_file("lib/libebml/ebml/ebml_export.h", "#define EBML_DLL_API\n")
|
|
ensure_file("lib/libmatroska/matroska/matroska_export.h", "#define MATROSKA_DLL_API\n")
|
|
end
|
|
|
|
def define_default_task
|
|
if !c(:DEFAULT_TARGET).empty?
|
|
desc "Build target '#{c(:DEFAULT_TARGET)}' by default"
|
|
task :default => c(:DEFAULT_TARGET)
|
|
|
|
return
|
|
end
|
|
|
|
desc "Build everything"
|
|
|
|
# The applications themselves
|
|
targets = $applications.clone
|
|
targets += $tools.map { |name| "src/tools/#{$application_subdirs[name]}#{name}" + c(:EXEEXT) }
|
|
|
|
targets << "msix-assets" if $building_for[:windows] && !c(:CONVERT).empty?
|
|
targets += (c(:ADDITIONAL_TARGETS) || '').split(%r{ +})
|
|
|
|
# Build the unit tests only if requested
|
|
targets << ($run_unit_tests ? 'tests:run_unit' : 'tests:unit') if $have_gtest
|
|
|
|
# The tags file -- but only if it exists already
|
|
if File.exists?("TAGS")
|
|
targets << "TAGS" if !c(:ETAGS).empty?
|
|
targets << "BROWSE" if !c(:EBROWSE).empty?
|
|
end
|
|
|
|
# Build developer documentation?
|
|
targets << "doc/development.html" if !c(:PANDOC).empty?
|
|
|
|
# Build man pages and translations?
|
|
targets << "manpages"
|
|
targets << "translations:manpages" if c?(:PO4A_WORKS)
|
|
|
|
# Build translations for the programs
|
|
targets << "translations:programs"
|
|
|
|
# The Qt translation files: only for Windows
|
|
targets << "translations:qt" if $building_for[:windows] && !c(:LCONVERT).blank?
|
|
|
|
# Build ebml_validator by default when not cross-compiling as it is
|
|
# needed for running the tests.
|
|
targets << "apps:tools:ebml_validator" if c(:host) == c(:build)
|
|
|
|
targets << "src/benchmark/benchmark" if c?(:GOOGLE_BENCHMARK) && !$benchmark_sources.empty?
|
|
|
|
task :default => targets do
|
|
build_duration = Time.now - $build_start
|
|
build_duration = sprintf("%02d:%02d.%03d", (build_duration / 60).to_i, build_duration.to_i % 60, (build_duration * 1000).to_i % 1000)
|
|
|
|
puts "Done after #{build_duration}. Enjoy :)"
|
|
end
|
|
end
|
|
|
|
# main
|
|
setup_globals
|
|
setup_overrides
|
|
import_dependencies
|
|
generate_helper_files
|
|
update_version_number_include
|
|
|
|
# Default task
|
|
define_default_task
|
|
|
|
# A helper task to check if there are any unstaged changes.
|
|
task :no_unstaged_changes do
|
|
has_changes = false
|
|
has_changes = true if !system("git rev-parse --verify HEAD &> /dev/null") || $?.exitstatus != 0
|
|
has_changes = true if !system("git update-index -q --ignore-submodules --refresh &> /dev/null") || $?.exitstatus != 0
|
|
has_changes = true if !system("git diff-files --quiet --ignore-submodules &> /dev/null") || $?.exitstatus != 0
|
|
has_changes = true if !system("git diff-index --cached --quiet --ignore-submodules HEAD -- &> /dev/null") || $?.exitstatus != 0
|
|
|
|
fail "There are unstaged changes; the operation cannot continue." if has_changes
|
|
end
|
|
|
|
desc "Build all applications"
|
|
task :apps => $applications
|
|
|
|
desc "Build all command line applications"
|
|
namespace :apps do
|
|
task :cli => %w{apps:mkvmerge apps:mkvinfo apps:mkvextract apps:mkvpropedit}
|
|
|
|
desc "Strip all apps"
|
|
task :strip => $applications do
|
|
runq "strip", nil, "#{c(:STRIP)} #{$applications.join(' ')}"
|
|
end
|
|
end
|
|
|
|
# Store compiler block for re-use
|
|
cxx_compiler = lambda do |*args|
|
|
t = args.first
|
|
|
|
create_dependency_dirs
|
|
|
|
source = t.source ? t.source : t.prerequisites.first
|
|
dep = dependency_output_name_for t.name
|
|
pchi = PCH.info_for_user(source, t.name)
|
|
pchu = pchi.use_flags ? " #{pchi.use_flags}" : ""
|
|
pchx = pchi.extra_flags ? " #{pchi.extra_flags}" : ""
|
|
lang = pchi.language ? pchi.language : "c++"
|
|
flags = $flags[:cxxflags].dup
|
|
|
|
if %r{lib/fmt/}.match(source)
|
|
flags.gsub!(%r{-Wpedantic}, '')
|
|
end
|
|
|
|
if %r{src/common/iso639_language_list.cpp}.match(source)
|
|
# Even -O1 causes compilation time & memory usage to skyrocket,
|
|
# possibly exponentially, with the number of entries to
|
|
# emplace_back() into the vector.
|
|
flags.gsub!(%r{(^| )-O[^ ]*}, ' -O0')
|
|
end
|
|
|
|
args = [
|
|
"cxx", source,
|
|
"#{c(:CXX)} #{flags}#{pchu}#{pchx} #{$system_includes} -c -MMD -MF #{dep} -o #{t.name} -x #{lang} #{source}",
|
|
:allow_failure => true
|
|
]
|
|
|
|
Mtx::CompilationDatabase.add "directory" => $source_dir, "file" => source, "command" => args[2]
|
|
|
|
if pchi.pretty_flags
|
|
PCH.runq(*args[0..2], args[3].merge(pchi.pretty_flags))
|
|
else
|
|
runq(*args)
|
|
end
|
|
|
|
handle_deps t.name, last_exit_code, true
|
|
end
|
|
|
|
qrc_compiler = lambda do |*args|
|
|
t = args[0]
|
|
sources = t.prerequisites
|
|
|
|
runq "rcc", sources[0], "#{c(:RCC)} -o #{t.name} #{sources.join(" ")}"
|
|
end
|
|
|
|
# Pattern rules
|
|
rule '.o' => '.cpp', &cxx_compiler
|
|
rule '.o' => '.cc', &cxx_compiler
|
|
|
|
rule '.o' => '.c' do |t|
|
|
create_dependency_dirs
|
|
dep = dependency_output_name_for t.name
|
|
|
|
runq "cc", t.source, "#{c(:CC)} #{$flags[:cflags]} #{$system_includes} -c -MMD -MF #{dep} -o #{t.name} #{t.sources.join(" ")}", :allow_failure => true
|
|
handle_deps t.name, last_exit_code
|
|
end
|
|
|
|
rule '.o' => '.rc' do |t|
|
|
runq "windres", t.source, "#{c(:WINDRES)} #{$flags[:windres]} -o #{t.name} #{t.sources.join(" ")}"
|
|
end
|
|
|
|
rule '.xml' => '.xml.erb' do |t|
|
|
process_erb(t)
|
|
end
|
|
|
|
# Resources depend on the manifest.xml file for Windows builds.
|
|
if $building_for[:windows]
|
|
$programs.each do |program|
|
|
path = FileTest.directory?("src/#{program}") ? program : program.gsub(/^mkv/, '')
|
|
icon = program == 'mkvinfo' ? 'share/icons/windows/mkvinfo.ico' : 'share/icons/windows/mkvtoolnix-gui.ico'
|
|
file "src/#{path}/resources.o" => [ "src/#{path}/manifest.xml", "src/#{path}/resources.rc", icon ]
|
|
end
|
|
|
|
task 'msix-assets' => 'packaging/windows/msix/assets/StoreLogo.png'
|
|
|
|
file 'packaging/windows/msix/assets/StoreLogo.png' => 'packaging/windows/msix/generate_assets.sh' do
|
|
runq "generate", 'packaging/windows/msix/assets', 'packaging/windows/msix/generate_assets.sh'
|
|
end
|
|
end
|
|
|
|
rule '.mo' => '.po' do |t|
|
|
if !%r{doc/man}.match(t.sources[0])
|
|
runq_code "VERIFY-PO-FMT", :target => t.sources[0] do
|
|
FormatStringVerifier.new.verify t.sources[0]
|
|
end
|
|
end
|
|
|
|
runq "msgfmt", t.source, "#{c(:MSGFMT)} -c -o #{t.name} #{t.sources.join(" ")}"
|
|
end
|
|
|
|
if !c(:LCONVERT).blank?
|
|
rule '.qm' => '.ts' do |t|
|
|
runq "lconvert", t.source, "#{c(:LCONVERT)} -o #{t.name} -i #{t.sources.join(" ")}"
|
|
end
|
|
end
|
|
|
|
# man pages from DocBook XML
|
|
rule '.1' => '.xml' do |t|
|
|
filter = lambda do |code, lines|
|
|
if (0 == code) && lines.any? { |line| /^error|parser error/i.match(line) }
|
|
File.unlink(t.name) if File.exists?(t.name)
|
|
result = 1
|
|
puts lines.join('')
|
|
|
|
elsif 0 != code
|
|
result = code
|
|
puts lines.join('')
|
|
|
|
else
|
|
result = 0
|
|
puts lines.join('') if $verbose
|
|
end
|
|
|
|
result
|
|
end
|
|
|
|
stylesheet = "#{c(:DOCBOOK_ROOT)}/manpages/docbook.xsl"
|
|
|
|
if !FileTest.exists?(stylesheet)
|
|
puts "Error: the DocBook stylesheet '#{stylesheet}' does not exist."
|
|
exit 1
|
|
end
|
|
|
|
runq "xsltproc", t.source, "#{c(:XSLTPROC)} #{c(:XSLTPROC_FLAGS)} -o #{t.name} #{stylesheet} #{t.sources.join(" ")}", :filter_output => filter
|
|
end
|
|
|
|
$manpages.each do |manpage|
|
|
file manpage => manpage.ext('xml')
|
|
$available_languages[:manpages].each do |language|
|
|
localized_manpage = manpage.gsub(/.*\//, "doc/man/#{language}/")
|
|
file localized_manpage => localized_manpage.ext('xml')
|
|
end
|
|
end
|
|
|
|
# Qt files
|
|
rule '.h' => '.ui' do |t|
|
|
runq "uic", t.source, "#{c(:UIC)} --translate QTR #{t.sources.join(" ")} > #{t.name}"
|
|
end
|
|
|
|
rule '.moc' => '.h' do |t|
|
|
runq "moc", t.source, "#{c(:MOC)} #{$system_includes} #{$flags[:moc]} -nw #{t.source} > #{t.name}"
|
|
end
|
|
|
|
rule '.moco' => '.moc' do |t|
|
|
cxx_compiler.call t
|
|
end
|
|
|
|
# Tag files
|
|
desc "Create tags file for Emacs"
|
|
task :tags => "TAGS"
|
|
|
|
desc "Create browse file for Emacs"
|
|
task :browse => "BROWSE"
|
|
|
|
file "TAGS" => $all_sources do |t|
|
|
runq 'etags', nil, "#{c(:ETAGS)} -o #{t.name} #{t.prerequisites.join(" ")}"
|
|
end
|
|
|
|
file "BROWSE" => ($all_sources + $all_headers) do |t|
|
|
runq 'ebrowse', nil, "#{c(:EBROWSE)} -o #{t.name} #{t.prerequisites.join(" ")}"
|
|
end
|
|
|
|
file "doc/development.html" => [ "doc/development.md", "doc/pandoc-template.html" ] do |t|
|
|
runq "pandoc", t.prerequisites.first, <<COMMAND
|
|
#{c(:PANDOC)} -o #{t.name} --standalone --from markdown_strict --to html --number-sections --table-of-contents --css=pandoc.css --template=doc/pandoc-template.html doc/development.md
|
|
COMMAND
|
|
end
|
|
|
|
file "po/mkvtoolnix.pot" => $all_sources + $all_headers + $gui_ui_h_files + %w{Rakefile} do |t|
|
|
sources = (t.prerequisites.dup - %w{Rakefile}).sort.uniq
|
|
|
|
keywords = %w{--keyword=Y --keyword=NY:1,2} # singular & plural forms returning std::string
|
|
keywords += %w{--keyword=YT} # singular form returning translatable_string_c
|
|
keywords += %w{--keyword=QTR} # singular form returning QString, used by uic
|
|
keywords += %w{--keyword=QY --keyword=QNY:1,2} # singular & plural forms returning QString
|
|
keywords += %w{--keyword=QYH} # singular form returning HTML-escaped QString
|
|
|
|
flags = %w{Y NY YT QTR QY QNY QYH}.map { |func| "--flag=#{func}:1:no-c-format --flag=#{func}:1:no-boost-format" }.join(" ")
|
|
|
|
options = %w{--default-domain=mkvtoolnix --from-code=UTF-8 --sort-output --language=c++}
|
|
options += ["'--msgid-bugs-address=Moritz Bunkus <moritz@bunkus.org>'"]
|
|
options += ["'--copyright-holder=Moritz Bunkus <moritz@bunkus.org>'", "--package-name=MKVToolNix", "--package-version=#{c(:PACKAGE_VERSION)}", "--foreign-user"]
|
|
|
|
runq "xgettext", t.name, "xgettext #{keywords.join(" ")} #{flags} #{options.join(" ")} -o #{t.name} #{sources.join(" ")}"
|
|
end
|
|
|
|
task :manpages => $manpages
|
|
|
|
$po4a_output_filter = lambda do |code, lines|
|
|
lines = lines.reject { |l| %r{seems outdated.*differ between|please consider running po4a-updatepo|^$}i.match(l) }
|
|
puts lines.join('') unless lines.empty?
|
|
code
|
|
end
|
|
|
|
# Translations for the programs
|
|
namespace :translations do
|
|
desc "Create a template for translating the programs"
|
|
task :pot => "po/mkvtoolnix.pot"
|
|
|
|
desc "Create a new .po file with an empty template"
|
|
task "new-po" => "po/mkvtoolnix.pot" do
|
|
%w{LANGUAGE EMAIL}.each { |e| fail "Variable '#{e}' is not set" if ENV[e].blank? }
|
|
|
|
require 'rexml/document'
|
|
iso639_file = "/usr/share/xml/iso-codes/iso_639.xml"
|
|
node = REXML::XPath.first REXML::Document.new(File.new(iso639_file)), "//iso_639_entry[@name='#{ENV['LANGUAGE']}']"
|
|
locale = node ? node.attributes['iso_639_1_code'] : nil
|
|
if locale.blank?
|
|
if /^ [a-z]{2} (?: _ [A-Z]{2} )? $/x.match(ENV['LANGUAGE'])
|
|
locale = ENV['LANGUAGE']
|
|
else
|
|
fail "Unknown language/ISO-639-1 code not found in #{iso639_file}"
|
|
end
|
|
end
|
|
|
|
puts_action "create", :target => "po/#{locale}.po"
|
|
File.open "po/#{locale}.po", "w" do |out|
|
|
now = Time.now
|
|
email = ENV['EMAIL']
|
|
email = "YOUR NAME <#{email}>" unless /</.match(email)
|
|
header = <<EOT
|
|
# translation of mkvtoolnix.pot to #{ENV['LANGUAGE']}
|
|
# Copyright (C) #{now.year} Moritz Bunkus
|
|
# This file is distributed under the same license as the MKVToolNix package.
|
|
#
|
|
msgid ""
|
|
EOT
|
|
|
|
content = IO.
|
|
readlines("po/mkvtoolnix.pot").
|
|
join("").
|
|
gsub(/\A.*?msgid ""\n/m, header).
|
|
gsub(/^"PO-Revision-Date:.*?$/m, %{"PO-Revision-Date: #{now.strftime('%Y-%m-%d %H:%M%z')}\\n"}).
|
|
gsub(/^"Last-Translator:.*?$/m, %{"Last-Translator: #{email}\\n"}).
|
|
gsub(/^"Language-Team:.*?$/m, %{"Language-Team: #{ENV['LANGUAGE']} <moritz@bunkus.org>\\n"}).
|
|
gsub(/^"Language: \\n"$/, %{"Language: #{locale}\\n"})
|
|
|
|
out.puts content
|
|
end
|
|
|
|
puts "Remember to look up the plural forms in this document:\nhttp://docs.translatehouse.org/projects/localization-guide/en/latest/l10n/pluralforms.html"
|
|
end
|
|
|
|
def verify_format_strings languages
|
|
is_ok = true
|
|
|
|
languages.
|
|
collect { |language| "po/#{language}.po" }.
|
|
sort.
|
|
each do |file_name|
|
|
puts "VERIFY #{file_name}"
|
|
is_ok &&= FormatStringVerifier.new.verify file_name
|
|
end
|
|
|
|
is_ok
|
|
end
|
|
|
|
desc "Verify format strings in translations"
|
|
task "verify-format-strings" do
|
|
languages = (ENV['LANGUAGES'] || '').split(/ +/)
|
|
languages = $available_languages[:programs] if languages.empty?
|
|
|
|
exit 1 if !verify_format_strings(languages)
|
|
end
|
|
|
|
desc "Verify format strings in staged translations"
|
|
task "verify-format-strings-staged" do
|
|
languages = `git --no-pager diff --cached --name-only`.
|
|
split(/\n/).
|
|
select { |file| /po\/.*\.po$/.match(file) }.
|
|
map { |file| file.gsub(/.*\//, '').gsub(/\.po/, '') }
|
|
|
|
if languages.empty?
|
|
puts "Error: Nothing staged"
|
|
exit 2
|
|
end
|
|
|
|
|
|
exit 1 if !verify_format_strings(languages)
|
|
end
|
|
|
|
$all_po_files.each do |po_file|
|
|
task "normalize-po-#{po_file}" do
|
|
normalize_po po_file
|
|
end
|
|
end
|
|
|
|
desc "Normalize all .po files to a standard format"
|
|
task "normalize-po" => $all_po_files.map { |e| "translations:normalize-po-#{e}" }
|
|
|
|
[ :programs, :manpages ].each { |type| task type => $translations[type] }
|
|
|
|
task :qt => FileList[ "#{$source_dir }/po/qt/*.ts" ].collect { |file| file.ext 'qm' }
|
|
|
|
if c?(:PO4A_WORKS)
|
|
$available_languages[:manpages].each do |language|
|
|
$manpages.each do |manpage|
|
|
name = manpage.gsub(/man\//, "man/#{language}/")
|
|
file name => [ name.ext('xml'), "doc/man/po4a/po/#{language}.po" ]
|
|
file name.ext('xml') => [ manpage.ext('.xml'), "doc/man/po4a/po/#{language}.po" ] do |t|
|
|
runq "po4a", "#{manpage.ext('.xml')} (#{language})", "#{c(:PO4A_TRANSLATE)} #{c(:PO4A_TRANSLATE_FLAGS)} -m #{manpage.ext('.xml')} -p doc/man/po4a/po/#{language}.po -l #{t.name}", :filter_output => $po4a_output_filter
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
desc "Update all translation files"
|
|
task :update => [ "translations:update:programs", "translations:update:manpages", "translations:update:translations" ]
|
|
|
|
namespace :update do
|
|
desc "Update the program's translation files"
|
|
task :programs => [ "po/mkvtoolnix.pot", ] + $available_languages[:programs].collect { |language| "translations:update:programs:#{language}" }
|
|
|
|
namespace :programs do
|
|
$available_languages[:programs].each do |language|
|
|
task language => "po/mkvtoolnix.pot" do |t|
|
|
po = "po/#{language}.po"
|
|
tmp_file = "#{po}.new"
|
|
no_wrap = $unwrapped_po.include?(language) ? "" : "--no-wrap"
|
|
runq "msgmerge", po, "msgmerge -q -s #{no_wrap} #{po} po/mkvtoolnix.pot > #{tmp_file}", :allow_failure => true
|
|
|
|
exit_code = last_exit_code
|
|
if 0 != exit_code
|
|
File.unlink tmp_file
|
|
exit exit_code
|
|
end
|
|
|
|
FileUtils.move tmp_file, po
|
|
|
|
normalize_po po
|
|
end
|
|
end
|
|
end
|
|
|
|
if c?(:PO4A_WORKS)
|
|
desc "Update the man pages' translation files"
|
|
task :manpages do
|
|
runq "po4a", "doc/man/po4a/po4a.cfg", "#{c(:PO4A)} #{c(:PO4A_FLAGS)} --msgmerge-opt=--no-wrap doc/man/po4a/po4a.cfg"
|
|
$all_man_po_files.each do |po_file|
|
|
normalize_po po_file
|
|
end
|
|
end
|
|
end
|
|
|
|
desc "Update the Windows installer's translation files"
|
|
task :installer do |t|
|
|
Mtx::Installer.update_all_translation_files
|
|
end
|
|
end
|
|
|
|
namespace :transifex do
|
|
transifex_pull_targets = {
|
|
"man-pages" => [],
|
|
"programs" => [],
|
|
}
|
|
|
|
transifex_push_targets = {
|
|
"man-pages" => [],
|
|
"programs" => [],
|
|
}
|
|
|
|
$all_po_files.each do |po_file|
|
|
language = /\/([^\/]+)\.po$/.match(po_file)[1]
|
|
resource = /doc\/man/.match(po_file) ? "man-pages" : "programs"
|
|
pull_target = "pull-#{resource}-#{language}"
|
|
push_target = "push-#{resource}-#{language}"
|
|
|
|
transifex_pull_targets[resource] << "translations:transifex:#{pull_target}"
|
|
transifex_push_targets[resource] << "translations:transifex:#{push_target}"
|
|
|
|
desc "Fetch and merge #{resource} translations from Transifex (#{language})" if list_targets?("transifex", "transifex_pull")
|
|
task pull_target => :no_unstaged_changes do
|
|
transifex_pull_and_merge resource, language
|
|
end
|
|
|
|
desc "Push #{resource} translations to Transifex (#{language})" if list_targets?("transifex", "transifex_push")
|
|
task push_target => :no_unstaged_changes do
|
|
transifex_remove_fuzzy_and_push resource, language
|
|
end
|
|
end
|
|
|
|
desc "Fetch and merge program translations from Transifex"
|
|
task "pull-programs" => transifex_pull_targets["programs"]
|
|
|
|
desc "Fetch and merge man page translations from Transifex"
|
|
task "pull-man-pages" => transifex_pull_targets["man-pages"]
|
|
|
|
desc "Fetch and merge all translations from Transifex"
|
|
task "pull" => transifex_pull_targets.values.flatten
|
|
|
|
desc "Push program translation source file to Transifex"
|
|
task "push-programs-source" => "po/mkvtoolnix.pot" do
|
|
runq "tx push", "po/mkvtoolnix.pot", "tx push -s -r mkvtoolnix.programs > /dev/null"
|
|
end
|
|
|
|
desc "Push man page translation source file to Transifex"
|
|
task "push-man-pages-source" => "doc/man/po4a/po/mkvtoolnix.pot" do
|
|
runq "tx push", "doc/man/po4a/po/mkvtoolnix.pot", "tx push -s -r mkvtoolnix.man-pages > /dev/null"
|
|
end
|
|
desc "Push program translations to Transifex"
|
|
task "push-programs" => transifex_push_targets["programs"]
|
|
|
|
desc "Push man page translations to Transifex"
|
|
task "push-man-pages" => transifex_push_targets["man-pages"]
|
|
|
|
desc "Push all translations to Transifex"
|
|
task "push" => transifex_push_targets.values.flatten
|
|
end
|
|
|
|
[ :stats, :statistics ].each_with_index do |task_name, idx|
|
|
desc "Generate statistics about translation coverage" if 0 == idx
|
|
task task_name do
|
|
FileList["po/*.po", "doc/man/po4a/po/*.po"].each do |name|
|
|
command = "msgfmt --statistics -o /dev/null #{name} 2>&1"
|
|
if $verbose
|
|
runq "msgfmt", name, command, :allow_failure => true
|
|
else
|
|
puts "#{name} : " + `#{command}`.split(/\n/).first
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
# HTML generation for the man pages
|
|
targets = ([ 'en' ] + $languages[:manpages]).collect do |language|
|
|
dir = language == 'en' ? '' : "/#{language}"
|
|
FileList[ "doc/man#{dir}/*.xml" ].collect { |name| "man2html:#{language}:#{File.basename(name, '.xml')}" }
|
|
end.flatten
|
|
|
|
%w{manpages-html man2html}.each_with_index do |task_name, idx|
|
|
desc "Create HTML files for the man pages" if 0 == idx
|
|
task task_name => targets
|
|
end
|
|
|
|
namespace :man2html do
|
|
xsl_source_dir = "doc/stylesheets"
|
|
docbook_html_xsl = FileList[ "#{xsl_source_dir}/*.xsl" ].map { |f| f.gsub(%r{.*/}, '') }
|
|
|
|
([ 'en' ] + $languages[:manpages]).collect do |language|
|
|
namespace language do
|
|
dir = language == 'en' ? '' : "/#{language}"
|
|
xml = FileList[ "doc/man#{dir}/*.xml" ].to_a
|
|
html = xml.map { |name| name.ext(".html") }
|
|
|
|
translated_xsls = docbook_html_xsl.map { |xsl| "doc/man#{dir}/#{xsl}" }
|
|
po_file = language == 'en' ? nil : "doc/man/po4a/po/#{language}.po"
|
|
|
|
docbook_html_xsl.each do |xsl|
|
|
file "doc/man#{dir}/#{xsl}" => [ "#{xsl_source_dir}/#{xsl}", po_file ].compact do |t|
|
|
if language == 'en'
|
|
FileUtils.copy(t.prerequisites.first, t.name)
|
|
else
|
|
runq "po4a", "#{t.prerequisites.first} (#{language})", "#{c(:PO4A_TRANSLATE)} #{c(:PO4A_TRANSLATE_FLAGS)} -m #{t.prerequisites.first} -p doc/man/po4a/po/#{language}.po -l #{t.name}", :filter_output => $po4a_output_filter
|
|
end
|
|
end
|
|
end
|
|
|
|
xml.each do |name|
|
|
file name.ext('html') => ([ name ] + translated_xsls) do
|
|
runq "saxon-he", name, "java -classpath lib/saxon-he/saxon9he.jar net.sf.saxon.Transform -o:#{name.ext('html')} '-xsl:doc/man#{dir}/docbook-to-html.xsl' '#{name}'"
|
|
end
|
|
|
|
task File.basename(name, '.xml') => name.ext('html')
|
|
end
|
|
|
|
task :all => html
|
|
end
|
|
end
|
|
end
|
|
|
|
# Developer helper tasks
|
|
namespace :dev do
|
|
if $build_mkvtoolnix_gui
|
|
desc "Update Qt resource files"
|
|
task "update-qt-resources" do
|
|
update_qrc
|
|
end
|
|
|
|
desc "Update Qt project file"
|
|
task "update-qt-project" do
|
|
project_file = "src/mkvtoolnix-gui/mkvtoolnix-gui.pro"
|
|
content = []
|
|
skipping = false
|
|
IO.readlines(project_file).collect { |line| line.chomp }.each do |line|
|
|
content << line unless skipping
|
|
|
|
if /^FORMS\b/.match line
|
|
skipping = true
|
|
content << $gui_ui_files.collect { |ui| ui.gsub!(/.*forms\//, 'forms/'); " #{ui}" }.sort.join(" \\\n")
|
|
|
|
elsif skipping && /^\s*$/.match(line)
|
|
skipping = false
|
|
content << line
|
|
end
|
|
end
|
|
|
|
File.open(project_file, "w") do |file|
|
|
file.puts content.join("\n")
|
|
end
|
|
end
|
|
end
|
|
|
|
desc "Create source code tarball from current version in .."
|
|
task :tarball do
|
|
create_source_tarball
|
|
end
|
|
|
|
desc "Create source code tarball from current version in .. with git revision in name"
|
|
task "tarball-rev" do
|
|
revision = `git rev-parse --short HEAD`.chomp
|
|
create_source_tarball "-#{revision}"
|
|
end
|
|
|
|
desc "Dump dependencies of the task given with TASK environment variable"
|
|
task "dependencies" do
|
|
if ENV['TASK'].blank?
|
|
puts "'TASK' environment variable not set"
|
|
exit 1
|
|
end
|
|
|
|
task = Rake::Task[ENV['TASK']]
|
|
if !task
|
|
puts "No task named '#{ENV['MTASK']}'"
|
|
exit 1
|
|
end
|
|
|
|
prereqs = task.mo_all_prerequisites
|
|
longest = prereqs.map { |p| p[0].length }.max
|
|
|
|
puts prereqs.map { |p| sprintf("%-#{longest}s => %s", p[0], p[1].sort.join(" ")) }.join("\n")
|
|
end
|
|
|
|
desc "Create iso639_language_list.cpp from online ISO code lists"
|
|
task :iso639_list do
|
|
create_iso639_language_list_file
|
|
end
|
|
|
|
desc "Create iso3166_country_list.cpp from online ISO & UN code lists"
|
|
task :iso3166_list do
|
|
create_iso3166_country_list_file
|
|
end
|
|
|
|
desc "Create iso15924_script_list.cpp from online ISO script list"
|
|
task :iso15924_list do
|
|
create_iso15924_script_list_file
|
|
end
|
|
|
|
desc "Create iana_language_subtag_registry_list.cpp from online IANA registry"
|
|
task :iana_language_subtag_registry_list do
|
|
Mtx::IANALanguageSubtagRegistry.create_cpp
|
|
end
|
|
|
|
desc "Create all auto-generated lists"
|
|
task :lists => [ :iso639_list, :iso3166_list, :iso15924_list, :iana_language_subtag_registry_list ]
|
|
end
|
|
|
|
# Installation tasks
|
|
desc "Install all applications and support files"
|
|
targets = [ "install:programs", "install:manpages", "install:translations:programs" ]
|
|
targets += [ "install:translations:manpages" ] if c?(:PO4A_WORKS)
|
|
targets += [ "install:shared" ] if c?(:BUILD_GUI)
|
|
task :install => targets
|
|
|
|
namespace :install do
|
|
application_name_mapper = lambda do |name|
|
|
File.basename name
|
|
end
|
|
|
|
task :programs => $applications do
|
|
install_dir :bindir
|
|
$applications.each { |application| install_program "#{c(:bindir)}/#{application_name_mapper[application]}", application }
|
|
end
|
|
|
|
task :shared do
|
|
install_dir :desktopdir, :mimepackagesdir
|
|
install_data :mimepackagesdir, FileList[ "#{$source_dir}/share/mime/*.xml" ]
|
|
if c?(:BUILD_GUI)
|
|
install_dir :appdatadir
|
|
install_data :desktopdir, "#{$source_dir}/share/desktop/org.bunkus.mkvtoolnix-gui.desktop"
|
|
install_data :appdatadir, "#{$source_dir}/share/metainfo/org.bunkus.mkvtoolnix-gui.appdata.xml"
|
|
end
|
|
|
|
wanted_apps = %w{mkvmerge mkvtoolnix-gui mkvinfo mkvextract mkvpropedit}.collect { |e| "#{e}.png" }.to_hash_by
|
|
wanted_dirs = %w{16x16 24x24 32x32 48x48 64x64 96x96 128x128 256x256}.to_hash_by
|
|
dirs_to_install = FileList[ "#{$source_dir}/share/icons/*" ].select { |dir| wanted_dirs[ dir.gsub(/.*icons\//, '').gsub(/\/.*/, '') ] }.sort.uniq
|
|
|
|
dirs_to_install.each do |dir|
|
|
dest_dir = "#{c(:icondir)}/#{dir.gsub(/.*icons\//, '')}/apps"
|
|
install_dir dest_dir
|
|
install_data "#{dest_dir}/", FileList[ "#{dir}/*" ].to_a.select { |file| wanted_apps[ file.gsub(/.*\//, '') ] }
|
|
end
|
|
|
|
if c?(:BUILD_GUI)
|
|
sounds_dir ="#{c(:pkgdatadir)}/sounds"
|
|
|
|
install_dir sounds_dir
|
|
install_data sounds_dir, FileList["#{$source_dir}/share/sounds/*"]
|
|
end
|
|
end
|
|
|
|
man_page_name_mapper = lambda do |name|
|
|
File.basename name
|
|
end
|
|
|
|
task :manpages => $manpages do
|
|
install_dir :man1dir
|
|
$manpages.each { |manpage| install_data "#{c(:man1dir)}/#{man_page_name_mapper[manpage]}", manpage }
|
|
end
|
|
|
|
namespace :translations do
|
|
task :programs => $translations[:programs] do
|
|
install_dir $languages[:programs].collect { |language| "#{c(:localedir)}/#{language}/LC_MESSAGES" }
|
|
$languages[:programs].each do |language|
|
|
install_data "#{c(:localedir)}/#{language}/LC_MESSAGES/mkvtoolnix.mo", "po/#{language}.mo"
|
|
end
|
|
end
|
|
|
|
if c?(:PO4A_WORKS)
|
|
task :manpages => $translations[:manpages] do
|
|
install_dir $languages[:manpages].collect { |language| "#{c(:mandir)}/#{language}/man1" }
|
|
$languages[:manpages].each do |language|
|
|
$manpages.each { |manpage| install_data "#{c(:mandir)}/#{language}/man1/#{man_page_name_mapper[manpage]}", manpage.sub(/man\//, "man/#{language}/") }
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
# Cleaning tasks
|
|
desc "Remove all compiled files"
|
|
task :clean do
|
|
puts_action "clean"
|
|
|
|
patterns = %w{
|
|
**/*.a
|
|
**/*.autosave
|
|
**/*.deps
|
|
**/*.dll
|
|
**/*.exe
|
|
**/*.exe
|
|
**/*.mo
|
|
**/*.moc
|
|
**/*.moco
|
|
**/*.o
|
|
**/*.pot
|
|
**/*.qm
|
|
doc/man/*.1
|
|
doc/man/*.html
|
|
doc/man/*.xsl
|
|
doc/man/*/*.1
|
|
doc/man/*/*.html
|
|
doc/man/*/*.xml
|
|
doc/man/*/*.xsl
|
|
lib/libebml/ebml/ebml_export.h
|
|
packaging/windows/msix/assets/*.png
|
|
src/*/qt_resources.cpp
|
|
src/**/manifest.xml
|
|
src/info/ui/*.h
|
|
src/mkvtoolnix-gui/forms/**/*.h
|
|
src/benchmark/benchmark
|
|
tests/unit/all
|
|
tests/unit/merge/merge
|
|
tests/unit/propedit/propedit
|
|
}
|
|
patterns += $applications + $tools.collect { |name| "src/tools/#{name}" }
|
|
patterns += PCH.clean_patterns
|
|
patterns << $version_header_name
|
|
|
|
remove_files_by_patterns patterns
|
|
|
|
if Dir.exists? $dependency_dir
|
|
puts_vaction "rm -rf", :target => "#{$dependency_dir}"
|
|
FileUtils.rm_rf $dependency_dir
|
|
end
|
|
end
|
|
|
|
namespace :clean do
|
|
desc "Remove all compiled and generated files ('tarball' clean)"
|
|
task :dist => :clean do
|
|
run "rm -f config.h config.log config.cache build-config TAGS src/mkvtoolnix-gui/static_plugins.cpp #{Mtx::CompilationDatabase.database_file_name}", :allow_failure => true
|
|
end
|
|
|
|
desc "Remove all compiled and generated files ('git' clean)"
|
|
task :maintainer => "clean:dist" do
|
|
run "rm -f configure config.h.in", :allow_failure => true
|
|
end
|
|
|
|
desc "Remove compiled objects and programs in the unit test suite"
|
|
task :unittests do
|
|
patterns = %w{tests/unit/*.o tests/unit/*/*.o tests/unit/*.a tests/unit/*/*.a}
|
|
patterns += $gtest_apps.collect { |app| "tests/unit/#{app}/#{app}" }
|
|
remove_files_by_patterns patterns
|
|
end
|
|
end
|
|
|
|
# Tests
|
|
desc "Run all tests"
|
|
task :tests => [ 'tests:products' ]
|
|
namespace :tests do
|
|
desc "Run product tests from 'tests' sub-directory (requires data files to be present)"
|
|
task :products do
|
|
run "cd tests && ./run.rb"
|
|
end
|
|
|
|
desc "Run built-in tests on source code files"
|
|
task :source do
|
|
Mtx::SourceTests.test_include_guards
|
|
end
|
|
end
|
|
|
|
#
|
|
# avilib-0.6.10
|
|
# librmff
|
|
# spyder's MPEG parser
|
|
# src/common
|
|
# src/input
|
|
# src/output
|
|
#
|
|
|
|
# libraries required for all programs via mtxcommon
|
|
$common_libs = [
|
|
:flac,
|
|
:z,
|
|
:pugixml,
|
|
:intl,
|
|
:iconv,
|
|
:fmt,
|
|
:stdcppfs,
|
|
:qt_non_gui,
|
|
:gmp,
|
|
"-lstdc++",
|
|
]
|
|
|
|
$common_libs += [:cmark] if c?(:BUILD_GUI)
|
|
$common_libs += [:dvdread] if c?(:USE_DVDREAD)
|
|
$common_libs += [:exchndl] if c?(:USE_DRMINGW) && $building_for[:windows]
|
|
if !$libmtxcommon_as_dll
|
|
$common_libs = [
|
|
:matroska,
|
|
:ebml,
|
|
] + $common_libs
|
|
end
|
|
$common_libs += [ :CoreFoundation ] if $building_for[:macos]
|
|
|
|
[ { :name => 'avi', :dir => 'lib/avilib-0.6.10' },
|
|
{ :name => 'fmt', :dir => 'lib/fmt/src', :except => [ 'fmt.cc'] },
|
|
{ :name => 'rmff', :dir => 'lib/librmff' },
|
|
{ :name => 'pugixml', :dir => 'lib/pugixml/src' },
|
|
{ :name => 'mpegparser', :dir => 'src/mpegparser' },
|
|
{ :name => 'mtxcommon', :dir => [ 'src/common' ] + FileList['src/common/*'].select { |e| FileTest.directory? e } },
|
|
{ :name => 'mtxinput', :dir => 'src/input' },
|
|
{ :name => 'mtxoutput', :dir => 'src/output' },
|
|
{ :name => 'mtxmerge', :dir => 'src/merge', :except => [ 'mkvmerge.cpp' ], },
|
|
{ :name => 'mtxextract', :dir => 'src/extract', :except => [ 'mkvextract.cpp' ], },
|
|
{ :name => 'mtxpropedit', :dir => 'src/propedit', :except => [ 'mkvpropedit.cpp' ], },
|
|
{ :name => 'ebml', :dir => 'lib/libebml/src' },
|
|
{ :name => 'matroska', :dir => 'lib/libmatroska/src' },
|
|
].each do |lib|
|
|
Library.
|
|
new("#{[ lib[:dir] ].flatten.first}/lib#{lib[:name]}").
|
|
sources([ lib[:dir] ].flatten, :type => :dir, :except => lib[:except]).
|
|
only_if(lib[:name] == 'mtxcommon').
|
|
qt_dependencies_and_sources("common").
|
|
end_if.
|
|
only_if($libmtxcommon_as_dll && (lib[:name] == 'mtxcommon')).
|
|
build_dll(true).
|
|
libraries(:matroska, :ebml, $common_libs,:qt).
|
|
end_if.
|
|
create
|
|
end
|
|
|
|
$common_libs.unshift(:mtxcommon)
|
|
|
|
# custom libraries
|
|
$custom_libs = [
|
|
:static,
|
|
]
|
|
|
|
#
|
|
# mkvmerge
|
|
#
|
|
|
|
Application.new("src/mkvmerge").
|
|
description("Build the mkvmerge executable").
|
|
aliases(:mkvmerge).
|
|
sources("src/merge/mkvmerge.cpp").
|
|
sources("src/merge/resources.o", :if => $building_for[:windows]).
|
|
libraries(:mtxmerge, :mtxinput, :mtxoutput, :mtxmerge, $common_libs, :avi, :rmff, :mpegparser, :vorbis, :ogg, $custom_libs).
|
|
create
|
|
|
|
#
|
|
# mkvinfo
|
|
#
|
|
|
|
Application.new("src/mkvinfo").
|
|
description("Build the mkvinfo executable").
|
|
aliases(:mkvinfo).
|
|
sources(FileList["src/info/*.cpp"]).
|
|
sources("src/info/resources.o", :if => $building_for[:windows]).
|
|
libraries($common_libs, $custom_libs).
|
|
create
|
|
|
|
#
|
|
# mkvextract
|
|
#
|
|
|
|
Application.new("src/mkvextract").
|
|
description("Build the mkvextract executable").
|
|
aliases(:mkvextract).
|
|
sources("src/extract/mkvextract.cpp").
|
|
sources("src/extract/resources.o", :if => $building_for[:windows]).
|
|
libraries(:mtxextract, $common_libs, :avi, :rmff, :vorbis, :ogg, $custom_libs).
|
|
create
|
|
|
|
#
|
|
# mkvpropedit
|
|
#
|
|
|
|
Application.new("src/mkvpropedit").
|
|
description("Build the mkvpropedit executable").
|
|
aliases(:mkvpropedit).
|
|
sources("src/propedit/propedit.cpp").
|
|
sources("src/propedit/resources.o", :if => $building_for[:windows]).
|
|
libraries(:mtxpropedit, $common_libs, $custom_libs).
|
|
create
|
|
|
|
#
|
|
# mkvtoolnix-gui
|
|
#
|
|
|
|
if $build_mkvtoolnix_gui
|
|
qrc = [ "src/mkvtoolnix-gui/qt_resources.qrc" ]
|
|
|
|
add_qrc_dependencies(*qrc)
|
|
|
|
file "src/mkvtoolnix-gui/qt_resources.cpp" => qrc, &qrc_compiler
|
|
|
|
Application.new("src/mkvtoolnix-gui/mkvtoolnix-gui").
|
|
description("Build the mkvtoolnix-gui executable").
|
|
aliases("mkvtoolnix-gui").
|
|
qt_dependencies_and_sources("mkvtoolnix-gui").
|
|
sources("src/mkvtoolnix-gui/qt_resources.cpp").
|
|
sources("src/mkvtoolnix-gui/resources.o", :if => $building_for[:windows]).
|
|
libraries($common_libs - [ :qt_non_gui ], :qt, :vorbis, :ogg).
|
|
libraries("-mwindows", :powrprof, :if => $building_for[:windows]).
|
|
libraries("-framework IOKit", :if => $building_for[:macos]).
|
|
libraries($custom_libs).
|
|
create
|
|
end
|
|
|
|
#
|
|
# benchmark
|
|
#
|
|
|
|
if c?(:GOOGLE_BENCHMARK) && !$benchmark_sources.empty?
|
|
Application.new("src/benchmark/benchmark").
|
|
description("Build the benchmark executable").
|
|
aliases(:benchmark, :bench).
|
|
sources($benchmark_sources).
|
|
libraries($common_libs, :benchmark, :qt).
|
|
create
|
|
end
|
|
|
|
#
|
|
# Applications in src/tools
|
|
#
|
|
namespace :apps do
|
|
task :tools => $tools.collect { |name| "apps:tools:#{name}" }
|
|
end
|
|
|
|
#
|
|
# tools
|
|
#
|
|
$tool_sources = {
|
|
"ebml_validator" => ["ebml_validator", "element_info"],
|
|
}
|
|
$tools.each do |tool|
|
|
Application.new("src/tools/#{tool}").
|
|
description("Build the #{tool} executable").
|
|
aliases("tools:#{tool}").
|
|
sources(* ($tool_sources[tool] || [tool]).map { |src| "src/tools/#{src}.cpp" }).
|
|
libraries($common_libs).
|
|
create
|
|
end
|
|
|
|
# Engage pch system
|
|
PCH.engage(&cxx_compiler)
|
|
|
|
$build_system_modules.values.each { |bsm| bsm[:define_tasks].call if bsm[:define_tasks] }
|
|
|
|
# Local Variables:
|
|
# mode: ruby
|
|
# End:
|