# file : libbuild2/buildfile # license : MIT; see accompanying LICENSE file # NOTE: remember to update bundled_modules in libbuild2/module.cxx if adding a # new module. # bundled_modules = bash/ bin/ c/ cc/ cli/ cxx/ in/ version/ ./: lib{build2} $bundled_modules # Note that we have to load these buildfiles explicitly in order to have their # imports processed before the $config.save() call below. Failed that, we will # get a warning about saving unused config.import.* values. # include $bundled_modules # A module should treat lib{build2} as an "implied interface dependency" # meaning that it can link it as an implementation dependency and assume that # whomever imports and links this module will also import and link lib{build2} # explicitly. A module should also assume that lib{butl} will always be an # interface dependency of lib{build2} and therefore need not be explicitly # imported or linked. # NOTE: shared imports should go into root.build. # intf_libs = $libbutl lib{build2}: libul{build2}: \ {hxx ixx txx cxx}{* -utility-*installed \ -common-options \ -b-options \ -config \ -version \ -*.test...} \ {hxx ixx cxx}{common-options} \ {hxx ixx cxx}{b-options} \ {hxx}{config version} libul{build2}: script/{hxx ixx txx cxx}{** -*-options -**.test...} \ script/{hxx ixx cxx}{builtin-options} libul{build2}: build/script/{hxx ixx txx cxx}{** -*-options -**.test...} \ build/script/{hxx ixx cxx}{builtin-options} # Note that this won't work in libul{} since it's not installed. # lib{build2}: cxx{utility-installed}: for_install = true lib{build2}: cxx{utility-uninstalled}: for_install = false # These are "core modules" that come bundled with libbuild2 (see also unit # tests loop below). Note that the build system core can still function # without them or with their alternative implementations. Also note that # config/utility.?xx are part of the build system core (see comments in the # header for details). # # NOTE: remember to update import_modules() in libbuild2/modules.cxx if adding # a new such module. # libul{build2}: config/{hxx ixx txx cxx}{** -host-config -**.test...} \ config/cxx{host-config} # Derive ~host and ~build2 configurations from current configuration. # # This will of course blow up spectacularly if we are cross-compiling. But # let's wait and enjoy the fireworks (and get a sense of why someone would # want to cross-compile a build system). # # For the ~host configuration we only want c/cxx/cc and bin that they load. # For ~build2 we want to keep everything except dist. # # We also remove comment lines which could be confused with preprocessor # directives by some lesser compilers and blank lines between groups of # options which could cause spurious rebuilds when we filter out entire # groups. # # For ~host also filter out config.bin.lib/config.bin.*.lib (static/shared # library build/link preferences). In particular, we don't want to force # config.bin.lib=shared since that will cause static libraries to link shared # versions of their prerequisites (see mysql-client for a case where this can # make a difference). # # For ~build2 also filter out config.install.chroot -- we definitely don't # want it carried through. Also filter out variables that control tests # execution. # # Finally, for both ~host and ~build2 we keep config.config.environment # but strip config.config.hermetic* (we shouldn't be forcing hermiticity # on the users of ~host/~build2; they can decide for themselves if they # want it). # # The *_no_warnings variants are with the suppressed C/C++ compiler warnings # (in particular, used for private host configuration in bpkg). # # host_config_lines = [strings] build2_config_lines = [strings] host_config_no_warnings_lines = [strings] build2_config_no_warnings_lines = [strings] for l: $regex.replace_lines( \ $config.save(), \ '^( *(#|(config\.(test[. ]|dist\.|install\.chroot|config\.hermetic))).*|)$', \ [null]) { # Note: also preserve config.version. # h = [null] if $regex.match( \ $l, \ ' *config\.(c[. ]|cxx[. ]|cc[.]|bin[.]|config.environment |version ).*') { if! ($regex.match(\ $l, \ ' *config\.bin\.(lib|exe\.lib|liba\.lib|libs\.lib)[ =].*')) { # Filter out sanitizer options in ~host. We run the toolchain with # various sanitizers on CI but sanitizers cause issues in some packages. # Note that we can have both -fsanitize and -fno-sanitize forms. For # example: # # -fsanitize=address -fsanitize=undefined -fno-sanitize-recover=all # if $regex.match($l, ' *config\.(c|cxx|cc)\.(coptions|loptions)[ =].*') { h = $regex.replace($l, ' ?-f(no-)?sanitize[=-][^ ]+', '') } else h = $l } } if ($h != [null]) host_config_lines += $h build2_config_lines += $l # Append the warning suppressing option to config.{c,cxx}.coptions rather # than config.cc.coptions since the former could re-enable them. # if ($regex.match($l, ' *config\.(c|cxx)\.coptions[ =].*')) { # Note that in MSVC overriding one warning option (say /W3) with another # (say /w) triggers a warning. However, our compile_rule sanitizes the # command line to resolve such overrides (see msvc_sanitize_cl()). # o = ($cxx.class == 'gcc' ? -w : $cxx.class == 'msvc' ? /w : ) if ($regex.match($l, '[^=]+= *\[null\] *')) { l = $regex.replace($l, '= *\[null\] *$', "= $o") h = $regex.replace($h, '= *\[null\] *$', "= $o") } else { l = $regex.replace($l, '=(.*)$', "=\\1 $o") h = $regex.replace($h, '=(.*)$', "=\\1 $o") } } if ($h != [null]) host_config_no_warnings_lines += $h build2_config_no_warnings_lines += $l } config/cxx{host-config}: config/in{host-config} { host_config = $regex.merge($host_config_lines, '(.+)', '\1\n') build2_config = $regex.merge($build2_config_lines, '(.+)', '\1\n') host_config_no_warnings = $regex.merge($host_config_no_warnings_lines, \ '(.+)', '\1\n') build2_config_no_warnings = $regex.merge($build2_config_no_warnings_lines, \ '(.+)', '\1\n') } libul{build2}: dist/{hxx ixx txx cxx}{** -**.test...} libul{build2}: install/{hxx ixx txx cxx}{** -**.test...} libul{build2}: test/{hxx ixx txx cxx}{** -**.test...} libul{build2}: $intf_libs # Include the generated config and version headers into the distribution (so # that we don't pick up installed ones) and don't remove them when cleaning in # src (so that clean results in a state identical to distributed). # hxx{config}: in{config} hxx{version}: in{version} $src_root/manifest hxx{config version}: { dist = true clean = ($src_root != $out_root) } # Unit tests. # exe{*.test}: { test = true install = false } for t: cxx{ *.test...} \ script/cxx{**.test...} \ build/cxx{**.test...} \ config/cxx{**.test...} \ dist/cxx{**.test...} \ install/cxx{**.test...} \ test/cxx{**.test...} { d = $directory($t) n = $name($t)... b = $path.base($name($t)) ./: $d/exe{$n}: $t $d/{hxx ixx txx}{+$n} $d/testscript{+$n +$b+*.test...} $d/exe{$n}: libul{build2}: bin.whole = false $d/exe{$n}: cxx{utility-uninstalled} } # Build options. # # NOTE: this scope happens to be outer to the bundled modules which means they # will inherit any scope-wide options. So we should normally only set # them on targets. # obja{*}: cxx.poptions += -DLIBBUILD2_STATIC_BUILD objs{*}: cxx.poptions += -DLIBBUILD2_SHARED_BUILD # Pass our compiler target to be used as build2 host and our out_root to be # used as the build system import path (unless cross-compiling and not # forgetting to escape backslashes on Windows). # {obja objs}{context}: cxx.poptions += "-DBUILD2_HOST_TRIPLET=\"$cxx.target\"" # Note that we used to compare complete target triplets but that proved too # strict. For example, we may be running on x86_64-apple-darwin17.7.0 while # the compiler is targeting x86_64-apple-darwin17.3.0. # cross = ($cxx.target.cpu != $build.host.cpu || \ $cxx.target.system != $build.host.system) if! $cross { {obja objs}{context}: cxx.poptions += \ -DBUILD2_IMPORT_PATH=\"$regex.replace($out_root, '\\', '\\\\')\" } # Note that while the -installed object file should only be linked when we # are installing, it will be compiled even in the uninstalled case. # if ($install.root != [null]) { # Only if installed. # {obja objs}{utility-installed}: cxx.poptions += \ -DBUILD2_INSTALL_LIB=\"$regex.replace(\ $install.resolve($install.lib), '\\', '\\\\')\" # Only if configured. # # Note: strip the last directory component (). # # @@ TMP drop after 0.16.0 release. # install_buildfile = ($install.buildfile != [null] \ ? $directory($install.resolve($install.buildfile)) \ :) {obja objs}{utility-installed utility-uninstalled}: cxx.poptions += \ -DBUILD2_INSTALL_BUILDFILE=\"$regex.replace($install_buildfile, '\\', '\\\\')\" #\ {obja objs}{utility-installed utility-uninstalled}: cxx.poptions += \ -DBUILD2_INSTALL_BUILDFILE=\"$regex.replace(\ $directory($install.resolve($install.buildfile)), '\\', '\\\\')\" #\ # Data directory or src_root if not installed. # # Note: normalized in both cases. # {obja objs}{utility-installed}: cxx.poptions += \ -DBUILD2_INSTALL_DATA=\"$regex.replace(\ $install.resolve($install.data), '\\', '\\\\')\" {obja objs}{utility-uninstalled}: cxx.poptions += \ -DBUILD2_INSTALL_DATA=\"$regex.replace(\ $src_root, '\\', '\\\\')\" } if ($cxx.target.class != 'windows') { libul{build2}: cxx.libs += -lpthread # Note: only linking libdl in shared build. # if ($cxx.target.class != "bsd") libus{build2}: cxx.libs += -ldl } else { # @@ TMP work around Clang bug #45021. # if ($cxx.id == 'clang' && $cxx.target.system == 'win32-msvc') { if ($regex.find_match($cc.coptions $cxx.coptions, '-O[23]')) script/obj{run}: cxx.coptions += -O1 } } # Export options. # lib{build2}: { cxx.export.poptions = "-I$out_root" "-I$src_root" cxx.export.libs = $intf_libs } # While we don't call any pthread_*() functions in our API, this appears to be # needed for some std::thread implementations (like libstdc++). # if ($cxx.target.class != 'windows') lib{build2}: cxx.export.libs += -lpthread liba{build2}: cxx.export.poptions += -DLIBBUILD2_STATIC libs{build2}: cxx.export.poptions += -DLIBBUILD2_SHARED # For pre-releases use the complete version to make sure they cannot be used # in place of another pre-release or the final version. See the version module # for details on the version.* variable values. # if $version.pre_release lib{build2}: bin.lib.version = @"-$version.project_id" else lib{build2}: bin.lib.version = @"-$version.major.$version.minor" # Generated options parser. # # Note that the cli runtime namespace is build2::build::cli rather than # build2::cli. That's because the cli namespace inside build2 is reserved for # the cli build system module (libbuild2-cli). In fact, every namespace inside # build2 is reserved for a potential module and the only namespace names we # can use are build (this name, along with import and export, is reserved by # the build system core) and names that start with an underscore. # if $cli.configured { cli.options += --std c++11 -I $src_root --include-with-brackets \ --cli-namespace build2::build::cli --generate-specifier cli.cxx{*}: { # Include the generated cli files into the distribution and don't remove # them when cleaning in src (so that clean results in a state identical # to distributed). # dist = true clean = ($src_root != $out_root) # We keep the generated code in the repository so copy it back to src in # case of a forwarded configuration. # backlink = overwrite } cli.cxx{common-options}: cli{common} { cli.options += --include-prefix libbuild2 --guard-prefix LIBBUILD2 \ --export-symbol LIBBUILD2_SYMEXPORT \ --hxx-prologue '#include ' \ --generate-file-scanner --generate-vector-scanner } cli.cxx{b-options}: cli{b} { cli.options += --include-prefix libbuild2 --guard-prefix LIBBUILD2 \ --export-symbol LIBBUILD2_SYMEXPORT \ --hxx-prologue '#include ' \ --cxx-prologue "#include " \ --keep-separator --generate-parse --generate-merge # Usage options. # cli.options += --suppress-undocumented --long-usage --ansi-color \ --ascii-tree --page-usage 'build2::print_$name$_' --option-length 23 } script/cli.cxx{builtin-options}: script/cli{builtin} { cli.options += --include-prefix libbuild2/script \ --guard-prefix LIBBUILD2_SCRIPT --generate-modifier --suppress-usage # Don't install the generated cli headers since they are only used # internally in the script implementation. # install = false } build/script/cli.cxx{builtin-options}: build/script/cli{builtin} { cli.options += --include-prefix libbuild2/build/script \ --guard-prefix LIBBUILD2_BUILD_SCRIPT \ --cxx-prologue "#include " \ --generate-parse --generate-modifier --suppress-usage # Don't install the generated cli headers since they are only used # internally in the buildscript implementation. # install = false } } else { # No install for the pre-generated case. # script/hxx{builtin-options}@script/ \ script/ixx{builtin-options}@script/: install = false build/script/hxx{builtin-options}@build/script/ \ build/script/ixx{builtin-options}@build/script/: install = false } # Install into the libbuild2/ subdirectory of, say, /usr/include/ # recreating subdirectories. # {hxx ixx txx}{*}: { install = include/libbuild2/ install.subdirs = true }