diff --git a/doc/wiki/Developing-with-VS-Code.md b/doc/wiki/Developing-with-VS-Code.md new file mode 100644 index 0000000000..6cf89bdd5d --- /dev/null +++ b/doc/wiki/Developing-with-VS-Code.md @@ -0,0 +1,66 @@ +# Developing GAMER with Visual Studio Code + +This guide provides step-by-step instructions on how to set up and use Visual Studio Code (VS Code) for developing the GAMER codebase. + +## Setup + +### Prerequisites + +- **Quick Start**: Follow the instructions in the [[Quick Start | Quick-Start]] guide to download GAMER and do at least one [[demo | Quick-Start:-1D-Shock-Tube]]. +- **Visual Studio Code**: Download and install from [https://code.visualstudio.com/](https://code.visualstudio.com/). +- **C/C++ Extension**: Install the "C/C++" extension from the VS Code Marketplace. + +### Setting up the workspace + +1. **Launch VS Code**. +2. **Open the GAMER Project Folder**: + - Go to `File` > `Open Folder...`. + - Select your GAMER project directory. + +### Disabling auto-formatting + +To disable auto-formatting in VS Code, add the following to your `settings.json`: + +Access `settings.json` by navigating to `File` > `Preferences` > `Settings`, then search for `C_Cpp.formatting` and set it to `"disabled"`. + +### Configuring VS Code to integrate with GAMER + +Run the following script from the root directory of the GAMER project: +```bash +sh tool/vscode/copy_to_vscode.sh +``` +This script copies the necessary configuration files to the `.vscode` directory, integrating GAMER with VS Code. + +## Developing with VS Code + +Before starting to run the tasks below, **set the working directory** by selecting `Terminal` > `Run Task...` > `set-working-bin` and entering the name of the working directory under `bin/` where the input files are located. + +### Configure GAMER + +Select `Terminal` > `Run Task...` > `build-GAMER` to configure GAMER with the `generate_make.sh` script in your working directory. + +### Build + +After configuring GAMER with [configure.py](https://github.com/gamer-project/gamer/wiki/Installation%3A-Configure.py) or `generate_make.sh`, select `Terminal` > `Run Build Task...` or press `Ctrl + Shift + B` to start the build task. This will update the macros, providing IntelliSense highlighting support. + +> [!IMPORTANT] +> To make sure the debugger works correctly, ensure the compiler flags in `Makefile` are set to `-g -O0`. (TBD: Add a argument to `configure.py` to set the flags.) + +### Start debugging + +To start debugging GAMER, select `Run` > `Start Debugging` or press `F5`. After enter the working directory, the debugger will be launched. See the [official documentation](https://code.visualstudio.com/docs/editor/debugging) to learn more about debugging with VS Code. + +> [!NOTE] +> If you are using macOS and `gdb` is not supported, then you need to setup `lldb` as the debugger in `launch.json` by yourself. You can refer to the [official documentation](https://code.visualstudio.com/docs/cpp/launch-json-reference) for more information. + +### Clean working directory + +Select `Terminal` > `Run Task...` > `clean-work-dir` to clean the working directory with the `clean.sh` script in your working directory. + +## Understanding Configuration Files + +These are the configuration files that are copied to the `.vscode` directory: +- `c_cpp_properties.json`: Configures IntelliSense settings, including include paths and macros. See the [official documentation](https://code.visualstudio.com/docs/cpp/c-cpp-properties-schema-reference) for more information and the [document of IntelliSense](https://code.visualstudio.com/docs/editor/intellisense) to learn about IntelliSense in VS Code. +- `launch.json`: Contains debugging configurations such as executable paths and arguments. See the [official documentation](https://code.visualstudio.com/docs/cpp/launch-json-reference) for more information. +- `tasks.json`: Specifies the build and other dependent tasks. Learn more about [tasks in VS Code](https://code.visualstudio.com/docs/editor/tasks). +- `gamercpp.natvis`: Defines custom visualizations for data structures in the debugger. Learn more about [customizing the visualization of data structures](https://learn.microsoft.com/en-us/visualstudio/debugger/create-custom-views-of-native-objects?view=vs-2022). diff --git a/doc/wiki/_Sidebar.md b/doc/wiki/_Sidebar.md index ce72b0b81c..f2e714f956 100644 --- a/doc/wiki/_Sidebar.md +++ b/doc/wiki/_Sidebar.md @@ -33,3 +33,4 @@ * [[ ELBDM Spectral Interpolation | ELBDM-Spectral-Interpolation ]] * [[ Style Guide | Style-Guide ]] * [[ How to Contribute | How-to-Contribute ]] + * [[ Developing with VS Code | Developing-with-VS-Code ]] diff --git a/tool/vscode/README.md b/tool/vscode/README.md new file mode 100644 index 0000000000..e82c93be24 --- /dev/null +++ b/tool/vscode/README.md @@ -0,0 +1,19 @@ +# Integrating GAMER with Visual Studio Code + +Run `sh tool/vscode/copy_to_vscode.sh` to copy necessary files to the `.vscode` directory to integrate GAMER with VS Code. + +Please check the [wiki](https://github.com/gamer-project/gamer/wiki/Developing-with-VS-Code) for more information. + +## Files in this directory +- `c_cpp_properties.json`: Contains the IntelliSense configuration for VS Code. +- `gamercpp.natvis`: Contains the visualization configuration for VS Code debugger. +- `launch.json`: Contains the debug configuration for VS Code. +- `tasks.json`: Contains the build configuration for VS Code. +- `extract_macros.py`: Script to extract the macros from the `Makefile.log` to `c_cpp_properties.json`. +- `copy_to_vscode.sh`: Script to copy the above files to `.vscode` directory. +- `bin_working`: File for storing the name of the working directory under `bin/`. +- `set_bin_working.sh`: Script to set up the path of the input files and the executable. +- `build.sh`: Script for the build task. +- `clean_work_dir.sh`: Script for the clean task. +- `config.sh`: Script for the configuration task. +- `README.md`: This file. diff --git a/tool/vscode/bin_working b/tool/vscode/bin_working new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tool/vscode/build.sh b/tool/vscode/build.sh new file mode 100644 index 0000000000..eb6a4d603d --- /dev/null +++ b/tool/vscode/build.sh @@ -0,0 +1,19 @@ +PYTHON=python3 + +bin_working=$(cat bin_working) +if [ -z "${bin_working}" ]; then + echo "Error: Please set the working directory by the task 'set-working-bin' first." + exit 1 +fi + +cd ../src +make clean + +cd ../.vscode +${PYTHON} extract_macros.py + +cd ../src +make -j 8 + +cd ../bin/${bin_working}/ +cp ../gamer . diff --git a/tool/vscode/c_cpp_properties.json b/tool/vscode/c_cpp_properties.json new file mode 100644 index 0000000000..cfdaaa577f --- /dev/null +++ b/tool/vscode/c_cpp_properties.json @@ -0,0 +1,15 @@ +{ + "configurations": [ + { + "name": "Linux", + "includePath": [ + "${default}", + "${workspaceFolder}/include" + ], + "cStandard": "c17", + "cppStandard": "gnu++17", + "intelliSenseMode": "linux-gcc-x64" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/tool/vscode/clean_work_dir.sh b/tool/vscode/clean_work_dir.sh new file mode 100644 index 0000000000..83b71dd818 --- /dev/null +++ b/tool/vscode/clean_work_dir.sh @@ -0,0 +1,8 @@ +bin_working=$(cat bin_working) +if [ -z "${bin_working}" ]; then + echo "Error: Please set the working directory by the task 'set-working-bin' first." + exit 1 +fi + +cd ../bin/${bin_working}/ +sh clean.sh \ No newline at end of file diff --git a/tool/vscode/config.sh b/tool/vscode/config.sh new file mode 100644 index 0000000000..d3fcf06175 --- /dev/null +++ b/tool/vscode/config.sh @@ -0,0 +1,9 @@ +bin_working=$(cat bin_working) +if [ -z "${bin_working}" ]; then + echo "Error: Please set the working directory by the task 'set-working-bin' first." + exit 1 +fi + +cd ../src +cp ../bin/${bin_working}/generate_make.sh . +sh generate_make.sh \ No newline at end of file diff --git a/tool/vscode/copy_to_vscode.sh b/tool/vscode/copy_to_vscode.sh new file mode 100644 index 0000000000..8791289adc --- /dev/null +++ b/tool/vscode/copy_to_vscode.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +# Change to the directory where the script is located +cd "$(dirname "$0")" + +# Set source and destination paths relative to the script's location +SOURCE_DIR="." +TARGET_DIR="../../.vscode" + +# Specify files to exclude (space-separated list, e.g., "file1 file2") +EXCLUDE_FILES="copy_to_vscode.sh README.md" + +if [ ! -d "$TARGET_DIR" ]; then + echo "Target directory $TARGET_DIR does not exist." + mkdir -p "$TARGET_DIR" + echo "Target directory $TARGET_DIR created." +fi + +# Function to check if a file is in the exclude list +is_excluded() { + for excluded in $EXCLUDE_FILES; do + if [ "$excluded" = "$1" ]; then + return 0 + fi + done + return 1 +} + +for file in "$SOURCE_DIR"/*; do + filename=$(basename "$file") + + if is_excluded "$filename"; then + continue + fi + + if [ -e "$TARGET_DIR/$filename" ]; then + echo "File $filename already exists in $TARGET_DIR. Overwrite? (y/n)" + read -r answer + + if [ "$answer" = "y" ] || [ "$answer" = "Y" ]; then + cp "$file" "$TARGET_DIR/$filename" + echo "$filename overwritten." + else + echo "$filename not copied." + fi + else + cp "$file" "$TARGET_DIR/$filename" + echo "$filename copied." + fi + +done diff --git a/tool/vscode/extract_macros.py b/tool/vscode/extract_macros.py new file mode 100644 index 0000000000..58272ead59 --- /dev/null +++ b/tool/vscode/extract_macros.py @@ -0,0 +1,56 @@ +import re +import json + +''' +This script updates the "defines" section in the .vscode/c_cpp_properties.json file in Visual Studio Code +by directly parsing the Makefile.log file to extract relevant compiler macros (definitions). It provides an automated +way to synchronize project-specific preprocessor definitions with the VSCode configuration. This approach allows +VSCode to recognize the defines directly from your build configuration, improving VSCode IntelliSense and error +detection without manual intervention. + +Usage: +1. Place this script under the `.vscode` folder of your project. +2. Set the paths to `Makefile.log` and `c_cpp_properties.json` in the script as follows: + - `makefile_log_path`: Path to `Makefile.log`, which contains compiler settings output (default: "../src/Makefile.log"). + - `c_cpp_properties_path`: Path to the VSCode C++ configuration file (default: "c_cpp_properties.json"). +3. Run the script each time `Makefile.log` is updated, or set it as a pre-build or post-build task in VSCode + to keep the configuration in sync. +''' +# Path to Makefile.log and c_cpp_properties.json +makefile_log_path = "../src/Makefile.log" +c_cpp_properties_path = "c_cpp_properties.json" + +# Pattern to match the setting in the format of " MODEL : HYDRO" +pattern = re.compile(r":\s+(\w+)\s*:\s+(\w+)") +defines = [] + +# Read Makefile.log and extract macros +with open(makefile_log_path, 'r') as log_file: + print(f"Reading {makefile_log_path} and extracting defines...") + for line in log_file: + match = pattern.search(line) + if match: + key, value = match.groups() + if value == 'False': + continue + elif value == 'True': + defines.append(f"{key}") + else: + defines.append(f"{key}={value}") +print(f"Extracted {len(defines)} macros from {makefile_log_path}.") + +# Load c_cpp_properties.json +with open(c_cpp_properties_path, 'r') as cpp_properties_file: + print(f"Loading {c_cpp_properties_path}...") + cpp_properties = json.load(cpp_properties_file) + +# Update the "defines" array in c_cpp_properties.json +print("Updating defines in c_cpp_properties.json...") +cpp_properties['configurations'][0]['defines'] = defines + +# Write the updated content back to c_cpp_properties.json +with open(c_cpp_properties_path, 'w') as cpp_properties_file: + print(f"Writing updates to {c_cpp_properties_path}...") + json.dump(cpp_properties, cpp_properties_file, indent=4) + +print("Update completed successfully.") diff --git a/tool/vscode/gamercpp.natvis b/tool/vscode/gamercpp.natvis new file mode 100644 index 0000000000..81dd2d3fd4 --- /dev/null +++ b/tool/vscode/gamercpp.natvis @@ -0,0 +1,7 @@ + + + + Timer running + Timer stop: {Time*1.0e-6} sec + + diff --git a/tool/vscode/launch.json b/tool/vscode/launch.json new file mode 100644 index 0000000000..c77de7fd65 --- /dev/null +++ b/tool/vscode/launch.json @@ -0,0 +1,40 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Debug GAMER", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/bin/${input:bin-working}/gamer", + "args": [], + "stopAtEntry": true, + "cwd": "${workspaceFolder}/bin/${input:bin-working}/", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ], + "miDebuggerPath": "/usr/bin/gdb", + "miDebuggerArgs": "-quiet", + "logging": { + "engineLogging": false + }, + "internalConsoleOptions": "openOnSessionStart", + "preLaunchTask": "clean-work-dir", + "visualizerFile": "${workspaceFolder}/.vscode/gamercpp.natvis", + "showDisplayString": true + } + ], + "inputs": [ + { + "id": "bin-working", + "type": "promptString", + "description": "Enter the working directory under bin/." + } + ] +} \ No newline at end of file diff --git a/tool/vscode/set_bin_working.sh b/tool/vscode/set_bin_working.sh new file mode 100644 index 0000000000..4e08330f81 --- /dev/null +++ b/tool/vscode/set_bin_working.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +cd "$(dirname "$0")" + +# If $1 is given, use it as $chosen, else prompt the user +if [ -n "$1" ]; then + chosen="$1" +else + echo "Directories under bin/:" + for dir in ../bin/*/; do + echo "$(basename "$dir")" + done + echo -n "Enter a directory name from the above list: " + read chosen +fi + +printf "%s" "$chosen" > bin_working +echo "bin_working updated." \ No newline at end of file diff --git a/tool/vscode/tasks.json b/tool/vscode/tasks.json new file mode 100644 index 0000000000..3bf4e3a10b --- /dev/null +++ b/tool/vscode/tasks.json @@ -0,0 +1,59 @@ +{ + "tasks": [ + { + "label": "build-GAMER", + "type": "shell", + "command": "sh build.sh", + "group": { + "kind": "build", + "isDefault": true + }, + "options": { + "cwd": "${workspaceFolder}/.vscode" + }, + "detail": "After you configure the Makefile, run this task to build the project." + }, + { + "label": "config-GAMER", + "type": "shell", + "command": "sh config.sh", + "options": { + "cwd": "${workspaceFolder}/.vscode" + }, + "detail": "Run configure.py with generate_make.sh in the working directory.", + "problemMatcher": [] + }, + { + "label": "clean-work-dir", + "type": "shell", + "command": "sh clean_work_dir.sh", + "options": { + "cwd": "${workspaceFolder}/.vscode" + }, + "detail": "Clean the working directory with clean.sh.", + "problemMatcher": [] + }, + { + "label": "set-working-bin", + "type": "shell", + "command": "sh", + "args": [ + "set_bin_working.sh", + "${input:bin-working}" + ], + "options": { + "cwd": "${workspaceFolder}/.vscode" + }, + "detail": "Choose the working directory for the binary files.", + "problemMatcher": [] + } + ], + "inputs": [ + { + "id": "bin-working", + "type": "promptString", + "description": "Enter the working directory under bin/." + } + ], + "version": "2.0.0" +} \ No newline at end of file