wl2776
wl2776

Reputation: 4327

How to modify conan package during installation phase inside conanfile.py?

Our project uses Unreal Engine 4.26.2 and OpenCV 3.4.0 (yes, we need this old version!) Currently I'm trying to convert existing shell scripts for building Opencv to Conan recipes.

Everything went fine until building the final application.

The issue is that both OpenCV and UE contain conflicting definitions of int64 and uint64.

And our shell scripts patch OpenCV headers in the installation directory, like below

Patch file:

--- opencv2/core/hal/interface.old.h    2019-11-26 12:34:40.260333132 +0300
+++ opencv2/core/hal/interface.h    2019-11-26 17:13:27.232585976 +0300
@@ -58,8 +58,8 @@
 #  define CV_BIG_INT(n)   n##I64
 #  define CV_BIG_UINT(n)  n##UI64
 #else
-   typedef int64_t int64;
-   typedef uint64_t uint64;
+//   typedef int64_t int64;
+//   typedef uint64_t uint64;
 #  define CV_BIG_INT(n)   n##LL
 #  define CV_BIG_UINT(n)  n##ULL
 #endif

And outline of the shell script:

git clone --depth=1 https://github.com/opencv/opencv.git -b 3.4.0
git clone --depth=1 https://github.com/opencv/opencv_contrib.git -b 3.4.0

mkdir build
cd build
cmake .. .....
make 
make install

patch -N -p4 $INSTALL_DIR/include/opencv2/core/hal/interface.h $SCRIPT_DIR/opencv_02.patch

How can I do the same thing with Conan?

Here is my conanfile.py:

from conans import ConanFile, CMake, tools

class OpenCVUE4Conan(ConanFile):
    name = "opencv-ue4"
    version = "3.4.0"
    url = ""
    description = "OpenCV custom build for UE4"
    license = "BSD"
    settings = "os", "compiler", "build_type", "arch"
    generators = "cmake"
    exports_sources = 'patches/cmakes.patch', 'patches/check_function.patch
    
    def requirements(self):
        self.requires("ue4util/ue4@adamrehn/profile")
        self.requires("zlib/ue4@adamrehn/{}".format(self.channel))
        self.requires("UElibPNG/ue4@adamrehn/{}".format(self.channel))

    def cmake_flags(self):
        flags = [
            "-DOPENCV_ENABLE_NONFREE=OFF",
              # other flags
         ]

         return flags

    def source(self):
        self.run("git clone --depth=1 https://github.com/opencv/opencv.git -b {}".format(self.version))
        self.run("git clone --depth=1 https://github.com/opencv/opencv_contrib.git -b {}".format(self.version))

    def build(self):
        # Patch OpenCV to avoid build errors
        for p in self.exports_sources:
            if p.endswith(".patch"):
                tools.patch(base_path='opencv', patch_file=p, fuzz=True)

        cmake = CMake(self)
        cmake.configure(source_folder="opencv", args=self.cmake_flags())
        cmake.build()
        cmake.install()

I guess, I should add one more call to tools.patch after cmake.install

Upvotes: 1

Views: 689

Answers (1)

wl2776
wl2776

Reputation: 4327

This was quite obvious: just move respective call to tools.patch after call to cmake.install()

class OpenCVUE4Conan(ConanFile):
...
    # List all patches here, prebuild and post-build, to have them handled by conan
    exports_sources = 'patches/cmakes.patch', 'patches/check_function.patch', 'patches/typedefs.patch'

    # First two patch CMakeLists.txt and rename one of functions in OpenCV sources.
    # Its name `check` conflicts with the macro `check`, defined in UE.
    # The last one is listed above. 
    
...

    def build(self):
        # Patch OpenCV to avoid build errors,
        # but skip `typedefs.patch`
        tools.patch(base_path='opencv', patch_file='patches/cmakes.patch', fuzz=True)
        tools.patch(base_path='opencv', patch_file='patches/check_function.patch', fuzz=True)

        cmake = CMake(self)
        cmake.configure(source_folder="opencv", args=self.cmake_flags())
        cmake.build()
        cmake.install()

        # Apply "typedefs.patch" based on `package_folder`
        tools.patch(base_path=self.package_folder, patch_file="patches/typedefs.patch", fuzz=True)    

Resulting package will compile only in UE-based projects, built with the Unreal Build Tool.

Commented out typedefs are required for building OpenCV itself, but after it they conflict with similar typedefs from UE.

I have studied UE sources but haven't found any reliable way to detect presence of conflicting typedefs.

Alternative way is to use macro __OPENCV_BUILD that OpenCV defines in its CMakeLists.txt to detect that we are building OpenCV and therefore need those typedefs. However, the effect is the same.

Upvotes: 2

Related Questions