https://github.com/pawosm-arm updated https://github.com/llvm/llvm-project/pull/117573
>From 65917ba219e26bd8547e8d1d9ff2c4ced1cdcad1 Mon Sep 17 00:00:00 2001 From: Pawel Osmialowski <pawel.osmialow...@arm.com> Date: Mon, 25 Nov 2024 14:46:55 +0000 Subject: [PATCH] [clang][driver] Special care for -l and -Wl, flags in config files Currently, if a -l (or -Wl,) flag is added into a config file (e.g. clang.cfg), it is situated before any object file in the effective command line. If the library requested by given -l flag is static, its symbols will not be made visible to any of the object files provided by the user. Also, the presence of any of the linker flags in a config file confuses the driver whenever the user invokes clang without any parameters. This patch solves both of those problems, by moving the -l and -Wl, flags specified in a config file to the end of the input list, and by discarding them when there are no other inputs provided by the user, or the last phase is not the linking phase. --- clang/include/clang/Driver/Driver.h | 3 +++ clang/lib/Driver/Driver.cpp | 28 +++++++++++++++++++++++++++ clang/test/Driver/Inputs/config-l.cfg | 1 + clang/test/Driver/config-file.c | 26 +++++++++++++++++++++++++ flang/test/Driver/Inputs/config-l.cfg | 1 + flang/test/Driver/config-file.f90 | 26 +++++++++++++++++++++++++ 6 files changed, 85 insertions(+) create mode 100644 clang/test/Driver/Inputs/config-l.cfg create mode 100644 flang/test/Driver/Inputs/config-l.cfg diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h index 9177d56718ee77..b21606b6f54b77 100644 --- a/clang/include/clang/Driver/Driver.h +++ b/clang/include/clang/Driver/Driver.h @@ -297,6 +297,9 @@ class Driver { /// Object that stores strings read from configuration file. llvm::StringSaver Saver; + /// Linker inputs originated from configuration file. + std::unique_ptr<llvm::opt::InputArgList> CfgLinkerInputs; + /// Arguments originated from configuration file. std::unique_ptr<llvm::opt::InputArgList> CfgOptions; diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 7de8341b8d2d61..edc3d34c0fa63a 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -1060,6 +1060,15 @@ bool Driver::readConfigFile(StringRef FileName, for (Arg *A : *NewOptions) A->claim(); + // Filter out all -l and -Wl, options, put them into a separate list and erase + // from the original list of configuration file options. These will be used + // only when linking and appended after all of the command line options. + auto NewLinkerIns = std::make_unique<InputArgList>(); + for (Arg *A : NewOptions->filtered(options::OPT_Wl_COMMA, options::OPT_l)) + appendOneArg(*NewLinkerIns, A); + NewOptions->eraseArg(options::OPT_Wl_COMMA); + NewOptions->eraseArg(options::OPT_l); + if (!CfgOptions) CfgOptions = std::move(NewOptions); else { @@ -1067,6 +1076,15 @@ bool Driver::readConfigFile(StringRef FileName, for (auto *Opt : *NewOptions) appendOneArg(*CfgOptions, Opt); } + + if (!CfgLinkerInputs) + CfgLinkerInputs = std::move(NewLinkerIns); + else { + // If this is a subsequent config file, append options to the previous one. + for (auto *Opt : *NewLinkerIns) + appendOneArg(*CfgLinkerInputs, Opt); + } + ConfigFiles.push_back(std::string(CfgFileName)); return false; } @@ -1244,6 +1262,7 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { if (!ContainsError) ContainsError = loadConfigFiles(); bool HasConfigFile = !ContainsError && (CfgOptions.get() != nullptr); + bool HasConfigLinkerIn = !ContainsError && CfgLinkerInputs; // All arguments, from both config file and command line. InputArgList Args = std::move(HasConfigFile ? std::move(*CfgOptions) @@ -1540,6 +1559,15 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { // Construct the list of inputs. InputList Inputs; BuildInputs(C->getDefaultToolChain(), *TranslatedArgs, Inputs); + if (HasConfigLinkerIn && Inputs.size()) { + Arg *FinalPhaseArg; + if (getFinalPhase(*TranslatedArgs, &FinalPhaseArg) == phases::Link) { + DerivedArgList TranslatedLinkerIns(*CfgLinkerInputs); + for (Arg *A : *CfgLinkerInputs) + TranslatedLinkerIns.append(A); + BuildInputs(C->getDefaultToolChain(), TranslatedLinkerIns, Inputs); + } + } // Populate the tool chains for the offloading devices, if any. CreateOffloadingDeviceToolChains(*C, Inputs); diff --git a/clang/test/Driver/Inputs/config-l.cfg b/clang/test/Driver/Inputs/config-l.cfg new file mode 100644 index 00000000000000..853b179bd2da85 --- /dev/null +++ b/clang/test/Driver/Inputs/config-l.cfg @@ -0,0 +1 @@ +-Wall -lm -Wl,-Bstatic -lhappy -Wl,-Bdynamic diff --git a/clang/test/Driver/config-file.c b/clang/test/Driver/config-file.c index 9df830ca4c7538..0f6fc885eef1f8 100644 --- a/clang/test/Driver/config-file.c +++ b/clang/test/Driver/config-file.c @@ -82,3 +82,29 @@ // CHECK-TWO-CONFIGS: -isysroot // CHECK-TWO-CONFIGS-SAME: /opt/data // CHECK-TWO-CONFIGS-SAME: -Wall + +//--- The linker input flags should be moved to the end of input list and appear only when linking. +// RUN: %clang --target=aarch64-unknown-linux-gnu --config %S/Inputs/config-l.cfg %s -lmylib -Wl,foo.a -### 2>&1 | FileCheck %s -check-prefix CHECK-LINKING +// RUN: %clang --target=aarch64-unknown-linux-gnu --config %S/Inputs/config-l.cfg -fopenmp %s -lmylib -Wl,foo.a -### 2>&1 | FileCheck %s -check-prefix CHECK-LINKING-LIBOMP-GOES-LAST +// RUN: %clang --target=aarch64-unknown-linux-gnu --config %S/Inputs/config-l.cfg -S %s -### 2>&1 | FileCheck %s -check-prefix CHECK-NOLINKING +// RUN: %clang --target=aarch64-unknown-linux-gnu --config %S/Inputs/config-l.cfg -fopenmp -S %s -### 2>&1 | FileCheck %s -check-prefix CHECK-NOLINKING-OPENMP +// RUN: %clang --target=x86_64-pc-windows-msvc --config %S/Inputs/config-l.cfg %s -lmylib -Wl,foo.lib -### 2>&1 | FileCheck %s -check-prefix CHECK-LINKING-MSVC +// RUN: %clang --target=x86_64-pc-windows-msvc --config %S/Inputs/config-l.cfg -S %s -### 2>&1 | FileCheck %s -check-prefix CHECK-NOLINKING-MSVC +// CHECK-LINKING: Configuration file: {{.*}}Inputs{{.}}config-l.cfg +// CHECK-LINKING: "-Wall" +// CHECK-LINKING: "{{.*}}-{{.*}}.o" "-lmylib" "foo.a" "-lm" "-Bstatic" "-lhappy" "-Bdynamic" +// CHECK-LINKING-LIBOMP-GOES-LAST: Configuration file: {{.*}}Inputs{{.}}config-l.cfg +// CHECK-LINKING-LIBOMP-GOES-LAST: "-Wall" {{.*}}"-fopenmp" +// CHECK-LINKING-LIBOMP-GOES-LAST: "{{.*}}-{{.*}}.o" "-lmylib" "foo.a" "-lm" "-Bstatic" "-lhappy" "-Bdynamic" {{.*}}"-lomp" +// CHECK-NOLINKING: Configuration file: {{.*}}Inputs{{.}}config-l.cfg +// CHECK-NOLINKING: "-Wall" +// CHECK-NOLINKING-NO: "-lm" "-Bstatic" "-lhappy" "-Bdynamic" +// CHECK-NOLINKING-OPENMP: Configuration file: {{.*}}Inputs{{.}}config-l.cfg +// CHECK-NOLINKING-OPENMP: "-Wall" {{.*}}"-fopenmp" +// CHECK-NOLINKING-OPENMP-NO: "-lm" "-Bstatic" "-lhappy" "-Bdynamic" {{.*}}"-lomp" +// CHECK-LINKING-MSVC: Configuration file: {{.*}}Inputs{{.}}config-l.cfg +// CHECK-LINKING-MSVC: "-Wall" +// CHECK-LINKING-MSVC: "{{.*}}-{{.*}}.o" "mylib.lib" "foo.lib" "m.lib" "-Bstatic" "happy.lib" "-Bdynamic" +// CHECK-NOLINKING-MSVC: Configuration file: {{.*}}Inputs{{.}}config-l.cfg +// CHECK-NOLINKING-MSVC: "-Wall" +// CHECK-NOLINKING-MSVC-NO: "m.lib" "-Bstatic" "happy.lib" "-Bdynamic" diff --git a/flang/test/Driver/Inputs/config-l.cfg b/flang/test/Driver/Inputs/config-l.cfg new file mode 100644 index 00000000000000..c18ee1cd16ec41 --- /dev/null +++ b/flang/test/Driver/Inputs/config-l.cfg @@ -0,0 +1 @@ +-ffast-math -lm -Wl,-Bstatic -lhappy -Wl,-Bdynamic diff --git a/flang/test/Driver/config-file.f90 b/flang/test/Driver/config-file.f90 index 70316dd971f36b..925dd0bd3f615f 100644 --- a/flang/test/Driver/config-file.f90 +++ b/flang/test/Driver/config-file.f90 @@ -61,3 +61,29 @@ ! CHECK-TWO-CONFIGS-NEXT: Configuration file: {{.*}}Inputs{{.}}config2{{.}}config-4.cfg ! CHECK-TWO-CONFIGS: -ffp-contract=fast ! CHECK-TWO-CONFIGS: -O3 + +!--- The linker input flags should be moved to the end of input list and appear only when linking. +! RUN: %flang --target=aarch64-unknown-linux-gnu --config %S/Inputs/config-l.cfg %s -lmylib -Wl,foo.a -### 2>&1 | FileCheck %s -check-prefix CHECK-LINKING +! RUN: %flang --target=aarch64-unknown-linux-gnu --config %S/Inputs/config-l.cfg -fopenmp %s -lmylib -Wl,foo.a -### 2>&1 | FileCheck %s -check-prefix CHECK-LINKING-LIBOMP-GOES-LAST +! RUN: %flang --target=aarch64-unknown-linux-gnu --config %S/Inputs/config-l.cfg -S %s -### 2>&1 | FileCheck %s -check-prefix CHECK-NOLINKING +! RUN: %flang --target=aarch64-unknown-linux-gnu --config %S/Inputs/config-l.cfg -fopenmp -S %s -### 2>&1 | FileCheck %s -check-prefix CHECK-NOLINKING-OPENMP +! RUN: %flang --target=x86_64-pc-windows-msvc --config %S/Inputs/config-l.cfg %s -lmylib -Wl,foo.lib -### 2>&1 | FileCheck %s -check-prefix CHECK-LINKING-MSVC +! RUN: %flang --target=x86_64-pc-windows-msvc --config %S/Inputs/config-l.cfg -S %s -### 2>&1 | FileCheck %s -check-prefix CHECK-NOLINKING-MSVC +! CHECK-LINKING: Configuration file: {{.*}}Inputs{{.}}config-l.cfg +! CHECK-LINKING: "-ffast-math" +! CHECK-LINKING: "{{.*}}-{{.*}}.o" "-lmylib" "foo.a" "-lm" "-Bstatic" "-lhappy" "-Bdynamic" +! CHECK-LINKING-LIBOMP-GOES-LAST: Configuration file: {{.*}}Inputs{{.}}config-l.cfg +! CHECK-LINKING-LIBOMP-GOES-LAST: "-ffast-math" {{.*}}"-fopenmp" +! CHECK-LINKING-LIBOMP-GOES-LAST: "{{.*}}-{{.*}}.o" "-lmylib" "foo.a" "-lm" "-Bstatic" "-lhappy" "-Bdynamic" {{.*}}"-lomp" +! CHECK-NOLINKING: Configuration file: {{.*}}Inputs{{.}}config-l.cfg +! CHECK-NOLINKING: "-ffast-math" +! CHECK-NOLINKING-NO: "-lm" "-Bstatic" "-lhappy" "-Bdynamic" +! CHECK-NOLINKING-OPENMP: Configuration file: {{.*}}Inputs{{.}}config-l.cfg +! CHECK-NOLINKING-OPENMP: "-ffast-math" {{.*}}"-fopenmp" +! CHECK-NOLINKING-OPENMP-NO: "-lm" "-Bstatic" "-lhappy" "-Bdynamic" {{.}}"-lomp" +! CHECK-LINKING-MSVC: Configuration file: {{.*}}Inputs{{.}}config-l.cfg +! CHECK-LINKING-MSVC: "-ffast-math" +! CHECK-LINKING-MSVC: "{{.*}}-{{.*}}.o" "mylib.lib" "foo.lib" "m.lib" "-Bstatic" "happy.lib" "-Bdynamic" +! CHECK-NOLINKING-MSVC: Configuration file: {{.*}}Inputs{{.}}config-l.cfg +! CHECK-NOLINKING-MSVC: "-ffast-math" +! CHECK-NOLINKING-MSVC-NO: "m.lib" "-Bstatic" "happy.lib" "-Bdynamic" _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits