cmake for a toy programming language
$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)
compiler cmake
$endgroup$
add a comment |
$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)
compiler cmake
$endgroup$
add a comment |
$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)
compiler cmake
$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
compiler cmake
asked Jun 10 '18 at 20:45
gruszczygruszczy
5518
5518
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
$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.
$endgroup$
$begingroup$
Thanks a lot for suggestions!
$endgroup$
– gruszczy
2 mins ago
add a comment |
$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)
$endgroup$
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
$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.
$endgroup$
$begingroup$
Thanks a lot for suggestions!
$endgroup$
– gruszczy
2 mins ago
add a comment |
$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.
$endgroup$
$begingroup$
Thanks a lot for suggestions!
$endgroup$
– gruszczy
2 mins ago
add a comment |
$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.
$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.
answered 7 mins ago
tkausltkausl
49428
49428
$begingroup$
Thanks a lot for suggestions!
$endgroup$
– gruszczy
2 mins ago
add a comment |
$begingroup$
Thanks a lot for suggestions!
$endgroup$
– gruszczy
2 mins ago
$begingroup$
Thanks a lot for suggestions!
$endgroup$
– gruszczy
2 mins ago
$begingroup$
Thanks a lot for suggestions!
$endgroup$
– gruszczy
2 mins ago
add a comment |
$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)
$endgroup$
add a comment |
$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)
$endgroup$
add a comment |
$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)
$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)
answered Sep 9 '18 at 22:58
gruszczygruszczy
5518
5518
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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