Repository: Rblp/Rblpapi
Pull request #406: Make build more robust to absence of viable blp library and headers
Author: login: eddelbuettel
Created: 2025-03-09T16:17:28Z | Merged: 2025-03-10T01:30:00Z

Fixes #405 

This addresses the issue described in #405.  We now (on Unix and alike, windows is as usual separate) only attempt to download on the two known-good setups: amd64 on linux, and arm64 on macos.  Other combinations such as the (on life-support at CRAN) older amd64 on macOS will build with `#define` indicating lack of blp support.  All exported files now have an empty fallback and just return NULL or an empty list or data.frame.  The startup message reflects this too.

No actual working configuration is changed in any way.

Linked issue #405: Make build more tolerant of Blp absence
It is a little irritating that after years of asking for a more subtle approach of building CRAN, the package is still blindly submitted to whichever platform finds it.  So given that Bloomberg long ceased to supply macOS binaries for x86_64, this just fails and gets us three ERROR states on old-rel, rel, and dev.

I had once made `RcppApt` more robust to build on non-apt platforms (i.e. anything but Debian at CRAN) and can do the same here.  In fact, I just did.  I will open a PR and keep it open for inspection for a few days.  It uses `configure` to define flag, and wraps all blp-related compilation in the 'can do' branch with empty returns in the 'cannot do' branch.  This appears to work here (when the detection is overridden) and I will try to see if someone with an x86_64 macOS system can corrobate.

Diff:
diff --git a/ChangeLog b/ChangeLog
index 1c65567..51a2b70 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,27 @@
+2025-03-09  Dirk Eddelbuettel  <edd@debian.org>
+
+	* DESCRIPTION (Version, Date): Roll micro version and date
+
+	* configure: Rework to actively support amd64 on Linux and arm64 on
+	macOS only and define -DNoBlpHere otherwise
+	* src/Makevars.in: Adjusted accordingly for link and install_name_tool
+	* src/authenticate.cpp: Compilation reflects #if defined(NoBlpHere)
+        * src/bdh.cpp: Idem
+        * src/bdp.cpp: Idem
+        * src/bds.cpp: Idem
+        * src/beqs.cpp: Idem
+        * src/blpConnect.cpp: Idem
+        * src/blpVersion.cpp: Idem
+        * src/blpapi_utils.cpp: Idem
+        * src/bsrch.cpp: Idem
+        * src/fieldsearch.cpp: Idem
+        * src/getBars.cpp: Idem
+        * src/getFieldInfo.cpp: Idem
+        * src/getTicks.cpp: Idem
+        * src/lookup.cpp: Idem
+        * src/subscribe.cpp: Idem
+	* R/init.R: Startup message adjusted for build with/without blp
+
 2025-03-08  Dirk Eddelbuettel  <edd@debian.org>
 
 	* .github/workflows/ci.yaml: Use r-ci action with embedded bootstrap
diff --git a/DESCRIPTION b/DESCRIPTION
index 459c20d..e4ddafc 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,7 +1,7 @@
 Package: Rblpapi
 Title: R Interface to 'Bloomberg'
-Version: 0.3.15.1
-Date: 2024-12-04
+Version: 0.3.15.2
+Date: 2025-03-09
 Authors@R: c(person("Whit", "Armstrong", role = "aut"),
              person("Dirk", "Eddelbuettel", role = c("aut", "cre"), email = "edd@debian.org",
                     comment = c(ORCID = "0000-0001-6419-907X")),
diff --git a/R/init.R b/R/init.R
index 6d99b65..c78e78e 100644
--- a/R/init.R
+++ b/R/init.R
@@ -1,6 +1,6 @@
 
 ##
-##  Copyright (C) 2015 - 2016  Whit Armstrong and Dirk Eddelbuettel and John Laing
+##  Copyright (C) 2015 - 2025  Whit Armstrong and Dirk Eddelbuettel and John Laing
 ##
 ##  This file is part of Rblpapi
 ##
@@ -21,28 +21,33 @@
 .pkgenv <- new.env(parent=emptyenv())
 
 .onAttach <- function(libname, pkgname) {
-    packageStartupMessage(paste0("Rblpapi version ", packageVersion("Rblpapi"),
-                                 " using Blpapi headers ", getHeaderVersion(),
-                                 " and run-time ", getRuntimeVersion(), "."))
-    packageStartupMessage(paste0("Please respect the Bloomberg licensing agreement ",
-                                 "and terms of service."))
+    hrd <- getHeaderVersion()
+    rtm <- getRuntimeVersion()
+    if (nchar(hrd) + nchar(rtm) == 0) {
+        packageStartupMessage("No Blp available so no Rblapi functionality.")
+    } else {
+        packageStartupMessage(paste0("Rblpapi version ", packageVersion("Rblpapi"),
+                                     " using Blpapi headers ", hrd, " and run-time ", rtm, "."))
+        packageStartupMessage(paste0("Please respect the Bloomberg licensing agreement ",
+                                     "and terms of service."))
 
-    if (getOption("blpAutoConnect", FALSE)) {
-        con <- blpConnect()
-        if (getOption("blpVerbose", FALSE)) {
-            packageStartupMessage("Created and stored default connection object.")
+        if (getOption("blpAutoConnect", FALSE)) {
+            con <- blpConnect()
+            if (getOption("blpVerbose", FALSE)) {
+                packageStartupMessage("Created and stored default connection object.")
+            }
+        } else {
+            con <- NULL
         }
-    } else {
-        con <- NULL
-    }
-    if (getOption("blpAutoAuthenticate", FALSE)) {
-        blpAuth <- blpAuthenticate()
-        if (getOption("blpVerbose", FALSE)) {
-            packageStartupMessage("Created and stored default authentication object.")
+        if (getOption("blpAutoAuthenticate", FALSE)) {
+            blpAuth <- blpAuthenticate()
+            if (getOption("blpVerbose", FALSE)) {
+                packageStartupMessage("Created and stored default authentication object.")
+            }
+        } else {
+            blpAuth <- NULL
         }
-    } else {
-        blpAuth <- NULL
+        assign("con", con, envir=.pkgenv)
+        assign("blpAuth", blpAuth, envir=.pkgenv)
     }
-    assign("con", con, envir=.pkgenv)
-    assign("blpAuth", blpAuth, envir=.pkgenv)
 }
diff --git a/configure b/configure
index f4f8498..81a9920 100755
--- a/configure
+++ b/configure
@@ -3,7 +3,7 @@
 ##
 ##  configure -- Unix build preparation system
 ##
-##  Copyright (C) 2015 - 2024  Dirk Eddelbuettel and Jeroen Ooms.
+##  Copyright (C) 2015 - 2025  Dirk Eddelbuettel and Jeroen Ooms.
 ##
 ##  This file is part of Rblpapi
 ##
@@ -26,7 +26,8 @@ if ! [ -x $(command -v uname) ]; then
     exit 1
 fi
 
-## Check for Linux or OSX
+## Check for Linux or OSX. "These days" we support x86_64 on Linux and arm64 on macOS.
+## At CRAN or R-universe we encounter nothing else.
 : ${R_HOME=$(R RHOME)}
 sysname=$(${R_HOME}/bin/Rscript -e 'cat(Sys.info()["sysname"])')
 if [ ${sysname} = "Linux" ]; then
@@ -37,32 +38,36 @@ else
     echo "Unsupported platform: $sysname"
     echo "Check https://www.bloomberg.com/professional/support/api-library/ for possible support first."
     echo "Contributions welcome, see https://github.com/Rblp/blp for integration with Rblapi."
-    exit 2
+    echo "The build will proceed but not be functional for lack of a library."
+    sed -e"s/@config@//" -e"s/@badsystem@/-DNoBlpHere/" src/Makevars.in > src/Makevars
+    exit 0
 fi
 
 ## Populate Makevars
 arch=$(uname -m)
-if [ "${arch}" = "x86_64" ]; then
-    echo "Setting up compilation for a ${platform} 64-bit system"
-    sed -e"s/@config@/blpapi3_64/" src/Makevars.in > src/Makevars
+if [ "${arch}" = "x86_64" -a "${platform}" = "linux" ]; then
+    echo "Setting up compilation for a ${platform} ${arch} system"
+    sed -e"s/@config@/-lblpapi3_64/" -e"s/@badsystem@//" src/Makevars.in > src/Makevars
     flavour="64"
-    if [ "${platform}" = "osx" ]; then
-        cpu="x86"
-    fi
-elif [ "${arch}" = "arm64" ]; then
-    echo "Setting up compilation for a ${platform} 64-bit system"
-    sed -e"s/@config@/blpapi3_64/" src/Makevars.in > src/Makevars
+    # this used to matter when Blp supported x86 on macos, they no longer do
+    #if [ "${platform}" = "osx" ]; then
+    #    cpu="x86"
+    #fi
+elif [ "${arch}" = "arm64" -a "${platform}" = "osx" ]; then
+    echo "Setting up compilation for a ${platform} ${arch} system"
+    sed -e"s/@config@/-lblpapi3_64/" -e"s/@badsystem@//" src/Makevars.in > src/Makevars
     flavour="64"
-    if [ "${platform}" = "osx" ]; then
-        cpu="arm"
-    fi
-elif [ "${arch}" = "i686" ]; then
-    echo "Setting up compilation for a ${platform} 32-bit system"
-    sed -e"s/@config@/blpapi3_32/" src/Makevars.in > src/Makevars
-    flavour="32"
+    cpu="arm"
+#elif [ "${arch}" = "i686" ]; then
+#    echo "Setting up compilation for a ${platform} 32-bit system"
+#    sed -e"s/@config@/blpapi3_32/" src/Makevars.in > src/Makevars
+#    flavour="32"
 else
-    echo "Unknown architecture: ${arch}. Exiting."
-    exit 3
+    echo "Unsupported platform and architecture combination: ${platform} ${arch}."
+    echo "The build will proceed but not be functional for lack of a library."
+    echo "If you need such a combination please get in touch with the Blp vendor."
+    sed -e"s/@config@//" -e"s/@badsystem@/-DNoBlpHere/" src/Makevars.in > src/Makevars
+    exit 0
 fi
 
 ## helper function to not rely on curl which at least on OS X fails to follow redirects
diff --git a/src/Makevars.in b/src/Makevars.in
index 03dfb60..785b808 100644
--- a/src/Makevars.in
+++ b/src/Makevars.in
@@ -26,8 +26,14 @@ BBG_RPATH   = '$$ORIGIN/../blp'
 
 ## set include and linker options
 ## Bbg API files are assummed to be in the standard search path
-PKG_CPPFLAGS = -I../inst/include/ -I.
-PKG_LIBS     = -l$(BBG_LIB) -L../inst/blp -Wl,-rpath,$(BBG_RPATH)
+PKG_CPPFLAGS = -I../inst/include/ -I. @badsystem@
+PKG_LIBS     = $(BBG_LIB) -L../inst/blp -Wl,-rpath,$(BBG_RPATH)
 
 all: $(SHLIB)
-	@if command -v install_name_tool; then echo "fixing"; install_name_tool -add_rpath @loader_path/../blp Rblpapi.so; fi
+        # we rely on configure to replace @badsystem@ here to create a side effect
+        # notice that that there are only two outcomes we need to differentiate:
+        # - either (on a 'good' system with blp) we will in an empty string, so command -v works as
+        #   usual and we can run install_name_tool to add/update the rpath of shared librart
+        # - or on a bad system without blp we append -DNoBlpHere making command -v fail and avoiding
+        #   an install_name_call that would fails as we have no Rblpapi.so to adjust
+	@if command -v install_name_tool@badsystem@; then echo "fixing"; install_name_tool -add_rpath @loader_path/../blp Rblpapi.so; fi
diff --git a/src/authenticate.cpp b/src/authenticate.cpp
index 41eb57f..f4f8c86 100644
--- a/src/authenticate.cpp
+++ b/src/authenticate.cpp
@@ -2,8 +2,8 @@
 //  authenticate.cpp -- Function to authenticate to Bloomberg backend
 //
 //  Copyright (C) 2013      Whit Armstrong
-//  Copyright (C) 2015-2024 Whit Armstrong and Dirk Eddelbuettelp
-//  Copyright (C) 2019-2024 Whit Armstrong, Dirk Eddelbuettel and Alfred Kanzler
+//  Copyright (C) 2015-2025 Whit Armstrong and Dirk Eddelbuettelp
+//  Copyright (C) 2019-2025 Whit Armstrong, Dirk Eddelbuettel and Alfred Kanzler
 //
 //  This file is part of Rblpapi
 //
@@ -20,6 +20,7 @@
 //  You should have received a copy of the GNU General Public License
 //  along with Rblpapi.  If not, see <http://www.gnu.org/licenses/>.
 
+#if !defined(NoBlpHere)
 
 #include <string>
 #include <blpapi_defs.h>
@@ -194,3 +195,13 @@ SEXP authenticate_Impl(SEXP con_, SEXP uuid_, SEXP ip_address_, SEXP is_auth_id_
     if(identity_p == NULL) { Rcpp::stop("Identity pointer is null\n"); }
     return createExternalPointer<Identity>(identity_p, identityFinalizer, "blpapi::Identity*");
 }
+
+#else // ie if defined(NoBlpHere)
+
+#include <Rcpp/Lightest>
+// [[Rcpp::export]]
+SEXP authenticate_Impl(SEXP con_, SEXP uuid_, SEXP ip_address_, SEXP is_auth_id_, SEXP app_name_) {
+    return R_NilValue;
+}
+
+#endif
diff --git a/src/bdh.cpp b/src/bdh.cpp
index d7a144c..e0d8aaa 100644
--- a/src/bdh.cpp
+++ b/src/bdh.cpp
@@ -2,7 +2,7 @@
 //  bdh.cpp -- "Bloomberg Data History" query function for the BLP API
 //
 //  Copyright (C) 2013      Whit Armstrong
-//  Copyright (C) 2015-2024 Whit Armstrong and Dirk Eddelbuettel
+//  Copyright (C) 2015-2025 Whit Armstrong and Dirk Eddelbuettel
 //
 //  This file is part of Rblpapi
 //
@@ -19,6 +19,7 @@
 //  You should have received a copy of the GNU General Public License
 //  along with Rblpapi.  If not, see <http://www.gnu.org/licenses/>.
 
+#if !defined(NoBlpHere)
 
 #include <vector>
 #include <string>
@@ -189,3 +190,19 @@ Rcpp::List bdh_Impl(SEXP con_,
     ans.attr("names") = ans_names;
     return ans;
 }
+
+#else // ie if defined(NoBlpHere)
+
+#include <Rcpp/Lightest>
+// [[Rcpp::export]]
+Rcpp::List bdh_Impl(SEXP con_,
+                    std::vector<std::string> securities,
+                    std::vector<std::string> fields,
+                    std::string start_date_, SEXP end_date_,
+                    SEXP options_, SEXP overrides_,
+                    bool verbose, SEXP identity_,
+                    bool int_as_double) {
+    return Rcpp::List();
+}
+
+#endif
diff --git a/src/bdp.cpp b/src/bdp.cpp
index 536785c..39b35c0 100644
--- a/src/bdp.cpp
+++ b/src/bdp.cpp
@@ -2,7 +2,7 @@
 //  bdp.cpp -- "Bloomberg Data Point" query function for the BLP API
 //
 //  Copyright (C) 2013         Whit Armstrong
-//  Copyright (C) 2015 - 2024  Whit Armstrong and Dirk Eddelbuettel
+//  Copyright (C) 2015 - 2025  Whit Armstrong and Dirk Eddelbuettel
 //
 //  This file is part of Rblpapi
 //
@@ -19,6 +19,7 @@
 //  You should have received a copy of the GNU General Public License
 //  along with Rblpapi.  If not, see <http://www.gnu.org/licenses/>.
 
+#if !defined(NoBlpHere)
 
 // compare to RefDataExample.cpp
 
@@ -138,3 +139,14 @@ Rcpp::List bdp_Impl(SEXP con_, std::vector<std::string> securities, std::vector<
     }
     return res;
 }
+
+#else // ie if defined(NoBlpHere)
+
+#include <Rcpp/Lightest>
+// [[Rcpp::export]]
+Rcpp::List bdp_Impl(SEXP con_, std::vector<std::string> securities, std::vector<std::string> fields,
+                    SEXP options_, SEXP overrides_, bool verbose, SEXP identity_) {
+    return Rcpp::List();
+}
+
+#endif
diff --git a/src/bds.cpp b/src/bds.cpp
index c0359bf..b7b443d 100644
--- a/src/bds.cpp
+++ b/src/bds.cpp
@@ -2,7 +2,7 @@
 //  bds.cpp -- "Bloomberg Data Set" query function for the BLP API
 //
 //  Copyright (C) 2013         Whit Armstrong
-//  Copyright (C) 2015 - 2024  Whit Armstrong and Dirk Eddelbuettel
+//  Copyright (C) 2015 - 2025  Whit Armstrong and Dirk Eddelbuettel
 //
 //  This file is part of Rblpapi
 //
@@ -19,6 +19,8 @@
 //  You should have received a copy of the GNU General Public License
 //  along with Rblpapi.  If not, see <http://www.gnu.org/licenses/>.
 
+#if !defined(NoBlpHere)
+
 #include <vector>
 #include <string>
 #include <blpapi_session.h>
@@ -295,8 +297,8 @@ Rcpp::List bds_Impl(SEXP con_, std::vector<std::string> securities,
 
 // [[Rcpp::export]]
 Rcpp::List getPortfolio_Impl(SEXP con_, std::vector<std::string> securities,
-                    std::string field, SEXP options_, SEXP overrides_,
-                    bool verbose, SEXP identity_) {
+                             std::string field, SEXP options_, SEXP overrides_,
+                             bool verbose, SEXP identity_) {
 
     Session* session =
         reinterpret_cast<Session*>(checkExternalPointer(con_, "blpapi::Session*"));
@@ -337,3 +339,21 @@ Rcpp::List getPortfolio_Impl(SEXP con_, std::vector<std::string> securities,
     }
     return R_NilValue;
 }
+
+#else // ie if defined(NoBlpHere)
+
+#include <Rcpp/Lightest>
+// [[Rcpp::export]]
+Rcpp::List bds_Impl(SEXP con_, std::vector<std::string> securities,
+                    std::string field, SEXP options_, SEXP overrides_,
+                    bool verbose, SEXP identity_) {
+    return Rcpp::List();
+}
+// [[Rcpp::export]]
+Rcpp::List getPortfolio_Impl(SEXP con_, std::vector<std::string> securities,
+                             std::string field, SEXP options_, SEXP overrides_,
+                             bool verbose, SEXP identity_) {
+    return Rcpp::List();
+}
+
+#endif
diff --git a/src/beqs.cpp b/src/beqs.cpp
index 3ba2d7d..1d878c7 100644
--- a/src/beqs.cpp
+++ b/src/beqs.cpp
@@ -1,7 +1,7 @@
 //
 //  beqs.cpp -- "Bloomberg EQS" query function for the BLP API
 //
-//  Copyright (C) 2015-2024  Whit Armstrong and Dirk Eddelbuettel and John Laing
+//  Copyright (C) 2015-2025  Whit Armstrong and Dirk Eddelbuettel and John Laing
 //
 //  This file is part of Rblpapi
 //
@@ -20,6 +20,8 @@
 
 // TODO: Date, Datetime, Int (?), ... results
 
+#if !defined(NoBlpHere)
+
 #include <vector>
 #include <string>
 #include <blpapi_session.h>
@@ -241,3 +243,19 @@ DataFrame beqs_Impl(SEXP con,
     return ans;
 
 }
+
+#else // ie if defined(NoBlpHere)
+
+#include <Rcpp/Lightest>
+// [[Rcpp::export]]
+Rcpp::DataFrame beqs_Impl(SEXP con,
+                          std::string screenName,
+                          std::string screenType,
+                          std::string group,
+                          std::string pitdate,
+                          std::string languageId,
+                          bool verbose=false) {
+    return Rcpp::DataFrame();
+}
+
+#endif
diff --git a/src/blpConnect.cpp b/src/blpConnect.cpp
index 19fb094..c9bbffb 100644
--- a/src/blpConnect.cpp
+++ b/src/blpConnect.cpp
@@ -2,9 +2,9 @@
 //
 //  blpConnect.cpp -- Function to establish Bloomberg connection
 //
-//  Copyright (C) 2013  Whit Armstrong
-//  Copyright (C) 2015  Whit Armstrong and Dirk Eddelbuettel
-//  Copyright (C) 2019  Whit Armstrong, Dirk Eddelbuettel and Alfred Kanzler
+//  Copyright (C) 2013-2025  Whit Armstrong
+//  Copyright (C) 2015-2025  Whit Armstrong and Dirk Eddelbuettel
+//  Copyright (C) 2019-2025  Whit Armstrong, Dirk Eddelbuettel and Alfred Kanzler
 //
 //  This file is part of Rblpapi
 //
@@ -21,6 +21,8 @@
 //  You should have received a copy of the GNU General Public License
 //  along with Rblpapi.  If not, see <http://www.gnu.org/licenses/>.
 
+#if !defined(NoBlpHere)
+
 #include <string>
 #include <blpapi_session.h>
 #include <Rcpp.h>
@@ -63,3 +65,13 @@ SEXP blpConnect_Impl(const std::string host, const int port, SEXP app_name_) {
 
     return createExternalPointer<Session>(sp, sessionFinalizer, "blpapi::Session*");
 }
+
+#else // ie if defined(NoBlpHere)
+
+#include <Rcpp/Lightest>
+// [[Rcpp::export]]
+SEXP blpConnect_Impl(const std::string host, const int port, SEXP app_name_) {
+    return R_NilValue;
+}
+
+#endif
diff --git a/src/blpVersion.cpp b/src/blpVersion.cpp
index 20be4d1..0f89350 100644
--- a/src/blpVersion.cpp
+++ b/src/blpVersion.cpp
@@ -2,7 +2,7 @@
 //
 //  blpVersion.cpp -- Version of the Bloomberg API
 //
-//  Copyright (C) 2016  Whit Armstrong and Dirk Eddelbuettel and John Laing
+//  Copyright (C) 2016-2025  Whit Armstrong and Dirk Eddelbuettel and John Laing
 //
 //  This file is part of Rblpapi
 //
@@ -19,6 +19,8 @@
 //  You should have received a copy of the GNU General Public License
 //  along with Rblpapi.  If not, see <http://www.gnu.org/licenses/>.
 
+#if !defined(NoBlpHere)
+
 #include <Rcpp.h>
 #include <blpapi_versioninfo.h>
 
@@ -107,3 +109,17 @@ std::string getRuntimeVersion() {
              major, minor, patch, build);
     return std::string(txt);
 }
+
+#else // ie if defined(NoBlpHere)
+
+#include <Rcpp/Lightest>
+// [[Rcpp::export]]
+std::string getHeaderVersion() {
+    return std::string();
+}
+// [[Rcpp::export]]
+std::string getRuntimeVersion() {
+    return std::string();
+}
+
+#endif
diff --git a/src/blpapi_utils.cpp b/src/blpapi_utils.cpp
index 76bbbf2..55c3623 100644
--- a/src/blpapi_utils.cpp
+++ b/src/blpapi_utils.cpp
@@ -2,7 +2,7 @@
 //  blpapi_utils -- helper functions for the BLP API
 //
 //  Copyright (C) 2013         Whit Armstrong
-//  Copyright (C) 2017 - 2024  Whit Armstrong and Dirk Eddelbuettel
+//  Copyright (C) 2017 - 2025  Whit Armstrong and Dirk Eddelbuettel
 //
 //  This file is part of Rblpapi
 //
@@ -19,6 +19,8 @@
 //  You should have received a copy of the GNU General Public License
 //  along with Rblpapi.  If not, see <http://www.gnu.org/licenses/>.
 
+#if !defined(NoBlpHere)
+
 #include <stdexcept>
 #include <string>
 #include <sstream>
@@ -446,3 +448,5 @@ Rcpp::List allocateDataFrame(size_t nrows, const vector<string>& colnames, const
   }
   return ans;
 }
+
+#endif
diff --git a/src/bsrch.cpp b/src/bsrch.cpp
index 3f051df..18cbe5a 100644
--- a/src/bsrch.cpp
+++ b/src/bsrch.cpp
@@ -1,7 +1,7 @@
 //
 //  bsrch.cpp -- "Bloomberg SRCH" query function for the BLP API
 //
-//  Copyright (C) 2015 - 2024  Whit Armstrong and Dirk Eddelbuettel and John Laing
+//  Copyright (C) 2015 - 2025  Whit Armstrong and Dirk Eddelbuettel and John Laing
 //
 //  This file is part of Rblpapi
 //
@@ -18,6 +18,8 @@
 //  You should have received a copy of the GNU General Public License
 //  along with Rblpapi.  If not, see <http://www.gnu.org/licenses/>.
 
+#if !defined(NoBlpHere)
+
 #include <vector>
 #include <string>
 #include <blpapi_session.h>
@@ -175,9 +177,9 @@ Rcpp::DataFrame processBsrchResponse(Event event, const bool verbose) {
 
 // [[Rcpp::export]]
 DataFrame bsrch_Impl(SEXP con,
-                    std::string domain,
-                    std::string limit,
-                    bool verbose=false) {
+                     std::string domain,
+                     std::string limit,
+                     bool verbose=false) {
 
     Session* session = reinterpret_cast<Session*>(checkExternalPointer(con, "blpapi::Session*"));
 
@@ -226,3 +228,16 @@ DataFrame bsrch_Impl(SEXP con,
     return ans;
 
 }
+
+#else // ie if defined(NoBlpHere)
+
+#include <Rcpp/Lightest>
+// [[Rcpp::export]]
+Rcpp::DataFrame bsrch_Impl(SEXP con,
+                           std::string domain,
+                           std::string limit,
+                           bool verbose=false) {
+    return Rcpp::DataFrame();
+}
+
+#endif
diff --git a/src/fieldsearch.cpp b/src/fieldsearch.cpp
index e7a0f95..284de9b 100644
--- a/src/fieldsearch.cpp
+++ b/src/fieldsearch.cpp
@@ -2,7 +2,7 @@
 //  fieldsearch.cpp -- a simple field search function for the BLP API
 //
 //  Copyright (C) 2013         Whit Armstrong
-//  Copyright (C) 2014 - 2024  Whit Armstrong and Dirk Eddelbuettel
+//  Copyright (C) 2014 - 2025  Whit Armstrong and Dirk Eddelbuettel
 //
 //  This file is part of Rblpapi
 //
@@ -42,6 +42,7 @@
  * IN THE SOFTWARE.
  */
 
+#if !defined(NoBlpHere)
 
 #include <blpapi_session.h>
 #include <blpapi_utils.h>
@@ -118,3 +119,13 @@ Rcpp::DataFrame fieldSearch_Impl(SEXP con, std::string searchterm) {
                                    Rcpp::Named("Mnemonic")    = fieldMnen,
                                    Rcpp::Named("Description") = fieldDesc);
 }
+
+#else // ie if defined(NoBlpHere)
+
+#include <Rcpp/Lightest>
+// [[Rcpp::export]]
+Rcpp::DataFrame fieldSearch_Impl(SEXP con, std::string searchterm) {
+    return Rcpp::DataFrame();
+}
+
+#endif
diff --git a/src/getBars.cpp b/src/getBars.cpp
index 6b772ff..c65635e 100644
--- a/src/getBars.cpp
+++ b/src/getBars.cpp
@@ -2,7 +2,7 @@
 //  getBars.cpp -- a simple intraday bar retriever
 //
 //  Copyright (C) 2013         Whit Armstrong
-//  Copyright (C) 2014 - 2024  Whit Armstrong and Dirk Eddelbuettel
+//  Copyright (C) 2014 - 2025  Whit Armstrong and Dirk Eddelbuettel
 //
 //  This file is part of Rblpapi
 //
@@ -42,6 +42,8 @@
  * IN THE SOFTWARE.
  */
 
+#if !defined(NoBlpHere)
+
 #include <blpapi_session.h>
 #include <blpapi_eventdispatcher.h>
 
@@ -224,3 +226,20 @@ Rcpp::DataFrame getBars_Impl(SEXP con,
                                    Rcpp::Named("value")     = bars.value);
 
 }
+
+#else // ie if defined(NoBlpHere)
+
+#include <Rcpp/Lightest>
+// [[Rcpp::export]]
+Rcpp::DataFrame getBars_Impl(SEXP con,
+                             std::string security,
+                             std::string eventType,
+                             int barInterval,
+                             std::string startDateTime,
+                             std::string endDateTime,
+                             Rcpp::Nullable<Rcpp::CharacterVector> options,
+                             bool verbose=false) {
+    return Rcpp::DataFrame();
+}
+
+#endif
diff --git a/src/getFieldInfo.cpp b/src/getFieldInfo.cpp
index 9cf6705..d01c67a 100644
--- a/src/getFieldInfo.cpp
+++ b/src/getFieldInfo.cpp
@@ -1,5 +1,5 @@
 ///////////////////////////////////////////////////////////////////////////
-// Copyright (C) 2016  Whit Armstrong                                    //
+// Copyright (C) 2016-2025  Whit Armstrong                                    //
 //                                                                       //
 // This program is free software: you can redistribute it and/or modify  //
 // it under the terms of the GNU General Public License as published by  //
@@ -15,6 +15,8 @@
 // along with this program.  If not, see <http://www.gnu.org/licenses/>. //
 ///////////////////////////////////////////////////////////////////////////
 
+#if !defined(NoBlpHere)
+
 #include <Rcpp.h>
 #include <blpapi_utils.h>
 
@@ -29,7 +31,7 @@ using BloombergLP::blpapi::Element;
 // [[Rcpp::export]]
 Rcpp::List fieldInfo_Impl(SEXP con_, std::vector<std::string> fields) {
 
-  Session* session = 
+  Session* session =
     reinterpret_cast<Session*>(checkExternalPointer(con_, "blpapi::Session*"));
 
   // get the field info
@@ -47,3 +49,13 @@ Rcpp::List fieldInfo_Impl(SEXP con_, std::vector<std::string> fields) {
   }
   return res;
 }
+
+#else // ie if defined(NoBlpHere)
+
+#include <Rcpp/Lightest>
+// [[Rcpp::export]]
+Rcpp::List fieldInfo_Impl(SEXP con_, std::vector<std::string> fields) {
+    return Rcpp::List();
+}
+
+#endif
diff --git a/src/getTicks.cpp b/src/getTicks.cpp
index e994bb5..21abb8c 100644
--- a/src/getTicks.cpp
+++ b/src/getTicks.cpp
@@ -2,7 +2,7 @@
 //  getTicks.cpp -- a simple intraday tick retriever
 //
 //  Copyright (C) 2013         Whit Armstrong
-//  Copyright (C) 2014 - 2024  Whit Armstrong and Dirk Eddelbuettel
+//  Copyright (C) 2014 - 2025  Whit Armstrong and Dirk Eddelbuettel
 //
 //  This file is part of Rblpapi
 //
@@ -42,6 +42,8 @@
  * IN THE SOFTWARE.
  */
 
+#if !defined(NoBlpHere)
+
 #include <vector>
 #include <string>
 #include <blpapi_session.h>
@@ -205,3 +207,19 @@ Rcpp::DataFrame getTicks_Impl(SEXP con,
     	                           Rcpp::Named("condcode") = ticks.conditionCode);
 
 }
+
+#else // ie if defined(NoBlpHere)
+
+#include <Rcpp/Lightest>
+// [[Rcpp::export]]
+Rcpp::DataFrame getTicks_Impl(SEXP con,
+                              std::string security,
+                              std::vector<std::string> eventType,
+                              std::string startDateTime,
+                              std::string endDateTime,
+                              bool setCondCodes=true,
+                              bool verbose=false) {
+    return Rcpp::DataFrame();
+}
+
+#endif
diff --git a/src/lookup.cpp b/src/lookup.cpp
index eadafd5..b0fc3fe 100644
--- a/src/lookup.cpp
+++ b/src/lookup.cpp
@@ -1,7 +1,7 @@
 //
 //  lookup.cpp -- symbol look-up
 //
-//  Copyright (C) 2017 - 2024  Dirk Eddelbuettel and Kevin Jin
+//  Copyright (C) 2017 - 2025  Dirk Eddelbuettel and Kevin Jin
 //
 //  This file is part of Rblpapi
 //
@@ -18,6 +18,8 @@
 //  You should have received a copy of the GNU General Public License
 //  along with Rblpapi.  If not, see <http://www.gnu.org/licenses/>.
 
+#if !defined(NoBlpHere)
+
 #include <blpapi_session.h>
 
 #include <blpapi_event.h>
@@ -141,3 +143,18 @@ Rcpp::DataFrame lookup_Impl(SEXP con,
     return Rcpp::DataFrame::create(Rcpp::Named("security") = matches.security,
                                    Rcpp::Named("description") = matches.description);
 }
+
+#else // ie if defined(NoBlpHere)
+
+#include <Rcpp/Lightest>
+// [[Rcpp::export]]
+Rcpp::DataFrame lookup_Impl(SEXP con,
+                            std::string query,
+                            std::string yellowKeyFilter="YK_FILTER_NONE",
+                            std::string languageOverride="LANG_OVERRIDE_NONE",
+                            int maxResults=20,
+                            bool verbose=false) {
+    return Rcpp::DataFrame();
+}
+
+#endif
diff --git a/src/subscribe.cpp b/src/subscribe.cpp
index 4275517..97863d0 100644
--- a/src/subscribe.cpp
+++ b/src/subscribe.cpp
@@ -2,7 +2,7 @@
 //
 //  subscribe.cpp -- market data subscription function for the BLP API
 //
-//  Copyright (C) 2015  Whit Armstrong
+//  Copyright (C) 2015-2025  Whit Armstrong
 //
 //  This file is part of Rblpapi
 //
@@ -19,10 +19,10 @@
 //  You should have received a copy of the GNU General Public License
 //  along with Rblpapi.  If not, see <http://www.gnu.org/licenses/>.
 
+#if !defined(NoBlpHere)
 
 // compare to SimpleSubscriptionExample.cpp
 
-
 #include <iostream>
 #include <vector>
 #include <map>
@@ -166,8 +166,8 @@ SEXP recursiveParse(const Element& e) {
 }
 
 // [[Rcpp::export]]
-SEXP subscribe_Impl(SEXP con_, std::vector<std::string> securities, std::vector<std::string> fields, Rcpp::Function fun,
-                    SEXP options_, SEXP identity_) {
+SEXP subscribe_Impl(SEXP con_, std::vector<std::string> securities, std::vector<std::string> fields,
+                    Rcpp::Function fun, SEXP options_, SEXP identity_) {
 
     // via Rcpp Attributes we get a try/catch block with error propagation to R "for free"
     Session* session =
@@ -232,3 +232,14 @@ SEXP subscribe_Impl(SEXP con_, std::vector<std::string> securities, std::vector<
     }
     return R_NilValue;
 }
+
+#else // ie if defined(NoBlpHere)
+
+#include <Rcpp/Lightest>
+// [[Rcpp::export]]
+SEXP subscribe_Impl(SEXP con_, std::vector<std::string> securities, std::vector<std::string> fields,
+                    Rcpp::Function fun, SEXP options_, SEXP identity_) {
+    return R_NilValue;
+}
+
+#endif


Reviews:
user: login: johnlaing
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-09T20:09:28Z
user: login: eddelbuettel
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-09T20:14:18Z
user: login: johnlaing
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-09T20:24:32Z
user: login: eddelbuettel
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-09T20:27:52Z
user: login: eddelbuettel
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-10T01:27:57Z
user: login: johnlaing
body: 👍 
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-10T01:31:31Z
user: login: eddelbuettel
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-10T01:32:11Z

Review comments:
diff_hunk: @@ -26,8 +26,8 @@ BBG_RPATH   = '$$ORIGIN/../blp'
 
 ## set include and linker options
 ## Bbg API files are assummed to be in the standard search path
-PKG_CPPFLAGS = -I../inst/include/ -I.
-PKG_LIBS     = -l$(BBG_LIB) -L../inst/blp -Wl,-rpath,$(BBG_RPATH)
+PKG_CPPFLAGS = -I../inst/include/ -I. @badsystem@
+PKG_LIBS     = $(BBG_LIB) -L../inst/blp -Wl,-rpath,$(BBG_RPATH)
 
 all: $(SHLIB)
-	@if command -v install_name_tool; then echo "fixing"; install_name_tool -add_rpath @loader_path/../blp Rblpapi.so; fi
+	@if command -v install_name_tool@badsystem@; then echo "fixing"; install_name_tool -add_rpath @loader_path/../blp Rblpapi.so; fi
path: src/Makevars.in
user: login: johnlaing
body: Why `@badsystem@` here? I don't follow
created_at: 2025-03-09T20:09:28Z
author_association: CONTRIBUTOR
diff_hunk: @@ -26,8 +26,8 @@ BBG_RPATH   = '$$ORIGIN/../blp'
 
 ## set include and linker options
 ## Bbg API files are assummed to be in the standard search path
-PKG_CPPFLAGS = -I../inst/include/ -I.
-PKG_LIBS     = -l$(BBG_LIB) -L../inst/blp -Wl,-rpath,$(BBG_RPATH)
+PKG_CPPFLAGS = -I../inst/include/ -I. @badsystem@
+PKG_LIBS     = $(BBG_LIB) -L../inst/blp -Wl,-rpath,$(BBG_RPATH)
 
 all: $(SHLIB)
-	@if command -v install_name_tool; then echo "fixing"; install_name_tool -add_rpath @loader_path/../blp Rblpapi.so; fi
+	@if command -v install_name_tool@badsystem@; then echo "fixing"; install_name_tool -add_rpath @loader_path/../blp Rblpapi.so; fi
path: src/Makevars.in
user: login: eddelbuettel
body: I apologize for the sneakyness :grinning: but it safes another variable.  Basically in the 'false' case it appends the `-DNoBlpHere` creating a `type -p` or `which` tests implemented more portably via `command -v` for a binary that does not exist so we skip the call of `install_name_tool` ... which would otherwise fail and break as there is no Rblpapi.so.

As the CI runs show, it works in the two 'present' cases; it also works when I tested a bad system but just moving lines 38 to 43 to the top of `configure`.  I recommend you do that to even on a system that has blp support just to run through the 'false' case.
created_at: 2025-03-09T20:14:18Z
author_association: MEMBER
diff_hunk: @@ -26,8 +26,8 @@ BBG_RPATH   = '$$ORIGIN/../blp'
 
 ## set include and linker options
 ## Bbg API files are assummed to be in the standard search path
-PKG_CPPFLAGS = -I../inst/include/ -I.
-PKG_LIBS     = -l$(BBG_LIB) -L../inst/blp -Wl,-rpath,$(BBG_RPATH)
+PKG_CPPFLAGS = -I../inst/include/ -I. @badsystem@
+PKG_LIBS     = $(BBG_LIB) -L../inst/blp -Wl,-rpath,$(BBG_RPATH)
 
 all: $(SHLIB)
-	@if command -v install_name_tool; then echo "fixing"; install_name_tool -add_rpath @loader_path/../blp Rblpapi.so; fi
+	@if command -v install_name_tool@badsystem@; then echo "fixing"; install_name_tool -add_rpath @loader_path/../blp Rblpapi.so; fi
path: src/Makevars.in
user: login: johnlaing
body: Clever, I like it. Can we maybe add an explanatory comment? I'm unlikely to remember this years from now
created_at: 2025-03-09T20:24:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -26,8 +26,8 @@ BBG_RPATH   = '$$ORIGIN/../blp'
 
 ## set include and linker options
 ## Bbg API files are assummed to be in the standard search path
-PKG_CPPFLAGS = -I../inst/include/ -I.
-PKG_LIBS     = -l$(BBG_LIB) -L../inst/blp -Wl,-rpath,$(BBG_RPATH)
+PKG_CPPFLAGS = -I../inst/include/ -I. @badsystem@
+PKG_LIBS     = $(BBG_LIB) -L../inst/blp -Wl,-rpath,$(BBG_RPATH)
 
 all: $(SHLIB)
-	@if command -v install_name_tool; then echo "fixing"; install_name_tool -add_rpath @loader_path/../blp Rblpapi.so; fi
+	@if command -v install_name_tool@badsystem@; then echo "fixing"; install_name_tool -add_rpath @loader_path/../blp Rblpapi.so; fi
path: src/Makevars.in
user: login: eddelbuettel
body: Deal. Will commit a line or two.
created_at: 2025-03-09T20:27:52Z
author_association: MEMBER
diff_hunk: @@ -30,7 +30,7 @@ PKG_CPPFLAGS = -I../inst/include/ -I. @badsystem@
 PKG_LIBS     = $(BBG_LIB) -L../inst/blp -Wl,-rpath,$(BBG_RPATH)
 
 all: $(SHLIB)
-        # we relt yn configure to replace @badsystem@ here to create a side effect
+        # we rely on configure to replace @badsystem@ here to create a side effect
path: src/Makevars.in
user: login: eddelbuettel
body: Thanks for catching that
created_at: 2025-03-10T01:27:56Z
author_association: MEMBER
diff_hunk: @@ -26,8 +26,8 @@ BBG_RPATH   = '$$ORIGIN/../blp'
 
 ## set include and linker options
 ## Bbg API files are assummed to be in the standard search path
-PKG_CPPFLAGS = -I../inst/include/ -I.
-PKG_LIBS     = -l$(BBG_LIB) -L../inst/blp -Wl,-rpath,$(BBG_RPATH)
+PKG_CPPFLAGS = -I../inst/include/ -I. @badsystem@
+PKG_LIBS     = $(BBG_LIB) -L../inst/blp -Wl,-rpath,$(BBG_RPATH)
 
 all: $(SHLIB)
-	@if command -v install_name_tool; then echo "fixing"; install_name_tool -add_rpath @loader_path/../blp Rblpapi.so; fi
+	@if command -v install_name_tool@badsystem@; then echo "fixing"; install_name_tool -add_rpath @loader_path/../blp Rblpapi.so; fi
path: src/Makevars.in
user: login: eddelbuettel
body: I think medium-term we could make src/Makevars.in clearer by having configure assign an overall variable "HAVE_BLP" in the src/Makevars and then if/else branch based on that variable.

On the other hand what we have now _works_ as I gave it chase earlier so it would take some fresh effort to rewrite ...
created_at: 2025-03-10T01:32:11Z
author_association: MEMBER

PR comments:
user: login: johnlaing
created_at: 2025-03-09T16:27:57Z
body: Conceptually this idea makes sense. Unless I am missing something, this should not break checks, right?
author_association: CONTRIBUTOR
user: login: eddelbuettel
created_at: 2025-03-09T16:30:04Z
body: It should not break, I did a silly one I am fixing now.  I was 'too hopeful' when we made the change over at the `blp` repo and osx needs another variable I commented out and now restore because we have

![image](https://github.com/user-attachments/assets/ad127551-71f8-4039-a4e2-a8ed0aa1f3c2)

I had commented out what sets 'arm' for macOS so it bonked.  (No mac here to test....)

author_association: MEMBER
user: login: eddelbuettel
created_at: 2025-03-09T16:30:49Z
body: The repair was successful at mac-builder, an arm64 mac:  
https://mac.r-project.org/macbuilder/results/1741537623-826770841091dd45/
author_association: MEMBER
user: login: eddelbuettel
created_at: 2025-03-09T16:37:20Z
body: All good now after I corrected the small oversight (and then incremented the micro release to .2 for good measure).  This will allow me to remove `Rblpapi` from the blacklist for linux-arm64 builds I do at [r2u](https://eddelbuettel.github.io/r2u). The binary will of course be non-functional, just like the amd64 builds of macOS at CRAN, but they won't give the ugly red fail sign.
author_association: MEMBER
user: login: eddelbuettel
created_at: 2025-03-10T01:33:07Z
body: And I'll rebase the other open PR which will now need a similar with/without Blp switch.  One day this week hopefully.
author_association: MEMBER
user: login: eddelbuettel
created_at: 2025-03-10T12:12:24Z
body: This 'worked' in the sense that r-universe is back having macos x86_64 binaries for us whereas before it didn't. See https://rblp.r-universe.dev/Rblpapi


author_association: MEMBER
user: login: eddelbuettel
created_at: 2025-03-10T12:51:50Z
body: And I just realized that maybe we forgot one aspect:  to skip unit tests in case of a non-blp system?  Then again we already skip tests (at CRAN and alike) as real tests require blp anyway...
author_association: MEMBER
user: login: johnlaing
created_at: 2025-03-10T14:54:03Z
body: Yeah, not worried about that. If someone ends up running tests with a non-blp system, things *should* break!
author_association: CONTRIBUTOR