Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add build time option to make PROJ_LIB env var tested last (fixes #2399) #2476

Merged
merged 1 commit into from
Feb 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,13 @@ if(ENABLE_CURL)
endif()
endif()

################################################################################

option(PROJ_LIB_ENV_VAR_TRIED_LAST "Whether the PROJ_LIB environment variable should be tried after the hardcoded location" OFF)
if(PROJ_LIB_ENV_VAR_TRIED_LAST)
add_definitions(-DPROJ_LIB_ENV_VAR_TRIED_LAST)
endif()

################################################################################
# threading configuration
################################################################################
Expand Down
13 changes: 13 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,19 @@ AC_SUBST(CURL_LIBS,$CURL_LIBS)
AC_SUBST(CURL_ENABLED_FLAGS,$CURL_ENABLED_FLAGS)
AM_CONDITIONAL(HAVE_CURL, [test "x$FOUND_CURL" = "xyes"])


dnl ---------------------------------------------------------------------------
dnl proj-lib-env-var-tried-last
dnl ---------------------------------------------------------------------------

AC_ARG_ENABLE(proj-lib-env-var-tried-last,
AS_HELP_STRING([--enable-proj-lib-env-var-tried-last],
[Whether the PROJ_LIB environment variable should be tried after the hardcoded location [default=no]]))

if test "x$enable_proj_lib_env_var_tried_last" = "xyes"; then
AC_SUBST(PROJ_LIB_ENV_VAR_TRIED_LAST_FLAGS,-DPROJ_LIB_ENV_VAR_TRIED_LAST)
fi

dnl ---------------------------------------------------------------------------
dnl Check for external Google Test
dnl ---------------------------------------------------------------------------
Expand Down
5 changes: 5 additions & 0 deletions docs/source/resource_files.rst
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ The following paths are checked in order:
that since this is a hard-wired path setting, it only works if the whole
PROJ installation is not moved somewhere else.

.. note:: if PROJ is built with the PROJ_LIB_ENV_VAR_TRIED_LAST CMake option /
--enable-proj-lib-env-var-tried-last configure switch, then this
hard-wired path will be tried before looking at the environment
variable :envvar:`PROJ_LIB`.

- The current directory

When networking capabilities are enabled, either by API with the
Expand Down
2 changes: 1 addition & 1 deletion src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ TESTS = geodtest
check_PROGRAMS = geodtest

AM_CPPFLAGS = -DPROJ_LIB=\"$(pkgdatadir)\" \
-DMUTEX_@MUTEX_SETTING@ -I$(top_srcdir)/include @SQLITE3_CFLAGS@ @TIFF_CFLAGS@ @TIFF_ENABLED_FLAGS@ @CURL_CFLAGS@ @CURL_ENABLED_FLAGS@
-DMUTEX_@MUTEX_SETTING@ -I$(top_srcdir)/include @SQLITE3_CFLAGS@ @TIFF_CFLAGS@ @TIFF_ENABLED_FLAGS@ @CURL_CFLAGS@ @CURL_ENABLED_FLAGS@ @PROJ_LIB_ENV_VAR_TRIED_LAST_FLAGS@
AM_CXXFLAGS = @CXX_WFLAGS@ @FLTO_FLAG@

include_HEADERS = proj.h proj_experimental.h proj_constants.h geodesic.h \
Expand Down
79 changes: 63 additions & 16 deletions src/filemanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1362,6 +1362,12 @@ static const char *proj_lib_name =
nullptr;
#endif

#ifdef PROJ_LIB_ENV_VAR_TRIED_LAST
static bool gbPROJ_LIB_ENV_VAR_TRIED_LAST = true;
#else
static bool gbPROJ_LIB_ENV_VAR_TRIED_LAST = false;
#endif

static bool dontReadUserWritableDirectory() {
// Env var mostly for testing purposes and being independent from
// an existing installation
Expand Down Expand Up @@ -1448,8 +1454,10 @@ static void *pj_open_lib_internal(
sysname = fname.c_str();
}

/* if is environment PROJ_LIB defined */
else if (!(projLib = NS_PROJ::FileManager::getProjLibEnvVar(ctx))
/* if the environment PROJ_LIB defined, and *not* tried as last
possibility */
else if (!gbPROJ_LIB_ENV_VAR_TRIED_LAST &&
!(projLib = NS_PROJ::FileManager::getProjLibEnvVar(ctx))
.empty()) {
auto paths = NS_PROJ::internal::split(projLib, dirSeparator);
for (const auto &path : paths) {
Expand All @@ -1461,17 +1469,42 @@ static void *pj_open_lib_internal(
if (fid)
break;
}
}

else if ((sysname = get_path_from_relative_share_proj(
ctx, name, fname)) != nullptr) {
/* check if it lives in a ../share/proj dir of the proj dll */
} else if ((sysname = get_path_from_relative_share_proj(
ctx, name, fname)) != nullptr) {
} else if (proj_lib_name != nullptr &&
(fid = open_file(
ctx,
(std::string(proj_lib_name) + DIR_CHAR + name).c_str(),
mode)) != nullptr) {

/* or hardcoded path */
} else if ((sysname = proj_lib_name) != nullptr) {
fname = sysname;
fname = proj_lib_name;
fname += DIR_CHAR;
fname += name;
sysname = fname.c_str();
}

/* if the environment PROJ_LIB defined, and tried as last possibility */
else if (gbPROJ_LIB_ENV_VAR_TRIED_LAST &&
!(projLib = NS_PROJ::FileManager::getProjLibEnvVar(ctx))
.empty()) {
auto paths = NS_PROJ::internal::split(projLib, dirSeparator);
for (const auto &path : paths) {
fname = path;
fname += DIR_CHAR;
fname += name;
sysname = fname.c_str();
fid = open_file(ctx, sysname, mode);
if (fid)
break;
}
}

else {
/* just try it bare bones */
} else {
sysname = name;
}

Expand Down Expand Up @@ -1516,21 +1549,35 @@ std::vector<std::string> pj_get_default_searchpaths(PJ_CONTEXT *ctx) {
ignoreUserWritableDirectory[0] == '\0') {
ret.push_back(proj_context_get_user_writable_directory(ctx, false));
}

const std::string envPROJ_LIB = NS_PROJ::FileManager::getProjLibEnvVar(ctx);
if (!envPROJ_LIB.empty()) {
ret.push_back(envPROJ_LIB);
}
if (envPROJ_LIB.empty()) {
const std::string relativeSharedProj = pj_get_relative_share_proj(ctx);
const std::string relativeSharedProj = pj_get_relative_share_proj(ctx);

if (gbPROJ_LIB_ENV_VAR_TRIED_LAST) {
/* Situation where PROJ_LIB environment variable is tried in last */
#ifdef PROJ_LIB
ret.push_back(PROJ_LIB);
#endif
if (!relativeSharedProj.empty()) {
ret.push_back(relativeSharedProj);
}
}
if (!envPROJ_LIB.empty()) {
ret.push_back(envPROJ_LIB);
}
} else {
/* Situation where PROJ_LIB environment variable is used if defined */
if (!envPROJ_LIB.empty()) {
ret.push_back(envPROJ_LIB);
} else {
if (!relativeSharedProj.empty()) {
ret.push_back(relativeSharedProj);
}
#ifdef PROJ_LIB
if (envPROJ_LIB.empty()) {
ret.push_back(PROJ_LIB);
}
ret.push_back(PROJ_LIB);
#endif
}
}

return ret;
}

Expand Down