qmake_link_writer.cc 8.43 KiB
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWebEngine module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
** $QT_END_LICENSE$
****************************************************************************/
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "tools/gn/qmake_link_writer.h"
#include "tools/gn/deps_iterator.h"
#include "tools/gn/ninja_binary_target_writer.h"
#include "tools/gn/output_file.h"
#include "tools/gn/settings.h"
#include "tools/gn/target.h"
#include "tools/gn/config_values_extractors.h"
#include "base/logging.h"
#include "base/strings/string_util.h"
QMakeLinkWriter::QMakeLinkWriter(const NinjaBinaryTargetWriter* writer, const Target* target, std::ostream& out)
    : target_(target),
      nwriter_(writer),
      out_(out),
      path_output_(target->settings()->build_settings()->build_dir(),
                   target->settings()->build_settings()->root_path_utf8(),
                   ESCAPE_NONE) {
QMakeLinkWriter::~QMakeLinkWriter() {
// Based on similar function in qt_creator_writer.cc
void CollectDeps(std::set<const Target*> &deps, const Target* target) {
  for (const auto& dep : target->GetDeps(Target::DEPS_ALL)) {
    const Target* dep_target = dep.ptr;
    if (deps.count(dep_target))
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
continue; deps.insert(dep_target); CollectDeps(deps, dep_target); } } void PrintSourceFile(std::ostream& out, PathOutput& path_output, const SourceFile& file) { out << " \\\n \""; if (file.is_source_absolute()) { out << "$$PWD/"; path_output.WriteFile(out, file); } else { out << file.value(); } out << "\""; } void QMakeLinkWriter::Run() { CHECK(target_->output_type() == Target::SHARED_LIBRARY) << "QMakeLinkWriter only supports SHARED_LIBRARY"; std::vector<SourceFile> object_files; std::vector<SourceFile> other_files; std::vector<OutputFile> tool_outputs; const Settings* settings = target_->settings(); object_files.reserve(target_->sources().size()); for (const auto& source : target_->sources()) { Toolchain::ToolType tool_type = Toolchain::TYPE_NONE; if (!target_->GetOutputFilesForSource(source, &tool_type, &tool_outputs)) { if (GetSourceFileType(source) == SOURCE_DEF) other_files.push_back(source); continue; // No output for this source. } object_files.push_back(tool_outputs[0].AsSourceFile(settings->build_settings())); } UniqueVector<OutputFile> extra_object_files; UniqueVector<const Target*> linkable_deps; UniqueVector<const Target*> non_linkable_deps; nwriter_->GetDeps(&extra_object_files, &linkable_deps, &non_linkable_deps); std::set<const Target*> deps; deps.insert(target_); CollectDeps(deps, target_); // sources files. out_ << "NINJA_SOURCES ="; for (const auto& target : deps) { for (const auto& file : target->sources()) { PrintSourceFile(out_, path_output_, file); } } out_ << std::endl; // headers files. out_ << "NINJA_HEADERS ="; for (const auto& target : deps) { for (const auto& file : target->public_headers()) { PrintSourceFile(out_, path_output_, file); } } out_ << std::endl; std::set<std::string> defines; for (const auto& target : deps) { for (ConfigValuesIterator it(target); !it.done(); it.Next()) { for (std::string define : it.cur().defines()) {
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
defines.insert(define); } } } out_ << "NINJA_DEFINES ="; for (const auto& define : defines) { out_ << " \\\n " << define; } out_ << std::endl; // object files. out_ << "NINJA_OBJECTS ="; for (const auto& file : object_files) { out_ << " \\\n \"$$PWD/"; path_output_.WriteFile(out_, file); out_ << "\""; } for (const auto& file : extra_object_files) { out_ << " \\\n \"$$PWD/"; path_output_.WriteFile(out_, file); out_ << "\""; } out_ << std::endl; // linker flags out_ << "NINJA_LFLAGS ="; EscapeOptions opts; opts.mode = ESCAPE_COMMAND; // First the ldflags from the target and its config. RecursiveTargetConfigStringsToStream(target_, &ConfigValues::ldflags, opts, out_); out_ << std::endl; // archives out_ << "NINJA_ARCHIVES ="; std::vector<OutputFile> solibs; for (const Target* cur : linkable_deps) { if (cur->dependency_output_file().value() != cur->link_output_file().value()) { solibs.push_back(cur->link_output_file()); } else { out_ << " \\\n \"$$PWD/"; path_output_.WriteFile(out_, cur->link_output_file()); out_ << "\""; } } out_ << std::endl; // library dirs const OrderedSet<SourceDir> all_lib_dirs = target_->all_lib_dirs(); const Tool* tool = target_->toolchain()->GetToolForTargetFinalOutput(target_); if (!all_lib_dirs.empty()) { out_ << "NINJA_LIB_DIRS ="; PathOutput lib_path_output(path_output_.current_dir(), settings->build_settings()->root_path_utf8(), ESCAPE_COMMAND); for (size_t i = 0; i < all_lib_dirs.size(); i++) { out_ << " " << tool->lib_dir_switch(); lib_path_output.WriteDir(out_, all_lib_dirs[i], PathOutput::DIR_NO_LAST_SLASH); } } out_ << std::endl; //libs out_ << "NINJA_LIBS ="; EscapeOptions lib_escape_opts;
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
lib_escape_opts.mode = ESCAPE_COMMAND; const OrderedSet<LibFile> all_libs = target_->all_libs(); const std::string framework_ending(".framework"); for (size_t i = 0; i < all_libs.size(); i++) { const LibFile& lib_file = all_libs[i]; const std::string& lib_value = lib_file.value(); if (lib_file.is_source_file()) { out_ << " "; PathOutput lib_path_output(settings->build_settings()->build_dir(), settings->build_settings()->root_path_utf8(), ESCAPE_COMMAND); lib_path_output.WriteFile(out_, lib_file.source_file()); } else if (base::EndsWith(lib_value, framework_ending, base::CompareCase::INSENSITIVE_ASCII)) { out_ << " -framework "; EscapeStringToStream( out_, lib_value.substr(0, lib_value.size() - framework_ending.size()), lib_escape_opts); } else { out_ << " " << tool->lib_switch(); EscapeStringToStream(out_, lib_value, lib_escape_opts); } } out_ << std::endl; // solibs if (!solibs.empty()) { out_ << "NINJA_SOLIBS ="; for (const auto& file : solibs) { out_ << " \"$$PWD/"; path_output_.WriteFile(out_, file); out_ << "\""; } out_ << std::endl; } //targetdeps out_ << "NINJA_TARGETDEPS = "; path_output_.WriteFile(out_, OutputFile("\"$$PWD/" + target_->label().name() + ".stamp\"")); out_ << std::endl; }