def __init__(self, name, project, sources, requirements, default_build, usage_requirements): AliasTarget.__init__(self, name, project, sources, requirements, default_build, usage_requirements) # On Linux, we build release variant by default, since few users will # ever want to debug C++ Boost libraries, and there's no ABI # incompatibility between debug and release variants. We build # shared and static libraries since that's what most packages # seem to provide (.so in libfoo and .a in libfoo-dev). self.minimal_properties = property_set.create([ "<variant>release", "<threading>multi", "<link>shared", "<link>static", "<runtime-link>shared"]) # On Windows, new IDE projects use: # # runtime-link=dynamic, threading=multi, variant=(debug|release) # # and in addition, C++ Boost's autolink defaults to static linking. self.minimal_properties_win = property_set.create([ "<variant>debug", "<variant>release", "<threading>multi", "<link>static", "<runtime-link>shared"]) self.complete_properties = property_set.create([ "<variant>debug", "<variant>release", "<threading>single", "<threading>multi" "<link>shared", "<link>static", "<runtime-link>shared", "<runtime-link>static"])
def __init__(self, name, project, sources, requirements, default_build, usage_requirements): AliasTarget.__init__(self, name, project, sources, requirements, default_build, usage_requirements) # On Linux, we build release variant by default, since few users will # ever want to debug C++ Boost libraries, and there's no ABI # incompatibility between debug and release variants. We build # shared and static libraries since that's what most packages # seem to provide (.so in libfoo and .a in libfoo-dev). self.minimal_properties = property_set.create([ "<variant>release", "<threading>multi", "<link>shared", "<link>static", "<runtime-link>shared" ]) # On Windows, new IDE projects use: # # runtime-link=dynamic, threading=multi, variant=(debug|release) # # and in addition, C++ Boost's autolink defaults to static linking. self.minimal_properties_win = property_set.create([ "<variant>debug", "<variant>release", "<threading>multi", "<link>static", "<runtime-link>shared" ]) self.complete_properties = property_set.create([ "<variant>debug", "<variant>release", "<threading>single", "<threading>multi" "<link>shared", "<link>static", "<runtime-link>shared", "<runtime-link>static" ])
def set(self, attribute, specification, exact): """Set the named attribute from the specification given by the user. The value actually set may be different.""" if exact: self.__dict__[attribute] = specification elif attribute == "requirements": self.requirements = property_set.refine_from_user_input( self.requirements, specification, self.project_module, self.location) elif attribute == "usage-requirements": unconditional = [] for p in specification: split = property.split_conditional(p) if split: unconditional.append(split[1]) else: unconditional.append(p) non_free = property.remove("free", unconditional) if non_free: pass # FIXME: #errors.error "usage-requirements" $(specification) "have non-free properties" $(non-free) ; t = property.translate_paths(specification, self.location) existing = self.__dict__.get("usage-requirements") if existing: new = property_set.create(existing.raw() + t) else: new = property_set.create(t) self.__dict__["usage-requirements"] = new elif attribute == "default-build": self.__dict__["default-build"] = property_set.create(specification) elif attribute == "source-location": source_location = [] for path in specification: source_location += os.path.join(self.location, path) self.__dict__["source-location"] = source_location elif attribute == "build-dir": self.__dict__["build-dir"] = os.path.join(self.location, specification) elif not attribute in [ "id", "default-build", "location", "source-location", "parent", "projects-to-build", "project-root" ]: self.manager.errors()("""Invalid project attribute '%s' specified for project at '%s'""" % (attribute, self.location)) else: self.__dict__[attribute] = specification
def set(self, attribute, specification, exact): """Set the named attribute from the specification given by the user. The value actually set may be different.""" if exact: self.__dict__[attribute] = specification elif attribute == "requirements": self.requirements = property_set.refine_from_user_input( self.requirements, specification, self.project_module, self.location) elif attribute == "usage-requirements": unconditional = [] for p in specification: split = property.split_conditional(p) if split: unconditional.append(split[1]) else: unconditional.append(p) non_free = property.remove("free", unconditional) if non_free: pass # FIXME: #errors.error "usage-requirements" $(specification) "have non-free properties" $(non-free) ; t = property.translate_paths(specification, self.location) existing = self.__dict__.get("usage-requirements") if existing: new = property_set.create(existing.raw() + t) else: new = property_set.create(t) self.__dict__["usage-requirements"] = new elif attribute == "default-build": self.__dict__["default-build"] = property_set.create(specification) elif attribute == "source-location": source_location = [] for path in specification: source_location += os.path.join(self.location, path) self.__dict__["source-location"] = source_location elif attribute == "build-dir": self.__dict__["build-dir"] = os.path.join(self.location, specification) elif not attribute in ["id", "default-build", "location", "source-location", "parent", "projects-to-build", "project-root"]: self.manager.errors()( """Invalid project attribute '%s' specified for project at '%s'""" % (attribute, self.location)) else: self.__dict__[attribute] = specification
def extra_usage_requirements(self, created_targets, prop_set): result = property_set.empty() extra = [] # Add appropriate <xdll-path> usage requirements. raw = prop_set.raw() if '<link>shared' in raw: paths = [] # TODO: is it safe to use the current directory? I think we should use # another mechanism to allow this to be run from anywhere. pwd = os.getcwd() for t in created_targets: if type.is_derived(t.type(), 'SHARED_LIB'): paths.append(path.root(path.make(t.path()), pwd)) extra += replace_grist(paths, '<xdll-path>') # We need to pass <xdll-path> features that we've got from sources, # because if shared library is built, exe which uses it must know paths # to other shared libraries this one depends on, to be able to find them # all at runtime. # Just pass all features in property_set, it's theorically possible # that we'll propagate <xdll-path> features explicitly specified by # the user, but then the user's to blaim for using internal feature. values = prop_set.get('<xdll-path>') extra += replace_grist(values, '<xdll-path>') if extra: result = property_set.create(extra) return result
def run_pch(self, project, name, prop_set, sources): # Find the header in sources. Ignore any CPP sources. header = None for s in sources: if type.is_derived(s.type(), 'H'): header = s # Error handling: Base header file name should be the same as the base # precompiled header name. header_name = header.name() header_basename = os.path.basename(header_name).rsplit('.', 1)[0] if header_basename != name: location = project.project_module ###FIXME: raise Exception() ### errors.user-error "in" $(location)": pch target name `"$(name)"' should be the same as the base name of header file `"$(header-name)"'" ; pch_file = Generator.run(self, project, name, prop_set, [header]) # return result of base class and pch-file property as usage-requirements # FIXME: what about multiple results from generator.run? return (property_set.create([ Property('pch-file', pch_file[0]), Property('cflags', '-Winvalid-pch') ]), pch_file)
def convert_command_line_element(e): result = None parts = e.split("/") for p in parts: m = p.split("=") if len(m) > 1: feature = m[0] values = m[1].split(",") lresult = [("<%s>%s" % (feature, v)) for v in values] else: lresult = p.split(",") if p.find('-') == -1: # FIXME: first port property.validate # property.validate cannot handle subfeatures, # so we avoid the check here. #for p in lresult: # property.validate(p) pass if not result: result = lresult else: result = [e1 + "/" + e2 for e1 in result for e2 in lresult] return [property_set.create(b2.build.feature.split(r)) for r in result]
def convert_command_line_element(e): assert isinstance(e, basestring) result = None parts = e.split("/") for p in parts: m = p.split("=") if len(m) > 1: feature = m[0] values = m[1].split(",") lresult = [("<%s>%s" % (feature, v)) for v in values] else: lresult = p.split(",") if p.find('-') == -1: # FIXME: first port property.validate # property.validate cannot handle subfeatures, # so we avoid the check here. #for p in lresult: # property.validate(p) pass if not result: result = lresult else: result = [e1 + "/" + e2 for e1 in result for e2 in lresult] return [property_set.create(b2.build.feature.split(r)) for r in result]
def run(self, project, name, prop_set, sources): if not name: return None # If name is empty, it means we're called not from top-level. # In this case, we just fail immediately, because SearchedLibGenerator # cannot be used to produce intermediate targets. properties = prop_set.raw () shared = '<link>shared' in properties a = virtual_target.NullAction (project.manager(), prop_set) real_name = feature.get_values ('<name>', properties) if real_name: real_name = real_name[0] else: real_name = name search = feature.get_values('<search>', properties) usage_requirements = property_set.create(['<xdll-path>' + p for p in search]) t = SearchedLibTarget(real_name, project, shared, search, a) # We return sources for a simple reason. If there's # lib png : z : <name>png ; # the 'z' target should be returned, so that apps linking to # 'png' will link to 'z', too. return(usage_requirements, [b2.manager.get_manager().virtual_targets().register(t)] + sources)
def generated_targets (self, sources, prop_set, project, name): # sources to pass to inherited rule sources2 = [] # properties to pass to inherited rule properties2 = [] # sources which are libraries libraries = [] # Searched libraries are not passed as argument to linker # but via some option. So, we pass them to the action # via property. properties2 = prop_set.raw() fsa = [] fst = [] for s in sources: if type.is_derived(s.type(), 'SEARCHED_LIB'): name = s.real_name() if s.shared(): fsa.append(name) else: fst.append(name) else: sources2.append(s) if fsa: properties2 += [replace_grist('&&'.join(fsa), '<find-shared-library>')] if fst: properties2 += [replace_grist('&&'.join(fst), '<find-static-library>')] spawn = generators.Generator.generated_targets(self, sources2, property_set.create(properties2), project, name) return spawn
def run(self, project, name, prop_set, sources): if not name: return None # If name is empty, it means we're called not from top-level. # In this case, we just fail immediately, because SearchedLibGenerator # cannot be used to produce intermediate targets. properties = prop_set.raw() shared = '<link>shared' in properties a = virtual_target.NullAction(project.manager(), prop_set) real_name = feature.get_values('<name>', properties) if real_name: real_name = real_name[0] else: real_nake = name search = feature.get_values('<search>', properties) usage_requirements = property_set.create( ['<xdll-path>' + p for p in search]) t = SearchedLibTarget(name, project, shared, real_name, search, a) # We return sources for a simple reason. If there's # lib png : z : <name>png ; # the 'z' target should be returned, so that apps linking to # 'png' will link to 'z', too. return (usage_requirements, [b2.manager.get_manager().virtual_targets().register(t)] + sources)
def extra_usage_requirements (self, created_targets, prop_set): result = property_set.empty () extra = [] # Add appropriate <xdll-path> usage requirements. raw = prop_set.raw () if '<link>shared' in raw: paths = [] # TODO: is it safe to use the current directory? I think we should use # another mechanism to allow this to be run from anywhere. pwd = os.getcwd() for t in created_targets: if type.is_derived(t.type(), 'SHARED_LIB'): paths.append(path.root(path.make(t.path()), pwd)) extra += replace_grist(paths, '<xdll-path>') # We need to pass <xdll-path> features that we've got from sources, # because if shared library is built, exe which uses it must know paths # to other shared libraries this one depends on, to be able to find them # all at runtime. # Just pass all features in property_set, it's theorically possible # that we'll propagate <xdll-path> features explicitly specified by # the user, but then the user's to blaim for using internal feature. values = prop_set.get('<xdll-path>') extra += replace_grist(values, '<xdll-path>') if extra: result = property_set.create(extra) return result
def run(self, project, name, prop_set, sources): assert isinstance(project, targets.ProjectTarget) assert isinstance(name, basestring) or name is None assert isinstance(prop_set, property_set.PropertySet) assert is_iterable_typed(sources, virtual_target.VirtualTarget) # create a copy since sources is being modified sources = list(sources) sources.extend(prop_set.get('<library>')) # Add <library-path> properties for all searched libraries extra = [] for s in sources: if s.type() == 'SEARCHED_LIB': search = s.search() extra.extend( property.Property('<library-path>', sp) for sp in search) # It's possible that we have libraries in sources which did not came # from 'lib' target. For example, libraries which are specified # just as filenames as sources. We don't have xdll-path properties # for such target, but still need to add proper dll-path properties. extra_xdll_path = [] for s in sources: if type.is_derived(s.type(), 'SHARED_LIB') and not s.action(): # Unfortunately, we don't have a good way to find the path # to a file, so use this nasty approach. p = s.project() location = path.root(s.name(), p.get('source-location')[0]) extra_xdll_path.append(os.path.dirname(location)) # Hardcode DLL paths only when linking executables. # Pros: do not need to relink libraries when installing. # Cons: "standalone" libraries (plugins, python extensions) can not # hardcode paths to dependent libraries. if prop_set.get('<hardcode-dll-paths>') == ['true'] \ and type.is_derived(self.target_types_ [0], 'EXE'): xdll_path = prop_set.get('<xdll-path>') extra.extend(property.Property('<dll-path>', sp) \ for sp in extra_xdll_path) extra.extend(property.Property('<dll-path>', sp) \ for sp in xdll_path) if extra: prop_set = prop_set.add_raw(extra) result = generators.Generator.run(self, project, name, prop_set, sources) if result: ur = self.extra_usage_requirements(result, prop_set) ur = ur.add( property_set.create( ['<xdll-path>' + p for p in extra_xdll_path])) else: return None return (ur, result)
def expand_no_defaults (property_sets): """ Expand the given build request by combining all property_sets which don't specify conflicting non-free features. """ # First make all features and subfeatures explicit expanded_property_sets = [ps.expand_subfeatures() for ps in property_sets] # Now combine all of the expanded property_sets product = __x_product (expanded_property_sets) return [property_set.create(p) for p in product]
def boost_std(inc=None, lib=None): # The default definitions for pre-built libraries. rules.project(['boost'], ['usage-requirements'] + ['<include>{}'.format(i) for i in inc] + ['<define>BOOST_ALL_NO_LIB'], ['requirements'] + ['<search>{}'.format(l) for l in lib]) # TODO: There should be a better way to add a Python function into a # project requirements property set. tag_prop_set = property_set.create([property.Property('<tag>', tag_std)]) attributes = projects.attributes(projects.current().project_module()) attributes.requirements = attributes.requirements.refine(tag_prop_set) alias('headers') def boost_lib(lib_name, dyn_link_macro): if (isinstance(lib_name, str)): lib_name = [lib_name] builtin.lib(lib_name, usage_requirements=[ '<link>shared:<define>{}'.format(dyn_link_macro) ]) boost_lib('container', 'BOOST_CONTAINER_DYN_LINK') boost_lib('date_time', 'BOOST_DATE_TIME_DYN_LINK') boost_lib('filesystem', 'BOOST_FILE_SYSTEM_DYN_LINK') boost_lib('graph', 'BOOST_GRAPH_DYN_LINK') boost_lib('graph_parallel', 'BOOST_GRAPH_DYN_LINK') boost_lib('iostreams', 'BOOST_IOSTREAMS_DYN_LINK') boost_lib('locale', 'BOOST_LOG_DYN_LINK') boost_lib('log', 'BOOST_LOG_DYN_LINK') boost_lib('log_setup', 'BOOST_LOG_DYN_LINK') boost_lib('math_tr1', 'BOOST_MATH_TR1_DYN_LINK') boost_lib('math_tr1f', 'BOOST_MATH_TR1_DYN_LINK') boost_lib('math_tr1l', 'BOOST_MATH_TR1_DYN_LINK') boost_lib('math_c99', 'BOOST_MATH_TR1_DYN_LINK') boost_lib('math_c99f', 'BOOST_MATH_TR1_DYN_LINK') boost_lib('math_c99l', 'BOOST_MATH_TR1_DYN_LINK') boost_lib('mpi', 'BOOST_MPI_DYN_LINK') boost_lib('program_options', 'BOOST_PROGRAM_OPTIONS_DYN_LINK') boost_lib('python', 'BOOST_PYTHON_DYN_LINK') boost_lib('python3', 'BOOST_PYTHON_DYN_LINK') boost_lib('random', 'BOOST_RANDOM_DYN_LINK') boost_lib('regex', 'BOOST_REGEX_DYN_LINK') boost_lib('serialization', 'BOOST_SERIALIZATION_DYN_LINK') boost_lib('wserialization', 'BOOST_SERIALIZATION_DYN_LINK') boost_lib('signals', 'BOOST_SIGNALS_DYN_LINK') boost_lib('system', 'BOOST_SYSTEM_DYN_LINK') boost_lib('unit_test_framework', 'BOOST_TEST_DYN_LINK') boost_lib('prg_exec_monitor', 'BOOST_TEST_DYN_LINK') boost_lib('test_exec_monitor', 'BOOST_TEST_DYN_LINK') boost_lib('thread', 'BOOST_THREAD_DYN_DLL') boost_lib('wave', 'BOOST_WAVE_DYN_LINK')
def run (self, project, name, prop_set, sources): assert isinstance(project, targets.ProjectTarget) assert isinstance(name, basestring) or name is None assert isinstance(prop_set, property_set.PropertySet) assert is_iterable_typed(sources, virtual_target.VirtualTarget) # create a copy since sources is being modified sources = list(sources) sources.extend(prop_set.get('<library>')) # Add <library-path> properties for all searched libraries extra = [] for s in sources: if s.type () == 'SEARCHED_LIB': search = s.search() extra.extend(property.Property('<library-path>', sp) for sp in search) # It's possible that we have libraries in sources which did not came # from 'lib' target. For example, libraries which are specified # just as filenames as sources. We don't have xdll-path properties # for such target, but still need to add proper dll-path properties. extra_xdll_path = [] for s in sources: if type.is_derived (s.type (), 'SHARED_LIB') and not s.action (): # Unfortunately, we don't have a good way to find the path # to a file, so use this nasty approach. p = s.project() location = path.root(s.name(), p.get('source-location')[0]) extra_xdll_path.append(os.path.dirname(location)) # Hardcode DLL paths only when linking executables. # Pros: do not need to relink libraries when installing. # Cons: "standalone" libraries (plugins, python extensions) can not # hardcode paths to dependent libraries. if prop_set.get('<hardcode-dll-paths>') == ['true'] \ and type.is_derived(self.target_types_ [0], 'EXE'): xdll_path = prop_set.get('<xdll-path>') extra.extend(property.Property('<dll-path>', sp) \ for sp in extra_xdll_path) extra.extend(property.Property('<dll-path>', sp) \ for sp in xdll_path) if extra: prop_set = prop_set.add_raw (extra) result = generators.Generator.run(self, project, name, prop_set, sources) if result: ur = self.extra_usage_requirements(result, prop_set) ur = ur.add(property_set.create(['<xdll-path>' + p for p in extra_xdll_path])) else: return None return (ur, result)
def adjust_properties(self, target, build_ps): a = target.action() properties = [] if a: ps = a.properties() properties = ps.all() # Unless <hardcode-dll-paths>true is in properties, which can happen # only if the user has explicitly requested it, nuke all <dll-path> # properties. if build_ps.get('hardcode-dll-paths') != ['true']: properties = [ p for p in properties if p.feature().name() != 'dll-path' ] # If any <dll-path> properties were specified for installing, add # them. properties.extend(build_ps.get_properties('dll-path')) # Also copy <linkflags> feature from current build set, to be used # for relinking. properties.extend(build_ps.get_properties('linkflags')) # Remove the <tag> feature on original targets. # And <location>. If stage target has another stage target in # sources, then we shall get virtual targets with the <location> # property set. properties = [ p for p in properties if not p.feature().name() in ['tag', 'location'] ] properties.extend(build_ps.get_properties('dependency')) properties.extend(build_ps.get_properties('location')) properties.extend( build_ps.get_properties('install-no-version-symlinks')) d = build_ps.get_properties('install-source-root') # Make the path absolute: we shall use it to compute relative paths and # making the path absolute will help. if d: p = d[0] properties.append( property.Property(p.feature(), os.path.abspath(p.value()))) return property_set.create(properties)
def boost_std(inc = None, lib = None): # The default definitions for pre-built libraries. rules.project( ['boost'], ['usage-requirements'] + ['<include>{}'.format(i) for i in inc] + ['<define>BOOST_ALL_NO_LIB'], ['requirements'] + ['<search>{}'.format(l) for l in lib]) # TODO: There should be a better way to add a Python function into a # project requirements property set. tag_prop_set = property_set.create([property.Property('<tag>', tag_std)]) attributes = projects.attributes(projects.current().project_module()) attributes.requirements = attributes.requirements.refine(tag_prop_set) alias('headers') def boost_lib(lib_name, dyn_link_macro): if (isinstance(lib_name,str)): lib_name = [lib_name] builtin.lib(lib_name, usage_requirements=['<link>shared:<define>{}'.format(dyn_link_macro)]) boost_lib('container' , 'BOOST_CONTAINER_DYN_LINK' ) boost_lib('date_time' , 'BOOST_DATE_TIME_DYN_LINK' ) boost_lib('filesystem' , 'BOOST_FILE_SYSTEM_DYN_LINK' ) boost_lib('graph' , 'BOOST_GRAPH_DYN_LINK' ) boost_lib('graph_parallel' , 'BOOST_GRAPH_DYN_LINK' ) boost_lib('iostreams' , 'BOOST_IOSTREAMS_DYN_LINK' ) boost_lib('locale' , 'BOOST_LOG_DYN_LINK' ) boost_lib('log' , 'BOOST_LOG_DYN_LINK' ) boost_lib('log_setup' , 'BOOST_LOG_DYN_LINK' ) boost_lib('math_tr1' , 'BOOST_MATH_TR1_DYN_LINK' ) boost_lib('math_tr1f' , 'BOOST_MATH_TR1_DYN_LINK' ) boost_lib('math_tr1l' , 'BOOST_MATH_TR1_DYN_LINK' ) boost_lib('math_c99' , 'BOOST_MATH_TR1_DYN_LINK' ) boost_lib('math_c99f' , 'BOOST_MATH_TR1_DYN_LINK' ) boost_lib('math_c99l' , 'BOOST_MATH_TR1_DYN_LINK' ) boost_lib('mpi' , 'BOOST_MPI_DYN_LINK' ) boost_lib('program_options' , 'BOOST_PROGRAM_OPTIONS_DYN_LINK') boost_lib('python' , 'BOOST_PYTHON_DYN_LINK' ) boost_lib('python3' , 'BOOST_PYTHON_DYN_LINK' ) boost_lib('random' , 'BOOST_RANDOM_DYN_LINK' ) boost_lib('regex' , 'BOOST_REGEX_DYN_LINK' ) boost_lib('serialization' , 'BOOST_SERIALIZATION_DYN_LINK' ) boost_lib('wserialization' , 'BOOST_SERIALIZATION_DYN_LINK' ) boost_lib('signals' , 'BOOST_SIGNALS_DYN_LINK' ) boost_lib('system' , 'BOOST_SYSTEM_DYN_LINK' ) boost_lib('unit_test_framework' , 'BOOST_TEST_DYN_LINK' ) boost_lib('prg_exec_monitor' , 'BOOST_TEST_DYN_LINK' ) boost_lib('test_exec_monitor' , 'BOOST_TEST_DYN_LINK' ) boost_lib('thread' , 'BOOST_THREAD_DYN_DLL' ) boost_lib('wave' , 'BOOST_WAVE_DYN_LINK' )
def boost_std(inc=None, lib=None): # The default definitions for pre-built libraries. rules.project( ["boost"], ["usage-requirements"] + ["<include>{}".format(i) for i in inc] + ["<define>BOOST_ALL_NO_LIB"], ["requirements"] + ["<search>{}".format(l) for l in lib], ) # TODO: There should be a better way to add a Python function into a # project requirements property set. tag_prop_set = property_set.create([property.Property("<tag>", tag_std)]) attributes = projects.attributes(projects.current().project_module()) attributes.requirements = attributes.requirements.refine(tag_prop_set) alias("headers") def boost_lib(lib_name, dyn_link_macro): if isinstance(lib_name, str): lib_name = [lib_name] builtin.lib(lib_name, usage_requirements=["<link>shared:<define>{}".format(dyn_link_macro)]) boost_lib("date_time", "BOOST_DATE_TIME_DYN_LINK") boost_lib("filesystem", "BOOST_FILE_SYSTEM_DYN_LINK") boost_lib("graph", "BOOST_GRAPH_DYN_LINK") boost_lib("graph_parallel", "BOOST_GRAPH_DYN_LINK") boost_lib("iostreams", "BOOST_IOSTREAMS_DYN_LINK") boost_lib("locale", "BOOST_LOG_DYN_LINK") boost_lib("log", "BOOST_LOG_DYN_LINK") boost_lib("log_setup", "BOOST_LOG_DYN_LINK") boost_lib("math_tr1", "BOOST_MATH_TR1_DYN_LINK") boost_lib("math_tr1f", "BOOST_MATH_TR1_DYN_LINK") boost_lib("math_tr1l", "BOOST_MATH_TR1_DYN_LINK") boost_lib("math_c99", "BOOST_MATH_TR1_DYN_LINK") boost_lib("math_c99f", "BOOST_MATH_TR1_DYN_LINK") boost_lib("math_c99l", "BOOST_MATH_TR1_DYN_LINK") boost_lib("mpi", "BOOST_MPI_DYN_LINK") boost_lib("program_options", "BOOST_PROGRAM_OPTIONS_DYN_LINK") boost_lib("python", "BOOST_PYTHON_DYN_LINK") boost_lib("python3", "BOOST_PYTHON_DYN_LINK") boost_lib("random", "BOOST_RANDOM_DYN_LINK") boost_lib("regex", "BOOST_REGEX_DYN_LINK") boost_lib("serialization", "BOOST_SERIALIZATION_DYN_LINK") boost_lib("wserialization", "BOOST_SERIALIZATION_DYN_LINK") boost_lib("signals", "BOOST_SIGNALS_DYN_LINK") boost_lib("system", "BOOST_SYSTEM_DYN_LINK") boost_lib("unit_test_framework", "BOOST_TEST_DYN_LINK") boost_lib("prg_exec_monitor", "BOOST_TEST_DYN_LINK") boost_lib("test_exec_monitor", "BOOST_TEST_DYN_LINK") boost_lib("thread", "BOOST_THREAD_DYN_DLL") boost_lib("wave", "BOOST_WAVE_DYN_LINK")
def run(self, project, name, prop_set, sources): lib_sources = prop_set.get('<library>') sources.extend(lib_sources) # Add <library-path> properties for all searched libraries extra = [] for s in sources: if s.type() == 'SEARCHED_LIB': search = s.search() extra.extend( property.Property('<library-path>', sp) for sp in search) orig_xdll_path = [] if prop_set.get('<hardcode-dll-paths>') == ['true'] \ and type.is_derived(self.target_types_ [0], 'EXE'): xdll_path = prop_set.get('<xdll-path>') orig_xdll_path = [ replace_grist(x, '<dll-path>') for x in xdll_path ] # It's possible that we have libraries in sources which did not came # from 'lib' target. For example, libraries which are specified # just as filenames as sources. We don't have xdll-path properties # for such target, but still need to add proper dll-path properties. for s in sources: if type.is_derived(s.type(), 'SHARED_LIB') and not s.action(): # Unfortunately, we don't have a good way to find the path # to a file, so use this nasty approach. p = s.project() location = path.root(s.name(), p.get('source-location')) xdll_path.append(path.parent(location)) extra.extend( property.Property('<dll-path>', sp) for sp in xdll_path) if extra: prop_set = prop_set.add_raw(extra) result = generators.Generator.run(self, project, name, prop_set, sources) if result: ur = self.extra_usage_requirements(result, prop_set) ur = ur.add(property_set.create(orig_xdll_path)) else: return None return (ur, result)
def adjust_properties(self, target, build_ps): a = target.action() properties = [] if a: ps = a.properties() properties = ps.all() # Unless <hardcode-dll-paths>true is in properties, which can happen # only if the user has explicitly requested it, nuke all <dll-path> # properties. if build_ps.get('hardcode-dll-paths') != ['true']: properties = [p for p in properties if p.feature.name != 'dll-path'] # If any <dll-path> properties were specified for installing, add # them. properties.extend(build_ps.get_properties('dll-path')) # Also copy <linkflags> feature from current build set, to be used # for relinking. properties.extend(build_ps.get_properties('linkflags')) # Remove the <tag> feature on original targets. # And <location>. If stage target has another stage target in # sources, then we shall get virtual targets with the <location> # property set. properties = [p for p in properties if not p.feature.name in ['tag', 'location']] properties.extend(build_ps.get_properties('dependency')) properties.extend(build_ps.get_properties('location')) properties.extend(build_ps.get_properties('install-no-version-symlinks')) d = build_ps.get_properties('install-source-root') # Make the path absolute: we shall use it to compute relative paths and # making the path absolute will help. if d: p = d[0] properties.append(property.Property(p.feature, os.path.abspath(p.value))) return property_set.create(properties)
def run (self, project, name, prop_set, sources): lib_sources = prop_set.get('<library>') sources.extend(lib_sources) # Add <library-path> properties for all searched libraries extra = [] for s in sources: if s.type () == 'SEARCHED_LIB': search = s.search() extra.extend(property.Property('<library-path>', sp) for sp in search) orig_xdll_path = [] if prop_set.get('<hardcode-dll-paths>') == ['true'] \ and type.is_derived(self.target_types_ [0], 'EXE'): xdll_path = prop_set.get('<xdll-path>') orig_xdll_path = [ replace_grist(x, '<dll-path>') for x in xdll_path ] # It's possible that we have libraries in sources which did not came # from 'lib' target. For example, libraries which are specified # just as filenames as sources. We don't have xdll-path properties # for such target, but still need to add proper dll-path properties. for s in sources: if type.is_derived (s.type (), 'SHARED_LIB') and not s.action (): # Unfortunately, we don't have a good way to find the path # to a file, so use this nasty approach. p = s.project() location = path.root(s.name(), p.get('source-location')) xdll_path.append(path.parent(location)) extra.extend(property.Property('<dll-path>', sp) for sp in xdll_path) if extra: prop_set = prop_set.add_raw (extra) result = generators.Generator.run(self, project, name, prop_set, sources) if result: ur = self.extra_usage_requirements(result, prop_set) ur = ur.add(property_set.create(orig_xdll_path)) else: return None return(ur, result)
def check(self, ps): assert isinstance(ps, property_set.PropertySet) # FIXME: this should not be hardcoded. Other checks might # want to consider different set of features as relevant. toolset = ps.get('toolset')[0] toolset_version_property = "<toolset-" + toolset + ":version>" relevant = ps.get_properties('target-os') + \ ps.get_properties("toolset") + \ ps.get_properties(toolset_version_property) + \ ps.get_properties("address-model") + \ ps.get_properties("architecture") rps = property_set.create(relevant) t = get_manager().targets().current() p = t.project() if builds(self.target, p, rps, "%s builds" % self.target): choosen = self.true_properties else: choosen = self.false_properties return property.evaluate_conditionals_in_context(choosen, ps)
def check(self, ps): assert isinstance(ps, property_set.PropertySet) # FIXME: this should not be hardcoded. Other checks might # want to consider different set of features as relevant. toolset = ps.get('toolset')[0] toolset_version_property = "<toolset-" + toolset + ":version>" ; relevant = ps.get_properties('target-os') + \ ps.get_properties("toolset") + \ ps.get_properties(toolset_version_property) + \ ps.get_properties("address-model") + \ ps.get_properties("architecture") rps = property_set.create(relevant) t = get_manager().targets().current() p = t.project() if builds(self.target, p, rps, "%s builds" % self.target): choosen = self.true_properties else: choosen = self.false_properties return property.evaluate_conditionals_in_context(choosen, ps)
def run(self, project, name, prop_set, sources): sources.extend(prop_set.get("<library>")) # Add <library-path> properties for all searched libraries extra = [] for s in sources: if s.type() == "SEARCHED_LIB": search = s.search() extra.extend(property.Property("<library-path>", sp) for sp in search) # It's possible that we have libraries in sources which did not came # from 'lib' target. For example, libraries which are specified # just as filenames as sources. We don't have xdll-path properties # for such target, but still need to add proper dll-path properties. extra_xdll_path = [] for s in sources: if type.is_derived(s.type(), "SHARED_LIB") and not s.action(): # Unfortunately, we don't have a good way to find the path # to a file, so use this nasty approach. p = s.project() location = path.root(s.name(), p.get("source-location")[0]) extra_xdll_path.append(os.path.dirname(location)) # Hardcode DLL paths only when linking executables. # Pros: do not need to relink libraries when installing. # Cons: "standalone" libraries (plugins, python extensions) can not # hardcode paths to dependent libraries. if prop_set.get("<hardcode-dll-paths>") == ["true"] and type.is_derived(self.target_types_[0], "EXE"): xdll_path = prop_set.get("<xdll-path>") extra.extend(property.Property("<dll-path>", sp) for sp in extra_xdll_path) extra.extend(property.Property("<dll-path>", sp) for sp in xdll_path) if extra: prop_set = prop_set.add_raw(extra) result = generators.Generator.run(self, project, name, prop_set, sources) if result: ur = self.extra_usage_requirements(result, prop_set) ur = ur.add(property_set.create(["<xdll-path>" + p for p in extra_xdll_path])) else: return None return (ur, result)
def generated_targets(self, sources, prop_set, project, name): # sources to pass to inherited rule sources2 = [] # properties to pass to inherited rule properties2 = [] # sources which are libraries libraries = [] # Searched libraries are not passed as argument to linker # but via some option. So, we pass them to the action # via property. properties2 = prop_set.raw() fsa = [] fst = [] for s in sources: if type.is_derived(s.type(), 'SEARCHED_LIB'): name = s.real_name() if s.shared(): fsa.append(name) else: fst.append(name) else: sources2.append(s) if fsa: properties2 += [ replace_grist('&&'.join(fsa), '<find-shared-library>') ] if fst: properties2 += [ replace_grist('&&'.join(fst), '<find-static-library>') ] spawn = generators.Generator.generated_targets( self, sources2, property_set.create(properties2), project, name) return spawn
def run (self, project, name, prop_set, sources): assert isinstance(project, targets.ProjectTarget) assert isinstance(name, basestring) or name is None assert isinstance(prop_set, property_set.PropertySet) assert is_iterable_typed(sources, virtual_target.VirtualTarget) # create a copy since this modifies the sources list sources = list(sources) sources.extend(prop_set.get('<library>')) result = generators.Generator.run (self, project, name, prop_set, sources) usage_requirements = [] link = prop_set.get('<link>') if 'static' in link: for t in sources: if type.is_derived(t.type(), 'LIB'): usage_requirements.append(property.Property('<library>', t)) usage_requirements = property_set.create(usage_requirements) return usage_requirements, result
def run(self, project, name, prop_set, sources): assert isinstance(project, targets.ProjectTarget) assert isinstance(name, basestring) or name is None assert isinstance(prop_set, property_set.PropertySet) assert is_iterable_typed(sources, virtual_target.VirtualTarget) # create a copy since this modifies the sources list sources = list(sources) sources.extend(prop_set.get("<library>")) result = generators.Generator.run(self, project, name, prop_set, sources) usage_requirements = [] link = prop_set.get("<link>") if "static" in link: for t in sources: if type.is_derived(t.type(), "LIB"): usage_requirements.append(property.Property("<library>", t)) usage_requirements = property_set.create(usage_requirements) return usage_requirements, result
def run_pch(self, project, name, prop_set, sources): # Find the header in sources. Ignore any CPP sources. header = None for s in sources: if type.is_derived(s.type(), 'H'): header = s # Error handling: Base header file name should be the same as the base # precompiled header name. header_name = header.name() header_basename = os.path.basename(header_name).rsplit('.', 1)[0] if header_basename != name: location = project.project_module ###FIXME: raise Exception() ### errors.user-error "in" $(location)": pch target name `"$(name)"' should be the same as the base name of header file `"$(header-name)"'" ; pch_file = Generator.run(self, project, name, prop_set, [header]) # return result of base class and pch-file property as usage-requirements # FIXME: what about multiple results from generator.run? return (property_set.create([Property('pch-file', pch_file[0]), Property('cflags', '-Winvalid-pch')]), pch_file)
import bjam from b2.build import alias, property, property_set, feature from b2.manager import get_manager from b2.tools import builtin, common from b2.util import bjam_signature, regex # TODO: This is currently necessary in Python Port, but was not in Jam. feature.feature("layout", ["system", "versioned", "tag"], ["optional"]) feature.feature("root", [], ["optional", "free"]) feature.feature("build-id", [], ["optional", "free"]) __initialized = None __boost_auto_config = property_set.create([property.Property("layout", "system")]) __boost_configured = {} __boost_default = None __build_id = None __debug = None def debug(): global __debug if __debug is None: __debug = "--debug-configuration" in bjam.variable("ARGV") return __debug # Configuration of the boost library to use.
def main_real(): global debug_config, out_xml debug_config = "--debug-configuration" in sys.argv out_xml = any(re.match("^--out-xml=(.*)$", a) for a in sys.argv) engine = Engine() global_build_dir = option.get("build-dir") manager = Manager(engine, global_build_dir) import b2.build.configure as configure if "--version" in sys.argv: version.report() return # This module defines types and generator and what not, # and depends on manager's existence import b2.tools.builtin b2.tools.common.init(manager) load_configuration_files() # Load explicitly specified toolset modules. extra_properties = process_explicit_toolset_requests() # Load the actual project build script modules. We always load the project # in the current folder so 'use-project' directives have any chance of # being seen. Otherwise, we would not be able to refer to subprojects using # target ids. current_project = None projects = get_manager().projects() if projects.find(".", "."): current_project = projects.target(projects.load(".")) # Load the default toolset module if no other has already been specified. if not feature.values("toolset"): dt = default_toolset dtv = None if default_toolset: dtv = default_toolset_version else: dt = "gcc" if os.name == 'nt': dt = "msvc" # FIXME: # else if [ os.name ] = MACOSX # { # default-toolset = darwin ; # } print "warning: No toolsets are configured." print "warning: Configuring default toolset '%s'." % dt print "warning: If the default is wrong, your build may not work correctly." print "warning: Use the \"toolset=xxxxx\" option to override our guess." print "warning: For more configuration options, please consult" print "warning: http://boost.org/boost-build2/doc/html/bbv2/advanced/configuration.html" using(dt, dtv) # Parse command line for targets and properties. Note that this requires # that all project files already be loaded. (target_ids, properties) = build_request.from_command_line(sys.argv[1:] + extra_properties) # Expand properties specified on the command line into multiple property # sets consisting of all legal property combinations. Each expanded property # set will be used for a single build run. E.g. if multiple toolsets are # specified then requested targets will be built with each of them. if properties: expanded = build_request.expand_no_defaults(properties) else: expanded = [property_set.empty()] # Check that we actually found something to build. if not current_project and not target_ids: get_manager().errors( )("no Jamfile in current directory found, and no target references specified." ) # FIXME: # EXIT # Flags indicating that this build system run has been started in order to # clean existing instead of create new targets. Note that these are not the # final flag values as they may get changed later on due to some special # targets being specified on the command line. clean = "--clean" in sys.argv cleanall = "--clean-all" in sys.argv # List of explicitly requested files to build. Any target references read # from the command line parameter not recognized as one of the targets # defined in the loaded Jamfiles will be interpreted as an explicitly # requested file to build. If any such files are explicitly requested then # only those files and the targets they depend on will be built and they # will be searched for among targets that would have been built had there # been no explicitly requested files. explicitly_requested_files = [] # List of Boost Build meta-targets, virtual-targets and actual Jam targets # constructed in this build system run. targets = [] virtual_targets = [] actual_targets = [] explicitly_requested_files = [] # Process each target specified on the command-line and convert it into # internal Boost Build target objects. Detect special clean target. If no # main Boost Build targets were explictly requested use the current project # as the target. for id in target_ids: if id == "clean": clean = 1 else: t = None if current_project: t = current_project.find(id, no_error=1) else: t = find_target(id) if not t: print "notice: could not find main target '%s'" % id print "notice: assuming it's a name of file to create " explicitly_requested_files.append(id) else: targets.append(t) if not targets: targets = [projects.target(projects.module_name("."))] # FIXME: put this BACK. ## if [ option.get dump-generators : : true ] ## { ## generators.dump ; ## } # We wish to put config.log in the build directory corresponding # to Jamroot, so that the location does not differ depending on # directory where we do build. The amount of indirection necessary # here is scary. first_project = targets[0].project() first_project_root_location = first_project.get('project-root') first_project_root_module = manager.projects().load( first_project_root_location) first_project_root = manager.projects().target(first_project_root_module) first_build_build_dir = first_project_root.build_dir() configure.set_log_file(os.path.join(first_build_build_dir, "config.log")) virtual_targets = [] global results_of_main_targets # Now that we have a set of targets to build and a set of property sets to # build the targets with, we can start the main build process by using each # property set to generate virtual targets from all of our listed targets # and any of their dependants. for p in expanded: manager.set_command_line_free_features(property_set.create(p.free())) for t in targets: try: g = t.generate(p) if not isinstance(t, ProjectTarget): results_of_main_targets.extend(g.targets()) virtual_targets.extend(g.targets()) except ExceptionWithUserContext, e: e.report() except Exception: raise
import bjam from b2.build import alias, property, property_set, feature from b2.manager import get_manager from b2.tools import builtin, common from b2.util import bjam_signature, regex # TODO: This is currently necessary in Python Port, but was not in Jam. feature.feature('layout', ['system', 'versioned', 'tag'], ['optional']) feature.feature('root', [], ['optional', 'free']) feature.feature('build-id', [], ['optional', 'free']) __initialized = None __boost_auto_config = property_set.create([property.Property('layout', 'system')]) __boost_configured = {} __boost_default = None __build_id = None __debug = None def debug(): global __debug if __debug is None: __debug = "--debug-configuration" in bjam.variable("ARGV") return __debug # Configuration of the boost library to use. #
def main_real(): global debug_config, out_xml debug_config = "--debug-configuration" in sys.argv out_xml = any(re.match("^--out-xml=(.*)$", a) for a in sys.argv) engine = Engine() global_build_dir = option.get("build-dir") manager = Manager(engine, global_build_dir) import b2.build.configure as configure if "--version" in sys.argv: from b2.build import version version.report() return # This module defines types and generator and what not, # and depends on manager's existence import b2.tools.builtin b2.tools.common.init(manager) load_configuration_files() # Load explicitly specified toolset modules. extra_properties = process_explicit_toolset_requests() # Load the actual project build script modules. We always load the project # in the current folder so 'use-project' directives have any chance of # being seen. Otherwise, we would not be able to refer to subprojects using # target ids. current_project = None projects = get_manager().projects() if projects.find(".", "."): current_project = projects.target(projects.load(".")) # Load the default toolset module if no other has already been specified. if not feature.values("toolset"): dt = default_toolset dtv = None if default_toolset: dtv = default_toolset_version else: dt = "gcc" if os.name == 'nt': dt = "msvc" # FIXME: #else if [ os.name ] = MACOSX #{ # default-toolset = darwin ; #} print "warning: No toolsets are configured." print "warning: Configuring default toolset '%s'." % dt print "warning: If the default is wrong, your build may not work correctly." print "warning: Use the \"toolset=xxxxx\" option to override our guess." print "warning: For more configuration options, please consult" print "warning: http://boost.org/boost-build2/doc/html/bbv2/advanced/configuration.html" using(dt, dtv) # Parse command line for targets and properties. Note that this requires # that all project files already be loaded. (target_ids, properties) = build_request.from_command_line(sys.argv[1:] + extra_properties) # Expand properties specified on the command line into multiple property # sets consisting of all legal property combinations. Each expanded property # set will be used for a single build run. E.g. if multiple toolsets are # specified then requested targets will be built with each of them. if properties: expanded = build_request.expand_no_defaults(properties) else: expanded = [property_set.empty()] # Check that we actually found something to build. if not current_project and not target_ids: get_manager().errors()("no Jamfile in current directory found, and no target references specified.") # FIXME: # EXIT # Flags indicating that this build system run has been started in order to # clean existing instead of create new targets. Note that these are not the # final flag values as they may get changed later on due to some special # targets being specified on the command line. clean = "--clean" in sys.argv cleanall = "--clean-all" in sys.argv # List of explicitly requested files to build. Any target references read # from the command line parameter not recognized as one of the targets # defined in the loaded Jamfiles will be interpreted as an explicitly # requested file to build. If any such files are explicitly requested then # only those files and the targets they depend on will be built and they # will be searched for among targets that would have been built had there # been no explicitly requested files. explicitly_requested_files = [] # List of Boost Build meta-targets, virtual-targets and actual Jam targets # constructed in this build system run. targets = [] virtual_targets = [] actual_targets = [] explicitly_requested_files = [] # Process each target specified on the command-line and convert it into # internal Boost Build target objects. Detect special clean target. If no # main Boost Build targets were explictly requested use the current project # as the target. for id in target_ids: if id == "clean": clean = 1 else: t = None if current_project: t = current_project.find(id, no_error=1) else: t = find_target(id) if not t: print "notice: could not find main target '%s'" % id print "notice: assuming it's a name of file to create " ; explicitly_requested_files.append(id) else: targets.append(t) if not targets: targets = [projects.target(projects.module_name("."))] # FIXME: put this BACK. ## if [ option.get dump-generators : : true ] ## { ## generators.dump ; ## } # We wish to put config.log in the build directory corresponding # to Jamroot, so that the location does not differ depending on # directory where we do build. The amount of indirection necessary # here is scary. first_project = targets[0].project() first_project_root_location = first_project.get('project-root') first_project_root_module = manager.projects().load(first_project_root_location) first_project_root = manager.projects().target(first_project_root_module) first_build_build_dir = first_project_root.build_dir() configure.set_log_file(os.path.join(first_build_build_dir, "config.log")) virtual_targets = [] global results_of_main_targets # Now that we have a set of targets to build and a set of property sets to # build the targets with, we can start the main build process by using each # property set to generate virtual targets from all of our listed targets # and any of their dependants. for p in expanded: manager.set_command_line_free_features(property_set.create(p.free())) for t in targets: try: g = t.generate(p) if not isinstance(t, ProjectTarget): results_of_main_targets.extend(g.targets()) virtual_targets.extend(g.targets()) except ExceptionWithUserContext, e: e.report() except Exception: raise
def set(self, attribute, specification, exact=False): """Set the named attribute from the specification given by the user. The value actually set may be different.""" if exact: self.__dict__[attribute] = specification elif attribute == "requirements": self.requirements = property_set.refine_from_user_input( self.requirements, specification, self.project_module, self.location) elif attribute == "usage-requirements": unconditional = [] for p in specification: split = property.split_conditional(p) if split: unconditional.append(split[1]) else: unconditional.append(p) non_free = property.remove("free", unconditional) if non_free: get_manager().errors()("usage-requirements %s have non-free properties %s" \ % (specification, non_free)) t = property.translate_paths( property.create_from_strings(specification, allow_condition=True), self.location) existing = self.__dict__.get("usage-requirements") if existing: new = property_set.create(existing.all() + t) else: new = property_set.create(t) self.__dict__["usage-requirements"] = new elif attribute == "default-build": self.__dict__["default-build"] = property_set.create(specification) elif attribute == "source-location": source_location = [] for path in specification: source_location.append(os.path.join(self.location, path)) self.__dict__["source-location"] = source_location elif attribute == "build-dir": self.__dict__["build-dir"] = os.path.join(self.location, specification[0]) elif attribute == "id": id = specification[0] if id[0] != '/': id = "/" + id self.manager.projects().register_id(id, self.project_module) self.__dict__["id"] = id elif not attribute in [ "default-build", "location", "source-location", "parent", "projects-to-build", "project-root" ]: self.manager.errors()("""Invalid project attribute '%s' specified for project at '%s'""" % (attribute, self.location)) else: self.__dict__[attribute] = specification
def set(self, attribute, specification, exact=False): """Set the named attribute from the specification given by the user. The value actually set may be different.""" if exact: self.__dict__[attribute] = specification elif attribute == "requirements": self.requirements = property_set.refine_from_user_input( self.requirements, specification, self.project_module, self.location) elif attribute == "usage-requirements": unconditional = [] for p in specification: split = property.split_conditional(p) if split: unconditional.append(split[1]) else: unconditional.append(p) non_free = property.remove("free", unconditional) if non_free: get_manager().errors()("usage-requirements %s have non-free properties %s" \ % (specification, non_free)) t = property.translate_paths( property.create_from_strings(specification, allow_condition=True), self.location) existing = self.__dict__.get("usage-requirements") if existing: new = property_set.create(existing.all() + t) else: new = property_set.create(t) self.__dict__["usage-requirements"] = new elif attribute == "default-build": self.__dict__["default-build"] = property_set.create(specification) elif attribute == "source-location": source_location = [] for path in specification: source_location.append(os.path.join(self.location, path)) self.__dict__["source-location"] = source_location elif attribute == "build-dir": self.__dict__["build-dir"] = os.path.join(self.location, specification[0]) elif attribute == "id": id = specification[0] if id[0] != '/': id = "/" + id self.manager.projects().register_id(id, self.project_module) self.__dict__["id"] = id elif not attribute in ["default-build", "location", "source-location", "parent", "projects-to-build", "project-root"]: self.manager.errors()( """Invalid project attribute '%s' specified for project at '%s'""" % (attribute, self.location)) else: self.__dict__[attribute] = specification
def main_real(): global ignore_config global debug_config boost_build_path = bjam.variable("BOOST_BUILD_PATH") engine = Engine() global_build_dir = get_string_option("build-dir") debug_config = get_boolean_option("debug-configuration") manager = Manager(engine, global_build_dir) # This module defines types and generator and what not, # and depends on manager's existence import b2.tools.builtin # Check if we can load 'test-config.jam'. If we can, load it and # ignore user configs. test_config = glob(boost_build_path, ["test-config.jam"]) if test_config: test_config = test_config[0] if test_config: if debug_config: print "notice: loading testing-config.jam from '%s'" % test_config print "notice: user-config.jam and site-config.jam will be ignored" manager.projects().load_standalone("test-config", test_config) ignore_config = test_config or get_boolean_option("ignore-config") user_path = home_directories() + boost_build_path site_path = ["/etc"] + user_path if bjam.variable("OS") in ["NT", "CYGWIN"]: site_path = [os.environ("SystemRoot")] + user_path load_config(manager, "site-config", site_path) user_config_path = get_string_option("user-config") if not user_config_path: user_config_path = os.environ.get("BOOST_BUILD_USER_CONFIG") if user_config_path: if debug_config: print "Loading explicitly specifier user configuration file:" print " %s" % user_config_path manager.projects().load_standalone("user-config", user_config_path) else: load_config(manager, "user-config", user_path) # FIXME: ## # ## # Autoconfigure toolsets based on any instances of --toolset=xx,yy,...zz or ## # toolset=xx,yy,...zz in the command line ## # ## local option-toolsets = [ regex.split-list [ MATCH ^--toolset=(.*) : $(argv) ] : "," ] ; ## local feature-toolsets = [ regex.split-list [ MATCH ^toolset=(.*) : $(argv) ] : "," ] ; ## # if the user specified --toolset=..., we need to add toolset=... to ## # the build request ## local extra-build-request ; extra_build_request = [] ## if ! $(ignore-config) ## { ## for local t in $(option-toolsets) $(feature-toolsets) ## { ## # Parse toolset-version/properties ## local (t-v,t,v) = [ MATCH (([^-/]+)-?([^/]+)?)/?.* : $(t) ] ; ## local toolset-version = $((t-v,t,v)[1]) ; ## local toolset = $((t-v,t,v)[2]) ; ## local version = $((t-v,t,v)[3]) ; ## if $(debug-config) ## { ## ECHO notice: [cmdline-cfg] Detected command-line request for ## $(toolset-version): toolset= \"$(toolset)\" "version= \""$(version)\" ; ## } ## local known ; ## # if the toolset isn't known, configure it now. ## if $(toolset) in [ feature.values <toolset> ] ## { ## known = true ; ## } ## if $(known) && $(version) ## && ! [ feature.is-subvalue toolset : $(toolset) : version : $(version) ] ## { ## known = ; ## } ## if ! $(known) ## { ## if $(debug-config) ## { ## ECHO notice: [cmdline-cfg] toolset $(toolset-version) ## not previously configured; configuring now ; ## } ## toolset.using $(toolset) : $(version) ; ## } ## else ## { ## if $(debug-config) ## { ## ECHO notice: [cmdline-cfg] toolset $(toolset-version) already configured ; ## } ## } ## # make sure we get an appropriate property into the build request in ## # case the user used the "--toolset=..." form ## if ! $(t) in $(argv) ## && ! $(t) in $(feature-toolsets) ## { ## if $(debug-config) ## { ## ECHO notice: [cmdline-cfg] adding toolset=$(t) "to build request." ; ## } ## extra-build-request += toolset=$(t) ; ## } ## } ## } # FIXME: ## if USER_MODULE in [ RULENAMES ] ## { ## USER_MODULE site-config user-config ; ## } if get_boolean_option("version"): # FIXME: Move to a separate module. Include bjam # verision. print "Boost.Build M15 (Python port in development)" sys.exit(0) b2.tools.common.init(manager) # We always load project in "." so that 'use-project' directives has # any chance of been seen. Otherwise, we won't be able to refer to # subprojects using target ids. current_project = None projects = manager.projects() if projects.find(".", "."): current_project = projects.target(projects.load(".")) # FIXME: revive this logic, when loading of gcc works if not feature.values("<toolset>") and not ignore_config and 0: default_toolset = "gcc" if bjam.variable("OS") == "NT": default_toolset = "msvc" print "warning: No toolsets are configured." print "warning: Configuring default toolset '%s'" % default_toolset print "warning: If the default is wrong, you may not be able to build C++ programs." print "warning: Use the \"--toolset=xxxxx\" option to override our guess." print "warning: For more configuration options, please consult" print "warning: http://boost.org/boost-build2/doc/html/bbv2/advanced/configuration.html" projects.project_rules().using([default_toolset]) (target_ids, properties ) = b2.build.build_request.from_command_line(argv[1:] + extra_build_request) if properties: expanded = b2.build.build_request.expand_no_defaults(properties) xexpanded = [] for e in expanded: xexpanded.append(property_set.create(feature.split(e))) expanded = xexpanded else: expanded = [property_set.empty()] targets = [] clean = get_boolean_option("clean") clean_all = get_boolean_option("clean-all") bjam_targets = [] # Given a target id, try to find and return corresponding target. # This is only invoked when there's no Jamfile in "." # This code somewhat duplicates code in project-target.find but we can't reuse # that code without project-targets instance. def find_target(target_id): split = target_id.split("//") pm = None if len(split) > 1: pm = projects.find(split[0], ".") else: pm = projects.find(target_id, ".") result = None if pm: result = projects.target(pm) if len(split) > 1: result = result.find(split[1]) if not current_project and not target_ids: print "error: no Jamfile in current directory found, and no target references specified." sys.exit(1) for id in target_ids: if id == "clean": clean = 1 else: t = None if current_project: t = current_project.find(id, no_error=1) else: t = find_target(id) if not t: print "notice: could not find main target '%s'" % id print "notice: assuming it's a name of file to create " bjam_targets.append(id) else: targets.append(t) if not targets: targets = [projects.target(projects.module_name("."))] virtual_targets = [] # Virtual targets obtained when building main targets references on # the command line. When running # # bjam --clean main_target # # we want to clean the files that belong only to that main target, # so we need to record which targets are produced. results_of_main_targets = [] for p in expanded: manager.set_command_line_free_features(property_set.create(p.free())) for t in targets: try: g = t.generate(p) if not isinstance(t, ProjectTarget): results_of_main_targets.extend(g.targets()) virtual_targets.extend(g.targets()) except ExceptionWithUserContext, e: e.report() except Exception: raise
def main_real(): global ignore_config global debug_config boost_build_path = bjam.variable("BOOST_BUILD_PATH") engine = Engine() global_build_dir = get_string_option("build-dir") debug_config = get_boolean_option("debug-configuration") manager = Manager(engine, global_build_dir) # This module defines types and generator and what not, # and depends on manager's existence import b2.tools.builtin # Check if we can load 'test-config.jam'. If we can, load it and # ignore user configs. test_config = glob(boost_build_path, ["test-config.jam"]) if test_config: test_config = test_config[0] if test_config: if debug_config: print "notice: loading testing-config.jam from '%s'" % test_config print "notice: user-config.jam and site-config.jam will be ignored" manager.projects().load_standalone("test-config", test_config) ignore_config = test_config or get_boolean_option("ignore-config") user_path = home_directories() + boost_build_path site_path = ["/etc"] + user_path if bjam.variable("OS") in ["NT", "CYGWIN"]: site_path = [os.environ("SystemRoot")] + user_path load_config(manager, "site-config", site_path) user_config_path = get_string_option("user-config") if not user_config_path: user_config_path = os.environ.get("BOOST_BUILD_USER_CONFIG") if user_config_path: if debug_config: print "Loading explicitly specifier user configuration file:" print " %s" % user_config_path manager.projects().load_standalone("user-config", user_config_path) else: load_config(manager, "user-config", user_path) # FIXME: ## # ## # Autoconfigure toolsets based on any instances of --toolset=xx,yy,...zz or ## # toolset=xx,yy,...zz in the command line ## # ## local option-toolsets = [ regex.split-list [ MATCH ^--toolset=(.*) : $(argv) ] : "," ] ; ## local feature-toolsets = [ regex.split-list [ MATCH ^toolset=(.*) : $(argv) ] : "," ] ; ## # if the user specified --toolset=..., we need to add toolset=... to ## # the build request ## local extra-build-request ; extra_build_request = [] ## if ! $(ignore-config) ## { ## for local t in $(option-toolsets) $(feature-toolsets) ## { ## # Parse toolset-version/properties ## local (t-v,t,v) = [ MATCH (([^-/]+)-?([^/]+)?)/?.* : $(t) ] ; ## local toolset-version = $((t-v,t,v)[1]) ; ## local toolset = $((t-v,t,v)[2]) ; ## local version = $((t-v,t,v)[3]) ; ## if $(debug-config) ## { ## ECHO notice: [cmdline-cfg] Detected command-line request for ## $(toolset-version): toolset= \"$(toolset)\" "version= \""$(version)\" ; ## } ## local known ; ## # if the toolset isn't known, configure it now. ## if $(toolset) in [ feature.values <toolset> ] ## { ## known = true ; ## } ## if $(known) && $(version) ## && ! [ feature.is-subvalue toolset : $(toolset) : version : $(version) ] ## { ## known = ; ## } ## if ! $(known) ## { ## if $(debug-config) ## { ## ECHO notice: [cmdline-cfg] toolset $(toolset-version) ## not previously configured; configuring now ; ## } ## toolset.using $(toolset) : $(version) ; ## } ## else ## { ## if $(debug-config) ## { ## ECHO notice: [cmdline-cfg] toolset $(toolset-version) already configured ; ## } ## } ## # make sure we get an appropriate property into the build request in ## # case the user used the "--toolset=..." form ## if ! $(t) in $(argv) ## && ! $(t) in $(feature-toolsets) ## { ## if $(debug-config) ## { ## ECHO notice: [cmdline-cfg] adding toolset=$(t) "to build request." ; ## } ## extra-build-request += toolset=$(t) ; ## } ## } ## } # FIXME: ## if USER_MODULE in [ RULENAMES ] ## { ## USER_MODULE site-config user-config ; ## } if get_boolean_option("version"): # FIXME: Move to a separate module. Include bjam # verision. print "Boost.Build M15 (Python port in development)" sys.exit(0) b2.tools.common.init(manager) # We always load project in "." so that 'use-project' directives has # any chance of been seen. Otherwise, we won't be able to refer to # subprojects using target ids. current_project = None projects = manager.projects() if projects.find(".", "."): current_project = projects.target(projects.load(".")) # FIXME: revive this logic, when loading of gcc works if not feature.values("<toolset>") and not ignore_config and 0: default_toolset = "gcc" ; if bjam.variable("OS") == "NT": default_toolset = "msvc" print "warning: No toolsets are configured." ; print "warning: Configuring default toolset '%s'" % default_toolset print "warning: If the default is wrong, you may not be able to build C++ programs." print "warning: Use the \"--toolset=xxxxx\" option to override our guess." print "warning: For more configuration options, please consult" print "warning: http://boost.org/boost-build2/doc/html/bbv2/advanced/configuration.html" projects.project_rules().using([default_toolset]) (target_ids, properties) = b2.build.build_request.from_command_line( argv[1:] + extra_build_request) if properties: expanded = b2.build.build_request.expand_no_defaults(properties) xexpanded = [] for e in expanded: xexpanded.append(property_set.create(feature.split(e))) expanded = xexpanded else: expanded = [property_set.empty()] targets = [] clean = get_boolean_option("clean") clean_all = get_boolean_option("clean-all") bjam_targets = [] # Given a target id, try to find and return corresponding target. # This is only invoked when there's no Jamfile in "." # This code somewhat duplicates code in project-target.find but we can't reuse # that code without project-targets instance. def find_target (target_id): split = target_id.split("//") pm = None if len(split) > 1: pm = projects.find(split[0], ".") else: pm = projects.find(target_id, ".") result = None if pm: result = projects.target(pm) if len(split) > 1: result = result.find(split[1]) if not current_project and not target_ids: print "error: no Jamfile in current directory found, and no target references specified." sys.exit(1) for id in target_ids: if id == "clean": clean = 1 else: t = None if current_project: t = current_project.find(id, no_error=1) else: t = find_target(id) if not t: print "notice: could not find main target '%s'" % id print "notice: assuming it's a name of file to create " ; bjam_targets.append(id) else: targets.append(t) if not targets: targets = [projects.target(projects.module_name("."))] virtual_targets = [] # Virtual targets obtained when building main targets references on # the command line. When running # # bjam --clean main_target # # we want to clean the files that belong only to that main target, # so we need to record which targets are produced. results_of_main_targets = [] for p in expanded: manager.set_command_line_free_features(property_set.create(p.free())) for t in targets: try: g = t.generate(p) if not isinstance(t, ProjectTarget): results_of_main_targets.extend(g.targets()) virtual_targets.extend(g.targets()) except ExceptionWithUserContext, e: e.report() except Exception: raise