Skip to content

Commit 714bed5

Browse files
authored
Merge pull request #1 from stlab/sean-parent/source-support
Adding Support for source
2 parents c2c9f37 + 8f400a0 commit 714bed5

File tree

8 files changed

+251
-36
lines changed

8 files changed

+251
-36
lines changed

README.md

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ cpp_library_setup(
3939
DESCRIPTION "${PROJECT_DESCRIPTION}"
4040
NAMESPACE your_namespace
4141
HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/include/your_namespace/your_header.hpp
42+
# Optional: add SOURCES for non-header-only libraries
43+
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/your_library.cpp
4244
EXAMPLES your_example your_example_fail
4345
TESTS your_tests
4446
DOCS_EXCLUDE_SYMBOLS "your_namespace::implementation"
@@ -66,14 +68,17 @@ cpp_library_setup(
6668
# Header specification (one required)
6769
HEADERS header_list # List of header files
6870
HEADER_DIR directory # Directory to install recursively
69-
71+
72+
# Optional: source specification for non-header-only libraries
73+
SOURCES source_list # List of source files (e.g., src/*.cpp)
74+
7075
# Optional features
7176
[EXAMPLES example_list] # Example executables to build
72-
[TESTS test_list] # Test executables to build
77+
[TESTS test_list] # Test executables to build
7378
[DOCS_EXCLUDE_SYMBOLS symbols] # Symbols to exclude from docs
7479
[REQUIRES_CPP_VERSION 17|20|23] # C++ version (default: 17)
7580
[ADDITIONAL_DEPS dep_list] # Extra CPM dependencies
76-
81+
7782
# Optional flags
7883
[CUSTOM_INSTALL] # Skip default installation
7984
[NO_PRESETS] # Skip CMakePresets.json generation
@@ -83,6 +88,11 @@ cpp_library_setup(
8388
```
8489

8590
## Features
91+
### Non-Header-Only Library Support
92+
93+
- **Automatic detection of sources in `src/`**: If source files are present in `src/`, the template will build a regular (static) library instead of header-only INTERFACE target.
94+
Specify sources manually with the `SOURCES` argument, or let the template auto-detect files in `src/`.
95+
Both header-only and compiled libraries are supported seamlessly.
8696

8797
### Automated Infrastructure
8898

@@ -186,8 +196,8 @@ cpp_library_setup(
186196
# Clone or create your project
187197
mkdir my-library && cd my-library
188198

189-
# Create basic structure
190-
mkdir -p include/your_namespace examples tests cmake
199+
# Create basic structure
200+
mkdir -p include/your_namespace src examples tests cmake
191201

192202
# Add CPM.cmake
193203
curl -L https://github.com/cpm-cmake/CPM.cmake/releases/latest/download/get_cpm.cmake -o cmake/CPM.cmake
@@ -212,10 +222,11 @@ cpp_library_setup(
212222

213223
The template automatically generates:
214224

215-
- **CMakePresets.json**: Build configurations for different purposes
216-
- **.github/workflows/ci.yml**: Multi-platform CI/CD pipeline
217-
- **.gitignore**: Standard ignores for C++ projects
218-
- **Package config files**: For proper CMake integration
225+
- **CMakePresets.json**: Build configurations for different purposes
226+
- **.github/workflows/ci.yml**: Multi-platform CI/CD pipeline
227+
- **.gitignore**: Standard ignores for C++ projects
228+
- **src/**: Source directory for non-header-only libraries (auto-detected)
229+
- **Package config files**: For proper CMake integration
219230

220231
## License
221232

cmake/cpp-library-setup.cmake

Lines changed: 70 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,35 +14,48 @@ function(_cpp_library_setup_core)
1414
)
1515
set(multiValueArgs
1616
HEADERS
17+
SOURCES
1718
)
1819

1920
cmake_parse_arguments(ARG "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
2021

2122
# Extract the library name without namespace prefix for target naming
2223
string(REPLACE "${ARG_NAMESPACE}-" "" CLEAN_NAME "${ARG_NAME}")
2324

24-
# Create the INTERFACE library target
25-
add_library(${ARG_NAME} INTERFACE)
26-
add_library(${ARG_NAMESPACE}::${CLEAN_NAME} ALIAS ${ARG_NAME})
27-
28-
# Set include directories
29-
target_include_directories(${ARG_NAME} INTERFACE
30-
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
31-
$<INSTALL_INTERFACE:include>
32-
)
33-
34-
# Set C++ standard requirement
35-
target_compile_features(${ARG_NAME} INTERFACE cxx_std_${ARG_REQUIRES_CPP_VERSION})
36-
37-
# Set up installation if headers are specified
38-
if(ARG_HEADERS)
39-
# Use FILE_SET for modern CMake header installation
40-
target_sources(${ARG_NAME} INTERFACE
41-
FILE_SET headers
42-
TYPE HEADERS
43-
BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include
44-
FILES ${ARG_HEADERS}
25+
if(ARG_SOURCES)
26+
# Create a regular library if sources are present
27+
add_library(${ARG_NAME} STATIC ${ARG_SOURCES})
28+
add_library(${ARG_NAMESPACE}::${CLEAN_NAME} ALIAS ${ARG_NAME})
29+
target_include_directories(${ARG_NAME} PUBLIC
30+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
31+
$<INSTALL_INTERFACE:include>
4532
)
33+
target_compile_features(${ARG_NAME} PUBLIC cxx_std_${ARG_REQUIRES_CPP_VERSION})
34+
if(ARG_HEADERS)
35+
target_sources(${ARG_NAME} PUBLIC
36+
FILE_SET headers
37+
TYPE HEADERS
38+
BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include
39+
FILES ${ARG_HEADERS}
40+
)
41+
endif()
42+
else()
43+
# Header-only INTERFACE target
44+
add_library(${ARG_NAME} INTERFACE)
45+
add_library(${ARG_NAMESPACE}::${CLEAN_NAME} ALIAS ${ARG_NAME})
46+
target_include_directories(${ARG_NAME} INTERFACE
47+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
48+
$<INSTALL_INTERFACE:include>
49+
)
50+
target_compile_features(${ARG_NAME} INTERFACE cxx_std_${ARG_REQUIRES_CPP_VERSION})
51+
if(ARG_HEADERS)
52+
target_sources(${ARG_NAME} INTERFACE
53+
FILE_SET headers
54+
TYPE HEADERS
55+
BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include
56+
FILES ${ARG_HEADERS}
57+
)
58+
endif()
4659
endif()
4760

4861
# Only set up full installation when building as top-level project
@@ -93,3 +106,39 @@ function(_cpp_library_setup_core)
93106
endif()
94107

95108
endfunction()
109+
110+
# Function to copy static template files
111+
function(_cpp_library_copy_templates)
112+
set(options FORCE_INIT)
113+
cmake_parse_arguments(ARG "${options}" "" "" ${ARGN})
114+
115+
# List of static template files to copy
116+
set(TEMPLATE_FILES
117+
".clang-format"
118+
".gitignore"
119+
".gitattributes"
120+
".vscode/extensions.json"
121+
"docs/index.html"
122+
)
123+
124+
foreach(template_file IN LISTS TEMPLATE_FILES)
125+
set(source_file "${CPP_LIBRARY_ROOT}/templates/${template_file}")
126+
set(dest_file "${CMAKE_CURRENT_SOURCE_DIR}/${template_file}")
127+
128+
# Check if template file exists
129+
if(EXISTS "${source_file}")
130+
# Copy if file doesn't exist or FORCE_INIT is enabled
131+
if(NOT EXISTS "${dest_file}" OR ARG_FORCE_INIT)
132+
# Create directory if needed
133+
get_filename_component(dest_dir "${dest_file}" DIRECTORY)
134+
file(MAKE_DIRECTORY "${dest_dir}")
135+
136+
# Copy the file
137+
file(COPY "${source_file}" DESTINATION "${dest_dir}")
138+
message(STATUS "Copied template file: ${template_file}")
139+
endif()
140+
else()
141+
message(WARNING "Template file not found: ${source_file}")
142+
endif()
143+
endforeach()
144+
endfunction()

cpp-library.cmake

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,22 @@ function(cpp_library_setup)
3737
)
3838
set(multiValueArgs
3939
HEADERS # List of header files
40-
EXAMPLES # Example executables to build
41-
TESTS # Test executables to build
42-
DOCS_EXCLUDE_SYMBOLS # Symbols to exclude from docs
43-
ADDITIONAL_DEPS # Extra CPM dependencies
40+
SOURCES # List of source files (optional, for non-header-only)
41+
EXAMPLES # Example executables to build
42+
TESTS # Test executables to build
43+
DOCS_EXCLUDE_SYMBOLS # Symbols to exclude from docs
44+
ADDITIONAL_DEPS # Extra CPM dependencies
4445
)
4546

4647
cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
48+
49+
# Detect sources in <root>/src if SOURCES not provided
50+
if(NOT ARG_SOURCES)
51+
file(GLOB_RECURSE DETECTED_SOURCES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "src/*.cpp" "src/*.c" "src/*.cc" "src/*.cxx")
52+
if(DETECTED_SOURCES)
53+
set(ARG_SOURCES ${DETECTED_SOURCES})
54+
endif()
55+
endif()
4756

4857
# Validate required arguments
4958
if(NOT ARG_NAME)
@@ -79,6 +88,7 @@ function(cpp_library_setup)
7988
DESCRIPTION "${ARG_DESCRIPTION}"
8089
NAMESPACE "${ARG_NAMESPACE}"
8190
HEADERS "${ARG_HEADERS}"
91+
SOURCES "${ARG_SOURCES}"
8292
HEADER_DIR "${ARG_HEADER_DIR}"
8393
REQUIRES_CPP_VERSION "${ARG_REQUIRES_CPP_VERSION}"
8494
TOP_LEVEL "${PROJECT_IS_TOP_LEVEL}"
@@ -103,6 +113,9 @@ function(cpp_library_setup)
103113
if(NOT ARG_NO_PRESETS)
104114
_cpp_library_generate_presets(FORCE_INIT ${ARG_FORCE_INIT})
105115
endif()
116+
117+
# Copy static template files (like .clang-format, .gitignore, etc.)
118+
_cpp_library_copy_templates(FORCE_INIT ${ARG_FORCE_INIT})
106119

107120
# Setup testing (if tests are specified)
108121
if(BUILD_TESTING AND ARG_TESTS)

templates/.clang-format

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
# Format style options described here:
2+
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
3+
4+
# Many of the alignment and single line changes were made to facilitate setting
5+
# breakpoints on specific expressions.
6+
7+
---
8+
AccessModifierOffset: -4
9+
AlignAfterOpenBracket: Align
10+
AlignConsecutiveAssignments: false
11+
AlignConsecutiveDeclarations: false
12+
AlignEscapedNewlines: Left
13+
AlignOperands: true
14+
AlignTrailingComments: true
15+
AllowAllParametersOfDeclarationOnNextLine: true
16+
AllowShortBlocksOnASingleLine: false
17+
AllowShortCaseLabelsOnASingleLine: false
18+
AllowShortFunctionsOnASingleLine: All
19+
AllowShortIfStatementsOnASingleLine: true
20+
AllowShortLoopsOnASingleLine: false
21+
# AlwaysBreakAfterDefinitionReturnType: TopLevel
22+
AlwaysBreakAfterReturnType: None
23+
AlwaysBreakBeforeMultilineStrings: false
24+
AlwaysBreakTemplateDeclarations: true
25+
BinPackArguments: true
26+
BinPackParameters: false
27+
# BraceWrapping:
28+
# AfterClass: true
29+
# AfterControlStatement: false
30+
# AfterEnum: false
31+
# AfterFunction: false
32+
# AfterNamespace: false
33+
# AfterObjCDeclaration: false
34+
# AfterStruct: false
35+
# AfterUnion: false
36+
# AfterExternBlock: false
37+
# BeforeCatch: false
38+
# BeforeElse: false
39+
# IndentBraces: false
40+
# SplitEmptyFunction: true
41+
# SplitEmptyRecord: true
42+
# SplitEmptyNamespace: true
43+
BreakBeforeBinaryOperators: None
44+
BreakBeforeBraces: Attach
45+
BreakBeforeInheritanceComma: false
46+
BreakBeforeTernaryOperators: false
47+
BreakConstructorInitializersBeforeComma: false
48+
BreakConstructorInitializers: AfterColon
49+
BreakAfterJavaFieldAnnotations: false
50+
BreakStringLiterals: false
51+
ColumnLimit: 100
52+
CommentPragmas: '^ IWYU pragma:'
53+
CompactNamespaces: false
54+
ConstructorInitializerAllOnOneLineOrOnePerLine: false
55+
ConstructorInitializerIndentWidth: 4
56+
ContinuationIndentWidth: 4
57+
Cpp11BracedListStyle: true
58+
DerivePointerAlignment: false
59+
DisableFormat: false
60+
ExperimentalAutoDetectBinPacking: false
61+
FixNamespaceComments: true
62+
ForEachMacros:
63+
- foreach
64+
- Q_FOREACH
65+
- BOOST_FOREACH
66+
IncludeBlocks: Preserve
67+
IncludeCategories:
68+
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
69+
Priority: 2
70+
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
71+
Priority: 3
72+
- Regex: '.*'
73+
Priority: 1
74+
IncludeIsMainRegex: '$'
75+
IndentCaseLabels: true
76+
IndentPPDirectives: None # Other option is AfterHash, which indents top level includes as well
77+
IndentWidth: 4
78+
IndentWrappedFunctionNames: true
79+
JavaScriptQuotes: Leave
80+
JavaScriptWrapImports: true
81+
KeepEmptyLinesAtTheStartOfBlocks: false
82+
MacroBlockBegin: ''
83+
MacroBlockEnd: ''
84+
MaxEmptyLinesToKeep: 1
85+
NamespaceIndentation: None
86+
ObjCBlockIndentWidth: 4
87+
ObjCSpaceAfterProperty: true
88+
ObjCSpaceBeforeProtocolList: true
89+
PenaltyBreakAssignment: 2
90+
PenaltyBreakBeforeFirstCallParameter: 19
91+
PenaltyBreakComment: 300
92+
PenaltyBreakFirstLessLess: 120
93+
PenaltyBreakString: 1000
94+
PenaltyExcessCharacter: 1000000
95+
PenaltyReturnTypeOnItsOwnLine: 1000
96+
PointerAlignment: Left
97+
ReflowComments: true
98+
SortIncludes: true
99+
SortUsingDeclarations: true
100+
SpaceAfterCStyleCast: false
101+
SpaceAfterTemplateKeyword: true
102+
SpaceBeforeAssignmentOperators: true
103+
SpaceBeforeParens: ControlStatements
104+
SpaceInEmptyParentheses: false
105+
SpacesBeforeTrailingComments: 1
106+
SpacesInAngles: false
107+
SpacesInContainerLiterals: true
108+
SpacesInCStyleCastParentheses: false
109+
SpacesInParentheses: false
110+
SpacesInSquareBrackets: false
111+
Standard: Cpp17
112+
TabWidth: 4
113+
UseTab: Never
114+
---
115+
Language: Cpp
116+
---
117+
Language: ObjC
118+
PointerAlignment: Right
119+
...

templates/.gitattributes

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Auto detect text files and perform LF normalization
2+
* text=auto

templates/.gitignore

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
/.cpm-cache
2-
/.cpp-library-cache
32
/.cache
43
/build
5-
include/.DS_Store
4+
.DS_Store
65
compile_commands.json

templates/.vscode/extensions.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"recommendations": [
3+
"matepek.vscode-catch2-test-adapter",
4+
"llvm-vs-code-extensions.vscode-clangd",
5+
"ms-vscode.live-server",
6+
"xaver.clang-format"
7+
]
8+
}

templates/docs/index.html

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<!-- Open or preview this file after building the docs to view the documentation. -->
4+
5+
<head>
6+
<meta http-equiv="refresh" content="0; URL=../build/docs/html/index.html">
7+
<title>Redirecting to Documentation</title>
8+
</head>
9+
10+
<body>
11+
<p>If you are not redirected automatically, <a href="../build/docs/html/index.html">click here</a>.</p>
12+
</body>
13+
14+
</html>

0 commit comments

Comments
 (0)