Search code examples
makefilegnu-makebusybox

Running GREP command in windows build system


I am trying to read the text in header file elf.h which has following content:-

#define ELFOSABIV_STDELF_V1          8U      // STD ELF ABI
#define ELFOSABIV_PRE_STDELF         7U      // latest abi version
#define ELFOSABIV_LATEST             6U      // latest abi version

Basically, I am interested in ELFOSABIV_LATEST version which is 6U.

Here is my makefile snippet:-

MDCONVERTER := $(HOST_TOOLSBIN)/mdConverter$(EXESUFFIX) --abi-version `$(GREP) -Po '^\#define\s+ELFOSABIV_LATEST\s+\K\S+' $(ELF_DIR)/elf.h`

--abi-version parameter to mdConverter.exe has to be 6U. Above makefile snippet works fine in Linux build system where i am getting the output 6U for grep command. Issue is seen only on windows.

In windows build system, it uses busybox_glob.exe which is software suite that provides several Unix utilities in a single executable. Here is the command in log file :-

build/busybox_glob.exe grep -Po '^#define\s+ELFOSABIV_LATEST\s+\K\S+' /home/test/utilities/elf/elf.h 

Issue i am facing:-

BusyBox v1.25.0-FRP-261-gea341c7 (2015-11-01 15:13:33 GMT) multi-call binary.

Usage: grep [-HhnlLoqvsriwFEz] [-m N] [-A/B/C N] PATTERN/-e PATTERN.../-f FILE [FILE]...

Search for PATTERN in FILEs (or stdin)

    -H  Add 'filename:' prefix
    -h  Do not add 'filename:' prefix
 ....

Instead of following grep/sed, I am trying to achieve this via perl one liner where the command is same, But output is different as follows:-

In Linux:-

perl -ne "print $1 if /#define\s+ELFOSABIV_LATEST\s+(\S+)/" /home/test/elf/elf.h
#define ELFOSABIV_LATEST             6U

In Windows:-

perl -ne "print $1 if /#define\s+ELFOSABIV_LATEST\s+(\S+)/" /home/test/elf/elf.h
 6U

Why is the difference in output among windows and linux above?


Solution

  • Presumably, the impetus to use the Perl flavor of regexes (grep -P) came from wanting to extract only the ABI version number from the line. Having started with the questionable choice of grep -o for the purpose, you then needed something like Perl's \K to separate the version number from the rest of the line. That relies on features specific to GNU's implementation of grep, which you don't have in your Windows build environment, and which you might not have in some other environments, either.

    Better in every context would be to use a more appropriate tool for the job in the first place.

    Option 1

    Since you're analyzing macro definitions in a header file, the most fitting choice for the job would be the C preprocessor. For example, you could include this test file in your distribution:

    elf_version_test.c

    #include <elf.h>
    ELFOSABIV_LATEST
    

    Then, supposing that your makefile defines CPP as as a command to run the C preprocessor (for example, as gcc -E if you're using gcc), your makefile might do this:

    MDCONVERTER := $(HOST_TOOLSBIN)/mdConverter$(EXESUFFIX) \
      --abi-version $$($(CPP) -I$(ELF_DIR) elf_version_test.c | tail -n1)
    

    Option 2

    If you're determined to analyze the header directly, then sed would be a better choice for that than grep. I would expect any suite that aims to provide a Unix-like build environment to include sed in the tools provided, too. That might look like so:

    MDCONVERTER := $(HOST_TOOLSBIN)/mdConverter$(EXESUFFIX) \
      --abi-version $$($(SED) -n '/#define ELFOSABIV_LATEST/ s/^.*LATEST[[:space:]]\+\([^[:space:]]\+\).*/\1/p')
    

    That's a bit of a mouthful, but it's still a one-liner, and it does the job using only POSIX-specified features.