Skip to content

Commit 70108b3

Browse files
Add an in-tree Conan recipe, tested by CI
FTXUI is currently only consumable via Conan through the community-maintained recipe on Conan Center, which lags behind releases. This adds a conanfile.py at the repository root wrapping the existing CMake install, plus a test_package smoke test and a GitHub Actions workflow (Linux/macOS/Windows, static/shared) that runs `conan create .` on every push and PR. Related to #1296
1 parent 01bcb68 commit 70108b3

7 files changed

Lines changed: 205 additions & 0 deletions

File tree

.github/workflows/conan.yaml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
name: Conan
2+
3+
on:
4+
# On new commits to main:
5+
push:
6+
branches:
7+
- main
8+
9+
# On pull requests:
10+
pull_request:
11+
branches:
12+
- main
13+
14+
jobs:
15+
test_conan:
16+
name: "Conan, ${{ matrix.os }}, shared=${{ matrix.shared }}"
17+
strategy:
18+
fail-fast: false
19+
matrix:
20+
os: [ubuntu-latest, macos-latest, windows-latest]
21+
shared: [false, true]
22+
23+
runs-on: ${{ matrix.os }}
24+
steps:
25+
- name: "Checkout repository"
26+
uses: actions/checkout@v4
27+
28+
- name: "Setup Python"
29+
uses: actions/setup-python@v5
30+
with:
31+
python-version: '3.x'
32+
33+
- name: "Install Conan"
34+
run: pip install conan
35+
36+
- name: "Detect Conan profile"
37+
run: conan profile detect
38+
39+
- name: "conan create ."
40+
run: >
41+
conan create .
42+
--build=missing
43+
-o "&:shared=${{ matrix.shared }}"

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ out/
1313
!.gitignore
1414
!CHANGELOG.md
1515
!CMakeLists.txt
16+
!conanfile.py
1617
!LICENSE
1718
!README.md
1819
!GEMINI.md
@@ -84,6 +85,11 @@ out/
8485
/subprojects/*
8586
!subprojects/*.wrap
8687

88+
# test_package directory (Conan recipe self-test):
89+
!test_package/**/*.py
90+
!test_package/**/*.txt
91+
!test_package/**/*.cpp
92+
8793
# tools directory:
8894
!tools/**/*.sh
8995
!tools/**/*.py

conanfile.py

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import os
2+
import re
3+
4+
from conan import ConanFile
5+
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
6+
from conan.tools.files import copy, load, rmdir
7+
8+
required_conan_version = ">=2.0.0"
9+
10+
11+
class FtxuiConan(ConanFile):
12+
name = "ftxui"
13+
description = "C++ Functional Terminal User Interface."
14+
license = "MIT"
15+
url = "https://github.com/ArthurSonzogni/FTXUI"
16+
homepage = "https://github.com/ArthurSonzogni/FTXUI"
17+
topics = ("terminal", "tui", "cli", "console", "functional")
18+
package_type = "library"
19+
settings = "os", "arch", "compiler", "build_type"
20+
options = {
21+
"shared": [True, False],
22+
"fPIC": [True, False],
23+
}
24+
default_options = {
25+
"shared": False,
26+
"fPIC": True,
27+
}
28+
29+
exports_sources = (
30+
"CMakeLists.txt",
31+
"cmake/*",
32+
"include/*",
33+
"src/*",
34+
"ftxui.pc.in",
35+
"LICENSE",
36+
# CMakeLists.txt unconditionally add_subdirectory()s these two
37+
# directories; each one's own CMakeLists.txt returns immediately
38+
# when its FTXUI_BUILD_* option is off, so nothing else from
39+
# examples/ or doc/ needs to be exported.
40+
"examples/CMakeLists.txt",
41+
"doc/CMakeLists.txt",
42+
)
43+
44+
def set_version(self):
45+
cmake_lists = load(self, os.path.join(self.recipe_folder, "CMakeLists.txt"))
46+
match = re.search(r"project\(\s*ftxui.*?VERSION\s+(\S+)", cmake_lists, re.DOTALL)
47+
self.version = match.group(1)
48+
49+
def config_options(self):
50+
if self.settings.os == "Windows":
51+
self.options.rm_safe("fPIC")
52+
53+
def configure(self):
54+
if self.options.shared:
55+
self.options.rm_safe("fPIC")
56+
57+
def layout(self):
58+
cmake_layout(self, src_folder=".")
59+
60+
def generate(self):
61+
tc = CMakeToolchain(self)
62+
tc.variables["BUILD_SHARED_LIBS"] = bool(self.options.shared)
63+
tc.variables["FTXUI_BUILD_DOCS"] = False
64+
tc.variables["FTXUI_BUILD_EXAMPLES"] = False
65+
tc.variables["FTXUI_BUILD_MODULES"] = False
66+
tc.variables["FTXUI_BUILD_TESTS"] = False
67+
tc.variables["FTXUI_BUILD_TESTS_FUZZER"] = False
68+
tc.variables["FTXUI_ENABLE_INSTALL"] = True
69+
tc.variables["FTXUI_QUIET"] = True
70+
tc.generate()
71+
72+
def build(self):
73+
cmake = CMake(self)
74+
cmake.configure()
75+
cmake.build()
76+
77+
def package(self):
78+
copy(self, "LICENSE", src=self.source_folder, dst=os.path.join(self.package_folder, "licenses"))
79+
cmake = CMake(self)
80+
cmake.install()
81+
rmdir(self, os.path.join(self.package_folder, "lib", "cmake"))
82+
rmdir(self, os.path.join(self.package_folder, "lib", "pkgconfig"))
83+
84+
def package_info(self):
85+
self.cpp_info.set_property("cmake_file_name", "ftxui")
86+
87+
self.cpp_info.components["screen"].set_property("cmake_target_name", "ftxui::screen")
88+
self.cpp_info.components["screen"].libs = ["ftxui-screen"]
89+
90+
self.cpp_info.components["dom"].set_property("cmake_target_name", "ftxui::dom")
91+
self.cpp_info.components["dom"].libs = ["ftxui-dom"]
92+
self.cpp_info.components["dom"].requires = ["screen"]
93+
94+
self.cpp_info.components["component"].set_property("cmake_target_name", "ftxui::component")
95+
self.cpp_info.components["component"].libs = ["ftxui-component"]
96+
self.cpp_info.components["component"].requires = ["dom"]

doc/installation_conan.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ After ensuring your environment is set up correctly, create a Conan configuratio
2626
> team but by the community. The package maintainer appears to actively update it
2727
> to the latest releases. Many thanks to the maintainer for their work!
2828
29+
FTXUI also ships its own `conanfile.py` at the root of the repository, tested
30+
by CI on every commit. It isn't published to Conan Center itself, but it can
31+
be used to consume FTXUI directly from a local checkout via
32+
`conan create .`, and could serve as the basis for an official Conan Center
33+
recipe.
34+
2935
@todo If you are familiar with the process, please consider adding an "official" build script to Conan Center.
3036
This could be a GitHub Action that automatically updates Conan Center upon new releases.
3137

test_package/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
cmake_minimum_required(VERSION 3.15)
2+
project(test_package CXX)
3+
4+
find_package(ftxui CONFIG REQUIRED)
5+
6+
add_executable(example src/example.cpp)
7+
target_compile_features(example PRIVATE cxx_std_17)
8+
target_link_libraries(example PRIVATE ftxui::component)

test_package/conanfile.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import os
2+
3+
from conan import ConanFile
4+
from conan.tools.build import can_run
5+
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
6+
7+
8+
class FtxuiTestConan(ConanFile):
9+
settings = "os", "arch", "compiler", "build_type"
10+
generators = "CMakeDeps"
11+
12+
def requirements(self):
13+
self.requires(self.tested_reference_str)
14+
15+
def layout(self):
16+
cmake_layout(self)
17+
18+
def generate(self):
19+
tc = CMakeToolchain(self)
20+
tc.generate()
21+
22+
def build(self):
23+
cmake = CMake(self)
24+
cmake.configure()
25+
cmake.build()
26+
27+
def test(self):
28+
if can_run(self):
29+
bin_path = os.path.join(self.cpp.build.bindir, "example")
30+
self.run(bin_path, env="conanrun")

test_package/src/example.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#include <ftxui/dom/elements.hpp>
2+
#include <ftxui/screen/screen.hpp>
3+
#include <iostream>
4+
5+
int main() {
6+
using namespace ftxui;
7+
auto document = hbox({
8+
text(" Hello "),
9+
text("FTXUI ") | bold | color(Color::Red),
10+
text(" world! "),
11+
});
12+
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
13+
Render(screen, document);
14+
std::cout << screen.ToString() << std::endl;
15+
return 0;
16+
}

0 commit comments

Comments
 (0)