diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..6958982 --- /dev/null +++ b/.clang-format @@ -0,0 +1,38 @@ +--- +Language: Cpp +BasedOnStyle: LLVM +DisableFormat: false +AccessModifierOffset: -1 +AlignArrayOfStructures: Right +AllowShortCaseLabelsOnASingleLine: false +AllowShortCompoundRequirementOnASingleLine: true +AlwaysBreakTemplateDeclarations: MultiLine +BreakConstructorInitializers: BeforeColon +BreakInheritanceList: BeforeComma +BreakTemplateDeclarations: MultiLine +EmptyLineBeforeAccessModifier: Always +IncludeBlocks: Regroup +IndentCaseLabels: false +InsertBraces: true +InsertNewlineAtEOF: true +IntegerLiteralSeparator: + Binary: 4 + Decimal: 3 + Hex: 4 +KeepEmptyLines: + AtEndOfFile: false + AtStartOfBlock: false + AtStartOfFile: false +KeepEmptyLinesAtEOF: false +KeepEmptyLinesAtTheStartOfBlocks: false +LineEnding: LF +PointerAlignment: Left +QualifierAlignment: Custom +QualifierOrder: ['inline', 'static', 'constexpr', 'type', 'const', 'volatile'] +RequiresClausePosition: OwnLine +RequiresExpressionIndentation: OuterScope +ShortNamespaceLines: 8 +SpacesBeforeTrailingComments: 2 +UseCRLF: false +UseTab: Never +... diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..548256c --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,96 @@ +--- +# check options see https://clang.llvm.org/extra/clang-tidy/checks/list.html + +Checks: > + -*, + boost-*, + bugprone-*, + -bugprone-argument-comment, + -bugprone-easily-swappable-parameters, + -bugprone-unsafe-functions, + cert-*, + -cert-dcl58-cpp, + -cert-err52-cpp, + -cert-err58-cpp, + -cert-msc50-cpp, + concurrency-*, + clang-analyzer-core.*, + clang-analyzer-cplusplus.*, + clang-analyzer-nullability.*, + clang-analyzer-optin.cplusplus.*, + clang-analyzer-optin.performance.*, + clang-analyzer-unix.*, + clang-analyzer-valist.*, + cppcoreguidelines-avoid-capture-default-when-capturing-this, + cppcoreguidelines-prefer-member-initializer, + cppcoreguidelines-slicing, + cppcoreguidelines-special-member-functions, + cppcoreguidelines-virtual-class-destructor, + google-*, + -google-objc-*, + -google-runtime-references, + misc-*, + -misc-no-recursion, + -misc-non-private-member-variables-in-classes, + modernize-*, + -modernize-avoid-c-arrays, + -modernize-deprecated-headers, + performance-*, + readability-*, + -readability-avoid-nested-conditional-operator, + -readability-convert-member-functions-to-static, + -readability-inconsistent-declaration-parameter-name, + -readability-magic-numbers, + -readability-suspicious-call-argument, + -readability-uppercase-literal-suffix, +CheckOptions: + bugprone-suspicious-include.HeaderFileExtensions: ';h;hh;hpp;hxx;tcc;inc;def' + google-build-namespaces.HeaderFileExtensions: 'h,hh,hpp,hxx,tcc,' + google-global-names-in-headers.HeaderFileExtensions: 'h,hh,hpp,hxx,tcc,' + google-readability-namespace-comments.SpacesBeforeComments: '2' + google-readability-namespace-comments.ShortNamespaceLines: '8' + misc-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic: 'true' + misc-uniqueptr-reset-release.IncludeStyle: llvm + modernize-loop-convert.MaxCopySize: '8' + modernize-loop-convert.MinConfidence: reasonable + modernize-pass-by-value.IncludeStyle: llvm + modernize-replace-auto-ptr.IncludeStyle: llvm + modernize-use-emplace.IgnoreImplicitConstructors: 'true' + modernize-use-override.IgnoreDestructors: 'true' + # SEE: https://clang.llvm.org/extra/clang-tidy/checks/readability-function-cognitive-complexity.html + readability-function-cognitive-complexity.Threshold: '25' + readability-function-size.LineThreshold: '64' + readability-function-size.StatementThreshold: '512' + readability-identifier-length.MinimumVariableNameLength: '2' + readability-identifier-length.MinimumParameterNameLength: '2' + readability-identifier-naming.ClassCase: CamelCase + readability-identifier-naming.ClassConstantCase: lower_case + readability-identifier-naming.ClassMemberCase: lower_case + readability-identifier-naming.ClassMethodCase: lower_case + readability-identifier-naming.ConstantCase: CamelCase + readability-identifier-naming.ConstantIgnoredRegexp: '__.*' + readability-identifier-naming.ConstantPrefix: k + readability-identifier-naming.EnumCase: CamelCase + readability-identifier-naming.EnumConstantCase: CamelCase + readability-identifier-naming.EnumConstantPrefix: k + readability-identifier-naming.FunctionCase: lower_case + readability-identifier-naming.MacroDefinitionCase: UPPER_CASE + readability-identifier-naming.MacroDefinitionIgnoredRegexp: '__.*' + readability-identifier-naming.PrivateMemberSuffix: _ + readability-identifier-naming.ProtectedMemberSuffix: _ + readability-identifier-naming.StaticConstantCase: lower_case + readability-identifier-naming.StructCase: CamelCase + readability-identifier-naming.TemplateParameterCase: CamelCase + readability-identifier-naming.TypeTemplateParameterIgnoredRegexp: expr-type + readability-identifier-naming.TypeAliasCase: CamelCase + readability-identifier-naming.TypeAliasIgnoredRegexp: '^(.+_)?type$|^(.+_)?pointer$|^(.+_)?reference$|^(.+_)?iterator$' + readability-identifier-naming.TypedefCase: CamelCase + readability-identifier-naming.TypedefIgnoredRegexp: '^(.+_)?type$|^(.+_)?pointer$|^(.+_)?reference$|^(.+_)?iterator$' + readability-identifier-naming.VariableCase: lower_case + readability-identifier-naming.VariableIgnoredRegexp: '__.*' + readability-implicit-bool-conversion.AllowIntegerConditions: 'true' + readability-implicit-bool-conversion.AllowPointerConditions: 'true' +FormatStyle: none +HeaderFilterRegex: '.*' +WarningsAsErrors: '' +... diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..daf5bb3 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,50 @@ +root = true + +[*] +charset = utf-8 +curly_bracket_next_line = false +end_of_line = lf +indent_size = 2 +indent_style = space +insert_final_newline = true +max_line_length = 80 +quote_type = double +spaces_around_operators = true +tab_width = 4 +trim_trailing_whitespace = true + +[*.{bat,cmd}] +end_of_line = crlf +indent_size = 4 +max_line_length = 120 + +[*.{c,h}] +indent_size = 8 + +[{CMakeLists.txt,*.cmake,*.rst}] +max_line_length = 120 + +[{Makefile,*.{go,mk}}] +indent_style = tab +max_line_length = 120 + +[*.{md,markdown}] +indent_size = 2 +max_line_length = 120 +trim_trailing_whitespace = false + +[*.ps1] +end_of_line = crlf +indent_size = 4 +max_line_length = 120 + +[*.{py,rs}] +indent_size = 4 + +[*.sh] +indent_size = 4 +max_line_length = 120 + +[*.{sln,vcxproj,vcproj,xproj,props,vcxitems,manifest}] +charset = utf-8-bom +end_of_line = crlf diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..0dc13c9 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,45 @@ +.git* export-ignore +.editorconfig export-ignore + + +######################### C ######################### +*.c text eol=lf diff=c encoding +*.h text eol=lf diff=c encoding + + +######################### C++ ######################### +*.cc text eol=lf diff=cpp encoding +*.cxx text eol=lf diff=cpp encoding +*.cpp text eol=lf diff=cpp encoding +*.c++ text eol=lf diff=cpp encoding +*.hh text eol=lf diff=cpp encoding +*.hxx test eol=lf diff=cpp encoding +*.hpp text eol=lf diff=cpp encoding +*.h++ text eol=lf diff=cpp encoding +*.tcc text eol=lf diff=cpp encoding + + +######################### CMake ######################### +*.cmake text eol=lf encoding +CMakeLists.txt text eol=lf encoding + + +######################### VisualStudio ######################### +*.sln text eol=crlf +*.csproj text eol=crlf +*.vbproj text eol=crlf +*.vcxproj text eol=crlf +*.vcproj text eol=crlf +*.dbproj text eol=crlf +*.fsproj text eol=crlf +*.lsproj text eol=crlf +*.wixproj text eol=crlf +*.modelproj text eol=crlf +*.sqlproj text eol=crlf +*.wwaproj text eol=crlf + +*.xproj text eol=crlf +*.props text eol=crlf +*.filters text eol=crlf +*.vcxitems text eol=crlf +*.manifest text eol=crlf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ee217f6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,672 @@ +*build/ +*3rdparty/ +[._]cache/ + + +######################### C++ ######################### +# repo: github/gitignore; pin: 2c52d023dd; file: C++.gitignore +# LICENSE: Creative Commons Zero v1.0 Universal +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + + +######################### CMake ######################### +# repo: github/gitignore; pin: f273474b97; file: CMake.gitignore +# LICENSE: Creative Commons Zero v1.0 Universal +CMakeLists.txt.user +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +_deps + + +######################### Emacs ######################### +# repo: github/gitignore; pin: 87ec1bd864; file: Global/Emacs.gitignore +# LICENSE: Creative Commons Zero v1.0 Universal +# -*- mode: gitignore; -*- +*~ +\#*\# +/.emacs.desktop +/.emacs.desktop.lock +*.elc +auto-save-list +tramp +.\#* + +# Org-mode +.org-id-locations +*_archive + +# flymake-mode +*_flymake.* + +# eshell files +/eshell/history +/eshell/lastdir + +# elpa packages +/elpa/ + +# reftex files +*.rel + +# AUCTeX auto folder +/auto/ + +# cask packages +.cask/ +dist/ + +# Flycheck +flycheck_*.el + +# server auth directory +/server/ + +# projectiles files +.projectile + +# directory configuration +.dir-locals.el + +# network security +/network-security.data + + +######################### Vim ######################### +# repo: github/gitignore; pin: 41ec05833a; file: Global/Vim.gitignore +# LICENSE: Creative Commons Zero v1.0 Universal +# Swap +[._]*.s[a-v][a-z] +!*.svg # comment out if you don't need vector files +[._]*.sw[a-p] +[._]s[a-rt-v][a-z] +[._]ss[a-gi-z] +[._]sw[a-p] + +# Session +Session.vim +Sessionx.vim + +# Temporary +.netrwhist +*~ +# Auto-generated tag files +tags +# Persistent undo +[._]*.un~ + + +######################### VisualStudioCode ######################### +# repo: github/gitignore; pin: bf3f140cfa; file: Global/VisualStudioCode.gitignore +# LICENSE: Creative Commons Zero v1.0 Universal +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + + +######################### JetBrains ######################### +# repo: github/gitignore; pin: cdde85a36e; file: Global/JetBrains.gitignore +# LICENSE: Creative Commons Zero v1.0 Universal +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + + +######################### VisualStudio ######################### +# repo: github/gitignore; pin: 491040e88a; file: Global/VisualStudio.gitignore +# LICENSE: Creative Commons Zero v1.0 Universal +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml + + +######################### Archives ######################### +# repo: github/gitignore; pin: 3794768510; file: Global/Archives.gitignore +# LICENSE: Creative Commons Zero v1.0 Universal +# It's better to unpack these files and commit the raw source because +# git has its own built in compression methods. +*.7z +*.jar +*.rar +*.zip +*.gz +*.gzip +*.tgz +*.bzip +*.bzip2 +*.bz2 +*.xz +*.lzma +*.cab +*.xar + +# Packing-only formats +*.iso +*.tar + +# Package management formats +*.dmg +*.xpi +*.gem +*.egg +*.deb +*.rpm +*.msi +*.msm +*.msp +*.txz diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..2dcb633 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.13 FATAL_ERROR) + +project(nautilus + LANGUAGES CXX + VERSION 0.1) + +if(CMAKE_VERSION VERSION_LESS 3.21) + get_property(not_top DIRECTORY PROPERTY PARENT_DIRECTORY) + if(NOT not_top) + set(PROJECT_IS_TOP_LEVEL ON) + endif() +endif() + +list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") + +include(nautilus_configuration) +include(nautilus_definition) +include(nautilus_tool) + +list(REMOVE_AT CMAKE_MODULE_PATH -1) + +add_subdirectory(src) + +enable_testing() +if(NAUTILUS_BUILD_TESTS) + add_subdirectory(test) +endif() diff --git a/cmake/configuration/nautilus_compiler.cmake b/cmake/configuration/nautilus_compiler.cmake new file mode 100644 index 0000000..cd47d35 --- /dev/null +++ b/cmake/configuration/nautilus_compiler.cmake @@ -0,0 +1,116 @@ +include_guard() + +macro(_NAUTILUS_COMPILER_CONFIG_MSVC) + list(APPEND NAUTILUS_COMPILE_DEFINITIONS_COMMON + _CRT_NONSTDC_NO_DEPRECATE + _CRT_SECURE_NO_DEPRECATE + _CRT_SECURE_NO_WARNINGS + _SCL_SECURE_NO_WARNINGS + NOMINMAX # disable min/max problem in windows.h + ) + list(APPEND NAUTILUS_COMPILE_OPTIONS_COMMON + /bigobj # Compiler Fatal error C1128: Object Limit Exceed + /Oi # enable built-in functions + /permissive- + /source-charset:utf-8 + /volatile:iso # Specifies how the volatile keyword is to be interpreted. + /wd4996 # mark deprecated (/W3) + $<$,$>:/WX> + ) + list(APPEND NAUTILUS_COMPILE_OPTIONS_DEVELOP + /Wall + ) + if(CXX IN_LIST NAUTILUS_LANGUAGES) + list(APPEND NAUTILUS_COMPILE_OPTIONS_COMMON + /GR- # Disable RTTI + ) + endif() +endmacro() + +macro(_NAUTILUS_COMPILER_CONFIG_GCC) + # GNU Compiler Collection + # Learn more at https://gcc.gnu.org/onlinedocs/gcc/Invoking-GCC.html + list(APPEND NAUTILUS_COMPILE_OPTIONS_COMMON + -fmax-errors=5 + -finput-charset=UTF8 + ) + list(APPEND NAUTILUS_COMPILE_OPTIONS_DEVELOP + -fprofile-abs-path + # --coverage is equivalent to -ftest-profile -fprofile-arcs + $<$>>:--coverage> + ) + if(CXX IN_LIST NAUTILUS_LANGUAGES) + list(APPEND NAUTILUS_COMPILE_OPTIONS_COMMON + -fno-threadsafe-statics + -fmerge-all-constants + $<$>:-nostdinc++> + ) + endif() + foreach(dir IN LISTS NAUTILUS_STDLIB_INCLUDEDIRS) + list(APPEND NAUTILUS_COMPILE_OPTIONS_COMMON -isystem${dir}) + endforeach() +endmacro() + +macro(_NAUTILUS_COMPILER_CONFIG_CLANG) + # Clang + # Learn more at https://clang.llvm.org/docs/UsersManual.html + list(APPEND NAUTILUS_COMPILE_OPTIONS_COMMON + -ferror-limit=5 + -finput-charset=UTF-8 + ) + list(APPEND NAUTILUS_COMPILE_OPTIONS_DEVELOP + -fdiagnostics-absolute-paths + # --coverage is equivalent to -ftest-profile -fprofile-arcs + $<$>>: + $>, + --coverage, + -fprofile-instr-generate\;-fcoverage-mapping>> + ) + if(CXX IN_LIST NAUTILUS_LANGUAGES) + list(APPEND NAUTILUS_COMPILE_OPTIONS_COMMON + -Wthread-safety + $<$>:-stdlib=libc++> + ) + endif() +endmacro() + +get_property(NAUTILUS_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) +if(NAUTILUS_COMPILER_IS_MSVC) + _NAUTILUS_COMPILER_CONFIG_MSVC() +else() + list(APPEND NAUTILUS_COMPILE_OPTIONS_COMMON + -fno-common + $<$:-Werror\;-Wno-error=deprecated-declarations> + ) + list(APPEND NAUTILUS_COMPILE_OPTIONS_DEVELOP + -Wall + -fno-inline + -pedantic + # from lua Makefile, enable compiler warning + -Wdisabled-optimization + -Wdouble-promotion + -Wextra + -Wmissing-declarations + -Wredundant-decls + -Wshadow + -Wsign-compare + -Wundef + # -Wfatal-errors + # from kDE cmake + -Wcast-align + -Wno-long-long + ) + if(CXX IN_LIST NAUTILUS_LANGUAGES) + list(APPEND NAUTILUS_COMPILE_OPTIONS_COMMON + -fno-rtti # Disable RTTI + ) + endif() + if(NAUTILUS_COMPILER_IS_GCC) + _NAUTILUS_COMPILER_CONFIG_GCC() + elseif(NAUTILUS_COMPILER_IS_CLANG) + _NAUTILUS_COMPILER_CONFIG_CLANG() + else() + message(${NAUTILUS_MESSAGE_WARNING} "Unknow compiler ${CMAKE_CXX_COMPILER_ID}.") + endif() +endif() +unset(NAUTILUS_LANGUAGES) diff --git a/cmake/configuration/nautilus_generator.cmake b/cmake/configuration/nautilus_generator.cmake new file mode 100644 index 0000000..940e109 --- /dev/null +++ b/cmake/configuration/nautilus_generator.cmake @@ -0,0 +1,14 @@ +include_guard() + +if(CMAKE_GENERATOR MATCHES "Ninja") + if(NAUTILUS_COMPILER_IS_MSVC) + elseif(NAUTILUS_COMPILER_IS_GCC) + list(APPEND NAUTILUS_COMPILE_OPTIONS_COMMON + -fdiagnostics-color=always + ) + elseif(NAUTILUS_COMPILER_IS_CLANG) + list(APPEND NAUTILUS_COMPILE_OPTIONS_COMMON + -fcolor-diagnostics + ) + endif() +endif() diff --git a/cmake/configuration/nautilus_linker.cmake b/cmake/configuration/nautilus_linker.cmake new file mode 100644 index 0000000..553295b --- /dev/null +++ b/cmake/configuration/nautilus_linker.cmake @@ -0,0 +1,73 @@ +include_guard() + +function(nautilus_target_ipo TARGET_NAME) + if(NOT NAUTILUS_ENABLE_IPO) + return() + endif() + include(CheckIPOSupported) + check_ipo_supported(RESULT result OUTPUT output) + if(result) + set_target_properties(${TARGET_NAME} PROPERTIES + INTERPROCEDURAL_OPTIMIZATION ON) + else() + message(${NAUTILUS_MESSAGE_WARNING} "IPO is not supported: ${output}.") + endif() +endfunction() + +macro(_NAUTILUS_LINKER_CONFIG_GCC) + list(APPEND NAUTILUS_LINK_OPTIONS_DEVELOP + $<$>>:--coverage> + ) + if(NAUTILUS_USE_STDLIB) + list(APPEND NAUTILUS_LINK_OPTIONS_COMMON + -lm + -lc + -nodefaultlibs + $<$:-lgcc_s\;-lgcc> + $,$>>,-m32,-march=native> + ) + endif() + if(NAUTILUS_USE_STDLIB AND C IN_LIST NAUTILUS_LANGUAGES) + list(APPEND NAUTILUS_COMPILE_OPTIONS_COMMON + -nostdlib + ) + endif() + if(NAUTILUS_USE_STDLIB AND CXX IN_LIST NAUTILUS_LANGUAGES) + list(APPEND NAUTILUS_COMPILE_OPTIONS_COMMON + -nostdlib++ + $<$:-lc++\;-lc++abi\;-lsupc++> + $<$:-lstdc++> + ) + endif() +endmacro() + +macro(_NAUTILUS_LINKER_CONFIG_CLANG) + list(APPEND NAUTILUS_LINK_OPTIONS_DEVELOP + # --coverage is equivalent to -ftest-profile -fprofile-arcs + $<$>>: + $>, + --coverage, + -fprofile-instr-generate\;-fcoverage-mapping>> + ) + if(NAUTILUS_USE_STDLIB AND CXX IN_LIST NAUTILUS_LANGUAGES) + list(APPEND NAUTILUS_LINK_OPTIONS_COMMON + $<$:-stdlib=libc++\;-lc++> + ) + endif() +endmacro() + +get_property(NAUTILUS_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) +if(NAUTILUS_COMPILER_IS_MSVC) +else() + list(APPEND NAUTILUS_LINK_OPTIONS_COMMON + $<$:-fuse-ld=${NAUTILUS_USE_LINKER}> + ) + if(NAUTILUS_COMPILER_IS_GCC) + _NAUTILUS_LINKER_CONFIG_GCC() + elseif(NAUTILUS_COMPILER_IS_CLANG) + _NAUTILUS_LINKER_CONFIG_CLANG() + else() + message(${NAUTILUS_MESSAGE_WARNING} "Unknow compiler ${CMAKE_CXX_COMPILER_ID}.") + endif() +endif() +unset(NAUTILUS_LANGUAGES) diff --git a/cmake/configuration/nautilus_precompile_header.cmake b/cmake/configuration/nautilus_precompile_header.cmake new file mode 100644 index 0000000..9cd5c74 --- /dev/null +++ b/cmake/configuration/nautilus_precompile_header.cmake @@ -0,0 +1,203 @@ +include_guard() + +function(nautilus_target_pch TARGET_NAME) + if(NOT NAUTILUS_ENABLE_PCH) + return() + endif() + if(CMAKE_VERSION VERSION_LESS 3.16) + message(${NAUTILUS_MESSAGE_WARNING} "Consider upgrading CMake to 3.16 or latest, current version ${CMAKE_VERSION} does not support PCH.") + return() + endif() + if(NOT NAUTILUS_COMPILER_IS_CLANG AND NAUTILUS_ENABLE_LINT) + message(${NAUTILUS_MESSAGE_WARNING} "clang-tidy not support with non-clang pch") + return() + endif() + + set(options THREAD) + set(oneValueArgs) + set(multiValueArgs PUBLIC INTERFACE PRIVATE) + cmake_parse_arguments(NAUTILUS_PCH "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + get_property(NAUTILUS_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) + get_target_property(C_STANDARD_VAR ${TARGET_NAME} C_STANDARD) + if(C_STANDARD_VAR MATCHES "-NOTFOUND" OR C_STANDARD_VAR STREQUAL 99) + set(C_STANDARD_VAR 0) + endif() + get_target_property(CXX_STANDARD_VAR ${TARGET_NAME} CXX_STANDARD) + + target_precompile_headers(${TARGET_NAME} PUBLIC + + + + + + + + + + + + + + + + + + + + ) + if(C_STANDARD_VAR GREATER_EQUAL 11) + target_precompile_headers(${TARGET_NAME} PUBLIC + + + + ) + endif() + if(C_STANDARD_VAR GREATER_EQUAL 23) + target_precompile_headers(${TARGET_NAME} PUBLIC + + + ) + endif() + if(NAUTILUS_PCH_THREAD AND C_STANDARD_VAR GREATER_EQUAL 11) + target_precompile_headers(${TARGET_NAME} PUBLIC + + + ) + endif() + if(CXX IN_LIST NAUTILUS_LANGUAGES) + target_precompile_headers(${TARGET_NAME} PUBLIC + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ) + if(CXX_STANDARD_VAR GREATER_EQUAL 17) + target_precompile_headers(${TARGET_NAME} PUBLIC + + + + + + + + + ) + endif() + if(CXX_STANDARD_VAR GREATER_EQUAL 20) + target_precompile_headers(${TARGET_NAME} PUBLIC + + + + + + + + + + + ) + endif() + if(CXX_STANDARD_VAR GREATER_EQUAL 23) + target_precompile_headers(${TARGET_NAME} PUBLIC + + + + + + + + + ) + endif() + if(NAUTILUS_PCH_THREAD) + target_precompile_headers(${TARGET_NAME} PUBLIC + + + + + + ) + endif() + if(NAUTILUS_PCH_THREAD AND CXX_STANDARD_VAR GREATER_EQUAL 14) + target_precompile_headers(${TARGET_NAME} PUBLIC + + ) + endif() + if(NAUTILUS_PCH_THREAD AND CXX_STANDARD_VAR GREATER_EQUAL 20) + target_precompile_headers(${TARGET_NAME} PUBLIC + + + + + ) + endif() + endif() + + target_precompile_headers(${TARGET_NAME} + PUBLIC ${NAUTILUS_PCH_PUBLIC} + INTERFACE ${NAUTILUS_PCH_INTERFACE} + PRIVATE ${NAUTILUS_PCH_PRIVATE} + ) +endfunction() + +function(nautilus_target_reuse_pch TARGET_NAME REUSED_TARGET_NAME) + if(NOT NAUTILUS_ENABLE_PCH OR TARGET_NAME STREQUAL REUSED_TARGET_NAME) + return() + endif() + set(options) + set(oneValueArgs) + set(multiValueArgs PUBLIC INTERFACE PRIVATE) + cmake_parse_arguments(NAUTILUS_PCH "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + target_precompile_headers(${TARGET_NAME} REUSE_FROM + ${REUSED_TARGET_NAME} + ) + + target_precompile_headers(${TARGET_NAME} + PUBLIC ${NAUTILUS_PCH_PUBLIC} + INTERFACE ${NAUTILUS_PCH_INTERFACE} + PRIVATE ${NAUTILUS_PCH_PRIVATE} + ) +endfunction() diff --git a/cmake/definition/nautilus_defvar.cmake b/cmake/definition/nautilus_defvar.cmake new file mode 100644 index 0000000..c5f6589 --- /dev/null +++ b/cmake/definition/nautilus_defvar.cmake @@ -0,0 +1,88 @@ +include_guard() + +include(nautilus_option) + +set(NAUTILUS_COMPILE_DEFINITIONS_COMMON) +set(NAUTILUS_COMPILE_DEFINITIONS_DEVELOP) +set(NAUTILUS_COMPILE_DEFINITIONS_RELEASE) +set(NAUTILUS_COMPILE_OPTIONS_COMMON) +set(NAUTILUS_COMPILE_OPTIONS_DEVELOP) +set(NAUTILUS_COMPILE_OPTIONS_RELEASE) +set(NAUTILUS_LINK_OPTIONS_COMMON) +set(NAUTILUS_LINK_OPTIONS_DEVELOP) +set(NAUTILUS_LINK_OPTIONS_RELEASE) + +if(NAUTILUS_WARNINGS_AS_ERRORS) + set(NAUTILUS_MESSAGE_WARNING FATAL_ERROR) +else() + set(NAUTILUS_MESSAGE_WARNING WARNING) +endif() + +# compiler + +if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) + set(NAUTILUS_COMPILER_IS_GCC ON) +elseif(CMAKE_C_COMPILER_ID MATCHES ".*Clang" OR + CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") + set(NAUTILUS_COMPILER_IS_CLANG ON) +elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + set(NAUTILUS_COMPILER_IS_MSVC ON) +endif() + +# system +## Please use $. +## see more: https://cmake.org/cmake/help/latest/variable/CMAKE_SYSTEM_NAME.html#variable:CMAKE_SYSTEM_NAME + +# IHV +# learn more about platform at https://github.com/Kitware/CMake/blob/master/Modules/CMakePlatformId.h.in + +if(CMAKE_SYSTEM_PROCESSOR STREQUAL "") + set(CMAKE_SYSTEM_PROCESSOR ${CMAKE_HOST_SYSTEM_PROCESSOR}) +endif() +string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" NAUTILUS_ARCH_ID) + +if(NAUTILUS_ARCH_ID MATCHES "arm" OR NAUTILUS_ARCH_ID MATCHES "^aarch.*") + set(NAUTILUS_ARCH_IS_ARM ON) +elseif(NAUTILUS_ARCH_ID MATCHES "^ppc.*" OR NAUTILUS_ARCH_ID MATCHES "^powerpc.*") + set(NAUTILUS_ARCH_IS_POWERPC ON) +elseif(NAUTILUS_ARCH_ID MATCHES "^riscv.*") + set(NAUTILUS_ARCH_IS_RISCV ON) +elseif(NAUTILUS_ARCH_ID MATCHES "^loongarch.*") + set(NAUTILUS_ARCH_IS_LOONG ON) +elseif(NAUTILUS_ARCH_ID MATCHES "x86.*" OR NAUTILUS_ARCH_ID MATCHES "^i.*86") + set(NAUTILUS_ARCH_IS_X86 ON) +elseif(NAUTILUS_ARCH_ID STREQUAL "amd64") + set(NAUTILUS_ARCH_IS_X86 ON) +elseif(NAUTILUS_ARCH_ID MATCHES "^sparc.*" OR NAUTILUS_ARCH_ID STREQUAL "s390x") + set(NAUTILUS_ARCH_IS_SPARC ON) +else() + message(FATAL_ERROR "Not support the architecture platform: ${NAUTILUS_ARCH_ID}.") +endif() + +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(NAUTILUS_ARCH_IS_64BIT ON) +elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) + set(NAUTILUS_ARCH_IS_32BIT ON) +else() + message(FATAL_ERROR "Not support the architecture.") +endif() + +if(CMAKE_VERSION VERSION_LESS 3.20) + include(TestBigEndian) + test_big_endian(NAUTILUS_IS_BIG_ENDIAN) +else() + get_property(NAUTILUS_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) + foreach(lang IN LISTS NAUTILUS_LANGUAGES) + if(NOT ${CMAKE_${lang}_BYTE_ORDER} STREQUAL "") + set(NAUTILUS_ARCH_ENDIANNESS ${CMAKE_${lang}_BYTE_ORDER}) + break() + endif() + endforeach() + if(NAUTILUS_ARCH_ENDIANNESS STREQUAL "BIG_ENDIAN") + set(NAUTILUS_IS_BIG_ENDIAN ON) + else() + set(NAUTILUS_IS_BIG_ENDIAN OFF) + endif() + unset(NAUTILUS_ARCH_ENDIANNESS) + unset(NAUTILUS_LANGUAGES) +endif() diff --git a/cmake/definition/nautilus_option.cmake b/cmake/definition/nautilus_option.cmake new file mode 100644 index 0000000..60edfa2 --- /dev/null +++ b/cmake/definition/nautilus_option.cmake @@ -0,0 +1,70 @@ +include_guard() + +include(nautilus_policy) + +# flag + +set(NAUTILUS_STDLIB_INCLUDEDIRS "" + CACHE STRING "Specify header directories of stdlib, must be specify if not use default") +# e.g. +# stdcxx: /usr/include/c++/7;/usr/include/x86_64-linux-gnu/c++/7 +# cxx: /usr/lib/llvm-15/include/c++/v1 + +set(NAUTILUS_USE_SANITIZER "" + CACHE STRING "Build with sanitizers, e.g. `Address;Undefined'.") + +set(NAUTILUS_USE_STDLIB "" + CACHE STRING "Use std library of C++.") +set_property(CACHE NAUTILUS_USE_STDLIB PROPERTY STRINGS + "" + "stdcxx" + "cxx" + ) + +set(NAUTILUS_USE_LINKER "" + CACHE STRING "Use a specific linker, e.g. `bfd'") +set_property(CACHE NAUTILUS_USE_LINKER PROPERTY STRINGS + "" # default is bfd + "bfd" + "gold" + "lld" + "mold" + ) + +set(NAUTILUS_COMPILER_LAUNCHER "" + CACHE STRING "A compiler launching tool, e.g. `ccache'") +set_property(CACHE NAUTILUS_COMPILER_LAUNCHER PROPERTY STRINGS + "" # default None + "ccache" + ) + +set(NAUTILUS_USE_COVERAGE "" + CACHE STRING "Use a specific coverage, e.g. `gcovr'") +set_property(CACHE NAUTILUS_USE_COVERAGE PROPERTY STRINGS + "" # default None + "gcovr" + "lcov" + ) + +# option + +option(NAUTILUS_WARNINGS_AS_ERRORS "Warnings as errors?" OFF) + +option(NAUTILUS_BUILD_32BITS "Build 32 bits executables and libraries." OFF) + +option(NAUTILUS_BUILD_SHARED "Build shared libraries." OFF) + +option(NAUTILUS_BUILD_TESTS "Build tests?" OFF) + +option(NAUTILUS_BUILD_TOOLS "Build tools?" ON) + +option(NAUTILUS_ENABLE_IPO "Enable interprocedual optimization." OFF) + +option(NAUTILUS_ENABLE_PCH "Enable precompile headers." OFF) + +option(NAUTILUS_ENABLE_LINT "Use code check by clang tidy." OFF) + +option(NAUTILUS_ENABLE_DOXYGEN "Generate documentation with doxygen." OFF) + +# Set off means to use the default way to link. +option(NAUTILUS_LINK_STATIC "Statically link 3rdpatry libraries." OFF) diff --git a/cmake/definition/nautilus_override.cmake b/cmake/definition/nautilus_override.cmake new file mode 100644 index 0000000..83491a0 --- /dev/null +++ b/cmake/definition/nautilus_override.cmake @@ -0,0 +1,32 @@ +include_guard() + +include(nautilus_defvar) +include(nautilus_option) + +if(NAUTILUS_ARCH_IS_32BIT) + set(NAUTILUS_TARGET_IS_64BIT OFF) + set(NAUTILUS_TARGET_IS_32BIT ON) +endif() + +if(NAUTILUS_BUILD_SHARED) + set(CMAKE_POSITION_INDEPENDENT_CODE ON) +endif() + +if(NAUTILUS_USE_STDLIB AND NOT NAUTILUS_COMPILER_IS_CLANG AND + NAUTILUS_STDLIB_INCLUDEDIRS STREQUAL "") + message(FATAL_ERROR "Must specify header directory of stdlib if don't use default stdlib") +elseif(NOT NAUTILUS_USE_STDLIB) + set(NAUTILUS_STDLIB_INCLUDEDIRS "" CACHE STRING "Don't specify header dir when use default stdlib." FORCE) +endif() + +if(NOT PROJECT_IS_TOP_LEVEL) + set(NAUTILUS_USE_SANITIZER "" CACHE STRING "Disable sanitizers when project is submodule." FORCE) + set(NAUTILUS_BUILD_TESTS OFF CACHE BOOL "Build tests override when project is submodule." FORCE) + set(NAUTILUS_BUILD_TOOLS OFF CACHE BOOL "Build tools override when project is submodule." FORCE) + set(NAUTILUS_USE_COVERAGE "" CACHE STRING "Build coverage override when project is submodule." FORCE) + set(NAUTILUS_ENABLE_LINT OFF CACHE BOOL "Disable code check override when project is submodule." FORCE) +elseif(NAUTILUS_BUILD_TESTS) + set(NAUTILUS_BUILD_TOOLS ON CACHE BOOL "Build tools override by NAUTILUS_BUILD_TESTS." FORCE) +elseif(NAUTILUS_USE_COVERAGE) # Not build tests, disable coverage + set(NAUTILUS_USE_COVERAGE "" CACHE STRING "Disable code coverage override by NAUTILUS_BUILD_TESTS." FORCE) +endif() diff --git a/cmake/definition/nautilus_policy.cmake b/cmake/definition/nautilus_policy.cmake new file mode 100644 index 0000000..108406e --- /dev/null +++ b/cmake/definition/nautilus_policy.cmake @@ -0,0 +1,48 @@ +# copy from OpenCV +# LICENSE: Apache License 2.0 + +include_guard() + +if(POLICY CMP0026) + cmake_policy(SET CMP0026 NEW) +endif() + +if(POLICY CMP0042) + cmake_policy(SET CMP0042 NEW) # CMake 3.0+ (2.8.12): MacOS "@rpath" in target's install name +endif() + +if(POLICY CMP0046) + cmake_policy(SET CMP0046 NEW) # warn about non-existed dependencies +endif() + +if(POLICY CMP0051) + cmake_policy(SET CMP0051 NEW) +endif() + +if(POLICY CMP0054) # CMake 3.1: Only interpret if() arguments as variables or keywords when unquoted. + cmake_policy(SET CMP0054 NEW) +endif() + +if(POLICY CMP0056) + cmake_policy(SET CMP0056 NEW) # try_compile(): link flags +endif() + +if(POLICY CMP0066) + cmake_policy(SET CMP0066 NEW) # CMake 3.7: try_compile(): use per-config flags, like CMAKE_CXX_FLAGS_RELEASE +endif() + +if(POLICY CMP0067) + cmake_policy(SET CMP0067 NEW) # CMake 3.8: try_compile(): honor language standard variables (like C++11) +endif() + +if(POLICY CMP0068) + cmake_policy(SET CMP0068 NEW) # CMake 3.9+: `RPATH` settings on macOS do not affect `install_name`. +endif() + +if(POLICY CMP0075) + cmake_policy(SET CMP0075 NEW) # CMake 3.12+: Include file check macros honor `CMAKE_REQUIRED_LIBRARIES` +endif() + +if(POLICY CMP0077) + cmake_policy(SET CMP0077 NEW) # CMake 3.13+: option() honors normal variables. +endif() diff --git a/cmake/nautilus_configuration.cmake b/cmake/nautilus_configuration.cmake new file mode 100644 index 0000000..461ae33 --- /dev/null +++ b/cmake/nautilus_configuration.cmake @@ -0,0 +1,13 @@ +include_guard() + +include(nautilus_check) +include(nautilus_definition) + +list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/configuration") + +include(nautilus_compiler) +include(nautilus_generator) +include(nautilus_linker) +include(nautilus_precompile_header) + +list(REMOVE_AT CMAKE_MODULE_PATH -1) diff --git a/cmake/nautilus_definition.cmake b/cmake/nautilus_definition.cmake new file mode 100644 index 0000000..b2374f5 --- /dev/null +++ b/cmake/nautilus_definition.cmake @@ -0,0 +1,10 @@ +include_guard() + +list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/definition") + +include(nautilus_defvar) +include(nautilus_option) +include(nautilus_override) +include(nautilus_policy) + +list(REMOVE_AT CMAKE_MODULE_PATH -1) diff --git a/cmake/nautilus_tool.cmake b/cmake/nautilus_tool.cmake new file mode 100644 index 0000000..f99c0af --- /dev/null +++ b/cmake/nautilus_tool.cmake @@ -0,0 +1,16 @@ +include_guard() + +include(nautilus_check) +include(nautilus_definition) + +list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/tool") + +include(nautilus_coverage) +if(NAUTILUS_ENABLE_DOXYGEN) + include(nautilus_doxygen) +endif() +include(nautilus_launcher) +include(nautilus_lint) +include(nautilus_sanitizer) + +list(REMOVE_AT CMAKE_MODULE_PATH -1) diff --git a/cmake/tool/nautilus_coverage.cmake b/cmake/tool/nautilus_coverage.cmake new file mode 100644 index 0000000..5cc7495 --- /dev/null +++ b/cmake/tool/nautilus_coverage.cmake @@ -0,0 +1,232 @@ +include_guard() + +macro(__nautilus_coverage_parse_args PREFIX) + set(options) + set(oneValueArgs BASEDIR) + set(multiValueArgs ADDITIONAL_ARGS EXCLUDES) + cmake_parse_arguments(${PREFIX} "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT ${PREFIX}_BASEDIR) + set(${PREFIX}_BASEDIR ${PROJECT_SOURCE_DIR}) + endif() +endmacro() + +function(__nautilus_coverage_get_excludes BASEDIR EXCLUDES) + set(COV_LIST_EXCLUDES) + foreach(EXCLUDE ${EXCLUDES}) + get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR}) + list(APPEND COV_LIST_EXCLUDES "${EXCLUDE}") + endforeach() + list(REMOVE_DUPLICATES COV_LIST_EXCLUDES) + set(COV_LIST_EXCLUDES ${COV_LIST_EXCLUDES} PARENT_SCOPE) +endfunction() + +macro(__nautilus_coverage_get_gcov) + find_program(COV_FE_PATH ${NAUTILUS_USE_COVERAGE}) + if(NOT COV_FE_PATH) + message(FATAL_ERROR "${NAUTILUS_USE_COVERAGE} not found! Aborting...") + endif() + if(NAUTILUS_COMPILER_IS_CLANG) + find_program(LLVM_COV_PATH llvm-cov) + if(LLVM_COV_PATH) + file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/llvm-gcov + CONTENT "#!/usr/bin/env bash\nexec ${LLVM_COV_PATH} gcov \"$@\"\n" + FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE) + set(COV_PATH ${CMAKE_BINARY_DIR}/llvm-gcov) + endif() + endif() + if(NOT COV_PATH) + find_program(GCOV_PATH gcov) + if(NOT GCOV_PATH) + message(FATAL_ERROR "gcov / llvm-cov not found!") + else() + set(COV_PATH ${GCOV_PATH}) + endif() + endif() +endmacro() + +function(__nautilus_coverage_name TARGET_NAME TOOL) + set(NAME ${TARGET_NAME}_coverage_${TOOL}) + set(RESULT_DIR ${PROJECT_BINARY_DIR}/${NAME}) + set(REUSLT_FILE ${RESULT_DIR}/index.html) + set(CREATE_REUSLT_DIR_CMD ${CMAKE_COMMAND} -E make_directory ${RESULT_DIR}) + set(COV_NAME ${NAME} PARENT_SCOPE) + set(COV_RESULT_DIR ${RESULT_DIR} PARENT_SCOPE) + set(COV_CREATE_REUSLT_DIR_CMD ${CREATE_REUSLT_DIR_CMD} PARENT_SCOPE) +endfunction() + +function(nautilus_target_coverage_gcovr TARGET_NAME) + if(NOT NAUTILUS_USE_COVERAGE OR NOT NAUTILUS_USE_COVERAGE STREQUAL "gcovr") + return() + endif() + + __nautilus_coverage_get_gcov() + __nautilus_coverage_parse_args(NAUTILUS_GCOVR ${ARGN}) + __nautilus_coverage_get_excludes(${NAUTILUS_GCOVR_BASEDIR} "${NAUTILUS_GCOVR_EXCLUDES}") + set(GCOVR_EXCLUDE_ARGS) + foreach(EXCLUDE ${COV_LIST_EXCLUDES}) + list(APPEND GCOVR_EXCLUDE_ARGS "-e") + list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE}") + endforeach() + __nautilus_coverage_name(${TARGET_NAME} ${NAUTILUS_USE_COVERAGE}) + get_property(TGT_WORKING_DIR TEST ${TARGET_NAME} PROPERTY WORKING_DIRECTORY) + if(NOT TGT_WORKING_DIR) + set(TGT_WORKING_DIR ${CMAKE_CURRENT_BINARY_DIR}) + endif() + + set(GCOVR_CMD + ${COV_FE_PATH} --html ${COV_RESULT_DIR}/index.html --html-details -r ${NAUTILUS_GCOVR_BASEDIR} + ${NAUTILUS_GCOVR_ADDITIONAL_ARGS} ${GCOVR_EXCLUDE_ARGS} --object-directory=${PROJECT_BINARY_DIR} + --gcov-executable=${COV_PATH} + ) + add_custom_target(${COV_NAME} + COMMAND ${COV_CREATE_REUSLT_DIR_CMD} + COMMAND ${GCOVR_CMD} + BYPRODUCTS ${COV_RESULT_DIR}/index.html + WORKING_DIRECTORY ${TGT_WORKING_DIR} + DEPENDS ${TARGET_NAME} + VERBATIM # Protect arguments to commands + COMMENT "Running ${NAUTILUS_USE_COVERAGE} to code coverage report." + ) + add_test( + NAME ${TARGET_NAME}_coverage + CONFIGURATIONS Debug + COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR} --target ${COV_NAME} + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + ) + set_tests_properties(${TARGET_NAME}_coverage PROPERTIES FIXTURES_CLEANUP ${TARGET_NAME}) +endfunction() + +macro(__nautilus_coverage_lcov_with_gcov) + # the latest gcc maybe failed with lcov: https://github.com/linux-test-project/lcov/issues/296 + set(LCOV_CLEANUP_CMD ${COV_FE_PATH} --zerocounters --directory ${PROJECT_BINARY_DIR}) + set(LCOV_BASELINE_CMD + ${COV_FE_PATH} --capture --branch-coverage --directory ${PROJECT_BINARY_DIR} --output-file ${LCOV_NAME_PREFIX}.base + --base-directory ${NAUTILUS_LCOV_BASEDIR} --initial --gcov-tool ${COV_PATH} ${NAUTILUS_LCOV_ADDITIONAL_ARGS}) + add_custom_target(${COV_NAME}_cleanup + COMMAND ${COV_CREATE_REUSLT_DIR_CMD} + COMMAND ${LCOV_CLEANUP_CMD} + COMMAND ${LCOV_BASELINE_CMD} + WORKING_DIRECTORY ${TGT_WORKING_DIR} + BYPRODUCTS ${LCOV_NAME_PREFIX}.base + VERBATIM + COMMENT "Running ${NAUTILUS_USE_COVERAGE} to cleanup first." + ) + add_test( + NAME ${TARGET_NAME}_coverage_setup + CONFIGURATIONS Debug + COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR} --target ${COV_NAME}_cleanup + WORKING_DIRECTORY ${TGT_WORKING_DIR} + ) + set_tests_properties(${TARGET_NAME}_coverage_setup PROPERTIES FIXTURES_SETUP ${TARGET_NAME}) + set_tests_properties(${TARGET_NAME} PROPERTIES DEPENDS ${TARGET_NAME}_coverage_setup) + + set(LCOV_CAPTURE_CMD + ${COV_FE_PATH} --capture --directory ${PROJECT_BINARY_DIR} --output-file ${LCOV_NAME_PREFIX}.info + --base-directory ${NAUTILUS_LCOV_BASEDIR} --gcov-tool ${COV_PATH} --branch-coverage ${NAUTILUS_LCOV_ADDITIONAL_ARGS}) + set(LCOV_MERGE_CMD + ${COV_FE_PATH} --add-tracefile ${LCOV_NAME_PREFIX}.info --add-tracefile ${LCOV_NAME_PREFIX}.base + ${NAUTILUS_LCOV_ADDITIONAL_ARGS} --branch-coverage --output-file ${LCOV_NAME_PREFIX}.lcov) + set(LCOV_EXCLUDE_CMD ${COV_FE_PATH} --branch-coverage + ${LCOV_EXCLUDE_ARGS} --remove ${LCOV_NAME_PREFIX}.lcov "/usr/*" --output-file ${LCOV_NAME_PREFIX}.lcov) + find_program(GENHTML_PATH genhtml) + if(NOT GENHTML_PATH) + message(FATAL_ERROR "genhtml not found!") + endif() + set(LCOV_GENHTML_CMD ${GENHTML_PATH} --branch-coverage --demangle-cpp -o ${COV_RESULT_DIR} ${LCOV_NAME_PREFIX}.lcov) + + add_custom_target(${COV_NAME} + COMMAND ${LCOV_CAPTURE_CMD} + COMMAND ${LCOV_MERGE_CMD} + COMMAND ${LCOV_EXCLUDE_CMD} + COMMAND ${LCOV_GENHTML_CMD} + BYPRODUCTS + ${LCOV_NAME_PREFIX}.lcov + ${LCOV_NAME_PREFIX}.info + ${COV_RESULT_DIR}/index.html + WORKING_DIRECTORY ${TGT_WORKING_DIR} + DEPENDS ${TARGET_NAME} + VERBATIM # Protect arguments to commands + COMMENT "Running ${NAUTILUS_USE_COVERAGE} to code coverage report." + ) +endmacro() + +macro(__nautilus_coverage_lcov_with_llvmcov) + set_tests_properties(${TARGET_NAME} PROPERTIES ENVIRONMENT "LLVM_PROFILE_FILE=${TARGET_NAME}.profraw") + + find_program(LLVM_PROFDATA_PATH llvm-profdata) + if(NOT LLVM_PROFDATA_PATH) + message(FATAL_ERROR "llvm-profdata not found!") + endif() + + set(LCOV_PROCESS_CMD ${LLVM_PROFDATA_PATH} merge -sparse ${TGT_WORKING_DIR}/${TARGET_NAME}.profraw -o ${LCOV_NAME_PREFIX}.profdata) + set(LCOV_EXPORT_CMD ${LLVM_COV_PATH} export $ -instr-profile=${LCOV_NAME_PREFIX}.profdata -format=lcov > ${LCOV_NAME_PREFIX}.lcov) + set(LCOV_EXCLUDE_CMD ${COV_FE_PATH} ${LCOV_EXCLUDE_ARGS} --branch-coverage --output-file ${LCOV_NAME_PREFIX}.lcov) + find_program(GENHTML_PATH genhtml) + if(NOT GENHTML_PATH) + message(FATAL_ERROR "genhtml not found!") + endif() + set(LCOV_GENHTML_CMD ${GENHTML_PATH} --demangle-cpp --branch-coverage -o ${COV_RESULT_DIR} ${LCOV_NAME_PREFIX}.lcov) + + add_custom_target(${COV_NAME} + COMMAND ${COV_CREATE_REUSLT_DIR_CMD} + COMMAND ${LCOV_PROCESS_CMD} + COMMAND ${LCOV_EXPORT_CMD} + COMMAND ${LCOV_EXCLUDE_CMD} + COMMAND ${LCOV_GENHTML_CMD} + BYPRODUCTS + ${LCOV_NAME_PREFIX}.lcov + ${LCOV_NAME_PREFIX}.profdata + ${TGT_WORKING_DIR}/${TARGET_NAME}.profraw + ${COV_RESULT_DIR}/index.html + WORKING_DIRECTORY ${TGT_WORKING_DIR} + DEPENDS ${TARGET_NAME} + VERBATIM # Protect arguments to commands + COMMENT "Running ${NAUTILUS_USE_COVERAGE} to code coverage report." + ) +endmacro() + +function(nautilus_target_coverage_lcov TARGET_NAME) + if(NOT NAUTILUS_USE_COVERAGE OR NOT NAUTILUS_USE_COVERAGE STREQUAL "lcov") + return() + endif() + + __nautilus_coverage_get_gcov() + __nautilus_coverage_parse_args(NAUTILUS_LCOV ${ARGN}) + __nautilus_coverage_get_excludes(${NAUTILUS_LCOV_BASEDIR} "${NAUTILUS_LCOV_EXCLUDES}") + __nautilus_coverage_name(${TARGET_NAME} ${NAUTILUS_USE_COVERAGE}) + get_property(TGT_WORKING_DIR TEST ${TARGET_NAME} PROPERTY WORKING_DIRECTORY) + if(NOT TGT_WORKING_DIR) + set(TGT_WORKING_DIR ${CMAKE_CURRENT_BINARY_DIR}) + endif() + set(LCOV_NAME_PREFIX "${TGT_WORKING_DIR}/${COV_NAME}") + set(LCOV_EXCLUDE_ARGS) + foreach(EXCLUDE ${COV_LIST_EXCLUDES}) + list(APPEND LCOV_EXCLUDE_ARGS "--remove") + list(APPEND LCOV_EXCLUDE_ARGS "${LCOV_NAME_PREFIX}.lcov") + list(APPEND LCOV_EXCLUDE_ARGS "${EXCLUDE}") + endforeach() + + if(NAUTILUS_COMPILER_IS_GCC) + __nautilus_coverage_lcov_with_gcov() + elseif(NAUTILUS_COMPILER_IS_CLANG) + if(NOT LLVM_COV_PATH) + message(FATAL_ERROR "llvm-cov not found!") + endif() + __nautilus_coverage_lcov_with_llvmcov() + endif() + add_test( + NAME ${TARGET_NAME}_coverage + CONFIGURATIONS Debug + COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR} --target ${COV_NAME} + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + ) + set_tests_properties(${TARGET_NAME}_coverage PROPERTIES FIXTURES_CLEANUP ${TARGET_NAME}) +endfunction() + +function(nautilus_target_coverage TARGET_NAME) + if(NOT NAUTILUS_USE_COVERAGE) + return() + endif() + cmake_language(CALL nautilus_target_coverage_${NAUTILUS_USE_COVERAGE} ${TARGET_NAME} ${ARGN}) +endfunction() diff --git a/cmake/tool/nautilus_doxygen.cmake b/cmake/tool/nautilus_doxygen.cmake new file mode 100644 index 0000000..c7c65da --- /dev/null +++ b/cmake/tool/nautilus_doxygen.cmake @@ -0,0 +1 @@ +include_guard() diff --git a/cmake/tool/nautilus_launcher.cmake b/cmake/tool/nautilus_launcher.cmake new file mode 100644 index 0000000..53fbbbf --- /dev/null +++ b/cmake/tool/nautilus_launcher.cmake @@ -0,0 +1,20 @@ +include_guard() + +if(NOT NAUTILUS_COMPILER_LAUNCHER) + return() +endif() + +function(nautilus_enable_launcher TARGET_NAME) + if(NOT NAUTILUS_COMPILER_LAUNCHER STREQUAL "ccache") + return() + endif() + + find_program(CCACHE_EXE ccache) + if(NOT CCACHE_EXE) + message(${NAUTILUS_MESSAGE_WARNING} "ccache requested but executable not found.") + return() + endif() + + set_target_properties(${TARGET_NAME} PROPERTIES C_COMPILER_LAUNCHER "${CCACHE_EXE}") + set_target_properties(${TARGET_NAME} PROPERTIES CXX_COMPILER_LAUNCHER "${CCACHE_EXE}") +endfunction() diff --git a/cmake/tool/nautilus_lint.cmake b/cmake/tool/nautilus_lint.cmake new file mode 100644 index 0000000..bcff74b --- /dev/null +++ b/cmake/tool/nautilus_lint.cmake @@ -0,0 +1,56 @@ +include_guard() + +function(nautilus_enable_clang_tidy TARGET_NAME) + if(NOT NAUTILUS_ENABLE_LINT) + return() + endif() + if(NOT NAUTILUS_COMPILER_IS_CLANG) + message(${NAUTILUS_MESSAGE_WARNING} "clang-tidy requested but compiler is not clang.") + return() + endif() + + find_program(CLANG_TIDY_EXE clang-tidy) + if(NOT CLANG_TIDY_EXE) + message(${NAUTILUS_MESSAGE_WARNING} "clang-tidy requested but executable not found.") + return() + endif() + + set(options) + set(oneValueArgs) + set(multiValueArgs OPTIONS) + cmake_parse_arguments(NAUTILUS_CLANG_TIDY "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + set(lint_command ${CLANG_TIDY_EXE} --use-color) + if(NAUTILUS_CLANG_TIDY_OPTIONS) + list(APPEND lint_command "${NAUTILUS_CLANG_TIDY_OPTIONS}") + endif() + if(NAUTILUS_WARNINGS_AS_ERRORS) + list(APPEND lint_command -warnings-as-errors='*') + endif() + set_target_properties(${TARGET_NAME} PROPERTIES C_CLANG_TIDY "${lint_command}") + set_target_properties(${TARGET_NAME} PROPERTIES CXX_CLANG_TIDY "${lint_command}") +endfunction() + +function(nautilus_enable_iwyu TARGET_NAME) + if(NOT NAUTILUS_ENABLE_LINT) + return() + endif() + + find_program(IWYU_EXE include-what-you-use) + if(NOT IWYU_EXE) + message(${NAUTILUS_MESSAGE_WARNING} "include-what-you-use requested but executable not found.") + return() + endif() + + set(options) + set(oneValueArgs) + set(multiValueArgs OPTIONS) + cmake_parse_arguments(NAUTILUS_IWYU "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + set(lint_command ${IWYU_EXE}) + if(NAUTILUS_CLANG_TIDY_OPTIONS) + list(APPEND lint_command "${NAUTILUS_IWYU_OPTIONS}") + endif() + set_target_properties(${TARGET_NAME} PROPERTIES C_INCLUDE_WHAT_YOU_USE "${lint_command}") + set_target_properties(${TARGET_NAME} PROPERTIES CXX_INCLUDE_WHAT_YOU_USE "${lint_command}") +endfunction() diff --git a/cmake/tool/nautilus_sanitizer.cmake b/cmake/tool/nautilus_sanitizer.cmake new file mode 100644 index 0000000..d4929a2 --- /dev/null +++ b/cmake/tool/nautilus_sanitizer.cmake @@ -0,0 +1,185 @@ +include_guard() + +if(NAUTILUS_USE_SANITIZER STREQUAL "") + function(nautilus_target_sanitize TARGET_NAME) + endfunction() + function(nautilus_target_sanitize_ldpreload TARGET_NAME) + endfunction() + return() +endif() + +function(nautilus_target_sanitize TARGET_NAME) + foreach(sanitizer IN LISTS NAUTILUS_USE_SANITIZER) + if(NAUTILUS_COMPILER_IS_MSVC) + if(sanitizer STREQUAL "Address") + list(APPEND NAUTILUS_SAN_KIND address) + else() + message(${NAUTILUS_MESSAGE_WARNING} + "This sanitizer not yet supported in the C / C++ environment: ${sanitizer}") + endif() + else(NAUTILUS_COMPILER_IS_MSVC) + if(sanitizer STREQUAL "Address") + list(APPEND NAUTILUS_SAN_KIND address) + list(APPEND NAUTILUS_SAN_COMPILE_OPTIONS + -fsanitize-address-use-after-scope + ) + if(NAUTILUS_COMPILER_IS_GCC) + list(APPEND NAUTILUS_SAN_LINK_OPTIONS -lasan) + endif() + elseif(sanitizer MATCHES "Memory(WithOrigins)?") + # Learn more at https://github.com/google/sanitizers/wiki/MemorySanitizer + if("Address" IN_LIST NAUTILUS_USE_SANITIZER OR + "Leak" IN_LIST NAUTILUS_USE_SANITIZER OR + "Thread" IN_LIST NAUTILUS_USE_SANITIZER) + message(${NAUTILUS_MESSAGE_WARNING} + "Memory sanitizer does not work with Address, Leak and Thread sanitizer enabled") + elseif(NAUTILUS_COMPILER_IS_CLANG) + list(APPEND NAUTILUS_SAN_KIND memory) + if(sanitizer STREQUAL "MemoryWithOrigins") + list(APPEND NAUTILUS_SAN_COMPILE_OPTIONS + -fsanitize-memory-track-origins + ) + list(APPEND NAUTILUS_SAN_LINK_OPTIONS + -fsanitize-memory-track-origins + ) + endif() + endif() + elseif(sanitizer STREQUAL "Undefined") + # Learn more at https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html + list(APPEND NAUTILUS_SAN_KIND undefined) + if(NAUTILUS_COMPILER_IS_GCC) + list(APPEND NAUTILUS_SAN_LINK_OPTIONS -lubsan) + endif() + elseif(sanitizer STREQUAL "Thread") + # Learn more at https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual + if("Address" IN_LIST NAUTILUS_USE_SANITIZER OR + "Leak" IN_LIST NAUTILUS_USE_SANITIZER OR + "Memory" IN_LIST NAUTILUS_USE_SANITIZER OR + "MemoryWithOrigins" IN_LIST NAUTILUS_USE_SANITIZER) + message(${NAUTILUS_CMAKE_MESSAGE_WARNING} + "Thread sanitizer does not work with Address, Leak and Memory sanitizer enabled") + else() + list(APPEND NAUTILUS_SAN_KIND thread) + list(APPEND NAUTILUS_SAN_LINK_OPTIONS -pthread) + if(NAUTILUS_COMPILER_IS_GCC) + list(APPEND NAUTILUS_SAN_LINK_OPTIONS -ltsan) + endif() + endif() + elseif(sanitizer STREQUAL "Leak") + # Learn more at https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer + list(APPEND NAUTILUS_SAN_KIND leak) + if(NAUTILUS_COMPILER_IS_GCC) + list(APPEND NAUTILUS_SAN_LINK_OPTIONS -llsan) + endif() + else() + message(${NAUTILUS_MESSAGE_WARNING} + "This sanitizer not yet supported in the C / C++ environment: ${sanitizer}") + endif() + endif() + endforeach() + + if(NAUTILUS_COMPILER_IS_MSVC AND NAUTILUS_SAN_KIND) + list(APPEND NAUTILUS_SAN_COMPILE_OPTIONS + /fsanitize=${NAUTILUS_SAN_KIND} + /Oy- + /Z7 # Always ask the linker to produce symbols with asan. + ) + elseif(NAUTILUS_SAN_KIND) + list(JOIN NAUTILUS_SAN_KIND "," NAUTILUS_SAN_KIND_STR) + list(APPEND NAUTILUS_SAN_COMPILE_OPTIONS + -fsanitize=${NAUTILUS_SAN_KIND_STR} + -fno-omit-frame-pointer + -O1 + ) + list(APPEND NAUTILUS_SAN_LINK_OPTIONS + -fsanitize=${NAUTILUS_SAN_KIND_STR} + ) + if(NAUTILUS_COMPILER_IS_CLANG) + list(APPEND NAUTILUS_SAN_LINK_OPTIONS -shared-libsan) + endif() + get_property(NAUTILUS_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) + if(CXX IN_LIST NAUTILUS_LANGUAGES) + list(APPEND NAUTILUS_SAN_COMPILE_OPTIONS + -fno-sanitize=vptr + ) + if(NAUTILUS_COMPILER_IS_CLANG) + list(APPEND NAUTILUS_SAN_LINK_OPTIONS + -fsanitize-link-c++-runtime + ) + endif() + endif() + endif() + + get_target_property(TARGET_LINK_OPTIONS_VAR ${TARGET_NAME} LINK_OPTIONS) + if("${TARGET_LINK_OPTIONS_VAR}" STREQUAL "TARGET_LINK_OPTIONS_VAR-NOTFOUND") + set(TARGET_LINK_OPTIONS_VAR ${NAUTILUS_SAN_LINK_OPTIONS}) + else() + list(APPEND TARGET_LINK_OPTIONS_VAR ${NAUTILUS_SAN_LINK_OPTIONS}) + endif() + set_target_properties(${TARGET_NAME} PROPERTIES LINK_OPTIONS "${TARGET_LINK_OPTIONS_VAR}") + get_target_property(TARGET_COMPILE_OPTIONS_VAR ${TARGET_NAME} COMPILE_OPTIONS) + if("${TARGET_COMPILE_OPTIONS_VAR}" STREQUAL "TARGET_COMPILE_OPTIONS_VAR-NOTFOUND") + set(TARGET_COMPILE_OPTIONS_VAR ${NAUTILUS_SAN_COMPILE_OPTIONS}) + else() + list(APPEND TARGET_COMPILE_OPTIONS_VAR ${NAUTILUS_SAN_COMPILE_OPTIONS}) + endif() + set_target_properties(${TARGET_NAME} PROPERTIES COMPILE_OPTIONS "${TARGET_COMPILE_OPTIONS_VAR}") +endfunction() + +function(nautilus_target_sanitize_ldpreload TARGET_NAME) + macro(SEARCH_LIBSAN_PATH LIBNAME POSTFIX) + if(NAUTILUS_COMPILER_IS_GCC) + execute_process(COMMAND gcc -print-file-name=lib${LIBNAME}.so + OUTPUT_VARIABLE LIBSAN_DYNAMIC_PATH + OUTPUT_STRIP_TRAILING_WHITESPACE) + else() # clang + set(LIBNAME_POSTFIX ${POSTFIX}) + if(NOT NAUTILUS_ARCH_IS_64BIT) + message(FATAL_ERROR "32bit doesn't have clang_rt library") + endif() + if(NAUTILUS_ARCH_IS_ARM) + pstring(APPEND LIBNAME_POSTFIX "-aarch64") + elseif(NAUTILUS_ARCH_IS_POWERPC) + string(APPEND LIBNAME_POSTFIX "-powerpc64le") + elseif(NAUTILUS_ARCH_IS_RISCV) + message(FATAL_ERROR "Unknow arch: RISCV") + elseif(NAUTILUS_ARCH_IS_X86) + string(APPEND LIBNAME_POSTFIX "-x86_64") + endif() + execute_process(COMMAND clang -print-file-name=libclang_rt.${LIBNAME}${LIBNAME_POSTFIX}.so + OUTPUT_VARIABLE LIBSAN_DYNAMIC_PATH + OUTPUT_STRIP_TRAILING_WHITESPACE) + endif() + if(EXISTS ${LIBSAN_DYNAMIC_PATH}) + set(LIBSAN_PATH "${LIBSAN_DYNAMIC_PATH}") + endif() + endmacro() + set(LDPRELOAD_VARLIST) + foreach(sanitizer IN LISTS NAUTILUS_USE_SANITIZER) + set(LIBSAN_PATH) + if(sanitizer STREQUAL "Address") + SEARCH_LIBSAN_PATH(asan "") + elseif(sanitizer MATCHES "Memory(WithOrigins)?") + SEARCH_LIBSAN_PATH(msan "") + elseif(sanitizer STREQUAL "Undefined") + SEARCH_LIBSAN_PATH(ubsan "_standalone") + elseif(sanitizer STREQUAL "Thread") + SEARCH_LIBSAN_PATH(tsan "") + elseif(sanitizer STREQUAL "Leak") + SEARCH_LIBSAN_PATH(lsan "") + endif() + if(LIBSAN_PATH) + list(APPEND LDPRELOAD_VARLIST ${LIBSAN_PATH}) + endif() + endforeach() + list(JOIN LDPRELOAD_VARLIST ":" LDPRELOAD_VAR) + if(CMAKE_VERSION VERSION_LESS 3.22) + set_property(TEST ${TARGET_NAME} PROPERTY + ENVIRONMENT "LD_PRELOAD=$ENV{LD_PRELOAD}:${LDPRELOAD_VAR}" + ) + else() + set_property(TEST ${TARGET_NAME} PROPERTY + ENVIRONMENT_MODIFICATION "LD_PRELOAD=path_list_prepend:${LDPRELOAD_VAR}" + ) + endif() +endfunction() diff --git a/inc/.gitkeep b/inc/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..e69de29