From 8fecf7325a0495b2dc9ea90d218e6a6a250606a3 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Sat, 17 Sep 2022 23:32:06 +0000 Subject: [PATCH 1/7] bugfix: missing headers in cpp2util & tests --- ...d-captures-in-expressions-and-postconditions.cpp2 | 2 ++ .../mixed-intro-example-three-loops.cpp2 | 5 +++-- ...ed-captures-in-expressions-and-postconditions.cpp | 12 +++++++----- ...res-in-expressions-and-postconditions.cpp2.output | 2 +- .../test-results/mixed-intro-example-three-loops.cpp | 5 +++-- 5 files changed, 16 insertions(+), 10 deletions(-) diff --git a/regression-tests/mixed-captures-in-expressions-and-postconditions.cpp2 b/regression-tests/mixed-captures-in-expressions-and-postconditions.cpp2 index 43ebd4e871..7adf5fa868 100644 --- a/regression-tests/mixed-captures-in-expressions-and-postconditions.cpp2 +++ b/regression-tests/mixed-captures-in-expressions-and-postconditions.cpp2 @@ -1,3 +1,5 @@ +#include +#include main: () -> int = { vec: std::vector diff --git a/regression-tests/mixed-intro-example-three-loops.cpp2 b/regression-tests/mixed-intro-example-three-loops.cpp2 index 6cc3839152..b377583b88 100644 --- a/regression-tests/mixed-intro-example-three-loops.cpp2 +++ b/regression-tests/mixed-intro-example-three-loops.cpp2 @@ -3,12 +3,13 @@ #include #include #include +#include -auto print(auto const& thing) -> void { +auto print(auto const& thing) -> void { std::cout << ">> " << thing << "\n"; } -auto decorate_and_print(auto& thing) -> void { +auto decorate_and_print(auto& thing) -> void { thing = "[" + thing + "]"; print(thing); } diff --git a/regression-tests/test-results/mixed-captures-in-expressions-and-postconditions.cpp b/regression-tests/test-results/mixed-captures-in-expressions-and-postconditions.cpp index d67a42a73a..f0e3f3d767 100644 --- a/regression-tests/test-results/mixed-captures-in-expressions-and-postconditions.cpp +++ b/regression-tests/test-results/mixed-captures-in-expressions-and-postconditions.cpp @@ -1,16 +1,18 @@ // ----- Cpp2 support ----- #include "cpp2util.h" +#line 1 "mixed-captures-in-expressions-and-postconditions.cpp2" +#include +#include -#line 2 "mixed-captures-in-expressions-and-postconditions.cpp2" [[nodiscard]] auto main() -> int; -#line 14 "mixed-captures-in-expressions-and-postconditions.cpp2" #line 16 "mixed-captures-in-expressions-and-postconditions.cpp2" +#line 18 "mixed-captures-in-expressions-and-postconditions.cpp2" auto insert_at(cpp2::in where, cpp2::in val) -> void; //=== Cpp2 definitions ========================================================== -#line 1 "mixed-captures-in-expressions-and-postconditions.cpp2" +#line 3 "mixed-captures-in-expressions-and-postconditions.cpp2" [[nodiscard]] auto main() -> int{ std::vector vec { @@ -29,8 +31,8 @@ std::vector vec { }; auto insert_at(cpp2::in where, cpp2::in val) -> void { cpp2::Default.expects(0 <= where && where <= CPP2_UFCS_0(ssize, vec), ""); - auto post_18_5 = cpp2::finally_success([_0 = CPP2_UFCS_0(ssize, vec)]{cpp2::Default.expects(CPP2_UFCS_0(ssize, vec) == _0 + 1, "");} ); -#line 18 "mixed-captures-in-expressions-and-postconditions.cpp2" + auto post_20_5 = cpp2::finally_success([_0 = CPP2_UFCS_0(ssize, vec)]{cpp2::Default.expects(CPP2_UFCS_0(ssize, vec) == _0 + 1, "");} ); +#line 20 "mixed-captures-in-expressions-and-postconditions.cpp2" CPP2_UFCS(insert, vec, CPP2_UFCS_0(begin, vec) + where, val); diff --git a/regression-tests/test-results/mixed-captures-in-expressions-and-postconditions.cpp2.output b/regression-tests/test-results/mixed-captures-in-expressions-and-postconditions.cpp2.output index cfb6100576..0306a1939b 100644 --- a/regression-tests/test-results/mixed-captures-in-expressions-and-postconditions.cpp2.output +++ b/regression-tests/test-results/mixed-captures-in-expressions-and-postconditions.cpp2.output @@ -1,2 +1,2 @@ -mixed-captures-in-expressions-and-postconditions.cpp2... ok (all Cpp2, passes safety checks) +mixed-captures-in-expressions-and-postconditions.cpp2... ok (mixed Cpp1/Cpp2, Cpp2 code passes safety checks) diff --git a/regression-tests/test-results/mixed-intro-example-three-loops.cpp b/regression-tests/test-results/mixed-intro-example-three-loops.cpp index 6cc3839152..b377583b88 100644 --- a/regression-tests/test-results/mixed-intro-example-three-loops.cpp +++ b/regression-tests/test-results/mixed-intro-example-three-loops.cpp @@ -3,12 +3,13 @@ #include #include #include +#include -auto print(auto const& thing) -> void { +auto print(auto const& thing) -> void { std::cout << ">> " << thing << "\n"; } -auto decorate_and_print(auto& thing) -> void { +auto decorate_and_print(auto& thing) -> void { thing = "[" + thing + "]"; print(thing); } From 48abc465358ed2381e96e50e27367c18b1bcc1ed Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Sat, 17 Sep 2022 22:18:13 +0000 Subject: [PATCH 2/7] Add a CMake build and CTest tests --- .gitignore | 3 +- CMakeLists.txt | 127 +++++++++++++++++++++++ cmake/CppfrontHelpers.cmake | 86 +++++++++++++++ cmake/cppfront-config.cmake.in | 10 ++ cmake/cppfront-exe-config.cmake.in | 7 ++ example/CMakeLists.txt | 8 ++ example/README.md | 21 ++++ example/main.cpp2 | 8 ++ regression-tests/CMakeLists.txt | 117 +++++++++++++++++++++ regression-tests/cmake/CMakeLists.txt.in | 15 +++ test-all.sh | 22 ++++ 11 files changed, 423 insertions(+), 1 deletion(-) create mode 100644 CMakeLists.txt create mode 100644 cmake/CppfrontHelpers.cmake create mode 100644 cmake/cppfront-config.cmake.in create mode 100644 cmake/cppfront-exe-config.cmake.in create mode 100644 example/CMakeLists.txt create mode 100644 example/README.md create mode 100644 example/main.cpp2 create mode 100644 regression-tests/CMakeLists.txt create mode 100644 regression-tests/cmake/CMakeLists.txt.in create mode 100755 test-all.sh diff --git a/.gitignore b/.gitignore index 93669d9eb4..2f08ac4676 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ - *.vcxproj *.filters *.recipe @@ -22,3 +21,5 @@ *.vsidx *.lock .editorconfig +build/ +*local/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000..b54fcb6701 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,127 @@ +cmake_minimum_required(VERSION 3.23) +project( + cppfront + LANGUAGES CXX + VERSION 0.1.0 +) + +option( + CPPFRONT_INSTALL_RULES "Enable install rules for cppfront" "${PROJECT_IS_TOP_LEVEL}" +) + +add_executable(cppfront source/cppfront.cpp) +add_executable(cppfront::cppfront ALIAS cppfront) +target_compile_features(cppfront PRIVATE cxx_std_20) +target_sources( + cppfront + PRIVATE + FILE_SET HEADERS + BASE_DIRS source + FILES source/common.h source/lex.h source/load.h source/parse.h source/sema.h +) + +add_library(cpp2util INTERFACE) +add_library(cppfront::cpp2util ALIAS cpp2util) +target_compile_features(cpp2util INTERFACE cxx_std_20) +target_include_directories( + cpp2util INTERFACE "$" +) +target_sources( + cpp2util + INTERFACE + FILE_SET HEADERS + BASE_DIRS include + FILES include/cpp2util.h +) + +if (NOT PROJECT_IS_TOP_LEVEL) + get_directory_property(_CPPFRONT_MAGIC_DIR PARENT_DIRECTORY) + include(cmake/CppfrontHelpers.cmake) +endif () + +if (CPPFRONT_INSTALL_RULES) + include(GNUInstallDirs) + include(CMakePackageConfigHelpers) + + set(CPPFRONT_INSTALL_CMAKEDIR "${CMAKE_INSTALL_DATADIR}/cmake/cppfront" + CACHE STRING "Install location for cppfront's platform-independent CMake files") + + set(CPPFRONT_INSTALL_EXE_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/cppfront-exe" + CACHE STRING "Install location for cppfront's platform-specific CMake files") + + ## + # Install rules for cppfront executable (which is naturally platform + # dependent) + + install( + TARGETS cppfront + EXPORT cppfront-exe-targets + COMPONENT cppfront + ) + + install( + EXPORT cppfront-exe-targets + DESTINATION "${CPPFRONT_INSTALL_EXE_CMAKEDIR}" + NAMESPACE cppfront:: + COMPONENT cppfront + ) + + configure_package_config_file( + cmake/cppfront-exe-config.cmake.in + cmake/cppfront-exe-config.cmake + INSTALL_DESTINATION "${CPPFRONT_INSTALL_EXE_CMAKEDIR}" + PATH_VARS CMAKE_INSTALL_BINDIR + ) + + write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/cmake/cppfront-exe-config-version.cmake" + COMPATIBILITY ExactVersion + ARCH_INDEPENDENT # to allow finding host executables in cross-builds + ) + + install( + FILES + "${CMAKE_CURRENT_BINARY_DIR}/cmake/cppfront-exe-config.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/cmake/cppfront-exe-config-version.cmake" + DESTINATION "${CPPFRONT_INSTALL_EXE_CMAKEDIR}" + COMPONENT cppfront + ) + + ## + # Install rules for cppfront CMake helpers and runtime headers, + # which are platform-independent + + install( + TARGETS cpp2util + EXPORT cppfront-targets + FILE_SET HEADERS + COMPONENT cppfront + ) + install( + EXPORT cppfront-targets + DESTINATION "${CPPFRONT_INSTALL_CMAKEDIR}" + NAMESPACE cppfront:: + COMPONENT cppfront + ) + + configure_package_config_file( + cmake/cppfront-config.cmake.in + cmake/cppfront-config.cmake + INSTALL_DESTINATION "${CPPFRONT_INSTALL_CMAKEDIR}" + ) + + write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/cmake/cppfront-config-version.cmake" + COMPATIBILITY ExactVersion + ARCH_INDEPENDENT + ) + + install( + FILES + "${CMAKE_CURRENT_BINARY_DIR}/cmake/cppfront-config.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/cmake/cppfront-config-version.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/CppfrontHelpers.cmake" + DESTINATION "${CPPFRONT_INSTALL_CMAKEDIR}" + COMPONENT cppfront + ) +endif () diff --git a/cmake/CppfrontHelpers.cmake b/cmake/CppfrontHelpers.cmake new file mode 100644 index 0000000000..69ddb86cb3 --- /dev/null +++ b/cmake/CppfrontHelpers.cmake @@ -0,0 +1,86 @@ +function(_cppfront_unique_name base hash outvar) + string(LENGTH "${hash}" len) + foreach (i RANGE 0 "${len}") + string(SUBSTRING "${hash}" 0 "${i}" uniq) + if (uniq) + set(name "${base}-${uniq}") + else () + set(name "${base}") + endif () + get_property(name_used GLOBAL PROPERTY "cppfront/names/${name}" SET) + if (NOT name_used) + set("${outvar}" "${name}" PARENT_SCOPE) + set_property(GLOBAL PROPERTY "cppfront/names/${name}" 1) + return() + endif () + endforeach () + # This should be impossible, unless caching in _cppfront_generate_source + # is broken. + message(FATAL_ERROR "Could not compute a unique name using ${base} and ${hash}") +endfunction() + +function(_cppfront_generate_source src out) + # TODO: there's probably something nicer/more user-friendly to be + # done here, but it's maybe not worth thinking about until cppfront's + # command line improves. + + file(REAL_PATH "${src}" src) + string(SHA256 src_hash "${src}") + + get_property(out_file GLOBAL PROPERTY "cppfront/out_file/${src_hash}") + if (out_file) + set("${out}" "${out_file}" PARENT_SCOPE) + return() + endif () + + cmake_path(GET src STEM original_stem) + _cppfront_unique_name("${original_stem}" "${src_hash}" basename) + + # assume no SHA256 collisions + file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/_cppfront/") + set(src_file "${CMAKE_BINARY_DIR}/_cppfront/${basename}.cpp2") + set(out_file "${CMAKE_BINARY_DIR}/_cppfront/${basename}.cpp") + + add_custom_command( + OUTPUT "${out_file}" + COMMAND "${CMAKE_COMMAND}" -E copy "${src}" "${src_file}" + COMMAND cppfront::cppfront "${basename}.cpp2" ${CPPFRONT_FLAGS} + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/_cppfront" + DEPENDS "${src}" cppfront::cppfront + VERBATIM + ) + + set_property(GLOBAL PROPERTY "cppfront/out_file/${src_hash}" "${out_file}") + set("${out}" "${out_file}" PARENT_SCOPE) +endfunction() + +function(cppfront_enable) + cmake_parse_arguments(PARSE_ARGV 0 ARG "" "" "TARGETS") + + foreach (tgt IN LISTS ARG_TARGETS) + get_property(sources TARGET "${tgt}" PROPERTY SOURCES) + list(FILTER sources INCLUDE REGEX "\\.cpp2$") + + if (sources) + target_link_libraries("${tgt}" PRIVATE cppfront::cpp2util) + endif () + + foreach (src IN LISTS sources) + _cppfront_generate_source("${src}" out_path) + target_sources("${tgt}" PRIVATE "${out_path}") + endforeach () + endforeach () +endfunction() + +function(_cppfront_enable_dir) + get_property(targets DIRECTORY . PROPERTY BUILDSYSTEM_TARGETS) + cppfront_enable(TARGETS ${targets}) +endfunction() + +if (NOT CPPFRONT_NO_MAGIC) + if (NOT _CPPFRONT_MAGIC_DIR) + set(_CPPFRONT_MAGIC_DIR "${CMAKE_CURRENT_SOURCE_DIR}") + endif () + message(VERBOSE "Enabling cppfront for all targets in ${_CPPFRONT_MAGIC_DIR}") + cmake_language(DEFER DIRECTORY "${_CPPFRONT_MAGIC_DIR}" CALL _cppfront_enable_dir) +endif () diff --git a/cmake/cppfront-config.cmake.in b/cmake/cppfront-config.cmake.in new file mode 100644 index 0000000000..f840e7990b --- /dev/null +++ b/cmake/cppfront-config.cmake.in @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.23) +@PACKAGE_INIT@ + +include(CMakeFindDependencyMacro) +find_dependency(cppfront-exe) + +include("${CMAKE_CURRENT_LIST_DIR}/cppfront-targets.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/CppfrontHelpers.cmake") + +check_required_components(cppfront) diff --git a/cmake/cppfront-exe-config.cmake.in b/cmake/cppfront-exe-config.cmake.in new file mode 100644 index 0000000000..f5cf8bda1e --- /dev/null +++ b/cmake/cppfront-exe-config.cmake.in @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.23) +@PACKAGE_INIT@ + +include("${CMAKE_CURRENT_LIST_DIR}/cppfront-exe-targets.cmake") + +set_and_check(CPPFRONT_EXECUTABLE "@PACKAGE_CMAKE_INSTALL_BINDIR@/cppfront@CMAKE_EXECUTABLE_SUFFIX@") +check_required_components(cppfront-exe) diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt new file mode 100644 index 0000000000..1ba7908cf4 --- /dev/null +++ b/example/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.23) +project(cpp2-example) + +find_package(cppfront REQUIRED) +# This works, too: +# add_subdirectory(../ cppfront) + +add_executable(main main.cpp2) diff --git a/example/README.md b/example/README.md new file mode 100644 index 0000000000..0606ec1b06 --- /dev/null +++ b/example/README.md @@ -0,0 +1,21 @@ +# CPPFront CMake example + +This is a simple demo of this fork's CMake integration. To build it, +first build cppfront. From this directory, run: + +``` +$ cmake -G Ninja -S .. -B build/cppfront -DCMAKE_BUILD_TYPE=Release +$ cmake --build build/cppfront +$ cmake --install build/cppfront --prefix _local +``` + +Now we'll configure this project to use the locally installed cppfront: + +``` +$ cmake -G Ninja -S . -B build/example -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_PREFIX_PATH=$PWD/_local +$ cmake --build build/example +$ ./build/example/main +$ cat xyxxy +Hello Fred with UFCS! +``` diff --git a/example/main.cpp2 b/example/main.cpp2 new file mode 100644 index 0000000000..7d0ff7eccc --- /dev/null +++ b/example/main.cpp2 @@ -0,0 +1,8 @@ +// "A better C than C" ... ? +// +main: () -> int = { + s: std::string = "Fred"; + myfile := fopen("xyzzy", "w"); + myfile.fprintf( "Hello %s with UFCS!\n", s.c_str() ); + myfile.fclose(); +} diff --git a/regression-tests/CMakeLists.txt b/regression-tests/CMakeLists.txt new file mode 100644 index 0000000000..50e3a397d1 --- /dev/null +++ b/regression-tests/CMakeLists.txt @@ -0,0 +1,117 @@ +cmake_minimum_required(VERSION 3.23) +project(cppfront-regression-tests LANGUAGES NONE) + +enable_testing() + +set(CPPFRONT_NO_MAGIC 1) +find_package(cppfront REQUIRED) + +# The following tests aren't expected to be buildable C++, even if +# cppfront succeeds. +set( + codegen_only_tests + mixed-postfix-expression-custom-formatting +) + +function(cppfront_command_tests) + cmake_parse_arguments(PARSE_ARGV 0 ARG "" "SOURCE;EXPECTED_FILE" "EXTRA_FLAGS") + + configure_file("${ARG_SOURCE}" "${ARG_SOURCE}" COPYONLY) + + cmake_path(GET ARG_SOURCE STEM test_name) + add_test( + NAME "codegen/${test_name}" + COMMAND cppfront::cppfront "${ARG_SOURCE}" ${ARG_EXTRA_FLAGS} + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" + ) + + file(READ "test-results/${ARG_SOURCE}-output" expected_output) + string(REPLACE "\\" "\\\\" expected_output "${expected_output}") + string(REPLACE "(" "\\(" expected_output "${expected_output}") + string(REPLACE ")" "\\)" expected_output "${expected_output}") + string(REPLACE "[" "\\[" expected_output "${expected_output}") + string(REPLACE "]" "\\]" expected_output "${expected_output}") + string(REPLACE "." "\\." expected_output "${expected_output}") + string(REPLACE "+" "\\+" expected_output "${expected_output}") + string(REPLACE "*" "\\*" expected_output "${expected_output}") + + set_tests_properties("codegen/${test_name}" PROPERTIES PASS_REGULAR_EXPRESSION "^${expected_output}$") + + if (ARG_EXPECTED_FILE) + cmake_path(REPLACE_EXTENSION ARG_SOURCE "cpp" OUTPUT_VARIABLE gen_cpp_src) + + add_test( + NAME "codegen/check/${test_name}" + COMMAND "${CMAKE_COMMAND}" -E compare_files "${gen_cpp_src}" "${ARG_EXPECTED_FILE}" + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" + ) + + set_tests_properties("codegen/${test_name}" PROPERTIES FIXTURES_SETUP "codegen/${test_name}") + set_tests_properties("codegen/check/${test_name}" PROPERTIES FIXTURES_REQUIRED "codegen/${test_name}") + endif () +endfunction() + +function(cppfront_cmake_tests) + cmake_parse_arguments(PARSE_ARGV 0 ARG "" "SOURCE" "EXTRA_FLAGS") + + cmake_path(GET ARG_SOURCE STEM stem) + if (stem IN_LIST codegen_only_tests) + return() + endif () + + set(test_dir "${CMAKE_CURRENT_BINARY_DIR}/${stem}") + set(test_name "build/${stem}") + + configure_file("${ARG_SOURCE}" "${test_dir}/${ARG_SOURCE}" COPYONLY) + configure_file("cmake/CMakeLists.txt.in" "${test_dir}/CMakeLists.txt" @ONLY) + + add_test( + NAME "${test_name}" + COMMAND + "${CMAKE_CTEST_COMMAND}" + --build-and-test "${test_dir}" "${test_dir}/build" + --build-generator "${CMAKE_GENERATOR}" + -C Release + --build-options + "-DCMAKE_BUILD_TYPE=Release" + "-Dcppfront_DIR=${cppfront_DIR}" + "-Dcppfront-exe_DIR=${cppfront-exe_DIR}" + "-DCPPFRONT_FLAGS=${ARG_EXTRA_FLAGS}" + ) +endfunction() + +function(cppfront_tests) + cmake_parse_arguments(PARSE_ARGV 0 ARG "" "GROUP" "EXTRA_FLAGS") + + # Naughty, but needed for quick rebasing... :( + file( + GLOB sources + RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" + CONFIGURE_DEPENDS "${ARG_GROUP}-*.cpp2" + ) + + foreach (src IN LISTS sources) + cmake_path(REPLACE_EXTENSION src "cpp" OUTPUT_VARIABLE expected_file) + set(expected_file "${CMAKE_CURRENT_SOURCE_DIR}/test-results/${expected_file}") + + if (EXISTS "${expected_file}") + cppfront_cmake_tests( + SOURCE ${src} + EXTRA_FLAGS ${ARG_EXTRA_FLAGS} + ) + cppfront_command_tests( + SOURCE ${src} + EXPECTED_FILE ${expected_file} + EXTRA_FLAGS ${ARG_EXTRA_FLAGS} + ) + else () + cppfront_command_tests( + SOURCE ${src} + EXTRA_FLAGS ${ARG_EXTRA_FLAGS} + ) + endif () + endforeach () +endfunction() + +cppfront_tests(GROUP mixed) +cppfront_tests(GROUP pure2 EXTRA_FLAGS -p) diff --git a/regression-tests/cmake/CMakeLists.txt.in b/regression-tests/cmake/CMakeLists.txt.in new file mode 100644 index 0000000000..7d26306f24 --- /dev/null +++ b/regression-tests/cmake/CMakeLists.txt.in @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.23) +project(test-case) + +if (WIN32) + set(CMAKE_OBJECT_PATH_MAX 260) +endif () + +find_package(cppfront REQUIRED) + +add_executable(test-case "@ARG_SOURCE@") +target_compile_options( + test-case + PRIVATE + "$<$:/experimental:module>" +) diff --git a/test-all.sh b/test-all.sh new file mode 100755 index 0000000000..cb13a71dce --- /dev/null +++ b/test-all.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +set -e + +export CMAKE_CXX_COMPILER_LAUNCHER=ccache + +rm -rf build _local + +cmake -S . -B build/cppfront -DCMAKE_BUILD_TYPE=Release \ + "-DCMAKE_INSTALL_PREFIX=$PWD/_local" +cmake --build build/cppfront --target install + +cmake -S regression-tests -B build/regression-tests \ + -DCMAKE_BUILD_TYPE=Release "-DCMAKE_PREFIX_PATH=$PWD/_local" +cmake --build build/regression-tests + +( + cd build/regression-tests + ctest --output-on-failure -j "$(nproc)" +) + +rm -rf build _local From 29fa3b5db1ccceb507c386b978781d0473ac85e1 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Sat, 24 Sep 2022 13:39:06 -0400 Subject: [PATCH 3/7] Add GitHub Actions workflow --- .github/workflows/ci.yml | 46 ++++++++++++++++++++++++++++++++++++++++ .gitignore | 1 + 2 files changed, 47 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000000..316665b921 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,46 @@ +name: CI +on: [ push, pull_request, workflow_dispatch ] +jobs: + test: + name: test ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ + windows-latest, + # macos-latest, # cppfront is currently broken on AppleClang + ubuntu-latest, + ] + runs-on: ${{ matrix.os }} + steps: + # System set-up + - uses: actions/checkout@v2 + - uses: ilammy/msvc-dev-cmd@v1 + - uses: lukka/get-cmake@latest + + - name: Install GCC 11 + if: startsWith(matrix.os, 'ubuntu') + run: | + sudo apt-get update + sudo apt-get install -y gcc-11 g++-11 + echo "CC=gcc-11" >> $GITHUB_ENV + echo "CXX=g++-11" >> $GITHUB_ENV + + # Main cppfront library + - name: Configure cppfront + run: cmake -G Ninja -S . -B build/cppfront -DCMAKE_BUILD_TYPE=Release + - name: Build cppfront + run: cmake --build build/cppfront --config Release + - name: Install cppfront locally + run: cmake --install build/cppfront --config Release --prefix _local + + # Regression tests + - name: Configure regression tests + run: > + cmake -G Ninja -S regression-tests -B build/regression-tests -DCMAKE_BUILD_TYPE=Release + "-DCMAKE_PREFIX_PATH=${{github.workspace}}/_local" + - name: Build regression tests + run: cmake --build build/regression-tests --config Release + - name: Run regression tests + run: ctest --output-on-failure -C Release -j 4 + working-directory: build/regression-tests diff --git a/.gitignore b/.gitignore index 2f08ac4676..126220b7a8 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ .editorconfig build/ *local/ +.idea/ From e913b010c583b48894c77afe200f5f9848ce4ab6 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Tue, 27 Sep 2022 11:24:39 -0400 Subject: [PATCH 4/7] Respond to reviewer comments 1. Mark custom install dirs as advanced 2. Reduce concurrency in GHA workflow to match runner cores (2) --- .github/workflows/ci.yml | 2 +- CMakeLists.txt | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 316665b921..cc9b75a3bd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,5 +42,5 @@ jobs: - name: Build regression tests run: cmake --build build/regression-tests --config Release - name: Run regression tests - run: ctest --output-on-failure -C Release -j 4 + run: ctest --output-on-failure -C Release -j 2 working-directory: build/regression-tests diff --git a/CMakeLists.txt b/CMakeLists.txt index b54fcb6701..165d7ba54b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,6 +49,8 @@ if (CPPFRONT_INSTALL_RULES) set(CPPFRONT_INSTALL_EXE_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/cppfront-exe" CACHE STRING "Install location for cppfront's platform-specific CMake files") + mark_as_advanced(CPPFRONT_INSTALL_CMAKEDIR CPPFRONT_INSTALL_EXE_CMAKEDIR) + ## # Install rules for cppfront executable (which is naturally platform # dependent) From 67f4e93c7cc20ab33a28773955ef1368cc52f25a Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Tue, 27 Sep 2022 11:32:21 -0400 Subject: [PATCH 5/7] Prefix all targets with `cppfront_` --- CMakeLists.txt | 46 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 165d7ba54b..cf54f93647 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,40 +5,64 @@ project( VERSION 0.1.0 ) +## +# Project options + option( CPPFRONT_INSTALL_RULES "Enable install rules for cppfront" "${PROJECT_IS_TOP_LEVEL}" ) -add_executable(cppfront source/cppfront.cpp) -add_executable(cppfront::cppfront ALIAS cppfront) -target_compile_features(cppfront PRIVATE cxx_std_20) +## +# Target definition for cppfront executable + +add_executable(cppfront_cppfront source/cppfront.cpp) +add_executable(cppfront::cppfront ALIAS cppfront_cppfront) +set_target_properties( + cppfront_cppfront + PROPERTIES + OUTPUT_NAME cppfront + EXPORT_NAME cppfront +) + +target_compile_features(cppfront_cppfront PRIVATE cxx_std_20) target_sources( - cppfront + cppfront_cppfront PRIVATE FILE_SET HEADERS BASE_DIRS source FILES source/common.h source/lex.h source/load.h source/parse.h source/sema.h ) -add_library(cpp2util INTERFACE) -add_library(cppfront::cpp2util ALIAS cpp2util) -target_compile_features(cpp2util INTERFACE cxx_std_20) +## +# Target definition for cpp2util runtime library + +add_library(cppfront_cpp2util INTERFACE) +add_library(cppfront::cpp2util ALIAS cppfront_cpp2util) +set_target_properties(cppfront_cpp2util PROPERTIES EXPORT_NAME cpp2util) + +target_compile_features(cppfront_cpp2util INTERFACE cxx_std_20) target_include_directories( - cpp2util INTERFACE "$" + cppfront_cpp2util INTERFACE "$" ) target_sources( - cpp2util + cppfront_cpp2util INTERFACE FILE_SET HEADERS BASE_DIRS include FILES include/cpp2util.h ) +## +# Enable cpp2 autodetection for add_subdirectory users + if (NOT PROJECT_IS_TOP_LEVEL) get_directory_property(_CPPFRONT_MAGIC_DIR PARENT_DIRECTORY) include(cmake/CppfrontHelpers.cmake) endif () +## +# Installation and CMake packaging logic + if (CPPFRONT_INSTALL_RULES) include(GNUInstallDirs) include(CMakePackageConfigHelpers) @@ -56,7 +80,7 @@ if (CPPFRONT_INSTALL_RULES) # dependent) install( - TARGETS cppfront + TARGETS cppfront_cppfront EXPORT cppfront-exe-targets COMPONENT cppfront ) @@ -94,7 +118,7 @@ if (CPPFRONT_INSTALL_RULES) # which are platform-independent install( - TARGETS cpp2util + TARGETS cppfront_cpp2util EXPORT cppfront-targets FILE_SET HEADERS COMPONENT cppfront From 0d8f8fcb675e0caa99f9ebc4e32c977839e24ba6 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Tue, 27 Sep 2022 13:15:16 -0400 Subject: [PATCH 6/7] Add cppfront_generate_cpp by analogy to Protobuf --- cmake/CppfrontHelpers.cmake | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/cmake/CppfrontHelpers.cmake b/cmake/CppfrontHelpers.cmake index 69ddb86cb3..82c08a4e44 100644 --- a/cmake/CppfrontHelpers.cmake +++ b/cmake/CppfrontHelpers.cmake @@ -54,6 +54,15 @@ function(_cppfront_generate_source src out) set("${out}" "${out_file}" PARENT_SCOPE) endfunction() +function(cppfront_generate_cpp srcs) + set(cpp2srcs "") + foreach (src IN LISTS ARGN) + _cppfront_generate_source("${src}" cpp2) + list(APPEND cpp2srcs "${cpp2}") + endforeach () + set("${srcs}" "${cpp2srcs}" PARENT_SCOPE) +endfunction() + function(cppfront_enable) cmake_parse_arguments(PARSE_ARGV 0 ARG "" "" "TARGETS") @@ -63,24 +72,22 @@ function(cppfront_enable) if (sources) target_link_libraries("${tgt}" PRIVATE cppfront::cpp2util) + cppfront_generate_cpp(cpp1sources ${sources}) + target_sources("${tgt}" PRIVATE ${cpp1sources}) endif () - - foreach (src IN LISTS sources) - _cppfront_generate_source("${src}" out_path) - target_sources("${tgt}" PRIVATE "${out_path}") - endforeach () endforeach () endfunction() -function(_cppfront_enable_dir) - get_property(targets DIRECTORY . PROPERTY BUILDSYSTEM_TARGETS) - cppfront_enable(TARGETS ${targets}) -endfunction() - if (NOT CPPFRONT_NO_MAGIC) + function(_cppfront_enable_dir) + get_property(targets DIRECTORY . PROPERTY BUILDSYSTEM_TARGETS) + cppfront_enable(TARGETS ${targets}) + endfunction() + if (NOT _CPPFRONT_MAGIC_DIR) set(_CPPFRONT_MAGIC_DIR "${CMAKE_CURRENT_SOURCE_DIR}") endif () + message(VERBOSE "Enabling cppfront for all targets in ${_CPPFRONT_MAGIC_DIR}") cmake_language(DEFER DIRECTORY "${_CPPFRONT_MAGIC_DIR}" CALL _cppfront_enable_dir) endif () From be6d737e35fee26bf5e12a350b0e925cbfc54684 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Tue, 27 Sep 2022 15:41:46 -0400 Subject: [PATCH 7/7] Add CPPFRONT_NO_SYSTEM option In builds using FetchContent or add_subdirectory, the cpp2util library will have its headers marked as SYSTEM to suppress warnings caused by code in cpp2util.h. This can be overridden by setting CPPFRONT_NO_SYSTEM to ON. --- CMakeLists.txt | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cf54f93647..19137df98f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,9 +8,27 @@ project( ## # Project options -option( - CPPFRONT_INSTALL_RULES "Enable install rules for cppfront" "${PROJECT_IS_TOP_LEVEL}" +include(CMakeDependentOption) + +cmake_dependent_option( + CPPFRONT_INSTALL_RULES "Include install rules for cppfront" "${PROJECT_IS_TOP_LEVEL}" + "NOT CMAKE_SKIP_INSTALL_RULES" OFF +) + +cmake_dependent_option( + CPPFRONT_NO_SYSTEM "Do not mark cpp2 runtime headers as SYSTEM" OFF + "NOT PROJECT_IS_TOP_LEVEL" ON ) +mark_as_advanced(CPPFRONT_NO_SYSTEM) + +## +# Compute option-derived constants + +if (CPPFRONT_NO_SYSTEM) + set(_cppfront_SYSTEM "") +else () + set(_cppfront_SYSTEM SYSTEM) +endif () ## # Target definition for cppfront executable @@ -42,7 +60,7 @@ set_target_properties(cppfront_cpp2util PROPERTIES EXPORT_NAME cpp2util) target_compile_features(cppfront_cpp2util INTERFACE cxx_std_20) target_include_directories( - cppfront_cpp2util INTERFACE "$" + cppfront_cpp2util ${_cppfront_SYSTEM} INTERFACE "$" ) target_sources( cppfront_cpp2util