From 9b9397d077995af72e25dcf0c330fa115cde45a6 Mon Sep 17 00:00:00 2001 From: Paul Harris Date: Fri, 19 Jul 2024 12:01:37 +0800 Subject: [PATCH 1/3] Add example of editable package with custom src folder layout Also gives an example where the consumer applies additional options to the dependency library. --- .../ci_test_example.py | 80 +++++++++++++++++++ .../hello/CMakeLists.txt | 8 ++ .../hello/conanfile.py | 23 ++++++ .../hello/src/hello.cpp | 5 ++ .../say/CMakeLists.txt | 4 + .../editable_cmake_packages/say/conanfile.py | 46 +++++++++++ .../say/thelib/src/CMakeLists.txt | 6 ++ .../say/thelib/src/say.cpp | 10 +++ .../say/thelib/src/say.h | 9 +++ 9 files changed, 191 insertions(+) create mode 100644 tutorial/developing_packages/editable_cmake_packages/ci_test_example.py create mode 100644 tutorial/developing_packages/editable_cmake_packages/hello/CMakeLists.txt create mode 100644 tutorial/developing_packages/editable_cmake_packages/hello/conanfile.py create mode 100644 tutorial/developing_packages/editable_cmake_packages/hello/src/hello.cpp create mode 100644 tutorial/developing_packages/editable_cmake_packages/say/CMakeLists.txt create mode 100644 tutorial/developing_packages/editable_cmake_packages/say/conanfile.py create mode 100644 tutorial/developing_packages/editable_cmake_packages/say/thelib/src/CMakeLists.txt create mode 100644 tutorial/developing_packages/editable_cmake_packages/say/thelib/src/say.cpp create mode 100644 tutorial/developing_packages/editable_cmake_packages/say/thelib/src/say.h diff --git a/tutorial/developing_packages/editable_cmake_packages/ci_test_example.py b/tutorial/developing_packages/editable_cmake_packages/ci_test_example.py new file mode 100644 index 00000000..be247a22 --- /dev/null +++ b/tutorial/developing_packages/editable_cmake_packages/ci_test_example.py @@ -0,0 +1,80 @@ +import platform +import os + +from conan import conan_version + +from test.examples_tools import run, chdir, replace + + +print("- Editable packages (cmake_layout with separate build folders) -") + + +# FIXME: remove once 2.0-beta10 is out +prefix_preset_name = "" if "beta9" in str(conan_version) else "conan-" +editable_add_argument = "say/1.0" if "beta9" in str(conan_version) else "--name=say --version=1.0" +editable_remove_argument = "say/1.0" if "beta9" in str(conan_version) else "--refs=say/1.0" + +run(f"conan editable add --output-folder build_say say {editable_add_argument}") + +# Set up the conan generators folders +# Use the consumer to generate the ../build_say/*/generators folders +with chdir("hello"): + if platform.system() == "Windows": + run("conan install . -s build_type=Release --output-folder ../build_hello") + run("conan install . -s build_type=Debug --output-folder ../build_hello") + else: + run("conan install . -s build_type=Release --output-folder ../build_hello") + +# Build the dependency explicitly (no need for conan-install, that was done by consumer in previous step) +# This step could be skipped if conan install (above) included --build=editable +with chdir("say"): + if platform.system() == "Windows": + # This step was done by hello ... run("conan install . -s build_type=Release") + # This step was done by hello ... run("conan install . -s build_type=Debug") + run(f"cmake --preset {prefix_preset_name}default") + run(f"cmake --build --preset {prefix_preset_name}release") + run(f"cmake --build --preset {prefix_preset_name}debug") + else: + # This step was done by hello ... run("conan install . -s build_type=Release") + run(f"cmake --preset {prefix_preset_name}release") + run(f"cmake --build --preset {prefix_preset_name}release") + +# Build the consumer +with chdir("hello"): + if platform.system() == "Windows": + run(f"cmake --preset {prefix_preset_name}default") + run(f"cmake --build --preset {prefix_preset_name}release") + run(f"cmake --build --preset {prefix_preset_name}debug") + cmd_out = run("../build_hello/Release/hello.exe") + assert "say/1.0: Hello World Release!" in cmd_out + cmd_out = run("../build_hello/Debug/hello.exe") + assert "say/1.0: Hello World Debug!" in cmd_out + else: + run(f"cmake --preset {prefix_preset_name}release") + run(f"cmake --build --preset {prefix_preset_name}release") + cmd_out = run("../build_hello/Release/hello") + assert "say/1.0: Hello World Release!" in cmd_out + +# Edit 'say' source code +with chdir("say"): + replace(os.path.join("thelib/src", "say.cpp"), "Hello World", "Bye World") + if platform.system() == "Windows": + run(f"cmake --build --preset {prefix_preset_name}release") + run(f"cmake --build --preset {prefix_preset_name}debug") + else: + run(f"cmake --build --preset {prefix_preset_name}release") + +with chdir("hello"): + if platform.system() == "Windows": + run(f"cmake --build --preset {prefix_preset_name}release") + run(f"cmake --build --preset {prefix_preset_name}debug") + cmd_out = run("../build_hello/Release/hello.exe") + assert "say/1.0: Bye World Release!" in cmd_out + cmd_out = run("../build_hello/Debug/hello.exe") + assert "say/1.0: Bye World Debug!" in cmd_out + else: + run(f"cmake --build --preset {prefix_preset_name}release") + cmd_out = run("../build_hello/Release/hello") + assert "say/1.0: Bye World Release!" in cmd_out + +run(f"conan editable remove {editable_remove_argument}") diff --git a/tutorial/developing_packages/editable_cmake_packages/hello/CMakeLists.txt b/tutorial/developing_packages/editable_cmake_packages/hello/CMakeLists.txt new file mode 100644 index 00000000..e2580ac5 --- /dev/null +++ b/tutorial/developing_packages/editable_cmake_packages/hello/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.15) + +project(Hello) + +find_package(say REQUIRED) + +add_executable(hello src/hello.cpp) +target_link_libraries(hello say::say) diff --git a/tutorial/developing_packages/editable_cmake_packages/hello/conanfile.py b/tutorial/developing_packages/editable_cmake_packages/hello/conanfile.py new file mode 100644 index 00000000..76d99ab3 --- /dev/null +++ b/tutorial/developing_packages/editable_cmake_packages/hello/conanfile.py @@ -0,0 +1,23 @@ +from conan import ConanFile +from conan.tools.cmake import cmake_layout, CMake + + +class HelloConan(ConanFile): + name = "hello" + version = "1.0" + + settings = "os", "compiler", "build_type", "arch" + + generators = "CMakeToolchain", "CMakeDeps" + requires = "say/1.0" + + def layout(self): + cmake_layout(self) + + def configure(self): + self.options["say"].something_custom = True + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() diff --git a/tutorial/developing_packages/editable_cmake_packages/hello/src/hello.cpp b/tutorial/developing_packages/editable_cmake_packages/hello/src/hello.cpp new file mode 100644 index 00000000..1151f50d --- /dev/null +++ b/tutorial/developing_packages/editable_cmake_packages/hello/src/hello.cpp @@ -0,0 +1,5 @@ +#include "say.h" + +int main() { + say(); +} diff --git a/tutorial/developing_packages/editable_cmake_packages/say/CMakeLists.txt b/tutorial/developing_packages/editable_cmake_packages/say/CMakeLists.txt new file mode 100644 index 00000000..d18c026f --- /dev/null +++ b/tutorial/developing_packages/editable_cmake_packages/say/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.15) +project(say CXX) + +add_subdirectory(thelib/src) diff --git a/tutorial/developing_packages/editable_cmake_packages/say/conanfile.py b/tutorial/developing_packages/editable_cmake_packages/say/conanfile.py new file mode 100644 index 00000000..c99b0135 --- /dev/null +++ b/tutorial/developing_packages/editable_cmake_packages/say/conanfile.py @@ -0,0 +1,46 @@ +from conan import ConanFile +from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout + + +class SayConan(ConanFile): + name = "say" + version = "1.0" + + # Binary configuration + settings = "os", "compiler", "build_type", "arch" + options = {"shared": [True, False], "fPIC": [True, False], "something_custom": [True, False]} + default_options = {"shared": False, "fPIC": True, "something_custom": False} + + # Sources are located in the same place as this recipe, copy them to the recipe + exports_sources = "CMakeLists.txt", "src/*", "include/*" + + def config_options(self): + if self.settings.os == "Windows": + del self.options.fPIC + + def validate(self): + # ensure the consumer's options affect this dependency + if not self.options.something_custom: + raise ConanInvalidConfiguration("The consumer should set something_custom=True") + + def layout(self): + cmake_layout(self) + + self.cpp.source.includedirs = ["thelib/src"] + self.cpp.build.libdirs = ["thelib/src"] + + 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 = ["say"] diff --git a/tutorial/developing_packages/editable_cmake_packages/say/thelib/src/CMakeLists.txt b/tutorial/developing_packages/editable_cmake_packages/say/thelib/src/CMakeLists.txt new file mode 100644 index 00000000..66d6b1c5 --- /dev/null +++ b/tutorial/developing_packages/editable_cmake_packages/say/thelib/src/CMakeLists.txt @@ -0,0 +1,6 @@ +add_library(say say.cpp) +# target_include_directories(say PUBLIC include) + +# set_target_properties(say PROPERTIES PUBLIC_HEADER "include/say.h") +install(TARGETS say) +install(FILES say.h DESTINATION "include/say") diff --git a/tutorial/developing_packages/editable_cmake_packages/say/thelib/src/say.cpp b/tutorial/developing_packages/editable_cmake_packages/say/thelib/src/say.cpp new file mode 100644 index 00000000..f4168a4e --- /dev/null +++ b/tutorial/developing_packages/editable_cmake_packages/say/thelib/src/say.cpp @@ -0,0 +1,10 @@ +#include +#include "say.h" + +void say(){ + #ifdef NDEBUG + std::cout << "say/1.0: Hello World Release!\n"; + #else + std::cout << "say/1.0: Hello World Debug!\n"; + #endif +} diff --git a/tutorial/developing_packages/editable_cmake_packages/say/thelib/src/say.h b/tutorial/developing_packages/editable_cmake_packages/say/thelib/src/say.h new file mode 100644 index 00000000..54d92ac1 --- /dev/null +++ b/tutorial/developing_packages/editable_cmake_packages/say/thelib/src/say.h @@ -0,0 +1,9 @@ +#pragma once + +#ifdef WIN32 + #define say_EXPORT __declspec(dllexport) +#else + #define say_EXPORT +#endif + +say_EXPORT void say(); From 832f96779223f49d0950d0ecc61d8a0da80b4e95 Mon Sep 17 00:00:00 2001 From: Paul Harris Date: Sun, 21 Jul 2024 20:11:49 +0800 Subject: [PATCH 2/3] Remove Debug build --- .../ci_test_example.py | 20 +++++-------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/tutorial/developing_packages/editable_cmake_packages/ci_test_example.py b/tutorial/developing_packages/editable_cmake_packages/ci_test_example.py index be247a22..0307ca38 100644 --- a/tutorial/developing_packages/editable_cmake_packages/ci_test_example.py +++ b/tutorial/developing_packages/editable_cmake_packages/ci_test_example.py @@ -6,7 +6,7 @@ from test.examples_tools import run, chdir, replace -print("- Editable packages (cmake_layout with separate build folders) -") +print("- Editable packages (cmake_layout with separate build folders, and an unusual layout) -") # FIXME: remove once 2.0-beta10 is out @@ -21,7 +21,6 @@ with chdir("hello"): if platform.system() == "Windows": run("conan install . -s build_type=Release --output-folder ../build_hello") - run("conan install . -s build_type=Debug --output-folder ../build_hello") else: run("conan install . -s build_type=Release --output-folder ../build_hello") @@ -30,10 +29,8 @@ with chdir("say"): if platform.system() == "Windows": # This step was done by hello ... run("conan install . -s build_type=Release") - # This step was done by hello ... run("conan install . -s build_type=Debug") run(f"cmake --preset {prefix_preset_name}default") run(f"cmake --build --preset {prefix_preset_name}release") - run(f"cmake --build --preset {prefix_preset_name}debug") else: # This step was done by hello ... run("conan install . -s build_type=Release") run(f"cmake --preset {prefix_preset_name}release") @@ -44,15 +41,12 @@ if platform.system() == "Windows": run(f"cmake --preset {prefix_preset_name}default") run(f"cmake --build --preset {prefix_preset_name}release") - run(f"cmake --build --preset {prefix_preset_name}debug") - cmd_out = run("../build_hello/Release/hello.exe") + cmd_out = run("../build_hello/build/Release/hello.exe") assert "say/1.0: Hello World Release!" in cmd_out - cmd_out = run("../build_hello/Debug/hello.exe") - assert "say/1.0: Hello World Debug!" in cmd_out else: run(f"cmake --preset {prefix_preset_name}release") run(f"cmake --build --preset {prefix_preset_name}release") - cmd_out = run("../build_hello/Release/hello") + cmd_out = run("../build_hello/build/Release/hello") assert "say/1.0: Hello World Release!" in cmd_out # Edit 'say' source code @@ -60,21 +54,17 @@ replace(os.path.join("thelib/src", "say.cpp"), "Hello World", "Bye World") if platform.system() == "Windows": run(f"cmake --build --preset {prefix_preset_name}release") - run(f"cmake --build --preset {prefix_preset_name}debug") else: run(f"cmake --build --preset {prefix_preset_name}release") with chdir("hello"): if platform.system() == "Windows": run(f"cmake --build --preset {prefix_preset_name}release") - run(f"cmake --build --preset {prefix_preset_name}debug") - cmd_out = run("../build_hello/Release/hello.exe") + cmd_out = run("../build_hello/build/Release/hello.exe") assert "say/1.0: Bye World Release!" in cmd_out - cmd_out = run("../build_hello/Debug/hello.exe") - assert "say/1.0: Bye World Debug!" in cmd_out else: run(f"cmake --build --preset {prefix_preset_name}release") - cmd_out = run("../build_hello/Release/hello") + cmd_out = run("../build_hello/build/Release/hello") assert "say/1.0: Bye World Release!" in cmd_out run(f"conan editable remove {editable_remove_argument}") From 33aa25a74eb70cd2864c781ddb4e6e0cf96612b6 Mon Sep 17 00:00:00 2001 From: Paul Harris Date: Mon, 12 Aug 2024 13:41:10 +0000 Subject: [PATCH 3/3] Tweaked paths --- .../editable_cmake_packages/say/conanfile.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tutorial/developing_packages/editable_cmake_packages/say/conanfile.py b/tutorial/developing_packages/editable_cmake_packages/say/conanfile.py index c99b0135..6e1a0689 100644 --- a/tutorial/developing_packages/editable_cmake_packages/say/conanfile.py +++ b/tutorial/developing_packages/editable_cmake_packages/say/conanfile.py @@ -26,8 +26,9 @@ def validate(self): def layout(self): cmake_layout(self) - self.cpp.source.includedirs = ["thelib/src"] - self.cpp.build.libdirs = ["thelib/src"] + # adjust the includedirs location, for the editing-mode + self.cpp.source.includedirs = [ os.path.join("thelib","src") ] + self.cpp.build.libdirs = [ os.path.join("thelib","src",self.cpp.build.libdirs[0]) ] def generate(self): tc = CMakeToolchain(self)