mirror of
https://gitlab.com/mbunkus/mkvtoolnix.git
synced 2024-12-25 04:11:44 +00:00
64d2f5e112
The dark mode is only turned on if Windows 10's own dark mode is enabled. This manual dark mode configuration is necessary as Qt itself doesn't support Windows' dark mode yet; see the following bug: https://bugreports.qt.io/browse/QTBUG-72028 This isn't a problem for other operating systems (Linux, macOS…) as Qt uses the system colors there and will use dark colors when the system's colors are set to dark colors, too.
1299 lines
46 KiB
Ruby
1299 lines
46 KiB
Ruby
# coding: utf-8
|
|
|
|
$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/installer"
|
|
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/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?(:USE_QT)
|
|
$build_tools ||= c?(:BUILD_TOOLS)
|
|
|
|
$programs = %w{mkvmerge mkvinfo mkvextract mkvpropedit}
|
|
$programs << "mkvtoolnix-gui" if $build_mkvtoolnix_gui
|
|
$tools = %w{ac3parser base64tool bluray_dump checksum diracparser ebml_validator hevc_dump hevcc_dump vc1parser}
|
|
|
|
$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 += " -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(: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 c?(:USE_QT) && !$building_for[:windows]
|
|
cflags_common += " -DQT_STATICPLUGIN" if c?(:USE_QT) && $building_for[:windows]
|
|
cflags_common += " -DUSE_DRMINGW -I#{c(:DRMINGW_PATH)}/include" if c?(:USE_DRMINGW) && $building_for[:windows]
|
|
cflags_common += " -DMTX_APPIMAGE" if c?(:APPIMAGE_BUILD) && !$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?
|
|
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 = $building_for[:macos] ? "-DSYS_APPLE" : $building_for[:windows] ? "-DSYS_WINDOWS" : ""
|
|
|
|
$flags = {
|
|
:cflags => cflags,
|
|
:cxxflags => cxxflags,
|
|
:ldflags => ldflags,
|
|
:windres => windres,
|
|
:moc => mocflags,
|
|
}
|
|
|
|
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")
|
|
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 << "apps:tools" if $build_tools
|
|
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]
|
|
|
|
if %r{lib/fmt/}.match(source)
|
|
flags.gsub!(%r{-Wpedantic}, '')
|
|
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
|
|
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)} #{c(:QT_CFLAGS)} #{$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
|
|
|
|
# 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)
|
|
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
|
|
|
|
$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 => 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
|
|
([ '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") }
|
|
|
|
xml.each do |name|
|
|
file name.ext('html') => name do
|
|
runq "saxon-he", name, "java -classpath lib/saxon-he/saxon9he.jar net.sf.saxon.Transform -o:#{name.ext('html')} -xsl:doc/stylesheets/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
|
|
require 'rexml/document'
|
|
|
|
qrc = "src/mkvtoolnix-gui/qt_resources.qrc"
|
|
puts_action "UPDATE", :target => qrc
|
|
|
|
doc = REXML::Document.new File.new(qrc)
|
|
|
|
doc.elements.to_a("/RCC/qresource/file").select { |node| %r{icons/}.match(node.text) }.each(&:remove)
|
|
|
|
parent = doc.elements.to_a("/RCC/qresource")[0]
|
|
icons = FileList["share/icons/*/*.png"].sort
|
|
seen = Hash.new
|
|
add_node = lambda do |name_to_add, name_alias|
|
|
node = REXML::Element.new "file"
|
|
node.attributes["alias"] = name_alias.gsub(/share\//, '')
|
|
node.text = "../../#{name_to_add}"
|
|
parent << node
|
|
end
|
|
|
|
icons.each do |file|
|
|
add_node.call(file, file)
|
|
|
|
base_name = file.gsub(%r{.*/|\.png$}, '')
|
|
size = file.gsub(%r{.*/(\d+)x\d+/.*}, '\1').to_i
|
|
name_alias = file.gsub(%r{\.png}, '@2x.png')
|
|
double_size = size * 2
|
|
double_file = "share/icons/#{double_size}x#{double_size}/#{base_name}.png"
|
|
|
|
next unless FileTest.exists?(double_file)
|
|
|
|
add_node.call(double_file, name_alias)
|
|
seen[file.gsub(%r{.*/icons}, 'icons')] = true
|
|
end
|
|
|
|
output = ""
|
|
formatter = REXML::Formatters::Pretty.new 1
|
|
formatter.compact = true
|
|
formatter.width = 9999999
|
|
formatter.write doc, output
|
|
File.open(qrc, "w").write(output.gsub(%r{ +\n}, "\n"))
|
|
|
|
warned = Hash.new
|
|
files = read_files( %w{ui cpp}.map { |ext| FileList["src/mkvtoolnix-gui/**/*.#{ext}"].to_a.reject { |name| %r{qt_resources\.cpp$}.match(name) } }.flatten )
|
|
files.each do |file, lines|
|
|
line_num = 0
|
|
|
|
lines.each do |line|
|
|
line_num += 1
|
|
|
|
line.scan(%r{icons/\d+x\d+/.*?\.png}) do |icon|
|
|
next if seen[icon] || warned[icon]
|
|
next if %r{%}.match(icon)
|
|
|
|
puts "Warning: no double-sized variant found for '#{icon}' (found first in '#{file}:#{line_num}')"
|
|
warned[icon] = true
|
|
end
|
|
end
|
|
end
|
|
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
|
|
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?(:USE_QT)
|
|
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?(:USE_QT)
|
|
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?(:USE_QT)
|
|
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
|
|
**/manifest.xml
|
|
doc/man/*.1
|
|
doc/man/*.html
|
|
doc/man/*/*.1
|
|
doc/man/*/*.html
|
|
doc/man/*/*.xml
|
|
lib/libebml/ebml/ebml_export.h
|
|
src/*/qt_resources.cpp
|
|
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 = [
|
|
:boost_filesystem,
|
|
:boost_regex,
|
|
:boost_system,
|
|
:magic,
|
|
:flac,
|
|
:z,
|
|
:pugixml,
|
|
:intl,
|
|
:iconv,
|
|
:fmt,
|
|
]
|
|
|
|
$common_libs += [:cmark] if c?(:USE_QT)
|
|
$common_libs += [:exchndl] if c?(:USE_DRMINGW) && $building_for[:windows]
|
|
if !$libmtxcommon_as_dll
|
|
$common_libs += [
|
|
:matroska,
|
|
:ebml,
|
|
]
|
|
end
|
|
$common_libs += [ :CoreFoundation ] if $building_for[:macos]
|
|
|
|
[ { :name => 'avi', :dir => 'lib/avilib-0.6.10' },
|
|
{ :name => 'fmt', :dir => 'lib/fmt/src' },
|
|
{ :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(c?(:USE_QT) && (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" ]
|
|
qrc << "lib/QDarkStyleSheet/qdarkstyle/style.qrc" if $building_for[:windows]
|
|
|
|
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).
|
|
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: ac3parser
|
|
#
|
|
Application.new("src/tools/ac3parser").
|
|
description("Build the ac3parser executable").
|
|
aliases("tools:ac3parser").
|
|
sources("src/tools/ac3parser.cpp").
|
|
libraries($common_libs).
|
|
create
|
|
|
|
#
|
|
# tools: base64tool
|
|
#
|
|
Application.new("src/tools/base64tool").
|
|
description("Build the base64tool executable").
|
|
aliases("tools:base64tool").
|
|
sources("src/tools/base64tool.cpp").
|
|
libraries($common_libs).
|
|
create
|
|
|
|
#
|
|
# tools: checksum
|
|
#
|
|
Application.new("src/tools/checksum").
|
|
description("Build the checksum executable").
|
|
aliases("tools:checksum").
|
|
sources("src/tools/checksum.cpp").
|
|
libraries($common_libs).
|
|
create
|
|
|
|
#
|
|
# tools: diracparser
|
|
#
|
|
Application.new("src/tools/diracparser").
|
|
description("Build the diracparser executable").
|
|
aliases("tools:diracparser").
|
|
sources("src/tools/diracparser.cpp").
|
|
libraries($common_libs).
|
|
create
|
|
|
|
#
|
|
# tools: ebml_validator
|
|
#
|
|
Application.new("src/tools/ebml_validator").
|
|
description("Build the ebml_validator executable").
|
|
aliases("tools:ebml_validator").
|
|
sources("src/tools/ebml_validator.cpp", "src/tools/element_info.cpp").
|
|
libraries($common_libs).
|
|
create
|
|
|
|
#
|
|
# tools: hevc_dump
|
|
#
|
|
Application.new("src/tools/hevc_dump").
|
|
description("Build the hevc_dump executable").
|
|
aliases("tools:hevc_dump").
|
|
sources("src/tools/hevc_dump.cpp").
|
|
libraries($common_libs).
|
|
create
|
|
|
|
#
|
|
# tools: hevcs_dump
|
|
#
|
|
Application.new("src/tools/hevcc_dump").
|
|
description("Build the hevcc_dump executable").
|
|
aliases("tools:hevcc_dump").
|
|
sources("src/tools/hevcc_dump.cpp").
|
|
libraries($common_libs).
|
|
create
|
|
|
|
#
|
|
# tools: bluray_dump
|
|
#
|
|
Application.new("src/tools/bluray_dump").
|
|
description("Build the bluray_dump executable").
|
|
aliases("tools:bluray_dump").
|
|
sources("src/tools/bluray_dump.cpp").
|
|
libraries($common_libs).
|
|
create
|
|
|
|
#
|
|
# tools: vc1parser
|
|
#
|
|
Application.new("src/tools/vc1parser").
|
|
description("Build the vc1parser executable").
|
|
aliases("tools:vc1parser").
|
|
sources("src/tools/vc1parser.cpp").
|
|
libraries($common_libs).
|
|
create
|
|
|
|
# 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:
|