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 requires for conan new cmake_{exe,lib} #12875

Merged
merged 7 commits into from
Jan 12, 2023
Merged
Show file tree
Hide file tree
Changes from 4 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
21 changes: 16 additions & 5 deletions conan/api/subapi/new.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@


class NewAPI:

_NOT_TEMPLATES = "not_templates" # Filename containing filenames of files not to be rendered

def __init__(self, conan_api):
Expand Down Expand Up @@ -84,17 +83,29 @@ def _read_files(self, template_folder):

return template_files, non_template_files


@staticmethod
def render(template_files, definitions):
result = {}
name = definitions.get("name", "Pkg")
definitions["conan_version"] = __version__
definitions["package_name"] = name.replace("-", "_").replace("+", "_").replace(".", "_")

def as_package_name(n):
return n.replace("-", "_").replace("+", "_").replace(".", "_")

def as_name(ref):
ref = as_package_name(ref)
if '/' in ref:
ref = ref[0:ref.index('/')]
return ref

definitions["package_name"] = as_package_name(name)
definitions["as_iterable"] = lambda x: [x] if isinstance(x, str) else x
definitions["as_name"] = as_name
for k, v in template_files.items():
k = Template(k, keep_trailing_newline=True, undefined=StrictUndefined).render(**definitions)
v = Template(v, keep_trailing_newline=True, undefined=StrictUndefined).render(**definitions)
k = Template(k, keep_trailing_newline=True, undefined=StrictUndefined).render(
**definitions)
v = Template(v, keep_trailing_newline=True, undefined=StrictUndefined).render(
**definitions)
if v:
result[k] = v
return result
5 changes: 3 additions & 2 deletions conan/cli/commands/new.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,9 @@ def get_template_vars():
ast = env.parse(templ_str)
template_vars.extend(meta.find_undeclared_variables(ast))

injected_vars = {"conan_version", "package_name"}
template_vars = list(set(template_vars) - injected_vars)
injected_vars = {"conan_version", "package_name", "as_iterable", "as_name"}
optional_vars = {"requires"}
template_vars = list(set(template_vars) - injected_vars - optional_vars)
template_vars.sort()
return template_vars

Expand Down
23 changes: 22 additions & 1 deletion conan/internal/api/new/cmake_exe.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from conan.internal.api.new.cmake_lib import source_cpp, source_h, test_main

conanfile_exe = '''from conan import ConanFile
from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout
from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout, CMakeDeps


class {{package_name}}Recipe(ConanFile):
Expand All @@ -26,6 +26,8 @@ def layout(self):
cmake_layout(self)

def generate(self):
deps = CMakeDeps(self)
deps.generate()
tc = CMakeToolchain(self)
tc.generate()

Expand All @@ -37,13 +39,32 @@ def build(self):
def package(self):
cmake = CMake(self)
cmake.install()

{% if requires is defined -%}
def requirements(self):
{% for require in as_iterable(requires) -%}
self.requires("{{ require }}")
{% endfor %}
{%- endif %}
'''

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

{% if requires is defined -%}
{% for require in as_iterable(requires) -%}
find_package({{as_name(require)}} CONFIG REQUIRED)
{% endfor %}
{%- endif %}

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

{% if requires is defined -%}
{% for require in as_iterable(requires) -%}
target_link_libraries({{name}} PRIVATE {{as_name(require)}}::{{as_name(require)}})
{% endfor %}
{%- endif %}

install(TARGETS {{name}} DESTINATION "."
RUNTIME DESTINATION bin
ARCHIVE DESTINATION lib
Expand Down
50 changes: 45 additions & 5 deletions conan/internal/api/new/cmake_lib.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
conanfile_sources_v2 = '''from conan import ConanFile
from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout
from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout, CMakeDeps


class {{package_name}}Recipe(ConanFile):
Expand Down Expand Up @@ -29,6 +29,8 @@ def layout(self):
cmake_layout(self)

def generate(self):
deps = CMakeDeps(self)
deps.generate()
tc = CMakeToolchain(self)
tc.generate()

Expand All @@ -43,34 +45,66 @@ def package(self):

def package_info(self):
self.cpp_info.libs = ["{{name}}"]

{% if requires is defined -%}
def requirements(self):
{% for require in as_iterable(requires) -%}
self.requires("{{ require }}")
{% endfor %}
{%- endif %}
'''

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

{% if requires is defined -%}
{% for require in as_iterable(requires) -%}
find_package({{as_name(require)}} CONFIG REQUIRED)
{% endfor %}
{%- endif %}


add_library({{name}} src/{{name}}.cpp)
target_include_directories({{name}} PUBLIC include)

{% if requires is defined -%}
{% for require in as_iterable(requires) -%}
target_link_libraries({{name}} PRIVATE {{as_name(require)}}::{{as_name(require)}})
{% endfor %}
{%- endif %}

set_target_properties({{name}} PROPERTIES PUBLIC_HEADER "include/{{name}}.h")
install(TARGETS {{name}})
"""

source_h = """#pragma once

{% set define_name = name.replace("-", "_").replace("+", "_").replace(".", "_").upper() %}
{% set define_name = package_name.upper() %}
#ifdef _WIN32
#define {{define_name}}_EXPORT __declspec(dllexport)
#else
#define {{define_name}}_EXPORT
#endif

{{define_name}}_EXPORT void {{name.replace("-", "_").replace("+", "_").replace(".", "_")}}();
{{define_name}}_EXPORT void {{package_name}}();
"""

source_cpp = r"""#include <iostream>
#include "{{name}}.h"
{% if requires is defined -%}
{% for require in as_iterable(requires) -%}
#include "{{ as_name(require) }}.h"
{% endfor %}
{%- endif %}


void {{package_name}}(){
{% if requires is defined -%}
{% for require in as_iterable(requires) -%}
{{ as_name(require) }}();
{% endfor %}
{%- endif %}

void {{name.replace("-", "_").replace("+", "_").replace(".", "_")}}(){
#ifdef NDEBUG
std::cout << "{{name}}/{{version}}: Hello World Release!\n";
#else
Expand Down Expand Up @@ -198,6 +232,12 @@ def test(self):

find_package({{name}} CONFIG REQUIRED)

{% if requires is defined -%}
{% for require in as_iterable(requires) -%}
find_package({{as_name(require)}} CONFIG REQUIRED)
{% endfor %}
{%- endif %}

add_executable(example src/example.cpp)
target_link_libraries(example {{name}}::{{name}})
"""
Expand All @@ -206,7 +246,7 @@ def test(self):
test_main = """#include "{{name}}.h"

int main() {
{{name.replace("-", "_").replace("+", "_").replace(".", "_")}}();
{{package_name}}();
}
"""

Expand Down
23 changes: 23 additions & 0 deletions conans/test/functional/command/new_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import pytest as pytest

from utils.tools import TestClient


@pytest.mark.tool("cmake")
def test_diamonds_cmake_with_new():
tc = TestClient()
tc.run("new cmake_lib -d name=math -d version=3.14")
tc.run("create .")
tc.run("new cmake_lib -d name=ai -d version=0.1 -d requires=math/3.14 -f")
tc.run("create .")
assert "math/3.14: Hello World" in tc.out
tc.run("new cmake_lib -d name=ui -d version=1.0 -d requires=math/3.14 -f")
tc.run("create .")
assert "math/3.14: Hello World" in tc.out
tc.run("new cmake_exe -d name=game -d version=0.0 -d requires=ai/0.1 -d requires=ui/1.0 -f")
tc.run("create .")
assert "math/3.14: Hello World" in tc.out
assert "ai/0.1: Hello World" in tc.out
assert "ui/1.0: Hello World" in tc.out