|
| 1 | +-- Form B inline descriptor for {fmt} exposed as the C++23 module `fmt`, so |
| 2 | +-- users can write `import fmt;` out of the box (no `#include` needed). This is |
| 3 | +-- the module sibling of the header-based `compat.fmt` package. Namespaced under |
| 4 | +-- `fmtlib` (package `fmtlib.fmt`) so a workspace member can route the dependency |
| 5 | +-- to this repo's local `[indices] fmtlib = { path }` — an empty namespace would |
| 6 | +-- bind to the builtin default index and can't be pointed at a local path. The |
| 7 | +-- exported module name is still plain `fmt`, so consumers write `import fmt;`. |
| 8 | +-- |
| 9 | +-- fmt's release DOES ship an official C++20 module interface unit at |
| 10 | +-- `src/fmt.cc` (`export module fmt;`), but it cannot be fed to mcpp verbatim: |
| 11 | +-- mcpp's M1 module scanner rejects ANY `import` that appears inside a |
| 12 | +-- conditional preprocessor block (the scanner is a pre-preprocess text pass, so |
| 13 | +-- it can't evaluate the `#ifdef` — the guard is textual, not value-based), and |
| 14 | +-- fmt.cc carries `#ifdef FMT_IMPORT_STD / import std; / #endif`. So we reproduce |
| 15 | +-- fmt.cc via `generated_files` with two minimal edits: (1) `#define |
| 16 | +-- FMT_IMPORT_STD` right after `#define FMT_MODULE`, which flips fmt's own |
| 17 | +-- `#ifndef FMT_IMPORT_STD` include block to the import-std path (dropping the |
| 18 | +-- ~40 `#include <algorithm>`…`<vector>` lines); (2) that `#ifdef` guard around |
| 19 | +-- `import std;` removed so the import sits unconditional at module top level, |
| 20 | +-- which the scanner accepts. `import_std = true` makes mcpp build the `std` |
| 21 | +-- module first. Everything else is upstream fmt.cc verbatim: the |
| 22 | +-- `export module fmt;` line, the FMT_EXPORT macro plumbing (fmt's headers |
| 23 | +-- self-`export` under FMT_MODULE), and the tail `#include "format.cc"` / |
| 24 | +-- `"os.cc"` that pulls the implementation INTO the module (so its definitions |
| 25 | +-- attach to module `fmt`; compiling them as standalone TUs would leave them on |
| 26 | +-- the global module and break module linkage). |
| 27 | +-- |
| 28 | +-- include_dirs exposes BOTH `*/include` (so the module unit's `#include |
| 29 | +-- <fmt/*.h>` resolves) and `*/src` (so the tail `#include "format.cc"` / |
| 30 | +-- `"os.cc"` resolve). The wrapper path under mcpp_generated/ is verdir-relative |
| 31 | +-- (no glob), like nlohmann.json / compat.eigen. |
| 32 | +-- |
| 33 | +-- The wrapper MUST be named `.cppm`, not `.cc`. On macOS/Windows mcpp drives |
| 34 | +-- Clang in gnu (`--driver-mode=g++`) mode, where Clang decides "is this a module |
| 35 | +-- interface unit?" purely from the file extension: `.cppm`/`.ixx` yes, `.cc` no. |
| 36 | +-- A `.cc` module unit still compiles, but Clang silently drops `-fmodule-output` |
| 37 | +-- as an "unused argument" (-Wunused-command-line-argument), so NO BMI (`fmt.pcm`) |
| 38 | +-- is written — the consumer's `import fmt;` then fails with `module 'fmt' not |
| 39 | +-- found`. GCC (Linux) keys off `export module` instead of the extension, so `.cc` |
| 40 | +-- happened to work there and masked the bug. nlohmann.json already uses `.cppm`; |
| 41 | +-- this matches it. |
| 42 | +package = { |
| 43 | + spec = "1", |
| 44 | + namespace = "fmtlib", |
| 45 | + name = "fmtlib.fmt", |
| 46 | + description = "A modern formatting library for C++, exposed as C++23 module fmt", |
| 47 | + licenses = {"MIT"}, |
| 48 | + repo = "https://github.com/fmtlib/fmt", |
| 49 | + type = "package", |
| 50 | + |
| 51 | + xpm = { |
| 52 | + linux = { |
| 53 | + ["12.2.0"] = { |
| 54 | + url = "https://github.com/fmtlib/fmt/archive/refs/tags/12.2.0.tar.gz", |
| 55 | + sha256 = "8b852bb5aa6e7d8564f9e81394055395dd1d1936d38dfd3a17792a02bebd7af0", |
| 56 | + }, |
| 57 | + }, |
| 58 | + macosx = { |
| 59 | + ["12.2.0"] = { |
| 60 | + url = "https://github.com/fmtlib/fmt/archive/refs/tags/12.2.0.tar.gz", |
| 61 | + sha256 = "8b852bb5aa6e7d8564f9e81394055395dd1d1936d38dfd3a17792a02bebd7af0", |
| 62 | + }, |
| 63 | + }, |
| 64 | + windows = { |
| 65 | + ["12.2.0"] = { |
| 66 | + url = "https://github.com/fmtlib/fmt/archive/refs/tags/12.2.0.tar.gz", |
| 67 | + sha256 = "8b852bb5aa6e7d8564f9e81394055395dd1d1936d38dfd3a17792a02bebd7af0", |
| 68 | + }, |
| 69 | + }, |
| 70 | + }, |
| 71 | + |
| 72 | + mcpp = { |
| 73 | + schema = "0.1", |
| 74 | + language = "c++23", |
| 75 | + import_std = true, |
| 76 | + modules = { "fmt" }, |
| 77 | + include_dirs = { "*/include", "*/src" }, |
| 78 | + generated_files = { |
| 79 | + ["mcpp_generated/fmt_module.cppm"] = "// Formatting library for C++ - C++20 module\n//\n// Copyright (c) 2012 - present, Victor Zverovich and {fmt} contributors\n// All rights reserved.\n//\n// For the license information refer to format.h.\n\nmodule;\n\n#define FMT_MODULE\n\n#define FMT_IMPORT_STD\n\n#ifdef _MSVC_LANG\n# define FMT_CPLUSPLUS _MSVC_LANG\n#else\n# define FMT_CPLUSPLUS __cplusplus\n#endif\n\n// Put all implementation-provided headers into the global module fragment\n// to prevent attachment to this module.\n#ifndef FMT_IMPORT_STD\n# include <algorithm>\n# include <bitset>\n# include <chrono>\n# include <cmath>\n# include <complex>\n# include <cstddef>\n# include <cstdint>\n# include <cstdio>\n# include <cstdlib>\n# include <cstring>\n# include <ctime>\n# include <exception>\n# if FMT_CPLUSPLUS > 202002L\n# include <expected>\n# endif\n# include <filesystem>\n# include <fstream>\n# include <functional>\n# include <iterator>\n# include <limits>\n# include <locale>\n# include <memory>\n# include <optional>\n# include <ostream>\n# include <source_location>\n# include <stdexcept>\n# include <string>\n# include <string_view>\n# include <system_error>\n# include <thread>\n# include <type_traits>\n# include <typeinfo>\n# include <utility>\n# include <variant>\n# include <vector>\n#else\n# include <limits.h>\n# include <stdint.h>\n# include <stdio.h>\n# include <stdlib.h>\n# include <string.h>\n# include <time.h>\n#endif\n#include <cerrno>\n#include <climits>\n#include <version>\n\n#if __has_include(<cxxabi.h>)\n# include <cxxabi.h>\n#endif\n#if defined(_MSC_VER) || defined(__MINGW32__)\n# include <intrin.h>\n#endif\n#if defined __APPLE__ || defined(__FreeBSD__)\n# include <xlocale.h>\n#endif\n#if __has_include(<winapifamily.h>)\n# include <winapifamily.h>\n#endif\n#if (__has_include(<fcntl.h>) || defined(__APPLE__) || \\\n defined(__linux__)) && \\\n (!defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP))\n# include <fcntl.h>\n# include <sys/stat.h>\n# include <sys/types.h>\n# ifndef _WIN32\n# include <unistd.h>\n# else\n# include <io.h>\n# endif\n#endif\n#ifdef _WIN32\n# if defined(__GLIBCXX__)\n# include <ext/stdio_filebuf.h>\n# include <ext/stdio_sync_filebuf.h>\n# endif\n# define WIN32_LEAN_AND_MEAN\n# include <windows.h>\n#endif\n\nexport module fmt;\n\nimport std;\n\n#define FMT_EXPORT export\n#define FMT_BEGIN_EXPORT export {\n#define FMT_END_EXPORT }\n\n// If you define FMT_ATTACH_TO_GLOBAL_MODULE\n// - all declarations are detached from module 'fmt'\n// - the module behaves like a traditional static library, too\n// - all library symbols are mangled traditionally\n// - you can mix TUs with either importing or #including the {fmt} API\n#ifdef FMT_ATTACH_TO_GLOBAL_MODULE\nextern \"C++\" {\n#endif\n\n#ifndef FMT_OS\n# define FMT_OS 1\n#endif\n\n// All library-provided declarations and definitions must be in the module\n// purview to be exported.\n#include \"fmt/args.h\"\n#include \"fmt/chrono.h\"\n#include \"fmt/color.h\"\n#include \"fmt/compile.h\"\n#include \"fmt/format.h\"\n#if FMT_OS\n# include \"fmt/os.h\"\n#endif\n#include \"fmt/ostream.h\"\n#include \"fmt/printf.h\"\n#include \"fmt/ranges.h\"\n#include \"fmt/std.h\"\n#include \"fmt/xchar.h\"\n\n#ifdef FMT_ATTACH_TO_GLOBAL_MODULE\n}\n#endif\n\n#ifdef FMT_ATTACH_TO_GLOBAL_MODULE\nextern \"C++\" {\n#endif\n\n#if FMT_HAS_INCLUDE(\"format.cc\")\n# include \"format.cc\"\n#endif\n#if FMT_OS && FMT_HAS_INCLUDE(\"os.cc\")\n# include \"os.cc\"\n#endif\n\n#ifdef FMT_ATTACH_TO_GLOBAL_MODULE\n}\n#endif\n", |
| 80 | + }, |
| 81 | + sources = { "mcpp_generated/fmt_module.cppm" }, |
| 82 | + targets = { ["fmt"] = { kind = "lib" } }, |
| 83 | + deps = { }, |
| 84 | + }, |
| 85 | +} |
0 commit comments