Node-gyp (or gyp) action targets containing =, & on Linux - node-gyp

I'm using node-gyp on Linux with and need to use actions to define custom build steps (note sure whether this is a node-gyp issue or a general gyp issue).
The documentation seems to suggest that you should specify the command for the build steps as an array of strings, which must get concatenated together at some point to form the command:
'action': ['python', 'tools/js2c.py', '<#(_outputs)', 'CORE', '<#(core_library_files)'],
As it's Linux, node-gyp is going to generate a makefile for each target in the binding.gyp file, and for actions the custom command will appear in that makefile.
The problem I'm having is that the command needs to contain an = sign to set an environment variable as part of the command, and I need to chain commands with &&, e.g.:
export FOO=BAR && do-something-else --option
If I try to specify that as a gyp actions step, I hit various problems. I tried adding each 'word' in the command as a separate array element.
'action': ['export', 'FOO=BAR', '&&', 'do-something-else', '--option'],
That doesn't work, gyp (or rather the shell the command is passed to) complains that '&&' is not a valid identifier.
Peeking into the generated makefile, the command has been expanded to this, which explains the shell error:
export "FOO=BAR" "&&" do-something-else --option
The quotes have been left around the variable assignment and the &&. It's not clear why. I've tried many variations to stop this from happening to no avail. Anything that contains = or & ends up with quotes left around it, which in most cases renders the command syntax invalid.
Suggestions appreciated.

The reason this happens is that Gyp considers everything after the first word to be an argument to the command given in the first word so it quotes these and other special characters to prevent the shell interpreting them. I do not think there is any way to prevent it which, as you discovered, makes creating a custom command using a pipeline of shell commands well nigh impossible.

Related

How to specify the flags and files needed for the program to work in debug mode? [duplicate]

I need someone to outline how to pass command line arguments to CLion. What I've found so far hasn't worked for me. Specifically I need to know how to pass multiple arguments to the program from the command line.
If you click on Run-Edit Configurations you can create an "Application" configuration that allows you to provide the Program arguments - either in a single line, or in a separate window one argument per line.
I landed on this SO page as I was using CLion with Rust.
For Rust I was able to add the command line arguments to the end of the Run\Edit Configurations\Command. Notice the required --.
I got this tip from Jetbrains.
For C, it was Run\Edit Configurations\Program Arguments, as #Zulan said.

How to pass installation arguments directly to an MSI installer (like -ArgumentLIist in PowerShell) using Chocolatey?

I want to pass custom arguments directly to the MSI installer. I have tried adding those arguments in the silentArgs but when I do that, after I run choco install I get the following (and after that the installation is aborted):
This is how I have passed those parameters in silentArgs:
silentArgs = "/qn /norestart /l*v `"$($env:TEMP)\$($packageName).$($env:chocolateyPackageVersion).MsiInstall.log`" /CUSTOMPARAM1:'dummydata' /CUSTOMPARAM2:'dummydata'"
I have tried different syntax (instead of using :, I used = but still the same result). Then I tried choco install <pckgName> --install-arguments="CUSTOMPARAM1=""dummy.data""", but with this approach the package does get installed but the parameters weren't passed to the MSI installer. I searched for some kind of docs related to --install-arguments such as the format that it expects (e.g. quotes, = or :, etc.) but didn't find anything.
TLDR; I want to pass custom parameters/arguments to my MSI installer through choco.
For an installer package that is managing an MSI, you must pass arguments to the underlying installer as the installer expects to see them, for an MSI, that is UPPERCASEPROPERTY="Value" NEXTPROPERTY="Another value". Otherwise MSI exec will pop up like you are seeing, telling you that you are passing things to it incorrectly.
There are three approaches to this if you are creating the packaging:
In Packaging
Install-Arguments (the only option if you are using a package you can't change)
Package Parameters (recommended)
I'll go through each in a bit more detail.
In Packaging - chocolateyInstall.ps1
You were actually quite close on this. All you needed to do was change:
/CUSTOMPARAM1:'dummydata' in
silentArgs = "/qn /norestart /l*v `"$($env:TEMP)\$($packageName).$($env:chocolateyPackageVersion).MsiInstall.log`" /CUSTOMPARAM1:'dummydata' /CUSTOMPARAM2:'dummydata'"
to:
CUSTOMPARAM1=`"dummydata`", such as the following (I renamed CUSTOMPARAM1 to MSIPROPERTY below to signify that these must already exist in the MSI installer as properties you can set):
silentArgs = "/qn /norestart /l*v `"$($env:TEMP)\$($packageName).$($env:chocolateyPackageVersion).MsiInstall.log`" MSIPROPERTY=`"dummydata`" EXISTINGMSIPROPERTY2=`"dummydata`""
Install-Arguments at Runtime - choco install
You could also pass in additional arguments directly to the installer at runtime.
choco install <pkgName> --install-arguments="'CUSTOMPARAM1=""dummy.data""'" (NOTE: the quoting bits are specific to the shell you are running, cmd.exe expects these one way and powershell.exe needs them a bit different.). https://docs.chocolatey.org/en-us/choco/commands/#how-to-pass-options-switches (see Pass Quotes in Arguments) Also note this is different in that it employs the quotes bookending apostrophes as Chocolatey docs describe it ("'values'").
Also, if you want to override the install arguments already being passed with silentArgs instead of just appending to the end of it, you want to use an additional switch --override-arguments. From https://docs.chocolatey.org/en-us/choco/commands/install#options-and-switches:
-o, --override, --overrideargs, --overridearguments, --override-arguments
OverrideArguments - Should install arguments be used exclusively without appending to
current package passed arguments? Defaults to false.
Package Parameters
This is a combination of putting together package parameters in your ChocolateyInstall.ps1 and then deciding how to pass those to the silentArgs.
Based on the docs, you'll want to specify default options you would have for each parameter, then you'll look to convert that properly.
Based on https://docs.chocolatey.org/en-us/guides/create/parse-packageparameters-argument, you would set up something like this in your script:
$pp = Get-PackageParameters
$additionalArgs = ''
if ($pp['SOMEPROPERTY']) {
$additionalArgs += " MSIPROPERTYNAME=`"$($pp['SOMEPROPERTY'])`""
}
[..snip..]
silentArgs = "/qn /norestart MSIPROPERTY=`"dummydata`" $additionalArgs"
# removed /l*v args for readability/brevity
You would want to add those parameters to the description of your nuspec file. There is a specific format as outlined at https://docs.chocolatey.org/en-us/guides/create/parse-packageparameters-argument#step-2-add-package-parameters-to-the-description
And then you can call the Choco install like this:
choco install <pkgName> --package-parameters="'/SOMEPROPERTY=dummy.data'"
The benefits of Package Parameters:
The syntax is easier to pass - no weird quoting issues are required.
You can set sensible defaults.
You can validate what is passed in with the property.
You can name things how you want and translate them to the installer arguments.
You can provide a better explanation in validation of a value than something like an MSI exec pop up or error code that is unhelpful.
You can fail a package if there is a required parameter you need.
You can use package parameters for other things as well - https://docs.chocolatey.org/en-us/guides/create/parse-packageparameters-argument#example
It looks to me like you are passing the same argument in twice, once in the silent args for your package and again when calling choco install. I think this is where the issue lies as I believe msiexec will use the first value it finds for a given parameter. If you want to override the silent arguments, you will need to add the --override-arguments parameter to choco install. The downside to this approach is that this will override all of the silent args baked into the package, so you will also need provide all of the silent arguments needed to install the package.
If this is a package you developed (which it seems like it might be), I would suggest making use of package parameters instead. This way you can keep the default silent installation arguments, and in your ChocolateyInstall.ps1 you can add each CUSTOMPARAM to -SilentArgs passed in via a package parameter or optionally set defaults (or omit the extra parameters) for parameters that are not passed in. You can also throw errors if a require package parameter is not provided.

CMake: how to break a PRE_LINK infinite loop?

I'm trying to automatically label my application sign-on line with a build number. This application is a plain vanilla C one without graphic UI; it is intended for command line, therefore it is a "simple" one.
The sign-on id is located in a "template" source file which is customized by CMake with a configure_file() command. Recently, I fancied to include a build number in this sign-on id. Consequently, the customization can no longer be statically done at CMake time, but everytime make is invoked.
To achieve that, there are two possibilities in CMake:
add_custom_target(), but it is triggered even when nothing else changes in the source tree which does not reflect the state of the tree;
add_custom_command(), which can be triggered only when the application (target) needs to be linked again.
I opted for the second solution and did not succeed.
Here is an extract of my CMakeLists.txt, the sign-on id being in file ErrAux.c (template in PROJECT_SOURCE_DIR, configured in PROJECT_BINARY_DIR):
add_executable(anathem ... ${PROJECT_BINARY_DIR}/ErrAux.c ...)
add_custom_command(TARGET anathem PRE_LINK
COMMAND "${CMAKE_COMMAND}" "-DVERS=${PROJECT_VERSION}"
"-DSRC=${PROJECT_SOURCE_DIR}"
"-DDST=${PROJECT_BINARY_DIR}"
-P "${CMAKE_HOME_DIRECTORY}/BuildNumber.cmake"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT "Numbering build"
VERBATIM
)
This launches script BuildNumber.cmake just before the link step. It computes the next build number and customizes ErrAux.c with configure_file().
It works fine, except ...
It happens late in the make sequence and the update to ErrAux.c goes unnoticed. The sign-on id in the executable contains the previous build number.
Next time I run make, make notices the generated ErrAux.c is younger than its object module and causes it to be compiled again, which in turn causes a link which triggers a build number update. This happens even if no other file has changed and this loop can't be broken. This is clearly shown in the compiling log:
Scanning dependencies of target anathem
[ 13%] Building C object AnaThem/CMakeFiles/anathem.dir/ErrAux.c.o
[ 14%] Linking C executable anathem
Numbering build
3.0.0-45
[ 36%] Built target anathem
The crux seems to be that add_custom_command(TARGET ...) can't specify an output file like add_custom_command(OUTPUT ...) does. But this latter form can't be triggered in PRE_LINK mode.
As a workaround, I forced a compilation to "refresh" the object module with:
add_custom_command(TARGET anathem PRE_LINK
COMMAND "${CMAKE_COMMAND}" "-DVERS=${PROJECT_VERSION}"
"-DSRC=${PROJECT_SOURCE_DIR}"
"-DDST=${PROJECT_BINARY_DIR}"
-P "${CMAKE_HOME_DIRECTORY}/BuildNumber.cmake"
COMMAND echo "Numbering"
COMMAND echo "${CMAKE_C_COMPILER}" "\$(C_DEFINES)" "\$(C_INCLUDES)" "\$(C_FLAGS)" -c "${PROJECT_BINARY_DIR}/ErrAux.c"
COMMAND "${CMAKE_C_COMPILER}" "\$(C_DEFINES)" "\$(C_INCLUDES)" "\$(C_FLAGS)" -c "${PROJECT_BINARY_DIR}/ErrAux.c"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT "Numbering build"
VERBATIM
)
An explicit compilation is forced after sign-on id customization. It mimics what is found in the various Makefile's and my not be safe for production. It's a cheat trick on both CMake and make.
UPDATE: Option -c is required to postpone link step until the final application liniking process.
This addition creates havoc in the link, as shown by the log, where you see a double compilation (the standard make one and the add_custom_command() one):
Scanning dependencies of target anathem
[ 13%] Building C object AnaThem/CMakeFiles/anathem.dir/ErrAux.c.o
[ 14%] Linking C executable anathem
Numbering build
3.0.0-47
Numbering
/usr/bin/cc -DANA_DEBUG=1 -I/home/prog/projects/AnaLLysis/build/AnaThem -I/home/prog/projects/AnaLLysis/AnaThem -g /home/prog/projects/AnaLLysis/build/AnaThem/ErrAux.c
/usr/lib/gcc/x86_64-redhat-linux/6.3.1/../../../../lib64/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
AnaThem/CMakeFiles/anathem.dir/build.make:798: recipe for target 'AnaThem/anathem' failed
make[2]: *** [AnaThem/anathem] Error 1
If I force a full recompilation, to make sure all sources are compiled, *main.c* included, I get the same error on `main`.
The only logical explanation is my manual C invocation is faulty and somehow destroys vital information. I checked with *readelf* that `main` is still in the symbol table for *main.c.o* and that it is still taken into account by the link step (from file *link.txt*).
UPDATE: Even with the correct link, I'm still experiencing the infinite loop syndrom. The generated application still has its sign-on id lagging behind the actual build counter.
Can someone give me a clue for the right direction?
FYI I'm quite new to CMake, so I may do things really wrong. Don't hesitate to criticize my mistakes.
The key to the solution is to put the generated module where make expects to find it. CMake organizes the build tree in a non-trivial way.
The shortcomming in my added compilation in add_custom_command() was to believe that by default the binary will be stored in the "usual" CMake locations. Since I forge manually my compiler command, this is not the case.
I found the module in the source directory, which is a consequence of the WORKING_DIRECTORY option, with name ErrAux.o and not ErrAux.c.o.
To obtain the correct behavior, I force an output location with:
-o "${PROJECT_BINARY_DIR}/CMakeFiles/anathem.dir/ErrAux.c.o"
Now, when I run make again, nothing happens since nothing changed.
Side question
To make the solution portable (if needed), are there CMake variables for CMakeFiles and anathem.dir directories? Or in the latter case, for the current target as "anathem" as the target name in add_custom_command()?

Syntax error: word unexpected (expecting ")")

Problem in short - In Linux, whenever we get the following error
"Syntax error: word unexpected (expecting ")")", what does it generally mean?
Problem in details - I have been trying to cross-compile Qt 4.6 as per the Sourcery tool chain on Ubuntu 10.04 (Lucid Lynx). I followed the exact steps mentioned at the link compiling Qt-4.6. But I get the following error right in the ./configure step -
/home/weds/qt-everywhere-opensource-src-4.6.1/bin/qmake: 1: Syntax error: word unexpected (expecting ")")
Searching on the Internet I found lots of posts regarding this error and read all of them. What is this error and how can I solve it?
P.S 1 - the Sourcery toolchain is present inside /opt/ folder and my PATH variable is correctly pointing to it.
P.S 2 - This toolchain was not installed manually by me. Rather it was provided by a vendor as a .tgz file which I extracted inside the /opt/ folder.
That's an error reported by the Almquist shell or any of its derivatives like Dash (and Dash happened to be the default implementation of /bin/sh on Ubuntu 10.04 (Lucid Lynx)) when a word is found while parsing the syntax of a script where a ) is expected instead, for instance like in this case statement:
dash -c 'case a in b c) :; esac'
dash: 1: Syntax error: word unexpected (expecting ")")
That's because after b , the only thing that is expected after is ), (though actually | would also be allowed) so that c word is unexpected.
dash -c 'myfunc( something'
dash: 1: Syntax error: word unexpected (expecting ")")
One case where that can happen is if the script has been written on or transferred through a Microsoft OS where text line endings are CRLF instead of just LF.
A
case a in b) cmd1;;
c) cmd2
esac
script written on MS-DOS would appear as:
case a in b) cmd1;;<CR>
c) cmd2<CR>
esac<CR>
on Unix and that c would be an extra word after the <CR> word.
Here that's unlikely as your error reports the problem being on the first line of the script and most scripts start with the #! /path/to/interpreter shebang line.
Another possibility is that that script you're trying to run has been written on the assumption that sh was bash and uses constructs that are not portable to other sh implementations.
Since you're using an outdated and no longer maintained OS, it's also possible that you're running into a bug in that version of Dash. You could run dpkg-reconfigure dash and tell the system not to use Dash for sh (but Bash instead) to see if that helps.
Again, it is unlikely to be on the first line.
What sounds more likely is that that qmake file is not a script, but a binary executable that is not recognised as such by the system, for instance because it is of a binary format for the wrong architecture or it has been corrupted in transfer.
In that case, when the system fails to recognise it as a native executable, the invoking application would try to run sh on it as if it was a shell script, and the presence of a ( character in the file could cause Dash to fail with such an error.
On my system:
dash /bin/touch
/bin/touch: 1: /bin/touch: Syntax error: word unexpected (expecting ")")
And if you look at the content of /bin/touch as if it were a script, you see:
^?ELF^B^A^A^#^#^#^#^#^#^#^#^#^B^#>^#^A^#^#^#5&#^#^#^#^#^##^#^#^#^#^#^#^#(ô^#^#...
An answer to this seems to be posted in the instructions to which you linked.
Admittedly it's a long way down in the comments but it didn't take long to search for qmake: Syntax error: word unexpected.
Quote:
Tej says: January 4, 2013 at 12:20 pm
Ok, I have solved the Problem. Its very unfortunate that ppl did not
tell what actually is the problem. Problem is we have to use Host
qmake. For that whatever Export (export
PATH=/usr/local/arm/4.3.2/bin:$PATH etc.) we did in step during tslib
installation, we have to undo all of that. Thats it.
Hope that help someone
In case that's not clear, Tej suggests that it would seem that you're trying to run the cross-compiled qmake on the host system.
In 99% of the cases it is a wrong file transfer mode, ASCII or binary.
Try to extract the toolchain directly on the target system.
I was writing a C++ program on Ubuntu 18.04 (Bionic Beaver) when this problem came around. The cause was that the file name of the program contained the characters "(" and ")". After renaming the files, it worked for me.
This error can also be thrown when calling a NodeJS script from a shell script, without providing the correct shebang line in NodeJS:
#!/usr/bin/env node
// Rest of your NodeJS script
A weird fix for me was deleting file package-lock.json and the node_modules folder, and then building the Docker image again.
Sometimes this error occurs just because the directory in which you are currently working has "wrong naming convention" .. like it could be
demo_project (copy)
my_project_1 (another copy)
The correct naming convention says
1. demo_project_copy
2. my_project_1_another_copy

tclreadline - insert-completions

I'm using tclreadline to handle completions in my project, which is written in C/C++ and TCL.
I had to modify some configurations to deal with Readline 6.2, but I managed it.
I have 3 problems:
I defined other commands in the TCL interpreter, like get_ports and get_modules.
If I type get_por, it correctly executes get_ports, but the history says get_por.
If I type get_por -of_objects [get_mod], it correctly executes get_ports -of_objects [get_modules], but the history says get_por -of_objects [get_mod]. So the command is not expanded before adding it to the history. How can I manage this?
If I type get_por -of [get_mod] it doesn't expand -of in -of_objects, because I check for -of_objects inside the command and it doesn't appear. How can I manage INSERT-COMPLETIONS mode of readline? Or alternatively, any kind of INSERT-ALL-COMPLETIONS ?
If I type get_por -ofTAB, tclreadline issues an error of ScriptCompleter, which says that get_por is not a command. It should complete the command, first, and then complete the option, which is defined in a proc complete(get_ports).

Resources