-
Notifications
You must be signed in to change notification settings - Fork 990
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] cmake_layout with subproject vs conan.tools.scm.Git #12360
Comments
I'd also have this question. Is this documented feature supported at all? |
Hi all, Sorry @db4 this was not responded back then, it probably fell through the cracks. We would need a bit more detail what is failing, and something that we can actually reproduce. It is not clear why
It seems that Hi @seesturm, if it is the same question, could you please provide those details to understand better the problem? Thanks. |
For demo purposes I've created https://github.com/seesturm/subprj . I can build locally using "conan install ." + "conan build ." in pkg1 folder. But "conan create ." fails for me.
As the original submitter writes, the problem is that the git is not cloned into "b" but into "b/pkg1" which makes CMakeLists.txt end up in "b/pkg1/pkg1". |
Thanks very much for the repro case. diff --git a/pkg1/conanfile.py b/pkg1/conanfile.py
index 74ddfce..0be5162 100644
--- a/pkg1/conanfile.py
+++ b/pkg1/conanfile.py
@@ -2,6 +2,7 @@ from conan import ConanFile
from conan.tools.scm import Git
from conan.tools.files import update_conandata
from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout, CMakeDeps
+from conan.tools.files.files import swap_child_folder
class pkg1Recipe(ConanFile):
@@ -28,6 +29,7 @@ class pkg1Recipe(ConanFile):
sources = self.conan_data["sources"]
git.clone(url=sources["url"], target=".")
git.checkout(commit=sources["commit"])
+ swap_child_folder(self.source_folder, "pkg1")
def generate(self):
deps = CMakeDeps(self) It would be a matter to polish the implementation, find a better name for it, and make it part of the public tools. I am annotating this for next 2.0.3, but if you want to give it a try (don't rely on it, because it is private and will certainly break), that would be useful |
Hi @memsharded,
Unfortunately, I can't. When I started the issue, I tried to make the feature work for Conan 1.x. Recipes that need it haven't been ported to 2.x yet. |
|
Well, I tried your approach with def source(self):
tmp = self.folders.source
self.folders.source = None
with chdir(self, self.source_folder):
shutil.rmtree(os.path.normpath(self.folders.subproject).split(os.sep)[0])
git = tools.Git()
ver = self.conan_data["sources"][self.version]
git.clone(ver["url"])
git.checkout(ver["revision"])
self.folders.source = tmp |
Thanks for pointing this out @db4 I have tried what you suggest, but unfortunately I couldn't make it work. The issue seems to be that |
For the record, here is my implementation of swap_child_folder: def move_child_folder(parent_folder, child_folder):
""" move child_folder subtree into parent_folder """
child_path = os.path.join(parent_folder, child_folder)
for (root, dirs, files) in os.walk(child_path):
rel_root = os.path.relpath(root, child_path)
for d in dirs:
os.makedirs(os.path.join(parent_folder, rel_root, d), exist_ok=True)
for f in files:
shutil.move(os.path.join(root, f), os.path.join(parent_folder, rel_root, f))
# We don't care about empty directories left in child_folder. They don't affect git state
# but cleaning them correctly could be challenging. Consider this case:
# a/a/a/b -> a/a/b
Sure. Note |
#13509 was merged to |
Hi @memsharded Unfortunately, it doesn't work for me: def source(self):
sources = self.conan_data["sources"][self.version]
git = Git(self)
git.clone(url=sources["url"], target=".")
git.checkout(commit=sources["revision"])
src_folder = os.path.normpath(self.source_folder)
dst_folder = os.path.dirname(os.path.dirname(src_folder))
self.output.info(f"{src_folder=} {dst_folder=}")
move_folder_contents(src_folder, dst_folder)
BTW, it would be great if you do |
Hi all, This has been moved to Conan 2 scope, to make sure there isn't any gap or missing thing in Conan 2. The first step is making sure we have a unit test that captures the scenario. This is the current unit test, that is working in Conan 2: def test_move_sources():
pkg = textwrap.dedent("""
import os
from conan import ConanFile
from conan.tools.scm import Git
from conan.tools.files import update_conandata, move_folder_contents
from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout
class pkg1Recipe(ConanFile):
name = "pkg1"
version = "1.0"
settings = "os", "compiler", "arch", "build_type"
def layout(self):
self.folders.root = ".."
self.folders.subproject = "pkg1"
cmake_layout(self)
def export(self):
git = Git(self, self.recipe_folder)
scm_url, scm_commit = git.get_url_and_commit()
update_conandata(self, {"sources": {"commit": scm_commit, "url": scm_url,
"folder": "pkg1"}})
def source(self):
git = Git(self)
sources = self.conan_data["sources"]
git.clone(url=sources["url"], target=".")
git.checkout(commit=sources["commit"])
move_folder_contents(self, os.path.join(self.source_folder, sources["folder"]),
self.source_folder)
def generate(self):
tc = CMakeToolchain(self)
tc.generate()
def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()
def package_info(self):
self.cpp_info.libs = ["pkg1"]
""")
c = TestClient()
c.init_git_repo({"pkg1/conanfile.py": pkg,
"pkg1/CMakeLists.txt": gen_cmakelists()})
c.run("create pkg1")
print(c.out) If you can please have a look, and try to propose changes to the unit test that would capture the issue, that would help a lot, thanks! |
@memsharded , thanks for the timely example! I think this would also work: def source(self):
git = Git(self)
sources = self.conan_data["sources"]
with chdir(self, ".."):
git.fetch_commit(url=sources['url'], commit=sources['commit']) Then we wouldn't need to move files around. I wonder if it'd be possible to teach the Git commands to cd to the It'd also be sort of amazing if we could recognize this sub-project setup and attempt to do a sparse1 checkout too Footnotes |
In Conan 2, the constructor is https://git-scm.com/docs/git-sparse-checkout is still experimental, and might require quite a modern git version, so it sounds a bit too early to make it built-in. At the moment, |
Fair. Our thought process was that Git.fetch_commit is also experimental, and also requires a recent git (partial clone, shallow clone, and sparse checkout are all only mainstream in the last few years, though the implementation aremuch older). I think As far as doing it yourself, the problem is you can't configure sparse filters before But while we have some repos with multiple packages, they are not enormous monorepos, so it's only a nice-to-have. |
Some of the features or at least the modern interfaces are way newer like git 2.25, as seen in https://github.blog/2020-01-17-bring-your-monorepo-down-to-size-with-sparse-checkout. From what I see in those posts, this is far from trivial, and giving this is a nice to have (performance) it seems too much of an effort at the moment. As the conversation has also deviated from the original post and the layout question has been responded, I am closing this ticket. If someone wants to contribute it, I think it should have no big risk if it can be limited to an opt-in method in the |
I'm trying to make layout with multiple subprojects work. My sources are stored in a git repo organized as follows:
Trying to build them in Conan cache I wrote
This doesn't work: git.clone() clones the whole git repo inside
pkg1
subfolder and cmake.configure() fails. What's the recommended way to use scm.Git with package layout feature?The text was updated successfully, but these errors were encountered: