diff --git a/recipes/ccache/binary/ccache-autoinject.cmake b/recipes/ccache/binary/ccache-autoinject.cmake new file mode 100644 index 0000000..c79deeb --- /dev/null +++ b/recipes/ccache/binary/ccache-autoinject.cmake @@ -0,0 +1,30 @@ +include_guard() + +# Find ccache executable +find_program(CCACHE_PROGRAM NAMES ccache) + +if(CCACHE_PROGRAM) + message(STATUS "ccache found: ${CCACHE_PROGRAM}, enabling via CMake launcher and environment.") + if (CMAKE_GENERATOR MATCHES "Visual Studio") + # Copy original ccache.exe and rename to cl.exe, this way intermediate cmd file is not needed + file(COPY_FILE ${CCACHE_PROGRAM} ${CMAKE_BINARY_DIR}/cl.exe ONLY_IF_DIFFERENT) + + # Set Visual Studio global variables: + # - Use above cl.exe (ccache.exe) as a compiler + # - Enable parallel compilation + list(APPEND CMAKE_VS_GLOBALS + "CLToolExe=cl.exe" + "CLToolPath=${CMAKE_BINARY_DIR}" + "UseMultiToolTask=true" + "UseStructuredOutput=false" + ) + elseif(CMAKE_GENERATOR MATCHES "Ninja" OR CMAKE_GENERATOR MATCHES "Unix Makefiles") + message(STATUS "Using ccache as compiler launcher for Ninja or Makefiles.") + set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE_PROGRAM} CACHE FILEPATH "CXX compiler cache used" FORCE) + set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE_PROGRAM} CACHE FILEPATH "C compiler cache used" FORCE) + else() + message(WARNING "Unsupported generator for ccache integration: ${CMAKE_GENERATOR}. ccache will not be used.") + endif() +else() + message(WARNING "ccache not found. Not enabling ccache integration.") +endif() diff --git a/recipes/ccache/binary/conandata.yml b/recipes/ccache/binary/conandata.yml new file mode 100644 index 0000000..3d92022 --- /dev/null +++ b/recipes/ccache/binary/conandata.yml @@ -0,0 +1,23 @@ +sources: + "4.12": + Linux: + x86_64: + url: "https://github.com/ccache/ccache/releases/download/v4.12/ccache-4.12-linux-x86_64.tar.xz" + sha256: "d77e140d0403175b93f979f0b0d36e821bf31728b282f4bfda939f65836bcabe" + armv8: + url: "https://github.com/ccache/ccache/releases/download/v4.12/ccache-4.12-linux-aarch64.tar.xz" + sha256: "378ed4b9f645f5aab691447e4ec45b4c68508a424ac37c9be7baa28ded385791" + Macos: + universal: + url: "https://github.com/ccache/ccache/releases/download/v4.12/ccache-4.12-darwin.tar.gz" + sha256: "95cb03de0f2e0edb264d2443f2fe4500a13086689cc9ecd1095eb274dd8d9aee" + Windows: + armv8: + url: "https://github.com/ccache/ccache/releases/download/v4.12/ccache-4.12-windows-aarch64.zip" + sha256: "12d8a95507ce19bb90cff49faa5f5de07919d5d8d91f129bcf597dbc30d0c250" + x86: + url: "https://github.com/ccache/ccache/releases/download/v4.12/ccache-4.12-windows-i686.zip" + sha256: "c046ad7159d312312662c380da5932d441407f56164e451b09c16dad8db01051" + x86_64: + url: "https://github.com/ccache/ccache/releases/download/v4.12/ccache-4.12-windows-x86_64.zip" + sha256: "85c963b154dcf5e38dc6839d660218433a3b0b86387c302675d236e17ae7220d" diff --git a/recipes/ccache/binary/conanfile.py b/recipes/ccache/binary/conanfile.py new file mode 100644 index 0000000..651ab1f --- /dev/null +++ b/recipes/ccache/binary/conanfile.py @@ -0,0 +1,61 @@ +import os +from pathlib import Path + +from conan import ConanFile +from conan.errors import ConanInvalidConfiguration +from conan.tools.files import get, copy + +required_conan_version = ">=2.1" + +AUTOIJECT_CMAKE = "ccache-autoinject.cmake" + +class CcacheConan(ConanFile): + name = "ccache" + package_type = "application" + description = ( + "Ccache (or “ccache”) is a compiler cache. It speeds up recompilation " + "by caching previous compilations and detecting when the same " + "compilation is being done again." + ) + license = "GPL-3.0-or-later" + topics = ("compiler-cache", "recompilation", "cache", "compiler") + homepage = "https://ccache.dev" + url = "https://github.com/conan-io/conan-center-index" + settings = "os", "arch" + exports_sources = [AUTOIJECT_CMAKE] + + @property + def _arch(self): + return str(self.settings.arch) if self.settings.os != "Macos" else "universal" + + def validate(self): + if self.conan_data["sources"][self.version].get(str(self.settings.os), {}).get(self._arch) is None: + raise ConanInvalidConfiguration(f"ccache binaries do not support '{self.settings.os} - {self._arch}'") + + def build(self): + get(self, **self.conan_data["sources"][self.version][str(self.settings.os)][self._arch], + destination=self.source_folder, strip_root=True) + + def package_id(self): + if self.info.settings.os == "Macos": + self.info.settings.arch = "universal" + + def package(self): + copy(self, "*GPL-*.txt", src=self.build_folder, dst=os.path.join(self.package_folder, "licenses")) + copy(self, "LICENSE.*", src=self.build_folder, dst=os.path.join(self.package_folder, "licenses")) + copy(self, "ccache*", src=self.build_folder, dst=os.path.join(self.package_folder, "bin")) + copy(self, AUTOIJECT_CMAKE, src=self.build_folder, dst=self.package_folder) + + def package_info(self): + self.cpp_info.libdirs = [] + self.cpp_info.includedirs = [] + if self.conf.get("user.ccache:auto_inject", default=True, check_type=bool): + self.conf_info.append("tools.cmake.cmaketoolchain:user_toolchain", os.path.join(self.package_folder, AUTOIJECT_CMAKE)) + + # Set environment variables to allow ccache work correctly within conan build/create workflow + base_dir = self.conf.get("user.ccache:base_dir", default=str(Path.home()), check_type=str) + self.buildenv_info.define("CCACHE_BASEDIR", base_dir) + self.buildenv_info.define("CCACHE_NOHASHDIR", "1") + + self.output.warning("ccache recipe can autoinject itself into CMake projects but you need to define CC/CXX " + "environment variables to use it in other build systems such as Meson, Autotools, Premake, etc.") diff --git a/recipes/ccache/binary/test_package/CMakeLists.txt b/recipes/ccache/binary/test_package/CMakeLists.txt new file mode 100644 index 0000000..35cfafb --- /dev/null +++ b/recipes/ccache/binary/test_package/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.15) +project(test_package LANGUAGES CXX) + +add_executable(${PROJECT_NAME} test_package.cpp) diff --git a/recipes/ccache/binary/test_package/conanfile.py b/recipes/ccache/binary/test_package/conanfile.py new file mode 100644 index 0000000..1c490c7 --- /dev/null +++ b/recipes/ccache/binary/test_package/conanfile.py @@ -0,0 +1,34 @@ +import os +from conan import ConanFile +from conan.tools.build import can_run +from conan.tools.cmake import CMake, cmake_layout +from conan.errors import ConanException + + +class TestPackageConan(ConanFile): + settings = "os", "arch", "compiler", "build_type" + generators = "CMakeToolchain" + + def build_requirements(self): + self.tool_requires(self.tested_reference_str) + + def layout(self): + cmake_layout(self) + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def test(self): + generated_file = os.path.join(self.dependencies.build[self.tested_reference_str].package_folder, "ccache-autoinject.cmake") + if not os.path.exists(generated_file): + raise ConanException("ccache-autoinject.cmake toolchain file does not exist") + user_toolchain = self.conf.get("tools.cmake.cmaketoolchain:user_toolchain", check_type=list) + if generated_file not in user_toolchain: + raise ConanException("ccache not found in user toolchain") + + if can_run(self): + self.run("ccache --version", env="conanbuild") + self.run("ccache --get-config hash_dir", env="conanbuild") + self.run("ccache --get-config base_dir", env="conanbuild") diff --git a/recipes/ccache/binary/test_package/test_package.cpp b/recipes/ccache/binary/test_package/test_package.cpp new file mode 100644 index 0000000..fc9a9df --- /dev/null +++ b/recipes/ccache/binary/test_package/test_package.cpp @@ -0,0 +1,5 @@ +#include + +int main() { + std::cout << "Hello world!\n"; +} diff --git a/recipes/ccache/config.yml b/recipes/ccache/config.yml new file mode 100644 index 0000000..0d6ab71 --- /dev/null +++ b/recipes/ccache/config.yml @@ -0,0 +1,3 @@ +versions: + "4.12": + folder: binary