Skip to content

Commit 9867844

Browse files
committed
Build: Improve build definition API
1 parent 39ea983 commit 9867844

File tree

7 files changed

+244
-160
lines changed

7 files changed

+244
-160
lines changed

Libraries/Build/Build.cpp

Lines changed: 61 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ bool SC::Build::Configuration::applyPreset(const Project& project, Preset newPre
4848
switch (newPreset)
4949
{
5050
case Configuration::Preset::DebugCoverage:
51-
if (not project.compile.enableASAN.hasBeenSet())
51+
if (not project.files.compile.enableASAN.hasBeenSet())
5252
{
5353
compile.enableCoverage = true;
5454
}
@@ -60,7 +60,7 @@ bool SC::Build::Configuration::applyPreset(const Project& project, Preset newPre
6060
}
6161
break;
6262
case Configuration::Preset::Debug:
63-
if (not project.compile.enableASAN.hasBeenSet())
63+
if (not project.files.compile.enableASAN.hasBeenSet())
6464
{
6565
// VS ASAN is unsupported on ARM64 and needs manual flags / libs with ClangCL toolset
6666
// It also needs paths where clang_rt.asan_*.dll exist to be manually set before debugging
@@ -123,25 +123,67 @@ const SC::Build::Configuration* SC::Build::Project::getConfiguration(StringView
123123
return nullptr;
124124
}
125125

126-
bool SC::Build::Project::addDirectory(StringView subdirectory, StringView filter)
126+
bool SC::Build::SourceFiles::addSelection(StringView directory, StringView filter)
127+
{
128+
return selection.push_back({FilesSelection::Add, directory, filter});
129+
}
130+
131+
bool SC::Build::SourceFiles::removeSelection(StringView directory, StringView filter)
132+
{
133+
return selection.push_back({FilesSelection::Remove, directory, filter});
134+
}
135+
136+
bool SC::Build::Project::addFiles(StringView subdirectory, StringView filter)
127137
{
128138
if (subdirectory.containsCodePoint('*') or subdirectory.containsCodePoint('?'))
129139
return false;
130-
return files.push_back({Project::File::Add, subdirectory, filter});
140+
return files.selection.push_back({FilesSelection::Add, subdirectory, filter});
131141
}
132142

143+
bool SC::Build::Project::addIncludePaths(Span<const StringView> includePaths)
144+
{
145+
return files.compile.includePaths.append(includePaths);
146+
}
147+
148+
bool SC::Build::Project::addLinkLibraryPaths(Span<const StringView> libraryPaths)
149+
{
150+
return link.libraryPaths.append(libraryPaths);
151+
}
152+
153+
bool SC::Build::Project::addLinkLibraries(Span<const StringView> linkLibraries)
154+
{
155+
return link.libraries.append(linkLibraries);
156+
}
157+
158+
bool SC::Build::Project::addLinkFrameworks(Span<const StringView> frameworks)
159+
{
160+
return link.frameworks.append(frameworks);
161+
}
162+
163+
bool SC::Build::Project::addLinkFrameworksMacOS(Span<const StringView> frameworks)
164+
{
165+
return link.frameworksMacOS.append(frameworks);
166+
}
167+
168+
bool SC::Build::Project::addLinkFrameworksIOS(Span<const StringView> frameworks)
169+
{
170+
return link.frameworksIOS.append(frameworks);
171+
}
172+
173+
bool SC::Build::Project::addDefines(Span<const StringView> defines) { return files.compile.defines.append(defines); }
174+
133175
bool SC::Build::Project::addFile(StringView singleFile)
134176
{
135177
if (singleFile.containsCodePoint('*') or singleFile.containsCodePoint('?'))
136178
return false;
137-
return files.push_back({Project::File::Add, {}, singleFile});
179+
return files.selection.push_back({FilesSelection::Add, {}, singleFile});
138180
}
139181

140182
bool SC::Build::Project::removeFiles(StringView subdirectory, StringView filter)
141183
{
142184
if (subdirectory.containsCodePoint('*') or subdirectory.containsCodePoint('?'))
143185
return false;
144-
return files.push_back({Project::File::Remove, subdirectory, filter});
186+
return files.selection.push_back({FilesSelection::Remove, subdirectory, filter});
145187
}
146188

147189
SC::Result SC::Build::Project::validate() const
@@ -187,7 +229,7 @@ SC::Result SC::Build::DefinitionCompiler::validate()
187229
return Result(true);
188230
}
189231

190-
SC::Result SC::Build::DefinitionCompiler::fillPathsList(StringView path, const VectorSet<Project::File>& filters,
232+
SC::Result SC::Build::DefinitionCompiler::fillPathsList(StringView path, const VectorSet<FilesSelection>& filters,
191233
VectorMap<String, Vector<String>>& filtersToFiles)
192234
{
193235
bool doRecurse = false;
@@ -211,11 +253,11 @@ SC::Result SC::Build::DefinitionCompiler::fillPathsList(StringView path, const V
211253
return Result(true);
212254
}
213255

214-
Vector<Project::File> renderedFilters;
256+
Vector<FilesSelection> renderedFilters;
215257
for (const auto& filter : filters)
216258
{
217-
Project::File file;
218-
file.operation = filter.operation;
259+
FilesSelection file;
260+
file.action = filter.action;
219261
SC_TRY(file.mask.assign(path));
220262
SC_TRY(Path::append(file.mask, {filter.mask.view()}, Path::AsPosix));
221263
SC_TRY(renderedFilters.push_back(move(file)));
@@ -249,7 +291,7 @@ SC::Result SC::Build::DefinitionCompiler::fillPathsList(StringView path, const V
249291

250292
SC::Result SC::Build::DefinitionCompiler::build()
251293
{
252-
VectorMap<String, VectorSet<Project::File>> uniquePaths;
294+
VectorMap<String, VectorSet<FilesSelection>> uniquePaths;
253295
SC_TRY(collectUniqueRootPaths(uniquePaths));
254296
for (auto& it : uniquePaths)
255297
{
@@ -259,21 +301,21 @@ SC::Result SC::Build::DefinitionCompiler::build()
259301
}
260302

261303
// Collects root paths to build a stat map
262-
SC::Result SC::Build::DefinitionCompiler::collectUniqueRootPaths(VectorMap<String, VectorSet<Project::File>>& paths)
304+
SC::Result SC::Build::DefinitionCompiler::collectUniqueRootPaths(VectorMap<String, VectorSet<FilesSelection>>& paths)
263305
{
264306
String buffer;
265307
SmallVector<StringView, 16> components;
266308
for (const Workspace& workspace : definition.workspaces)
267309
{
268310
for (const Project& project : workspace.projects)
269311
{
270-
for (const Project::File& file : project.files)
312+
for (const FilesSelection& file : project.files.selection)
271313
{
272314
SC_TRY(buffer.assign(project.rootDirectory.view()));
273315
if (Path::isAbsolute(file.base.view(), Path::Type::AsNative))
274316
{
275-
Project::File absFile;
276-
absFile.operation = file.operation;
317+
FilesSelection absFile;
318+
absFile.action = file.action;
277319
SC_TRY(Path::normalize(file.base.view(), components, &absFile.base, Path::Type::AsPosix));
278320
SC_TRY(absFile.mask.assign(file.mask.view()));
279321
SC_TRY(paths.getOrCreate(absFile.base.view())->insert(absFile));
@@ -314,16 +356,16 @@ SC::Result SC::Build::DefinitionCompiler::collectUniqueRootPaths(VectorMap<Strin
314356
}
315357
else
316358
{
317-
const auto overlapNew = buffer.view().sliceStart(commonOverlap);
318-
const auto overlapExisting = it.key.view().sliceStart(commonOverlap);
359+
const StringView overlapNew = buffer.view().sliceStart(commonOverlap);
360+
const StringView overlapExisting = it.key.view().sliceStart(commonOverlap);
319361
if (overlapExisting.isEmpty())
320362
{
321363
// Case .5 and .3 after .2
322364
if (overlapNew.startsWithAnyOf({'/'}))
323365
{
324366
// Case .3 after 2 (can be merged)
325-
Project::File mergedFile;
326-
mergedFile.operation = file.operation;
367+
FilesSelection mergedFile;
368+
mergedFile.action = file.action;
327369
SC_TRY(mergedFile.base.assign(it.value.begin()->base.view()));
328370
SC_TRY(mergedFile.mask.assign(Path::removeStartingSeparator(overlapNew)));
329371
SC_TRY(Path::append(mergedFile.mask, {file.mask.view()}, Path::AsPosix));

Libraries/Build/Build.h

Lines changed: 64 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,39 @@ struct LinkFlags
168168
Parameter<bool> enableStdCpp = false; ///< Enable and link C++ Standard Library
169169
};
170170

171+
/// @brief Describes an additive / subtractive selection of files
172+
struct FilesSelection
173+
{
174+
/// @brief Add or removes from selection
175+
enum Action
176+
{
177+
Add, ///< Add files
178+
Remove ///< Remove files
179+
};
180+
Action action = Add; ///< Operation type (add or remove files)
181+
String base; ///< Base path (not containing `*`)
182+
String mask; ///< Mask suffix (can contain `*`)
183+
184+
bool operator==(const FilesSelection& other) const
185+
{
186+
// collectUniqueRootPaths doesn't care about de-duplicating also operation
187+
return base == other.base and mask == other.mask;
188+
}
189+
};
190+
191+
/// @brief A selection of files with their associated compile flags
192+
struct SourceFiles
193+
{
194+
Vector<FilesSelection> selection;
195+
CompileFlags compile;
196+
197+
/// @brief Add some files from a directory to the selection
198+
[[nodiscard]] bool addSelection(StringView directory, StringView filter);
199+
200+
/// @brief Remove some files from a directory to the selection
201+
[[nodiscard]] bool removeSelection(StringView directory, StringView filter);
202+
};
203+
171204
/// @brief Groups SC::Build::CompileFlags and SC::Build::LinkFlags for a given SC::Build::Architecture
172205
struct Configuration
173206
{
@@ -233,26 +266,6 @@ struct TargetType
233266
/// @brief Groups multiple Configuration and source files with their compile and link flags
234267
struct Project
235268
{
236-
/// @brief Project list of files
237-
struct File
238-
{
239-
/// @brief Indicates if this is an additive or subtractive files operation
240-
enum Operation
241-
{
242-
Add, ///< Add files
243-
Remove ///< Remove files
244-
};
245-
Operation operation = Add; ///< Operation type (add or remove files)
246-
String base; ///< Base path (not containing `*`)
247-
String mask; ///< Mask suffix (can contain `*`)
248-
249-
bool operator==(const File& other) const
250-
{
251-
// collectUniqueRootPaths doesn't care about de-duplicating also operation
252-
return base == other.base and mask == other.mask;
253-
}
254-
};
255-
256269
Project() = default;
257270
Project(TargetType::Type targetType, StringView name) : targetType(targetType), name(name), targetName(name) {}
258271

@@ -263,9 +276,8 @@ struct Project
263276
String targetName; ///< Project target name
264277
String iconPath; ///< Icon location
265278

266-
Vector<File> files; ///< Files that belong to the project
267-
CompileFlags compile; ///< Shared CompileFlags for all files in the project
268-
LinkFlags link; ///< Shared LinkFlags for all files in the project
279+
SourceFiles files; ///< Project source files with their associated compile flags
280+
LinkFlags link; ///< Linker flags applied to all files in the project
269281

270282
Vector<Configuration> configurations; ///< Build configurations created inside the project
271283

@@ -278,19 +290,42 @@ struct Project
278290

279291
/// @brief Get Configuration with the matching `configurationName`
280292
[[nodiscard]] Configuration* getConfiguration(StringView configurationName);
293+
281294
/// @brief Get Configuration with the matching `configurationName`
282295
[[nodiscard]] const Configuration* getConfiguration(StringView configurationName) const;
283296

284-
/// @brief Add all files from specific subdirectory (relative to project root) matching given filter
297+
/// @brief Add all source or header/inline files from a subdirectory (relative to project root) matching the given
298+
/// filter
285299
/// @param subdirectory The subdirectory to search files from, absolute or relative to project root. No `*` allowed.
286300
/// @param filter The suffix filter that is appended to `subdirectory` (can contain `*`)
287-
[[nodiscard]] bool addDirectory(StringView subdirectory, StringView filter);
301+
/// @note Files with header or inline extension (`.h`, `.hpp`, `.inl`) will be considered non-source files.
302+
[[nodiscard]] bool addFiles(StringView subdirectory, StringView filter);
288303

289-
/// @brief Add a single file to the project
304+
/// @brief Add a single source or header/inline file to the project, relative to project root
290305
[[nodiscard]] bool addFile(StringView singleFile);
291306

292-
/// @brief Remove files matching the given filter. Useful to remove only a specific file type after
293-
/// Project::addDirectory
307+
/// @brief Adds paths to include paths list
308+
[[nodiscard]] bool addIncludePaths(Span<const StringView> includePaths);
309+
310+
/// @brief Adds paths to libraries paths list
311+
[[nodiscard]] bool addLinkLibraryPaths(Span<const StringView> libraryPaths);
312+
313+
/// @brief Adds libraries to be linked
314+
[[nodiscard]] bool addLinkLibraries(Span<const StringView> linkLibraries);
315+
316+
/// @brief Add frameworks shared with all apple os
317+
[[nodiscard]] bool addLinkFrameworks(Span<const StringView> frameworks);
318+
319+
/// @brief Add frameworks only for macOS
320+
[[nodiscard]] bool addLinkFrameworksMacOS(Span<const StringView> frameworks);
321+
322+
/// @brief Add frameworks only for iOS
323+
[[nodiscard]] bool addLinkFrameworksIOS(Span<const StringView> frameworks);
324+
325+
/// @brief Adds some pre-processor defines
326+
[[nodiscard]] bool addDefines(Span<const StringView> defines);
327+
328+
/// @brief Remove files matching a filter, to remove only a specific file type after Project::addDirectory
294329
/// @param subdirectory The subdirectory to search files into, absolute or relative to project root. No `*` allowed.
295330
/// @param filter The suffix filter that is appended to `subdirectory` (can contain `*`)
296331
[[nodiscard]] bool removeFiles(StringView subdirectory, StringView filter);
@@ -312,6 +347,7 @@ struct Workspace
312347
[[nodiscard]] Result validate() const;
313348
};
314349

350+
/// @brief Collects all directories used during build generation
315351
struct Directories
316352
{
317353
String projectsDirectory;

0 commit comments

Comments
 (0)