cmake for a toy programming language












2












$begingroup$


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)









share|improve this question









$endgroup$

















    2












    $begingroup$


    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)









    share|improve this question









    $endgroup$















      2












      2








      2


      1



      $begingroup$


      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)









      share|improve this question









      $endgroup$




      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)






      compiler cmake






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Jun 10 '18 at 20:45









      gruszczygruszczy

      5518




      5518






















          2 Answers
          2






          active

          oldest

          votes


















          1












          $begingroup$

          I'm by no means a professional CMake user, I try to follow best practices though and have seen many talks and articles about modern CMake best practices, so lets go through your CMakeLists.



          set(CMAKE_CXX_STANDARD 14)


          This is generally frowned upon for two different reasons. First and most important, you set this configuration globally for every target you create or import through add_subdirectory. In modern CMake best practices you should always prefer target_ functions whenever possible to configure exactly the target which needs the configuration instead of setting it globally.
          Second, you should not need to set the C++ standard directly, instead you should select features which you need to compile your project and let CMake decide the standard. See target_compile_features.



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


          Same problem as previously, use target_compile_definitions(mytarget PUBLIC ELPP_FEATURE_CRASH_LOG)



          #
          # 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()


          This looks like a messy hack to pull in a dependency. If this dependency is required to build your project you should probably add it as a subrepository to your own git source repository and use it using add_subdirectory (assuming it's a CMake project). Alternatively, there is also the ExternalProject module which exists for this sole reason, to pull in and compile external dependencies.



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


          You're configuring globally again with include_directories, use target_include_directories instead. Also, I'd really consider splitting up your CMakeLists file, there is too much going on. Subdivide your project repository to subdirectories, one per library, and then use add_subdirectory to pull in all the libraries you need.



          find_package(gtest REQUIRED)
          include_directories(${GTEST_INCLUDE_DIRS})


          You're setting include directories globally again. Actually, you don't even need to set the directories at all. target_link_libraries does a lot more than linking. It probably should've called differently. Since gtest exports a target with it's INTERFACE_INCLUDE_DIRECTORIES set up, solely linking (target_link_libraries) to gtest sets up include directories automatically for the target.



          If you follow best practices and set all configurations with target_ functions then all you need to pull in a library should be a sole target_link_library since all other configurations (compiler features, include directories, ...) are automatically pulled in, given they're either set PUBLIC or INTERFACE on this library. As I said, target_link_library does a lot more than just linking, it's name is very misleading.
          A perfect example is the fmt package you're using. All you're doing is find_package(FMT REQUIRED CONFIG) and target_link_libraries(mytarget fmt::fmt) and everything else to use this package is set up by the target_link_libraries command since the fmt package exports all its own requirements and include paths through its target.



          I'm pretty sure I missed a few things but I hope these pointers help you to get started.





          share









          $endgroup$













          • $begingroup$
            Thanks a lot for suggestions!
            $endgroup$
            – gruszczy
            27 secs ago



















          0












          $begingroup$

          Instead of using set for source files, which made them get recompiled multiple times, I switched add_library and now it builds everything much faster. No more unnecessarily compiling the same file again.



          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()

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

          #
          # Local lib targets
          #

          add_library(ast ast.h ast.cc)

          add_library(ast_compare_visitor ast_compare_visitor.h ast_compare_visitor.cc)

          add_library(classes classes.h classes.cc)

          add_library(codegen
          codegen.h
          codegen.cc
          codegen_common.h
          codegen_common.cc
          expression_type_visitor.cc
          expression_type_visitor.h)

          add_library(common common.h utils.h utils.cc)

          add_library(compilation_context
          compilation_context.h
          compilation_context.cc
          enum.h
          enum.cc
          errors.h
          errors.cc
          operators.h
          operators.cc
          type.h
          type.cc)

          add_library(functions functions.h functions.cc)

          add_library(jit jit.cc jit.h)

          add_library(lexer lexer.cc lexer.h lexer_common.cc lexer_common.h)

          add_library(parser parser.h parser.cc)

          add_library(runtime runtime.cc runtime.h)

          add_library(type_inference
          type_inference.h
          type_inference.cc
          symbol_visitor.cc
          symbol_visitor.h
          type_inference_visitor.cc
          type_inference_visitor.h)

          #
          # External lib targets
          #

          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)

          #
          # Schwifty main executable
          #

          add_executable(schwifty schwifty.cc)
          target_link_libraries(schwifty
          ${llvm_libs}
          ast
          classes
          codegen
          common
          compilation_context
          easyloggingpp
          fmt::fmt
          functions
          lexer
          parser
          runtime
          type_inference)

          #
          # Testing
          #

          enable_testing()
          find_package(gtest REQUIRED)

          include_directories(${GTEST_INCLUDE_DIRS})

          add_executable(codegen_test codegen_test.cc)
          target_link_libraries(codegen_test
          ${GTEST_BOTH_LIBRARIES}
          ${llvm_libs}
          easyloggingpp
          ast
          classes
          codegen
          common
          compilation_context
          fmt::fmt
          functions
          jit
          lexer
          parser
          runtime
          type_inference)
          add_test(codegen_test COMMAND out/codegen_test)

          add_executable(lexer_test lexer_test.cc)
          target_link_libraries(lexer_test
          ${GTEST_BOTH_LIBRARIES}
          ast
          common
          compilation_context
          easyloggingpp
          functions
          lexer
          parser
          fmt::fmt)
          add_test(lexer_test COMMAND out/lexer_test)

          add_executable(parser_test parser_test.cc)
          target_link_libraries(parser_test
          ${GTEST_BOTH_LIBRARIES}
          ast
          ast_compare_visitor
          compilation_context
          common
          easyloggingpp
          functions
          lexer
          parser
          fmt::fmt)
          add_test(parser_test COMMAND out/parser_test)

          add_executable(type_test type_test.cc)
          target_link_libraries(type_test
          ${GTEST_BOTH_LIBRARIES}
          ast
          common
          compilation_context
          easyloggingpp
          functions
          lexer
          parser)
          add_test(type_test COMMAND out/type_test)

          add_executable(type_inference_test type_inference_test.cc)
          target_link_libraries(type_inference_test
          ${GTEST_BOTH_LIBRARIES}
          easyloggingpp
          ast
          classes
          common
          compilation_context
          functions
          fmt::fmt
          lexer
          parser
          runtime
          type_inference)
          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} end_to_end_tests.py)





          share|improve this answer









          $endgroup$













            Your Answer





            StackExchange.ifUsing("editor", function () {
            return StackExchange.using("mathjaxEditing", function () {
            StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
            StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
            });
            });
            }, "mathjax-editing");

            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "196"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: false,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f196243%2fcmake-for-a-toy-programming-language%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            1












            $begingroup$

            I'm by no means a professional CMake user, I try to follow best practices though and have seen many talks and articles about modern CMake best practices, so lets go through your CMakeLists.



            set(CMAKE_CXX_STANDARD 14)


            This is generally frowned upon for two different reasons. First and most important, you set this configuration globally for every target you create or import through add_subdirectory. In modern CMake best practices you should always prefer target_ functions whenever possible to configure exactly the target which needs the configuration instead of setting it globally.
            Second, you should not need to set the C++ standard directly, instead you should select features which you need to compile your project and let CMake decide the standard. See target_compile_features.



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


            Same problem as previously, use target_compile_definitions(mytarget PUBLIC ELPP_FEATURE_CRASH_LOG)



            #
            # 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()


            This looks like a messy hack to pull in a dependency. If this dependency is required to build your project you should probably add it as a subrepository to your own git source repository and use it using add_subdirectory (assuming it's a CMake project). Alternatively, there is also the ExternalProject module which exists for this sole reason, to pull in and compile external dependencies.



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


            You're configuring globally again with include_directories, use target_include_directories instead. Also, I'd really consider splitting up your CMakeLists file, there is too much going on. Subdivide your project repository to subdirectories, one per library, and then use add_subdirectory to pull in all the libraries you need.



            find_package(gtest REQUIRED)
            include_directories(${GTEST_INCLUDE_DIRS})


            You're setting include directories globally again. Actually, you don't even need to set the directories at all. target_link_libraries does a lot more than linking. It probably should've called differently. Since gtest exports a target with it's INTERFACE_INCLUDE_DIRECTORIES set up, solely linking (target_link_libraries) to gtest sets up include directories automatically for the target.



            If you follow best practices and set all configurations with target_ functions then all you need to pull in a library should be a sole target_link_library since all other configurations (compiler features, include directories, ...) are automatically pulled in, given they're either set PUBLIC or INTERFACE on this library. As I said, target_link_library does a lot more than just linking, it's name is very misleading.
            A perfect example is the fmt package you're using. All you're doing is find_package(FMT REQUIRED CONFIG) and target_link_libraries(mytarget fmt::fmt) and everything else to use this package is set up by the target_link_libraries command since the fmt package exports all its own requirements and include paths through its target.



            I'm pretty sure I missed a few things but I hope these pointers help you to get started.





            share









            $endgroup$













            • $begingroup$
              Thanks a lot for suggestions!
              $endgroup$
              – gruszczy
              27 secs ago
















            1












            $begingroup$

            I'm by no means a professional CMake user, I try to follow best practices though and have seen many talks and articles about modern CMake best practices, so lets go through your CMakeLists.



            set(CMAKE_CXX_STANDARD 14)


            This is generally frowned upon for two different reasons. First and most important, you set this configuration globally for every target you create or import through add_subdirectory. In modern CMake best practices you should always prefer target_ functions whenever possible to configure exactly the target which needs the configuration instead of setting it globally.
            Second, you should not need to set the C++ standard directly, instead you should select features which you need to compile your project and let CMake decide the standard. See target_compile_features.



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


            Same problem as previously, use target_compile_definitions(mytarget PUBLIC ELPP_FEATURE_CRASH_LOG)



            #
            # 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()


            This looks like a messy hack to pull in a dependency. If this dependency is required to build your project you should probably add it as a subrepository to your own git source repository and use it using add_subdirectory (assuming it's a CMake project). Alternatively, there is also the ExternalProject module which exists for this sole reason, to pull in and compile external dependencies.



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


            You're configuring globally again with include_directories, use target_include_directories instead. Also, I'd really consider splitting up your CMakeLists file, there is too much going on. Subdivide your project repository to subdirectories, one per library, and then use add_subdirectory to pull in all the libraries you need.



            find_package(gtest REQUIRED)
            include_directories(${GTEST_INCLUDE_DIRS})


            You're setting include directories globally again. Actually, you don't even need to set the directories at all. target_link_libraries does a lot more than linking. It probably should've called differently. Since gtest exports a target with it's INTERFACE_INCLUDE_DIRECTORIES set up, solely linking (target_link_libraries) to gtest sets up include directories automatically for the target.



            If you follow best practices and set all configurations with target_ functions then all you need to pull in a library should be a sole target_link_library since all other configurations (compiler features, include directories, ...) are automatically pulled in, given they're either set PUBLIC or INTERFACE on this library. As I said, target_link_library does a lot more than just linking, it's name is very misleading.
            A perfect example is the fmt package you're using. All you're doing is find_package(FMT REQUIRED CONFIG) and target_link_libraries(mytarget fmt::fmt) and everything else to use this package is set up by the target_link_libraries command since the fmt package exports all its own requirements and include paths through its target.



            I'm pretty sure I missed a few things but I hope these pointers help you to get started.





            share









            $endgroup$













            • $begingroup$
              Thanks a lot for suggestions!
              $endgroup$
              – gruszczy
              27 secs ago














            1












            1








            1





            $begingroup$

            I'm by no means a professional CMake user, I try to follow best practices though and have seen many talks and articles about modern CMake best practices, so lets go through your CMakeLists.



            set(CMAKE_CXX_STANDARD 14)


            This is generally frowned upon for two different reasons. First and most important, you set this configuration globally for every target you create or import through add_subdirectory. In modern CMake best practices you should always prefer target_ functions whenever possible to configure exactly the target which needs the configuration instead of setting it globally.
            Second, you should not need to set the C++ standard directly, instead you should select features which you need to compile your project and let CMake decide the standard. See target_compile_features.



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


            Same problem as previously, use target_compile_definitions(mytarget PUBLIC ELPP_FEATURE_CRASH_LOG)



            #
            # 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()


            This looks like a messy hack to pull in a dependency. If this dependency is required to build your project you should probably add it as a subrepository to your own git source repository and use it using add_subdirectory (assuming it's a CMake project). Alternatively, there is also the ExternalProject module which exists for this sole reason, to pull in and compile external dependencies.



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


            You're configuring globally again with include_directories, use target_include_directories instead. Also, I'd really consider splitting up your CMakeLists file, there is too much going on. Subdivide your project repository to subdirectories, one per library, and then use add_subdirectory to pull in all the libraries you need.



            find_package(gtest REQUIRED)
            include_directories(${GTEST_INCLUDE_DIRS})


            You're setting include directories globally again. Actually, you don't even need to set the directories at all. target_link_libraries does a lot more than linking. It probably should've called differently. Since gtest exports a target with it's INTERFACE_INCLUDE_DIRECTORIES set up, solely linking (target_link_libraries) to gtest sets up include directories automatically for the target.



            If you follow best practices and set all configurations with target_ functions then all you need to pull in a library should be a sole target_link_library since all other configurations (compiler features, include directories, ...) are automatically pulled in, given they're either set PUBLIC or INTERFACE on this library. As I said, target_link_library does a lot more than just linking, it's name is very misleading.
            A perfect example is the fmt package you're using. All you're doing is find_package(FMT REQUIRED CONFIG) and target_link_libraries(mytarget fmt::fmt) and everything else to use this package is set up by the target_link_libraries command since the fmt package exports all its own requirements and include paths through its target.



            I'm pretty sure I missed a few things but I hope these pointers help you to get started.





            share









            $endgroup$



            I'm by no means a professional CMake user, I try to follow best practices though and have seen many talks and articles about modern CMake best practices, so lets go through your CMakeLists.



            set(CMAKE_CXX_STANDARD 14)


            This is generally frowned upon for two different reasons. First and most important, you set this configuration globally for every target you create or import through add_subdirectory. In modern CMake best practices you should always prefer target_ functions whenever possible to configure exactly the target which needs the configuration instead of setting it globally.
            Second, you should not need to set the C++ standard directly, instead you should select features which you need to compile your project and let CMake decide the standard. See target_compile_features.



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


            Same problem as previously, use target_compile_definitions(mytarget PUBLIC ELPP_FEATURE_CRASH_LOG)



            #
            # 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()


            This looks like a messy hack to pull in a dependency. If this dependency is required to build your project you should probably add it as a subrepository to your own git source repository and use it using add_subdirectory (assuming it's a CMake project). Alternatively, there is also the ExternalProject module which exists for this sole reason, to pull in and compile external dependencies.



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


            You're configuring globally again with include_directories, use target_include_directories instead. Also, I'd really consider splitting up your CMakeLists file, there is too much going on. Subdivide your project repository to subdirectories, one per library, and then use add_subdirectory to pull in all the libraries you need.



            find_package(gtest REQUIRED)
            include_directories(${GTEST_INCLUDE_DIRS})


            You're setting include directories globally again. Actually, you don't even need to set the directories at all. target_link_libraries does a lot more than linking. It probably should've called differently. Since gtest exports a target with it's INTERFACE_INCLUDE_DIRECTORIES set up, solely linking (target_link_libraries) to gtest sets up include directories automatically for the target.



            If you follow best practices and set all configurations with target_ functions then all you need to pull in a library should be a sole target_link_library since all other configurations (compiler features, include directories, ...) are automatically pulled in, given they're either set PUBLIC or INTERFACE on this library. As I said, target_link_library does a lot more than just linking, it's name is very misleading.
            A perfect example is the fmt package you're using. All you're doing is find_package(FMT REQUIRED CONFIG) and target_link_libraries(mytarget fmt::fmt) and everything else to use this package is set up by the target_link_libraries command since the fmt package exports all its own requirements and include paths through its target.



            I'm pretty sure I missed a few things but I hope these pointers help you to get started.






            share











            share


            share










            answered 5 mins ago









            tkausltkausl

            49428




            49428












            • $begingroup$
              Thanks a lot for suggestions!
              $endgroup$
              – gruszczy
              27 secs ago


















            • $begingroup$
              Thanks a lot for suggestions!
              $endgroup$
              – gruszczy
              27 secs ago
















            $begingroup$
            Thanks a lot for suggestions!
            $endgroup$
            – gruszczy
            27 secs ago




            $begingroup$
            Thanks a lot for suggestions!
            $endgroup$
            – gruszczy
            27 secs ago













            0












            $begingroup$

            Instead of using set for source files, which made them get recompiled multiple times, I switched add_library and now it builds everything much faster. No more unnecessarily compiling the same file again.



            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()

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

            #
            # Local lib targets
            #

            add_library(ast ast.h ast.cc)

            add_library(ast_compare_visitor ast_compare_visitor.h ast_compare_visitor.cc)

            add_library(classes classes.h classes.cc)

            add_library(codegen
            codegen.h
            codegen.cc
            codegen_common.h
            codegen_common.cc
            expression_type_visitor.cc
            expression_type_visitor.h)

            add_library(common common.h utils.h utils.cc)

            add_library(compilation_context
            compilation_context.h
            compilation_context.cc
            enum.h
            enum.cc
            errors.h
            errors.cc
            operators.h
            operators.cc
            type.h
            type.cc)

            add_library(functions functions.h functions.cc)

            add_library(jit jit.cc jit.h)

            add_library(lexer lexer.cc lexer.h lexer_common.cc lexer_common.h)

            add_library(parser parser.h parser.cc)

            add_library(runtime runtime.cc runtime.h)

            add_library(type_inference
            type_inference.h
            type_inference.cc
            symbol_visitor.cc
            symbol_visitor.h
            type_inference_visitor.cc
            type_inference_visitor.h)

            #
            # External lib targets
            #

            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)

            #
            # Schwifty main executable
            #

            add_executable(schwifty schwifty.cc)
            target_link_libraries(schwifty
            ${llvm_libs}
            ast
            classes
            codegen
            common
            compilation_context
            easyloggingpp
            fmt::fmt
            functions
            lexer
            parser
            runtime
            type_inference)

            #
            # Testing
            #

            enable_testing()
            find_package(gtest REQUIRED)

            include_directories(${GTEST_INCLUDE_DIRS})

            add_executable(codegen_test codegen_test.cc)
            target_link_libraries(codegen_test
            ${GTEST_BOTH_LIBRARIES}
            ${llvm_libs}
            easyloggingpp
            ast
            classes
            codegen
            common
            compilation_context
            fmt::fmt
            functions
            jit
            lexer
            parser
            runtime
            type_inference)
            add_test(codegen_test COMMAND out/codegen_test)

            add_executable(lexer_test lexer_test.cc)
            target_link_libraries(lexer_test
            ${GTEST_BOTH_LIBRARIES}
            ast
            common
            compilation_context
            easyloggingpp
            functions
            lexer
            parser
            fmt::fmt)
            add_test(lexer_test COMMAND out/lexer_test)

            add_executable(parser_test parser_test.cc)
            target_link_libraries(parser_test
            ${GTEST_BOTH_LIBRARIES}
            ast
            ast_compare_visitor
            compilation_context
            common
            easyloggingpp
            functions
            lexer
            parser
            fmt::fmt)
            add_test(parser_test COMMAND out/parser_test)

            add_executable(type_test type_test.cc)
            target_link_libraries(type_test
            ${GTEST_BOTH_LIBRARIES}
            ast
            common
            compilation_context
            easyloggingpp
            functions
            lexer
            parser)
            add_test(type_test COMMAND out/type_test)

            add_executable(type_inference_test type_inference_test.cc)
            target_link_libraries(type_inference_test
            ${GTEST_BOTH_LIBRARIES}
            easyloggingpp
            ast
            classes
            common
            compilation_context
            functions
            fmt::fmt
            lexer
            parser
            runtime
            type_inference)
            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} end_to_end_tests.py)





            share|improve this answer









            $endgroup$


















              0












              $begingroup$

              Instead of using set for source files, which made them get recompiled multiple times, I switched add_library and now it builds everything much faster. No more unnecessarily compiling the same file again.



              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()

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

              #
              # Local lib targets
              #

              add_library(ast ast.h ast.cc)

              add_library(ast_compare_visitor ast_compare_visitor.h ast_compare_visitor.cc)

              add_library(classes classes.h classes.cc)

              add_library(codegen
              codegen.h
              codegen.cc
              codegen_common.h
              codegen_common.cc
              expression_type_visitor.cc
              expression_type_visitor.h)

              add_library(common common.h utils.h utils.cc)

              add_library(compilation_context
              compilation_context.h
              compilation_context.cc
              enum.h
              enum.cc
              errors.h
              errors.cc
              operators.h
              operators.cc
              type.h
              type.cc)

              add_library(functions functions.h functions.cc)

              add_library(jit jit.cc jit.h)

              add_library(lexer lexer.cc lexer.h lexer_common.cc lexer_common.h)

              add_library(parser parser.h parser.cc)

              add_library(runtime runtime.cc runtime.h)

              add_library(type_inference
              type_inference.h
              type_inference.cc
              symbol_visitor.cc
              symbol_visitor.h
              type_inference_visitor.cc
              type_inference_visitor.h)

              #
              # External lib targets
              #

              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)

              #
              # Schwifty main executable
              #

              add_executable(schwifty schwifty.cc)
              target_link_libraries(schwifty
              ${llvm_libs}
              ast
              classes
              codegen
              common
              compilation_context
              easyloggingpp
              fmt::fmt
              functions
              lexer
              parser
              runtime
              type_inference)

              #
              # Testing
              #

              enable_testing()
              find_package(gtest REQUIRED)

              include_directories(${GTEST_INCLUDE_DIRS})

              add_executable(codegen_test codegen_test.cc)
              target_link_libraries(codegen_test
              ${GTEST_BOTH_LIBRARIES}
              ${llvm_libs}
              easyloggingpp
              ast
              classes
              codegen
              common
              compilation_context
              fmt::fmt
              functions
              jit
              lexer
              parser
              runtime
              type_inference)
              add_test(codegen_test COMMAND out/codegen_test)

              add_executable(lexer_test lexer_test.cc)
              target_link_libraries(lexer_test
              ${GTEST_BOTH_LIBRARIES}
              ast
              common
              compilation_context
              easyloggingpp
              functions
              lexer
              parser
              fmt::fmt)
              add_test(lexer_test COMMAND out/lexer_test)

              add_executable(parser_test parser_test.cc)
              target_link_libraries(parser_test
              ${GTEST_BOTH_LIBRARIES}
              ast
              ast_compare_visitor
              compilation_context
              common
              easyloggingpp
              functions
              lexer
              parser
              fmt::fmt)
              add_test(parser_test COMMAND out/parser_test)

              add_executable(type_test type_test.cc)
              target_link_libraries(type_test
              ${GTEST_BOTH_LIBRARIES}
              ast
              common
              compilation_context
              easyloggingpp
              functions
              lexer
              parser)
              add_test(type_test COMMAND out/type_test)

              add_executable(type_inference_test type_inference_test.cc)
              target_link_libraries(type_inference_test
              ${GTEST_BOTH_LIBRARIES}
              easyloggingpp
              ast
              classes
              common
              compilation_context
              functions
              fmt::fmt
              lexer
              parser
              runtime
              type_inference)
              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} end_to_end_tests.py)





              share|improve this answer









              $endgroup$
















                0












                0








                0





                $begingroup$

                Instead of using set for source files, which made them get recompiled multiple times, I switched add_library and now it builds everything much faster. No more unnecessarily compiling the same file again.



                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()

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

                #
                # Local lib targets
                #

                add_library(ast ast.h ast.cc)

                add_library(ast_compare_visitor ast_compare_visitor.h ast_compare_visitor.cc)

                add_library(classes classes.h classes.cc)

                add_library(codegen
                codegen.h
                codegen.cc
                codegen_common.h
                codegen_common.cc
                expression_type_visitor.cc
                expression_type_visitor.h)

                add_library(common common.h utils.h utils.cc)

                add_library(compilation_context
                compilation_context.h
                compilation_context.cc
                enum.h
                enum.cc
                errors.h
                errors.cc
                operators.h
                operators.cc
                type.h
                type.cc)

                add_library(functions functions.h functions.cc)

                add_library(jit jit.cc jit.h)

                add_library(lexer lexer.cc lexer.h lexer_common.cc lexer_common.h)

                add_library(parser parser.h parser.cc)

                add_library(runtime runtime.cc runtime.h)

                add_library(type_inference
                type_inference.h
                type_inference.cc
                symbol_visitor.cc
                symbol_visitor.h
                type_inference_visitor.cc
                type_inference_visitor.h)

                #
                # External lib targets
                #

                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)

                #
                # Schwifty main executable
                #

                add_executable(schwifty schwifty.cc)
                target_link_libraries(schwifty
                ${llvm_libs}
                ast
                classes
                codegen
                common
                compilation_context
                easyloggingpp
                fmt::fmt
                functions
                lexer
                parser
                runtime
                type_inference)

                #
                # Testing
                #

                enable_testing()
                find_package(gtest REQUIRED)

                include_directories(${GTEST_INCLUDE_DIRS})

                add_executable(codegen_test codegen_test.cc)
                target_link_libraries(codegen_test
                ${GTEST_BOTH_LIBRARIES}
                ${llvm_libs}
                easyloggingpp
                ast
                classes
                codegen
                common
                compilation_context
                fmt::fmt
                functions
                jit
                lexer
                parser
                runtime
                type_inference)
                add_test(codegen_test COMMAND out/codegen_test)

                add_executable(lexer_test lexer_test.cc)
                target_link_libraries(lexer_test
                ${GTEST_BOTH_LIBRARIES}
                ast
                common
                compilation_context
                easyloggingpp
                functions
                lexer
                parser
                fmt::fmt)
                add_test(lexer_test COMMAND out/lexer_test)

                add_executable(parser_test parser_test.cc)
                target_link_libraries(parser_test
                ${GTEST_BOTH_LIBRARIES}
                ast
                ast_compare_visitor
                compilation_context
                common
                easyloggingpp
                functions
                lexer
                parser
                fmt::fmt)
                add_test(parser_test COMMAND out/parser_test)

                add_executable(type_test type_test.cc)
                target_link_libraries(type_test
                ${GTEST_BOTH_LIBRARIES}
                ast
                common
                compilation_context
                easyloggingpp
                functions
                lexer
                parser)
                add_test(type_test COMMAND out/type_test)

                add_executable(type_inference_test type_inference_test.cc)
                target_link_libraries(type_inference_test
                ${GTEST_BOTH_LIBRARIES}
                easyloggingpp
                ast
                classes
                common
                compilation_context
                functions
                fmt::fmt
                lexer
                parser
                runtime
                type_inference)
                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} end_to_end_tests.py)





                share|improve this answer









                $endgroup$



                Instead of using set for source files, which made them get recompiled multiple times, I switched add_library and now it builds everything much faster. No more unnecessarily compiling the same file again.



                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()

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

                #
                # Local lib targets
                #

                add_library(ast ast.h ast.cc)

                add_library(ast_compare_visitor ast_compare_visitor.h ast_compare_visitor.cc)

                add_library(classes classes.h classes.cc)

                add_library(codegen
                codegen.h
                codegen.cc
                codegen_common.h
                codegen_common.cc
                expression_type_visitor.cc
                expression_type_visitor.h)

                add_library(common common.h utils.h utils.cc)

                add_library(compilation_context
                compilation_context.h
                compilation_context.cc
                enum.h
                enum.cc
                errors.h
                errors.cc
                operators.h
                operators.cc
                type.h
                type.cc)

                add_library(functions functions.h functions.cc)

                add_library(jit jit.cc jit.h)

                add_library(lexer lexer.cc lexer.h lexer_common.cc lexer_common.h)

                add_library(parser parser.h parser.cc)

                add_library(runtime runtime.cc runtime.h)

                add_library(type_inference
                type_inference.h
                type_inference.cc
                symbol_visitor.cc
                symbol_visitor.h
                type_inference_visitor.cc
                type_inference_visitor.h)

                #
                # External lib targets
                #

                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)

                #
                # Schwifty main executable
                #

                add_executable(schwifty schwifty.cc)
                target_link_libraries(schwifty
                ${llvm_libs}
                ast
                classes
                codegen
                common
                compilation_context
                easyloggingpp
                fmt::fmt
                functions
                lexer
                parser
                runtime
                type_inference)

                #
                # Testing
                #

                enable_testing()
                find_package(gtest REQUIRED)

                include_directories(${GTEST_INCLUDE_DIRS})

                add_executable(codegen_test codegen_test.cc)
                target_link_libraries(codegen_test
                ${GTEST_BOTH_LIBRARIES}
                ${llvm_libs}
                easyloggingpp
                ast
                classes
                codegen
                common
                compilation_context
                fmt::fmt
                functions
                jit
                lexer
                parser
                runtime
                type_inference)
                add_test(codegen_test COMMAND out/codegen_test)

                add_executable(lexer_test lexer_test.cc)
                target_link_libraries(lexer_test
                ${GTEST_BOTH_LIBRARIES}
                ast
                common
                compilation_context
                easyloggingpp
                functions
                lexer
                parser
                fmt::fmt)
                add_test(lexer_test COMMAND out/lexer_test)

                add_executable(parser_test parser_test.cc)
                target_link_libraries(parser_test
                ${GTEST_BOTH_LIBRARIES}
                ast
                ast_compare_visitor
                compilation_context
                common
                easyloggingpp
                functions
                lexer
                parser
                fmt::fmt)
                add_test(parser_test COMMAND out/parser_test)

                add_executable(type_test type_test.cc)
                target_link_libraries(type_test
                ${GTEST_BOTH_LIBRARIES}
                ast
                common
                compilation_context
                easyloggingpp
                functions
                lexer
                parser)
                add_test(type_test COMMAND out/type_test)

                add_executable(type_inference_test type_inference_test.cc)
                target_link_libraries(type_inference_test
                ${GTEST_BOTH_LIBRARIES}
                easyloggingpp
                ast
                classes
                common
                compilation_context
                functions
                fmt::fmt
                lexer
                parser
                runtime
                type_inference)
                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} end_to_end_tests.py)






                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Sep 9 '18 at 22:58









                gruszczygruszczy

                5518




                5518






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Code Review Stack Exchange!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    Use MathJax to format equations. MathJax reference.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f196243%2fcmake-for-a-toy-programming-language%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Сан-Квентин

                    Алькесар

                    Josef Freinademetz