Setting Up the Initial CMake for my TVM project
CMake is a powerful tool used for managing the build process in C++ projects. It’s designed to be cross-platform, allowing you to easily configure and build your project on multiple operating systems.
This blog shows the initial CMake configuration for my TVM from scratch project. It walks through the setup of a simple CMakeLists.txt
file, and explain it step by step.
Why Use CMake?
CMake is highly flexible and widely used in the C++ community. It abstracts away many details of the build system, making it easier to manage large projects, link external libraries, and handle platform-specific configurations. By using CMake, you’re setting up your project in a standardized way that many other C++ developers will recognize.
Setting Up a Basic CMakeLists.txt File
Project Directory Structure
Before we dive into the CMakeLists.txt
file, let’s think about the project structure. For now, we may just have the following
MyTVM/
├── src/
├── include/
├── 3rdparty/
├── CMakeLists.txt
└── README.md
src/
: This directory contains the C++ source files.CMakeLists.txt
: This file is where we’ll configure CMake to build our project.
Writing the CMakeLists.txt File
cmake_minimal_required(VERSION 3.31)
project(MyTVM)
First we define the minimum CMake version at the top of the file. This ensures compatibility and helps avoid issues on older CMake versions.
Then we define the project name as MyTVM.
# Set C++ standard
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
Next we specify the C++ standard.
CMAKE_CXX_STANDARD
: This sets the C++ standard to C++14.CMAKE_CXX_STANDARD_REQUIRED
: Ensures that the C++ standard we set is strictly enforced.CMAKE_CXX_EXTENSIONS
: Disables compiler-specific extensions, which can improve cross-platform compatibility.
# Add subdirectories
add_subdirectory(src)
CMake’s add_subdirectory
function allows us to modularize the project. Each subdirectory can have its own CMakeLists.txt
, making it easier to manage large codebases. For now, we’ll just include the src/
directory.
option(USE_DEBUG "Enable debugging symbols" OFF)
if(USE_DEBUG)
set(CMAKE_BUILD_TYPE Debug)
else()
set(CMAKE_BUILD_TYPE Release)
endif()
This part configures the debug options. Sometimes we want to build the project with debugging symbols (for development) or optimizations (for release). CMake allows us to define options that developers can toggle.
USE_DEBUG
: A toggle for enabling debugging symbols, defaulting toOFF
.CMAKE_BUILD_TYPE
: Sets the build type toDebug
orRelease
based on the toggle.
To build with debugging symbols, simply run: cmake -DUSE_DEBUG=ON ..
include(FetchContent)
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG v1.15.0
)
FetchContent_MakeAvailable(googletest)
Adding Third-Party Dependencies with FetchContent:
CMake's FetchContent makes it straightforward to managing external dependencies. Instead of manually downloading and including libraries, we can fetch and configure them directly in the CMakeLists.txt. Here, we’ll add GoogleTest for unit testing.
FetchContent_Declare
: Declares an external dependency (GoogleTest in this case) by specifying its repository and version.FetchContent_MakeAvailable
: Fetches and makes the dependency available for use.
Placeholder src directory
In /src
directory, put the following two files as the placeholder.
# Placeholder CMakeLists.txt for the src directory
add_library(myTVM STATIC placeholder.cpp)
target_include_directories(myTVM PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
This is the placeholder CMakeLists.txt
We also need a placeholder.cpp
#include <iostream>
void placeholder_function() {
std::cout << "This is a placeholder function in myTVM!" << std::endl;
}
Building the project
To build your project using CMake, follow these steps:
Create a
build/
directory for out-of-source builds:mkdir build && cd build
Run
cmake
to configure the project:cmake ..
Build the project:
make
Conclusion
We configured a simple CMakeLists.txt
file to get started. This setup establishes a initial point for future development, where we will build our own TVM from scratch.