From caf5fb0742e99c35abdfb127dde749138adc2715 Mon Sep 17 00:00:00 2001 From: Jordan Bayles Date: Mon, 9 Sep 2024 18:35:36 -0700 Subject: [PATCH 01/16] Update meson.yml (#1562) --- .github/workflows/meson.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/meson.yml b/.github/workflows/meson.yml index 1899470f2..48d496c73 100644 --- a/.github/workflows/meson.yml +++ b/.github/workflows/meson.yml @@ -1,6 +1,6 @@ name: meson build and test run-name: update pushed to ${{ github.ref }} -on: [check_run, push] +on: [check_run, push, pull_request] jobs: publish: From badbbc7185cde8270e6005bcdb6686363fe00557 Mon Sep 17 00:00:00 2001 From: Jordan Bayles Date: Mon, 9 Sep 2024 18:35:49 -0700 Subject: [PATCH 02/16] Update clang-format.yml --- .github/workflows/clang-format.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/clang-format.yml b/.github/workflows/clang-format.yml index 497b9d64e..221f8b839 100644 --- a/.github/workflows/clang-format.yml +++ b/.github/workflows/clang-format.yml @@ -1,5 +1,5 @@ name: clang-format check -on: [check_run, push] +on: [check_run, pull_request, push] jobs: formatting-check: From fd1abe4cca7f496438f92d797371dabe14e49373 Mon Sep 17 00:00:00 2001 From: Andrea Pappacoda Date: Tue, 10 Sep 2024 03:42:23 +0200 Subject: [PATCH 03/16] build(meson): use find_program('python3') (#1386) If you really want to be sure to always find python3 when running Meson (and not some other implementation like [Muon](https://muon.build)) it is a bit better to use `find_program('python3')`, as described in https://mesonbuild.com/Reference-manual_functions.html#find_program : "if the "python3" program is requested and it is not found in the system, Meson will return its current interpreter Co-authored-by: Jordan Bayles --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index f68db30dd..fb2b47cd9 100644 --- a/meson.build +++ b/meson.build @@ -73,7 +73,7 @@ if meson.is_subproject() or not get_option('tests') subdir_done() endif -python = import('python').find_installation() +python = find_program('python3') jsoncpp_test = executable( 'jsoncpp_test', files([ From d39b0dff0c5673ed6b21a7808773cd45b661aae2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20R=C3=B6hling?= Date: Tue, 10 Sep 2024 03:42:54 +0200 Subject: [PATCH 04/16] Bump CMake policy version to avoid deprecation warning (#1499) Starting with CMake 3.27, there will be a warning for compat levels below CMake 3.5. Co-authored-by: Jordan Bayles --- jsoncppConfig.cmake.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jsoncppConfig.cmake.in b/jsoncppConfig.cmake.in index 76570bc30..fdd9fea6b 100644 --- a/jsoncppConfig.cmake.in +++ b/jsoncppConfig.cmake.in @@ -1,5 +1,5 @@ cmake_policy(PUSH) -cmake_policy(VERSION 3.0) +cmake_policy(VERSION 3.0...3.26) @PACKAGE_INIT@ From c857395951c1d5e80b0ac62f760d698f03b209f2 Mon Sep 17 00:00:00 2001 From: NotWearingPants <26556598+NotWearingPants@users.noreply.github.com> Date: Tue, 10 Sep 2024 04:43:32 +0300 Subject: [PATCH 05/16] Update link in amalgamate.py (#1335) --- amalgamate.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/amalgamate.py b/amalgamate.py index 4a328ab5a..1d1e48810 100755 --- a/amalgamate.py +++ b/amalgamate.py @@ -63,7 +63,7 @@ def amalgamate_source(source_top_dir=None, """ print("Amalgamating header...") header = AmalgamationFile(source_top_dir) - header.add_text("/// Json-cpp amalgamated header (http://jsoncpp.sourceforge.net/).") + header.add_text("/// Json-cpp amalgamated header (https://github.com/open-source-parsers/jsoncpp/).") header.add_text('/// It is intended to be used with #include "%s"' % header_include_path) header.add_file("LICENSE", wrap_in_comment=True) header.add_text("#ifndef JSON_AMALGAMATED_H_INCLUDED") @@ -90,7 +90,7 @@ def amalgamate_source(source_top_dir=None, forward_header_include_path = base + "-forwards" + ext print("Amalgamating forward header...") header = AmalgamationFile(source_top_dir) - header.add_text("/// Json-cpp amalgamated forward header (http://jsoncpp.sourceforge.net/).") + header.add_text("/// Json-cpp amalgamated forward header (https://github.com/open-source-parsers/jsoncpp/).") header.add_text('/// It is intended to be used with #include "%s"' % forward_header_include_path) header.add_text("/// This header provides forward declaration for all JsonCpp types.") header.add_file("LICENSE", wrap_in_comment=True) @@ -112,7 +112,7 @@ def amalgamate_source(source_top_dir=None, print("Amalgamating source...") source = AmalgamationFile(source_top_dir) - source.add_text("/// Json-cpp amalgamated source (http://jsoncpp.sourceforge.net/).") + source.add_text("/// Json-cpp amalgamated source (https://github.com/open-source-parsers/jsoncpp/).") source.add_text('/// It is intended to be used with #include "%s"' % header_include_path) source.add_file("LICENSE", wrap_in_comment=True) source.add_text("") From c04c0c2131e2c0e90eb731b58877eef39bcf8e47 Mon Sep 17 00:00:00 2001 From: martinduffy1 <106178409+martinduffy1@users.noreply.github.com> Date: Mon, 9 Sep 2024 21:48:54 -0400 Subject: [PATCH 06/16] CharReader: Add StructuredError (#1409) * CharReader: Add Structured Error Add getStructuredError to CharReader * run clang format --------- Co-authored-by: Jordan Bayles Co-authored-by: Jordan Bayles --- include/json/reader.h | 27 +++++++++++++++- src/lib_json/json_reader.cpp | 60 ++++++++++++++++++++++++------------ src/test_lib_json/main.cpp | 30 ++++++++++++++++++ 3 files changed, 97 insertions(+), 20 deletions(-) diff --git a/include/json/reader.h b/include/json/reader.h index 85539d161..38b9360cf 100644 --- a/include/json/reader.h +++ b/include/json/reader.h @@ -244,6 +244,12 @@ class JSON_API Reader { */ class JSON_API CharReader { public: + struct JSON_API StructuredError { + ptrdiff_t offset_start; + ptrdiff_t offset_limit; + String message; + }; + virtual ~CharReader() = default; /** \brief Read a Value from a JSON * document. The document must be a UTF-8 encoded string containing the @@ -262,7 +268,12 @@ class JSON_API CharReader { * error occurred. */ virtual bool parse(char const* beginDoc, char const* endDoc, Value* root, - String* errs) = 0; + String* errs); + + /** \brief Returns a vector of structured errors encountered while parsing. + * Each parse call resets the stored list of errors. + */ + std::vector getStructuredErrors() const; class JSON_API Factory { public: @@ -272,6 +283,20 @@ class JSON_API CharReader { */ virtual CharReader* newCharReader() const = 0; }; // Factory + +protected: + class Impl { + public: + virtual ~Impl() = default; + virtual bool parse(char const* beginDoc, char const* endDoc, Value* root, + String* errs) = 0; + virtual std::vector getStructuredErrors() const = 0; + }; + + explicit CharReader(std::unique_ptr impl) : _impl(std::move(impl)) {} + +private: + std::unique_ptr _impl; }; // CharReader /** \brief Build a CharReader implementation. diff --git a/src/lib_json/json_reader.cpp b/src/lib_json/json_reader.cpp index 86ed030a3..4ab4dffd3 100644 --- a/src/lib_json/json_reader.cpp +++ b/src/lib_json/json_reader.cpp @@ -878,17 +878,12 @@ class OurReader { public: using Char = char; using Location = const Char*; - struct StructuredError { - ptrdiff_t offset_start; - ptrdiff_t offset_limit; - String message; - }; explicit OurReader(OurFeatures const& features); bool parse(const char* beginDoc, const char* endDoc, Value& root, bool collectComments = true); String getFormattedErrorMessages() const; - std::vector getStructuredErrors() const; + std::vector getStructuredErrors() const; private: OurReader(OurReader const&); // no impl @@ -1836,10 +1831,11 @@ String OurReader::getFormattedErrorMessages() const { return formattedMessage; } -std::vector OurReader::getStructuredErrors() const { - std::vector allErrors; +std::vector +OurReader::getStructuredErrors() const { + std::vector allErrors; for (const auto& error : errors_) { - OurReader::StructuredError structured; + CharReader::StructuredError structured; structured.offset_start = error.token_.start_ - begin_; structured.offset_limit = error.token_.end_ - begin_; structured.message = error.message_; @@ -1849,20 +1845,36 @@ std::vector OurReader::getStructuredErrors() const { } class OurCharReader : public CharReader { - bool const collectComments_; - OurReader reader_; public: OurCharReader(bool collectComments, OurFeatures const& features) - : collectComments_(collectComments), reader_(features) {} - bool parse(char const* beginDoc, char const* endDoc, Value* root, - String* errs) override { - bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_); - if (errs) { - *errs = reader_.getFormattedErrorMessages(); + : CharReader( + std::unique_ptr(new OurImpl(collectComments, features))) {} + +protected: + class OurImpl : public Impl { + public: + OurImpl(bool collectComments, OurFeatures const& features) + : collectComments_(collectComments), reader_(features) {} + + bool parse(char const* beginDoc, char const* endDoc, Value* root, + String* errs) override { + bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_); + if (errs) { + *errs = reader_.getFormattedErrorMessages(); + } + return ok; } - return ok; - } + + std::vector + getStructuredErrors() const override { + return reader_.getStructuredErrors(); + } + + private: + bool const collectComments_; + OurReader reader_; + }; }; CharReaderBuilder::CharReaderBuilder() { setDefaults(&settings_); } @@ -1952,6 +1964,16 @@ void CharReaderBuilder::setDefaults(Json::Value* settings) { //! [CharReaderBuilderDefaults] } +std::vector +CharReader::getStructuredErrors() const { + return _impl->getStructuredErrors(); +} + +bool CharReader::parse(char const* beginDoc, char const* endDoc, Value* root, + String* errs) { + return _impl->parse(beginDoc, endDoc, root, errs); +} + ////////////////////////////////// // global functions diff --git a/src/test_lib_json/main.cpp b/src/test_lib_json/main.cpp index 1ef33bb5a..fa41d19ed 100644 --- a/src/test_lib_json/main.cpp +++ b/src/test_lib_json/main.cpp @@ -3917,6 +3917,36 @@ JSONTEST_FIXTURE_LOCAL(FuzzTest, fuzzDoesntCrash) { example.size())); } +struct ParseWithStructuredErrorsTest : JsonTest::TestCase { + void testErrors( + const std::string& doc, bool success, + const std::vector& expectedErrors) { + Json::CharReaderBuilder b; + CharReaderPtr reader(b.newCharReader()); + Json::Value root; + JSONTEST_ASSERT_EQUAL( + reader->parse(doc.data(), doc.data() + doc.length(), &root, nullptr), + success); + auto actualErrors = reader->getStructuredErrors(); + JSONTEST_ASSERT_EQUAL(expectedErrors.size(), actualErrors.size()); + for (std::size_t i = 0; i < actualErrors.size(); i++) { + const auto& a = actualErrors[i]; + const auto& e = expectedErrors[i]; + JSONTEST_ASSERT_EQUAL(a.offset_start, e.offset_start); + JSONTEST_ASSERT_EQUAL(a.offset_limit, e.offset_limit); + JSONTEST_ASSERT_STRING_EQUAL(a.message, e.message); + } + } +}; + +JSONTEST_FIXTURE_LOCAL(ParseWithStructuredErrorsTest, success) { + testErrors("{}", true, {}); +} + +JSONTEST_FIXTURE_LOCAL(ParseWithStructuredErrorsTest, singleError) { + testErrors("{ 1 : 2 }", false, {{2, 3, "Missing '}' or object member name"}}); +} + int main(int argc, const char* argv[]) { JsonTest::Runner runner; From 483f1c310e36db6d53868f9a4f8b9c0f90faba5b Mon Sep 17 00:00:00 2001 From: Pavel Tsynk <36221942+TsynkPavel@users.noreply.github.com> Date: Tue, 10 Sep 2024 08:50:38 +0700 Subject: [PATCH 07/16] Fix compile on windows with clang (#1480) Co-authored-by: Jordan Bayles --- src/lib_json/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib_json/CMakeLists.txt b/src/lib_json/CMakeLists.txt index 3cf66eb34..ce8100b29 100644 --- a/src/lib_json/CMakeLists.txt +++ b/src/lib_json/CMakeLists.txt @@ -144,7 +144,7 @@ if(BUILD_STATIC_LIBS) # avoid name clashes on windows as the shared import lib is also named jsoncpp.lib if(NOT DEFINED STATIC_SUFFIX AND BUILD_SHARED_LIBS) - if (MSVC) + if (WIN32) set(STATIC_SUFFIX "_static") else() set(STATIC_SUFFIX "") From 31754ce2e25056c0bbf6599c49059d2778e9109c Mon Sep 17 00:00:00 2001 From: Pavel Tsynk <36221942+TsynkPavel@users.noreply.github.com> Date: Tue, 10 Sep 2024 08:51:11 +0700 Subject: [PATCH 08/16] Fixed setting JSONCPP_USE_SECURE_MEMORY definition (#1479) * Fixed setting JSONCPP_USE_SECURE_MEMORY definition * fix indent * Fix passing from command line * simplified definition --------- Co-authored-by: Jordan Bayles --- CMakeLists.txt | 4 +++- include/json/version.h | 5 ++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8920544a3..ac0a8eda2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -103,7 +103,9 @@ if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" CACHE PATH "Executable/dll output dir.") endif() -set(JSONCPP_USE_SECURE_MEMORY "0" CACHE STRING "-D...=1 to use memory-wiping allocator for STL") +if(JSONCPP_USE_SECURE_MEMORY) + add_definitions("-DJSONCPP_USE_SECURE_MEMORY=1") +endif() configure_file("${PROJECT_SOURCE_DIR}/version.in" "${PROJECT_BINARY_DIR}/version" diff --git a/include/json/version.h b/include/json/version.h index e931d0383..9e9541191 100644 --- a/include/json/version.h +++ b/include/json/version.h @@ -18,10 +18,9 @@ ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \ (JSONCPP_VERSION_PATCH << 8)) -#ifdef JSONCPP_USING_SECURE_MEMORY -#undef JSONCPP_USING_SECURE_MEMORY -#endif +#if !defined(JSONCPP_USE_SECURE_MEMORY) #define JSONCPP_USING_SECURE_MEMORY 0 +#endif // If non-zero, the library zeroes any memory that it has allocated before // it frees its memory. From 742c645ab31088f95edd112ffc65eca839cdf8ff Mon Sep 17 00:00:00 2001 From: Kapandaria Date: Tue, 10 Sep 2024 04:51:35 +0300 Subject: [PATCH 09/16] Update readFromString.cpp (#1477) Print the error to screen Co-authored-by: Jordan Bayles --- example/readFromString/readFromString.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/readFromString/readFromString.cpp b/example/readFromString/readFromString.cpp index 0b29a4e86..878f9eb92 100644 --- a/example/readFromString/readFromString.cpp +++ b/example/readFromString/readFromString.cpp @@ -25,7 +25,7 @@ int main() { const std::unique_ptr reader(builder.newCharReader()); if (!reader->parse(rawJson.c_str(), rawJson.c_str() + rawJsonLength, &root, &err)) { - std::cout << "error" << std::endl; + std::cout << "error: " << err << std::endl; return EXIT_FAILURE; } } From 62f7f3efe650dde5f6075a8dcecbfe358ba530e8 Mon Sep 17 00:00:00 2001 From: Pedro Kaj Kjellerup Nacht Date: Mon, 9 Sep 2024 22:53:23 -0300 Subject: [PATCH 10/16] Add security policy (#1484) Signed-off-by: Pedro Kaj Kjellerup Nacht --- SECURITY.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..67af8830b --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,17 @@ +# Security Policy + +If you have discovered a security vulnerability in this project, please report it +privately. **Do not disclose it as a public issue.** This gives us time to work with you +to fix the issue before public exposure, reducing the chance that the exploit will be +used before a patch is released. + +Please submit the report by filling out +[this form](https://github.com/open-source-parsers/jsoncpp/security/advisories/new). + +Please provide the following information in your report: + +- A description of the vulnerability and its impact +- How to reproduce the issue + +This project is maintained by volunteers on a reasonable-effort basis. As such, +we ask that you give us 90 days to work on a fix before public exposure. From a4a083c30751a178b7cdfe1bee685d0ec1c2ed28 Mon Sep 17 00:00:00 2001 From: SpaceIm <30052553+SpaceIm@users.noreply.github.com> Date: Tue, 10 Sep 2024 03:57:51 +0200 Subject: [PATCH 11/16] remove ccache micro management (#1448) Co-authored-by: Jordan Bayles --- CMakeLists.txt | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ac0a8eda2..a37e726f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,16 +54,6 @@ endif() set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake") -# --------------------------------------------------------------------------- -# use ccache if found, has to be done before project() -# --------------------------------------------------------------------------- -find_program(CCACHE_EXECUTABLE "ccache" HINTS /usr/local/bin /opt/local/bin) -if(CCACHE_EXECUTABLE) - message(STATUS "use ccache") - set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_EXECUTABLE}" CACHE PATH "ccache" FORCE) - set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_EXECUTABLE}" CACHE PATH "ccache" FORCE) -endif() - project(jsoncpp # Note: version must be updated in three places when doing a release. This # annoying process ensures that amalgamate, CMake, and meson all report the From d791737ccd74beb4c6bf3f0fa499db74c2791192 Mon Sep 17 00:00:00 2001 From: Jordan Bayles Date: Mon, 9 Sep 2024 19:05:11 -0700 Subject: [PATCH 12/16] Create cmake.yml (#1563) * Create cmake.yml * Update cmake.yml * Update cmake.yml --- .github/workflows/cmake.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .github/workflows/cmake.yml diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml new file mode 100644 index 000000000..675493b8f --- /dev/null +++ b/.github/workflows/cmake.yml @@ -0,0 +1,18 @@ +name: cmake +on: [push] +jobs: + publish: + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + + steps: + - name: checkout project + uses: actions/checkout@v4 + + - name: build project + uses: threeal/cmake-action@v2.0.0 + From d13801e83239924c281119316aefb8f611d9bfd0 Mon Sep 17 00:00:00 2001 From: Jordan Bayles Date: Mon, 9 Sep 2024 19:06:30 -0700 Subject: [PATCH 13/16] Update meson.yml (#1564) --- .github/workflows/meson.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/meson.yml b/.github/workflows/meson.yml index 48d496c73..22fe32f72 100644 --- a/.github/workflows/meson.yml +++ b/.github/workflows/meson.yml @@ -3,7 +3,7 @@ run-name: update pushed to ${{ github.ref }} on: [check_run, push, pull_request] jobs: - publish: + meson-publish: runs-on: ${{ matrix.os }} strategy: @@ -32,7 +32,7 @@ jobs: ninja-version: 1.11.1.1 action: test - coverage: + meson-coverage: runs-on: ubuntu-latest steps: From 8d1ea7054f4a0984fc84e406f9253b9cafacd64a Mon Sep 17 00:00:00 2001 From: Jordan Bayles Date: Mon, 9 Sep 2024 19:07:04 -0700 Subject: [PATCH 14/16] Update cmake.yml --- .github/workflows/cmake.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 675493b8f..91f387a50 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -1,7 +1,7 @@ name: cmake -on: [push] +on: [check_run, push, pull_request] jobs: - publish: + cmake-publish: runs-on: ${{ matrix.os }} strategy: From fdb529bd0613308591352ac1d4e765c4d33710c9 Mon Sep 17 00:00:00 2001 From: jedav Date: Mon, 9 Sep 2024 19:53:56 -0700 Subject: [PATCH 15/16] Move removeIndex's result instead of copying (#1516) Currently removeIndex copies the removed value into removed and then destructs the original, which can cause significant performance overhead. Co-authored-by: Jordan Bayles --- src/lib_json/json_value.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib_json/json_value.cpp b/src/lib_json/json_value.cpp index 26cd843cc..a5e2dd8e4 100644 --- a/src/lib_json/json_value.cpp +++ b/src/lib_json/json_value.cpp @@ -1205,7 +1205,7 @@ bool Value::removeIndex(ArrayIndex index, Value* removed) { return false; } if (removed) - *removed = it->second; + *removed = std::move(it->second); ArrayIndex oldSize = size(); // shift left all items left, into the place of the "removed" for (ArrayIndex i = index; i < (oldSize - 1); ++i) { From 2072e2b4e394f90ca9cbea32db53231900c01618 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20M=C3=BCller?= <34514239+appgurueu@users.noreply.github.com> Date: Tue, 10 Sep 2024 04:56:37 +0200 Subject: [PATCH 16/16] Use current source / binary dir when assuring out of source builds (#1527) Co-authored-by: Jordan Bayles --- include/PreventInSourceBuilds.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/PreventInSourceBuilds.cmake b/include/PreventInSourceBuilds.cmake index 7ddda546a..be5d0dd41 100644 --- a/include/PreventInSourceBuilds.cmake +++ b/include/PreventInSourceBuilds.cmake @@ -2,8 +2,8 @@ # This function will prevent in-source builds function(AssureOutOfSourceBuilds) # make sure the user doesn't play dirty with symlinks - get_filename_component(srcdir "${CMAKE_SOURCE_DIR}" REALPATH) - get_filename_component(bindir "${CMAKE_BINARY_DIR}" REALPATH) + get_filename_component(srcdir "${CMAKE_CURRENT_SOURCE_DIR}" REALPATH) + get_filename_component(bindir "${CMAKE_CURRENT_BINARY_DIR}" REALPATH) # disallow in-source builds if("${srcdir}" STREQUAL "${bindir}")