Search code examples
windowsperlstrawberry-perl

How to call system with VAR=$VAL passed to called program?


I'm using Strawberry Perl (latest) on Windows 7 (fully patched). I'm trying to invoke nmake to compile a library. The makefile is OK and I use it manually. Next I want to automate it.

I'm having trouble getting some Perl correct. I have the following:

#!/usr/bin/env perl

use strict;
use warnings;

my $DEBUG32_CXXFLAGS="/DDEBUG";

system('nmake', '/f', 'cryptest.nmake', 'CXXFLAGS="$DEBUG32_CXXFLAGS"');

It results in:

        cl.exe EBUG32_CXXFLAGS /Yc"pch.h" /Fp"pch.pch" /c pch.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

cl : Command line warning D9024 : unrecognized source file type 'EBUG32_CXXFLAGS
', object file assumed
cl : Command line warning D9027 : source file 'EBUG32_CXXFLAGS' ignored
pch.cpp
        cl.exe EBUG32_CXXFLAGS /c cryptlib.cpp

According to how to pass arguments to system command in perl, I'm supposed to use the dollar sign for the scalar variable. Searching for terms like "how to pass a scalar variable through system" keeps leading back to the Stack Overflow question and answer.

Attempting to use variations, like 'CXXFLAGS="DEBUG32_CXXFLAGS"', 'CXXFLAGS="${DEBUG32_CXXFLAGS}"' and others results in similar Perl breaks.

I'm using single quotes because system(nmake, /f, cryptest.nmake); and system("nmake", "/f", "cryptest.nmake") did not work as expected. These are close to the cited question and answer.

Eventually I am going to need to pass a real name value pair. That would be closer to something like DEBUG_CXXFLAGS = /nologo /W4 /wd4511 /D_MBCS /Zi /TP /GR /EHsc /MD /FI sdkddkver.h /FI winapifamily.h

How do I call system with VAR=$VAL passed as an argument to the called program?

Thanks in advance


> perl.exe --version

This is perl 5, version 22, subversion 1 (v5.22.1) built for MSWin32-x64-multi-thread

Solution

  • Variables only get expanded in double quoted strings. You can use single quotes around the parameters that don't include variables, but you'll need to switch to double quotes for the ones that do.

    The next problem is that you want to include a double quote character in the string that uses double quotes as a delimiter. To achieve that, use a backslash character to escape each double quote inside the string:

    my $DEBUG32_CXXFLAGS="/DDEBUG";
    
    system('nmake', '/f', 'cryptest.nmake', "CXXFLAGS=\"$DEBUG32_CXXFLAGS\"");
    

    Another approach is to use the qq double quote operator which provides the double quote context you need for variable interpolation, but allows you to chose the delimiter. In this example I chose to use curly braces to delimit the string:

    system('nmake', '/f', 'cryptest.nmake', qq{CXXFLAGS="$DEBUG32_CXXFLAGS"});
    

    More details can be found in the docs on Quote and Quote like Operators.