Tidy how we're finding the tags and xsd directories.
authorCarl Hetherington <cth@carlh.net>
Wed, 17 Mar 2021 10:53:28 +0000 (11:53 +0100)
committerCarl Hetherington <cth@carlh.net>
Thu, 18 Mar 2021 22:30:48 +0000 (23:30 +0100)
run/tests
run/tools/dcpverify
src/util.cc
src/util.h
src/verify.cc
src/verify.h
test/encryption_test.cc
test/recovery_test.cc
tools/dcpverify.cc
tools/wscript
wscript

index eb599af4ca50e6496fad7829ca2a07ede609ae5b..adfd48d1f7b7a4a8cc3e5da21e14461d0ad089e8 100755 (executable)
--- a/run/tests
+++ b/run/tests
@@ -13,7 +13,7 @@ dcpverify=build/tools/dcpverify
 export LD_LIBRARY_PATH=build/src:$LD_LIBRARY_PATH
 # SIP stops this being passed in from the caller's environment
 export DYLD_LIBRARY_PATH=/Users/ci/osx-environment/x86_64/lib
-export LIBDCP_SHARE_PREFIX=.
+export LIBDCP_RESOURCES=.
 
 # Make sure we have the required tools
 for c in xmlsec1 xmllint; do
index 382a6c67e592429495eeb6679dd9742fae71f74c..eda2d2d78d8653dba6ebf3fb8da81037f9880786 100755 (executable)
@@ -2,6 +2,7 @@
 
 DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
 top=$DIR/../..
+export LIBDCP_RESOURCES=$top
 
 export LD_LIBRARY_PATH=$top/build/src:build/asdcplib/src:$LD_LIBRARY_PATH
 if [ "$1" == "--debug" ]; then
index 7c21c8893e61ceb98282beedcd18f037841b80c4..0b011bf971408183ac227288cc6b4b1292dbb473 100644 (file)
 #include <libxml++/nodes/element.h>
 #include <libxml++/document.h>
 #include <openssl/sha.h>
-#include <boost/filesystem.hpp>
 #include <boost/algorithm/string.hpp>
+#if BOOST_VERSION >= 106100
+#include <boost/dll/runtime_symbol_info.hpp>
+#endif
+#include <boost/filesystem.hpp>
 #include <stdexcept>
 #include <iostream>
 #include <iomanip>
@@ -192,12 +195,7 @@ dcp::init (optional<boost::filesystem::path> tags_directory)
        asdcp_smpte_dict = &ASDCP::DefaultSMPTEDict();
 
        if (!tags_directory) {
-               char* prefix = getenv("LIBDCP_SHARE_PREFIX");
-               if (prefix) {
-                       tags_directory = boost::filesystem::path(prefix) / "tags";
-               } else {
-                       tags_directory = LIBDCP_SHARE_PREFIX "/tags";
-               }
+               tags_directory = resources_directory() / "tags";
        }
 
        load_language_tag_lists (*tags_directory);
@@ -440,3 +438,33 @@ ASDCPErrorSuspender::~ASDCPErrorSuspender ()
        delete _sink;
 }
 
+
+boost::filesystem::path dcp::directory_containing_executable ()
+{
+#if BOOST_VERSION >= 106100
+       return boost::filesystem::canonical(boost::dll::program_location().parent_path());
+#else
+       char buffer[PATH_MAX];
+       ssize_t N = readlink ("/proc/self/exe", buffer, PATH_MAX);
+       return boost::filesystem::path(string(buffer, N)).parent_path();
+#endif
+}
+
+
+boost::filesystem::path dcp::resources_directory ()
+{
+#if defined(LIBDCP_OSX)
+       return directory_containing_executable().parent_path() / "Resources";
+#elif defined(LIBDCP_WINDOWS)
+       return directory_containing_executable().parent_path();
+#else
+       /* We need a way to specify the tags directory for running un-installed binaries */
+       char* prefix = getenv("LIBDCP_RESOURCES");
+       if (prefix) {
+               return prefix;
+       }
+       return directory_containing_executable().parent_path() / "share" / "libdcp";
+#endif
+}
+
+
index d6803cdf32772c9df8c62388a2092458913f58bd..aa26bfaf80688f28ff2ced1f1c9cce00353866c1 100644 (file)
@@ -94,8 +94,8 @@ extern std::string remove_urn_uuid (std::string raw);
  *  by client applications.
  *
  *  @param tags_directory Path to a copy of the tags directory from the source code;
- *  if none is specified libdcp will look for a tags directory inside the environment
- *  variable LIBDCP_SHARE_PREFIX or the LIBDCP_SHARE_PREFIX #defined during the build.
+ *  if none is specified libdcp will look for a tags directory in the environment
+ *  variable LIBDCP_RESOURCES or based on where the current executable is.
  */
 extern void init (boost::optional<boost::filesystem::path> tags_directory = boost::optional<boost::filesystem::path>());
 
@@ -150,6 +150,9 @@ extern std::string unique_string (std::vector<std::string> existing, std::string
 
 extern ASDCP::Dictionary const* asdcp_smpte_dict;
 
+extern boost::filesystem::path directory_containing_executable ();
+extern boost::filesystem::path resources_directory ();
+
 
 class ASDCPErrorSuspender
 {
index 97758e6192e632aae3bf4c498c167a90120818ad..8c36756306511661ba757d7588245c5751c5924f 100644 (file)
@@ -1104,17 +1104,20 @@ dcp::verify (
        vector<boost::filesystem::path> directories,
        function<void (string, optional<boost::filesystem::path>)> stage,
        function<void (float)> progress,
-       boost::filesystem::path xsd_dtd_directory
+       optional<boost::filesystem::path> xsd_dtd_directory
        )
 {
-       xsd_dtd_directory = boost::filesystem::canonical (xsd_dtd_directory);
+       if (!xsd_dtd_directory) {
+               xsd_dtd_directory = resources_directory() / "xsd";
+       }
+       *xsd_dtd_directory = boost::filesystem::canonical (*xsd_dtd_directory);
 
        vector<VerificationNote> notes;
        State state{};
 
        vector<shared_ptr<DCP>> dcps;
        for (auto i: directories) {
-               dcps.push_back (shared_ptr<DCP> (new DCP (i)));
+               dcps.push_back (make_shared<DCP>(i));
        }
 
        for (auto dcp: dcps) {
@@ -1137,7 +1140,7 @@ dcp::verify (
 
                for (auto cpl: dcp->cpls()) {
                        stage ("Checking CPL", cpl->file());
-                       validate_xml (cpl->file().get(), xsd_dtd_directory, notes);
+                       validate_xml (cpl->file().get(), *xsd_dtd_directory, notes);
 
                        if (cpl->any_encrypted() && !cpl->all_encrypted()) {
                                notes.push_back ({VerificationNote::Type::BV21_ERROR, VerificationNote::Code::PARTIALLY_ENCRYPTED});
@@ -1266,7 +1269,7 @@ dcp::verify (
                                if (reel->main_subtitle()) {
                                        verify_main_subtitle_reel (reel->main_subtitle(), notes);
                                        if (reel->main_subtitle()->asset_ref().resolved()) {
-                                               verify_subtitle_asset (reel->main_subtitle()->asset(), stage, xsd_dtd_directory, notes, state);
+                                               verify_subtitle_asset (reel->main_subtitle()->asset(), stage, *xsd_dtd_directory, notes, state);
                                        }
                                        have_main_subtitle = true;
                                } else {
@@ -1276,7 +1279,7 @@ dcp::verify (
                                for (auto i: reel->closed_captions()) {
                                        verify_closed_caption_reel (i, notes);
                                        if (i->asset_ref().resolved()) {
-                                               verify_closed_caption_asset (i->asset(), stage, xsd_dtd_directory, notes);
+                                               verify_closed_caption_asset (i->asset(), stage, *xsd_dtd_directory, notes);
                                        }
                                }
 
@@ -1384,7 +1387,7 @@ dcp::verify (
 
                for (auto pkl: dcp->pkls()) {
                        stage ("Checking PKL", pkl->file());
-                       validate_xml (pkl->file().get(), xsd_dtd_directory, notes);
+                       validate_xml (pkl->file().get(), *xsd_dtd_directory, notes);
                        if (pkl_has_encrypted_assets(dcp, pkl)) {
                                cxml::Document doc ("PackingList");
                                doc.read_file (pkl->file().get());
@@ -1396,7 +1399,7 @@ dcp::verify (
 
                if (dcp->asset_map_path()) {
                        stage ("Checking ASSETMAP", dcp->asset_map_path().get());
-                       validate_xml (dcp->asset_map_path().get(), xsd_dtd_directory, notes);
+                       validate_xml (dcp->asset_map_path().get(), *xsd_dtd_directory, notes);
                } else {
                        notes.push_back ({VerificationNote::Type::ERROR, VerificationNote::Code::MISSING_ASSETMAP});
                }
index 16700127ae49e4f1ffc28c32029a275139ced221..f14382c53dcd55f4dcf37c095397bcbeeb5f370a 100644 (file)
@@ -436,7 +436,7 @@ std::vector<VerificationNote> verify (
        std::vector<boost::filesystem::path> directories,
        boost::function<void (std::string, boost::optional<boost::filesystem::path>)> stage,
        boost::function<void (float)> progress,
-       boost::filesystem::path xsd_dtd_directory
+       boost::optional<boost::filesystem::path> xsd_dtd_directory = boost::optional<boost::filesystem::path>()
        );
 
 std::string note_to_string (dcp::VerificationNote note);
index becd1df77b17dfd5a2cac4d87719ddcdc29c8919..a4246294cba87d5edba07891ef9eabf2c074e252 100644 (file)
@@ -153,10 +153,10 @@ BOOST_AUTO_TEST_CASE (encryption_test)
                "> build/test/xmllint.log 2>&1 < /dev/null"
                );
 
-#ifdef LIBDCP_POSIX
-       BOOST_CHECK_EQUAL (WEXITSTATUS (r), 0);
-#else
+#ifdef LIBDCP_WINDOWS
        BOOST_CHECK_EQUAL (r, 0);
+#else
+       BOOST_CHECK_EQUAL (WEXITSTATUS (r), 0);
 #endif
 
        r = system ("xmlsec1 verify "
@@ -167,9 +167,9 @@ BOOST_AUTO_TEST_CASE (encryption_test)
                "--id-attr:Id http://www.smpte-ra.org/schemas/430-3/2006/ETM:AuthenticatedPrivate "
                    "build/test/encryption_test.kdm.xml > build/test/xmlsec1.log 2>&1 < /dev/null");
 
-#ifdef LIBDCP_POSIX
-       BOOST_CHECK_EQUAL (WEXITSTATUS (r), 0);
-#else
+#ifdef LIBDCP_WINDOWS
        BOOST_CHECK_EQUAL (r, 0);
+#else
+       BOOST_CHECK_EQUAL (WEXITSTATUS (r), 0);
 #endif
 }
index 59e477a305ccadd4a69d027651361a875bc5ae02..1f76b964acc14b3965ff2c3f7cfc9f24ed19bccf 100644 (file)
@@ -52,12 +52,12 @@ BOOST_AUTO_TEST_CASE (recovery)
 
        boost::filesystem::remove_all ("build/test/baz");
        boost::filesystem::create_directories ("build/test/baz");
-       shared_ptr<dcp::MonoPictureAsset> mp (new dcp::MonoPictureAsset (dcp::Fraction (24, 1), dcp::Standard::SMPTE));
-       shared_ptr<dcp::PictureAssetWriter> writer = mp->start_write ("build/test/baz/video1.mxf", false);
+       auto mp = make_shared<dcp::MonoPictureAsset>(dcp::Fraction (24, 1), dcp::Standard::SMPTE);
+       auto writer = mp->start_write ("build/test/baz/video1.mxf", false);
 
        int written_size = 0;
        for (int i = 0; i < 24; ++i) {
-               dcp::FrameInfo info = writer->write (data.data(), data.size());
+               auto info = writer->write (data.data(), data.size());
                BOOST_CHECK_EQUAL (info.hash, "c3c9a3adec09baf2b0bcb65806fbeac8");
                written_size = info.size;
        }
@@ -69,7 +69,7 @@ BOOST_AUTO_TEST_CASE (recovery)
        boost::filesystem::resize_file ("build/test/baz/video2.mxf", 16384 + data.size() * 11);
 
        {
-               FILE* f = fopen ("build/test/baz/video2.mxf", "rb+");
+               auto f = fopen ("build/test/baz/video2.mxf", "rb+");
                rewind (f);
                char zeros[256];
                memset (zeros, 0, 256);
@@ -77,7 +77,7 @@ BOOST_AUTO_TEST_CASE (recovery)
                fclose (f);
        }
 
-#ifdef LIBDCP_POSIX
+#ifndef LIBDCP_WINDOWS
        Kumu::ResetTestRNG ();
 #endif
 
index 5739b71a26a3f6f21a62285c4f4c105b8764167c..f29393ed2baac88cfa45980cefabbb19dcb43e81 100644 (file)
@@ -137,7 +137,7 @@ main (int argc, char* argv[])
 
        vector<boost::filesystem::path> directories;
        directories.push_back (argv[optind]);
-       auto notes = dcp::verify (directories, bind(&stage, quiet, _1, _2), bind(&progress), "xsd");
+       auto notes = dcp::verify (directories, bind(&stage, quiet, _1, _2), bind(&progress));
        dcp::filter_notes (notes, ignore_missing_assets);
 
        bool failed = false;
index 3d07d4b6af2b616f1da11f628661820800d0fdd4..2e0d2761264f328eb16cb7ccf19d52f75ca775ca 100644 (file)
 #
 
 def build(bld):
+    uselib = 'OPENJPEG CXML OPENMP ASDCPLIB_CTH BOOST_FILESYSTEM LIBXML++ XMLSEC1 OPENSSL XERCES DL'
+
     obj = bld(features='cxx cxxprogram')
     obj.use = ['libdcp%s' % bld.env.API_VERSION]
-    obj.uselib = 'OPENJPEG CXML OPENMP ASDCPLIB_CTH BOOST_FILESYSTEM LIBXML++ XMLSEC1 OPENSSL XERCES'
+    obj.uselib = uselib
     obj.source = 'dcpdiff.cc common.cc'
     obj.target = 'dcpdiff'
 
     obj = bld(features='cxx cxxprogram')
     obj.use = ['libdcp%s' % bld.env.API_VERSION]
-    obj.uselib = 'OPENJPEG CXML OPENMP ASDCPLIB_CTH BOOST_FILESYSTEM LIBXML++ XMLSEC1 OPENSSL XERCES'
+    obj.uselib = uselib
     obj.source = 'dcpinfo.cc common.cc'
     obj.target = 'dcpinfo'
 
     obj = bld(features='cxx cxxprogram')
     obj.use = ['libdcp%s' % bld.env.API_VERSION]
-    obj.uselib = 'OPENJPEG CXML OPENMP ASDCPLIB_CTH BOOST_FILESYSTEM LIBXML++ XMLSEC1 OPENSSL XERCES'
+    obj.uselib = uselib
     obj.source = 'dcpverify.cc common.cc'
     obj.target = 'dcpverify'
 
     for f in ['dumpsub', 'decryptmxf', 'kdm', 'thumb', 'recover']:
         obj = bld(features='cxx cxxprogram')
         obj.use = ['libdcp%s' % bld.env.API_VERSION]
-        obj.uselib = 'OPENJPEG CXML OPENMP ASDCPLIB_CTH BOOST_FILESYSTEM LIBXML++ XMLSEC1 OPENSSL XERCES '
+        obj.uselib = uselib
         obj.source = 'dcp%s.cc' % f
         obj.target = 'dcp%s' % f
diff --git a/wscript b/wscript
index 41f996a755a14e32e50bb58c34d5ed676231754e..83344d072c5a9d4eca7dac2bd7a600baf31c20e5 100644 (file)
--- a/wscript
+++ b/wscript
@@ -71,10 +71,10 @@ def configure(conf):
     if int(gcc[0]) >= 4 and int(gcc[1]) > 1:
         conf.env.append_value('CXXFLAGS', ['-Wno-maybe-uninitialized'])
     conf.env.append_value('CXXFLAGS', ['-DLIBDCP_VERSION="%s"' % VERSION])
-    conf.env.append_value('CXXFLAGS', ['-DLIBDCP_SHARE_PREFIX="%s/share/libdcp"' % conf.env['PREFIX']])
 
     conf.env.TARGET_WINDOWS = conf.options.target_windows
     conf.env.TARGET_OSX = sys.platform == 'darwin'
+    conf.env.TARGET_LINUX = not conf.env.TARGET_WINDOWS and not conf.env.TARGET_OSX
     conf.env.ENABLE_DEBUG = conf.options.enable_debug
     conf.env.DISABLE_TESTS = conf.options.disable_tests
     conf.env.DISABLE_BENCHMARKS = conf.options.disable_benchmarks
@@ -82,10 +82,12 @@ def configure(conf):
     conf.env.STATIC = conf.options.static
     conf.env.API_VERSION = API_VERSION
 
-    if conf.options.target_windows:
+    if conf.env.TARGET_WINDOWS:
         conf.env.append_value('CXXFLAGS', '-DLIBDCP_WINDOWS')
-    else:
-        conf.env.append_value('CXXFLAGS', '-DLIBDCP_POSIX')
+    if conf.env.TARGET_OSX:
+        conf.env.append_value('CXXFLAGS', '-DLIBDCP_OSX')
+    if conf.env.TARGET_LINUX:
+        conf.env.append_value('CXXFLAGS', '-DLIBDCP_LINUX')
 
     if conf.env.TARGET_OSX:
         conf.env.append_value('CXXFLAGS', ['-Wno-unused-result', '-Wno-unused-parameter', '-Wno-unused-local-typedef'])
@@ -102,6 +104,9 @@ def configure(conf):
     if not conf.env.TARGET_WINDOWS:
         conf.env.append_value('LINKFLAGS', '-pthread')
 
+    if conf.env.TARGET_LINUX:
+        conf.check(lib='dl', uselib_store='DL', msg='Checking for library dl')
+
     if conf.options.jpeg == 'oj1':
         conf.env.append_value('CXXFLAGS', ['-DLIBDCP_OPENJPEG1'])
     elif conf.options.jpeg == 'oj2':
@@ -167,17 +172,21 @@ def configure(conf):
         # Windows builds are any more reliable
         conf.env.append_value('CXXFLAGS', '-O2')
 
+    # We support older boosts on Linux so we can use the distribution-provided package
+    # on Centos 7, but it's good if we can use 1.61 for boost::dll::program_location()
+    boost_version = ('1.45', '104500') if conf.env.TARGET_LINUX else ('1.61', '106800')
+
     conf.check_cxx(fragment="""
                             #include <boost/version.hpp>\n
-                            #if BOOST_VERSION < 104500\n
+                            #if BOOST_VERSION < %s\n
                             #error boost too old\n
                             #endif\n
                             int main(void) { return 0; }\n
-                            """,
+                            """ % boost_version[1],
                    mandatory=True,
-                   msg='Checking for boost library >= 1.45',
+                   msg='Checking for boost library >= %s' % boost_version[0],
                    okmsg='yes',
-                   errmsg='too old\nPlease install boost version 1.45 or higher.')
+                   errmsg='too old\nPlease install boost version %s or higher.' % boost_version[0])
 
     conf.check_cxx(fragment="""
                            #include <boost/filesystem.hpp>\n
@@ -218,10 +227,14 @@ def build(bld):
     else:
         boost_lib_suffix = ''
 
+    libs="-L${libdir} -ldcp%s -lcxml -lboost_system%s" % (bld.env.API_VERSION, boost_lib_suffix)
+    if bld.env.TARGET_LINUX:
+        libs += " -ldl"
+
     bld(source='libdcp%s.pc.in' % bld.env.API_VERSION,
         version=VERSION,
         includedir='%s/include/libdcp%s' % (bld.env.PREFIX, bld.env.API_VERSION),
-        libs="-L${libdir} -ldcp%s -lcxml -lboost_system%s" % (bld.env.API_VERSION, boost_lib_suffix),
+        libs=libs,
         install_path='${LIBDIR}/pkgconfig')
 
     bld.recurse('src')