diff --git a/conans/assets/templates/new_v2_cmake.py b/conans/assets/templates/new_v2_cmake.py index 2ee8a3d8a10..5b9a299b331 100644 --- a/conans/assets/templates/new_v2_cmake.py +++ b/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): @@ -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) @@ -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}"] @@ -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 @@ -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) @@ -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 + ) """ @@ -110,14 +113,91 @@ def test(self): """ -source_cpp = """#include +source_cpp = r"""#include #include "{name}.h" void {name}(){{ #ifdef NDEBUG - std::cout << "{name}/{version}: Hello World Release!" <", "", "") + + # 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 diff --git a/conans/client/cmd/new.py b/conans/client/cmd/new.py index 2aefb257cbc..bf1edfcff66 100644 --- a/conans/client/cmd/new.py +++ b/conans/client/cmd/new.py @@ -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) diff --git a/conans/test/functional/command/test_command_test.py b/conans/test/functional/command/test_command_test.py index 5908f7c46ab..ff97e0b37a1 100644 --- a/conans/test/functional/command/test_command_test.py +++ b/conans/test/functional/command/test_command_test.py @@ -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) diff --git a/conans/test/functional/toolchains/cmake/test_cmake_toolchain_m1.py b/conans/test/functional/toolchains/cmake/test_cmake_toolchain_m1.py index 4e75d1635b7..afccf05bb7d 100644 --- a/conans/test/functional/toolchains/cmake/test_cmake_toolchain_m1.py +++ b/conans/test/functional/toolchains/cmake/test_cmake_toolchain_m1.py @@ -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"]) diff --git a/conans/test/functional/toolchains/cmake/test_v2_cmake_template.py b/conans/test/functional/toolchains/cmake/test_v2_cmake_template.py index 9f8cf335426..cfd6c9fa7c7 100644 --- a/conans/test/functional/toolchains/cmake/test_v2_cmake_template.py +++ b/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 diff --git a/conans/test/functional/toolchains/env/test_complete.py b/conans/test/functional/toolchains/env/test_complete.py index f85ea250517..a9b61eca0db 100644 --- a/conans/test/functional/toolchains/env/test_complete.py +++ b/conans/test/functional/toolchains/env/test_complete.py @@ -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") diff --git a/conans/test/functional/toolchains/gnu/autotools/test_basic.py b/conans/test/functional/toolchains/gnu/autotools/test_basic.py index 5971750e538..d5b47bd357f 100644 --- a/conans/test/functional/toolchains/gnu/autotools/test_basic.py +++ b/conans/test/functional/toolchains/gnu/autotools/test_basic.py @@ -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"]) @@ -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")) diff --git a/conans/test/functional/toolchains/gnu/autotools/test_ios.py b/conans/test/functional/toolchains/gnu/autotools/test_ios.py index e6b04021339..51c2b63cbb6 100644 --- a/conans/test/functional/toolchains/gnu/autotools/test_ios.py +++ b/conans/test/functional/toolchains/gnu/autotools/test_ios.py @@ -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"]) diff --git a/conans/test/functional/toolchains/microsoft/test_msbuild.py b/conans/test/functional/toolchains/microsoft/test_msbuild.py index 6ff5b170e63..4c9ff513264 100644 --- a/conans/test/functional/toolchains/microsoft/test_msbuild.py +++ b/conans/test/functional/toolchains/microsoft/test_msbuild.py @@ -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 diff --git a/conans/test/integration/command/new_test.py b/conans/test/integration/command/new_test.py index 2548316e356..2401d9f5053 100644 --- a/conans/test/integration/command/new_test.py +++ b/conans/test/integration/command/new_test.py @@ -377,30 +377,30 @@ def test_new_test_package_custom_name(self): self.assertIn('#include "hello.h"', source) self.assertIn("hello();", source) - def test_new_v2_cmake(self): + def test_new_cmake_lib(self): client = TestClient() - client.run("new pkg/0.1 --template=v2_cmake") + client.run("new pkg/0.1 --template=cmake_lib") conanfile = client.load("conanfile.py") self.assertIn("CMakeToolchain", conanfile) conanfile = client.load("test_package/conanfile.py") self.assertIn("CMakeToolchain", conanfile) - cmake = client.load("test_package/CMakeLists.txt") + cmake = client.load("test_package/src/CMakeLists.txt") self.assertIn("find_package", cmake) def test_new_reference(self): client = TestClient() # full reference - client.run("new MyPackage/1.3@myuser/testing --template=v2_cmake") + client.run("new MyPackage/1.3@myuser/testing --template=cmake_lib") conanfile = client.load("conanfile.py") self.assertIn('name = "MyPackage"', conanfile) self.assertIn('version = "1.3"', conanfile) # no username, no channel (with @) - client.run("new MyPackage/1.3@ --template=v2_cmake") + client.run("new MyPackage/1.3@ --template=cmake_lib") conanfile = client.load("conanfile.py") self.assertIn('version = "1.3"', conanfile) self.assertIn('name = "MyPackage"', conanfile) # no username, no channel (without @) - client.run("new MyPackage/1.3 --template=v2_cmake") + client.run("new MyPackage/1.3 --template=cmake_lib") conanfile = client.load("conanfile.py") self.assertIn('name = "MyPackage"', conanfile) self.assertIn('version = "1.3"', conanfile)