#StackBounty: #compiler #cmake cmake for a toy programming language

Bounty: 150

I have very little experience with cmake, this is really the first time I used it for a project. In the past I used some autotools and recently mostly bazel. I would appreciate some suggestions how to better structure the code. For example during compilation I noticed that the same targets get compiled multiple times, which ideally I would like to avoid.

cmake_minimum_required(VERSION 3.10)
project(schwifty)

set(CMAKE_CXX_STANDARD 14)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DELPP_FEATURE_CRASH_LOG")

set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/out)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/out)

find_package(PythonInterp 3.6 REQUIRED)

file(MAKE_DIRECTORY downloads external)

################################################################################
# Easylogging++
################################################################################
if(EXISTS "external/easyloggingpp")
else()
file(MAKE_DIRECTORY external/easyloggingpp)
file(DOWNLOAD
        https://github.com/muflihun/easyloggingpp/archive/v9.96.4.zip
        downloads/easyloggingpp.zip)
execute_process(COMMAND unzip downloads/easyloggingpp.zip -d downloads)
file(GLOB easyloggingpp_files downloads/easyloggingpp-9.96.4/src/easylogging++.*)
file(COPY ${easyloggingpp_files} DESTINATION external/easyloggingpp)
endif()

set(ast ast.h ast.cc)
set(codegen codegen.h codegen.cc)
set(functions functions.h functions.cc)
set(parser parser.h parser.cc)

include_directories(external/easyloggingpp)
set(easyloggingpp external/easyloggingpp/easylogging++.cc)

set(SOURCE_FILES
        ast_compare_visitor.cc
        ast_compare_visitor.h
        classes.cc
        classes.h
        compilation_context.cc
        compilation_context.h
        common.h
        errors.h
        errors.cc
        expression_type_visitor.cc
        expression_type_visitor.h
        functions.cc
        functions.h
        jit.cc
        jit.h
        lexer.cc
        lexer.h
        lexer_common.cc
        lexer_common.h
        runtime.h
        runtime.cc
        utils.h
        utils.cc
        type.cc
        type.h
        type_inference_visitor.cc
        type_inference_visitor.h
        enum.cc
        enum.h
        type_inference.cc
        type_inference.h
        operators.cc
        operators.h
        symbol_visitor.cc
        symbol_visitor.h)

add_library(sources ${SOURCE_FILES})

find_package(LLVM REQUIRED CONFIG)

message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")

include_directories(${LLVM_INCLUDE_DIRS})
add_definitions(${LLVM_DEFINITIONS})

llvm_map_components_to_libnames(llvm_libs all)

find_package(FMT REQUIRED CONFIG)

add_executable(schwifty
        schwifty.cc
        ${ast}
        ${codegen}
        ${easyloggingpp}
        ${parser})

target_link_libraries(schwifty ${llvm_libs})
target_link_libraries(schwifty fmt::fmt)
target_link_libraries(schwifty sources)

################################################################################
# Testing
################################################################################

enable_testing()
find_package(gtest REQUIRED)

include_directories(${GTEST_INCLUDE_DIRS})

add_executable(codegen_test codegen_test.cc ${ast} ${codegen} ${easyloggingpp}
        ${functions} ${parser})
target_link_libraries(codegen_test ${GTEST_BOTH_LIBRARIES})
target_link_libraries(codegen_test ${llvm_libs})
target_link_libraries(codegen_test fmt::fmt)
target_link_libraries(codegen_test sources)
add_test(codegen_test COMMAND out/codegen_test)

add_executable(lexer_test lexer_test.cc ${ast} ${codegen} ${easyloggingpp}
        ${functions} ${parser})
target_link_libraries(lexer_test ${GTEST_BOTH_LIBRARIES})
target_link_libraries(lexer_test ${llvm_libs})
target_link_libraries(lexer_test fmt::fmt)
target_link_libraries(lexer_test sources)
add_test(lexer_test COMMAND out/lexer_test)

add_executable(parser_test parser_test.cc ${ast} ${codegen} ${easyloggingpp}
        ${functions} ${parser})
target_link_libraries(parser_test ${GTEST_BOTH_LIBRARIES})
target_link_libraries(parser_test ${llvm_libs})
target_link_libraries(parser_test fmt::fmt)
target_link_libraries(parser_test sources)
add_test(parser_test COMMAND out/parser_test)

add_executable(type_test type_test.cc ${ast} ${codegen} ${easyloggingpp}
        ${functions} ${parser})
target_link_libraries(type_test ${GTEST_BOTH_LIBRARIES})
target_link_libraries(type_test ${llvm_libs})
target_link_libraries(type_test fmt::fmt)
target_link_libraries(type_test sources)
add_test(type_test COMMAND out/type_test)

add_executable(type_inference_test type_inference_test.cc ${ast} ${codegen}
        ${easyloggingpp} ${functions} ${parser})
target_link_libraries(type_inference_test ${GTEST_BOTH_LIBRARIES})
target_link_libraries(type_inference_test ${llvm_libs})
target_link_libraries(type_inference_test fmt::fmt)
target_link_libraries(type_inference_test sources)
add_test(type_inference_test COMMAND ./out/type_inference_test)

add_test(NAME end_to_end_tests WORKING_DIRECTORY ${CTEST_SOURCE_DIRECTORY}
        COMMAND ${PYTHON_EXECUTABLE} ${CTEST_SOURCE_DIRECTORY}/end_to_end_tests.py)


Get this bounty!!!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.