nmake fails on building Perl module - windows

I am trying to build Win32::Daemon by myself. The reason I not use CPAN is because I want to dig deeper into the working of Perl modules. In the end I hope to come up with a solution for another problem by seeing this working (not of importance here).
I would see 3 options to build the module: cygwin, mingw, microsoft compiler (cl)
On MinGW it reports that it is not supported (simple if in the Makefile.PL) which expands to more errors once I modify the check to match MinGW
On Cygwin it complains about tchar.h which, as I found out, is a Windows header (MinGW does have it).
But my real goal anyway is building it with the MS compiler, so while any compilation that does not require any special libs (like it would do with cygwin I suppose) will more.
So now here goes my nmake output from running just name /f Makefile:
NMAKE : fatal error U1073: "C:/Program" could not be created.
Stop.
I roughly translated the error message from german, but the statement is simple.
What I see here seems to be a path problem (probably the spaces). I also notice the forward slash. The Makefile was created by the Makefile.PL script (I am using Active Perl v5.12.1):
use strict;
use warnings;
use Config qw(%Config);
use ExtUtils::MakeMaker;
unless ($^O eq "MSWin32" || $^O eq "cygwin") {
die "OS unsupported\n";
}
require Win32;
my %param = (
NAME => 'Win32::Daemon',
VERSION_FROM => 'Daemon.pm',
DEFINE => '-DPERL_NO_GET_CONTEXT',
OBJECT => 'CCallbackList$(OBJ_EXT) CCallbackTimer$(OBJ_EXT) Constant$(OBJ_EXT) CWinStation$(OBJ_EXT) Daemon$(OBJ_EXT) ServiceThread$(OBJ_EXT)',
XS => { 'Daemon.xs' => 'Daemon.cpp' },
);
$param{INC} .= ' -EHsc' if $Config{'cc'} =~ /^cl/i;
$param{NO_META} = 1 if eval "$ExtUtils::MakeMaker::VERSION" >= 6.10_03;
WriteMakefile(%param);
sub MY::xs_c {
'
.xs.cpp:
$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) $(XSUBPP) $(XSPROTOARG) $(XSUBPPARGS) $*.xs >xstmp.c && $(MV) xstmp.c $*.cpp
';
}
I don't know much about the MakeMaker but I don't see anything here that I could fix and would expect that it boils down to fixing the Makefile itself by hand. I tried a couple of things like quoting but nothing helped.
The thing is, I am used to problems like this when building on Windows, but normally this is for tools that were created for Unix. This one is explicitly ONLY Windows and so I would expect it to work out of the box. So I figure that I am doing something wrong.
Any help on where to find the solution?
Thanks in advance.
Edit/Addition: I tried this on another Win7 machine with Active Perl 5.16.x and it worked like a charm. I looked at the different output from this machine and the current one which fails when running perl Makefile.PL and I recieve the following output:
... Detected uninstalled Perl. Trying to continue.
Unable to find a perl 5 (by these names: C:\Program Files\Perl64\bin\perl.exe perl.exe perl5.exe perl5.12.1.exe miniperl.exe, in these dirs: . [...] C:\Program Files\Perl64\site\bin C:\Program Files\Perl64\bin [...])
Have \progra~1\perl64\lib
Want \temp\perl---please-run-the-install-script---\lib
Writing Makefile for Win32::Daemon
I truncated the output. Now please someone explain to me: Why can I run perl Makefile.PL or perl -v but it does not find my Perl in the exact directory it is in? I reinstalled it but it did not work...

Okay I finally seem to have solved this after hours of searching. The problem lies within multiple issues.
The first command of "uninstalled perl" does not make any sense to be, but you can fix it, by supplying perl Makefile.PL PERL_SRC="C\:Program Files\Perl64". Warning: This did not work in a command shell for me, I had to use powershell, because he would not treat the path correctly. You maybe need to juggle with this a bit. Note: In the end I fixed it by installing the original Active Perl, not the one provided by my installer (company software distribution)
Now to the issue of not finding perl: This is a problem with spaces in the path. I fixed this (seemingly) by creating a symlink without spaces. Now perl Makefile.PL does not throw any errors, but nmake -f "Makefile" failed. So the solution really was: Do not have spaces in your perl-path! This sucks, and quite frankfly in 2012 this shouldn't be a problem any more but here you go.
Thanks for all the effort everyone put in, this was a tough one to solve.

Related

Chef compile error when capturing shell output

I have a chef recipe that looks something like this:
package 'build-essential' do
action :install
end
cmd = Mixlib::ShellOut.new("gcc -dumpversion")
cmd.run_command
gcc_version = cmd.stdout.strip()
If I execute the recipe on a system where gcc is installed, the recipe runs fine without errors. However, if I run the recipe on a system which doesn't have gcc install I get the error 'no such file or directory - gcc'.
I came to know about the chef two-phases stuff when trying to find a solution to my problem. I was expecting the package installation to satisfy the gcc requirement. How can I tell chef that this requirement will be satisfied later and not throw an error at compile time?
I tried the following, but the attribute does not get updated.
Chef::Resource::RubyBlock.send(:include, Chef::Mixin::ShellOut)
ruby_block "gcc_version" do
block do
s = shell_out("gcc -dumpversion")
node.default['gcc_version'] = s.stdout.strip()
end
end
echo "echo #{node[:gcc_version]}" do
command "echo #{node[:gcc_version]}"
end
Any help is appreciated. Thanks.
So okay, a few issues here. First, forget that Chef::Resource::whatever.send(:include trick. Never do it, literally never. In this case, the ShellOut mixin is already available in all the places anyway.
Next, and more importantly, you've still got a two-pass confusion issue. See https://coderanger.net/two-pass/ for details but basically the strings in that echo resource (I assume that said execute originally and you messed up the coping?) get interpolated at compile time. You haven't said what you are trying to do, but you probably need to use the lazy{} helper method.
And last, don't store things in node attributes like that, it's super brittle and hard to work with.

Trying to compile with make on Windows gives error 127

this is the very first time that I try to compile anything in Windows and it already gives me the creeps (not because of Windows that is).
I downloaded a dictionary from here:
https://www.j3e.de/ispell/igerman98/dict/igerman98-20161207.tar.bz2
When I extract the folder then there is a Makefile, so I think that I have to compile the progrmam first. I tried that with two methods: first Cygwin, second MinGW. Both programs are in my PATH.
I use the terminal of both programs to navigate to D:/igerman98 and there I enter
make
The first message I get is:
$ make
A default make target doesn't exist. You might want to use one of those:
make hunspell/de_DE.dic hunspell/de_DE.aff (or de_AT or de_CH)
make myspell/de_DE.dic myspell/de_DE.aff (or de_AT or de_CH)
make ispell/de_DE.aff ispell/de_DE.hash (or de_AT, de_CH ...)
make aspell/de_DE.rws (or de_AT, de_CH ...)
make ligature/rmligs
make isowordlist-de_DE (or de_AT, de_CH ...)
Did I forget an important one ?-)
So I enter again the following:
make hunspell/de_DE.dic hunspell/de_DE.aff
But then I get the following error:
$ make hunspell/de_DE.dic hunspell/de_DE.aff
test -e all.words.placebo.tmp || echo a > all.words.placebo.tmp
buildhash all.words.placebo.tmp ispell/de_DE_null.aff ispell/de_DE_null.hash
make: buildhash: Command not found
make: *** [ispell/de_DE_null.hash] Error 127
What am I doing wrong here? I just want de_DE.dic and de_DE.aff files to be created so I can use them with the spelling module in Textadept...
Under Linux, the program buildhash comes with the ispell-package. Under Windows, you can use: ISPELL for Windwos

Why do I get 'Can't locate object method "init" via package "wlgmod::odt"' when I try to run wyd.pl in Cygwin?

I'm trying to run a Perl script called WyD using Cygwin on Windows. Cygwin is installed at C:\cygwin64, and WyD is installed at C:\wyd\wyd.pl. Both are in the Windows PATH environment variable as C:\cygwin64 and C:\wyd respectively.
When running WyD with bash/Mintty using:
wyd.pl -b -e -t -s 3 -o "OUTPUTTEDWORDLIST" "TARGETFOLDER"
...I get the following error:
Can't locate object method "init" via package "wlgmod::odt" (perhaps
you forgot to load "wlgmod::odt"?) at /cygdrive/c/WYD/wyd.pl line 284.
Sometimes wlgmod::odt is replaced with wlgmod::doc or any other document type, but running the script always generates that same basic error. A previous answer to this question recommended installing several dependencies, which turned out to be a mere copy-paste of an answer for Ubuntu systems, and didn't solve the error, so I've decided to start at the beginning and re-ask the question with more details. I also have all Perl packages in the Cygwin installer installed.
After everything I've tried and done to get this script working, I can personally think of two possible causes for the error. Think of these as a guide more than anything else.
The error above references line 284 in the wyd.pl script, so it's possible that something in that script is hardcoded so that it doesn't work with Cygwin/Windows, or just generally has a compatibility bug. I don't understand Perl, so I can't confirm this.
I notice that the installation of WyD at C:\wyd contains a folder called wlgmod, and that folder contains all the files that the above error seems to be looking for; doc.pm, html.pm, jpeg.pm, etc. If those files exist in that directory but bash is unable to find them, maybe it's due to the fact WyD needs to be run from within Cygwin itself. I've only recently thought about this possibility, and my knowledge of both Cygwin and WyD is too sparse to definitively know how both work. Is it even possible to run WyD from within the Cygwin folder? It's not a package so can't be installed as one, and therefore I'm not sure how that would work.
Here are the relevant sections of the script:
# Module hash containing module name and supported file extensions
# Multiple extensions are seperated using ';'
my %wlgmods = (
'wlgmod::strings', '', # only used with command-line switch
'wlgmod::plain' , '.txt', # used for all MIME text/plain as well
'wlgmod::html' , '.html;.htm;.php;.php3;.php4',
'wlgmod::doc' , '.doc',
'wlgmod::pdf' , '.pdf',
'wlgmod::mp3' , '.mp3',
'wlgmod::ppt' , '.ppt',
'wlgmod::jpeg' , '.jpeg;.jpg;.JPG;.JPEG',
'wlgmod::odt' , '.odt;.ods;.odp'
);
...
# Initialize possible modules
foreach(keys %wlgmods) {
eval("use $_;");
my $ret = $_->init(); # line 284
# If module failed, add errortext and remove from hash
if($ret) {
$retvals .= "$_: $ret\n";
delete $wlgmods{$_};
$ret = "";
}
}

Why isn't my GNAT's standout file descriptor working?

As part of a little project, I'm writing a shell in Ada. As such, when I was investigating the system calls, I learned that there are three ways to do it.
The POSIX system calls, which are probably the least reliable.
Passing the arguments along to C's system(), which I didn't really want to do, since this was about writing the emulator in Ada and not C.
Using GNAT's runtime libraries.
I chose to go for the last option, considering this to be the most "Ada-like" of the choices. I found a code snippet on RosettaCode here. I copied and pasted it and compiled it after changing the "cmd.exe" to "ls" and removing the second argument definition. However, nothing happens when I run the executable. The shell just goes right back to the prompt. I have tested this on two different computers, one running Fedora 21, the other Debian Jessie. Here's what I've done to test it:
Seen if lacking an arguments string caused it
Checked if any of the file descriptors in GNAT's libraries are mis-named
Redirected both stderr and stdin to stdout just to see if GNAT was dumping them to the wrong FD anyway.
Looked thoroughly through the System.OS_lib library file, and there seems to be no reason.
Googled it, but GNAT's own page on the GCC website is very poorly documented.
For now I'm using the C.Interface system in the preparation of my shell, but I'm dissatisfied with this. I'm new to Ada and have only been tinkering with it for a month or so now, so if there's some kind of Ada wisdom here that would help I'm not in on it.
UPDATE: I have tried running it with absolute path, both to /usr/bin and /bin locations, and it doesn't work. Interestingly, the result code returned by the operating system is 1, but I don't know what that means. A quick search suggests that it's for "all general errors", and another site suggests that it's for "incorrect functions".
I had to tweak the RosettaCode example a little to run /bin/ls on Debian Linux, but it does run as expected...
with Ada.Text_IO; use Ada.Text_IO;
with Gnat.OS_Lib; use Gnat.OS_Lib;
procedure Execute_Synchronously is
Result : Integer;
Arguments : Argument_List :=
( 1=> new String'("-al")
);
begin
Spawn
( Program_Name => "/bin/ls",
Args => Arguments,
Output_File_Descriptor => Standout,
Return_Code => Result
);
for Index in Arguments'Range loop
Free (Arguments (Index));
end loop;
end Execute_Synchronously;
Changes :
my Gnat (FSF Gnat 4.92 from Debian Jessie) warned about System.OS_Lib, recommending Gnat.OS_Lib instead. (Which simply renames System.OS_Lib .... why???
System.OS_Lib comments:
-- Note: this package is in the System hierarchy so that it can be directly
-- be used by other predefined packages. User access to this package is via
-- a renaming of this package in GNAT.OS_Lib (file g-os_lib.ads).
Program name including path.
Arguments. The first time I ran it, it displayed the details of "ls" itself, because it was given its own name as the first argument, so I deleted that to see the current directory instead.
Notes :
the best information ot the available subprograms and their arguments is usually in the package specs themselves in the "adainclude" folder : this is /usr/lib/gcc/x86_64-linux-gnu/4.9/adainclude on my Debian installation, locate system.ads will find yours. The specific files are: s-os_lib.ads for System.OS_Lib which exports Spawn and Standout, and a-textio.ads for Ada.Text_IO.
Standout is not the preferred way of accessing Standard Output : it's a file descriptor (integer), the preferred way would be the Standard_Output function from Ada.Text_IO which returns a File. However there doesn't seem to be an overload for Spawn which takes a File (nor would I expect one in this low level library) so the lower level file descriptor is used here.
Absent a shell, you'll need to search the PATH yourself or specify a full path for the desired executable:
Spawn (
Program_Name => "/bin/ls",
…
);
I have tried running it with absolute path…neither /usr/bin nor /bin locations work.
Use which to determine the full path to the executable:
$ which ls
/bin/ls

How can I include Win32 modules only when I'm running my Perl script on Windows?

I have a problem that I cannot seem to find an answer to.
With Perl I need to use a script across Windows and unix platforms. Te problem is that on Windows we use Win32-pecific modules like Win32::Process, and those modules do not exist on unix.
I need a way to include those Win32 modules only on Windows.
if($^O =~ /win/i)
{
use win32::process qw(CREATE_NEW_CONSOLE);
}
else
{
#unix fork
}
The problem lies in that use statement for windows. No matter what I try this does not compile on unix.
I have tried using dynamic evals, requires, BEGIN, etc.
Is there a good solution to this problem? Any help will be greatly appreciated.
Thanks in advance,
Dan
Update:
A coworker pointed out to me this is the correct way to do it.
require Win32;
require Win32::Process;
my $flag = Win32::Process::CREATE_NEW_CONSOLE();
Win32::Process::Create($process,
$program,
$cmd,
0,
$flag, ".") || die ErrorReport();
print "Child started, pid = " . getPID() . "\n";
Thank you all for your help!
Dan
use is executed at compile time.
Instead do:
BEGIN {
if( $^O eq 'MSWin32' ) {
require Win32::Process;
# import Win32::Process qw(CREATE_NEW_CONSOLE);
Win32::Process->import(qw/ CREATE_NEW_CONSOLE /);
}
else {
#unix fork
}
}
See the perldoc for use.
Also see perlvar on $^O.
Update:
As Sinan Unur points out, it is best to avoid indirect object syntax.
I use direct method calls in every case, except, with calls to import. Probably because import masquerades as a built-in. Since import is really a class method, it should be called as a class method.
Thanks, Sinan.
Also, on Win32 systems, you need to be very careful that you get the capitalization of your module names correct. Incorrect capitalization means that symbols won't be imported properly. It can get ugly.use win32::process may appear to work fine.
Are you sure win32::process can be loaded on OSX? "darwin" matches your /win/i.
You may want to use http://search.cpan.org/dist/Sys-Info-Base/ which tries to do the right thing.
That aside, can you post an example of the code that you actually are using, the failure message you're receiving, and on which unix platform (uname -a) ?
What about a parser that modifies the file on each OS?
You could parse your perl file via a configure script that works on both operating systems to output perl with the proper Use clauses. You could even bury the parse action in the executable script to launch the code.
Originally I was thinking of precompiler directives from C would do the trick, but I don't know perl very well.
Here's an answer to your second set of questions:
Are you using strict and warnings?
Did you define an ErrorReport() subroutine? ErrorReport() is just an example in the synopsis for Win32::Process.
CREATE_NEW_CONSOLE is probably not numeric because it didn't import properly. Check the capitalization in your call to import.
Compare these one-liners:
C:\>perl -Mwin32::process -e "print 'CNC: '. CREATE_NEW_CONSOLE;
CNC: CREATE_NEW_CONSOLE
C:\>perl -Mwin32::process -Mstrict -e "print 'CNC: '. CREATE_NEW_CONSOLE;
Bareword "CREATE_NEW_CONSOLE" not allowed while "strict subs" in use at -e line 1.
Execution of -e aborted due to compilation errors.
C:\>perl -MWin32::Process -e "print 'CNC: '. CREATE_NEW _CONSOLE;
CNC: 16
You could just place your platform specific code inside of an eval{}, and check for an error.
BEGIN{
eval{
require Win32::Process;
Win32::Process->import(qw'CREATE_NEW_CONSOLE');
};
if( $# ){ # $# is $EVAL_ERROR
# Unix code here
}
}

Resources