Follow these steps to create a basic CMake
project with torch C++
enabled. The proposed folders structure is not mandatory, but is focused to run tests with ease.
We will be working with VS-Code, for Visual Studio, find a tutorial ,by Khareed, here
- Setup VS Code
- Setting up My_Torch_Project
- Building an Running My_Torch_Project
- Full clean and then Build
- Testing program in terminal
- EASY MODE: After Initial Setup
- MISC
VS Code Extensions to make life easier:
- C/C++ for Intellisense support
- CMake for cmake language support
- clangd for autocomplete, errors and warnings, etc.
- CMakeTools for automating cmake builds, tests,etc.
To get intellisense support for torch, we will create (and/or) add a path to includePath
in the settings.json
file:
{
"configurations": [
{
"name": "Win32",
"includePath": [
"${workspaceFolder}/**",
// Add this line below explicitly (torch.h lives here)
"${workspaceFolder}/external/libtorch/include/torch/csrc/api/include",
],
// other settings, etc......
}
}
Now we can include <torch/torch.h>
in our .cpp
and .h
files.
- Goto command pallet (
Ctrl
+Shift
+P
) - Search for
C/C++: Change Configuration Provider
- Select
CMake Tools
Right click on activity bar and make CMake visible if not visible. This will help in exploring the CMake project.
We can now create an example project called My_Torch_Project which is configured with CMake
with the following folder structure.
Note: We will call them by their assigned names (assigned names are in "{ NAME }" ).
- For example:
- Project Cmake file refers to -->
My_Torch_Project/CMakeLists.txt
- Test Cmake file refers to -->
My_Torch_Project/test/CMakeLists.txt
and so on...
- Project Cmake file refers to -->
In this example, My_Torch_Project/test/test_2/*
and My_Torch_Project/src/*
files require torch.
My_Torch_Project
|
|-CMakeLists.txt <--------------- {Project} CMakeLists.txt
|
|-external
| |-libtorch
| |-another_dependency
|
|-src
| |-main.cpp
| |-main.h
|
|-test
| |-CMakeLists.txt <--------------- {Test} CMakeLists.txt
| |
| |-test_1
| | |-CMakeLists.txt <--------------- {Test_1} CMakeLists.txt
| | |-test_1.cpp
| | |-test_1.h
| |
| |-test_2
| | |-CMakeLists.txt <--------------- {Test_2} CMakeLists.txt
| | |-test_2.cpp
| | |-test_2.h
|
|-build <---------------- Scroll down for # Building My_Torch_Project
This file requires the following in order. Since it is the main file, the order is important.
enable_testing()
is required at the top of fileTorch Settings
are required before executables can be added- Any executable with torch dependency will need to follow the pattern in
Main Executable
- Finally, at the end-of-file, add the block as specified in
REMOVE WINDOWS ERRORS
.
cmake_minimum_required (VERSION X.X) #Usually the latest one you are using
project(
My_Torch_Project
VERSION X.Y.Z
DESCRIPTION "My Torch Project")
# --------- Optionally enable standards ---------
# ------------------ STANDARDS ------------------
enable_language(C)
enable_language(CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
enable_testing() # --- This is placed specifically at the top of the file to enable testing
# ------------------ Path Settings ------------------
set(MAIN_PATH "${CMAKE_SOURCE_DIR}") # ------- Makes source dir
set(CMAKE_PREFIX_PATH "${MAIN_PATH}/external/libtorch")
set(ANOTHER_DEPENDENCY_PATH "${MAIN_PATH}/external/another_dependency")
set(SRC "${MAIN_PATH}/src")
# ------------------ Torch Settings ------------------
include_directories("${MAIN_PATH}/external/libtorch")
find_package(Torch REQUIRED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TORCH_CXX_FLAGS}")
# -------------------- Add Tests Subdirectory --------------------
add_subdirectory(${SRC}/test)
# ------------------ Main Executable ------------------
add_executable (MY_MAIN_EXECUTABLE "${SRC}/main.cpp" "${SRC}/main.h")
target_link_libraries(MY_MAIN_EXECUTABLE "${TORCH_LIBRARIES}")
# -------------------- REMOVE WINDOWS ERRORS --------------------
# The following code block is suggested to be used on Windows.
# According to https://github.com/pytorch/pytorch/issues/25457,
# the DLLs need to be copied to avoid memory errors.
if (MSVC)
file(GLOB TORCH_DLLS "${TORCH_INSTALL_PREFIX}/lib/*.dll")
add_custom_command(TARGET MY_MAIN_EXECUTABLE
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${TORCH_DLLS}
$<TARGET_FILE_DIR:MY_MAIN_EXECUTABLE >)
endif (MSVC)
This is for adding what tests we will be running. If we do not want to run test_2, we can simply comment it out
add_subdirectory(test_1)
add_subdirectory(test_2)
# add_subdirectory(test_3) This test is no longer detected
add_executable(TEST_1_EXEC_NAME "test_1.cpp" "test_1.h")
add_test(NAME 1_ST_TEST_ON__TEST_1_EXEC
COMMAND $<TARGET_FILE:TEST_1_EXEC_NAME> 12.5 "arg2" "arg3" # -- These are args passed to the test, of course optional
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
add_test(NAME 2_ND_TEST_ON__TEST_1_EXEC
COMMAND $<TARGET_FILE:TEST_1_EXEC_NAME> # -- This test has no args passed to the executable
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
add_test(NAME 3_RD_TEST_ON__TEST_1_EXEC
COMMAND $<TARGET_FILE:TEST_1_EXEC_NAME> 1.51 "arg2" "arg3" # -- These are args passed to the test, of course optional
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
add_executable(TEST_2_EXEC_NAME "test_2.cpp" "test_2.h")
# --------------------- Tests ---------------------
add_test(NAME 1_ST_TEST_ON__TEST_1_EXEC
COMMAND $<TARGET_FILE:TEST_1_EXEC_NAME> 12.5 "arg2" # -- These are args passed to the test, of course optional
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
add_test(NAME 2_ND_TEST_ON__TEST_1_EXEC
COMMAND $<TARGET_FILE:TEST_1_EXEC_NAME> 1.51 "arg2" "arg3" # -- These are args passed to the test, of course optional
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
# ----------------------------------------------------------
# -- Add this to block to each CMakeLists.txt file which --
# -- depends on torch for running tests. For Example, --
# -- If it includes a `#include <torch/torch.h>` --
# ----------------------------------------------------------
include_directories("${MAIN_PATH}/external/libtorch")
find_package(Torch REQUIRED)
target_link_libraries(TEST_2_EXEC_NAME "${TORCH_LIBRARIES}")
# According to https://github.com/pytorch/pytorch/issues/25457
if (MSVC)
file(GLOB TORCH_DLLS "${TORCH_INSTALL_PREFIX}/lib/*.dll")
add_custom_command(TARGET TEST_2_EXEC_NAME
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${TORCH_DLLS}
$<TARGET_FILE_DIR:TEST_2_EXEC_NAME >)
endif (MSVC)
# ----------------------------------------------------------
We can now build the project. Lets iterate the project structure.
Steps to build:
-
Create a directory for building the project
My_Torch_Project~$ mkdir build My_Torch_Project~$ cd build
-
Generate project files
My_Torch_Project/build~$ cmake ..
-
Open Command Pallet (
Ctrl
+Shift
+P
) and runCMake: Build
. This will generate the executables inbuild/Debug
(or Release, etc. See the OUTPUT window for exact commands). -
To run tests click on the CMake explorer in the Activity bar. Right click and see options. You can build, debug or run in terminal, etc.
-
The main executable is stored in
build/Debug/MY_MAIN_EXECUTABLE.exe
and tests inbuild/src/test/test_1/Debug/TEST_1_EXEC_NAME.exe
, etc. -
To easily run these, use the CMake explorer and right-click to show the options. Select
Run in Terminal
to see the output of the test or the executable.
Now The folder structure is something like this:
My_Torch_Project
|
|-CMakeLists.txt <--------------- {Project} CMakeLists.txt
|-external/*
|-src/*
|-test
| |-CMakeLists.txt
| |-test_1/*
| |-test_2/*
|
|-build/*
To completely clean the project and rebuild, go to root dir and remove all files.
My_Torch_Project~$ rm -rf build/* # removes all files
My_Torch_Project~$ cd build
My_Torch_Project/build~$ cmake .. # rebuild project
# You can hit **`CMake:Build`** command in the command pallet after this.
# All the tests and executables will be regenerated and be available to the CMake extension.
Go to the build/Debug
and run the main executable: MY_MAIN_EXECUTABLE.exe
Go to the build/src/test/test2/Debug
and run: TEST_2_EXEC_NAME.exe
if main.cpp has the following...
#pragma warning(disable : 4624) // Torch warnings
#pragma warning(disable : 4805) // Torch warnings
#pragma warning(disable : 4067) // Torch warnings
#include <iostream>
#include "main.h"
#include <torch/torch.h>
int main()
{
std::cout << "\nRunning Test file -> " << __FILE__ << std::endl;
std::cout << torch::randn({3, 2}) << std::endl;
return 0;
}
We will get the following output:
My_Torch_Project/build/Debug~$ MY_MAIN_EXECUTABLE.exe
Running Test file -> C:/My_Torch_Project/src/main.cpp
1.0816 -1.2137
0.2768 -0.5250
0.3836 2.9232
[ CPUFloatType{3,2} ]
On the status bar right-click and enable CMake Tools (Extension)
. This helps to select targets, build targets (for Debug, Release, MiniSizeRel, RelwithDebInfo), run tests, run built files in the terminal, etc. Makes life easier 😅.
To disable common warnings, place these in the .cpp
or the .h
files.
// To suppress those torch annoying when building with CMake
#pragma warning(disable : 4624) // Class Destructor Not visible
#pragma warning(disable : 4805) // Comparing bool and int
#pragma warning(disable : 4067) // Extra /Za preprocessor command