Setting up platform-specific default tasks in VS Code - cmake

Broader Question:
This post originally asked about how to specify a platform-specific problem matcher, but it seems that the more important question to be answered is:
How do you set up platform-specific properties for tasks when those properties are not recognized in the "windows" or "linux" sections?
Even if I break this task into two tasks, it seems that only one of them can be set as the default build task for both platforms.
Before anyone asks, this problem stems from the need to commit my tasks.json file to the repository so that the other developers are able to build the project on any platform using the "Run Build Task..." command in VS Code. I realize they could always change the default task after checking out the code.
Original Question:
I have a task in VSCode that runs a shell/batch script for building my C++ (CMake) application. The task makes use of the "windows" and "linux" keys for platform-specific commands.
{
"label": "Build x64",
"type": "shell",
"windows": { "command": "${workspaceRoot}/Build-Win-x64.bat" },
"linux": { "command": "${workspaceRoot}/Build-Linux-x64.sh" },
"group": { "kind": "build", "isDefault": true }
}
The Windows script builds with the MSVC compiler which requires putting "problemMatcher": "$msCompile" in the task so that VSCode can parse the compiler output.
However the Linux script uses GCC which requires "problemMatcher": "$gcc".
These values seem to be mutually exclusive and VSCode does not allow them inside the platform-specific properties.
Is there any way to set up a default build task with different problem matchers for each platform?
I've thought about using an environment variable like this "problemMatcher": "${env:VSCODE_CPP_MATCHER}" but this would be annoying to set up for every workstation that works with this project.

It turns out that you can use an array of problem matchers!
{
"label": "Build",
"windows": { "command": "${workspaceFolder}/Build-Win-x64.bat" },
"linux": { "command": "${workspaceFolder}/Build-Linux-x64.sh" },
"problemMatcher": ["$msCompile", "$gcc"]
}
Since this solution lets me use the same task for Windows and Linux, I don't need to define separate default build tasks for each platform.
Just out of curiousity, is it possible to set up a different default build task for each platform?

Related

How to set working directory in CMake Visual Studio 2022?

I have a problem with setting the working directory with CMake (Visual Studio 2022).
I'm currently working on a project (some OpenGL learning stuff) and decided to switch from typical VS solution-project to CMake project. I need to load some files (.obj, shaders) from Resources folder (LearnOpenGL/Resources) but I see that paths in c++ code are relative to LearnOpenGL/out/build/x64-Debug/.
I've already tried :
setting property VS_DEBUGGER_WORKING_DIRECTORY like (also without trailing slash):
set_property(TARGET LearnOpenGL PROPERTY VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/")
adding "currentDir" or "cwd" to CMakeSettings.json like:
"currentDir": "${projectDir}"
"cwd": "${projectDir}"
but there is no effect of any of those changes. Does anyone have some ideas what else can I do? Or maybe I'm doing here something wrong?
You can add currentDir property to your launch.vs.json which will typically be in ${workspaceRoot}/.vs directory.
To access it from Visual Studio 2022 CMake project you can follow these steps:
In the solution explorer click on Switch between solutions and available views button:
Then click on CMake Targets View
Now right click on your project and press Add Debug Configuration in context menu
This will open launch.vs.json file where you can edit currentDir property, for example - my project 02_texture.exe should start in root directory so my launch config looks like this:
{
"version": "0.2.1",
"defaults": {},
"configurations": [
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "",
"name": "CMakeLists.txt"
},
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "02_texture.exe (02_texture\\02_texture.exe)",
"name": "02_texture.exe (02_texture\\02_texture.exe)",
"currentDir": "${workspaceRoot}"
}
]
}

How to apply 'out of the box' Cumulocity Widgets (such as 'Radial Gauge') in custom Cumulocity applications

So I've been trying to make a customised application in Cumulocity. However, I want to maintain the consistency for cockpit and my customised application, so I'm just wondering is there any way to apply the "out of the box" widgets to our own application?
Thanks
You can achieve that through the manifest file in your application (cumulocity.json). Just list the plugins you want to include into your custom application.
{
"availability": "MARKET",
"contextPath": "charts",
"key": "charts-app-key",
"name": "Charts",
"resourcesUrl": "/",
"type": "HOSTED",
"imports": [
"core/c8yBranding",
"charts/dygraphsHour",
"charts/dygraphsTenMin",
"administration/alarmMapping"
]
}
You can list all the imports of a default application using the CLI tool.
c8y util:showimports cockpit
If you want to have the full cockpit application and just add you plugins it might be easier to use the target files:
{
"name": "Training",
"comment": "Release with additional example plugins",
"applications": [
{
"contextPath": "cockpit",
"addImports": [ "charts/dygraphsHour", "core/c8yBranding"]
}
]
}
This will use the full cockpit and just adds the wo plugins listed. It will replace your default cockpit with your extended one.

VSCode appends taskName to msbuild automatically

In Visual Studio Code (VSCode) I've create a task to build my c++ project. The build-process is based on Visual-Studio 12.0 projects files create by CMake. It provides configurations for Release/Debug/... modes and I want to create for each configuration a separate task.
Problem: VSCode appends the taskName to msbuild automatically. My tasks.json file looks like:
{
"version": "0.1.0",
"command": "msbuild",
"args": ["${cwd}/build/PROJECTNAME.sln",
"/property:GenerateFullPaths=true"],
"taskSelector": "/t:",
"tasks": [
{
"taskName": "build release",
"args": ["/p:Configuration=Release"],
"problemMatcher": "$msCompile"
},
{
"taskName": "build debug",
"args": ["/p:Configuration=Debug"],
"problemMatcher": "$msCompile"
}]
}
The argument /t:${taskName} seems to be appended automatically to msbuild. If I add the parameter /t:Build in the args variable of a task manually, It gives me the error, that two targets are specified in msbuild. Removing the taskSelector variable does not help. The only way I get it running, is to set all taskName variables to Build, but then I can not distiguish between different tasks in the tasks-selector.
Any ideas how to solve this?
PS: is there a reference of possible parameters for the tasks.json file, except those provided in the example file and on the official documentation site?
We have a work item to support suppressTaskName on the task description. If this does get implemented would it solve your problem.
After playing around with msbuild command-line arguments I've figured out a workaround. It is not nice and only works in some cases, but for me it is fine. Hopefully in later versions of VSCode a better solution can be implemented.
The idea: Add a dummy argument to msbuild, that has no meaningful effect. I've tried two version: (1) add the preprocess command-line switch, that creates a file with content that you could ignore, i.e. "taskSelect": "/pp:"; (2) add a dummy property to msbuild that accepts any argument, like /p:DefineConstants=....
The final tasks.json file looks like:
{
"version": "0.1.0",
"command": "msbuild",
"args": ["${cwd}/build/PROJECTNAME.sln",
"/property:GenerateFullPaths=true"],
// a dummy taskSelector to overcome a restriction in msbuild
// (1) "taskSelector": "/pp:",
// (2) ...
"taskSelector": "/p:DefineConstants=taskName_",
"tasks": [
{
"taskName": "build_release",
"args": ["/t:Build", "/p:Configuration=Release"],
"problemMatcher": "$msCompile"
},
{
"taskName": "build_debug",
"args": ["/t:Build", "/p:Configuration=Debug"],
"problemMatcher": "$msCompile"
}
]}
You can only use taskName without spaces, but this is ok, since one can now distinguish between different tasks.
Maybe in other build-systems like grunt there is a similar dummy-parameter that can be set to taskName without changing the build-process.
I'm open to better solutions to this problem.

Durandal.js optimizer not working (empty main-built.js)

I'm trying to get Durandal.js optimizer working on my test project, but it seems to generate nothing to main-built.js. I use the following command from node.js command prompt, in durandal/amd folder:
optimizer.exe --verbose true
Result is
Using default base configuration.
Configuring for deploy with almond (custom).
{
"name": "durandal/amd/almond-custom",
"inlineText": true,
"stubModules": [
"durandal/amd/text"
],
"paths": {
"text": "durandal/amd/text"
},
"baseUrl": "C:\\Users\\Tommi Gustafsson\\Documents\\Visual Studio 2012\\Projects\\DurandalTests\\DurandalTest1\\TestApp",
"mainConfigFile": "C:\\Users\\Tommi Gustafsson\\Documents\\Visual Studio 2012\\Projects\\DurandalTests\\DurandalTest1\\TestApp\\main.js",
"include": [
"main-built",
"main",
"bindings/tinymce-binding",
"durandal/app",
"durandal/composition",
"durandal/events",
"durandal/http",
"text!durandal/messageBox.html",
"durandal/messageBox",
"durandal/modalDialog",
"durandal/system",
"durandal/viewEngine",
"durandal/viewLocator",
"durandal/viewModel",
"durandal/viewModelBinder",
"durandal/widget",
"durandal/plugins/router",
"durandal/transitions/entrance",
"raphael-amd/eve.0.3.4",
"raphael-amd/raphael.2.1.0.amd",
"raphael-amd/raphael.2.1.0.core",
"raphael-amd/raphael.2.1.0.svg",
"raphael-amd/raphael.2.1.0.vml",
"viewmodels/flickr",
"viewmodels/modal1",
"viewmodels/myPage",
"viewmodels/shell",
"viewmodels/welcome",
"text!views/detail.html",
"text!views/flickr.html",
"text!views/modal1.html",
"text!views/myPage.html",
"text!views/shell.html",
"text!views/welcome.html"
],
"exclude": [],
"keepBuildDir": true,
"optimize": "uglify2",
"out": "C:\\Users\\Tommi Gustafsson\\Documents\\Visual Studio 2012\\Projects\\DurandalTests\\DurandalTest1\\TestApp\\main-built.js",
"pragmas": {
"build": true
},
"wrap": true,
"insertRequire": [
"main"
]
}
Deleting old output file.
Tracing dependencies for: durandal/amd/almond-custom
Then, when I check main-built.js, it is empty. Can anyone help me what is the problem? I have several AMD modules in the test project, including Raphael.js AMD modules.
My requirejs configuration looks like this:
requirejs.config({
paths: {
'text': 'durandal/amd/text',
'eve': './raphael-amd/eve.0.3.4',
'raphael.core': './raphael-amd/raphael.2.1.0.core',
'raphael.svg': './raphael-amd/raphael.2.1.0.svg',
'raphael.vml': './raphael-amd/raphael.2.1.0.vml',
'raphael': './raphael-amd/raphael.2.1.0.amd',
'tinymce': "../Scripts/tinymce/jquery.tinymce.min"
}
});
In the same amd folder, where optimizer is stored, try running node r.js -o app.build.js. I've seen r.js sometimes choke about some dependencies, which resolves without problem when loading via require.js. For whatever reason the error messages won't show up when using optimizer --verbose. Typically the error message provides enough information to see where this occurs and if you've to update require.contig.paths or a specific define dependency.

Create different versions form one bootstrap file with require.js

I develop an iPad/iPhone App web app. Both share some of the resources. Now I wanna build a bootstrap js that looks like this:
requirejs(['app'], function(app) {
app.start();
});
The app resource should be ipadApp.js or iphoneApp.js. So I create the following build file for the optimizer:
{
"appDir": "../develop",
"baseUrl": "./javascripts",
"dir": "../public",
"modules": [
{
"name": "bootstrap",
"out": "bootstrap-ipad.js",
"override": {
"paths": {
"app": "ipadApp"
}
}
},
{
"name": "bootstrap",
"out": "bootstrap-iphone.js",
"override": {
"paths": {
"app": "iphoneApp"
}
}
}
]
}
But this doesn't seems to work. It works with just one module but not with the same module with different outputs.
The only other solution that came in my mind was 4 build files which seems a bit odd. So is there a solution where i only need one build file?
AFAIK the r.js optimizer can only output a module with a given name once - in your case you are attempting to generate the module named bootstrap twice. The author of require.js, #jrburke made the following comment on a related issue here:
...right now you would need to generate a separate build command for each script being targeted, since the name property would always be "almond.js" for each one.
He also suggests:
...if you wanted just one build file to run, you could create a node program and drive the optimizer multiple times in one script file. This example shows using requirejs as a module and calling requirejs.optimize().
I took a similar approach in one of my projects - I made my build.js file an ERB template and created a Thor task that ran through my modules and ran r.js once for each one. But #jrburke's solution using node.js is cleaner.