Perl: How to deal with a duplicated modules installation? - strawberry-perl

I'm new with Perl and stumbled on a doubled modules installation.
I made a fresh installation of Strawbery Perl on Windows 10. After that, I tried to update all modules at once by using a command proposed in this answer; :
cpan-outdated -p | cpanm
Unfortunately, it appeared that probably the updates were installed on another location:
whichpm -a Mojolicious
C:\Strawberry\perl\site\lib\Mojolicious.pm
C:\Strawberry\perl\vendor\lib\Mojolicious.pm
whichpm -v Mojolicious
whichpm: WARNING: DUPLICATE module files found for 'Mojolicious':
C:\Strawberry\perl\vendor\lib\Mojolicious.pm
Mojolicious 8.22 (non-core) C:\Strawberry\perl\site\lib\Mojolicious.pm
How to deal whit that case?
How to prevent such cases in further updates?
perl -wE "say for #INC"
C:/Strawberry/perl/site/lib/MSWin32-x64-multi-thread
C:/Strawberry/perl/site/lib
C:/Strawberry/perl/vendor/lib
C:/Strawberry/perl/lib

Everything is working as expected.
There are three sets of installation locations: core, vendor and site.
The vendor directories are usually used by the package managers of linux distros, but it appears that Strawberry Perl includes a number of non-core modules in its distribution (including Mojolicious) and it places these in the vendor directories. This is proper.[1]
The site directories are used for user-installed modules. So your upgraded Mojolicious was installed into the site directories. This is proper.
(More on the differences here.)
This is not a problem because the site directories are placed before the vendor directories in #INC, so the user-installed version of a module is found before the vendor-installed version.
Using the site directories would probably also have been fine since Strawberry Perl doesn't provide a way of managing the distributions it bundles. But using the vendor directories is sure to be safe.

Related

"Fatal error: 'EXTERN.h' file not found" while installing Perl modules

While trying to install Perl modules like JSON::XS or YAML::XS, i receive the same error:
XS.xs:1:10: fatal error: 'EXTERN.h' file not found
I use MacBook, xCode is up to date, everything else that could help is up to date too.
Since OS X El Capitan, Apple introduced System Integrity Protection which restricts writing to /usr/lib /usr/bin and other sensitive directories (even to root or sudo user) that are used by the installation of Perl bundled with the Operating System. This can cause issues when it comes to installing new modules and also if trying to install XS modules ( those linked to external C libraries ).
For this reason you should not consider the default Perl installation as a working development environment, especially if you are installing custom modules.
Check out this thread on PM and others. I had since El-Capitan managed to solve this before by manually building from tarball and adding a few params or environment variables to set the paths believing that it would be best to retain use of the system Perl but this is not the way to go. This makes your environment difficult to build but also brittle and sensitive to OS updates that may either break things in many different ways.
The best practice seems to be starting with a Perl using brew install perl and work in this environment, remembering to setup your bash_profile as directed by the installer.
Also worth remembering to do a brew link perl. If you receive warnings about this clobbering what looks like system Perl libraries don't worry - these are likely modules that were installed by you over the top and it will cause you less trouble to link over these. If you have concerns, make a note of which module installs will be cleared and re-install them once your environment is configured ( ie your module installer approach is configured using cpanm or sticking with the old perl -MCPAN -e shell etc)
This new Perl setup from brew eliminates the need to continuing running sudo which adds another layer of things that can go wrong as environment variables don't follow through and permission conflicts arise etc.
Finally to simplify package/module installation I suggest doing a brew install cpanminus. If you had previously already installed this, you can ensure the paths etc are configured by doing a brew reinstall cpanminus
If you want to take it another step further then you can install perlbrew as well which will give you the ability to run multiple versions of Perl as your user and configure these with their own libs and modules which can be very useful particularly if aligning with your production environment for testing etc.
One problem you may face if moving from system Perl to this kind of approach is needing to deal with any hangovers from installing things with sudo. It wis worth taking a little time to get all this set up right though and your issues going forward will be greatly reduced and you won't be left with that nagging feeling that you don't want to change anything for fear of it all breaking.
I have also come across a Perl Blog Article that suggests a fix for XS issues with perlbrew on Mojave
This Gist described updating your cpan shell install root though this shouldn't be necessary unless your cpan is stuck in an old config after taking steps above.
I've also raised this as a new issue on PerlMonks
After reading https://developer.apple.com/documentation/xcode_release_notes/xcode_10_release_notes#3035624 and installing the Additional headers via
sudo installer -pkg /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg -target /
I successfully compiled without the missing 'EXTERN.h' error
In order to follow the common advice I also tried with Perlbrew to install a dedicated development version of Perl. Especially with the advice in mind First, do not use the system Perl on MacOS. The installed version is for Apple, not for you (see the discussion here: https://www.perlmonks.org/?node_id=1224727).
Unfortunately, the following error occurred:
Test Summary Report
-------------------
porting/libperl.t (Wstat: 65280 Tests: 35 Failed: 0)
Non-zero exit status: 255
Parse errors: No plan found in TAP output
Files=2653, Tests=1217766, 708 wallclock secs (52.74 usr 9.40 sys + 395.38 cusr 49.90 csys = 507.42 CPU)
Result: FAIL
make: *** [test_harness] Error 1
##### Brew Failed #####
Therefore, I decided to install it the following way (and not following the advice due to the error).
Even after having the above mentioned macOS SDK headers already installed on Catalina (macOS 10.15.2) it didn't work for me. I faced the issue during the installation of the Perl module Mac-SystemDirectory-0.13. The following steps (by identifying the missing file in hope of having a more generic approach for more or less equivalent issues) did the trick:
Locate the header file (in this case EXTERN.h)
sudo find /Library -type f -name EXTERN.h
/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/System/Library/Perl/5.18/darwin-thread-multi-2level/CORE/EXTERN.h
/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Perl/5.28/darwin-thread-multi-2level/CORE/EXTERN.h
/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Perl/5.18/darwin-thread-multi-2level/CORE/EXTERN.h
Ensure the installed Perl version (here 5.18) match the header file:
perl -v | grep version
This is perl 5, version 18, subversion 4 (v5.18.4) built for darwin-thread-multi-2level
Export the path for the C-Compiler (note MacOSX10.15.sdk for Catalina and Perl Version 5.18)
export CPATH=/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Perl/5.18/darwin-thread-multi-2level/CORE
Invoke the Makefile.PL with perl
perl Makefile.PL
BTW — For anybody who's still struggling with this, my workaround was:
bash% module="Sub::Util" # For example
bash% cpanm --configure-args="INC=-I/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Perl/5.18/darwin-thread-multi-2level/CORE" "$module"
Please try this
CPATH=$(dirname $(find /usr/local/Cellar/ -name EXTERN.h)) cpan JSON::XS
For Big Sur and perl 5.30, EXTERN.h is at /Library/Developer/CommandLineTools/SDKs/MacOSX11.3.sdk/System/Library/Perl/5.30/darwin-thread-multi-2level/CORE
I'm trying to upgrade CPAN itself and got that error. But I have /usr/bin/cpan and I can't write there so I have to tweak it to write the updated version to /usr/local/bin/cpan.
No promises, but yum install perl-devel worked for me.
As #huyz has helpfully pointed out, if you hit this error on a Mac, you don't have this option, even though this is probably your issue, and you need to follow one of the above methods of getting a version of Perl that isn't missing important chunks, as per other answers.
But if, dear reader, you hit this error on a linux host, as I did, then this might be an option for you.
Building on what E Lisse suggested, you might also have luck looking in
/System/Volumes/Data/Library/Developer/CommandLineTools/SDKs/
For example:
CPATH=$(dirname $(find /System/Volumes/Data/Library/Developer/CommandLineTools/SDKs/ -name EXTERN.h)) cpan JSON::XS
You could also find where EXTERN.h is located and add that to your shell by default, e.g. in your .bashrc or .zshrc file:
export CPATH=/System/Volumes/Data/Library/Developer/CommandLineTools/SDKs/MacOSX12.sdk/System/Library/Perl/5.18/darwin-thread-multi-2level/CORE/

How to install MySQL unattended with custom settings?

This is the command-line used install MySQL silently,
/quiet
But how to run the MySQL installer unattended with custom settings in the installer?
UPDATE: A newer and somewhat related answer here.
UPDATE: Several stages of answers here. I will leave them all in. The proposed technical solution / workaround moved to the top.
Instance Configuration
The actual configuration of instances seems to have been moved from MySQLInstanceConfig.exe to the installer itself: Where is the MySql 5.6 equivalent of `MySQLInstanceConfig.exe` to edit configuration files? Please try the MySQLInstallerConsole.exe (note: that links to version 8.0, not 5.7) application, sample:
Silent Installation: It seems this console appliation can run the installation silently in
various flavors, making the procedure below optional.
MSI Packages
I did a test run of what I believe was the mysql-5.7.22-winx64.msi file (there are many MSI files embedded in the main one, please see below). My best tip: get on the phone with the vendor to determine if they have actively tried to prevent silent installation. They just might have, and then you might be fighting windmills over time. They should improve this design if you ask me - though it is not the worst I have seen.
By launching the original, large MSI and enabling automatic logging (see section in that link: "Globally for all setups on a machine"), then running through its built-in, custom GUI and kicking off the actual install and then checking the "CommandLine" entry in the actual log file generated in the temp folder - it looks like it sets the following properties: REBOOT, ADDLOCAL, INSTALLDIR, INSTALLLOCATION, ARPINSTALLLOCATION, INSTALL_ROOT, DATADIR. Actual log entry below:
******* Product: C:\ProgramData\MySQL\MySQL Installer for Windows\Product Cache\mysql-5.7.22-winx64.msi
******* Action:
******* CommandLine: REBOOT=ReallySuppress ADDLOCAL=RegKeys,ALWAYSINSTALL,Readme,MISC,Server_Scripts,ProgramMenu,MYSQLSERVER,Client,DEVEL,SharedLibraries,UserEditableDataFiles INSTALLDIR="C:\Program Files\MySQL\MySQL Server 5.7" INSTALLLOCATION="C:\Program Files\MySQL\MySQL Server 5.7" ARPINSTALLLOCATION="C:\Program Files\MySQL\MySQL Server 5.7" INSTALL_ROOT="C:\Program Files\MySQL\MySQL Server 5.7" DATADIR="C:\ProgramData\MySQL\MySQL Server 5.7" ALLUSERS=1
These are in other words the properties set by the custom setup GUI that normally runs the installation process. You should be able to use this procedure for all the embedded MSI files you need to install. Then you simply extract these MSI files that you need from the large MSI and run them in sequence in some fashion, with the command lines you have found. You can also apply transforms if need be.
To state the obvious: this might take you some time to get right as you struggle with pre-requisites and your corporate use case. I'd go for piloting. Find a dynamic team and get your stuff on their test PCs quickly and tell them to give it a trashing asap :-). Chances are you already do, just mentioning it. I for one can never get these things right without some unfortunate, time-consuming iterations.
Summary of procedure:
Enable automatic logging (MSI expert Stefan Kruger's info)
Install via custom setup-GUI with options set as appropriate
Find properties to set in the log file in the %temp% folder.
Log file will have random name, sort by data and open most recently changed log file.
Get hold of the embedded MSI files from the wrapper setup:
Get hold of an MSI tool for viewing / editing MSI files (list towards bottom)
Delete launch conditions from wrapper setup (LaunchCondition table)
Extract content like this: msiexec.exe /a mysql-installer-community-5.7.22.1.msi TARGETDIR=C:\YourFolder
Tha above command kick off an administrative installation - essentially a glorified file extract, but a very good feature of MSI used by application packagers every day
Try to install on a test machine with an msiexec.exe command line based on the properties you found set
Sample:
msiexec.exe /i mysql-5.7.22-winx64.msi REBOOT=ReallySuppress ADDLOCAL="RegKeys,ALWAYSINSTALL,Readme,MISC,Server_Scripts,ProgramMenu,MYSQLSERVER,Client,DEVEL,SharedLibraries,UserEditableDataFiles" INSTALLDIR="C:\Program Files\MySQL\MySQL Server 5.7" INSTALLLOCATION="C:\Program Files\MySQL\MySQL Server 5.7" ARPINSTALLLOCATION="C:\Program Files\MySQL\MySQL Server 5.7" INSTALL_ROOT="C:\Program Files\MySQL\MySQL Server 5.7" DATADIR="C:\ProgramData\MySQL\MySQL Server 5.7" ALLUSERS=1 /QN
And some parameter info:
ADDLOCAL="..." - list of features to install locally
REBOOT=ReallySuppress - prevent spontaneous reboot
ALLUSERS=1 - install per machine
/QN - crucial addition to the command line found in the log file. this makes the install run in silent mode
Unusual MSI Design: I know this is an unusual MSI, but generally you call the vendor or search their website to obtain documentation for deployment such as this and follow the procedure I outline below (let me add the link here too: How to make better use of MSI files) using PUBLIC properties or transforms to modify the installation.
However, I wrote the section below before I did a quick check of this MSI. A quick look revealed a myriad of embedded MSI packages. Not at all good. The MSI also has no GUI, and its administrative installation (file extraction) is blocked with a launch condition. Quite terrible design in fact. You can make an administrative installation by deleting the launch conditions using Orca or an equivalent tool and going:
msiexec.exe /a mysql-installer-community-5.7.22.1.msi TARGETDIR=C:\YourFolder
It seems the idea is that this is a wrapper MSI which will launch a proprietary GUI (.NET based?) that you can then use to install the bits and pieces you need of the MySQL tool suite. It would have been much better if this launcher was a setup.exe built with WiX Burn, Installshield, Advanced Installer or an equivalent tool.
Recommended Procedure: The honest answer is that I don't know. I would call the vendor if possible, check their user forums and do some further googling in general. Most of the embedded MSI files should be possible to install in silent mode, I would hope.
The real-world approach would probably be to extract all the MSI files using the above administrative installation trick, although there must be a reason why they block administative installations - which I am unaware of. Most likely they do not want to support silent installation with options? (give them a call?). Then you take the individual MSI files you need, and see if they will install in silent mode using the approach described here with PUBLIC properties and / or transforms. There are many features in these setups, and you can use ADDLOCAL at the command line to define which ones to install and not. See the linked answer below. However, as I state below as well; feature control is a very complex topic (recommended skim).
Beware of pre-requisite runtime requirements. There may be several, such as the .NET framework and various runtimes. I see several of these being installed by the custom setup GUI.
My original, generic answer below:
MSI: It looks like this installer is in Windows Installer format, in other words an MSI file. You are in luck in the sense that MSI files are very flexible with regards to silent installation and the configration of custom paramenters. It is, however, dependpent on the package being well-designed, which is not always the case.
PUBLIC PROPERTIES and Transforms: I have an ancient answer here on the topic of customizing MSI installations: How to make better use of MSI files (just the first parts, the ending flies a bit off the handle with other topics). As you will see in the linked answer, you essentially set available PUBLIC properties at the command line, or create a transform to customize anything you want in the installer. The latter is what most corporations do for deployment.
Configuration: What properties can be set at the command line (that has any effect), varies between different setups. The setup creator must have made these properties - and built functionality around them in the setup - for them to be configurable. Typical parameterized values would include license keys, URLs to license servers and user and company names and emails and similar. For more substantial changes (such as changing shortcuts or similar), people usually resort to using a transform. You also use the ADDLOCAL property to define which features to install (all other features will not be installed if you specify a value for ADDLOCAL). Feature control is a built-in property of MSI, and you can control feature selection in detail from the command line or via a transform. However, feature control is a very complex topic (recommended skim).
Concrete Sample: As mentioned above you need to set properties and values as appropriate for the setup in question. This means you have to hit the documenation for the setup in question to determine what is "settable" or not.
Some Links:
https://downloads.mysql.com/docs/refman-5.7-en.pdf
https://dev.mysql.com/doc/mysql-installation-excerpt/5.5/en/windows-using-installer.html

How do I find out what version of a bower package is actually installed?

Normally a bower.json file specifies some dependencies, but these are typically expressed so that they allow a range of versions of a bower package to be used (e.g. >=1.0, which means anything higher than version 1.0).
I have an automated process which needs to find what version of a bower package is actually installed on this system right now.
How can I find this out programmatically (just the version itself), ideally using standard Unix command line tools / the bower command?
bower info <thepackagename> does not show this - it shows information about what is currently available from the bower repository (for example, even if I do bower info apackageIdonthaveinstalled it will still show a valid JSON structure containing a version number).
cat bower_components/thepackagename/bower.json | node_modules/json/lib/json.js version works for some packages (assuming the npm package json is installed), but not all (e.g. jquery 2.2.0's bower package does not contain a bower.json).
Here's a grep command to do that:
grep "version\"\:" bower_components/thepackagename/.bower.json
Also, a command to see versions of all bower components for the project - this list can be a handy CI artefact:
grep "version\"\:" bower_components/*/.bower.json
Have you ever tried "bower list --json=0 --offline".
It would list all bower packages info.
The best approach I've now found, which seems to work for every package I've come across so far, is:
cat bower_components/thepackagename/.bower.json | node_modules/json/lib/json.js version
(note the extra . in .bower.json).
It would appear that bower stores some metadata about the installed package in .bower.json, and that includes the installed version.
The best I've come up with so far is:
bower list | grep jquery | perl -pe 's/.*jquery#(.*?) .*$/$1/'
(if, for example, the package I was interested in was jquery).
That's pretty ugly for a variety of reasons:
I have to repeat the package name (although this could probably be improved
with a better Perl script which filters lines too, I'm just being lazy).
bower list gets information about all installed packages, not just the one I'm interested in - the rest of the information is discarded.
bower list seems to require internet connectivity to check the registry, otherwise it fails.
Would be interested to see if this could be improved upon, particularly the last point.

How to use execute mysqldiff utilities in command line?

I have two versions of my database. The n and n+1 version. I want to know the difference between the two version. I have downloaded the archive on the link mysqldiff utility
I unzip my archive and went in the bin directory, then i type mysqldiff -help. But at my surprise, i have the following message. mysqldif is not recognozed as command line. Is there any way to install it ?
Thanks
Well, if you read the INSTALL file in the link you gave, it doesn't say to download the archive, it says to install via CPAN.
However, I'm not sure why you'd use a CPAN module or some random Github archive when MySQL distributes a mysqldiff.exe [1] tool itself.
[1] http://dev.mysql.com/downloads/utilities/
I'm the author of that ancient CPAN module and I don't really maintain it any more. It looks like another mysqldiff is offered in the MySQL Utilities suite which seems to be maintained (here's a github clone) and also a lot more sophisticated, so I'd recommend trying that.

Create fedora rpm that works with both upstart and systemd?

I've built a service and I'd like to distribute it via rpm and should work on different fedora releases. Since it is a service it should be integrated with the system so it is possible to do:
$ service myapp start
The problem is that fedora used upstart in releases 9 to 14 and systemd from 15 and up. I can do this for both systems, but I'm not sure how to package it correctly.
I think I have to build different rpms for the fedora releases. The only thing that differs is a few files to be copied to different locations.
How should I handle the differences? In the .spec-file or Makefile? Or should I use two different .spec-files?
Do it in the spec file. Use separate sources for the upstart and systemd scripts, and include the appropriate script based on the version of Fedora being built on. So, single spec file to handle both cases.