Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[question] autotools with CFLAGS/LDFLAGS #16202

Open
1 task done
nikoladsp opened this issue May 5, 2024 · 5 comments
Open
1 task done

[question] autotools with CFLAGS/LDFLAGS #16202

nikoladsp opened this issue May 5, 2024 · 5 comments
Assignees

Comments

@nikoladsp
Copy link

What is your question?

Hi,
I have to use a library (GraphicsMagick) that does not have CMake/Conan recipe. It depends on couple of other libraries that do have Conan recipe: libpng and libwebp (to name just a few).

I would like to make a Conan package so I can use it as other libraries - something like:

class ConanGraphicsMagick(ConanFile):
    name = "graphicsmagick"
    version = "1.3.42"
    package_type = "library"

    # Optional metadata
    license = "MIT"
    author = "Nikola Radovanovic <nikoladsp@gmail.com>"
    homepage = "http://www.graphicsmagick.org/"
    description = "GraphicsMagick is the swiss army knife of image processing"
    topics = ("image", "processing", "portable")

    # Binary configuration
    settings = "os", "compiler", "build_type", "arch"
    options = {"shared": [True, False], "fPIC": [True, False]}
    default_options = {"shared": True, "fPIC": False}

    implicit_deps = {
        "libwebp/1.4.0": {"shared": True},
        "libpng/1.6.43": {"shared": True},
    }

    def source(self):
        zip_name = f"GraphicsMagick-{self.version}.tar.xz"
        download(self, f"https://deac-fra.dl.sourceforge.net/project/{self.name}/{self.name}/{self.version}/{zip_name}?viasf=1", zip_name)
        # check_sha1(self, zip_name, "a48ec3fa59d9ca0915e1e6f78fd8bda55e9e0c6f")
        unzip(self, zip_name, strip_root=True)
        os.unlink(zip_name)

    def requirements(self):
        for dep, opts in self.implicit_deps.items():
            self.requires(dep, options=opts)

    def build(self):
        print("BUILD")

        # export CFLAGS and LFLAGS
        #self.run("./configure --enable-shared --disable-static --with-magick-plus-plus --with-webp --with-png --with-jpg --without-xml --without-x --without-perl --without-gs")
        #self.run("make V=1")

    def package(self):
        print("PACKAGE")

But I need to find out libpng and libwebp include and library directories in Conan cache prior running ./configure. Those have to match "shared" version (since "static" version of these libraries maybe exists in cache). Also, how to set output folder path/name?

Many thanks.

Have you read the CONTRIBUTING guide?

  • I've read the CONTRIBUTING guide
@memsharded memsharded self-assigned this May 5, 2024
@memsharded
Copy link
Member

Hi @nikoladsp

Thanks for your question.

The responsibility of extracting the information from dependencies and generating the necessary files for the build systems to locate the dependencies is the one of generators() and the generate() method. You can experiment a bit with:

def generate(self):
     deps = CMakeDeps(self)  # or deps = MSBuildDeps(self), or deps = PkgConfigDeps(self)...
     deps.generate()

And see how it works.
Then you need to do your own mapping from dependencies to your specific build system, you can access the dependencies via:

def generate(self):
     for require, dep in self.dependencies.host.items():
          dep.package_folder
          dep.cpp_info.includedirs
          dep.cpp_info.libdirs
          ...

Check https://docs.conan.io/2/reference/conanfile/methods/generate.html#conan-conanfile-model-dependencies for more information about dependencies and cpp_info in https://docs.conan.io/2/reference/conanfile/methods/generate.html#dependencies-cpp-info-interface

Don't worry about the shared one, the self.dependencies will contain the information of the specific packages that have been resolved, if you specified shared, it will be pointing to the shared binaries of the dependencies.

Then, when you know how to generate the files that you want, if you want to reuse it, the recommendation would be to put the code in a common python_requires and reuse it from there in all recipes that you want.

About the "libwebp/1.4.0": {"shared": True}, definition of "shared=True" inside the recipes, please not that in general, it is more robust and easier to specify those things in profile files instead. The reason is that there might be other recipes competing for having shared=False, and the first one to specify it wins, so the only guarantee to have them as shared is to specify that in the profile files.

Please let me know if this helps.

@nikoladsp
Copy link
Author

Many thanks for your answer - I will try it later today or tomorrow morning.

Just to check my understanding: I need to get package location (where include and lib are stored) so I can prepend CFLAGS and LDFLAGS when doing ./configure - so autotools can find it? Also, what I have to set --prefix to?

Kindest regards

@memsharded
Copy link
Member

Just to check my understanding: I need to get package location (where include and lib are stored) so I can prepend CFLAGS and LDFLAGS when doing ./configure - so autotools can find it? Also, what I have to set --prefix to?

Well, we already have the AutotoolsDeps generator, which is very close what you are trying to do, if I understand correctly. It is true that it doesn't work for Windows yet, but it does in Linux. Please check https://docs.conan.io/2/reference/tools/gnu/autotoolsdeps.html and try it, to see how it works.

You have the implementation here if you want to start from there: https://github.com/conan-io/conan/blob/develop2/conan/tools/gnu/autotoolsdeps.py

Also, what I have to set --prefix to?

The --prefix is for the current installation of the current package, isn't it? Note that you can also use bare copy() inside the package() method, very often it is easier than implementing installation steps, depending on the project.

In the case of the Autotools helper, it is using DESTDIR for this purpose:

def install(self, args=None, target="install"):

@nikoladsp
Copy link
Author

nikoladsp commented May 7, 2024

I did play a bit with suggested readings and realized that maybe I should of ask: "Is it possible to build package with autotools but in such way it can be consumed by CMake"? Majority of packages I am using are available via Conan recipes - but there will be couple of exceptions to this rule. Shall I make custom generate() method based on say PkgConfigDeps or completely custom generator that will help other team members to consume packages from their CMake projects?

@memsharded
Copy link
Member

I did play a bit with suggested readings and realized that maybe I should of ask: "Is it possible to build package with autotools but in such way it can be consumed by CMake"?

Absolutely. Conan packages are intended to be created with any build system and be consumed with any other build system. All packages in ConanCenter use different build systems, and there are already tons of packages using CMake consuming packages built with autotools, meson, etc.

Shall I make custom generate() method based on say PkgConfigDeps or completely custom generator that will help other team members to consume packages from their CMake projects?

The key here is the package_info() and the cpp_info abstractions. As long as it is filled correctly, the generators on the consumers side will be able to map that information to their respective build systems. PkgConfigDeps generates .pc files from the information in package_info() of its depenencies, and CMakeDeps generates .cmake files from exactly the same information of the dependencies.

If using CMake, they might be able to use the built-in CMakeToolchain and CMakeDeps, as recommended in the documentation, they can achieve transparent integration (no need to modify their CMakeListst.xt to add Conan-specific things, just using standard CMake)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants