Skip to content

PHPC-759: Ensure that the driver can be compiled as a built-in PHP extension #830

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

Merged
merged 10 commits into from
May 15, 2018

Conversation

jmikola
Copy link
Member

@jmikola jmikola commented May 10, 2018

[AC_MSG_ERROR([libbson requires pthreads on non-Windows platforms.])])
AX_PTHREAD([
PHP_EVAL_INCLINE([$PTHREAD_CFLAGS])
PHP_EVAL_LIBLINE([$PTHREAD_LIBS],[MONGODB_SHARED_LIBADD])
Copy link
Member Author

@jmikola jmikola May 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is still problematic for static builds, as pthread doesn't get linked to PHP. I believe this is similar to what @derickr brought up in https://github.com/mongodb/mongo-php-driver/pull/749/files#r166189048, although I'm still curious how other extensions manage to link libraries for shared/static builds in a portable manner.

@sgolemon: can you chime in?

@jmikola jmikola requested a review from derickr May 14, 2018 21:59
@jmikola jmikola changed the title [WIP] PHPC-759: Ensure that the driver can be compiled as a built-in PHP extension PHPC-759: Ensure that the driver can be compiled as a built-in PHP extension May 14, 2018
AC_MSG_RESULT(version $LIBBSON_VER found)
PHP_MONGODB_BSON_CFLAGS=`$PKG_CONFIG libbson-1.0 --cflags`
PHP_MONGODB_BSON_LIBS=`$PKG_CONFIG libbson-1.0 --libs`
PHP_MONGODB_BSON_VERSION=`$PKG_CONFIG libbson-1.0 --modversion`
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These names were changed for consistency with other CheckWhatever.m4 files and the PHP version check up top. I'm all for more "PHP_MONGODB" prefixing.

else
AC_MSG_ERROR(system libbson must be upgraded to version >= 1.9.0)
fi
else
AC_MSG_ERROR(pkgconfig and libbson must be installed)
fi
PHP_EVAL_INCLINE($LIBBSON_INC)
PHP_EVAL_LIBLINE($LIBBSON_LIB, MONGODB_SHARED_LIBADD)
PHP_MONGODB_CFLAGS="$PHP_MONGODB_CFLAGS $PHP_MONGODB_BSON_CFLAGS"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the off chance that pkg-config suggests CFLAGS that aren't just include directories, this ensures they get added. I imagine it's unlikely that libbson and the other libraries we use will do so, but I think this is the correct approach given the limitations of PHP_EVAL_INCLINE.

I do think it's OK to continue using PHP_EVAL_LIBLINE, since is less limited. We just require a single work-around for pthreads, which I mention below.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK, PHP_EVAL_INCLINE also makes sure there are no duplicates - not sure if that could be a problem here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Not important, if this is broken, people will tell us)

Copy link
Member Author

@jmikola jmikola May 15, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PHP_EVAL_INCLINE calls PHP_ADD_INCLUDE for each -I path, which calls both PHP_EXPAND_PATH (expanding to an absolute path) and PHP_RUN_ONCE to ensure each path is only added once.

Nearly all of these instances obtain CFLAGS from pkg-config being called for a unique library, so I'm comfortable trusting that their CFLAGS can be added as-is. The only overlap IMO is libmongoc and libbson. Since libmongoc's libmongoc-1.0.pc file depends on libbson-1.0, it ends up including libbson's pkg-config output in its own. To address that, I suppose we could skip merging in libbson's own pkg-config output and just rely on libmongoc. I'd propose making this change today.

One real exception is AX_PTHREAD, which is likely going to return -pthread (ignored by PHP_EVAL_INCLINE entirely) instead of an -I path. For that, I think we certainly need to just append to PHP_MONGODB_CFLAGS.

One other thought. There are more pkg-config options than I realized. Per pkg-config(1), we can request -I CFLAGS and "other" CFLAGS independently, which would let us rely on PHP_EVAL_INCLINE and defer to PHP_MONGODB_CFLAGS when necessary. Similarly, we can requires -L and -l libs independently from "other" linker arguments (which might require manual appends instead of PHP_EVAL_LIBLINE). While this is trivial to add for libbson and libmongoc, since we call pkg-config directly, we also know by looking at their package files that it would have no functional impact. It could be helpful for other libraries (e.g. CheckSSL.m4), but those are all using the pkg.m4 macro at the moment and would require some significant refactoring. I don't think there's a pressing need for this, but it does seem like it'd be the "correct" approach. If it sounds worthwhile, I can make a separate ticket to track the change and we can triage it for some future release.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't worry about it then. I'd defer making a ticket until somebody notices it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created PHPC-1190.

AC_MSG_ERROR([m4 could not include $1: No such file or directory])
fi
m4_builtin([sinclude],[$1])
m4_builtin([sinclude],[ext/mongodb/][$1])
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can assume that the extension will be build from this path, since it's the extension's name. That said, users need to manually copy/symlink in order to build statically so I suppose they could inadvertently place us under a different path. If so, the conditional a few lines up isn't going to point out that the ext/FOO path is the problem.

Let me know if you'd like a more helpful error for that case. It may be as simple as adding "ext/mongodb" to the error message, or conditionally printing a special message if $enable_static=yes.

Copy link
Contributor

@derickr derickr May 15, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should do this, as we don't want to promote compiling the driver as a static extension.

_include([scripts/build/autotools/libmongoc/Versions.m4])
_include([scripts/build/autotools/libmongoc/WeakSymbols.m4])

m4_popdef([_include])
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just cleaning up after ourselves so not to pollute the global M4 namespace. This should also be flexible in the event that some other extension (or PHP) defines an _include macro.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or also prefix it with php_mongodb_ ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently there is no risk of conflicting with an _include macro defined outside of this push/pop scope. The only risk would be if one of the M4 files we include defined its own _include macro without also using push/pop and overwrote our own.

PHP_MONGODB_ADD_SOURCES and friends can't use push/pop (reasonably) since we define them in an included file and call them later on in config.m4. Prefixing makes sense there to be a good citizen, but I don't think prefixing _include would add anything here (apart from verbosity).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK

src/libbson/src/bson/bson-version.h
src/libmongoc/src/mongoc/mongoc-config.h
src/libmongoc/src/mongoc/mongoc-version.h
${ac_config_dir}/src/libbson/src/bson/bson-config.h
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my testing, I wasn't able to use PHP_EXT_SRCDIR(mongodb) inside of AC_CONFIG_FILES, as it seems to care about its literal arguments to complain if it's invoked twice with the same parameters.

@@ -325,10 +348,17 @@ if test "$PHP_MONGODB" != "no"; then
PHP_ADD_BUILD_DIR(PHP_EXT_BUILDDIR(mongodb)[/src/MongoDB/Monitoring/])
PHP_ADD_BUILD_DIR(PHP_EXT_BUILDDIR(mongodb)[/src/contrib/])

dnl Necessary to ensure that static builds include "-pthread" when linking
if test "$ext_shared" != "yes"; then
EXTRA_LDFLAGS_PROGRAM="$EXTRA_LDFLAGS_PROGRAM $EXTRA_LDFLAGS"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I took a look at the Makefile produced when building PHP statically and found that EXTRA_LDFLAGS was ignored when making the actual SAPI binaries. I'm not sure why that is the case, but EXTRA_LDFLAGS_PROGRAM is actually included in the linking for all SAPI binaries.

We're adding $EXTRA_LDFLAGS here because that's going to be set when detecting pthreads (see my next comment in FindDependencies.m4).

@@ -325,10 +348,17 @@ if test "$PHP_MONGODB" != "no"; then
PHP_ADD_BUILD_DIR(PHP_EXT_BUILDDIR(mongodb)[/src/MongoDB/Monitoring/])
PHP_ADD_BUILD_DIR(PHP_EXT_BUILDDIR(mongodb)[/src/contrib/])

dnl Necessary to ensure that static builds include "-pthread" when linking
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you decide that --coverage is a relevant option for static builds, I can amend this comment. Otherwise, I believe this only applies to -pthread.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I said in the other PR: I don't think it's relevant.

AC_CONFIG_COMMANDS_POST([echo "
AC_CONFIG_COMMANDS_POST([
if test "$enable_static" = "no"; then
echo "
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AC_CONFIG_COMMANDS_POST emits no immediate output in the configure file and instead queues up output for the end of configure generation (after config.status). Therefore, any logic needs to go in its body.

I opted not to use $ext_shared here since this won't actually be executed anywhere near our extension's own configuration and I was worried that the logic might use the $ext_shared value from the very last extension that was configured. $enable_static seemed more reliable as it's always no for phpize shared builds and it appears to always be yes when building PHP itself.


# PTHREAD_CFLAGS may come back as "-pthread", which should also be used when
# linking. We can trust PHP_EVAL_LIBLINE to ignore other values.
PHP_EVAL_LIBLINE([$PTHREAD_CFLAGS],[MONGODB_SHARED_LIBADD])
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an odd edge case.

PHP_EVAL_LIBLINE has a special case where if it sees -pthread (instead of the usual -lfoo) and the build is static, it adds it to EXTRA_LDFLAGS instead of MONGODB_SHARED_LIBADD. For whatever reason, AX_PTHREAD's own tests doesn't determine that -pthread is required as a link flag, so it only reports it in CFLAGS. Without this, we'll get symbol errors when linking libbson object files in static builds.

Note: this goes hand in hand with our logic in config.m4 to ensure EXTRA_LDFLAGS is merged into EXTRA_LDFLAGS_PROGRAM for static builds.

dnl AX_PTHREAD
# Check for pthreads. libmongoc's original FindDependencies.m4 script did not
# require pthreads, but it does appear to be necessary on non-Windows platforms
# based on mongoc-openssl.c and mongoc-thread-private.h.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why libmongoc always considered pthreads optional, but they are certainly assumed to exist in these files. It's possible that this was an edge case and the dependency was satisfied by also linking libbson successfully.

In any event, I think this is correct and I'm not going to both libmongoc about it since the M4 file in question no longer exists in their repository.


# PTHREAD_CFLAGS may come back as "-pthread", which should also be used when
# linking. We can trust PHP_EVAL_LIBLINE to ignore other values.
PHP_EVAL_LIBLINE([$PTHREAD_CFLAGS],[MONGODB_SHARED_LIBADD])
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: PHP uses PHP_RUN_ONCE when adding -pthread, so we don't end up with duplicates from the libbson check done earlier. That said, I don't think it'd be problematic even if we did.

@jmikola
Copy link
Member Author

jmikola commented May 14, 2018

@derickr: I wasn't able to perform a static build locally with PHP 5.5 due to some token errors that appeared unrelated to our extension. Happy to discuss that tomorrow, but I'd appreciate it if you could test this locally with 5.x and 7.x anyway to ensure everything is on the up and up.

Copy link
Contributor

@derickr derickr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried a static build with PHP 5.5, and it works fine:

[GIT: PHP-5.5]
derick@singlemalt:~/dev/php/php-src.git $ ./sapi/cli/php -n -m | grep mongodb
mongodb

PHP_MONGODB_PHP_VERSION=$PHP_VERSION
PHP_MONGODB_PHP_VERSION_ID=$PHP_VERSION_ID

if test -z "$PHP_MONGODB_PHP_VERSION"; then
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How can it sometimes be set, and sometimes not?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test -z checks if the string has non-zero length. For shared builds, PHP_VERSION is never set so PHP_MONGODB_PHP_VERSION will be initialized as an empty string.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK


AC_MSG_RESULT($PHP_MONGODB_PHP_VERSION)
if test "$PHP_MONGODB_PHP_VERSION_ID" -lt "50500"; then
AC_MSG_ERROR([not supported. Need a PHP version >= 5.5.0 (found $PHP_MONGODB_PHP_VERSION)])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we currently want a check to make sure it's also lower than 7.3?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so. In the case of 7.3, we know there's a BC break for iteration that leads to a compile-time error, but jumping between earlier 7.x releases didn't require changes IIRC. I'm fine with that behavior.

Similarly, we don't limit the libbson/libmongoc shared library versions with an upper bound -- provided they satisfy 1.0 ABI. I realize they're more strict about BC than PHP, but it's also possible that behaviors of some of the internal functions we use could change inadvertently :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK

else
AC_MSG_ERROR(system libbson must be upgraded to version >= 1.9.0)
fi
else
AC_MSG_ERROR(pkgconfig and libbson must be installed)
fi
PHP_EVAL_INCLINE($LIBBSON_INC)
PHP_EVAL_LIBLINE($LIBBSON_LIB, MONGODB_SHARED_LIBADD)
PHP_MONGODB_CFLAGS="$PHP_MONGODB_CFLAGS $PHP_MONGODB_BSON_CFLAGS"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK, PHP_EVAL_INCLINE also makes sure there are no duplicates - not sure if that could be a problem here.

AC_MSG_ERROR([m4 could not include $1: No such file or directory])
fi
m4_builtin([sinclude],[$1])
m4_builtin([sinclude],[ext/mongodb/][$1])
Copy link
Contributor

@derickr derickr May 15, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should do this, as we don't want to promote compiling the driver as a static extension.

_include([scripts/build/autotools/libmongoc/Versions.m4])
_include([scripts/build/autotools/libmongoc/WeakSymbols.m4])

m4_popdef([_include])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or also prefix it with php_mongodb_ ?

@@ -325,10 +348,17 @@ if test "$PHP_MONGODB" != "no"; then
PHP_ADD_BUILD_DIR(PHP_EXT_BUILDDIR(mongodb)[/src/MongoDB/Monitoring/])
PHP_ADD_BUILD_DIR(PHP_EXT_BUILDDIR(mongodb)[/src/contrib/])

dnl Necessary to ensure that static builds include "-pthread" when linking
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I said in the other PR: I don't think it's relevant.

Copy link
Contributor

@derickr derickr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

@derickr derickr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

PHP_MONGODB_PHP_VERSION=$PHP_VERSION
PHP_MONGODB_PHP_VERSION_ID=$PHP_VERSION_ID

if test -z "$PHP_MONGODB_PHP_VERSION"; then
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK


AC_MSG_RESULT($PHP_MONGODB_PHP_VERSION)
if test "$PHP_MONGODB_PHP_VERSION_ID" -lt "50500"; then
AC_MSG_ERROR([not supported. Need a PHP version >= 5.5.0 (found $PHP_MONGODB_PHP_VERSION)])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK

_include([scripts/build/autotools/libmongoc/Versions.m4])
_include([scripts/build/autotools/libmongoc/WeakSymbols.m4])

m4_popdef([_include])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK

else
AC_MSG_ERROR(system libbson must be upgraded to version >= 1.9.0)
fi
else
AC_MSG_ERROR(pkgconfig and libbson must be installed)
fi
PHP_EVAL_INCLINE($LIBBSON_INC)
PHP_EVAL_LIBLINE($LIBBSON_LIB, MONGODB_SHARED_LIBADD)
PHP_MONGODB_CFLAGS="$PHP_MONGODB_CFLAGS $PHP_MONGODB_BSON_CFLAGS"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Not important, if this is broken, people will tell us)

Copy link
Contributor

@derickr derickr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

else
AC_MSG_ERROR(system libbson must be upgraded to version >= 1.9.0)
fi
else
AC_MSG_ERROR(pkgconfig and libbson must be installed)
fi
PHP_EVAL_INCLINE($LIBBSON_INC)
PHP_EVAL_LIBLINE($LIBBSON_LIB, MONGODB_SHARED_LIBADD)
PHP_MONGODB_CFLAGS="$PHP_MONGODB_CFLAGS $PHP_MONGODB_BSON_CFLAGS"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't worry about it then. I'd defer making a ticket until somebody notices it.

@jmikola jmikola merged commit e1827ed into mongodb:master May 15, 2018
jmikola added a commit that referenced this pull request May 15, 2018
@jmikola jmikola deleted the phpc-759 branch May 15, 2018 18:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants