Using node-gyp Predefined Variable PRODUCT_DIR - c++

In binding.gyp I want to set like this:
"libraries": [ "-Wl,-rpath,<working directory>/build/Release/" ]
I am using the following configuration to do the same:
"libraries": [ "-Wl,-rpath,<!(pwd)/build/Release/" ]
This works but the problem with this is that, it would not work on Windows or wherever pwd is not available and also this is not the best option as there is already a predefined variable PRODUCT_DIR available in node-gyp to achieve this. Strangely I am not able to use this variable PRODUCT_DIR.
I tried following options but no luck. error says Library not loaded: #rpath/<lib>.dylib (rpath is not getting set):
"libraries": [ "-Wl,-rpath,>(PRODUCT_DIR)/build/Release/" ]
"libraries": [ "-Wl,-rpath,<(PRODUCT_DIR)/build/Release/" ]
"libraries": [ "-Wl,-rpath,>(PRODUCT_DIR)"]
"libraries": [ "-Wl,-rpath,<(PRODUCT_DIR)"]
When i tried printing by "<!(echo <(PRODUCT_DIR) 1>&2)" it says builddir: command not found. Looks like variable has value builddir.
Shouldn't it print the target directory instead of builddir ? or builddir means something for compiler ?
Am I not using this variable properly or is there any other variable available that I should be using ?

PRODUCT_DIR behaves really weird, I got to say. I avoid it wherever possible. Often by writing external build scripts with plain node.
The reason why you can't "<!(echo <(PRODUCT_DIR) 1>&2)" is that is some kind of special variable to node-gyp.
However you are using the right format, like here...
{
'files': [ '<(PRODUCT_DIR)/libzip.dll' ],
'destination': '<(module_path)'
}
My guess though is that you need to...
"variables": {
"YOUR_DIR: "<(PRODUCT_DIR)/build/Release/"",
"your_libs": "-Wl,-rpath,<(CURRENT_DIR) ]"
}
You know, it's Python, we don't know about :)

Related

vcpkg does not use registry defined in `vcpkg-configuration.json`

I'm trying to use a modified version of imgui through vcpkg.
I've created a git repository to be used for the registry (https://github.com/altschuler/vcpkg-custom-ports), and copied over the imgui port configuration, and made the changes I needed (following guides like this and this).
However, vcpkg seems to ignore the entry for the custom repo in vcpkg-configuration.json, it simply doesn't load anything from it (I know because I tried changing the repository url to something that doesn't exist). If I set the default-repository to my custom one it does load stuff, but then all the packages I want from the builtin registry obviously fail to install.
Note: the reason I need a custom port for imgui is that I need to compile some definitions (basically just do target_compile_definitions in its CMakeLists). If you know of an easier way to do that I'm all ears.
vcpkg-configuration.json:
{
"registries": [
{
"kind": "git",
"baseline": "e3b33f3a548f20ba06b2959aa3701bd50ece0638",
"repository": "https://github.com/altschuler/vcpkg-custom-ports.git",
"packages": ["imgui"]
}
]
}
vcpkg.json:
{
"name": "tester",
"version-string": "0.1.0",
"dependencies": [
"lager",
"sdl2",
{
"name": "imgui",
"features": ["docking-experimental", "sdl2-binding", "opengl3-binding"]
},
"immer",
"cereal",
"rxcpp",
"range-v3",
"glew",
"boost"
]
}
Try setting an environment variable
VCPKG_FEATURE_FLAGS=manifests,binarycaching,registries
AFAIK, some features are not enabled by default. Seems that manifests are automatically enabled, so vcpkg.json gets picked up, but perhaps "registries" are not enabled by default. (Disregard "binarycaching", if you don't use it).
This is what is working for me.

How to pass comma-separated options to the g++ linker with VSCode?

I need to pass the arg -Wl,-Bstatic,--whole-archive to g++.
"version": "2.0.0",
"tasks": [
{
"type": "shell",
"label": "shell: g++.exe build active file",
"command": "C:\\MinGW\\x86\\bin\\g++.exe",
"args": [
"-g",
"${file}",
"-Wl,-Bstatic,--whole-archive",
"-Xlinker",
"-Map=${fileDirname}\\${fileBasenameNoExtension}.map",
"-o",
"${fileDirname}\\${fileBasenameNoExtension}.exe"
],
"options": {
"cwd": "C:\\MinGW\\x86\\bin"
},
"problemMatcher": [
"$gcc"
],
"group": "build"
}
]
}
It gives me in output this in the terminal.
Executing task: C:\MinGW\x86\bin\g++.exe -g 'c:\Users\remi\Desktop\OK - VSCode\loaderstack.cpp' -Wl,-Bstatic,--whole-archive -Xlinker '-Map=c:\Users\remi\Desktop\OK - VSCode\loaderstack.map' -o 'c:\Users\remi\Desktop\OK - VSCode\loaderstack.exe' <
At line:1 char:84
+ ... e -g 'c:\Users\remi\Desktop\OK - VSCode\loaderstack.cpp' -Wl,-Bstatic ...
+ ~
Missing argument in parameter list.
At line:1 char:93
+ ... Users\remi\Desktop\OK - VSCode\loaderstack.cpp' -Wl,-Bstatic,--whole- ...
+ ~
Missing argument in parameter list.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : MissingArgument
Is there anyway to build inside VSCode with these comma-separated args ?
I originally answered this question (like a dumb dumb) as if you were using Linux, so I deleted that answer and included a new one for PowerShell.
This is sort of a common problem when dev's use GCC with Powershell. The problem is that PowerShell is very programmatic in the way it implements its interface, and the way that it executes commands. With Linux, CLI's are all written opensource (mostly) and are developed by the developers, where powershell is created by a company that dictates how every little detail works (there are benefits, and downsides to both). PowerShell has aspects/features (or w/e you want to call them) that just feel like somthing a programming language has, for example PowerShell has scopes, and what you pass to powershell gets parsed according to the context (or scope) that your currently in. The problem you are dealing with is that your command, that your handing GCC through your VS Code v2 Task is not being parsed properly due to the context in which the task is handing it to Power-shell.
YOU HAVE 2 OPTIONS
Option #1
The first option is to use a scope where the parser will correctly interoperate the command.
Remember, your using a VSCode task, powershell & gcc, to make sure communication succeeds across all three, you need to include the scope to use in what you are communicating. To do that we want to make use of the...
Call Operator &
To use the call operator just format the initial command to execute as shown in the code block bellow:
"command": "& C:\\MinGW\\x86\\bin\\g++.exe",
Where I know that this is a valid solution to your problem, I am currently on a Linux System, I have windows dual booted, but I am too lazy to switch over to it, so just in-case something needs to be tweaked, use the link for the Call Operator I posted above, MS documentation is very good, and very specific about how to implement its software-technologies
Option #2
Your second option takes a totally different route than the first.
Instead of dealing with the scope being the problem, your gonna deal with Power-shell's inability to parse the MingW GCC Command.
To deal with Power-shell's parsing issue, we will tell it to stop parsing the command, henceforth, the...
stop-parsing flag --%
(For the semantics police-type of developers: I think its technically a token, not a flag)
Using the flag looks like this: gcc %--
So the whole command should look somthing like this:
"args": [
"--%"
"-g",
"${file}",
"-Wl,-Bstatic,--whole-archive",
"-Xlinker",
"-Map=${fileDirname}\\${fileBasenameNoExtension}.map",
"-o",
"${fileDirname}\\${fileBasenameNoExtension}.exe"
],
Again, I included the link to the docs for the stop-parsing token above, just in-case something needs to be tweaked.
The example I showed above is somthing I had to use on a project that I worked on for a very long time, because of that experiance, I perfer to use the no
Somthing else that I don't know much about, by I read about when I DDG'd the links to Microsoft-site that might, maybe work is using the Arguments mode, which seems to be similar to the stop parsing command?
Anyhow, here is the link if you want to read about it.
I should say that I have not tried this approach, but I think it will work.
I suggest that you escape , in powershell using `. Try it in your config file like this:
"-Wl`,-Bstatic`,--whole-archive",
I'm not sure if it works, but since it worked for echo hell`,o`,o, I guess everything will be fine. Please let me know if this approach works.

Node-gyp Library not loaded: /usr/local/lib/libmtp.9.dylib

I have been attempting to make a nodejs-native-addon which uses libmtp to carry out certain functions. I have been successful in the building the app but the app is throwing Library not loaded: /usr/local/lib/libmtp.9.dylib. Referenced from: /path/build/Debug/nbind.node. Reason: image not found error when I try to run it on another macbook where the libmtp isn't installed.
This is my binding.gyp file:
{
"targets": [
{
"includes": [
"auto.gypi"
],
"sources": [
"src/native/mtp.cc"
],
"link_settings": {
"libraries": [
"-lmtp"
],
},
}
],
"includes": [
"auto-top.gypi"
],
}
I even attempted to include the dylib file in the libraries option
"link_settings": {
"libraries": [
"<(module_root_dir)/src/native/lib/libmtp.9.dylib"
]
}
but the app fails to start with the Library not loaded: /usr/local/lib/libmtp.9.dylib. Referenced from: /path/build/Debug/nbind.node. Reason: image not found error.
Any help will be appreciated.
The error is indicating that the library libmtp.9.dylib cannot be found in the standard library include path /usr/local/lib
Try setting the environment variable LD_LIBRARY_PATH to point to the location where you have the libmtp.9.dylib before running the node.
One solution would be to create a symlink in a known rpath like /usr/local/lib manually to your built library. Not ideal but it may provide a workaround for at least having successful builds in development.
ln -s <absolute_path>/src/native/lib/libmtp.9.dylib /usr/local/lib/libmtp.9.dylib
This allows the binding.gyp file to find the library without it needing to configure an rpath with whatever process is throwing the error. This is easier in my opinion than tracking down the binding.gyp trace.

Custom build key binding sublime text

I've made a custom build in sublime which runs my program and it works fine. But I have the Makefile build as default. Is there a way, to let Ctrl+B use the default build (in my case Makefile) and have another shortcut (Ctrl+Shift+B) use another build. If yes, how?
I tried using this :
[
{ "keys": ["ctrl+shift+b"], "command": "build buildName" }
]
but it isn't working and watching at the sublime documentation this command is only for the default build selected.
Thanks in advance.
The actual syntax of the keybinding should be like so:
{ "keys": ["f1"], "command": "build", "args": {"build_system": "Packages/Python/Python3.sublime-build"} },
I would actually recommend against using CtrlShiftB as your custom keybinding, as it is already applied to the "Build With" command.

Detect MSVC version in GYP

I'm trying to detect a msvc version during node-gyp configure in my binding.gyp file.
Basically, I want to be able to link against particular 3rdparty library based on Visual C++ version:
['OS=="win"' and 'toolset="vc12"' , {
'libraries': [
"opencv/lib/vc12/opencv_world300.lib"
],
}],
['OS=="win"' and 'toolset="vc11"' , {
'libraries': [
"opencv/lib/vc11/opencv_world300.lib"
],
}],
['OS=="win"' and 'toolset="vc10"' , {
'libraries': [
"opencv/lib/vc10/opencv_world300.lib"
],
}]
Unfortunately, neither toolset, nor _toolset or even $(TOOLSET) variables are defined in GYP.
I wasn't able to find such variable in GYP documentation. Is it possible at all?
I couldn't figure out from the docs that how to check for toolset version, but only found the top-level settings: https://chromium.googlesource.com/external/gyp/+/master/docs/UserDocumentation.md#Skeleton-of-a-typical-executable-target-in-a-gyp-file.
However, #saper on GitHub figured it out using MSVS_VERSION instead:
['OS=="win"' and 'MSVS_VERSION=="2013"' , {
'libraries': [
"opencv/lib/vc12/opencv_world300.lib"
],
}],
['OS=="win"' and 'MSVS_VERSION=="2012"' , {
'libraries': [
"opencv/lib/vc11/opencv_world300.lib"
],
}],
['OS=="win"' and 'MSVS_VERSION=="2010"' , {
'libraries': [
"opencv/lib/vc10/opencv_world300.lib"
],
}]
(nit: in your example, although toolset token is not identified by gyp, = should be replaced with ==)
Example: https://github.com/saper/node-sass/blob/c7e9cf0f0e0098e8316bd41722fc2edf4a835d9f/src/libsass.gyp#L91-L94.
Limitation 1:
Unfortunately, these conditions are not emitted in the .targets or .vcxproj files (such as this), but it will emit the .vcxproj after post-processing the conditions separate for the given version of MSVS and hence renders the .vcxproj file incompatible with newer/older versions of VCR.
However, the MSVS version can by overridden for gyp in multiple ways, for instance, using environment variable:
In CMD:
SET GYP_MSVS_VERSION=2012
Or in PowerShell:
$env:GYP_MSVS_VERSION=2015
It can also be passed as a command line argument:
node_modules/.bin/node-gyp build --msvs_version=2012
If both env-var and command line argument are present, CLI arg will take the precedence.
This CLI argument can be supplied to npm task, for example, to enforce the constraint for all the Windows consumers of your package to use specific version of MSVCR otherwise error.
and since so forth..
Limitation 2:
From CLI arg, there is no way to specify minimum MSVS version no such flag as: --min-msvs-version.
Limitation 3:
In case of multiple version of MSBUILD installed, node-gyp's MSBUILD discovery (at present) will ignore the preferred/required version of toolset by .vcxproj, but will give precedence to the one in PATH. In this case, you may get errors, for instance if you are using C99/C++1[1/4/7] features only offered by VS2015. To remedy this situation:
either reset PATH to the desired version MSBuild bin directory.
instead of node-gyp build or rebuild, use node-gyp configure followed by "%ProgramFiles(x86)%\MSBuild\14.0\Bin\MSBuild" build/binding.sln /p:Configuration=Release (or from posh, it would become: &"${env:ProgramFiles(x86)}\MSBuild\14.0\Bin\MSBuild" build\binding.sln /p:Configuration=Release)
by sending a Pull Request for node-gyp and pangyp to fix the toolset-version-aware MSBUILD discovery, if your Windows Registry skills are not as rusty as mine. :)