first commit
This commit is contained in:
commit
3413c94f8d
194
.github/workflows/ci.yml
vendored
Normal file
194
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,194 @@
|
||||
name: Continuous Integration
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-python@v5
|
||||
with: { python-version: "3.8" }
|
||||
|
||||
- name: Install codespell
|
||||
run: pip3 install codespell
|
||||
|
||||
- name: Lint
|
||||
run: cmake -D FORMAT_COMMAND=clang-format-14 -P cmake/lint.cmake
|
||||
|
||||
- name: Spell check
|
||||
if: always()
|
||||
run: cmake -P cmake/spell.cmake
|
||||
|
||||
coverage:
|
||||
needs: [lint]
|
||||
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
# To enable coverage, delete the last line from the conditional below and
|
||||
# edit the "<name>" placeholder to your GitHub name.
|
||||
# If you do not wish to use codecov, then simply delete this job from the
|
||||
# workflow.
|
||||
if: github.repository_owner == '<name>'
|
||||
&& false
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install LCov
|
||||
run: sudo apt-get update -q
|
||||
&& sudo apt-get install lcov -q -y
|
||||
|
||||
- name: Configure
|
||||
run: cmake --preset=ci-coverage
|
||||
|
||||
- name: Build
|
||||
run: cmake --build build/coverage -j 2
|
||||
|
||||
- name: Test
|
||||
working-directory: build/coverage
|
||||
run: ctest --output-on-failure --no-tests=error -j 2
|
||||
|
||||
- name: Process coverage info
|
||||
run: cmake --build build/coverage -t coverage
|
||||
|
||||
- name: Submit to codecov.io
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
file: build/coverage/coverage.info
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
sanitize:
|
||||
needs: [lint]
|
||||
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
env: { CXX: clang++-14 }
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Configure
|
||||
run: cmake --preset=ci-sanitize
|
||||
|
||||
- name: Build
|
||||
run: cmake --build build/sanitize -j 2
|
||||
|
||||
- name: Test
|
||||
working-directory: build/sanitize
|
||||
env:
|
||||
ASAN_OPTIONS: "strict_string_checks=1:\
|
||||
detect_stack_use_after_return=1:\
|
||||
check_initialization_order=1:\
|
||||
strict_init_order=1:\
|
||||
detect_leaks=1:\
|
||||
halt_on_error=1"
|
||||
UBSAN_OPTIONS: "print_stacktrace=1:\
|
||||
halt_on_error=1"
|
||||
run: ctest --output-on-failure --no-tests=error -j 2
|
||||
|
||||
test:
|
||||
needs: [lint]
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
os: [macos-12, ubuntu-22.04, windows-2022]
|
||||
|
||||
type: [shared, static]
|
||||
|
||||
include:
|
||||
- { type: shared, shared: YES }
|
||||
- { type: static, shared: NO }
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install static analyzers
|
||||
if: matrix.os == 'ubuntu-22.04'
|
||||
run: >-
|
||||
sudo apt-get install clang-tidy-14 cppcheck -y -q
|
||||
|
||||
sudo update-alternatives --install
|
||||
/usr/bin/clang-tidy clang-tidy
|
||||
/usr/bin/clang-tidy-14 140
|
||||
|
||||
- name: Setup MultiToolTask
|
||||
if: matrix.os == 'windows-2022'
|
||||
run: |
|
||||
Add-Content "$env:GITHUB_ENV" 'UseMultiToolTask=true'
|
||||
Add-Content "$env:GITHUB_ENV" 'EnforceProcessCountAcrossBuilds=true'
|
||||
|
||||
- name: Configure
|
||||
shell: pwsh
|
||||
run: cmake "--preset=ci-$("${{ matrix.os }}".split("-")[0])"
|
||||
-D BUILD_SHARED_LIBS=${{ matrix.shared }}
|
||||
|
||||
- name: Setup PATH
|
||||
if: matrix.os == 'windows-2022' && matrix.type == 'shared'
|
||||
run: Add-Content "$env:GITHUB_PATH" "$(Get-Location)\build\Release"
|
||||
|
||||
- name: Build
|
||||
run: cmake --build build --config Release -j 2
|
||||
|
||||
- name: Install
|
||||
run: cmake --install build --config Release --prefix prefix
|
||||
|
||||
- name: Test
|
||||
working-directory: build
|
||||
run: ctest --output-on-failure --no-tests=error -C Release -j 2
|
||||
|
||||
docs:
|
||||
# Deploy docs only when builds succeed
|
||||
needs: [sanitize, test]
|
||||
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
# To enable, first you have to create an orphaned gh-pages branch:
|
||||
#
|
||||
# git switch --orphan gh-pages
|
||||
# git commit --allow-empty -m "Initial commit"
|
||||
# git push -u origin gh-pages
|
||||
#
|
||||
# Edit the <name> placeholder below to your GitHub name, so this action
|
||||
# runs only in your repository and no one else's fork. After these, delete
|
||||
# this comment and the last line in the conditional below.
|
||||
# If you do not wish to use GitHub Pages for deploying documentation, then
|
||||
# simply delete this job similarly to the coverage one.
|
||||
if: github.ref == 'refs/heads/master'
|
||||
&& github.event_name == 'push'
|
||||
&& github.repository_owner == '<name>'
|
||||
&& false
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-python@v5
|
||||
with: { python-version: "3.8" }
|
||||
|
||||
- name: Install m.css dependencies
|
||||
run: pip3 install jinja2 Pygments
|
||||
|
||||
- name: Install Doxygen
|
||||
run: sudo apt-get update -q
|
||||
&& sudo apt-get install doxygen -q -y
|
||||
|
||||
- name: Build docs
|
||||
run: cmake "-DPROJECT_SOURCE_DIR=$PWD" "-DPROJECT_BINARY_DIR=$PWD/build"
|
||||
-P cmake/docs-ci.cmake
|
||||
|
||||
- name: Deploy docs
|
||||
uses: peaceiris/actions-gh-pages@v4
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: build/docs/html
|
13
.gitignore
vendored
Normal file
13
.gitignore
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
**/.DS_Store
|
||||
.idea/
|
||||
.vs/
|
||||
.vscode/
|
||||
build/
|
||||
cmake-build-*/
|
||||
prefix/
|
||||
.clangd
|
||||
CMakeLists.txt.user
|
||||
CMakeUserPresets.json
|
||||
compile_commands.json
|
||||
env.bat
|
||||
env.ps1
|
82
CMakeLists.txt
Normal file
82
CMakeLists.txt
Normal file
@ -0,0 +1,82 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
include(cmake/prelude.cmake)
|
||||
|
||||
project(
|
||||
nix-gcc-multi-issue
|
||||
VERSION 0.1.0
|
||||
DESCRIPTION "Short description"
|
||||
HOMEPAGE_URL "https://example.com/"
|
||||
LANGUAGES CXX
|
||||
)
|
||||
|
||||
include(cmake/project-is-top-level.cmake)
|
||||
include(cmake/variables.cmake)
|
||||
|
||||
# ---- Declare library ----
|
||||
# build as 32-bit library
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32")
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
add_library(
|
||||
nix-gcc-multi-issue_nix-gcc-multi-issue
|
||||
SHARED
|
||||
source/nix-gcc-multi-issue.cpp
|
||||
)
|
||||
add_library(nix-gcc-multi-issue::nix-gcc-multi-issue ALIAS nix-gcc-multi-issue_nix-gcc-multi-issue)
|
||||
|
||||
include(GenerateExportHeader)
|
||||
generate_export_header(
|
||||
nix-gcc-multi-issue_nix-gcc-multi-issue
|
||||
BASE_NAME nix-gcc-multi-issue
|
||||
EXPORT_FILE_NAME export/nix-gcc-multi-issue/nix-gcc-multi-issue_export.hpp
|
||||
CUSTOM_CONTENT_FROM_VARIABLE pragma_suppress_c4251
|
||||
)
|
||||
|
||||
if(NOT BUILD_SHARED_LIBS)
|
||||
target_compile_definitions(nix-gcc-multi-issue_nix-gcc-multi-issue PUBLIC NIX_GCC_MULTI_ISSUE_STATIC_DEFINE)
|
||||
endif()
|
||||
|
||||
set_target_properties(
|
||||
nix-gcc-multi-issue_nix-gcc-multi-issue PROPERTIES
|
||||
CXX_VISIBILITY_PRESET hidden
|
||||
VISIBILITY_INLINES_HIDDEN YES
|
||||
VERSION "${PROJECT_VERSION}"
|
||||
SOVERSION "${PROJECT_VERSION_MAJOR}"
|
||||
EXPORT_NAME nix-gcc-multi-issue
|
||||
OUTPUT_NAME nix-gcc-multi-issue
|
||||
)
|
||||
|
||||
target_include_directories(
|
||||
nix-gcc-multi-issue_nix-gcc-multi-issue ${warning_guard}
|
||||
PUBLIC
|
||||
"\$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>"
|
||||
)
|
||||
|
||||
target_include_directories(
|
||||
nix-gcc-multi-issue_nix-gcc-multi-issue SYSTEM
|
||||
PUBLIC
|
||||
"\$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/export>"
|
||||
)
|
||||
|
||||
target_compile_features(nix-gcc-multi-issue_nix-gcc-multi-issue PUBLIC cxx_std_17)
|
||||
|
||||
# ---- Install rules ----
|
||||
|
||||
if(NOT CMAKE_SKIP_INSTALL_RULES)
|
||||
include(cmake/install-rules.cmake)
|
||||
endif()
|
||||
|
||||
# ---- Developer mode ----
|
||||
|
||||
if(NOT nix-gcc-multi-issue_DEVELOPER_MODE)
|
||||
return()
|
||||
elseif(NOT PROJECT_IS_TOP_LEVEL)
|
||||
message(
|
||||
AUTHOR_WARNING
|
||||
"Developer mode is intended for developers of nix-gcc-multi-issue"
|
||||
)
|
||||
endif()
|
||||
|
||||
include(cmake/dev-mode.cmake)
|
19
README.md
Normal file
19
README.md
Normal file
@ -0,0 +1,19 @@
|
||||
# nix-gcc-multi-issue
|
||||
|
||||
This is the nix-gcc-multi-issue project.
|
||||
|
||||
# Building and installing
|
||||
|
||||
See the [BUILDING](BUILDING.md) document.
|
||||
|
||||
# Contributing
|
||||
|
||||
See the [CONTRIBUTING](CONTRIBUTING.md) document.
|
||||
|
||||
# Licensing
|
||||
|
||||
<!--
|
||||
Please go to https://choosealicense.com/licenses/ and choose a license that
|
||||
fits your needs. The recommended license for a project of this type is the
|
||||
Boost Software License 1.0.
|
||||
-->
|
15
build.sh
Executable file
15
build.sh
Executable file
@ -0,0 +1,15 @@
|
||||
#!/bin/sh
|
||||
[ -z $CONFIG ] && config=Release || config="$CONFIG"
|
||||
|
||||
if [ "$SKIP_CMAKE" != "true" ]; then
|
||||
cmake \
|
||||
-S . \
|
||||
-B build \
|
||||
-G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=$config
|
||||
fi
|
||||
|
||||
cmake \
|
||||
--build build \
|
||||
--config $config \
|
||||
--parallel $(nproc)
|
33
cmake/coverage.cmake
Normal file
33
cmake/coverage.cmake
Normal file
@ -0,0 +1,33 @@
|
||||
# ---- Variables ----
|
||||
|
||||
# We use variables separate from what CTest uses, because those have
|
||||
# customization issues
|
||||
set(
|
||||
COVERAGE_TRACE_COMMAND
|
||||
lcov -c -q
|
||||
-o "${PROJECT_BINARY_DIR}/coverage.info"
|
||||
-d "${PROJECT_BINARY_DIR}"
|
||||
--include "${PROJECT_SOURCE_DIR}/*"
|
||||
CACHE STRING
|
||||
"; separated command to generate a trace for the 'coverage' target"
|
||||
)
|
||||
|
||||
set(
|
||||
COVERAGE_HTML_COMMAND
|
||||
genhtml --legend -f -q
|
||||
"${PROJECT_BINARY_DIR}/coverage.info"
|
||||
-p "${PROJECT_SOURCE_DIR}"
|
||||
-o "${PROJECT_BINARY_DIR}/coverage_html"
|
||||
CACHE STRING
|
||||
"; separated command to generate an HTML report for the 'coverage' target"
|
||||
)
|
||||
|
||||
# ---- Coverage target ----
|
||||
|
||||
add_custom_target(
|
||||
coverage
|
||||
COMMAND ${COVERAGE_TRACE_COMMAND}
|
||||
COMMAND ${COVERAGE_HTML_COMMAND}
|
||||
COMMENT "Generating coverage report"
|
||||
VERBATIM
|
||||
)
|
21
cmake/dev-mode.cmake
Normal file
21
cmake/dev-mode.cmake
Normal file
@ -0,0 +1,21 @@
|
||||
include(cmake/folders.cmake)
|
||||
|
||||
include(CTest)
|
||||
if(BUILD_TESTING)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
|
||||
option(BUILD_MCSS_DOCS "Build documentation using Doxygen and m.css" OFF)
|
||||
if(BUILD_MCSS_DOCS)
|
||||
include(cmake/docs.cmake)
|
||||
endif()
|
||||
|
||||
option(ENABLE_COVERAGE "Enable coverage support separate from CTest's" OFF)
|
||||
if(ENABLE_COVERAGE)
|
||||
include(cmake/coverage.cmake)
|
||||
endif()
|
||||
|
||||
include(cmake/lint-targets.cmake)
|
||||
include(cmake/spell-targets.cmake)
|
||||
|
||||
add_folders(Project)
|
112
cmake/docs-ci.cmake
Normal file
112
cmake/docs-ci.cmake
Normal file
@ -0,0 +1,112 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
foreach(var IN ITEMS PROJECT_BINARY_DIR PROJECT_SOURCE_DIR)
|
||||
if(NOT DEFINED "${var}")
|
||||
message(FATAL_ERROR "${var} must be defined")
|
||||
endif()
|
||||
endforeach()
|
||||
set(bin "${PROJECT_BINARY_DIR}")
|
||||
set(src "${PROJECT_SOURCE_DIR}")
|
||||
|
||||
# ---- Dependencies ----
|
||||
|
||||
set(mcss_SOURCE_DIR "${bin}/docs/.ci")
|
||||
if(NOT IS_DIRECTORY "${mcss_SOURCE_DIR}")
|
||||
file(MAKE_DIRECTORY "${mcss_SOURCE_DIR}")
|
||||
file(
|
||||
DOWNLOAD
|
||||
https://github.com/friendlyanon/m.css/releases/download/release-1/mcss.zip
|
||||
"${mcss_SOURCE_DIR}/mcss.zip"
|
||||
STATUS status
|
||||
EXPECTED_MD5 00cd2757ebafb9bcba7f5d399b3bec7f
|
||||
)
|
||||
if(NOT status MATCHES "^0;")
|
||||
message(FATAL_ERROR "Download failed with ${status}")
|
||||
endif()
|
||||
execute_process(
|
||||
COMMAND "${CMAKE_COMMAND}" -E tar xf mcss.zip
|
||||
WORKING_DIRECTORY "${mcss_SOURCE_DIR}"
|
||||
RESULT_VARIABLE result
|
||||
)
|
||||
if(NOT result EQUAL "0")
|
||||
message(FATAL_ERROR "Extraction failed with ${result}")
|
||||
endif()
|
||||
file(REMOVE "${mcss_SOURCE_DIR}/mcss.zip")
|
||||
endif()
|
||||
|
||||
find_program(Python3_EXECUTABLE NAMES python3 python)
|
||||
if(NOT Python3_EXECUTABLE)
|
||||
message(FATAL_ERROR "Python executable was not found")
|
||||
endif()
|
||||
|
||||
# ---- Process project() call in CMakeLists.txt ----
|
||||
|
||||
file(READ "${src}/CMakeLists.txt" content)
|
||||
|
||||
string(FIND "${content}" "project(" index)
|
||||
if(index EQUAL "-1")
|
||||
message(FATAL_ERROR "Could not find \"project(\"")
|
||||
endif()
|
||||
string(SUBSTRING "${content}" "${index}" -1 content)
|
||||
|
||||
string(FIND "${content}" "\n)\n" index)
|
||||
if(index EQUAL "-1")
|
||||
message(FATAL_ERROR "Could not find \"\\n)\\n\"")
|
||||
endif()
|
||||
string(SUBSTRING "${content}" 0 "${index}" content)
|
||||
|
||||
file(WRITE "${bin}/docs-ci.project.cmake" "docs_${content}\n)\n")
|
||||
|
||||
macro(list_pop_front list out)
|
||||
list(GET "${list}" 0 "${out}")
|
||||
list(REMOVE_AT "${list}" 0)
|
||||
endmacro()
|
||||
|
||||
function(docs_project name)
|
||||
cmake_parse_arguments(PARSE_ARGV 1 "" "" "VERSION;DESCRIPTION;HOMEPAGE_URL" LANGUAGES)
|
||||
set(PROJECT_NAME "${name}" PARENT_SCOPE)
|
||||
if(DEFINED _VERSION)
|
||||
set(PROJECT_VERSION "${_VERSION}" PARENT_SCOPE)
|
||||
string(REGEX MATCH "^[0-9]+(\\.[0-9]+)*" versions "${_VERSION}")
|
||||
string(REPLACE . ";" versions "${versions}")
|
||||
set(suffixes MAJOR MINOR PATCH TWEAK)
|
||||
while(NOT versions STREQUAL "" AND NOT suffixes STREQUAL "")
|
||||
list_pop_front(versions version)
|
||||
list_pop_front(suffixes suffix)
|
||||
set("PROJECT_VERSION_${suffix}" "${version}" PARENT_SCOPE)
|
||||
endwhile()
|
||||
endif()
|
||||
if(DEFINED _DESCRIPTION)
|
||||
set(PROJECT_DESCRIPTION "${_DESCRIPTION}" PARENT_SCOPE)
|
||||
endif()
|
||||
if(DEFINED _HOMEPAGE_URL)
|
||||
set(PROJECT_HOMEPAGE_URL "${_HOMEPAGE_URL}" PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
include("${bin}/docs-ci.project.cmake")
|
||||
|
||||
# ---- Generate docs ----
|
||||
|
||||
if(NOT DEFINED DOXYGEN_OUTPUT_DIRECTORY)
|
||||
set(DOXYGEN_OUTPUT_DIRECTORY "${bin}/docs")
|
||||
endif()
|
||||
set(out "${DOXYGEN_OUTPUT_DIRECTORY}")
|
||||
|
||||
foreach(file IN ITEMS Doxyfile conf.py)
|
||||
configure_file("${src}/docs/${file}.in" "${bin}/docs/${file}" @ONLY)
|
||||
endforeach()
|
||||
|
||||
set(mcss_script "${mcss_SOURCE_DIR}/documentation/doxygen.py")
|
||||
set(config "${bin}/docs/conf.py")
|
||||
|
||||
file(REMOVE_RECURSE "${out}/html" "${out}/xml")
|
||||
|
||||
execute_process(
|
||||
COMMAND "${Python3_EXECUTABLE}" "${mcss_script}" "${config}"
|
||||
WORKING_DIRECTORY "${bin}/docs"
|
||||
RESULT_VARIABLE result
|
||||
)
|
||||
if(NOT result EQUAL "0")
|
||||
message(FATAL_ERROR "m.css returned with ${result}")
|
||||
endif()
|
46
cmake/docs.cmake
Normal file
46
cmake/docs.cmake
Normal file
@ -0,0 +1,46 @@
|
||||
# ---- Dependencies ----
|
||||
|
||||
set(extract_timestamps "")
|
||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.24")
|
||||
set(extract_timestamps DOWNLOAD_EXTRACT_TIMESTAMP YES)
|
||||
endif()
|
||||
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
mcss URL
|
||||
https://github.com/friendlyanon/m.css/releases/download/release-1/mcss.zip
|
||||
URL_MD5 00cd2757ebafb9bcba7f5d399b3bec7f
|
||||
SOURCE_DIR "${PROJECT_BINARY_DIR}/mcss"
|
||||
UPDATE_DISCONNECTED YES
|
||||
${extract_timestamps}
|
||||
)
|
||||
FetchContent_MakeAvailable(mcss)
|
||||
|
||||
find_package(Python3 3.6 REQUIRED)
|
||||
|
||||
# ---- Declare documentation target ----
|
||||
|
||||
set(
|
||||
DOXYGEN_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/docs"
|
||||
CACHE PATH "Path for the generated Doxygen documentation"
|
||||
)
|
||||
|
||||
set(working_dir "${PROJECT_BINARY_DIR}/docs")
|
||||
|
||||
foreach(file IN ITEMS Doxyfile conf.py)
|
||||
configure_file("docs/${file}.in" "${working_dir}/${file}" @ONLY)
|
||||
endforeach()
|
||||
|
||||
set(mcss_script "${mcss_SOURCE_DIR}/documentation/doxygen.py")
|
||||
set(config "${working_dir}/conf.py")
|
||||
|
||||
add_custom_target(
|
||||
docs
|
||||
COMMAND "${CMAKE_COMMAND}" -E remove_directory
|
||||
"${DOXYGEN_OUTPUT_DIRECTORY}/html"
|
||||
"${DOXYGEN_OUTPUT_DIRECTORY}/xml"
|
||||
COMMAND "${Python3_EXECUTABLE}" "${mcss_script}" "${config}"
|
||||
COMMENT "Building documentation using Doxygen and m.css"
|
||||
WORKING_DIRECTORY "${working_dir}"
|
||||
VERBATIM
|
||||
)
|
21
cmake/folders.cmake
Normal file
21
cmake/folders.cmake
Normal file
@ -0,0 +1,21 @@
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS YES)
|
||||
|
||||
# Call this function at the end of a directory scope to assign a folder to
|
||||
# targets created in that directory. Utility targets will be assigned to the
|
||||
# UtilityTargets folder, otherwise to the ${name}Targets folder. If a target
|
||||
# already has a folder assigned, then that target will be skipped.
|
||||
function(add_folders name)
|
||||
get_property(targets DIRECTORY PROPERTY BUILDSYSTEM_TARGETS)
|
||||
foreach(target IN LISTS targets)
|
||||
get_property(folder TARGET "${target}" PROPERTY FOLDER)
|
||||
if(DEFINED folder)
|
||||
continue()
|
||||
endif()
|
||||
set(folder Utility)
|
||||
get_property(type TARGET "${target}" PROPERTY TYPE)
|
||||
if(NOT type STREQUAL "UTILITY")
|
||||
set(folder "${name}")
|
||||
endif()
|
||||
set_property(TARGET "${target}" PROPERTY FOLDER "${folder}Targets")
|
||||
endforeach()
|
||||
endfunction()
|
1
cmake/install-config.cmake
Normal file
1
cmake/install-config.cmake
Normal file
@ -0,0 +1 @@
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/nix-gcc-multi-issueTargets.cmake")
|
72
cmake/install-rules.cmake
Normal file
72
cmake/install-rules.cmake
Normal file
@ -0,0 +1,72 @@
|
||||
if(PROJECT_IS_TOP_LEVEL)
|
||||
set(
|
||||
CMAKE_INSTALL_INCLUDEDIR "include/nix-gcc-multi-issue-${PROJECT_VERSION}"
|
||||
CACHE STRING ""
|
||||
)
|
||||
set_property(CACHE CMAKE_INSTALL_INCLUDEDIR PROPERTY TYPE PATH)
|
||||
endif()
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
# find_package(<package>) call for consumers to find this project
|
||||
set(package nix-gcc-multi-issue)
|
||||
|
||||
install(
|
||||
DIRECTORY
|
||||
include/
|
||||
"${PROJECT_BINARY_DIR}/export/"
|
||||
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||
COMPONENT nix-gcc-multi-issue_Development
|
||||
)
|
||||
|
||||
install(
|
||||
TARGETS nix-gcc-multi-issue_nix-gcc-multi-issue
|
||||
EXPORT nix-gcc-multi-issueTargets
|
||||
RUNTIME #
|
||||
COMPONENT nix-gcc-multi-issue_Runtime
|
||||
LIBRARY #
|
||||
COMPONENT nix-gcc-multi-issue_Runtime
|
||||
NAMELINK_COMPONENT nix-gcc-multi-issue_Development
|
||||
ARCHIVE #
|
||||
COMPONENT nix-gcc-multi-issue_Development
|
||||
INCLUDES #
|
||||
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||
)
|
||||
|
||||
write_basic_package_version_file(
|
||||
"${package}ConfigVersion.cmake"
|
||||
COMPATIBILITY SameMajorVersion
|
||||
)
|
||||
|
||||
# Allow package maintainers to freely override the path for the configs
|
||||
set(
|
||||
nix-gcc-multi-issue_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/${package}"
|
||||
CACHE STRING "CMake package config location relative to the install prefix"
|
||||
)
|
||||
set_property(CACHE nix-gcc-multi-issue_INSTALL_CMAKEDIR PROPERTY TYPE PATH)
|
||||
mark_as_advanced(nix-gcc-multi-issue_INSTALL_CMAKEDIR)
|
||||
|
||||
install(
|
||||
FILES cmake/install-config.cmake
|
||||
DESTINATION "${nix-gcc-multi-issue_INSTALL_CMAKEDIR}"
|
||||
RENAME "${package}Config.cmake"
|
||||
COMPONENT nix-gcc-multi-issue_Development
|
||||
)
|
||||
|
||||
install(
|
||||
FILES "${PROJECT_BINARY_DIR}/${package}ConfigVersion.cmake"
|
||||
DESTINATION "${nix-gcc-multi-issue_INSTALL_CMAKEDIR}"
|
||||
COMPONENT nix-gcc-multi-issue_Development
|
||||
)
|
||||
|
||||
install(
|
||||
EXPORT nix-gcc-multi-issueTargets
|
||||
NAMESPACE nix-gcc-multi-issue::
|
||||
DESTINATION "${nix-gcc-multi-issue_INSTALL_CMAKEDIR}"
|
||||
COMPONENT nix-gcc-multi-issue_Development
|
||||
)
|
||||
|
||||
if(PROJECT_IS_TOP_LEVEL)
|
||||
include(CPack)
|
||||
endif()
|
33
cmake/lint-targets.cmake
Normal file
33
cmake/lint-targets.cmake
Normal file
@ -0,0 +1,33 @@
|
||||
set(
|
||||
FORMAT_PATTERNS
|
||||
source/*.cpp source/*.hpp
|
||||
include/*.hpp
|
||||
test/*.cpp test/*.hpp
|
||||
CACHE STRING
|
||||
"; separated patterns relative to the project source dir to format"
|
||||
)
|
||||
|
||||
set(FORMAT_COMMAND clang-format CACHE STRING "Formatter to use")
|
||||
|
||||
add_custom_target(
|
||||
format-check
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
-D "FORMAT_COMMAND=${FORMAT_COMMAND}"
|
||||
-D "PATTERNS=${FORMAT_PATTERNS}"
|
||||
-P "${PROJECT_SOURCE_DIR}/cmake/lint.cmake"
|
||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
|
||||
COMMENT "Linting the code"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
add_custom_target(
|
||||
format-fix
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
-D "FORMAT_COMMAND=${FORMAT_COMMAND}"
|
||||
-D "PATTERNS=${FORMAT_PATTERNS}"
|
||||
-D FIX=YES
|
||||
-P "${PROJECT_SOURCE_DIR}/cmake/lint.cmake"
|
||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
|
||||
COMMENT "Fixing the code"
|
||||
VERBATIM
|
||||
)
|
51
cmake/lint.cmake
Normal file
51
cmake/lint.cmake
Normal file
@ -0,0 +1,51 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
macro(default name)
|
||||
if(NOT DEFINED "${name}")
|
||||
set("${name}" "${ARGN}")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
default(FORMAT_COMMAND clang-format)
|
||||
default(
|
||||
PATTERNS
|
||||
source/*.cpp source/*.hpp
|
||||
include/*.hpp
|
||||
test/*.cpp test/*.hpp
|
||||
)
|
||||
default(FIX NO)
|
||||
|
||||
set(flag --output-replacements-xml)
|
||||
set(args OUTPUT_VARIABLE output)
|
||||
if(FIX)
|
||||
set(flag -i)
|
||||
set(args "")
|
||||
endif()
|
||||
|
||||
file(GLOB_RECURSE files ${PATTERNS})
|
||||
set(badly_formatted "")
|
||||
set(output "")
|
||||
string(LENGTH "${CMAKE_SOURCE_DIR}/" path_prefix_length)
|
||||
|
||||
foreach(file IN LISTS files)
|
||||
execute_process(
|
||||
COMMAND "${FORMAT_COMMAND}" --style=file "${flag}" "${file}"
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
RESULT_VARIABLE result
|
||||
${args}
|
||||
)
|
||||
if(NOT result EQUAL "0")
|
||||
message(FATAL_ERROR "'${file}': formatter returned with ${result}")
|
||||
endif()
|
||||
if(NOT FIX AND output MATCHES "\n<replacement offset")
|
||||
string(SUBSTRING "${file}" "${path_prefix_length}" -1 relative_file)
|
||||
list(APPEND badly_formatted "${relative_file}")
|
||||
endif()
|
||||
set(output "")
|
||||
endforeach()
|
||||
|
||||
if(NOT badly_formatted STREQUAL "")
|
||||
list(JOIN badly_formatted "\n" bad_list)
|
||||
message("The following files are badly formatted:\n\n${bad_list}\n")
|
||||
message(FATAL_ERROR "Run again with FIX=YES to fix these files.")
|
||||
endif()
|
10
cmake/prelude.cmake
Normal file
10
cmake/prelude.cmake
Normal file
@ -0,0 +1,10 @@
|
||||
# ---- In-source guard ----
|
||||
|
||||
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"In-source builds are not supported. "
|
||||
"Please read the BUILDING document before trying to build this project. "
|
||||
"You may need to delete 'CMakeCache.txt' and 'CMakeFiles/' first."
|
||||
)
|
||||
endif()
|
6
cmake/project-is-top-level.cmake
Normal file
6
cmake/project-is-top-level.cmake
Normal file
@ -0,0 +1,6 @@
|
||||
# This variable is set by project() in CMake 3.21+
|
||||
string(
|
||||
COMPARE EQUAL
|
||||
"${CMAKE_SOURCE_DIR}" "${PROJECT_SOURCE_DIR}"
|
||||
PROJECT_IS_TOP_LEVEL
|
||||
)
|
22
cmake/spell-targets.cmake
Normal file
22
cmake/spell-targets.cmake
Normal file
@ -0,0 +1,22 @@
|
||||
set(SPELL_COMMAND codespell CACHE STRING "Spell checker to use")
|
||||
|
||||
add_custom_target(
|
||||
spell-check
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
-D "SPELL_COMMAND=${SPELL_COMMAND}"
|
||||
-P "${PROJECT_SOURCE_DIR}/cmake/spell.cmake"
|
||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
|
||||
COMMENT "Checking spelling"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
add_custom_target(
|
||||
spell-fix
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
-D "SPELL_COMMAND=${SPELL_COMMAND}"
|
||||
-D FIX=YES
|
||||
-P "${PROJECT_SOURCE_DIR}/cmake/spell.cmake"
|
||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
|
||||
COMMENT "Fixing spelling errors"
|
||||
VERBATIM
|
||||
)
|
29
cmake/spell.cmake
Normal file
29
cmake/spell.cmake
Normal file
@ -0,0 +1,29 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
macro(default name)
|
||||
if(NOT DEFINED "${name}")
|
||||
set("${name}" "${ARGN}")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
default(SPELL_COMMAND codespell)
|
||||
default(FIX NO)
|
||||
|
||||
set(flag "")
|
||||
if(FIX)
|
||||
set(flag -w)
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND "${SPELL_COMMAND}" ${flag}
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
RESULT_VARIABLE result
|
||||
)
|
||||
|
||||
if(result EQUAL "65")
|
||||
message(FATAL_ERROR "Run again with FIX=YES to fix these errors.")
|
||||
elseif(result EQUAL "64")
|
||||
message(FATAL_ERROR "Spell checker printed the usage info. Bad arguments?")
|
||||
elseif(NOT result EQUAL "0")
|
||||
message(FATAL_ERROR "Spell checker returned with ${result}")
|
||||
endif()
|
41
cmake/variables.cmake
Normal file
41
cmake/variables.cmake
Normal file
@ -0,0 +1,41 @@
|
||||
# ---- Developer mode ----
|
||||
|
||||
# Developer mode enables targets and code paths in the CMake scripts that are
|
||||
# only relevant for the developer(s) of nix-gcc-multi-issue
|
||||
# Targets necessary to build the project must be provided unconditionally, so
|
||||
# consumers can trivially build and package the project
|
||||
if(PROJECT_IS_TOP_LEVEL)
|
||||
option(nix-gcc-multi-issue_DEVELOPER_MODE "Enable developer mode" OFF)
|
||||
option(BUILD_SHARED_LIBS "Build shared libs." OFF)
|
||||
endif()
|
||||
|
||||
# ---- Suppress C4251 on Windows ----
|
||||
|
||||
# Please see include/nix-gcc-multi-issue/nix-gcc-multi-issue.hpp for more details
|
||||
set(pragma_suppress_c4251 "
|
||||
/* This needs to suppress only for MSVC */
|
||||
#if defined(_MSC_VER) && !defined(__ICL)
|
||||
# define NIX_GCC_MULTI_ISSUE_SUPPRESS_C4251 _Pragma(\"warning(suppress:4251)\")
|
||||
#else
|
||||
# define NIX_GCC_MULTI_ISSUE_SUPPRESS_C4251
|
||||
#endif
|
||||
")
|
||||
|
||||
# ---- Warning guard ----
|
||||
|
||||
# target_include_directories with the SYSTEM modifier will request the compiler
|
||||
# to omit warnings from the provided paths, if the compiler supports that
|
||||
# This is to provide a user experience similar to find_package when
|
||||
# add_subdirectory or FetchContent is used to consume this project
|
||||
set(warning_guard "")
|
||||
if(NOT PROJECT_IS_TOP_LEVEL)
|
||||
option(
|
||||
nix-gcc-multi-issue_INCLUDES_WITH_SYSTEM
|
||||
"Use SYSTEM modifier for nix-gcc-multi-issue's includes, disabling warnings"
|
||||
ON
|
||||
)
|
||||
mark_as_advanced(nix-gcc-multi-issue_INCLUDES_WITH_SYSTEM)
|
||||
if(nix-gcc-multi-issue_INCLUDES_WITH_SYSTEM)
|
||||
set(warning_guard SYSTEM)
|
||||
endif()
|
||||
endif()
|
48
flake.lock
generated
Normal file
48
flake.lock
generated
Normal file
@ -0,0 +1,48 @@
|
||||
{
|
||||
"nodes": {
|
||||
"flake-parts": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1714641030,
|
||||
"narHash": "sha256-yzcRNDoyVP7+SCNX0wmuDju1NUCt8Dz9+lyUXEI0dbI=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "e5d10a24b66c3ea8f150e47dfdb0416ab7c3390e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1715534503,
|
||||
"narHash": "sha256-5ZSVkFadZbFP1THataCaSf0JH2cAH3S29hU9rrxTEqk=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "2057814051972fa1453ddfb0d98badbea9b83c06",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"flake-parts": "flake-parts",
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
31
flake.nix
Normal file
31
flake.nix
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
flake-parts = {
|
||||
url = "github:hercules-ci/flake-parts";
|
||||
inputs.nixpkgs-lib.follows = "nixpkgs";
|
||||
};
|
||||
};
|
||||
|
||||
outputs =
|
||||
inputs@{ flake-parts
|
||||
, ...
|
||||
}:
|
||||
flake-parts.lib.mkFlake { inherit inputs; } {
|
||||
systems = [
|
||||
"x86_64-linux"
|
||||
];
|
||||
|
||||
perSystem = { pkgs, lib, system, self', ... }: {
|
||||
devShells.default = pkgs.mkShell.override { stdenv = pkgs.multiStdenv; }
|
||||
(with pkgs;
|
||||
{
|
||||
packages = [
|
||||
pkg-config
|
||||
cmake
|
||||
ninja
|
||||
];
|
||||
});
|
||||
};
|
||||
};
|
||||
}
|
70
include/nix-gcc-multi-issue/nix-gcc-multi-issue.hpp
Normal file
70
include/nix-gcc-multi-issue/nix-gcc-multi-issue.hpp
Normal file
@ -0,0 +1,70 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "nix-gcc-multi-issue/nix-gcc-multi-issue_export.hpp"
|
||||
|
||||
/**
|
||||
* A note about the MSVC warning C4251:
|
||||
* This warning should be suppressed for private data members of the project's
|
||||
* exported classes, because there are too many ways to work around it and all
|
||||
* involve some kind of trade-off (increased code complexity requiring more
|
||||
* developer time, writing boilerplate code, longer compile times), but those
|
||||
* solutions are very situational and solve things in slightly different ways,
|
||||
* depending on the requirements of the project.
|
||||
* That is to say, there is no general solution.
|
||||
*
|
||||
* What can be done instead is understand where issues could arise where this
|
||||
* warning is spotting a legitimate bug. I will give the general description of
|
||||
* this warning's cause and break it down to make it trivial to understand.
|
||||
*
|
||||
* C4251 is emitted when an exported class has a non-static data member of a
|
||||
* non-exported class type.
|
||||
*
|
||||
* The exported class in our case is the class below (exported_class), which
|
||||
* has a non-static data member (m_name) of a non-exported class type
|
||||
* (std::string).
|
||||
*
|
||||
* The rationale here is that the user of the exported class could attempt to
|
||||
* access (directly, or via an inline member function) a static data member or
|
||||
* a non-inline member function of the data member, resulting in a linker
|
||||
* error.
|
||||
* Inline member function above means member functions that are defined (not
|
||||
* declared) in the class definition.
|
||||
*
|
||||
* Since this exported class never makes these non-exported types available to
|
||||
* the user, we can safely ignore this warning. It's fine if there are
|
||||
* non-exported class types as private member variables, because they are only
|
||||
* accessed by the members of the exported class itself.
|
||||
*
|
||||
* The name() method below returns a pointer to the stored null-terminated
|
||||
* string as a fundamental type (char const), so this is safe to use anywhere.
|
||||
* The only downside is that you can have dangling pointers if the pointer
|
||||
* outlives the class instance which stored the string.
|
||||
*
|
||||
* Shared libraries are not easy, they need some discipline to get right, but
|
||||
* they also solve some other problems that make them worth the time invested.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Reports the name of the library
|
||||
*
|
||||
* Please see the note above for considerations when creating shared libraries.
|
||||
*/
|
||||
class NIX_GCC_MULTI_ISSUE_EXPORT exported_class
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Initializes the name field to the name of the project
|
||||
*/
|
||||
exported_class();
|
||||
|
||||
/**
|
||||
* @brief Returns a non-owning pointer to the string stored in this class
|
||||
*/
|
||||
auto name() const -> char const*;
|
||||
|
||||
private:
|
||||
NIX_GCC_MULTI_ISSUE_SUPPRESS_C4251
|
||||
std::string m_name;
|
||||
};
|
15
source/nix-gcc-multi-issue.cpp
Normal file
15
source/nix-gcc-multi-issue.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "nix-gcc-multi-issue/nix-gcc-multi-issue.hpp"
|
||||
|
||||
exported_class::exported_class()
|
||||
: m_name {"nix-gcc-multi-issue"}
|
||||
{
|
||||
std::cout << "Hello, World!" << std::endl;
|
||||
}
|
||||
|
||||
auto exported_class::name() const -> char const*
|
||||
{
|
||||
return m_name.c_str();
|
||||
}
|
25
test/CMakeLists.txt
Normal file
25
test/CMakeLists.txt
Normal file
@ -0,0 +1,25 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
project(nix-gcc-multi-issueTests LANGUAGES CXX)
|
||||
|
||||
include(../cmake/project-is-top-level.cmake)
|
||||
include(../cmake/folders.cmake)
|
||||
|
||||
# ---- Dependencies ----
|
||||
|
||||
if(PROJECT_IS_TOP_LEVEL)
|
||||
find_package(nix-gcc-multi-issue REQUIRED)
|
||||
enable_testing()
|
||||
endif()
|
||||
|
||||
# ---- Tests ----
|
||||
|
||||
add_executable(nix-gcc-multi-issue_test source/nix-gcc-multi-issue_test.cpp)
|
||||
target_link_libraries(nix-gcc-multi-issue_test PRIVATE nix-gcc-multi-issue::nix-gcc-multi-issue)
|
||||
target_compile_features(nix-gcc-multi-issue_test PRIVATE cxx_std_17)
|
||||
|
||||
add_test(NAME nix-gcc-multi-issue_test COMMAND nix-gcc-multi-issue_test)
|
||||
|
||||
# ---- End-of-file commands ----
|
||||
|
||||
add_folders(Test)
|
10
test/source/nix-gcc-multi-issue_test.cpp
Normal file
10
test/source/nix-gcc-multi-issue_test.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
#include <string>
|
||||
|
||||
#include "nix-gcc-multi-issue/nix-gcc-multi-issue.hpp"
|
||||
|
||||
auto main() -> int
|
||||
{
|
||||
auto const exported = exported_class {};
|
||||
|
||||
return std::string("nix-gcc-multi-issue") == exported.name() ? 0 : 1;
|
||||
}
|
Loading…
Reference in New Issue
Block a user