# -*- mode: python -*- # This SConscript describes build and install rules for the Mongo C++ driver and associated exmaple # programs. import os Import('env has_option installSetup use_system_version_of_library') Import('nix linux darwin windows') buildShared = False if has_option("sharedclient"): buildShared = True env.Command(['mongo/base/error_codes.h', 'mongo/base/error_codes.cpp',], ['mongo/base/generate_error_codes.py', 'mongo/base/error_codes.err'], '$PYTHON $SOURCES $TARGETS') env.Command(['mongo/db/auth/action_type.h', 'mongo/db/auth/action_type.cpp'], ['mongo/db/auth/generate_action_types.py', 'mongo/db/auth/action_types.txt'], '$PYTHON $SOURCES $TARGETS') clientSourceBasic = [ 'mongo/base/error_codes.cpp', 'mongo/base/global_initializer.cpp', 'mongo/base/global_initializer_registerer.cpp', 'mongo/base/init.cpp', 'mongo/base/initializer.cpp', 'mongo/base/initializer_context.cpp', 'mongo/base/initializer_dependency_graph.cpp', 'mongo/base/make_string_vector.cpp', 'mongo/base/parse_number.cpp', 'mongo/base/status.cpp', 'mongo/base/string_data.cpp', 'mongo/bson/bson_validate.cpp', 'mongo/bson/oid.cpp', 'mongo/bson/util/bson_extract.cpp', 'mongo/buildinfo.cpp', 'mongo/client/auth_helpers.cpp', 'mongo/client/clientAndShell.cpp', 'mongo/client/clientOnly.cpp', 'mongo/client/connpool.cpp', 'mongo/client/dbclient.cpp', 'mongo/client/dbclient_rs.cpp', 'mongo/client/dbclientcursor.cpp', 'mongo/client/gridfs.cpp', 'mongo/client/sasl_client_authenticate.cpp', 'mongo/client/syncclusterconnection.cpp', 'mongo/db/jsobj.cpp', 'mongo/db/json.cpp', 'mongo/db/lasterror.cpp', 'mongo/db/dbmessage.cpp', 'mongo/logger/console.cpp', 'mongo/logger/log_manager.cpp', 'mongo/logger/log_severity.cpp', 'mongo/logger/logger.cpp', 'mongo/logger/logstream_builder.cpp', 'mongo/logger/message_event_utf8_encoder.cpp', 'mongo/logger/message_log_domain.cpp', 'mongo/logger/ramlog.cpp', 'mongo/logger/rotatable_file_manager.cpp', 'mongo/logger/rotatable_file_writer.cpp', 'mongo/pch.cpp', 'mongo/platform/backtrace.cpp', 'mongo/platform/posix_fadvise.cpp', 'mongo/platform/process_id.cpp', 'mongo/platform/random.cpp', 'mongo/util/assert_util.cpp', 'mongo/util/background.cpp', 'mongo/util/base64.cpp', 'mongo/util/concurrency/rwlockimpl.cpp', 'mongo/util/concurrency/spin_lock.cpp', 'mongo/util/concurrency/synchronization.cpp', 'mongo/util/concurrency/task.cpp', 'mongo/util/concurrency/thread_name.cpp', 'mongo/util/concurrency/thread_pool.cpp', 'mongo/util/concurrency/mutexdebugger.cpp', 'mongo/util/debug_util.cpp', 'mongo/util/stacktrace.cpp', 'mongo/util/file.cpp', 'mongo/util/file_allocator.cpp', 'mongo/util/fail_point.cpp', 'mongo/util/fail_point_registry.cpp', 'mongo/util/fail_point_service.cpp', 'mongo/util/hex.cpp', 'mongo/util/histogram.cpp', 'mongo/util/intrusive_counter.cpp', 'mongo/util/log.cpp', 'mongo/util/md5.cpp', 'mongo/util/md5main.cpp', 'mongo/util/net/httpclient.cpp', 'mongo/util/net/listen.cpp', 'mongo/util/net/message.cpp', 'mongo/util/net/message_port.cpp', 'mongo/util/net/sock.cpp', 'mongo/util/net/ssl_manager.cpp', 'mongo/util/password.cpp', 'mongo/util/processinfo.cpp', 'mongo/util/signal_handlers.cpp', 'mongo/util/stringutils.cpp', 'mongo/util/text.cpp', 'mongo/util/time_support.cpp', 'mongo/util/timer.cpp', 'mongo/util/trace.cpp', 'mongo/util/util.cpp', 'mongo/util/version.cpp', 'third_party/murmurhash3/MurmurHash3.cpp', ] clientSourceSasl = ['mongo/client/sasl_client_authenticate_impl.cpp', 'mongo/client/sasl_client_session.cpp'] clientSourceProcessInfo = [ 'mongo/util/processinfo_darwin.cpp', 'mongo/util/processinfo_freebsd.cpp', 'mongo/util/processinfo_linux2.cpp', 'mongo/util/processinfo_none.cpp', 'mongo/util/processinfo_sunos5.cpp', 'mongo/util/processinfo_win32.cpp' ] clientSourceAll = clientSourceBasic + clientSourceSasl + clientSourceProcessInfo usingSasl = env['MONGO_BUILD_SASL_CLIENT'] clientSource = list(clientSourceBasic) if usingSasl: clientSource += clientSourceSasl processInfoPlatformFile = env.File( "mongo/util/processinfo_${PYSYSPLATFORM}.cpp" ) # NOTE: See comment about similar code in src/mongo/SConscript if not os.path.exists( str( processInfoPlatformFile ) ): processInfoPlatformFile = env.File( "mongo/util/processinfo_none.cpp" ) clientSource += [processInfoPlatformFile] exampleSourceMap = [ ('authTest', 'mongo/client/examples/authTest.cpp'), ('clientTest', 'mongo/client/examples/clientTest.cpp'), ('firstExample', 'mongo/client/examples/first.cpp'), ('httpClientTest', 'mongo/client/examples/httpClientTest.cpp'), ('rsExample', 'mongo/client/examples/rs.cpp'), ('secondExample', 'mongo/client/examples/second.cpp'), ('tutorial', 'mongo/client/examples/tutorial.cpp'), ('whereExample', 'mongo/client/examples/whereExample.cpp'), ('bsondemo', 'mongo/bson/bsondemo/bsondemo.cpp'), ] clientHeaderDirectories = [ "base/", "bson/", "bson/util/", "client/", "db/", "db/auth/", "db/stats/", "db/repl/", "db/ops/", "logger/", "platform/", "s/", "scripting/", "shell/", "util/", "util/concurrency/", "util/mongoutils/", "util/net/", "" ] clientHeaders = [] for path in clientHeaderDirectories: clientHeaders.extend(Glob('mongo/%s/*.h' % path)) clientHeaders.extend(Glob('mongo/%s/*.hpp' % path)) # This relies on static and shared objects being the same, since we will link these object # files twice: once into a .a, and another time into a .so clientObjects = [env.Object(source) for source in clientSource] mongoClientLibs = [] mongoClientLibDeps = [] mongoClientSysLibDeps = [] if usingSasl: mongoClientSysLibDeps += ["sasl2"] if not use_system_version_of_library("boost"): mongoClientLibDeps.append(['$BUILD_DIR/third_party/shim_boost']) mongoClientInstalls = [] mongoClientPrefixInstalls = [] if windows and buildShared: print("Building the client driver as a DLL is not supported, see SERVER-5650") Exit(1) staticLibEnv = env.Clone() staticLibEnv.AppendUnique( LIBDEPS=mongoClientLibDeps, SYSLIBDEPS=mongoClientSysLibDeps) mongoClientStaticLib = staticLibEnv.StaticLibrary( 'mongoclient', clientObjects), mongoClientInstalls.append(staticLibEnv.Install('#/', mongoClientStaticLib)) if installSetup.libraries: mongoClientPrefixInstalls.append(env.Install("$INSTALL_DIR/lib", mongoClientStaticLib)) mongoClientSharedLib = None if buildShared: # TODO: When we are ready to set a SONAME for mongoclient, set SHLIBVERSION=x.y.z in this # environment to enable SCons versioned shared library support, and then change the two # 'Install' calls in this block to 'InstallVersionedLibrary'. SHLIBVERSION and # InstallVersionedLibrary support is only stable in SCons > 2.3.0, so if you add support # here, be sure to add an EnsuredSconsVersion here as well. sharedLibEnv = env.Clone() sharedLibEnv.AppendUnique( LIBS=mongoClientLibs + mongoClientSysLibDeps, # TODO: This currently causes the files for the libdep to get dragged into dependents # of this shared library, incorrectly. We need to patch up libdeps to treat shared # libraries as dependency terminals. LIBDEPS=mongoClientLibDeps) if linux: sharedLibEnv.AppendUnique(SHLINKFLAGS=["-Wl,--as-needed", "-Wl,-zdefs"]) mongoClientSharedLib = sharedLibEnv.SharedLibrary('mongoclient', clientObjects) mongoClientSharedLibInstall = sharedLibEnv.Install( '#/sharedclient', mongoClientSharedLib) if darwin: # Set up the copy of the client library in #/sharedclient so that things that link # against it record the local directory as the install_name. sharedLibEnv.AddPostAction( mongoClientSharedLibInstall, "install_name_tool -id @executable_path/%s %s" % ( mongoClientSharedLibInstall[0].name, mongoClientSharedLibInstall[0] )) mongoClientInstalls.append(mongoClientSharedLibInstall) if installSetup.libraries: mongoClientSharedLibPrefixInstall = sharedLibEnv.Install( '$INSTALL_DIR/lib', mongoClientSharedLib) if darwin: sharedLibEnv.AddPostAction( mongoClientSharedLibPrefixInstall, "install_name_tool -id %s %s" % ( mongoClientSharedLibPrefixInstall[0], mongoClientSharedLibPrefixInstall[0] )) mongoClientPrefixInstalls.append(mongoClientSharedLibPrefixInstall) env.Alias('mongoclient', mongoClientInstalls) if installSetup.headers: for x in clientHeaderDirectories: inst = env.Install("$INSTALL_DIR/include/mongo/" + x, [Glob('mongo/%s*.h' % x), Glob('mongo/%s*.hpp' % x)]) env.AddPostAction(inst, Chmod('$TARGET', 0644)) mongoClientPrefixInstalls.append(inst) if installSetup.headers or installSetup.libraries: env.Alias('install-mongoclient', mongoClientPrefixInstalls) clientEnv = env.Clone() clientEnv['CPPDEFINES'].remove('MONGO_EXPOSE_MACROS') # Compile the example files to .o so that we can link them twice: once statically, once shared. exampleObjMap = [(target, clientEnv.Object(source)) for (target, source) in exampleSourceMap] # Create an environment for linking the examples to the static library. For out of tree builds, # we need to use LIBS. For in-tree builds we need LIBDEPS. staticClientEnv = clientEnv.Clone() if '_LIBDEPS' in clientEnv: staticClientEnv.PrependUnique(LIBDEPS=[mongoClientStaticLib]) else: # We need the mongo client library to preceed the boost libraries. staticClientEnv.PrependUnique(LIBS=[mongoClientStaticLib]) # Build each statically linked client program staticClientPrograms = [staticClientEnv.Program(target, obj) for (target, obj) in exampleObjMap] # Install them to the root, and append the install targets to the list of client tests clientTests = staticClientEnv.Install("#/", staticClientPrograms) # Do the same for the shared library case, if we are doing that. if buildShared: sharedClientEnv = clientEnv.Clone() # Arrange for the tests to link against the mongoclient in the #/sharedclient directory. sharedClientEnv.PrependUnique( LIBS=['mongoclient'], LIBPATH=["#/sharedclient"] ) # Deal with the different lookup models between regular UNIX and Darwin. For regular unix, # we set $ORIGIN to pull the copy we run against from the current directory # (#/sharedclient). On Darwin, the staged copy of the mongoclient dylib in #sharedclient # has @executable path set as its install_name, so we pick up the same behavior that way. if nix and not darwin: sharedClientEnv.PrependUnique( LINKFLAGS="-Wl,-z,origin", RPATH=[sharedClientEnv.Literal("\\$$ORIGIN")]) sharedClientPrograms = [ sharedClientEnv.Program("sharedclient/" + target, obj) for (target, obj) in exampleObjMap] env.Depends(sharedClientPrograms, mongoClientInstalls) sharedClientProgramInstalls = sharedClientEnv.Install("#/sharedclient", sharedClientPrograms) clientTests.append(sharedClientProgramInstalls) clientEnv.Alias('clientTests', clientTests, []) env.Install( '#/', env.Command('$CLIENT_ARCHIVE', ['#buildscripts/make_archive.py', '$CLIENT_SCONSTRUCT', '$CLIENT_LICENSE', 'SConscript.client', 'mongo/base/generate_error_codes.py', 'mongo/base/error_codes.err', 'mongo/db/auth/generate_action_types.py', 'mongo/db/auth/action_types.txt', 'third_party/murmurhash3/MurmurHash3.h', '#buildscripts/make_archive.py', clientSourceAll, clientHeaders, [source for (target, source) in exampleSourceMap]], '${PYTHON} ${SOURCES[0]} -o $TARGET ' '--transform ${str(Dir(BUILD_DIR))}/client_build=$CLIENT_DIST_BASENAME/src ' '--transform ${str(Dir(BUILD_DIR))}=$CLIENT_DIST_BASENAME/src ' '--transform distsrc/client=$CLIENT_DIST_BASENAME ' '--transform =$CLIENT_DIST_BASENAME/ ' '${TEMPFILE(SOURCES[1:])}'))