conan-io / conan

Conan - The open-source C and C++ package manager
https://conan.io
MIT License
8.25k stars 980 forks source link

[question] Create Conan Package from Source : Recipe and Sources in a Different Repo #10355

Open Ju1He1 opened 2 years ago

Ju1He1 commented 2 years ago

Hey guys, I'd like to create a Conan package from an internally hosted gitlab project I'm currently struggling with the CMake Configure Step.

CMake Error: The source directory "C:/...../build/e9a552ebe8f994398de9ceee972f0ad207df0658" does not appear to contain CMakeLists.txt.

Now my files are getting cloned properly , however the CMakeLists file is is the subdirectory "./hello" How can I point the CMake class to this subdirectory. I could not find Source Dir Property within that class.

Can you help me out here?

Now my conan recipe is pretty simple


class TestConan(ConanFile):
  settings = "os", "compiler", "build_type", "arch"
    options = {"shared": [True, False], "fPIC": [True, False]}
    default_options = {"shared": True, "fPIC": True}
    generators = "cmake"

    def source(self):
        git = tools.Git(folder="hello")
        git.clone("https://github.com/conan-io/hello.git", "master")

    def config_options(self):
        if self.settings.os == "Windows":
            del self.options.fPIC

    def layout(self):
        cmake_layout(self)

    def generate(self):
        tc = CMakeToolchain(self)
        tc.generate()

    def build(self):
        cmake = CMake(self)
        cmake.configure()
        cmake.build()

    def package(self):
        cmake = CMake(self)
        cmake.install()

    def package_info(self):
        self.cpp_info.libs = ["TestConan"]

thx guys :)

memsharded commented 2 years ago

Hi @Ju1He1

I'd say that the problem is that the defined source folder in cmake_layout() does not match the location of the CMakeLists.txt sources you are retrieving in source().

If you check the https://docs.conan.io/en/latest/reference/conanfile/tools/layout.html, you can see that it assumes that the source folder is ".", and CMake and CMakeToolchain will go there to locate a CMakeLists.txt.

You probably want to try cmake.configure(build_script_folder="hello"), to indicate that the CMakeLists.txt is not in the root of the source, but inside a "hello" folder. Please let me know if this helps.

Tips:

Ju1He1 commented 2 years ago

@memsharded thx for your help. This was indeed the issue. After adding

    def build(self):
        cmake = CMake(self)
        cmake.configure(build_script_folder="hello")
        cmake.build()

and removing generators = "cmake"

It does seem to work. However there are 2 warnings. A .sln File (in my case) is generated. However the package folder is empty. I believe this is because of:

TestConan/2.0@couchbase-lite-core/2.0: Calling package() TestConan/2.0@couchbase-lite-core/2.0: CMake command: cmake --install C:...\2.0\build\e9a552ebe8f994398de9ceee972f0ad207df0658\build --config Release --prefix C:/.../2.0/package/e9a552ebe8f994398de9ceee972f0ad207df0658 TestConan/2.0@couchbase-lite-core/2.0: Package 'e9a552ebe8f994398de9ceee972f0ad207df0658' created TestConan/2.0@couchbase-lite-core/2.0: Created package revision c692963cef3616294e079b98d2733468 TestConan/2.0@couchbase-lite-core/2.0: WARN: Using the new toolchains and generators without specifying a build profile (e.g: -pr:b=default) is discouraged and might cause failures and unexpected behavior couchbase-lite-core/2.0@couchbase-lite-core/2.0 package(): WARN: No files in this package!

i checked the install() Method

Do I have to add some sort of self.copy() to the package() Method? From my Understanding self.copy() is not necessary since I'm allready calling CMake install() right?

memsharded commented 2 years ago

A .sln File (in my case) is generated. However the package folder is empty. I believe this is because of:

What do you have in your CMakeLists.txt? Can you copy it? It should contain a "install" section. As an example the conan new hello/0.1 -m=cmake_lib is a fully functional recipe. If your CMakeLists doesn't contain a "install" section, then yes, you should provide self.copy commands in your package() method.

Ju1He1 commented 2 years ago

hey @memsharded thx for your fast reply

To get started I'm using the test Repo from Conan to create a test Dummy Package https://github.com/conan-io/hello.git

So the CMakeLists.txt is located here https://github.com/conan-io/hello/blob/master/CMakeLists.txt

The recipe is hosted in a different repository. The modfied recipy looks like this now

from conan.tools.cmake import CMakeToolchain, CMake
from conan.tools.layout import cmake_layout
from conans import ConanFile, tools

class TestConan(ConanFile):
    name = "conanTest"
    version = "1.0"
    settings = "os", "compiler", "build_type", "arch"
    options = {"shared": [True, False], "fPIC": [True, False]}
    default_options = {"shared": True, "fPIC": True}

    def source(self):
        git = tools.Git(folder="hello")
        git.clone("https://github.com/conan-io/hello.git", "master")

    def config_options(self):
        if self.settings.os == "Windows":
            del self.options.fPIC

    def layout(self):
        cmake_layout(self)

    def generate(self):
        tc = CMakeToolchain(self)
        tc.generate()

    def build(self):
        cmake = CMake(self)
        cmake.configure(build_script_folder="hello")
        cmake.build()

    def package(self):
        cmake = CMake(self)
        cmake.install()

    def package_info(self):
        self.cpp_info.libs = ["TestConan"]

On this recipe I'm calling conan create . conanTest/1.0 --build=missing

to create a package. However this package is empty. Am I missing something? Is this conan test repo not suitable for creating dummy packages?

Edit: it looks like there is no install() in the CMakeLists.txt of this sample project. I'm guessing this is the problem?

memsharded commented 2 years ago

Yes, that is exactly the problem: https://github.com/conan-io/hello/blob/master/CMakeLists.txt does not contain CMake install functionality (you are mixing a repo intended for the legacy integration with the new one).

If you want cmake.install() to work, it assumes that functionality is there, but in your case it isnt. Otherwise you need to do your own self.copy() inside package() method. So your alternatives: