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?
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.
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)
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.