Automating build task with unique ids - visual-studio-code

I've written some embedded code (using VS-Code as my IDE) that is ready for deployment to many different devices.
The code contains a file config.h that defines a unique device_id that needs to change for each device.
I have a file unique_ids.csv that contains all of the unique ids that I need to use.
VS-Code can automatically build my project and creates a file called project_name.bin.
How can I set up a script that automatically takes the uniqe ids from my CSV file and builds a specific device_id.bin file for each one?
I suspect this may require utilizing Visual Studio Tasks in some way. Here is my current tasks.json:
tasks.json
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "0.1.0",
"name": "make",
"isShellCommand": true,
"showOutput": "always",
"problemMatcher": {
"owner": "cpp",
"fileLocation": ["relative", "${workspaceRoot}/mbed-os"],
"pattern": {
"regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
"file": 1,
"line": 2,
"column": 3,
"severity": 4,
"message": 5
}
},
"args": ["-j"],
"linux": {
"command": "make"
},
"osx": {
"command": "make"
},
"windows": {
"command": "make.exe"
}
}

Thinking of an alternative approach, I might not be answering directly.
If you are using the csv for release and not for debug, why would you build the release inside VS?
I would rather build my debug inside VS and build my different releases using command line with a batch script.
Something like this batch pseudo code
set id_list=unique_ids.csv
set id=
for %%a in (%id_list%) do (
set "id=%%~na"
replace in config.h device_id by device_%id%
make your_project
)

Related

VSCode launch configuration to run python file without debugging

I understand that by creating a launch.json file in VSCode (slightly more cumbersome than pycharm), I can set debug configurations to launch individual python files.
For example:
{
"version": "0.2.0",
"configurations": [
{
"name": "Python: Poker",
"type": "python",
"request": "launch",
"cwd": "C:/Users/dickr/git/poker",
"program": "C:/Users/dickr/git/Poker/poker/main.py",
"console": "integratedTerminal",
"env": {"PYTHONPATH": "${workspaceFolder}${pathSeparator}${env:PYTHONPATH}"}
},
]
}
That all works great, but how can I run it in normal mode, without a debugger? How can this be defined in the launch configuration so I can select this in the dropdown, and potentially pass arguments with it?
Write a task in a tasks.json file. For documentation on tasks, see https://code.visualstudio.com/docs/editor/tasks#_custom-tasks.
Your might look something like this:
{
"version": "2.0.0",
"tasks": [
{
"label": "run python script",
"type": "process",
"command": "python3 C:/Users/dickr/git/Poker/poker/main.py",
"options": {
"cwd": "C:/Users/dickr/git/poker"
},
"presentation": {
"reveal": "always",
}
}
]
}
though I'd suggest that if possible, you use variable substitution to try to get rid of the absolute paths that won't be the same on other machines (assuming you want to be able to run the task on other machines).
Then run the task. You can even bind the task to keyboard shortcuts. See the documentation for more info: https://code.visualstudio.com/docs/editor/tasks.

Configuring multiple commands to run in parallel in VS Code tasks (to compile and autoprefix Sass)

I had previously been using Koala to compile my Sass with autoprefixing and minifying (on Windows), but have come to find that Koala is no longer maintained. I'm therefore trying to figure out how people usually compile Sass, autoprefix it, and minify it automatically on save.
I'm not super experienced with command line tools like Gulp but have used NPM enough to get to the point of being able to install Dart Sass, PostCSS, etc., and since I use VS Code, have decided that its internal Tasks feature seems like the easiest way to go.
Currently if I do this in the VS Code terminal:
sass --watch sass:. --style compressed
It works, i.e., it successfully watches for changes in the sass directory and outputs a minified .css file in the parent directory.
If I stop that and do this instead:
postcss style-raw.css --output style.css --use autoprefixer --watch
It also works. I had to rename the original .scss file because apparently postcss doesn't allow --replace and --watch at the same time.
So right now, I have style-raw.scss which compiles to style-raw.css when I run the sass command, and style-raw.css gets autoprefixed and output to style.css when I run the postcss command.
Where I'm stuck is getting both commands to run at the same time via a Task. In my tasks.json file I have:
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "Sass Compile",
"type": "shell",
"command": "sass --watch sass:. --style compressed | postcss style-raw.css --output style.css --use autoprefixer --watch",
"problemMatcher": [
"$node-sass"
],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
This is connected to the Build task, which has a keyboard shortcut of ctrl+shift+B, so my ultimate goal thus far has been to be able to just hit ctrl+shift+B to start everything up getting watched and compiled and autoprefixed, etc.
Currently though, only the Sass command runs when I use the keyboard shortcut. I found another post somewhere that said the pipe should work for multiple commands, but it doesn't seem to, or perhaps you can't --watch two things at the same time, I have no idea. I tried an array for command: but that either doesn't work or I didn't have the right format.
Or perhaps there's an entirely different and better way to go about all this, but if anyone can help with using these two commands together, that'd be much appreciated.
UPDATE: SOLUTION --------------------------------------------------------
With the kind help of #soulshined below, I got the multiple commands working (the dependsOn option was the trick), but evidently it won't run two commands with the --watch parameter in the same terminal. For my use case this wouldn't work and I eventually found this extremely helpful article that explains how to run multiple tasks in a split terminal by grouping them.
If anyone else runs across this with the same use case, here is the working tasks.json file:
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "Compile CSS",
"dependsOn": [
"Sass Compile",
"Prefix Output",
],
"group": {
"kind": "build",
"isDefault": true
},
},
{
"label": "Prefix Output",
"type": "shell",
"command": "postcss style-raw.css --output style.css --use autoprefixer --watch",
"presentation": {
"group": "cssCompile"
}
},
{
"label": "Sass Compile",
"type": "shell",
"command": "sass --watch sass:. --style compressed",
"problemMatcher": [
"$node-sass"
],
"presentation": {
"group": "cssCompile"
}
}
]
}
UPDATE 2: GULP --------------------------------------------------------
Randomly ran across my own post and thought I would add that I now use Gulp. I don't remember why but the VS Code tasks turned into a hassle later on, and Gulp turned out to be not that hard to learn.
Where I'm stuck is getting both commands to run at the same time via a Task
Running concurrently can be tricky to accomplish; consider taking advantage of the dependsOn property. Here is a brief example of running commands tasks consecutively:
"version": "2.0.0",
"tasks": [
{
"label": "Echo All",
"type": "shell",
"command": "echo Done",
"dependsOn": [
"Last"
],
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "Last",
"type": "shell",
"command": "echo 'Did it last'",
"dependsOn": "First",
},
{
"label": "First",
"type": "shell",
"command": "echo 'Doing it first'",
}
]
That's a language [shell] agnostic solution. If you would like to run multiple commands you can try adding a semi colon after each statement:
"command": "sass --watch sass:. --style compressed; postcss style-raw.css --output style.css --use autoprefixer --watch"

VS Code: Create file inside the current directory of the editor

Is it possible to create a new file inside the same folder as the file that is active in the editor by the time the keyboard shortcut ctrl+n for explorer.newFile is hit?
I can tell if it's the correct folder by looking at the breadcrumbs and mostly have the file explorer toggled off. The command, however, seems to create a file inside the last folder opened or focused by the file explorer.
You can do this by overloading that explorer.newFile command's default keybinding to run a task instead. Here is the keybinding:
{
"key": "ctrl+n",
"command": "workbench.action.tasks.runTask",
"args": "newFile",
"when": "editorFocus" // must have an editor focused
},
And the task (in tasks.json):
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "newFile",
"command": "touch '${fileDirname}/${input:fileName}' && code '${fileDirname}/${input:fileName}'",
"type": "shell",
"problemMatcher": [],
},
],
"inputs": [
{
"type": "promptString",
"id": "fileName",
"description": "Complete my file name.",
"default": "new file name"
}
]
}
That will create a file in the same directory as the active editor's directory - it will ask you for the filename - and then open it.
I used the bash command touch to create the file (if it doesn't already exist), if you are using a different shell you will need the equivalent of touch.

VScode remote development: How can I run a build task to source environment variables before running the real build task?

I want to setup VScode so I can use build tasks to build my project. The project is build using make, en I have defined a build task that runs make. However, before running make, I normally would source a script that sets my environment variables correctly. If I add a new build task with the source command, and set my main build tasks to first execute the source command, the environment variables are not propagated properly. How can I make sure the enviroment variables are kept between build tasks?
My tasks.json file:
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"type": "shell",
"label": "make",
"command": "make",
"args": [],
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"dependsOn": "Set environment"
},
{
"label": "Set environment",
"type": "shell",
"command": "source path/to/source_me.sh",
"group": "build",
]
}
Not in this way. Sourcing a file is injecting file contents into current shell session, which ends as soon as the task ends. The make task is run in a separate shell session, so these two do not interact. You may try to do a single task that executes a single line: source path/to/source_me.sh && make.
I solved my problem like this:
"tasks": [
{
"label": "all",
"type": "shell",
**"command": "source gitenv.sh && cd ${fileDirname} && alfred all"**,
"problemMatcher": [],
"group": {
"kind": "build",
"isDefault": true
}
}
]
Where alfred is a macro for make command with extra args.
${fileDirname} returns a current directory in which you have open file.
So if you open a file and in the same directory you have Makefile you can CTRL + SHIFT + B to execute this default task.

Where to define a shared problemMatcher to check the terminal?

In vscode I experience sometimes I can click on build errors in the integrated terminal and sometimes it is not possible to do so. This has annoyed me for quite some time because I was not able to find a pattern, until today when I was editing tasks.json.
It looks to be related to defining a problemMatcher in .vscode/tasks.json. Removing the problemMatcher section from the file and build errors in terminal were no longer clickable but putting it back did not re-enable them.
My vscode-project is located in a subfolder of the build tree and its build root for the entire project is two levels up ${workspaceFolder}/../.. which I believe maybe could confuse some build tools.
tasks.json
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"problemMatcher": {
"fileLocation": "relative",
"severity": "error",
"pattern":{
"regexp": "^system/mytool/(.*):(\\d+):(\\d+):\\s+(warning|error):(.*)$",
"file": 1,
"location": 2,
"column": 3,
"severity": 4,
"message": 5
},
},
"tasks": [
{
"type": "shell",
"label": "android deploy",
"command": "cd ${workspaceFolder}/../..; source build/envsetup.sh ; lunch hikey960-userdebug ; m mytool",
"args": [
],
"options": {
},
"group": "build"
},
]
}
I have seen examples putting "problemMatcher" = "$gcc" inside the task, should I define my problem matcher globally somewhere else and refer to it my name instead?
How to use it to parse the output when I build by typing make-commands in the integrated terminal?
You cannot define problem matchers globally. Instead you have to define them in each task.
This is somewhat ugly because you may have to copy the same problem matcher into a lot of tasks. There is an open issue for this: Global task properties