diff --git a/CMakeLists.txt b/CMakeLists.txt index c7955236..d308e9dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,6 +55,11 @@ if(CODES_SANITIZER) add_link_options(-fsanitize=${CODES_SANITIZER}) endif() +# Opt-in Doxygen API docs. OFF by default and never part of `all`; the docs +# subdir registers an on-demand `docs` target (see doc/CMakeLists.txt). Output +# lands in the build tree, not the source tree. +option(CODES_BUILD_DOXYGEN "Build Doxygen API docs" OFF) + #prevent cmake from stripping the runtime path (important if shared libraries are imported) SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) @@ -276,6 +281,10 @@ configure_file(codes_config.h.cmake.in codes_config.h) add_subdirectory(doc/example) +if(CODES_BUILD_DOXYGEN) + add_subdirectory(doc) +endif() + # Tests are gated solely on BUILD_TESTING (the canonical CTest knob). A # $ genex can't gate this since add_subdirectory() runs at # configure time, and the old `STREQUAL "RELEASE"` compare never matched the diff --git a/README.md b/README.md index a701a73f..40513f74 100644 --- a/README.md +++ b/README.md @@ -245,6 +245,10 @@ CODES provides comprehensive simulation capabilities for: ## Contributing +For naming, file extensions, header guards, and how LP state must be constructed, +see the [coding conventions](doc/dev/conventions.md). Formatting is machine-checked +(below). + ### Code formatting This repo uses [clang-format](https://clang.llvm.org/docs/ClangFormat.html) to keep C/C++ style consistent. The rules live in [`.clang-format`](.clang-format) at the repo root; configure your editor to pick it up: diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt new file mode 100644 index 00000000..e1d9ab1b --- /dev/null +++ b/doc/CMakeLists.txt @@ -0,0 +1,50 @@ +# CODES API documentation (Doxygen). +# +# Reached only when -DCODES_BUILD_DOXYGEN=ON (see the option in the top-level +# CMakeLists). Registers an on-demand `docs` target — not built by `all`: +# +# cmake -S . -B build -DCODES_BUILD_DOXYGEN=ON +# cmake --build build --target docs +# +# The doc-comment convention (which entities get /** */ comments, and that there +# is no mass backfill) lives in doc/dev/conventions.md. + +find_package(Doxygen) +if(NOT DOXYGEN_FOUND) + message(WARNING + "CODES_BUILD_DOXYGEN=ON but Doxygen was not found; the `docs` target " + "will not be registered. Install Doxygen or set CODES_BUILD_DOXYGEN=OFF.") + return() +endif() + +# Generated output goes to the build tree, never the source tree (the stale +# committed Doxyfile this replaced dumped HTML into doc/). /build* is gitignored. +set(DOXYGEN_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/doc") + +# This is the setting that makes "infrastructure now, docs as code is touched" +# work: EXTRACT_ALL = NO means the output contains *only* entities that carry a +# Doxygen comment, so it starts near-empty and grows exactly as /** */ comments +# are added. WARN_IF_UNDOCUMENTED = NO +# keeps the build quiet about the as-yet-undocumented legacy tree instead of +# emitting thousands of warnings. +set(DOXYGEN_EXTRACT_ALL NO) +set(DOXYGEN_WARN_IF_UNDOCUMENTED NO) + +set(DOXYGEN_RECURSIVE YES) +set(DOXYGEN_GENERATE_HTML YES) +set(DOXYGEN_GENERATE_LATEX NO) + +set(DOXYGEN_PROJECT_NAME "CODES") +set(DOXYGEN_PROJECT_NUMBER "${PROJECT_VERSION}") + +# Render the README as the docs landing page. +set(DOXYGEN_USE_MDFILE_AS_MAINPAGE "${CMAKE_SOURCE_DIR}/README.md") + +# INPUT is broad (codes/ + src/); EXTRACT_ALL = NO does the filtering. Absolute +# paths so the inputs resolve regardless of WORKING_DIRECTORY. +doxygen_add_docs(docs + "${CMAKE_SOURCE_DIR}/codes" + "${CMAKE_SOURCE_DIR}/src" + "${CMAKE_SOURCE_DIR}/README.md" + WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" + COMMENT "Generating CODES API documentation (Doxygen)") diff --git a/doc/Doxyfile b/doc/Doxyfile deleted file mode 100644 index fce3f842..00000000 --- a/doc/Doxyfile +++ /dev/null @@ -1,376 +0,0 @@ -# Doxyfile 1.9.1 - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -DOXYFILE_ENCODING = UTF-8 -PROJECT_NAME = "CODES" -PROJECT_NUMBER = -PROJECT_BRIEF = -PROJECT_LOGO = -OUTPUT_DIRECTORY = doc -CREATE_SUBDIRS = NO -ALLOW_UNICODE_NAMES = NO -OUTPUT_LANGUAGE = English -OUTPUT_TEXT_DIRECTION = None -BRIEF_MEMBER_DESC = YES -REPEAT_BRIEF = YES -ABBREVIATE_BRIEF = "The $name class" \ - "The $name widget" \ - "The $name file" \ - is \ - provides \ - specifies \ - contains \ - represents \ - a \ - an \ - the -ALWAYS_DETAILED_SEC = NO -INLINE_INHERITED_MEMB = NO -FULL_PATH_NAMES = YES -STRIP_FROM_PATH = -STRIP_FROM_INC_PATH = -SHORT_NAMES = NO -JAVADOC_AUTOBRIEF = YES -JAVADOC_BANNER = NO -QT_AUTOBRIEF = NO -MULTILINE_CPP_IS_BRIEF = NO -PYTHON_DOCSTRING = YES -INHERIT_DOCS = YES -SEPARATE_MEMBER_PAGES = NO -TAB_SIZE = 4 -ALIASES = -OPTIMIZE_OUTPUT_FOR_C = NO -OPTIMIZE_OUTPUT_JAVA = NO -OPTIMIZE_FOR_FORTRAN = NO -OPTIMIZE_OUTPUT_VHDL = NO -OPTIMIZE_OUTPUT_SLICE = NO -EXTENSION_MAPPING = -MARKDOWN_SUPPORT = YES -TOC_INCLUDE_HEADINGS = 5 -AUTOLINK_SUPPORT = YES -BUILTIN_STL_SUPPORT = NO -CPP_CLI_SUPPORT = NO -SIP_SUPPORT = NO -IDL_PROPERTY_SUPPORT = YES -DISTRIBUTE_GROUP_DOC = NO -GROUP_NESTED_COMPOUNDS = NO -SUBGROUPING = YES -INLINE_GROUPED_CLASSES = NO -INLINE_SIMPLE_STRUCTS = NO -TYPEDEF_HIDES_STRUCT = NO -LOOKUP_CACHE_SIZE = 0 -NUM_PROC_THREADS = 1 - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -EXTRACT_ALL = YES -EXTRACT_PRIVATE = YES -EXTRACT_PRIV_VIRTUAL = YES -EXTRACT_PACKAGE = YES -EXTRACT_STATIC = YES -EXTRACT_LOCAL_CLASSES = YES -EXTRACT_LOCAL_METHODS = YES -EXTRACT_ANON_NSPACES = YES -RESOLVE_UNNAMED_PARAMS = YES -HIDE_UNDOC_MEMBERS = NO -HIDE_UNDOC_CLASSES = NO -HIDE_FRIEND_COMPOUNDS = NO -HIDE_IN_BODY_DOCS = NO -INTERNAL_DOCS = NO -CASE_SENSE_NAMES = YES -HIDE_SCOPE_NAMES = NO -HIDE_COMPOUND_REFERENCE= NO -SHOW_INCLUDE_FILES = YES -SHOW_GROUPED_MEMB_INC = NO -FORCE_LOCAL_INCLUDES = NO -INLINE_INFO = YES -SORT_MEMBER_DOCS = YES -SORT_BRIEF_DOCS = NO -SORT_MEMBERS_CTORS_1ST = NO -SORT_GROUP_NAMES = NO -SORT_BY_SCOPE_NAME = NO -STRICT_PROTO_MATCHING = NO -GENERATE_TODOLIST = YES -GENERATE_TESTLIST = YES -GENERATE_BUGLIST = YES -GENERATE_DEPRECATEDLIST= YES -ENABLED_SECTIONS = -MAX_INITIALIZER_LINES = 30 -SHOW_USED_FILES = YES -SHOW_FILES = YES -SHOW_NAMESPACES = YES -FILE_VERSION_FILTER = -LAYOUT_FILE = -CITE_BIB_FILES = - -#--------------------------------------------------------------------------- -# Configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -QUIET = NO -WARNINGS = YES -WARN_IF_UNDOCUMENTED = YES -WARN_IF_DOC_ERROR = YES -WARN_NO_PARAMDOC = NO -WARN_AS_ERROR = NO -WARN_FORMAT = "$file:$line: $text" -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# Configuration options related to the input files -#--------------------------------------------------------------------------- - -INPUT = src/ codes/ doc/example/ -INPUT_ENCODING = UTF-8 -FILE_PATTERNS = *.c \ - *.C \ - *.h \ - *.py -RECURSIVE = YES -EXCLUDE = -EXCLUDE_SYMLINKS = NO -EXCLUDE_PATTERNS = -EXCLUDE_SYMBOLS = -EXAMPLE_PATH = -EXAMPLE_PATTERNS = * -EXAMPLE_RECURSIVE = NO -IMAGE_PATH = -INPUT_FILTER = -FILTER_PATTERNS = -FILTER_SOURCE_FILES = NO -FILTER_SOURCE_PATTERNS = -USE_MDFILE_AS_MAINPAGE = - -#--------------------------------------------------------------------------- -# Configuration options related to source browsing -#--------------------------------------------------------------------------- - -SOURCE_BROWSER = YES -INLINE_SOURCES = NO -STRIP_CODE_COMMENTS = YES -REFERENCED_BY_RELATION = NO -REFERENCES_RELATION = NO -REFERENCES_LINK_SOURCE = YES -SOURCE_TOOLTIPS = YES -USE_HTAGS = NO -VERBATIM_HEADERS = YES - -#--------------------------------------------------------------------------- -# Configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -ALPHABETICAL_INDEX = YES -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the HTML output -#--------------------------------------------------------------------------- - -GENERATE_HTML = YES -HTML_OUTPUT = html -HTML_FILE_EXTENSION = .html -HTML_HEADER = -HTML_FOOTER = -HTML_STYLESHEET = -HTML_EXTRA_STYLESHEET = -HTML_EXTRA_FILES = -HTML_COLORSTYLE_HUE = 220 -HTML_COLORSTYLE_SAT = 100 -HTML_COLORSTYLE_GAMMA = 80 -HTML_TIMESTAMP = NO -HTML_DYNAMIC_MENUS = YES -HTML_DYNAMIC_SECTIONS = NO -HTML_INDEX_NUM_ENTRIES = 100 -GENERATE_DOCSET = NO -DOCSET_FEEDNAME = "Doxygen generated docs" -DOCSET_BUNDLE_ID = org.doxygen.Project -DOCSET_PUBLISHER_ID = org.doxygen.Publisher -DOCSET_PUBLISHER_NAME = Publisher -GENERATE_HTMLHELP = NO -CHM_FILE = -HHC_LOCATION = -GENERATE_CHI = NO -CHM_INDEX_ENCODING = -BINARY_TOC = NO -TOC_EXPAND = NO -GENERATE_QHP = NO -QCH_FILE = -QHP_NAMESPACE = org.doxygen.Project -QHP_VIRTUAL_FOLDER = doc -QHP_CUST_FILTER_NAME = -QHP_CUST_FILTER_ATTRS = -QHP_SECT_FILTER_ATTRS = -QHG_LOCATION = -GENERATE_ECLIPSEHELP = NO -ECLIPSE_DOC_ID = org.doxygen.Project -DISABLE_INDEX = NO -GENERATE_TREEVIEW = NO -ENUM_VALUES_PER_LINE = 4 -TREEVIEW_WIDTH = 250 -EXT_LINKS_IN_WINDOW = NO -HTML_FORMULA_FORMAT = png -FORMULA_FONTSIZE = 10 -FORMULA_TRANSPARENT = YES -FORMULA_MACROFILE = -USE_MATHJAX = NO -MATHJAX_FORMAT = HTML-CSS -MATHJAX_RELPATH = https://cdn.jsdelivr.net/npm/mathjax@2 -MATHJAX_EXTENSIONS = -MATHJAX_CODEFILE = -SEARCHENGINE = YES -SERVER_BASED_SEARCH = NO -EXTERNAL_SEARCH = NO -SEARCHENGINE_URL = -SEARCHDATA_FILE = searchdata.xml -EXTERNAL_SEARCH_ID = -EXTRA_SEARCH_MAPPINGS = - -#--------------------------------------------------------------------------- -# Configuration options related to the LaTeX output -#--------------------------------------------------------------------------- - -GENERATE_LATEX = NO -LATEX_OUTPUT = latex -LATEX_CMD_NAME = -MAKEINDEX_CMD_NAME = makeindex -LATEX_MAKEINDEX_CMD = makeindex -COMPACT_LATEX = NO -PAPER_TYPE = a4 -EXTRA_PACKAGES = -LATEX_HEADER = -LATEX_FOOTER = -LATEX_EXTRA_STYLESHEET = -LATEX_EXTRA_FILES = -PDF_HYPERLINKS = YES -USE_PDFLATEX = YES -LATEX_BATCHMODE = NO -LATEX_HIDE_INDICES = NO -LATEX_SOURCE_CODE = NO -LATEX_BIB_STYLE = plain -LATEX_TIMESTAMP = NO -LATEX_EMOJI_DIRECTORY = - -#--------------------------------------------------------------------------- -# Configuration options related to the RTF output -#--------------------------------------------------------------------------- - -GENERATE_RTF = NO -RTF_OUTPUT = rtf -COMPACT_RTF = NO -RTF_HYPERLINKS = NO -RTF_STYLESHEET_FILE = -RTF_EXTENSIONS_FILE = -RTF_SOURCE_CODE = NO - -#--------------------------------------------------------------------------- -# Configuration options related to the man page output -#--------------------------------------------------------------------------- - -GENERATE_MAN = NO -MAN_OUTPUT = man -MAN_EXTENSION = .3 -MAN_SUBDIR = -MAN_LINKS = NO - -#--------------------------------------------------------------------------- -# Configuration options related to the XML output -#--------------------------------------------------------------------------- - -GENERATE_XML = NO -XML_OUTPUT = xml -XML_PROGRAMLISTING = YES -XML_NS_MEMB_FILE_SCOPE = NO - -#--------------------------------------------------------------------------- -# Configuration options related to the DOCBOOK output -#--------------------------------------------------------------------------- - -GENERATE_DOCBOOK = NO -DOCBOOK_OUTPUT = docbook -DOCBOOK_PROGRAMLISTING = NO - -#--------------------------------------------------------------------------- -# Configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- - -GENERATE_AUTOGEN_DEF = NO - -#--------------------------------------------------------------------------- -# Configuration options related to the Perl module output -#--------------------------------------------------------------------------- - -GENERATE_PERLMOD = NO -PERLMOD_LATEX = NO -PERLMOD_PRETTY = YES -PERLMOD_MAKEVAR_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -ENABLE_PREPROCESSING = YES -MACRO_EXPANSION = NO -EXPAND_ONLY_PREDEF = NO -SEARCH_INCLUDES = NO -INCLUDE_PATH = -INCLUDE_FILE_PATTERNS = -PREDEFINED = -EXPAND_AS_DEFINED = -SKIP_FUNCTION_MACROS = YES - -#--------------------------------------------------------------------------- -# Configuration options related to external references -#--------------------------------------------------------------------------- - -TAGFILES = -GENERATE_TAGFILE = -ALLEXTERNALS = NO -EXTERNAL_GROUPS = YES -EXTERNAL_PAGES = YES - -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- - -CLASS_DIAGRAMS = YES -DIA_PATH = -HIDE_UNDOC_RELATIONS = YES -HAVE_DOT = YES -DOT_NUM_THREADS = 0 -DOT_FONTNAME = Helvetica -DOT_FONTSIZE = 10 -DOT_FONTPATH = -CLASS_GRAPH = YES -COLLABORATION_GRAPH = YES -GROUP_GRAPHS = YES -UML_LOOK = NO -UML_LIMIT_NUM_FIELDS = 10 -DOT_UML_DETAILS = NO -DOT_WRAP_THRESHOLD = 17 -TEMPLATE_RELATIONS = NO -INCLUDE_GRAPH = YES -INCLUDED_BY_GRAPH = YES -CALL_GRAPH = NO -CALLER_GRAPH = NO -GRAPHICAL_HIERARCHY = YES -DIRECTORY_GRAPH = YES -DOT_IMAGE_FORMAT = png -INTERACTIVE_SVG = NO -DOT_PATH = -DOTFILE_DIRS = -MSCFILE_DIRS = -DIAFILE_DIRS = -PLANTUML_JAR_PATH = -PLANTUML_CFG_FILE = -PLANTUML_INCLUDE_PATH = -DOT_GRAPH_MAX_NODES = 50 -MAX_DOT_GRAPH_DEPTH = 0 -DOT_TRANSPARENT = NO -DOT_MULTI_TARGETS = NO -GENERATE_LEGEND = YES -DOT_CLEANUP = YES diff --git a/doc/dev/conventions.md b/doc/dev/conventions.md new file mode 100644 index 00000000..012deb71 --- /dev/null +++ b/doc/dev/conventions.md @@ -0,0 +1,120 @@ +# CODES coding conventions + +The conventions a CODES contributor needs in one place: how to name things, which +file extension to use, how headers are guarded, and how Logical Process (LP) state +must be constructed. Formatting (braces, spacing, include ordering, line length) +is **machine-checked** — see [Formatting](#formatting) — so this doc covers the +rules a formatter can't enforce. + +## Naming + +**`snake_case` throughout**. +This applies to functions, variables, struct/class names, and file names alike. +The public CODES C surface keeps its existing `codes_`-prefixed names. + +## File extensions + +| Extension | Use for | +| --- | --- | +| `.cxx` | C++ source files | +| `.c` | C source files | +| `.h` | Headers — with `extern "C"` guards where the header is C-includable | + +The historical `.C` C++ extension has been retired (all `.C` files were renamed to +`.cxx`). `.cxx` also avoids the `.C`/`.c` collision on case-insensitive macOS +filesystems. Use `.cxx` for any new C++ translation unit; do not reintroduce `.C`. + +A header that is included from C translation units must wrap its declarations in +`extern "C"` guards so it stays C-includable. + +## Header guards + +Use the existing CODES `#ifndef` include-guard pattern — **not** `#pragma once`: + +```c +#ifndef CODES___H +#define CODES___H +/* ... */ +#endif /* CODES___H */ +``` + +Installed/public headers under `codes/` use the `CODES_..._H` form; internal +headers under `src/` use the `SRC_..._H` form mirroring their path. Match whichever +form the surrounding directory already uses. + +## Formatting + +Brace style, pointer placement, indentation, include ordering, and the soft +~100-column line length are owned by [`.clang-format`](../../.clang-format) at the +repo root — the **machine-checkable source of truth**. Don't restate or hand-apply +those rules; run the formatter (using v20): + +```bash +clang-format -i path/to/file.cxx +``` + +CI runs `clang-format --dry-run --Werror` on every PR and rejects any drift (see +[`ci.md`](ci.md) and the README "Code formatting" section for editor setup), so +unformatted code doesn't merge. + +## Documentation comments + +Public/installed API — the headers under `codes/` — gets `/** … */` Doxygen +comments. These are added **incrementally, as code is touched**: there is +**no mass backfill**. The generated docs grow with the code rather than as a one-time +documentation sprint. + +One Doxygen gotcha worth knowing because most of the public API is **C free +functions**: a documented function, variable, macro, or typedef only appears in +the output if its **enclosing header also carries a `/** @file */` block**. (C++ +classes and namespaces show up without one.) So when you first document a header, +give it a one-line `@file` block at the top: + +```c +/** @file + * Brief description of what this header provides. + */ +``` + +Then each `/** @brief … */` on a function in that header renders. Without the +`@file` block the symbol comment is silently dropped (a consequence of +`EXTRACT_ALL = NO`, not a bug). + +Build the API docs locally (off by default): + +```bash +cmake -S . -B build -DCODES_BUILD_DOXYGEN=ON +cmake --build build --target docs +``` + +Generated HTML lands in the **build tree** (`build/doc/html/`), which is already +git-ignored via `/build*` — it is never written into the source tree. The +Doxygen build uses `EXTRACT_ALL = NO`, so the output contains only entities that +actually carry a `/** */` comment: it starts near-empty by design and fills in as +comments are added. See [`doc/CMakeLists.txt`](../CMakeLists.txt) for the wiring. + +## LP state: rich, but constructed + +C++ members — including STL containers (`std::set`, `std::vector`, `std::map`, …) +— **are allowed** in LP state. But the state blob must be a *properly constructed* +C++ object: + +- **Construct in `init`** (placement-new the state object into the ROSS-provided + memory), and +- **Destruct in `final`** (run the destructor). + +**Never assign a C++ object into zero-initialized ROSS memory.** ROSS hands a model +a zeroed state blob; assigning `s->ports = std::set()` into never-constructed +memory is undefined behavior (the destructor of the moved-from temporary, and later +operations on the container, run against a never-constructed object). This has been +the root cause of some test segfaults and CI flakiness. + +TODO: a `make_lptype()` trampoline will make this **automatic** — +it placement-news the state object in `init` and runs its destructor in `final`, so +the state simply *is* a constructed C++ object. Until that lands, the tactical fixes +already applied pattern-match this rule by hand: placement-new +in `init`, explicit destructor call in `final`. Follow that pattern for any new +LP that carries C++ members. + +**Messages stay POD.** ROSS `memcpy`s events, so event/message structs must remain +plain-old-data — no C++ members with non-trivial construction.