# # Copyright (c) 2020, Trail of Bits, Inc. # # This source code is licensed in accordance with the terms specified in # the LICENSE file found in the root directory of this source tree. # cmake_minimum_required(VERSION 3.21) project(pasta LANGUAGES C CXX) include(GNUInstallDirs) include("cmake/options.cmake") include("${PROJECT_SOURCE_DIR}/cmake/settings.cmake") include("${PROJECT_SOURCE_DIR}/cmake/utils.cmake") include("${PROJECT_SOURCE_DIR}/cmake/ccache.cmake") list(PREPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/modules") # -------------------------------------------- # build-time options ------------------------- # -------------------------------------------- option(PASTA_ENABLE_INSTALL "Set to OFF to disable installing pasta." ON) if(PASTA_ENABLE_INSTALL) include("cmake/packaging.cmake") endif(PASTA_ENABLE_INSTALL) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # -------------------------------------------- # toolchain-specific warning options --------- # -------------------------------------------- set(GNULIKE_COMPILER_LIST "Clang" "AppleClang" "GNU") if(CMAKE_CXX_COMPILER_ID IN_LIST GNULIKE_COMPILER_LIST) set(CXX_WARNING_OPTIONS -Wall -pedantic -Wconversion -Wno-unknown-pragmas) set(CXX_WARNINGS_AS_ERRORS_OPTION -Werror) elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") set(CXX_WARNING_OPTIONS /W4) set(CXX_WARNINGS_AS_ERRORS_OPTION /WX) else() set(CXX_WARNING_OPTIONS) set(CXX_WARNINGS_AS_ERRORS_OPTION) message(WARNING "Unsupported C++ compiler '${CMAKE_CXX_COMPILER_ID}'; build may not work right!") endif() # -------------------------------------------------- # `pasta_cxx_settings` for global build options ---- # -------------------------------------------------- add_library(pasta_cxx_settings INTERFACE) target_compile_features(pasta_cxx_settings INTERFACE cxx_std_20) set_target_properties(pasta_cxx_settings PROPERTIES CXX_EXTENSIONS OFF) set_target_properties(pasta_cxx_settings PROPERTIES POSITION_INDEPENDENT_CODE ON) target_include_directories(pasta_cxx_settings INTERFACE $ $ ) target_compile_options(pasta_cxx_settings INTERFACE ${CXX_WARNING_OPTIONS}) option(PASTA_WARNINGS_AS_ERRORS "Set to ON to enalbe -Werror." OFF) if(PASTA_WARNINGS_AS_ERRORS) target_compile_options(pasta_cxx_settings INTERFACE ${CXX_WARNINGS_AS_ERRORS_OPTION}) endif() option(PASTA_BOOTSTRAP_MACROS "Set to ON to enable type bootstrapping macros. Developer option only." OFF) option(PASTA_BOOTSTRAP_TYPES "Set to ON to enable type bootstrapping types. Developer option only." OFF) if(PASTA_BOOTSTRAP_MACROS OR PASTA_BOOTSTRAP_TYPES) target_compile_definitions(pasta_cxx_settings INTERFACE -DPASTA_IN_BOOTSTRAP) endif() find_package(Filesystem REQUIRED COMPONENTS Final Experimental) if(Filesystem_FOUND) message(STATUS "Found filesystem: ${CXX_FILESYSTEM_HEADER}") endif() target_link_libraries(pasta_cxx_settings INTERFACE std::filesystem) # -------------------------------------------- # Clang/LLVM dependencies -------------------- # -------------------------------------------- add_subdirectory(vendor) find_package(LLVM CONFIG REQUIRED) find_package(Clang CONFIG REQUIRED) add_library(pasta_thirdparty_llvm INTERFACE) if(PASTA_ENABLE_TESTING) list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}") include(AddLLVM) # For LLVM lit test suite stuff. endif(PASTA_ENABLE_TESTING) target_link_libraries(pasta_thirdparty_llvm INTERFACE clangAST clangASTMatchers clangBasic clangCodeGen clangDriver clangFrontend clangSerialization clangTooling ) target_include_directories(pasta_thirdparty_llvm INTERFACE "$" $ ) # TODO(pag): Not sure if `Clang_DEFINITIONS` or `CLANG_DEFINITIONS`. target_compile_definitions(pasta_thirdparty_llvm INTERFACE ${LLVM_DEFINITIONS} ${Clang_DEFINITIONS} ) if(PASTA_ENABLE_INSTALL) export(PACKAGE "${PROJECT_NAME}") set(cmake_install_dir "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") include(CMakePackageConfigHelpers) configure_package_config_file("${PROJECT_NAME}Config.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" INSTALL_DESTINATION "${cmake_install_dir}" ) install( FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" "${PROJECT_SOURCE_DIR}/cmake/modules/FindFilesystem.cmake" DESTINATION "${cmake_install_dir}" ) install(EXPORT "${PROJECT_NAME}Targets" DESTINATION "${cmake_install_dir}" NAMESPACE "${PROJECT_NAME}::" ) endif(PASTA_ENABLE_INSTALL) # -------------------------------------------- # Configure lib/Compiler/Host.h -------------- # -------------------------------------------- set(PASTA_DUMMY_SOURCE_FILE "${CMAKE_CURRENT_BINARY_DIR}/pasta.x") set(PASTA_CC_VERSION_OUT_FILE "${CMAKE_CURRENT_BINARY_DIR}/pasta.cc.version") set(PASTA_CXX_VERSION_OUT_FILE "${CMAKE_CURRENT_BINARY_DIR}/pasta.cxx.version") if(CMAKE_C_COMPILER_ID MATCHES "Clang") if("x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC") set(PASTA_C_COMPILER_ID 3) # clang-cl elseif(CMAKE_C_COMPILER_ID STREQUAL "AppleClang") set(PASTA_C_COMPILER_ID 2) # Apple's Clang else() set(PASTA_C_COMPILER_ID 1) # LLVM Clang. endif() elseif (CMAKE_C_COMPILER_ID STREQUAL "MSVC") set(PASTA_C_COMPILER_ID 4) # cl elseif (CMAKE_C_COMPILER_ID STREQUAL "GNU") set(PASTA_C_COMPILER_ID 5) # g++ else() set(PASTA_C_COMPILER_ID 0) # Unknown. endif() if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") if("x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC") set(PASTA_CXX_COMPILER_ID 3) # clang-cl elseif(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") set(PASTA_CXX_COMPILER_ID 2) # Apple's Clang else() set(PASTA_CXX_COMPILER_ID 1) # LLVM Clang. endif() elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") set(PASTA_CXX_COMPILER_ID 4) # cl elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") set(PASTA_CXX_COMPILER_ID 5) # g++ else() set(PASTA_CXX_COMPILER_ID 0) # Unknown. endif() set(HOST_H_IN_FILE "${PROJECT_SOURCE_DIR}/lib/Compile/Host.h.in") set(HOST_H_FILE "${CMAKE_CURRENT_BINARY_DIR}/lib/Compile/Host.h") get_compiler_paths( COMPILER "${CMAKE_C_COMPILER}" OUT_VAR CSTR_HOST_CC_VERSION_INFO ARGS -x c -std=c23 ) get_compiler_paths( COMPILER "${CMAKE_C_COMPILER}" OUT_VAR CSTR_HOST_CC_VERSION_INFO_FAKE_SYSROOT ARGS -x c -std=c23 -isysroot "/xyz" -Wno-missing-sysroot ) get_compiler_paths( COMPILER "${CMAKE_CXX_COMPILER}" OUT_VAR CSTR_HOST_CXX_VERSION_INFO ARGS -x c++ -std=c++20 ) get_compiler_paths( COMPILER "${CMAKE_CXX_COMPILER}" OUT_VAR CSTR_HOST_CXX_VERSION_INFO_FAKE_SYSROOT ARGS -x c++ -std=c++20 -isysroot "/xyz" -Wno-missing-sysroot ) configure_file("${HOST_H_IN_FILE}" "${HOST_H_FILE}" @ONLY) # -------------------------------------------- # Main build targets ------------------------- # -------------------------------------------- set(util_HEADERS "include/pasta/Util/ArgumentVector.h" "include/pasta/Util/Compiler.h" "include/pasta/Util/Error.h" "include/pasta/Util/File.h" "include/pasta/Util/FileManager.h" "include/pasta/Util/FileSystem.h" "include/pasta/Util/Init.h" "include/pasta/Util/Result.h" ) add_library(pasta_util STATIC ${util_HEADERS} "lib/Util/FileManager.h" "lib/Util/ArgumentVector.cpp" "lib/Util/Error.cpp" "lib/Util/File.cpp" "lib/Util/FileManager.cpp" "lib/Util/FileSystem.cpp" "lib/Util/Init.cpp" ) target_link_libraries(pasta_util PUBLIC pasta_cxx_settings pasta_thirdparty_llvm ) set_target_properties( pasta_util PROPERTIES POSITION_INDEPENDENT_CODE YES ) set(ast_HEADERS "include/pasta/AST/AST.h" "include/pasta/AST/Attr.h" "include/pasta/AST/AttrManual.h" "include/pasta/AST/Decl.h" "include/pasta/AST/DeclHead.h" "include/pasta/AST/DeclTail.h" "include/pasta/AST/Forward.h" "include/pasta/AST/Macro.h" "include/pasta/AST/Printer.h" "include/pasta/AST/Stmt.h" "include/pasta/AST/StmtManual.h" "include/pasta/AST/Token.h" "include/pasta/AST/Type.h" "include/pasta/AST/TypeManual.h" "include/pasta/Compile/Command.h" "include/pasta/Compile/Compiler.h" "include/pasta/Compile/Job.h" ) add_library(pasta_compiler STATIC ${ast_HEADERS} "lib/AST/AlignTokens.cpp" "lib/AST/AST.cpp" "lib/AST/Attr.cpp" "lib/AST/AttrManual.cpp" "lib/AST/Bounds.cpp" "lib/AST/Builder.cpp" "lib/AST/Builder.h" "lib/AST/Decl.cpp" "lib/AST/DeclHead.cpp" "lib/AST/Macro.h" "lib/AST/Macro.cpp" "lib/AST/Stmt.cpp" "lib/AST/StmtManual.cpp" "lib/AST/Token.cpp" "lib/AST/Token.h" "lib/AST/Type.cpp" "lib/AST/TypeManual.cpp" "lib/AST/Util.h" "lib/AST/Printer/DeclPrinter.cpp" "lib/AST/Printer/DeclStmtPrinter.h" "lib/AST/Printer/NestedNameSpecifier.cpp" "lib/AST/Printer/Printer.cpp" "lib/AST/Printer/Printer.h" "lib/AST/Printer/raw_ostream.h" "lib/AST/Printer/StmtPrinter.cpp" "lib/AST/Printer/TypePrinter.cpp" "${HOST_H_FILE}" "lib/Compile/Builtins.cpp" "lib/Compile/BuiltinsPPC.h" "lib/Compile/BuiltinsX86.h" "lib/Compile/Command.h" "lib/Compile/Compiler.h" "lib/Compile/FileSystem.h" "lib/Compile/Job.h" "lib/Compile/PatchedMacroTracker.h" "lib/Compile/ParsedFileTracker.h" "lib/Compile/SplitTokenTracker.h" "lib/Compile/Builtins.cpp" "lib/Compile/Command.cpp" "lib/Compile/Compiler.cpp" "lib/Compile/Create.cpp" "lib/Compile/Diagnostic.cpp" "lib/Compile/FileSystem.cpp" "lib/Compile/Job.cpp" "lib/Compile/ParsedFileTracker.cpp" "lib/Compile/PatchedMacroTracker.cpp" "lib/Compile/Preprocess.cpp" "lib/Compile/Run.cpp" "lib/Compile/SplitTokenTracker.cpp" ) if(PASTA_DISABLE_HOST_COMPILER) target_compile_definitions(pasta_compiler PRIVATE -DPASTA_DISABLE_HOST_COMPILER) endif() set_target_properties( pasta_compiler PROPERTIES VISIBILITY_INLINES_HIDDEN YES POSITION_INDEPENDENT_CODE YES ) target_include_directories(pasta_compiler PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/lib/Compile" ) target_link_libraries(pasta_compiler PRIVATE pasta_cxx_settings pasta_thirdparty_llvm pasta_util ) add_library("pasta" INTERFACE) target_link_libraries("pasta" INTERFACE pasta_cxx_settings pasta_thirdparty_llvm pasta_util pasta_compiler ) if(PASTA_BOOTSTRAP_MACROS OR PASTA_BOOTSTRAP_TYPES) # -------------------------------------------- # Add bootstrap library ---------------------- # -------------------------------------------- add_library(pasta_bootstrap STATIC "include/pasta/AST/DeclBootstrap.h" "include/pasta/AST/StmtBootstrap.h" "include/pasta/AST/TypeBootstrap.h" "lib/AST/DeclBootstrap.cpp" "lib/AST/StmtBootstrap.cpp" "lib/AST/TypeBootstrap.cpp" ) target_include_directories(pasta_bootstrap PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/lib/Compile" ) target_link_libraries(pasta_bootstrap PRIVATE pasta_cxx_settings pasta_thirdparty_llvm pasta_util ) target_link_libraries("pasta" INTERFACE pasta_bootstrap ) endif() # --------------------------------------------------- # Configure bootstrap header files with source paths. # --------------------------------------------------- set(PASTA_INCLUDE_SOURCE_PATH "${PROJECT_SOURCE_DIR}/include") set(PASTA_BINARY_PATH "${CMAKE_CURRENT_BINARY_DIR}") set(PASTA_BIN_BOOTSTRAP_MACROS_MACRO_GENERATOR_CPP_PATH "${PROJECT_SOURCE_DIR}/bin/BootstrapMacros/MacroGenerator.cpp") set(PASTA_BIN_BOOTSTRAP_TYPES_GENERATED_H_PATH "${PROJECT_SOURCE_DIR}/bin/BootstrapTypes/Generated.h") set(PASTA_INCLUDE_AST_FORWARD_H_PATH "${PROJECT_SOURCE_DIR}/include/pasta/AST/Forward.h") set(PASTA_INCLUDE_AST_DECL_H_PATH "${PROJECT_SOURCE_DIR}/include/pasta/AST/Decl.h") set(PASTA_SRC_AST_DECL_CPP_PATH "${PROJECT_SOURCE_DIR}/lib/AST/Decl.cpp") set(PASTA_INCLUDE_AST_TYPE_H_PATH "${PROJECT_SOURCE_DIR}/include/pasta/AST/Type.h") set(PASTA_SRC_AST_TYPE_CPP_PATH "${PROJECT_SOURCE_DIR}/lib/AST/Type.cpp") set(PASTA_INCLUDE_AST_STMT_H_PATH "${PROJECT_SOURCE_DIR}/include/pasta/AST/Stmt.h") set(PASTA_SRC_AST_STMT_CPP_PATH "${PROJECT_SOURCE_DIR}/lib/AST/Stmt.cpp") set(PASTA_INCLUDE_AST_ATTR_H_PATH "${PROJECT_SOURCE_DIR}/include/pasta/AST/Attr.h") set(PASTA_SRC_AST_ATTR_CPP_PATH "${PROJECT_SOURCE_DIR}/lib/AST/Attr.cpp") set(PASTA_PYTHON_BINDINGS_PATH "${PROJECT_SOURCE_DIR}/bindings/python/src/AST") set(BOOTSTRAP_CONFIG_H_IN "${PROJECT_SOURCE_DIR}/BootstrapConfig.h.in") set(BOOTSTRAP_CONFIG_H "${CMAKE_CURRENT_BINARY_DIR}/BootstrapConfig.h") configure_file("${BOOTSTRAP_CONFIG_H_IN}" "${BOOTSTRAP_CONFIG_H}" @ONLY) # -------------------------------------------- # Bootstrap build targets -------------------- # -------------------------------------------- add_library(pasta_bootstrap_config INTERFACE) add_dependencies(pasta_bootstrap_config "${BOOTSTRAP_CONFIG_H}") target_include_directories(pasta_bootstrap_config INTERFACE "${CMAKE_CURRENT_BINARY_DIR}" ) if(NOT (PASTA_BOOTSTRAP_MACROS OR PASTA_BOOTSTRAP_TYPES)) add_subdirectory(bindings) endif() if(PASTA_ENABLE_INSTALL AND NOT PASTA_BOOTSTRAP_MACROS AND NOT PASTA_BOOTSTRAP_TYPES) if(PASTA_ENABLE_PY_BINDINGS) set(PASTA_PY_BINDING_LIB_NAME "pypasta") endif() install( DIRECTORY "include/pasta" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" ) install( TARGETS "pasta" "pasta_compiler" "pasta_util" "pasta_thirdparty_llvm" "pasta_cxx_settings" ${PASTA_PY_BINDING_LIB_NAME} EXPORT "${PROJECT_NAME}Targets" RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" ) endif() option(PASTA_ENABLE_TOOLS "Set to OFF to disable default building of tools." ON) if(PASTA_ENABLE_TOOLS) add_subdirectory(bin) endif(PASTA_ENABLE_TOOLS) option(PASTA_ENABLE_TESTING "Set to ON to enable building test code." OFF) if(PASTA_ENABLE_TESTING) enable_testing() add_subdirectory(test) endif(PASTA_ENABLE_TESTING)