Search code examples
oracleunixmakefileenvironment-variablessolaris

Setting dynamic ORACLE_HOME in makefile


So my organization is upgrading our Oracle database from 11g to 19c.

Previously, in my makefile, I had been setting ORACLE_HOME like this:

ORACLE_HOME=/opt/app/oracle/product/11.2.0.4/db_1

However, Oracle 19c has a fun feature that whenever they run a patch on it, the db_1 changes incrementally, becoming db_2, then db_3, with each patch, etc.

So obviously I can't hardcode the ORACLE_HOME path anymore.

In a bunch of my scripts, I'm pulling the current value from the ortab file, like this:

setenv ORACLE_SID DATABASE1
setenv ORACLE_HOME `cat /var/opt/oracle/oratab | sed 's/#.*//g' | grep -w $ORACLE_SID | awk -F: '{print $2;}'`

And this is working just fine, pulling the correct ORACLE_HOME path from the ortab file.

However, when I tried to do this in a makefile, like so:

ORACLE_SID=DATABASE1
ORACLE_HOME=`cat /var/opt/oracle/oratab | sed 's/#.*//g' | grep -w $ORACLE_SID | awk -F: '{print $2;}'`

I get this error when I try to run make:

 $ make
 `cat /var/opt/oracle/oratab | sed 's//bin/proc sys_include=/usr/include lines=yes iname=file1.pc oname=file1.c include=/path/to/include
 First RE may not be null
 *** Error code 2
 make: Fatal error: Command failed for target `file1.o'

So obviously the command isn't working the way I'm expecting, but I am unsure how to fix it. How do I fix the command to work inside makefile? I'm running Solaris 11.
This is not GNU make, this is just the default make that comes with Solaris 11.

Adding more information:

My ortab file looks like this:

$cat /var/opt/oracle/oratab
DATABASE_TEST:/opt/app/oracle/product/11.2.0.4/db_7:Y
DATABASE1:/opt/app/oracle/product/19.0.0.0/db_3:N
DATABASE2:/opt/app/oracle/product/11.2.0.4/db_13:Y
DATABASE3:/opt/app/oracle/product/11.2.0.4/db_1:Y
DATABASE_PROD:/opt/app/oracle/product/11.2.0.4/db_2:Y

So, what I need to do, is using the ORACLE_SID of DATABASE1, pull out the /opt/app/oracle/product/19.0.0.0/db_3 part, to use as my ORACLE_HOME directory in the makefile.

Update: Based on an answer below from MadScientist , this is now my makefile:

ORACLE_SID=DATABASE1
#ORACLE_HOME = /opt/app/oracle/product/19.0.0/db_3
ORACLE_HOME = `cat /var/opt/oracle/oratab | sed 's/\#.*//g' | grep -w ${ORACLE_SID} | awk -F: '{print $$2;}'`

PROC=${ORACLE_HOME}/bin/proc

E_INCLUDE=/path/to/include

print-%  : ; @echo $* = $($*)

file1.o: file1.pc
        ${PROC} sys_include=/usr/include lines=yes iname=$*.pc oname=$*.c include=${E_INCLUDE}

When I hardcode ORACLE_HOME, everything works correctly.

When I try to use the dynamically created ORACLE_HOME, I get this error:

$ make
`cat /var/opt/oracle/oratab | sed 's/\#.*//g' | grep -w DATABASE1 | awk -F: '{print $2;}'`/bin/proc sys_include=/usr/include lines=yes iname=file1.pc oname=file1.c include=/path/to/include
 make: Fatal error: Command failed for target `file1.o'

So it looks like it's setting ORACLE_HOME as the command itself, rather than as the result of the command.

Weirdly, when I run make print-ORACLE_HOME, I get the expected result /opt/app/oracle/product/19.0.0/db_3


Solution

  • I finally got it to work.

    Using @Milag 's answer regarding the :sh command substitution, I was able to find the documentation regarding that for Solaris (not GNU) make: link to documentation

    THIS was the answer:

    ORACLE_HOME :sh =cat /var/opt/oracle/oratab | sed 's/\#.*//g' | grep -w DATABASE1 | awk -F: '{print $2;}'
    

    The key? NOT putting a double dollar sign, as the documentation said:

    "In contrast to commands in rules, the command is not subject for macro substitution; therefore, a dollar sign ($) need not be replaced with a double dollar sign ($$)."

    Because of this I also had to hardcode DATABASE1 instead of using the ${ORACLE_SID} variable, but since that value will never change, I can live with that.