gumbo-d bindings with DUB - d

I'm trying to use gumbo-d in a project however dub is failing.
Here's the dub output:
Building: myproject (Default)
Performing main compilation...
dub build "myproject" "--build=plain"
Building package myproject in C:\Users\Matt\Documents\Projects\myproject\
Target vibe-d 0.7.23 is up to date. Use --force to rebuild.
Target gumbo-d 0.2.2 is up to date. Use --force to rebuild.
Building myproject ~master configuration "application", build type plain.
Compiling using dmd...
Linking...
OPTLINK (R) for Win32 Release 8.00.15
Copyright (C) Digital Mars 1989-2013 All rights reserved.
http://www.digitalmars.com/ctg/optlink.html
..\..\..\AppData\Roaming\dub\packages\gumbo-d-0.2.2\gumbo-d.lib(parse)
Error 42: Symbol Undefined _gumbo_destroy_output
..\..\..\AppData\Roaming\dub\packages\gumbo-d-0.2.2\gumbo-d.lib(parse)
Error 42: Symbol Undefined _gumbo_parse
--- errorlevel 2
FAIL .dub\build\application-plain-windows-x86-dmd_2066-946D41E793C045166B4DFD37035481AE\ myproject executable
Error executing command build: dmd failed with exit code 2.
Exit code 2
Build complete -- 1 error, 0 warnings
---------------------- Done ----------------------
Build: 1 error, 0 warnings
I'm at a bit of a loss of where the library file needs to go and what format it needs to be in. There is a .lib file in the gumbo-d dependency directory, is this meant to be the library? If so, why is the linker failing to link to it?
Here is the contents of my main dub.json file (for the overall project which includes the gumbo-d dependency)
{
"name": "googleplayscraper",
"description": "A simple vibe.d server application.",
"copyright": "Copyright © 2015, Matt",
"authors": ["Matt"],
"dependencies": {
"vibe-d": "~>0.7.19",
"gumbo-d": "~>0.2.2"
},
"versions": ["VibeDefaultMain"]
}
And here is the dub.json file for the gumbo-d dependency:
{
"libs-posix": [
"gumbo"
],
"version": "0.2.2",
"description": "D bindings for Google's Gumbo HTML5 parser library",
"authors": [
"Christopher Bertels"
],
"importPaths": [
"source/"
],
"configurations": [
{
"targetType": "library",
"name": "library"
}
],
"homepage": "https://github.com/bakkdoor/gumbo-d",
"sourcePaths": [
"source/"
],
"name": "gumbo-d",
"copyright": "Copyright © 2013, Christopher Bertels"
}

Related

Visual Studio compiling to wrong path AND trying to run wrong path when used with CMake

I'm very new to CMake (and new to C++ too, although that shouldn't matter here), and I am having a problem using CMake with Visual studio.
I have created a directory, let's say it's called Project, and put in it a simple project with the following structure:
Project/
build/ <empty>
src/
main.cpp
CMakeLists.txt
CMakePresets.json
Inside these files is just the most basic, default code:
CMakeLists.txt:
cmake_minimum_required (VERSION 3.8)
project (Project)
set (CMAKE_CXX_STANDARD 20)
set (CMAKE_CXX_STANDARD_REQUIRED True)
add_executable (Project src/main.cpp)
CMakePresets.json (this code is just the default that was generated):
{
"version": 3,
"configurePresets": [
{
"name": "windows-base",
"hidden": true,
"generator": "Ninja",
"binaryDir": "${sourceDir}/out/build/${presetName}",
"installDir": "${sourceDir}/out/install/${presetName}",
"cacheVariables": {
"CMAKE_C_COMPILER": "cl.exe",
"CMAKE_CXX_COMPILER": "cl.exe"
},
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Windows"
}
},
{
"name": "x64-debug",
"displayName": "x64 Debug",
"inherits": "windows-base",
"architecture": {
"value": "x64",
"strategy": "external"
},
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "x64-release",
"displayName": "x64 Release",
"inherits": "x64-debug",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
},
{
"name": "x86-debug",
"displayName": "x86 Debug",
"inherits": "windows-base",
"architecture": {
"value": "x86",
"strategy": "external"
},
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "x86-release",
"displayName": "x86 Release",
"inherits": "x86-debug",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
}
]
}
src/main.cpp:
#include <iostream>
int main() {
std::cout << "Hello, world!" << std::endl;
return 0;
}
Then, I have used CMake to create a Visual Studio solution:
C:\...\Project\build> cmake ..
This has worked fine without any errors, and Visual Studio can open the solution. It can also build the project correctly...
But it cannot run the executable which it has built. After successfully building the project, it has written the executable to C:\...\Project\build\Debug\Project.exe, but it tries to open C:\...\Project\build\x64\Debug\ALL_BUILD instead, and I get an error popup.
I gather that there are two things wrong here:
The executable file should be written within the C:\...\Project\build\x64\Debug folder, not just the C:\...\Project\build\Debug folder. This is how it has worked whenever I have used Visual Studio before, and this is the folder it is trying to search in.
It should be searching for an executable called Project.exe, not one called ALL_BUILD.
When I run Project.exe manually from the command line, it works fine. But I cannot seem to make Visual Studio run it correctly.
What have I done wrong here, and how can I get this to work?
Default project is set to ALL_BUILD to change the default for the VS generators use the following CMake statement:
set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT Project)
Anywhere after the add_executable command.
You see several projects in the solution explorer. These projects are build targets. The default target is ALL_BUILD, that builds all configured targets, like cmake --build . does it.
Set required target as the startup project in the solution explorer. This will point the debugger what executable to run.

How do I add command line launch arguments to a Release target in a CMake-managed C++ project in MSVC 2019?

My goal is to run e.g. MyTarget.exe "C:\Users\MHebes\config.json from MSVC.
I can do this in Debug mode, but can't get it to work in Release.
If I right-click on my top-level CMakeLists.txt, I can see the launch.vs.json for the current open folder:
..\..\..\..\AppData\Local\Microsoft\VisualStudio\16.0_45505961\OpenFolder\launch_schema.json:
{
"version": "0.2.1",
"defaults": {},
"configurations": [
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "MyTarget.exe (apps\\MyTarget\\Debug\\MyTarget.exe)",
"name": "Debug launch target for MyTarget",
"args": [
"C:/Users/MHebes/config.json"
]
}
]
}
I don't fully understand this in the first place, since the launch.vs.json docs don't mention anything about a "configurations" list but this was how it was auto-populated when I added a new configuration. Regardless, this works in debug mode—the "Debug launch target for MyTarget" option shows up in the Select Startup Item... list when Debug is selected in the dropdown.
I have added a Release/RelWithDebugInfo configuration to my CMakeSettings.json.
But when I actually switch the build to Release, the Select Startup Item... list is only populated with default CMakeTargets.
How do I add command-line launch arguments to Release builds?
My end goal is that when I Start Debugging in Release mode, it will build a Release exe and run it with some args.
I think I figured it out. I added another configuration with a different target:
{
"version": "0.2.1",
"defaults": {},
"configurations": [
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "MyTarget.exe (apps\\MyTarget\\Debug\\MyTarget.exe)",
"name": "Debug launch target for MyTarget",
"args": [
"C:/Users/MHebes/config.json"
]
},
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "MyTarget.exe (apps\\MyTarget\\RelWithDebInfo\\MyTarget.exe)",
"name": "RelWithDebInfo launch target for MyTarget",
"args": [
"C:/Users/MHebes/config.json"
]
}
]
}
The Microsoft Docs page on Configure CMake debugging sessions says:
projectTarget: Specifies the CMake target to invoke when building the project. Visual Studio autopopulates this property if you enter launch.vs.json from the Debug Menu or Targets View. This value must match the name of an existing debug target listed in the Startup Item dropdown.
Since Visual studio populates the Startup list with names that include the path to the executable, and because that path is dependent on the configuration name (i.e. buildRoot in CMakeSettings.json includes ${name} in the path by default), this explains why projectTarget must include the configuration path.
This seems like an insane interface to me. Maybe I'm doing something wrong.

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.

Compiling C/C++ in VS Code

I'm trying to compile C/C++ code in VS Code using cl (installed via visual studio 2019). I've set up the json files like the MS website suggests,
https://code.visualstudio.com/docs/cpp/config-msvc,
but I still get the error:
cl.exe : The term 'cl.exe' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
Here are my json files:
{
"configurations": [
{
"name": "Win32",
"includePath": [
"${workspaceFolder}/**"
],
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE"
],
"windowsSdkVersion": "10.0.17763.0",
"compilerPath": "C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.21.27702/bin/Hostx64/x64/cl.exe",
"cStandard": "c11",
"cppStandard": "c++17",
"intelliSenseMode": "msvc-x64"
}
],
"version": 4
}
{
"version": "2.0.0",
"tasks": [
{
"label": "msvc build",
"type": "shell",
"command": "cl.exe",
"args": [
"/EHsc",
"/Zi",
"/Fe:",
"helloworld.exe",
"test.c"
],
"group": {
"kind": "build",
"isDefault": true
},
"presentation": {
"reveal":"always"
},
"problemMatcher": "$msCompile"
}
]
}
cl.exe : The term 'cl.exe' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
Your "msvc build" task only specifies "cl.exe" for its command, with no leading path. The problem is that cl.exe isn't on your PATH, or anywhere that VS Code can see when it goes to run your build task.
One solution to this is to open VS Code using the "Developer Command Prompt" for whatever Visual Studio version you have. This version of the command prompt defines the location of the Visual Studio build tools so that any program or command that is run from that cmd prompt will be able to find the programs like "cl.exe".
There is another solution that I prefer to use, which is to write a batch script for your build task.
Put this script in the root of your VSCode workspace and call it build.bat:
:: set the path to your visual studio vcvars script, it is different for every version of Visual Studio.
set VS2017TOOLS="C:\Program Files(x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat"
:: make sure we found them
if not exist %VS2017TOOLS% (
echo VS 2017 Build Tools are missing!
exit
)
:: call that script, which essentially sets up the VS Developer Command Prompt
call %VS2017TOOLS%
:: run the compiler with your arguments
cl.exe /EHsc /Zi /Fe: helloworld.exe test.c
exit
Then your task has to be changed to run the batch script:
{
"label": "msvc build",
"type": "shell",
"command": "${workspaceFolder}/build.bat",
"group": {
"kind": "build",
"isDefault": true
},
"presentation": {
"reveal":"always"
},
"problemMatcher": "$msCompile"
}
The advantage to using the batch script this way is that you do not need to run VS Code from the Developer Command Prompt, and the $msCompile problem matcher will still be able to display errors and warnings inside VS Code.
Another note is that the batch script in this answer is specific to just your project. You can continue to update that script to build your project as it gets larger, or you could take advantage of a tool like CMake to handle the generation of the actual build scripts from a configuration file.
Then your build.bat may look more like this:
:: set the path to your visual studio vcvars script, it is different for every version of Visual Studio.
set VS2017TOOLS="C:\Program Files(x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat"
:: make sure we found them
if not exist %VS2017TOOLS% (
echo VS 2017 Build Tools are missing!
exit
)
:: call that script, which essentially sets up the VS Developer Command Prompt
call %VS2017TOOLS%
:: Set some variables for the source directory and the build directory
set SrcDir=%CD%
set BuildDir=%CD%\build
:: Make the build directory if it doesn't exist
if not exist "%BuildDir%" mkdir "%BuildDir%"
:: Make sure you configure with CMake from the build directory
cd "%BuildDir%"
:: Call CMake to configure the build (generates the build scripts)
cmake %SrcDir%^
-D CMAKE_C_COMPILER=cl.exe^
-D CMAKE_CXX_COMPILER=cl.exe^
:: Call CMake again to build the project
cmake --build %BuildDir%
exit
I have struggled in the same problem as following the instructions in Configure VS Code for Microsoft C++. Thankfully I found this question and #Romen's great answer.
However, here are some itchy points in his solution:
He hard-coded the executable name and the file name so that you have to change it every time you make a new project.
He put the .bat in the folder of the compiled file but not the .vscode folder so that we couldn't copy one folder directly while making new projects.
For this two flecks, I modified his codes a little bit so that it's more convenient to make new projects debugging with Microsoft C++.
In the build.bat file, change the command
cl.exe /EHsc /Zi /Fe: helloworld.exe helloworld.cpp
to
cl.exe /EHsc /Zi /Fe: %1.exe %1.cpp
Move the build.bat to .vscode folder and change "command": "build.bat" to "command": ".\\.vscode\\build.bat ${fileBasenameNoExtension}".
This is trivial, but I hope it could help some newbies like me and inspire better solutions for more complicated cases :)
For anyone comming here thinking the best solution would be to set the path environment variables, so cl.exe could be run in any command prompt, or power shell terminal, this is not recommended, as per documentation:
The MSVC command-line tools use the PATH, TMP, INCLUDE, LIB, and
LIBPATH environment variables, and also use other environment
variables specific to your installed tools, platforms, and SDKs. Even
a simple Visual Studio installation may set twenty or more environment
variables. Because the values of these environment variables are
specific to your installation and your choice of build configuration,
and can be changed by product updates or upgrades, we strongly
recommend that you use a developer command prompt shortcut or one of
the customized command files to set them, instead of setting them in
the Windows environment yourself.
https://learn.microsoft.com/en-us/cpp/build/setting-the-path-and-environment-variables-for-command-line-builds?view=vs-2019
What worked for me:
Following this guide, I made this change in task.json:
{
"version": "2.0.0",
"tasks": [
{
"type": "shell",
"label": "cl.exe build active file",
"command": "build.bat", //calling build.bat instead
"args": [
"/Zi",
"/EHsc",
"/Fe:",
"${fileDirname}\\${fileBasenameNoExtension}.exe",
"${file}"
],
"problemMatcher": [
"$msCompile"
],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
Then my build.bat (sDevCmd.bat is called when the developer terminal is opened):
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\Tools\VsDevCmd.bat"
echo Building...
cl.exe %*
Then Ctrl + Shift + B.
Default terminal of VSCode does not have cl.exe PATH, you need to use Developer Command Prompt :
Open Developer Command Prompt
https://code.visualstudio.com/docs/cpp/config-msvc:
To open the Developer Command Prompt for VS, start typing 'developer' in the Windows Start menu, and you should see it appear in the list of suggestions. The exact name depends on which version of Visual Studio or the Visual Studio Build Tools you have installed. Click on the item to open the prompt.
Go to project parent folder
Lets say it is D:\workspace and project name is myproject
Ctrl+Shift+B to build

Source synchronization in Visual Studio CMake project and WSL

I have a big solution where part of projects is a classic Visual C++ projects and other part is CMake type projects.
Previously I work with Windows 7 + VS 2017 + Ubuntu on virtual machine and before start building CMake project for linux, VS start rsync for synchronization source between PC and virtual machine.
For this I was create next rule in CMakeSettings.json file:
{
"name": "Linux-Debug",
"generator": "Unix Makefiles",
"remoteMachineName": "${defaultRemoteMachineName}",
"configurationType": "Debug",
"remoteCMakeListsRoot": "/var/tmp/src/Solution_dir/",
"cmakeExecutable": "/usr/bin/cmake",
"buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}",
"installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}",
"remoteBuildRoot": "/var/tmp/Solution_dir/build/x86_64_debug_unix",
"remoteInstallRoot": "/var/tmp/Solution_dir/install/x86_64_release_unix",
"remoteCopySources": true,
"remoteCopySourcesOutputVerbosity": "Normal",
"remoteCopySourcesConcurrentCopies": "10",
"remoteCopySourcesMethod": "rsync",
"remoteCopyBuildOutput": false,
"cmakeCommandArgs": "",
"buildCommandArgs": "",
"ctestCommandArgs": "",
"inheritEnvironments": [ "linux_x64" ],
"remoteCopySourcesExclusionList": [ "Debug", "Release", ".intermediate", ".vs", "Setup" ]
}
And now I have installed Windows 10 Pro and WSL.
By default WSL have mount my local drives(like /mnt/c, /mnt/d) and in my opinion there no more sense to make a copy of source code folder.
But if I will change remoteCMakeListsRoot property to "/mnt/d/Solution_dir" VS will start rsync that will remove my .git folder and all folders from remoteCopySourcesExclusionList property.
If I will remove remoteCopySourcesExclusionList property from CMakeSettings.json rsync will remove .git folder anyway.
What is the true way to work with WSL from Visual Studio? How can I say to VS that no need to start rsync?