Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tools for Integrating Gamer with VS Code #382

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions doc/wiki/Developing-with-VS-Code.md
Original file line number Diff line number Diff line change
@@ -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).
1 change: 1 addition & 0 deletions doc/wiki/_Sidebar.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 ]]
19 changes: 19 additions & 0 deletions tool/vscode/README.md
Original file line number Diff line number Diff line change
@@ -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.
Empty file added tool/vscode/bin_working
Empty file.
19 changes: 19 additions & 0 deletions tool/vscode/build.sh
Original file line number Diff line number Diff line change
@@ -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 .
15 changes: 15 additions & 0 deletions tool/vscode/c_cpp_properties.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${default}",
"${workspaceFolder}/include"
],
"cStandard": "c17",
"cppStandard": "gnu++17",
"intelliSenseMode": "linux-gcc-x64"
}
],
"version": 4
}
8 changes: 8 additions & 0 deletions tool/vscode/clean_work_dir.sh
Original file line number Diff line number Diff line change
@@ -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
9 changes: 9 additions & 0 deletions tool/vscode/config.sh
Original file line number Diff line number Diff line change
@@ -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
51 changes: 51 additions & 0 deletions tool/vscode/copy_to_vscode.sh
Original file line number Diff line number Diff line change
@@ -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
56 changes: 56 additions & 0 deletions tool/vscode/extract_macros.py
Original file line number Diff line number Diff line change
@@ -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.")
7 changes: 7 additions & 0 deletions tool/vscode/gamercpp.natvis
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="Timer_t">
<DisplayString Condition="Status">Timer running</DisplayString>
<DisplayString Condition="!Status">Timer stop: {Time*1.0e-6} sec</DisplayString>
</Type>
</AutoVisualizer>
40 changes: 40 additions & 0 deletions tool/vscode/launch.json
Original file line number Diff line number Diff line change
@@ -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/."
}
]
}
18 changes: 18 additions & 0 deletions tool/vscode/set_bin_working.sh
Original file line number Diff line number Diff line change
@@ -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."
59 changes: 59 additions & 0 deletions tool/vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -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"
}