conan icon indicating copy to clipboard operation
conan copied to clipboard

[question] Packaging NuttX libs with circular dependencies

Open sastel opened this issue 1 year ago • 2 comments

What is your question?

Hi! I have a question about the recommended way to deal with a set of imported CMake libs with circular dependencies in Conan. I'm building the NuttX project as a set of lib*.a files using NuttX makefiles, then treating them as imported targets in cmake. It appears that when you do this in NuttX you have to link your executable with the --start-group, --end-group flags around the set of libs to resolve all of the circular dependencies. This is how the NuttX make export target is used in an example in the documentation, and is also how the PX4 project links the NuttX libs.

I haven't been able to figure out how to get a consuming package to link my package (nuttxbsp::nuttxbsp) such that the NuttX libs are inside a link group. The code below shows my workaround, which was to place the list of libs in the exelinkflags.

This workaround is no good, because any lib that depends on the NuttX libs also needs to be part of the link group or be set in front of the link group in the linker command. I haven't been able to figure out how to get Conan to put the link group last in the linker command.

The package_info method from my NuttX package conanfile.py:

     def package_info(self):
         nuttx_libs = ["boards", "drivers", "fs", "sched", "crypto", "binfmt", "xx", "apps", "arch", "mm", "c", "net", "drivers_board"]
         module_libs = ["example"]

         # Binaries to link
         self.cpp_info.libs = module_libs # + nuttx_libs?

         # Directories
         self.cpp_info.includedirs = ['include/libcxx', 'include']  # Ordered list of include paths
         self.cpp_info.libdirs = ['lib']  # Directories where libraries can be found
...

         # We haven't been able to get cmake in the consuming package to place the nuttxbsp::nuttxbsp .a files
         # within --start-group and --end-group. The workaround we are using is to force the link group to be
         # used by the consuming package via self.cpp_info.exelinkflags.
         lib_path = os.path.join(self.package_folder, "lib")
         script_path = os.path.join(self.package_folder, "scripts")
         archives = [f"{lib_path}/lib{lib}.a" for lib in nuttx_libs]
         self.cpp_info.exelinkflags = ["-Wl,--start-group", *archives, "-Wl,--end-group"]

What is the recommended way to solve this problem?

Have you read the CONTRIBUTING guide?

  • [X] I've read the CONTRIBUTING guide

sastel avatar May 16 '24 17:05 sastel

Should I combine all of the NuttX static libs into one static lib?

sastel avatar May 16 '24 18:05 sastel

I tried modifying the components example as follows:

diff --git a/examples/conanfile/package_info/components/test_package/CMakeLists.txt b/examples/conanfile/package_info/components/test_package/CMakeLists.txt
index 9863ebf..dd7b2f0 100644
--- a/examples/conanfile/package_info/components/test_package/CMakeLists.txt
+++ b/examples/conanfile/package_info/components/test_package/CMakeLists.txt
@@ -5,7 +5,11 @@ find_package(game-engine REQUIRED COMPONENTS algorithms network ai rendering)

 add_executable(example src/example.cpp)

-target_link_libraries(example algorithms
-                              network
-                              ai
-                              rendering)
+target_link_libraries(example
+    -Wl,--start-group
+          algorithms
+          network
+          ai
+          rendering
+    -Wl,--end-group
+)
diff --git a/examples/conanfile/package_info/components/test_package/conanfile.py b/examples/conanfile/package_info/components/test_package/conanfile.py
index c0cd8d4..fba39a2 100644
--- a/examples/conanfile/package_info/components/test_package/conanfile.py
+++ b/examples/conanfile/package_info/components/test_package/conanfile.py
@@ -20,7 +20,7 @@ class game_engineTestConan(ConanFile):
     def build(self):
         cmake = CMake(self)
         cmake.configure()
-        cmake.build()
+        cmake.build(cli_args=["-v"])

     def layout(self):
         cmake_layout(self)

This is the resulting link behaviour in the test_package:

...
[100%] Linking CXX executable example
/usr/bin/cmake -E cmake_link_script CMakeFiles/example.dir/link.txt --verbose=1
/usr/bin/c++ -m64 -O3 -DNDEBUG -m64 CMakeFiles/example.dir/src/example.cpp.o -o example   -L/home/sstel/.conan2/p/b/game-b7d96689c1423/p/lib  -Wl,-rpath,/home/sstel/.conan2/p/b/game-b7d96689c1423/p/lib -Wl,--start-group -Wl,--end-group /home/sstel/.conan2/p/b/game-b7d96689c1423/p/lib/libnetwork.a /home/sstel/.conan2/p/b/game-b7d96689c1423/p/lib/libai.a /home/sstel/.conan2/p/b/game-b7d96689c1423/p/lib/librendering.a /home/sstel/.conan2/p/b/game-b7d96689c1423/p/lib/libalgorithms.a
...

As you can see, the link group -Wl,--start-group -Wl,--end-group is empty.

sastel avatar May 16 '24 19:05 sastel

Solved with an alternative approach in https://github.com/conan-io/conan/issues/16340.

sastel avatar May 27 '24 21:05 sastel

Hi @sastel

Sorry this wasn't responded back then, though we try our best to support quickly, the activity in the multiple repos can be too high and some tickets might fall through the cracks. Don't hesitate to ping or comment in the threads as necessary to resurface the tickets in our inboxes. Many thanks!

memsharded avatar May 27 '24 22:05 memsharded

@memsharded no worries. Next time I'll ping. 😄

sastel avatar May 28 '24 00:05 sastel

See also: https://github.com/conan-io/conan/issues/6530 It is a challenge to deal with libraries in the wild that have circular dependencies using Conan.

sastel avatar May 29 '24 14:05 sastel