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

update conan new modern templates #9516

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
208 changes: 185 additions & 23 deletions conans/assets/templates/new_v2_cmake.py
@@ -1,5 +1,6 @@
conanfile_sources_v2 = """from conans import ConanFile
from conan.tools.cmake import CMakeToolchain, CMake
from conan.tools.layout import cmake_layout


class {package_name}Conan(ConanFile):
Expand All @@ -26,9 +27,7 @@ def config_options(self):
del self.options.fPIC

def layout(self):
self.folders.source = "src"
self.folders.build = "build/{{}}".format(self.settings.build_type)
self.folders.generators = "build/generators"
cmake_layout(self)

def generate(self):
tc = CMakeToolchain(self)
Expand All @@ -40,12 +39,8 @@ def build(self):
cmake.build()

def package(self):
self.copy("*.h", dst="include")
self.copy("*.lib", dst="lib", keep_path=False)
self.copy("*.dll", dst="bin", keep_path=False)
self.copy("*.dylib*", dst="lib", keep_path=False)
self.copy("*.so", dst="lib", keep_path=False)
self.copy("*.a", dst="lib", keep_path=False)
cmake = CMake(self)
cmake.install()

def package_info(self):
self.cpp_info.libs = ["{name}"]
Expand All @@ -56,10 +51,13 @@ def package_info(self):

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


class {package_name}TestConan(ConanFile):
settings = "os", "compiler", "build_type", "arch"
# VirtualBuildEnv and VirtualRunEnv can be avoided if "tools.env.virtualenv:auto_use" is defined
# (it will be defined in Conan 2.0)
generators = "CMakeDeps", "CMakeToolchain", "VirtualBuildEnv", "VirtualRunEnv"
apply_env = False

Expand All @@ -68,22 +66,19 @@ def build(self):
cmake.configure()
cmake.build()

def layout(self):
cmake_layout(self)

def test(self):
if not tools.cross_building(self):
self.run(os.path.sep.join([".", "bin", "example"]), env="conanrunenv")
cmd = os.path.join(self.cpp.build.bindirs[0], "example")
self.run(cmd, env="conanrunenv")
"""


test_cmake_v2 = """cmake_minimum_required(VERSION 3.15)
project(PackageTest CXX)

# TODO: Remove this when layouts are available
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${{CMAKE_CURRENT_BINARY_DIR}}/bin)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${{CMAKE_RUNTIME_OUTPUT_DIRECTORY}})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${{CMAKE_RUNTIME_OUTPUT_DIRECTORY}})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${{CMAKE_RUNTIME_OUTPUT_DIRECTORY}})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${{CMAKE_RUNTIME_OUTPUT_DIRECTORY}})

find_package({name} CONFIG REQUIRED)

add_executable(example example.cpp)
Expand All @@ -95,6 +90,14 @@ def test(self):
project({name} CXX)

add_library({name} {name}.cpp)

set_target_properties({name} PROPERTIES PUBLIC_HEADER "{name}.h")
install(TARGETS {name} DESTINATION "."
PUBLIC_HEADER DESTINATION include
RUNTIME DESTINATION bin
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
)
"""


Expand All @@ -110,14 +113,91 @@ def test(self):
"""


source_cpp = """#include <iostream>
source_cpp = r"""#include <iostream>
#include "{name}.h"

void {name}(){{
#ifdef NDEBUG
std::cout << "{name}/{version}: Hello World Release!" <<std::endl;
std::cout << "{name}/{version}: Hello World Release!\n";
#else
std::cout << "{name}/{version}: Hello World Debug!" <<std::endl;
std::cout << "{name}/{version}: Hello World Debug!\n";
#endif

// ARCHITECTURES
#ifdef _M_X64
std::cout << " {name}/{version}: _M_X64 defined\n";
#endif

#ifdef _M_IX86
std::cout << " {name}/{version}: _M_IX86 defined\n";
#endif

#if __i386__
std::cout << " {name}/{version}: __i386__ defined\n";
#endif

#if __x86_64__
std::cout << " {name}/{version}: __x86_64__ defined\n";
#endif

// Libstdc++
#if defined _GLIBCXX_USE_CXX11_ABI
std::cout << " {name}/{version}: _GLIBCXX_USE_CXX11_ABI "<< _GLIBCXX_USE_CXX11_ABI << "\n";
#endif

// COMPILER VERSIONS
#if _MSC_VER
std::cout << " {name}/{version}: _MSC_VER" << _MSC_VER<< "\n";
#endif

#if _MSVC_LANG
std::cout << " {name}/{version}: _MSVC_LANG" << _MSVC_LANG<< "\n";
#endif

#if __cplusplus
std::cout << " {name}/{version}: __cplusplus" << __cplusplus<< "\n";
#endif

#if __INTEL_COMPILER
std::cout << " {name}/{version}: __INTEL_COMPILER" << __INTEL_COMPILER<< "\n";
#endif

#if __GNUC__
std::cout << " {name}/{version}: __GNUC__" << __GNUC__<< "\n";
#endif

#if __GNUC_MINOR__
std::cout << " {name}/{version}: __GNUC_MINOR__" << __GNUC_MINOR__<< "\n";
#endif

#if __clang_major__
std::cout << " {name}/{version}: __clang_major__" << __clang_major__<< "\n";
#endif

#if __clang_minor__
std::cout << " {name}/{version}: __clang_minor__" << __clang_minor__<< "\n";
#endif

#if __apple_build_version__
std::cout << " {name}/{version}: __apple_build_version__" << __apple_build_version__<< "\n";
#endif

// SUBSYSTEMS

#if __MSYS__
std::cout << " {name}/{version}: __MSYS__" << __MSYS__<< "\n";
#endif

#if __MINGW32__
std::cout << " {name}/{version}: __MINGW32__" << __MINGW32__<< "\n";
#endif

#if __MINGW64__
std::cout << " {name}/{version}: __MINGW64__" << __MINGW64__<< "\n";
#endif

#if __CYGWIN__
std::cout << " {name}/{version}: __CYGWIN__" << __CYGWIN__<< "\n";
#endif
}}
"""
Expand All @@ -131,7 +211,7 @@ def test(self):
"""


def get_files(name, version, package_name="Pkg"):
def get_cmake_lib_files(name, version, package_name="Pkg"):
files = {"conanfile.py": conanfile_sources_v2.format(name=name, version=version,
package_name=package_name),
"src/{}.cpp".format(name): source_cpp.format(name=name, version=version),
Expand All @@ -140,6 +220,88 @@ def get_files(name, version, package_name="Pkg"):
"test_package/conanfile.py": test_conanfile_v2.format(name=name,
version=version,
package_name=package_name),
"test_package/example.cpp": test_main.format(name=name),
"test_package/CMakeLists.txt": test_cmake_v2.format(name=name)}
"test_package/src/example.cpp": test_main.format(name=name),
"test_package/src/CMakeLists.txt": test_cmake_v2.format(name=name)}
return files


conanfile_exe = """from conans import ConanFile
Copy link
Contributor

Choose a reason for hiding this comment

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

Nonrelated question, are we moving/copying the ConanFile to conan namespace at some point?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, we are.
I didn't want to do it yet, because I am thinking of using the move to clean some potentially breaking things, and the opt-in would be the new import.

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


class {package_name}Conan(ConanFile):
name = "{name}"
version = "{version}"

# Optional metadata
license = "<Put the package license here>"
author = "<Put your name here> <And your email here>"
url = "<Package recipe repository url here, for issues about the package>"
description = "<Description of {package_name} here>"
topics = ("<Put some tag here>", "<here>", "<and here>")

# Binary configuration
settings = "os", "compiler", "build_type", "arch"

# Sources are located in the same place as this recipe, copy them to the recipe
exports_sources = "src/*"

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()
"""

cmake_exe_v2 = """cmake_minimum_required(VERSION 3.15)
project({name} CXX)

add_executable({name} {name}.cpp main.cpp)

install(TARGETS {name} DESTINATION "."
RUNTIME DESTINATION bin
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
)
"""

test_conanfile_exe_v2 = """import os
from conans import ConanFile, tools


class {package_name}TestConan(ConanFile):
settings = "os", "compiler", "build_type", "arch"
# VirtualRunEnv can be avoided if "tools.env.virtualenv:auto_use" is defined
# (it will be defined in Conan 2.0)
generators = "VirtualRunEnv"
apply_env = False

def test(self):
if not tools.cross_building(self):
self.run("{name}", env="conanrunenv")
"""


def get_cmake_exe_files(name, version, package_name="Pkg"):
files = {"conanfile.py": conanfile_exe.format(name=name, version=version,
package_name=package_name),
"src/{}.cpp".format(name): source_cpp.format(name=name, version=version),
"src/{}.h".format(name): source_h.format(name=name, version=version),
"src/main.cpp": test_main.format(name=name),
"src/CMakeLists.txt": cmake_exe_v2.format(name=name, version=version),
"test_package/conanfile.py": test_conanfile_exe_v2.format(name=name,
version=version,
package_name=package_name)
}
return files
9 changes: 6 additions & 3 deletions conans/client/cmd/new.py
Expand Up @@ -387,9 +387,12 @@ def cmd_new(ref, header=False, pure_c=False, test=False, exports_sources=False,
package_name=package_name,
defines=defines)
files = {"conanfile.py": replaced}
elif template == "v2_cmake":
from conans.assets.templates.new_v2_cmake import get_files
files = get_files(name, version, package_name)
elif template == "cmake_lib":
from conans.assets.templates.new_v2_cmake import get_cmake_lib_files
files = get_cmake_lib_files(name, version, package_name)
elif template == "cmake_exe":
from conans.assets.templates.new_v2_cmake import get_cmake_exe_files
files = get_cmake_exe_files(name, version, package_name)
else:
if not os.path.isabs(template):
template = os.path.join(cache.cache_folder, "templates", "command/new", template)
Expand Down
2 changes: 1 addition & 1 deletion conans/test/functional/command/test_command_test.py
Expand Up @@ -12,7 +12,7 @@ class ConanTestTest(unittest.TestCase):
@pytest.mark.tool_cmake
def test_conan_test(self):
client = TestClient()
client.run("new hello/0.1 -m=v2_cmake")
client.run("new hello/0.1 -m=cmake_lib")

client.run("create . lasote/stable -tf=None")
time.sleep(1) # Try to avoid windows errors in CI (Cannot change permissions)
Expand Down
Expand Up @@ -23,7 +23,7 @@ def test_m1(op_system):

client = TestClient(path_with_spaces=False)
client.save({"m1": profile}, clean_first=True)
client.run("new hello/0.1 --template=v2_cmake")
client.run("new hello/0.1 --template=cmake_lib")
client.run("create . --profile:build=default --profile:host=m1 -tf None")

main = gen_function_cpp(name="main", includes=["hello"], calls=["hello"])
Expand Down
23 changes: 19 additions & 4 deletions conans/test/functional/toolchains/cmake/test_v2_cmake_template.py
@@ -1,16 +1,31 @@
from conans.test.utils.tools import TestClient


def test_v2_cmake_template():
def test_cmake_lib_template():
client = TestClient(path_with_spaces=False)
client.run("new hello/0.1 --template=v2_cmake")
client.run("new hello/0.1 --template=cmake_lib")
# Local flow works
client.run("install . -if=install")
client.run("build . -if=install")

# Create works
client.run("create .")
assert "Hello World Release!" in client.out
assert "hello/0.1: Hello World Release!" in client.out

client.run("create . -s build_type=Debug")
assert "Hello World Debug!" in client.out
assert "hello/0.1: Hello World Debug!" in client.out


def test_cmake_exe_template():
client = TestClient(path_with_spaces=False)
client.run("new greet/0.1 --template=cmake_exe")
# Local flow works
client.run("install . -if=install")
client.run("build . -if=install")

# Create works
client.run("create .")
assert "greet/0.1: Hello World Release!" in client.out

client.run("create . -s build_type=Debug")
assert "greet/0.1: Hello World Debug!" in client.out
2 changes: 1 addition & 1 deletion conans/test/functional/toolchains/env/test_complete.py
Expand Up @@ -67,7 +67,7 @@ def build(self):

def test_complete():
client = TestClient()
client.run("new myopenssl/1.0 -m=v2_cmake")
client.run("new myopenssl/1.0 -m=cmake_lib")
client.run("create . -o myopenssl:shared=True")
client.run("create . -o myopenssl:shared=True -s build_type=Debug")

Expand Down
4 changes: 2 additions & 2 deletions conans/test/functional/toolchains/gnu/autotools/test_basic.py
Expand Up @@ -18,7 +18,7 @@
@pytest.mark.tool_autotools()
def test_autotools():
client = TestClient(path_with_spaces=False)
client.run("new hello/0.1 --template=v2_cmake")
client.run("new hello/0.1 --template=cmake_lib")
client.run("create .")

main = gen_function_cpp(name="main", includes=["hello"], calls=["hello"])
Expand Down Expand Up @@ -62,7 +62,7 @@ def build_windows_subsystem(profile, make_program):
"""
# FIXME: cygwin in CI (my local machine works) seems broken for path with spaces
client = TestClient(path_with_spaces=False)
client.run("new hello/0.1 --template=v2_cmake")
client.run("new hello/0.1 --template=cmake_lib")
# TODO: Test Windows subsystems in CMake, at least msys is broken
os.rename(os.path.join(client.current_folder, "test_package"),
os.path.join(client.current_folder, "test_package2"))
Expand Down
Expand Up @@ -35,7 +35,7 @@ def test_ios():

client = TestClient(path_with_spaces=False)
client.save({"m1": profile}, clean_first=True)
client.run("new hello/0.1 --template=v2_cmake")
client.run("new hello/0.1 --template=cmake_lib")
client.run("create . --profile:build=default --profile:host=m1 -tf None")

main = gen_function_cpp(name="main", includes=["hello"], calls=["hello"])
Expand Down
Expand Up @@ -460,7 +460,7 @@ def check_toolchain_win(self, compiler, version, runtime, cppstd):
# Build the profile according to the settings provided
settings = " ".join('-s %s="%s"' % (k, v) for k, v in settings if v)

client.run("new hello/0.1 -m=v2_cmake")
client.run("new hello/0.1 -m=cmake_lib")
client.run("create . hello/0.1@ %s" % (settings, ))

# Prepare the actual consumer package
Expand Down