Author: brane
Date: Sun Jun  8 00:17:52 2025
New Revision: 1926222

URL: http://svn.apache.org/viewvc?rev=1926222&view=rev
Log:
Make the SCons build work with SCons versions earlier than 4.7.0. Tested
with 4.4.0 and our baseline 2.3.0 (with Python 2.7.18).

* LICENSE, NOTICE: Add the SCons license, because we now reuse some
   code from SCons 4.7.0.

* SConstruct:
   Add StringIO compatibility for Python 2.7, needed for Scons 2.3.0.
   Replace Conftest.CheckFunc with our own version for SCons < 4.7.
   Add our extra check functions to every instance of Configuration.
  (CheckGnuCC): Move to the new build.scons_extras module.

* build/__init__.py: New.
* build/scons_extras.py: New.
  (CheckGnuCC): Moved here from SConstruct.
  (CheckFunc): Replacement test for older versions of SCons, copied
   essentially unchanged from SCons 4.7.0.

Added:
    serf/trunk/build/__init__.py   (with props)
    serf/trunk/build/scons_extras.py   (with props)
Modified:
    serf/trunk/LICENSE
    serf/trunk/NOTICE
    serf/trunk/SConstruct

Modified: serf/trunk/LICENSE
URL: 
http://svn.apache.org/viewvc/serf/trunk/LICENSE?rev=1926222&r1=1926221&r2=1926222&view=diff
==============================================================================
--- serf/trunk/LICENSE (original)
+++ serf/trunk/LICENSE Sun Jun  8 00:17:52 2025
@@ -200,3 +200,34 @@
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
+
+
+ADDITIONAL LICENSES:
+
+For parts of the configuration code in build/scons_extras.py:
+
+
+I. MIT License
+
+   Copyright The SCons Foundation
+   Copyright (c) 2003 Stichting NLnet Labs
+   Copyright (c) 2001, 2002, 2003 Steven Knight
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   "Software"), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+   KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+   WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+   LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+   OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+   WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Modified: serf/trunk/NOTICE
URL: 
http://svn.apache.org/viewvc/serf/trunk/NOTICE?rev=1926222&r1=1926221&r2=1926222&view=diff
==============================================================================
--- serf/trunk/NOTICE (original)
+++ serf/trunk/NOTICE Sun Jun  8 00:17:52 2025
@@ -5,3 +5,6 @@ This product includes software developed
 under Contributor License Agreements to The Apache Software Foundation
 (http://www.apache.org/).  See the revision logs for an exact contribution
 history.
+
+This product includes software developed by the SCons Foundation under the
+MIT license, see LICENSE.

Modified: serf/trunk/SConstruct
URL: 
http://svn.apache.org/viewvc/serf/trunk/SConstruct?rev=1926222&r1=1926221&r2=1926222&view=diff
==============================================================================
--- serf/trunk/SConstruct (original)
+++ serf/trunk/SConstruct Sun Jun  8 00:17:52 2025
@@ -21,25 +21,41 @@
 #
 
 import sys
-import io
 import os
 import re
 
 EnsureSConsVersion(2,3,0)
 
-# SCons 4.7 introduced the argument list parameter to CheckFunc.
-# Of course, GetSConsVersion() was added in 4.8, it's more fun that way.
-have_check_func = False
+
+# Compatibility with old versions of SCons
+try:
+  # Python 2 / SCons 2.3.0 etc.
+  from cStringIO import StringIO
+  print("warning: replaced StringIO() for Python version < 3.")
+except ImportError:
+  # Python 3
+  from io import StringIO
+
+# Set up our additional config tests.
+src_dir = File('SConstruct').rfile().get_dir().abspath
+sys.path.insert(0, src_dir)
+import build.scons_extras
+
+custom_tests = {'CheckGnuCC': build.scons_extras.CheckGnuCC}
+
+# SCons 4.7 introduced the function argument list parameter to CheckFunc.
 try:
-  if GetSConsVersion() >= (4, 7):
-    def CheckFunc(conf, name, code, lang='C', args=''):
-      return conf.CheckFunc(name, code, lang, args)
-    have_check_func = True
-except NameError:
+  import SCons.Conftest as _conftest
+  _conftest.CheckFunc(None, 'clock', '#include <time.h>', 'C', '')
+except AttributeError:
+  # This comes from the 'None' context argument, above. It's fine, we just
+  # proved that CheckFunc has the funcargs parameter, so we don't have to
+  # replace it with our own implementation.
   pass
-if not have_check_func:
-  def CheckFunc(conf, name, code, lang='C', _=''):
-    return conf.CheckFunc(name, code, lang)
+except TypeError:
+  # We have version < 4.7 without funcargs, use our replacement CheckFunc.
+  custom_tests['CheckFunc'] = build.scons_extras.CheckFunc
+  print('warning: replaced Conftest.CheckFunc() for SCons version < 4.7.')
 
 
 HEADER_FILES = ['serf.h',
@@ -292,7 +308,7 @@ if sys.platform != 'win32':
     context.Result(result)
     return result
 
-  conf = Configure(env, custom_tests = dict(CheckGnuCC=CheckGnuCC))
+  conf = Configure(env, custom_tests=custom_tests)
   have_gcc = conf.CheckGnuCC()
   env = conf.Finish()
 
@@ -440,7 +456,7 @@ if sys.platform == 'win32':
   else:
     env.Append(CPPPATH=['$OPENSSL/inc32'],
                LIBPATH=['$OPENSSL/out32dll'])
-  conf = Configure(env)
+  conf = Configure(env, custom_tests=custom_tests)
   if conf.CheckLib('libcrypto'):
     # OpenSSL 1.1.0+
     env.Append(LIBS=['libcrypto.lib', 'libssl.lib'])
@@ -523,38 +539,38 @@ else:
 
 # Check for OpenSSL functions which are only available in some of
 # the versions we support. Also handles forks like LibreSSL.
-with io.StringIO(env.File('buckets/ssl_buckets.c')
-                 .rfile().get_text_contents()) as stream:
-  ssl_include_rx = re.compile(r'^\s*#\s*include\s+<openssl/[^>]+>')
-  ssl_include_list = []
-  for line in stream.readlines():
-    if ssl_include_rx.match(line):
-      ssl_include_list.append(line.rstrip())
+ssl_include_rx = re.compile(r'^\s*#\s*include\s+<openssl/[^>]+>')
+ssl_include_list = []
+stream = StringIO(env.File('buckets/ssl_buckets.c')
+                  .rfile().get_text_contents())
+for line in stream.readlines():
+  if ssl_include_rx.match(line):
+    ssl_include_list.append(line.rstrip())
 ssl_includes = '\n'.join(ssl_include_list)
 
 
-conf = Configure(env)
-if not CheckFunc(conf, 'BIO_set_init', ssl_includes, 'C', 'NULL, 0'):
+conf = Configure(env, custom_tests=custom_tests)
+if not conf.CheckFunc('BIO_set_init', ssl_includes, 'C', 'NULL, 0'):
   env.Append(CPPDEFINES=['SERF_NO_SSL_BIO_WRAPPERS'])
-if not CheckFunc(conf, 'X509_STORE_get0_param', ssl_includes, 'C', 'NULL'):
+if not conf.CheckFunc('X509_STORE_get0_param', ssl_includes, 'C', 'NULL'):
   env.Append(CPPDEFINES=['SERF_NO_SSL_X509_STORE_WRAPPERS'])
-if not CheckFunc(conf, 'X509_get0_notBefore', ssl_includes, 'C', 'NULL'):
+if not conf.CheckFunc('X509_get0_notBefore', ssl_includes, 'C', 'NULL'):
   env.Append(CPPDEFINES=['SERF_NO_SSL_X509_GET0_NOTBEFORE'])
-if not CheckFunc(conf, 'X509_get0_notAfter', ssl_includes, 'C', 'NULL'):
+if not conf.CheckFunc('X509_get0_notAfter', ssl_includes, 'C', 'NULL'):
   env.Append(CPPDEFINES=['SERF_NO_SSL_X509_GET0_NOTAFTER'])
-if not CheckFunc(conf, 'X509_STORE_CTX_get0_chain', ssl_includes, 'C', 'NULL'):
+if not conf.CheckFunc('X509_STORE_CTX_get0_chain', ssl_includes, 'C', 'NULL'):
   env.Append(CPPDEFINES=['SERF_NO_SSL_X509_GET0_CHAIN'])
-if not CheckFunc(conf, 'ASN1_STRING_get0_data', ssl_includes, 'C', 'NULL'):
+if not conf.CheckFunc('ASN1_STRING_get0_data', ssl_includes, 'C', 'NULL'):
   env.Append(CPPDEFINES=['SERF_NO_SSL_ASN1_STRING_GET0_DATA'])
-if CheckFunc(conf, 'CRYPTO_set_locking_callback', ssl_includes, 'C', 'NULL'):
+if conf.CheckFunc('CRYPTO_set_locking_callback', ssl_includes, 'C', 'NULL'):
   env.Append(CPPDEFINES=['SERF_HAVE_SSL_LOCKING_CALLBACKS'])
-if CheckFunc(conf, 'OPENSSL_malloc_init', ssl_includes):
+if conf.CheckFunc('OPENSSL_malloc_init', ssl_includes):
   env.Append(CPPDEFINES=['SERF_HAVE_OPENSSL_MALLOC_INIT'])
-if CheckFunc(conf, 'SSL_library_init', ssl_includes):
+if conf.CheckFunc('SSL_library_init', ssl_includes):
   env.Append(CPPDEFINES=['SERF_HAVE_OPENSSL_SSL_LIBRARY_INIT'])
-if CheckFunc(conf, 'OpenSSL_version_num', ssl_includes):
+if conf.CheckFunc('OpenSSL_version_num', ssl_includes):
   env.Append(CPPDEFINES=['SERF_HAVE_OPENSSL_VERSION_NUM'])
-if CheckFunc(conf, 'SSL_set_alpn_protos', ssl_includes, 'C', 'NULL, NULL, 0'):
+if conf.CheckFunc('SSL_set_alpn_protos', ssl_includes, 'C', 'NULL, NULL, 0'):
   env.Append(CPPDEFINES=['SERF_HAVE_OPENSSL_ALPN'])
 if conf.CheckType('OSSL_HANDSHAKE_STATE', ssl_includes):
   env.Append(CPPDEFINES=['SERF_HAVE_OSSL_HANDSHAKE_STATE'])
@@ -572,11 +588,11 @@ if sys.platform == 'win32':
   env.Append(CPPDEFINES=['SERF_HAVE_SSPI'])
 
 if brotli and CALLOUT_OKAY:
-  conf = Configure(env)
+  conf = Configure(env, custom_tests=custom_tests)
   if conf.CheckCHeader('brotli/decode.h') and \
-     CheckFunc(conf, 'BrotliDecoderTakeOutput',
-               '#include <brotli/decode.h>',
-               'C', 'NULL, NULL'):
+     conf.CheckFunc('BrotliDecoderTakeOutput',
+                    '#include <brotli/decode.h>',
+                    'C', 'NULL, NULL'):
     env.Append(CPPDEFINES=['SERF_HAVE_BROTLI'])
   else:
     print("Cannot find Brotli library >= 1.0.0 in '%s'." % env.get('BROTLI'))
@@ -610,7 +626,7 @@ pkgconfig = env.Textfile('serf-%d.pc' %
 env.Default(lib_static, lib_shared, pkgconfig)
 
 if CALLOUT_OKAY:
-  conf = Configure(env)
+  conf = Configure(env, custom_tests=custom_tests)
 
   ### some configuration stuffs
   if conf.CheckCHeader('stdbool.h'):
@@ -672,7 +688,6 @@ else:
 
 check_script = env.File('build/check.py').rstr()
 test_dir = env.File('test/test_all.c').rfile().get_dir()
-src_dir = env.File('serf.h').rfile().get_dir()
 test_app = ("%s %s %s %s") % (sys.executable, check_script, test_dir, 'test')
 
 # Set the library search path for the test programs

Added: serf/trunk/build/__init__.py
URL: 
http://svn.apache.org/viewvc/serf/trunk/build/__init__.py?rev=1926222&view=auto
==============================================================================
    (empty)

Propchange: serf/trunk/build/__init__.py
------------------------------------------------------------------------------
    svn:eol-style = native

Added: serf/trunk/build/scons_extras.py
URL: 
http://svn.apache.org/viewvc/serf/trunk/build/scons_extras.py?rev=1926222&view=auto
==============================================================================
--- serf/trunk/build/scons_extras.py (added)
+++ serf/trunk/build/scons_extras.py Sun Jun  8 00:17:52 2025
@@ -0,0 +1,123 @@
+#!/usr/bin/env python
+#
+# scons_extras.py :  SCons extensions and compatibility functinos.
+#
+# ===================================================================
+#   Licensed to the Apache Software Foundation (ASF) under one
+#   or more contributor license agreements.  See the NOTICE file
+#   distributed with this work for additional information
+#   regarding copyright ownership.  The ASF licenses this file
+#   to you under the Apache License, Version 2.0 (the
+#   "License"); you may not use this file except in compliance
+#   with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing,
+#   software distributed under the License is distributed on an
+#   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#   KIND, either express or implied.  See the License for the
+#   specific language governing permissions and limitations
+#   under the License.
+# ===================================================================
+
+
+def CheckGnuCC(context):
+  '''Check if the compiler is compatible with gcc.'''
+
+  src = '''
+#ifndef __GNUC__
+oh noes!
+#endif
+'''
+
+  context.Display('Checking for GNU-compatible C compiler... ')
+  result = context.TryCompile(src, '.c')
+  context.Result(result)
+  return result
+
+
+#
+# The following code is derived from SCons, version 4.7.0.
+#
+# ===================================================================
+#
+# MIT License
+#
+# Copyright The SCons Foundation
+# Copyright (c) 2003 Stichting NLnet Labs
+# Copyright (c) 2001, 2002, 2003 Steven Knight
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+# ===================================================================
+
+
+from SCons.Conftest import _YesNoResult, _lang2suffix
+
+
+def CheckFunc(context, function_name, header=None, language=None, funcargs=''):
+  if context.headerfilename:
+    includetext = '#include "%s"' % context.headerfilename
+  else:
+    includetext = ''
+  if not header:
+    header = '''
+#ifdef __cplusplus
+extern "C"
+#endif
+char %s(void);''' % function_name
+
+  lang, suffix, msg = _lang2suffix(language)
+  if msg:
+    context.Display('Cannot check for %s(): %s\\n' % (function_name, msg))
+    return msg
+
+  text = '''
+%(include)s
+#include <assert.h>
+%(hdr)s
+
+#if _MSC_VER && !__INTEL_COMPILER
+  #pragma function(%(name)s)
+#endif
+
+int main(void) {
+#if defined (__stub_%(name)s) || defined (__stub___%(name)s)
+  #error "%(name)s has a GNU stub, cannot check"
+#else
+  %(name)s(%(args)s);
+#endif
+
+  return 0;
+}
+''' % { 'name': function_name,
+        'include': includetext,
+        'hdr': header,
+        'args': funcargs }
+
+  context.Display('Checking for %s function %s()... ' % (lang, function_name))
+  ret = context.BuildProg(text, suffix)
+  comment = "Define to 1 if the system has the function `%s'." % function_name
+  _YesNoResult(context, ret, 'HAVE_' + function_name, text, comment)
+
+  # This is different than in SCons.Conftest -- it's how SCons.SConf
+  # tweaks the result int its wrappers.
+  context.did_show_result = 1
+  return not ret

Propchange: serf/trunk/build/scons_extras.py
------------------------------------------------------------------------------
    svn:eol-style = native


Reply via email to