From dbcbf19ecea9d07d264dbbc1cd87ab22393be8a7 Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Sat, 21 Jan 2017 11:15:14 +0530 Subject: compilers: New class CompilerArgs derived from list() The purpose of this class is to make it possible to sanely generate compiler command-lines by ensuring that new arguments appended or added to a list of arguments properly override previous arguments. For instance: >>> a = CompilerArgs(['-Lfoo', '-DBAR']) >>> a += ['-Lgah', '-DTAZ'] >>> print(a) ['-Lgah', '-Lfoo', '-DBAR', '-DTAZ'] Arguments will be de-duped if it is safe to do so. Currently, this is only done for -I and -L arguments (previous occurances are removed when a new one is added) and arguments that once added cannot be overriden such as -pipe are removed completely. --- mesonbuild/backend/backends.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mesonbuild/backend/backends.py') diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 6f8a50e..eadc8cc 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -360,7 +360,7 @@ class Backend: for dep in target.get_external_deps(): # Cflags required by external deps might have UNIX-specific flags, # so filter them out if needed - commands += compiler.unix_compile_flags_to_native(dep.get_compile_args()) + commands += compiler.unix_args_to_native(dep.get_compile_args()) if isinstance(target, build.Executable): commands += dep.get_exe_args() -- cgit v1.1 From 2bb58c909fd80cc8ce053b5f1b6565bd28a416d2 Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Sat, 21 Jan 2017 12:05:38 +0530 Subject: Use CompilerArgs for generation of compile commands At the same time, also fix the order in which compile arguments are added. Detailed comments have been added concerning the priority and order of the arguments. Also adds a unit test and an integration test for the same. --- mesonbuild/backend/backends.py | 50 ++++++++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 11 deletions(-) (limited to 'mesonbuild/backend/backends.py') diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index eadc8cc..a83d95f 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -21,6 +21,7 @@ from .. import compilers import json import subprocess from ..mesonlib import MesonException, get_compiler_for_source, classify_unity_sources +from ..compilers import CompilerArgs class CleanTrees: ''' @@ -338,32 +339,59 @@ class Backend: return extra_args def generate_basic_compiler_args(self, target, compiler, no_warn_args=False): - commands = [] + # Create an empty commands list, and start adding arguments from + # various sources in the order in which they must override each other + # starting from hard-coded defaults followed by build options and so on. + commands = CompilerArgs(compiler) + # First, the trivial ones that are impossible to override. + # + # Add -nostdinc/-nostdinc++ if needed; can't be overriden commands += self.get_cross_stdlib_args(target, compiler) + # Add things like /NOLOGO or -pipe; usually can't be overriden commands += compiler.get_always_args() + # Only add warning-flags by default if the buildtype enables it, and if + # we weren't explicitly asked to not emit warnings (for Vala, f.ex) if no_warn_args: commands += compiler.get_no_warn_args() elif self.environment.coredata.get_builtin_option('buildtype') != 'plain': commands += compiler.get_warn_args(self.environment.coredata.get_builtin_option('warning_level')) + # Add -Werror if werror=true is set in the build options set on the + # command-line or default_options inside project(). This only sets the + # action to be done for warnings if/when they are emitted, so it's ok + # to set it after get_no_warn_args() or get_warn_args(). + if self.environment.coredata.get_builtin_option('werror'): + commands += compiler.get_werror_args() + # Add compile args for c_* or cpp_* build options set on the + # command-line or default_options inside project(). commands += compiler.get_option_compile_args(self.environment.coredata.compiler_options) - commands += self.build.get_global_args(compiler) + # Add buildtype args: optimization level, debugging, etc. + commands += compiler.get_buildtype_args(self.environment.coredata.get_builtin_option('buildtype')) + # Add compile args added using add_project_arguments() commands += self.build.get_project_args(compiler, target.subproject) + # Add compile args added using add_global_arguments() + # These override per-project arguments + commands += self.build.get_global_args(compiler) + # Compile args added from the env: CFLAGS/CXXFLAGS, etc. We want these + # to override all the defaults, but not the per-target compile args. commands += self.environment.coredata.external_args[compiler.get_language()] - commands += self.escape_extra_args(compiler, target.get_extra_args(compiler.get_language())) - commands += compiler.get_buildtype_args(self.environment.coredata.get_builtin_option('buildtype')) - if self.environment.coredata.get_builtin_option('werror'): - commands += compiler.get_werror_args() + # Always set -fPIC for shared libraries if isinstance(target, build.SharedLibrary): commands += compiler.get_pic_args() + # Set -fPIC for static libraries by default unless explicitly disabled if isinstance(target, build.StaticLibrary) and target.pic: commands += compiler.get_pic_args() + # Add compile args needed to find external dependencies + # Link args are added while generating the link command for dep in target.get_external_deps(): - # Cflags required by external deps might have UNIX-specific flags, - # so filter them out if needed - commands += compiler.unix_args_to_native(dep.get_compile_args()) + commands += dep.get_compile_args() + # Qt needs -fPIC for executables + # XXX: We should move to -fPIC for all executables if isinstance(target, build.Executable): - commands += dep.get_exe_args() - + commands += dep.get_exe_args(compiler) + # For 'automagic' deps: Boost and GTest. Also dependency('threads'). + # pkg-config puts the thread flags itself via `Cflags:` + if dep.need_threads(): + commands += compiler.thread_flags() # Fortran requires extra include directives. if compiler.language == 'fortran': for lt in target.link_targets: -- cgit v1.1 From 50c4851daa79919f475e2885653eafd572bd6dfb Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Sat, 21 Jan 2017 12:05:38 +0530 Subject: Use CompilerArgs for generation of link commands Also, now the linker options are added from various sources in the same order as compiler arguments for compile commands. As a result, all libraries and library paths from external and internal sources are added after all the linker options have been added. As a result option_link_args() are added when libraries are added to the list since currently the only thing they add are the libraries specific in cpp_winlibs/c_winlibs. This fixes an issue where compilation with the MinGW toolchain (which uses static libraries for winlibs) would result in undefined symbol errors because the static libraries would be added in the very beginning and hence would not be scanned for symbols. Detailed comments have been added that explain where each option is coming from and why it's been added at that specific point. More improvements are necessary here because we currently still unnecessarily repeat libraries from dependencies over and over, which is a major problem in gst-build because inter-subproject dependencies cause linker command-lines to almost exceed the argument list length limit imposed by the kernel. It is also causing us to unnecessarily add static libraries which have already been linked into a shared library. See: self.build_target_link_arguments() --- mesonbuild/backend/backends.py | 20 -------------------- 1 file changed, 20 deletions(-) (limited to 'mesonbuild/backend/backends.py') diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index a83d95f..4988f28 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -692,23 +692,3 @@ class Backend: for s in self.build.postconf_scripts: cmd = s['exe'] + s['args'] subprocess.check_call(cmd, env=child_env) - - # Subprojects of subprojects may cause the same dep args to be used - # multiple times. Remove duplicates here. Note that we can't dedup - # libraries based on name alone, because "-lfoo -lbar -lfoo" is - # a completely valid (though pathological) sequence and removing the - # latter may fail. Usually only applies to static libs, though. - def dedup_arguments(self, commands): - includes = {} - final_commands = [] - previous = '-fsuch_arguments=woof' - for c in commands: - if c.startswith(('-I', '-L', '/LIBPATH')): - if c in includes: - continue - includes[c] = True - if previous == c: - continue - previous = c - final_commands.append(c) - return final_commands -- cgit v1.1