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

Add example of editable package with custom src folder layout #156

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
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, and an unusual layout) -")


# 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")
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")
run(f"cmake --preset {prefix_preset_name}default")
run(f"cmake --build --preset {prefix_preset_name}release")
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")
cmd_out = run("../build_hello/build/Release/hello.exe")
assert "say/1.0: Hello World Release!" 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/build/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")
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")
cmd_out = run("../build_hello/build/Release/hello.exe")
assert "say/1.0: Bye World Release!" in cmd_out
else:
run(f"cmake --build --preset {prefix_preset_name}release")
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}")
Original file line number Diff line number Diff line change
@@ -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)
Original file line number Diff line number Diff line change
@@ -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()
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#include "say.h"

int main() {
say();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
cmake_minimum_required(VERSION 3.15)
project(say CXX)

add_subdirectory(thelib/src)
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
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")
Comment on lines +21 to +24
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This validate() seems unrelated to the example, I'd say it should be simplified and removed, and the example focused on the custom layout.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The point of validate() was to ensure the build of "say" had the flag set. That flag was set by the consumer.
The original example built "say" without any influence from the consumer.
If you attempted to build this example with the same procedure as the other example (ie conan-install "say" directly), then it should fail.
Perhaps that should be a different example?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re simplification, I got rid of the Debug build. It was there in the original example.
Can I also get rid of the "beta9" stuff?
I didn't test on Windows, do I really need the cmake --preset conan-default windows specialisation?
Seems weird that it is different on Windows.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you give me a place where it should be moved?
Are you able to help with the HTML linking?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The point of validate() was to ensure the build of "say" had the flag set. That flag was set by the consumer.

I might still be missing something. The option is not used at all for the build, is it? If it doesn't have any effect on the layout, the build or anything, it still doesn't seem related to an example that is focused on the custom source folder. This would be a completely different use case, which is setting options from consumers, but this still doesn't seem related to the current example of the layout().


def layout(self):
cmake_layout(self)

# 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)
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"]
Original file line number Diff line number Diff line change
@@ -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")
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include <iostream>
#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
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

#ifdef WIN32
#define say_EXPORT __declspec(dllexport)
#else
#define say_EXPORT
#endif

say_EXPORT void say();