learning.
learning18 min read

build sudoku from scratch: bài 0 — setup VS Code + C++ toolchain (Mac & Windows)

Bài 0 của series học thuật build-a-sudoku. Cài VS Code + toolchain C++20 (Apple Clang trên Mac / MSVC trên Windows) + CMake + Git để mở multi-root workspace, configure và build. Cover song song path Mac + Windows — mọi bài sau đều giả định cả hai chạy.

L\u1ea7n \u0111\u1ea7u t\u00f4i vi\u1ebft C++ tr\u00ean c\u1ea3 Mac v\u00e0 Windows, m\u1ed7i m\u00e1y l\u1ea1i "th\u1ea5y" code theo m\u1ed9t ki\u1ec3u kh\u00e1c nhau. C\u00f9ng m\u1ed9t file main.cpp, IntelliSense tr\u00ean Windows xanh l\u00e9t h\u00e0i l\u00f2ng, c\u00f2n clangd tr\u00ean Mac g\u1ea1ch \u0111\u1ecf ngay d\u00f2ng #include <iostream> \u0111\u1ea7u ti\u00ean. Sau khi \u0111\u1ed1t nguy\u00ean m\u1ed9t t\u1ed1i debug "l\u1ed7i C++" m\u00e0 g\u1ed1c r\u1ec5 ch\u1ec9 l\u00e0 CMake configure tr\u00ean Mac v\u1eabn \u0111ang tr\u1ecf v\u00e0o generator c\u1ee7a l\u1ea7n build tr\u01b0\u1edbc, t\u00f4i r\u00fat ra m\u1ed9t b\u00e0i h\u1ecdc kh\u00e1 \u0111\u1eaft: tr\u01b0\u1edbc khi vi\u1ebft b\u1ea5t k\u1ef3 d\u00f2ng game logic n\u00e0o, toolchain ph\u1ea3i \u0111\u01b0\u1ee3c d\u1ef1ng k\u1ef9 v\u00e0 ph\u1ea3i build ra \u0111\u01b0\u1ee3c gi\u1ed1ng nhau tr\u00ean hai m\u00e1y. \u0110\u00f3 ch\u00ednh l\u00e0 l\u00fd do B\u00e0i 0 c\u1ee7a series Build Sudoku t\u1ed3n t\u1ea1i, v\u00e0 l\u00e0 l\u00fd do n\u00f3 \u0111\u01b0\u1ee3c vi\u1ebft ra tr\u01b0\u1edbc c\u1ea3 b\u00e0i thu\u1eadt to\u00e1n backtracking n\u1ed5i ti\u1ebfng.

Series n\u00e0y s\u1ebd \u0111\u01b0a b\u1ea1n t\u1eeb m\u1ed9t th\u01b0 m\u1ee5c tr\u1ed1ng \u0111\u1ebfn m\u1ed9t game Sudoku c\u00f3 th\u1ec3 ch\u01a1i c\u1ed9ng v\u1edbi m\u1ed9t solver t\u1ef1 gi\u1ea3i, vi\u1ebft ho\u00e0n to\u00e0n b\u1eb1ng C++20. B\u00e0i h\u00f4m nay kh\u00f4ng c\u00f3 thu\u1eadt to\u00e1n, kh\u00f4ng c\u00f3 c\u1ea5u tr\u00fac d\u1eef li\u1ec7u, kh\u00f4ng c\u00f3 class design. N\u00f3 ch\u1ec9 l\u00e0m m\u1ed9t vi\u1ec7c duy nh\u1ea5t: c\u00e0i VS Code, m\u1ed9t b\u1ed9 C++ compiler h\u1ee3p l\u1ec7, CMake, Git, m\u1edf project \u1edf d\u1ea1ng multi-root workspace, configure v\u00e0 build m\u1ed9t executable in ra m\u1ed9t banner Sudoku r\u1ed7ng. Nghe \u0111\u01a1n gi\u1ea3n, nh\u01b0ng n\u00f3 l\u00e0 n\u1ec1n t\u1ea3ng cho h\u01a1n 10 b\u00e0i ti\u1ebfp theo. M\u1ecdi l\u1ec7nh cmake --build, m\u1ecdi tab debug F5, m\u1ecdi commit Git c\u1ee7a series \u0111\u1ec1u d\u1ef1a tr\u00ean nh\u1eefng g\u00ec b\u1ea1n d\u1ef1ng \u1edf b\u00e0i n\u00e0y.

1. M\u1ee5c ti\u00eau

B\u1ea1n s\u1ebd bi\u1ebft B\u00e0i 0 th\u00e0nh c\u00f4ng kh\u00f4ng ph\u1ea3i khi "c\u1ea3m th\u1ea5y \u0111\u00e3 hi\u1ec3u", m\u00e0 khi b\u1ea3y d\u00f2ng output sau \u0111\u00e2y xu\u1ea5t hi\u1ec7n \u0111\u00fang th\u1ee9 t\u1ef1 tr\u00ean c\u1ea3 Mac l\u1eabn Windows \u2014 v\u00e0 m\u1ed9t trong s\u1ed1 \u0111\u00f3 l\u00e0 con s\u1ed1 \u0111\u1ecbnh danh chu\u1ea9n C++20 m\u00e0 r\u1ea5t nhi\u1ec1u setup t\u01b0\u1edfng \u0111\u00e3 b\u1eadt nh\u01b0ng th\u1ef1c ra ch\u01b0a. Khi \u0111\u00f3ng tab tr\u00ecnh duy\u1ec7t cu\u1ed1i b\u00e0i n\u00e0y, b\u1ea1n ph\u1ea3i c\u00f3 \u0111\u1ee7 nh\u1eefng th\u1ee9 sau, \u0111o \u0111\u01b0\u1ee3c, kh\u00f4ng ph\u1ea3i "c\u1ea3m th\u1ea5y \u0111\u00e3 hi\u1ec3u":

  • VS Code \u0111\u00e3 c\u00e0i v\u00e0 m\u1edf \u0111\u01b0\u1ee3c file .cpp c\u00f3 syntax highlight c\u00f9ng IntelliSense (Microsoft) ho\u1eb7c clangd (LLVM).
  • M\u1ed9t b\u1ed9 compiler C++20 ho\u1ea1t \u0111\u1ed9ng \u0111\u01b0\u1ee3c. Tr\u00ean macOS l\u00e0 Apple Clang \u0111i k\u00e8m Xcode Command Line Tools. Tr\u00ean Windows l\u00e0 MSVC \u0111i k\u00e8m Visual Studio Build Tools 2022 ho\u1eb7c Visual Studio Community 2022 (ch\u1ecdn workload "Desktop development with C++").
  • CMake phi\u00ean b\u1ea3n t\u1ed1i thi\u1ec3u 3.20 \u0111\u00e3 c\u00f3 tr\u00ean PATH c\u1ee7a shell m\u1eb7c \u0111\u1ecbnh.
  • Git \u0111\u00e3 c\u1ea5u h\u00ecnh user.name v\u00e0 user.email, v\u00e0 bi\u1ebft b\u1ea1n \u0111ang d\u00f9ng t\u00e0i kho\u1ea3n GitHub n\u00e0o.
  • Th\u01b0 m\u1ee5c build-sudoku-from-scratch/ ch\u1ee9a \u0111\u00fang c\u00e1c file m\u00e0 b\u00e0i n\u00e0y y\u00eau c\u1ea7u: CMakeLists.txt, src/main.cpp, .vscode/, .gitignore, sudoku.code-workspace.
  • L\u1ec7nh cmake -S . -B build && cmake --build build ch\u1ea1y kh\u00f4ng l\u1ed7i v\u00e0 sinh ra binary build/sudoku tr\u00ean macOS ho\u1eb7c build\Debug\sudoku.exe tr\u00ean Windows.
  • Ch\u1ea1y executable in ra d\u00f2ng C++ standard: 202002 c\u00f9ng m\u1ed9t banner 9\u00d79 r\u1ed7ng. Con s\u1ed1 202002 l\u00e0 b\u1eb1ng ch\u1ee9ng compiler \u0111ang bi\u00ean d\u1ecbch \u1edf chu\u1ea9n C++20 th\u1eadt, kh\u00f4ng ph\u1ea3i C++17 m\u1eb7c \u0111\u1ecbnh c\u1ee7a CMake c\u0169.

B\u1ea1n KH\u00d4NG c\u1ea7n bi\u1ebft lu\u1eadt Sudoku, thu\u1eadt to\u00e1n solver, hay design class cho b\u00e0n c\u1edd \u1edf b\u00e0i n\u00e0y. \u0110\u00f3 l\u00e0 vi\u1ec7c c\u1ee7a B\u00e0i 1 tr\u1edf \u0111i. B\u00e0i 0 ch\u1ec9 tr\u1ea3 l\u1eddi m\u1ed9t c\u00e2u h\u1ecfi: m\u00e1y c\u1ee7a t\u00f4i c\u00f3 bi\u00ean d\u1ecbch \u0111\u01b0\u1ee3c C++20 kh\u00f4ng, v\u00e0 VS Code c\u00f3 hi\u1ec3u code c\u1ee7a t\u00f4i kh\u00f4ng.

2. C\u00e2y th\u01b0 m\u1ee5c

Ch\u00edn file. Kh\u00f4ng h\u01a1n. B\u00e0i n\u00e0y c\u1ed1 \u00fd kh\u00f4ng c\u00f3 file th\u1ee9 m\u01b0\u1eddi n\u00e0o v\u00ec m\u1ed7i file th\u00eam v\u00e0o \u1edf giai \u0111o\u1ea1n 0 \u0111\u1ec1u l\u00e0 m\u1ed9t th\u1ee9 b\u1ea1n ph\u1ea3i nh\u1edb \u1edf giai \u0111o\u1ea1n 7. \u0110\u00e2y l\u00e0 to\u00e0n b\u1ed9 c\u00e2y th\u01b0 m\u1ee5c b\u1ea1n s\u1ebd c\u00f3 \u1edf commit lesson 0 end:

build-sudoku-from-scratch/
\u251c\u2500\u2500 .vscode/
\u2502   \u251c\u2500\u2500 extensions.json        # g\u1ee3i \u00fd extension cho ng\u01b0\u1eddi clone repo
\u2502   \u251c\u2500\u2500 launch.json            # c\u1ea5u h\u00ecnh debug LLDB (Mac) + MSVC (Win)
\u2502   \u251c\u2500\u2500 settings.json          # CMake source/build dir + C++ standard
\u2502   \u2514\u2500\u2500 tasks.json             # task "cmake: configure" / "cmake: build" / "run: sudoku"
\u251c\u2500\u2500 src/
\u2502   \u2514\u2500\u2500 main.cpp               # banner Sudoku r\u1ed7ng + in __cplusplus
\u251c\u2500\u2500 .gitignore                 # b\u1ecf build/, .DS_Store, *.exe, CMake cache
\u251c\u2500\u2500 CMakeLists.txt             # khai b\u00e1o project + executable target "sudoku"
\u251c\u2500\u2500 README.md                  # b\u1ea3ng index lesson (start/end SHA)
\u2514\u2500\u2500 sudoku.code-workspace      # multi-root workspace cho VS Code

T\u1ed5ng c\u1ed9ng 9 file. Th\u01b0 m\u1ee5c build/ s\u1ebd xu\u1ea5t hi\u1ec7n sau khi configure, nh\u01b0ng kh\u00f4ng bao gi\u1edd v\u00e0o Git (nh\u1edd .gitignore). M\u1ecdi file \u0111\u1ec1u nh\u1ecf, m\u1ee5c ti\u00eau gi\u1eef cho project hi\u1ec3u \u0111\u01b0\u1ee3c trong m\u1ed9t l\u1ea7n \u0111\u1ecdc.

3. N\u1ed9i dung c\u1ea7n h\u1ecdc

T\u1ea1i sao m\u1ed9t file CMakeLists.txt m\u01b0\u1eddi s\u00e1u d\u00f2ng l\u1ea1i quy\u1ebft \u0111\u1ecbnh vi\u1ec7c IntelliSense tr\u00ean Mac c\u1ee7a b\u1ea1n c\u00f3 g\u1ea1ch \u0111\u1ecf #include <iostream> hay kh\u00f4ng? C\u00e2u tr\u1ea3 l\u1eddi n\u1eb1m \u1edf ch\u1ed7 build system kh\u00f4ng ch\u1ec9 build code \u2014 n\u00f3 c\u00f2n d\u1ea1y editor \u0111\u1ecdc code. B\u00e0i n\u00e0y kh\u00f4ng c\u00f3 thu\u1eadt to\u00e1n, nh\u01b0ng c\u00f3 kh\u00e1 nhi\u1ec1u kh\u00e1i ni\u1ec7m h\u1ea1 t\u1ea7ng m\u00e0 nhi\u1ec1u t\u00e0i li\u1ec7u C++ "nh\u1ea3y th\u1eb3ng v\u00e0o syntax" th\u01b0\u1eddng l\u01b0\u1edbt qua. T\u00f4i s\u1ebd t\u00f3m g\u1ecdn t\u1eebng kh\u00e1i ni\u1ec7m \u0111\u1ec3 b\u1ea1n v\u1eeba c\u00e0i v\u1eeba bi\u1ebft m\u00ecnh \u0111ang c\u00e0i c\u00e1i g\u00ec.

Toolchain \u2260 compiler. Khi b\u1ea1n build m\u1ed9t executable C++, c\u00f3 \u00edt nh\u1ea5t b\u1ed1n th\u00e0nh ph\u1ea7n tham gia: preprocessor x\u1eed l\u00fd #include, compiler d\u1ecbch .cpp th\u00e0nh object file .o/.obj, linker g\u1ed9p object file v\u1edbi standard library th\u00e0nh executable, build system \u0111i\u1ec1u ph\u1ed1i to\u00e0n b\u1ed9. Tr\u00ean Mac, Apple Clang g\u00f3i c\u1ea3 b\u1ed1n v\u00e0o m\u1ed9t binary clang. Tr\u00ean Windows, MSVC t\u00e1ch compiler (cl.exe) kh\u1ecfi linker (link.exe) nh\u01b0ng v\u1eabn g\u1ecdi chung l\u00e0 "toolchain". Khi m\u1ed9t b\u00e0i vi\u1ebft b\u1ea3o "c\u00e0i compiler C++", th\u1ef1c ra \u00fd h\u1ecd l\u00e0 c\u00e0i c\u1ea3 toolchain.

T\u1ea1i sao C++20 ch\u1ee9 kh\u00f4ng ph\u1ea3i C++17. C++20 \u0111em concepts, ranges, std::span, std::format, consteval, v\u00e0 nh\u1eefng c\u1ea3i ti\u1ebfn constexpr cho ph\u00e9p bi\u1ec3u di\u1ec5n thu\u1eadt to\u00e1n solver g\u1ecdn h\u01a1n \u0111\u00e1ng k\u1ec3. B\u00e0i 5 trong series s\u1ebd d\u00f9ng std::ranges::views \u0111\u1ec3 filter \u00f4 tr\u1ed1ng trong board, code \u0111\u00f3 kh\u00f4ng t\u1ed3n t\u1ea1i \u0111\u01b0\u1ee3c \u1edf C++17. So v\u1edbi C++23, h\u1ed7 tr\u1ee3 tr\u00ean Apple Clang c\u00f2n l\u1ed7 ch\u1ed7 (v\u00ed d\u1ee5 std::print ch\u01b0a c\u00f3), n\u00ean 20 l\u00e0 \u0111i\u1ec3m c\u00e2n b\u1eb1ng an to\u00e0n.

CMake source-dir vs build-dir. CMake b\u1eaft bu\u1ed9c t\u00e1ch th\u01b0 m\u1ee5c ch\u1ee9a CMakeLists.txt (source dir) kh\u1ecfi th\u01b0 m\u1ee5c ch\u1ee9a file makefile \u0111\u01b0\u1ee3c sinh ra (build dir). C\u00fa ph\u00e1p hi\u1ec7n \u0111\u1ea1i l\u00e0 cmake -S . -B build, ngh\u0129a l\u00e0 "source \u1edf th\u01b0 m\u1ee5c hi\u1ec7n t\u1ea1i, build v\u00e0o ./build". M\u1ecdi file generated, object, executable, cache \u0111\u1ec1u n\u1eb1m trong build/ v\u00e0 c\u00f3 th\u1ec3 xo\u00e1 an to\u00e0n \u0111\u1ec3 rebuild from scratch.

compile_commands.json. Khi b\u1ea1n set CMAKE_EXPORT_COMPILE_COMMANDS=ON, CMake sinh m\u1ed9t file JSON li\u1ec7t k\u00ea \u0111\u00fang compile flag cho t\u1eebng file .cpp. clangd v\u00e0 CMake Tools extension c\u1ee7a VS Code \u0111\u1ecdc file n\u00e0y \u0111\u1ec3 bi\u1ebft \u0111\u01b0\u1eddng d\u1eabn include th\u1eadt s\u1ef1, nh\u1edd \u0111\u00f3 IntelliSense kh\u00f4ng g\u1ea1ch \u0111\u1ecf nh\u1eefng header n\u00f3 t\u00ecm kh\u00f4ng th\u1ea5y.

Multi-root workspace. M\u1ed9t file .code-workspace cho ph\u00e9p VS Code m\u1edf nhi\u1ec1u th\u01b0 m\u1ee5c nh\u01b0 m\u1ed9t workspace duy nh\u1ea5t, m\u1ed7i th\u01b0 m\u1ee5c c\u00f3 settings ri\u00eang. Series n\u00e0y hi\u1ec7n t\u1ea1i ch\u1ec9 c\u00f3 m\u1ed9t root, nh\u01b0ng \u0111\u1eb7t workspace t\u1eeb ng\u00e0y \u0111\u1ea7u gi\u00fap c\u00e1c b\u00e0i sau (khi c\u00f3 submodule cho test framework) th\u00eam root m\u1edbi m\u00e0 kh\u00f4ng ph\u00e1 settings c\u0169.

.gitignore cho C++ project. Build artefacts (build/, *.o, *.exe, CMakeCache.txt) tuy\u1ec7t \u0111\u1ed1i kh\u00f4ng commit. Ch\u00fang ph\u1ee5 thu\u1ed9c OS + compiler + ng\u00e0y gi\u1edd build, commit v\u00e0o s\u1ebd l\u00e0m repo ph\u00ecnh v\u00e0 r\u1ea5t kh\u00f3 merge gi\u1eefa Mac v\u00e0 Windows.

4. C\u00e1ch l\u00e0m

Commit (start): e0e9b91 \u2014 repo tr\u1ed1ng, ch\u1ec9 c\u00f3 README l\u00e0m ch\u1ed7 \u0111\u1eb7t index. Commit (end-of-lesson): 75e8e38 \u2014 toolchain configure + build s\u1ea1ch.

\u0110\u00e2y l\u00e0 B\u00e0i 0 \u2014 Setup toolchain song song Mac + Windows. L\u00e0m tu\u1ea7n t\u1ef1 t\u1eebng b\u01b0\u1edbc, \u0111\u1eebng nh\u1ea3y. \u0110a s\u1ed1 s\u1ef1 c\u1ed1 "build kh\u00f4ng ch\u1ea1y" \u1edf c\u00e1c b\u00e0i sau quay v\u1ec1 v\u00ec b\u01b0\u1edbc 1 ho\u1eb7c b\u01b0\u1edbc 3 \u1edf b\u00e0i n\u00e0y b\u1ecb l\u00e0m t\u1eaft.

B\u01b0\u1edbc 1 \u2014 C\u00e0i compiler C++20

Tr\u00ean macOS: m\u1edf Terminal v\u00e0 ch\u1ea1y l\u1ec7nh d\u01b0\u1edbi \u0111\u00e2y. N\u1ebfu b\u1ea1n \u0111\u00e3 c\u00e0i Xcode \u0111\u1ea7y \u0111\u1ee7 tr\u01b0\u1edbc \u0111\u00f3, l\u1ec7nh s\u1ebd b\u00e1o \u0111\u00e3 c\u00f3 v\u00e0 tho\u00e1t; v\u1eabn n\u00ean ch\u1ea1y \u0111\u1ec3 ch\u1eafc ch\u1eafn:

xcode-select --install
clang++ --version

B\u1ea3n clang Apple g\u1eafn theo macOS 14+ ch\u1ea1y C++20 \u1ed5n \u0111\u1ecbnh. N\u1ebfu clang++ --version b\u00e1o phi\u00ean b\u1ea3n d\u01b0\u1edbi 14, h\u00e3y update macOS ho\u1eb7c c\u00e0i Xcode m\u1edbi h\u01a1n t\u1eeb App Store. Khuy\u1ebfn ngh\u1ecb th\u1ef1c t\u1ebf cho series n\u00e0y: macOS 14.4+ v\u1edbi Apple clang version 15.0.0 tr\u1edf l\u00ean.

Tr\u00ean Windows: t\u1ea3i Visual Studio Build Tools 2022 ho\u1eb7c Visual Studio Community 2022 t\u1eeb trang ch\u1ee7 Microsoft, ch\u1ecdn workload Desktop development with C++. Sau khi c\u00e0i xong, m\u1edf x64 Native Tools Command Prompt for VS 2022 t\u1eeb Start Menu r\u1ed3i ch\u1ea1y:

cl /Bv
cmake --version

N\u1ebfu cl kh\u00f4ng nh\u1eadn, b\u1ea1n \u0111ang m\u1edf terminal Windows th\u01b0\u1eddng thay v\u00ec Developer Command Prompt. M\u1edf \u0111\u00fang c\u00e1i c\u00f3 ch\u1eef "Native Tools".

B\u01b0\u1edbc 2 \u2014 C\u00e0i CMake v\u00e0 Git

Tr\u00ean macOS, d\u00f9ng Homebrew l\u00e0 \u0111\u01a1n gi\u1ea3n nh\u1ea5t:

brew install cmake git
cmake --version
git --version

Tr\u00ean Windows, c\u00e1ch an to\u00e0n nh\u1ea5t l\u00e0 c\u00e0i b\u1eb1ng installer t\u1eeb trang ch\u1ee7 (cmake.org, git-scm.com) v\u00e0 TICK \u00f4 "Add to PATH" trong qu\u00e1 tr\u00ecnh c\u00e0i. Chocolatey c\u0169ng d\u00f9ng \u0111\u01b0\u1ee3c n\u1ebfu b\u1ea1n quen:

choco install cmake git -y
cmake --version
git --version

C\u1ea5u h\u00ecnh Git l\u1ea7n \u0111\u1ea7u:

git config --global user.name "vytharion"
git config --global user.email "you@example.com"
git config --global init.defaultBranch main

B\u01b0\u1edbc 3 \u2014 C\u00e0i VS Code v\u00e0 extension

T\u1ea3i VS Code t\u1eeb trang ch\u1ee7. \u1ede ph\u1ea7n Extensions, c\u00e0i t\u1ed1i thi\u1ec3u ba extension:

  • ms-vscode.cpptools (C/C++ c\u1ee7a Microsoft)
  • ms-vscode.cmake-tools (CMake Tools)
  • llvm-vs-code-extensions.vscode-clangd (clangd, optional nh\u01b0ng khuy\u1ebfn ngh\u1ecb m\u1ea1nh tr\u00ean macOS)

C\u00f3 m\u1ed9t c\u00e2u h\u1ecfi r\u1ea5t hay tranh c\u00e3i: d\u00f9ng IntelliSense c\u1ee7a Microsoft hay clangd? IntelliSense \u1ed5n tr\u00ean Windows, nhanh c\u1ea5u h\u00ecnh, hi\u1ec3u r\u1ea5t s\u00e2u header MSVC. clangd th\u00ec l\u01b0\u1edbi warning g\u1eaft h\u01a1n, g\u1ee3i \u00fd refactor \u0111\u00fang h\u01a1n, \u0111\u1eb7c bi\u1ec7t t\u1ed1t tr\u00ean macOS/Linux. Khuy\u1ebfn ngh\u1ecb th\u1ef1c d\u1ee5ng: tr\u00ean Windows d\u00f9ng IntelliSense, tr\u00ean Mac d\u00f9ng clangd. C\u1ea3 hai c\u00f9ng \u0111\u1ecdc compile_commands.json n\u00ean c\u1ea5u h\u00ecnh CMake l\u00e0 chung.

B\u01b0\u1edbc 4 \u2014 T\u1ea1o CMakeLists.txt

T\u1ea1o th\u01b0 m\u1ee5c build-sudoku-from-scratch/ r\u1ed3i t\u1ea1o file CMakeLists.txt \u1edf g\u1ed1c:

cmake_minimum_required(VERSION 3.20)

project(sudoku
    VERSION 0.1.0
    DESCRIPTION "Build a Sudoku game + solver from scratch"
    LANGUAGES CXX
)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

if(MSVC)
    add_compile_options(/W4 /permissive-)
else()
    add_compile_options(-Wall -Wextra -Wpedantic)
endif()

add_executable(sudoku
    src/main.cpp
)

Ba d\u00f2ng CMAKE_CXX_* \u1edf gi\u1eefa ch\u1ed1t c\u1ee9ng chu\u1ea9n ng\u00f4n ng\u1eef l\u00e0 C++20 v\u00e0 C\u1ea4M compiler t\u1ef1 "th\u1ea3 l\u1ecfng" sang C++17 n\u1ebfu kh\u00f4ng h\u1ed7 tr\u1ee3. CMAKE_EXPORT_COMPILE_COMMANDS=ON l\u00e0 d\u00f2ng quan tr\u1ecdng nh\u1ea5t v\u1edbi ng\u01b0\u1eddi d\u00f9ng macOS: thi\u1ebfu n\u00f3, clangd s\u1ebd kh\u00f4ng bi\u1ebft flag include.

B\u01b0\u1edbc 5 \u2014 Vi\u1ebft src/main.cpp

#include <iostream>

namespace {

constexpr const char* kBanner = R"(
+-------+-------+-------+
| . . . | . . . | . . . |
| . . . | . . . | . . . |
| . . . | . . . | . . . |
+-------+-------+-------+
| . . . | . . . | . . . |
| . . . | . . . | . . . |
| . . . | . . . | . . . |
+-------+-------+-------+
| . . . | . . . | . . . |
| . . . | . . . | . . . |
| . . . | . . . | . . . |
+-------+-------+-------+
)";

} // namespace

int main() {
    std::cout << "sudoku - toolchain check\
";
    std::cout << "C++ standard: " << __cplusplus << '\
';
    std::cout << kBanner << '\
';
    return 0;
}

Macro __cplusplus tr\u1ea3 v\u1ec1 m\u1ed9t s\u1ed1 nguy\u00ean \u0111\u1ecbnh danh chu\u1ea9n C++. V\u1edbi C++20 n\u00f3 tr\u1ea3 202002. \u0110\u00e2y l\u00e0 c\u00e1ch ki\u1ec3m tra nhanh nh\u1ea5t r\u1eb1ng compiler th\u1eadt s\u1ef1 \u0111ang d\u1ecbch \u1edf chu\u1ea9n b\u1ea1n y\u00eau c\u1ea7u.

B\u01b0\u1edbc 6 \u2014 T\u1ea1o .vscode/tasks.json

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "cmake: configure",
            "type": "shell",
            "command": "cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug"
        },
        {
            "label": "cmake: build",
            "type": "shell",
            "command": "cmake --build build --config Debug",
            "group": { "kind": "build", "isDefault": true },
            "dependsOn": "cmake: configure"
        }
    ]
}

Ph\u1ea7n .vscode/launch.json, .vscode/settings.json, .vscode/extensions.json xem repo (commit 75e8e38). M\u1ed7i file \u00edt h\u01a1n 30 d\u00f2ng.

B\u01b0\u1edbc 7 \u2014 Configure v\u00e0 build

M\u1edf terminal trong th\u01b0 m\u1ee5c project r\u1ed3i ch\u1ea1y:

cmake -S . -B build
cmake --build build

Tr\u00ean Windows, m\u1edf x64 Native Tools Command Prompt for VS 2022 r\u1ed3i ch\u1ea1y \u0111\u00fang hai l\u1ec7nh tr\u00ean (CMake s\u1ebd t\u1ef1 ch\u1ecdn Visual Studio generator). L\u1ec7nh build s\u1ebd in d\u00f2ng [100%] Built target sudoku tr\u00ean macOS ho\u1eb7c sudoku.vcxproj -> ...sudoku.exe tr\u00ean Windows.

B\u01b0\u1edbc 8 \u2014 Kh\u1edfi t\u1ea1o Git v\u00e0 push l\u00ean GitHub

git init
git add .
git commit -m "lesson 0 end: VS Code + C++20 toolchain + CMake project builds and runs"
gh repo create vytharion/build-sudoku-from-scratch --public --source=. --push

L\u1ec7nh gh c\u1ea7n c\u00e0i GitHub CLI v\u00e0 gh auth login tr\u01b0\u1edbc. N\u1ebfu ch\u01b0a d\u00f9ng gh, b\u1ea1n c\u0169ng c\u00f3 th\u1ec3 t\u1ea1o repo tr\u00ean web r\u1ed3i git remote add origin ... && git push -u origin main.

5. B\u00e0i h\u1ecdc ch\u1ed1t

C\u00f3 ba \u0111i\u1ec1u n\u1ebfu b\u1ea1n nh\u1edb \u0111\u00fang sau b\u00e0i n\u00e0y, m\u1ecdi b\u00e0i sau d\u1ec5 h\u01a1n r\u1ea5t nhi\u1ec1u.

Th\u1ee9 nh\u1ea5t, toolchain ph\u1ea3i \u0111\u01b0\u1ee3c c\u1ed1 \u0111\u1ecbnh b\u1eb1ng file, kh\u00f4ng b\u1eb1ng "m\u00e1y c\u1ee7a t\u00f4i". CMakeLists.txt ghim version 3.20, CMAKE_CXX_STANDARD 20, CMAKE_CXX_EXTENSIONS OFF. Ba d\u00f2ng n\u00e0y l\u00e0 h\u1ee3p \u0111\u1ed3ng gi\u1eefa code c\u1ee7a b\u1ea1n v\u00e0 compiler. B\u1ea5t k\u1ef3 m\u00e1y n\u00e0o configure \u0111\u01b0\u1ee3c file CMake n\u00e0y \u0111\u1ec1u build ra c\u00f9ng m\u1ed9t binary (l\u1eadp lu\u1eadn, kh\u00f4ng byte-identical).

Th\u1ee9 hai, out-of-tree build l\u00e0 m\u1eb7c \u0111\u1ecbnh. M\u1ecdi th\u1ee9 generated n\u1eb1m trong build/. Khi build h\u1ecfng b\u1ea5t k\u1ef3 l\u00fd do g\u00ec, xo\u00e1 build/ r\u1ed3i configure l\u1ea1i l\u00e0 m\u1ed9t thao t\u00e1c an to\u00e0n 99% tr\u01b0\u1eddng h\u1ee3p. \u0110\u00e2y l\u00e0 kh\u00e1c bi\u1ec7t l\u1edbn so v\u1edbi Makefile c\u1ed5 \u0111i\u1ec3n, n\u01a1i make clean \u0111\u00f4i khi \u0111\u1ec3 s\u00f3t object file.

Th\u1ee9 ba, VS Code kh\u00f4ng ph\u1ea3i compiler, n\u00f3 ch\u1ec9 l\u00e0 m\u1ed9t editor \u0111\u1eb9p ch\u1ea1y b\u00ean tr\u00ean toolchain. IntelliSense g\u1ea1ch \u0111\u1ecf kh\u00f4ng c\u00f3 ngh\u0129a l\u00e0 code sai. Compiler kh\u00f4ng l\u1ed7i m\u1edbi c\u00f3 ngh\u0129a l\u00e0 code sai. T\u00e1ch hai c\u1ea3m gi\u00e1c n\u00e0y ra s\u1ebd ti\u1ebft ki\u1ec7m nhi\u1ec1u gi\u1edd debug sau n\u00e0y.

6. C\u00e1ch t\u1ef1 ki\u1ec3m tra

Ch\u1ea1y \u0111\u00fang c\u00e1c l\u1ec7nh sau, k\u1ebft qu\u1ea3 ph\u1ea3i kh\u1edbp.

cmake --version
# >= 3.20

cmake -S . -B build
# exit 0, kh\u00f4ng c\u00f3 d\u00f2ng "ERROR"

cmake --build build
# exit 0, c\u00f3 d\u00f2ng "Built target sudoku" ho\u1eb7c t\u01b0\u01a1ng \u0111\u01b0\u01a1ng tr\u00ean Windows

./build/sudoku       # macOS / Linux
# Windows: .\build\Debug\sudoku.exe

Output ph\u1ea3i c\u00f3 d\u00f2ng C++ standard: 202002. N\u1ebfu l\u00e0 201703, b\u1ea1n \u0111\u00e3 c\u00e0i compiler qu\u00e1 c\u0169 ho\u1eb7c CMake kh\u00f4ng \u00e9p \u0111\u01b0\u1ee3c chu\u1ea9n. Quay l\u1ea1i B\u01b0\u1edbc 1.

Output c\u0169ng ph\u1ea3i c\u00f3 banner 9\u00d79 v\u1edbi k\u00fd t\u1ef1 + \u1edf c\u00e1c g\u00f3c box. N\u1ebfu banner xu\u1ea5t hi\u1ec7n m\u00e9o l\u1ec7ch d\u1ea5u ho\u1eb7c k\u00e8m "warning: trigraph", b\u1ea1n \u0111ang d\u00f9ng compiler thi\u1ebfu h\u1ed7 tr\u1ee3 raw string literals C++11 \u2014 g\u1ea7n nh\u01b0 kh\u00f4ng bao gi\u1edd x\u1ea3y ra tr\u00ean Apple Clang hay MSVC 2022 hi\u1ec7n \u0111\u1ea1i, nh\u01b0ng n\u1ebfu x\u1ea3y ra th\u00ec compiler th\u1ef1c s\u1ef1 r\u1ea5t c\u0169.

Bonus check: m\u1edf src/main.cpp trong VS Code, \u0111\u1eb7t con tr\u1ecf l\u00ean __cplusplus, hover. Tooltip ph\u1ea3i hi\u1ec3n th\u1ecb Expands to: 202002L. N\u1ebfu IntelliSense n\u00f3i kh\u00e1c, settings.json \u0111ang n\u00f3i d\u1ed1i CMake \u2014 s\u1eeda C_Cpp.default.cppStandard v\u1ec1 c++20.

7. L\u1ed7i th\u01b0\u1eddng g\u1eb7p / pitfall

Tri\u1ec7u ch\u1ee9ngNguy\u00ean nh\u00e2nC\u00e1ch x\u1eed l\u00fd
clang: command not found (macOS)Ch\u01b0a c\u00e0i Xcode Command Line ToolsCh\u1ea1y xcode-select --install, \u0111\u1ee3i installer xong r\u1ed3i m\u1edf terminal m\u1edbi
'cl' is not recognized (Windows)\u0110ang m\u1edf Windows Terminal th\u01b0\u1eddng, kh\u00f4ng ph\u1ea3i Developer Command PromptM\u1edf x64 Native Tools Command Prompt for VS 2022 t\u1eeb Start Menu
Required CMake 3.20, found 3.16CMake c\u0169 tr\u00ean h\u1ec7 th\u1ed1ngmacOS: brew upgrade cmake. Windows: c\u00e0i l\u1ea1i t\u1eeb cmake.org v\u00e0 tick "Add to PATH"
clangd b\u00e1o 'iostream' file not foundThi\u1ebfu compile_commands.json \u1edf rootTh\u00eam CMAKE_EXPORT_COMPILE_COMMANDS ON, sau \u0111\u00f3 ln -s build/compile_commands.json . tr\u00ean macOS
Error: generator: Ninja khi configurebuild/ c\u00f2n cache c\u1ee7a generator c\u0169rm -rf build r\u1ed3i configure l\u1ea1i
.DS_Store l\u1eabn v\u00e0o commitmacOS Finder t\u1ef1 sinh metadataTh\u00eam .DS_Store v\u00e0o .gitignore, git rm --cached **/.DS_Store
permission denied khi ch\u1ea1y ./build/sudokuBuild dir n\u1eb1m tr\u00ean \u1ed5 external b\u1ecb mount noexecBuild v\u00e0o \u1ed5 c\u1ee9ng trong (home directory)
error: C++20 is not supportedCompiler qu\u00e1 c\u0169 (Apple clang < 12, MSVC 2019 RTM)Update compiler

8. Kh\u00f4ng gian t\u1ef1 h\u1ecdc

B\u00e0i n\u00e0y c\u1ed1 \u00fd ch\u1ec9 d\u00f9ng t\u1ed1i thi\u1ec3u c\u00f4ng c\u1ee5 \u0111\u1ec3 kh\u1ecfi lo\u1ea1n. N\u1ebfu b\u1ea1n th\u1ea5y h\u1ee9ng th\u00fa, c\u00f3 v\u00e0i h\u01b0\u1edbng ti\u1ebfn s\u00e2u:

  • CMake Presets. File CMakePresets.json cho ph\u00e9p \u0111\u1ecbnh ngh\u0129a c\u1ea5u h\u00ecnh build d\u00f9ng chung gi\u1eefa CLI v\u00e0 VS Code, gi\u1ea3m boilerplate trong tasks.json. \u0110\u1ecdc t\u00e0i li\u1ec7u ch\u00ednh th\u1ee9c t\u1ea1i https://cmake.org/cmake/help/latest/manual/cmake-presets.7.html.
  • Ninja generator. M\u1eb7c \u0111\u1ecbnh tr\u00ean macOS, CMake sinh Makefiles. C\u00e0i Ninja (brew install ninja) r\u1ed3i cmake -G Ninja -S . -B build \u2014 incremental build nhanh h\u01a1n Makefiles ~30 \u0111\u1ebfn 40% v\u1edbi project l\u1edbn.
  • clangd \u1edf ch\u1ebf \u0111\u1ed9 background indexing. \u0110\u1ecdc https://clangd.llvm.org/installation v\u00e0 b\u1eadt clangd: arguments v\u1edbi --background-index. L\u1ea7n \u0111\u1ea7u m\u1edf file s\u1ebd ch\u1eadm 5-10 gi\u00e2y nh\u01b0ng goto-definition sau \u0111\u00f3 t\u1ee9c th\u00ec.
  • Compare g++ v\u00e0 clang++ v\u00e0 cl.exe. Build c\u00f9ng m\u1ed9t file main.cpp qua ba compiler, \u0111o time cmake --build build v\u00e0 so warning text.
  • GitHub Actions cho cross-platform CI. Sau khi push xong, th\u00eam .github/workflows/build.yml build matrix [ubuntu-latest, macos-latest, windows-latest] \u0111\u1ec3 m\u1ed7i push x\u00e1c nh\u1eadn c\u1ea3 ba OS \u0111\u1ec1u xanh. Workflow n\u00e0y s\u1ebd l\u00e0 b\u00e0i t\u1eadp ch\u00ednh c\u1ee7a m\u1ed9t lesson ngo\u1ea1i bi\u00ean sau n\u00e0y.
  • Conan ho\u1eb7c vcpkg. Khi series ch\u1ea1m \u0111\u1ebfn lesson v\u1ec1 test framework (Catch2 hay GoogleTest), m\u1ed9t package manager C++ s\u1ebd ti\u1ec7n h\u01a1n submodule. T\u00ecm hi\u1ec3u vcpkg tr\u01b0\u1edbc v\u00ec n\u00f3 h\u1ee3p v\u1edbi MSVC tr\u00ean Windows.

9. B\u00e0i t\u1eadp cu\u1ed1i b\u00e0i

  1. \u0110\u1ed5i CMAKE_CXX_STANDARD trong CMakeLists.txt t\u1eeb 20 th\u00e0nh 17. Xo\u00e1 build/, configure v\u00e0 build l\u1ea1i. X\u00e1c minh __cplusplus \u0111\u1ed5i gi\u00e1 tr\u1ecb, ghi l\u1ea1i con s\u1ed1 \u0111\u00fang.
  2. Th\u00eam flag -Werror (macOS/Linux) ho\u1eb7c /WX (Windows) v\u00e0o add_compile_options. C\u1ed1 t\u00ecnh th\u00eam d\u00f2ng int unused = 0; ngay trong main. Build, \u0111\u1ecdc message l\u1ed7i \u0111\u1ea7u ti\u00ean compiler tr\u1ea3 ra, s\u1eeda.
  3. T\u00e1ch kBanner t\u1eeb main.cpp th\u00e0nh m\u1ed9t file m\u1edbi src/banner.h. Update main.cpp \u0111\u1ec3 #include "banner.h". Update CMakeLists.txt n\u1ebfu c\u1ea7n. Build s\u1ea1ch.
  4. T\u1ea1o branch feature/clang-format. Th\u00eam file .clang-format (chu\u1ea9n Google ho\u1eb7c LLVM). Format l\u1ea1i main.cpp b\u1eb1ng clang-format -i src/main.cpp. Commit branch, l\u00e0m PR nh\u1ecf v\u1ec1 main.
  5. (challenge) Vi\u1ebft script scripts/build.sh cho macOS v\u00e0 scripts/build.ps1 cho Windows wrap \u0111\u00fang hai l\u1ec7nh cmake -S . -B build && cmake --build build. Script ph\u1ea3i: exit code 0 khi th\u00e0nh c\u00f4ng, \u2260 0 khi fail, in t\u1ed5ng th\u1eddi gian build. Test tr\u00ean c\u1ea3 hai n\u1ec1n t\u1ea3ng n\u1ebfu c\u00f3 m\u00e1y.

10. \u0110\u00e1p \u00e1n b\u00e0i t\u1eadp

Repository

Full source at https://github.com/vytharion/build-sudoku-from-scratch \u2014 to\u00e0n b\u1ed9 commit c\u1ee7a series s\u1ebd \u0111\u01b0\u1ee3c push l\u00ean \u0111\u00e2y, m\u1ed7i b\u00e0i l\u00e0 m\u1ed9t (start, end) c\u1eb7p.

\u2192 Next: 01-board-representation \u2014 B\u00e0i 1: Bi\u1ec3u di\u1ec5n b\u00e0n Sudoku 9\u00d79 b\u1eb1ng struct v\u00e0 bitmask.