cmCPackIFWGenerator.cxx 15.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*============================================================================
  CMake - Cross Platform Makefile Generator
  Copyright 2000-2009 Kitware, Inc., Insight Software Consortium

  Distributed under the OSI-approved BSD License (the "License");
  see accompanying file Copyright.txt for details.

  This software is distributed WITHOUT ANY WARRANTY; without even the
  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  See the License for more information.
============================================================================*/

#include "cmCPackIFWGenerator.h"

#include "cmCPackIFWInstaller.h"
16
#include "cmCPackIFWPackage.h"
17 18

#include <CPack/cmCPackComponentGroup.h>
19
#include <CPack/cmCPackLog.h>
20 21

#include <cmsys/Directory.hxx>
22
#include <cmsys/Glob.hxx>
23
#include <cmsys/RegularExpression.hxx>
24
#include <cmsys/SystemTools.hxx>
25

26
#include <cmGeneratedFileStream.h>
27 28
#include <cmGlobalGenerator.h>
#include <cmMakefile.h>
29
#include <cmSystemTools.h>
30
#include <cmTimestamp.h>
31 32
#include <cmVersionConfig.h>
#include <cmXMLWriter.h>
33 34 35 36 37 38 39 40 41

cmCPackIFWGenerator::cmCPackIFWGenerator()
{
}

cmCPackIFWGenerator::~cmCPackIFWGenerator()
{
}

42
bool cmCPackIFWGenerator::IsVersionLess(const char* version)
43 44
{
  return cmSystemTools::VersionCompare(cmSystemTools::OP_LESS,
45
                                       FrameworkVersion.data(), version);
46 47
}

48
bool cmCPackIFWGenerator::IsVersionGreater(const char* version)
49 50
{
  return cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER,
51
                                       FrameworkVersion.data(), version);
52 53
}

54
bool cmCPackIFWGenerator::IsVersionEqual(const char* version)
55 56
{
  return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL,
57
                                       FrameworkVersion.data(), version);
58 59
}

60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
int cmCPackIFWGenerator::PackageFiles()
{
  cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Configuration" << std::endl);

  // Installer configuragion
  Installer.GenerateInstallerFile();

  // Packages configuration
  Installer.GeneratePackageFiles();

  std::string ifwTLD = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
  std::string ifwTmpFile = ifwTLD;
  ifwTmpFile += "/IFWOutput.log";

  // Run repogen
75
  if (!Installer.Repositories.empty()) {
76
    std::string ifwCmd = RepoGen;
77

78
    if (IsVersionLess("2.0.0")) {
79
      ifwCmd += " -c " + this->toplevel + "/config/config.xml";
80
    }
81

82 83
    ifwCmd += " -p " + this->toplevel + "/packages";

84 85 86
    if (!PkgsDirsVector.empty()) {
      for (std::vector<std::string>::iterator it = PkgsDirsVector.begin();
           it != PkgsDirsVector.end(); ++it) {
87 88
        ifwCmd += " -p " + *it;
      }
89
    }
90

91
    if (!OnlineOnly && !DownloadedPackages.empty()) {
92
      ifwCmd += " -i ";
93
      std::set<cmCPackIFWPackage*>::iterator it = DownloadedPackages.begin();
94 95
      ifwCmd += (*it)->Name;
      ++it;
96
      while (it != DownloadedPackages.end()) {
97 98 99
        ifwCmd += "," + (*it)->Name;
        ++it;
      }
100
    }
101
    ifwCmd += " " + this->toplevel + "/repository";
102
    cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << ifwCmd << std::endl);
103 104
    std::string output;
    int retVal = 1;
105 106
    cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Generate repository"
                    << std::endl);
107
    bool res = cmSystemTools::RunSingleCommand(
108 109
      ifwCmd.c_str(), &output, &output, &retVal, 0, this->GeneratorVerbose, 0);
    if (!res || retVal) {
110 111 112 113 114
      cmGeneratedFileStream ofs(ifwTmpFile.c_str());
      ofs << "# Run command: " << ifwCmd << std::endl
          << "# Output:" << std::endl
          << output << std::endl;
      cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running IFW command: "
115 116 117
                      << ifwCmd << std::endl
                      << "Please check " << ifwTmpFile << " for errors"
                      << std::endl);
118 119
      return 0;
    }
120 121 122
    cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- repository: "
                    << this->toplevel << "/repository generated" << std::endl);
  }
123 124 125

  // Run binary creator
  {
126 127 128 129 130 131 132 133
    std::string ifwCmd = BinCreator;
    ifwCmd += " -c " + this->toplevel + "/config/config.xml";
    ifwCmd += " -p " + this->toplevel + "/packages";

    if (!PkgsDirsVector.empty()) {
      for (std::vector<std::string>::iterator it = PkgsDirsVector.begin();
           it != PkgsDirsVector.end(); ++it) {
        ifwCmd += " -p " + *it;
134 135 136
      }
    }

137 138 139 140 141 142 143
    if (OnlineOnly) {
      ifwCmd += " --online-only";
    } else if (!DownloadedPackages.empty() &&
               !Installer.Repositories.empty()) {
      ifwCmd += " -e ";
      std::set<cmCPackIFWPackage*>::iterator it = DownloadedPackages.begin();
      ifwCmd += (*it)->Name;
144
      ++it;
145 146 147
      while (it != DownloadedPackages.end()) {
        ifwCmd += "," + (*it)->Name;
        ++it;
148
      }
149 150 151 152 153 154 155
    } else if (!DependentPackages.empty()) {
      ifwCmd += " -i ";
      // Binary
      std::set<cmCPackIFWPackage*>::iterator bit = BinaryPackages.begin();
      while (bit != BinaryPackages.end()) {
        ifwCmd += (*bit)->Name + ",";
        ++bit;
156
      }
157 158 159
      // Depend
      DependenceMap::iterator it = DependentPackages.begin();
      ifwCmd += it->second.Name;
160
      ++it;
161 162 163
      while (it != DependentPackages.end()) {
        ifwCmd += "," + it->second.Name;
        ++it;
164 165
      }
    }
166 167 168 169 170
    // TODO: set correct name for multipackages
    if (!this->packageFileNames.empty()) {
      ifwCmd += " " + packageFileNames[0];
    } else {
      ifwCmd += " installer";
171
    }
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
    cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << ifwCmd << std::endl);
    std::string output;
    int retVal = 1;
    cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Generate package" << std::endl);
    bool res = cmSystemTools::RunSingleCommand(
      ifwCmd.c_str(), &output, &output, &retVal, 0, this->GeneratorVerbose, 0);
    if (!res || retVal) {
      cmGeneratedFileStream ofs(ifwTmpFile.c_str());
      ofs << "# Run command: " << ifwCmd << std::endl
          << "# Output:" << std::endl
          << output << std::endl;
      cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running IFW command: "
                      << ifwCmd << std::endl
                      << "Please check " << ifwTmpFile << " for errors"
                      << std::endl);
      return 0;
188 189 190 191 192 193
    }
  }

  return 1;
}

194
const char* cmCPackIFWGenerator::GetPackagingInstallPrefix()
195
{
196
  const char* defPrefix = cmCPackGenerator::GetPackagingInstallPrefix();
197 198 199

  std::string tmpPref = defPrefix ? defPrefix : "";

200
  if (this->Components.empty()) {
201
    tmpPref += "packages/" + GetRootPackageName() + "/data";
202
  }
203 204 205 206 207 208

  this->SetOption("CPACK_IFW_PACKAGING_INSTALL_PREFIX", tmpPref.c_str());

  return this->GetOption("CPACK_IFW_PACKAGING_INSTALL_PREFIX");
}

209
const char* cmCPackIFWGenerator::GetOutputExtension()
210
{
211
  return ExecutableSuffix.c_str();
212 213 214 215 216 217
}

int cmCPackIFWGenerator::InitializeInternal()
{
  // Search Qt Installer Framework tools

218 219
  const std::string BinCreatorOpt = "CPACK_IFW_BINARYCREATOR_EXECUTABLE";
  const std::string RepoGenOpt = "CPACK_IFW_REPOGEN_EXECUTABLE";
220
  const std::string FrameworkVersionOpt = "CPACK_IFW_FRAMEWORK_VERSION";
221

222 223
  if (!this->IsSet(BinCreatorOpt) || !this->IsSet(RepoGenOpt) ||
      !this->IsSet(FrameworkVersionOpt)) {
224
    this->ReadListFile("CPackIFW.cmake");
225
  }
226 227 228

  // Look 'binarycreator' executable (needs)

229 230
  const char* BinCreatorStr = this->GetOption(BinCreatorOpt);
  if (!BinCreatorStr || cmSystemTools::IsNOTFOUND(BinCreatorStr)) {
231
    BinCreator = "";
232
  } else {
233
    BinCreator = BinCreatorStr;
234
  }
235

236
  if (BinCreator.empty()) {
237 238 239
    cmCPackLogger(cmCPackLog::LOG_ERROR,
                  "Cannot find QtIFW compiler \"binarycreator\": "
                  "likely it is not installed, or not in your PATH"
240
                    << std::endl);
241
    return 0;
242
  }
243 244 245

  // Look 'repogen' executable (optional)

246 247
  const char* RepoGenStr = this->GetOption(RepoGenOpt);
  if (!RepoGenStr || cmSystemTools::IsNOTFOUND(RepoGenStr)) {
248
    RepoGen = "";
249
  } else {
250
    RepoGen = RepoGenStr;
251
  }
252

253
  // Framework version
254
  if (const char* FrameworkVersionSrt = this->GetOption(FrameworkVersionOpt)) {
255
    FrameworkVersion = FrameworkVersionSrt;
256
  } else {
257
    FrameworkVersion = "1.9.9";
258
  }
259

260 261 262 263 264 265 266
  // Variables that Change Behavior

  // Resolve duplicate names
  ResolveDuplicateNames = this->IsOn("CPACK_IFW_RESOLVE_DUPLICATE_NAMES");

  // Additional packages dirs
  PkgsDirsVector.clear();
267 268 269
  if (const char* dirs = this->GetOption("CPACK_IFW_PACKAGES_DIRECTORIES")) {
    cmSystemTools::ExpandListArgument(dirs, PkgsDirsVector);
  }
270

271 272 273
  // Installer
  Installer.Generator = this;
  Installer.ConfigureFromOptions();
274

275
  if (const char* ifwDownloadAll = this->GetOption("CPACK_IFW_DOWNLOAD_ALL")) {
276
    OnlineOnly = cmSystemTools::IsOn(ifwDownloadAll);
277 278
  } else if (const char* cpackDownloadAll =
               this->GetOption("CPACK_DOWNLOAD_ALL")) {
279
    OnlineOnly = cmSystemTools::IsOn(cpackDownloadAll);
280
  } else {
281
    OnlineOnly = false;
282
  }
283

284
  if (!Installer.Repositories.empty() && RepoGen.empty()) {
285 286 287 288 289
    cmCPackLogger(cmCPackLog::LOG_ERROR,
                  "Cannot find QtIFW repository generator \"repogen\": "
                  "likely it is not installed, or not in your PATH"
                    << std::endl);
    return 0;
290 291
  }

292
  // Executable suffix
293
  if (const char* optExeSuffix = this->GetOption("CMAKE_EXECUTABLE_SUFFIX")) {
294
    ExecutableSuffix = optExeSuffix;
295
    if (ExecutableSuffix.empty()) {
296
      std::string sysName(this->GetOption("CMAKE_SYSTEM_NAME"));
297
      if (sysName == "Linux") {
298 299 300
        ExecutableSuffix = ".run";
      }
    }
301
  } else {
302
    ExecutableSuffix = cmCPackGenerator::GetOutputExtension();
303
  }
304

305 306 307
  return this->Superclass::InitializeInternal();
}

308
std::string cmCPackIFWGenerator::GetComponentInstallDirNameSuffix(
309 310 311 312 313 314
  const std::string& componentName)
{
  const std::string prefix = "packages/";
  const std::string suffix = "/data";

  if (componentPackageMethod == ONE_PACKAGE) {
315
    return std::string(prefix + GetRootPackageName() + suffix);
316 317
  }

318
  return prefix + GetComponentPackageName(&Components[componentName]) + suffix;
319 320
}

321 322
cmCPackComponent* cmCPackIFWGenerator::GetComponent(
  const std::string& projectName, const std::string& componentName)
323 324
{
  ComponentsMap::iterator cit = Components.find(componentName);
325 326
  if (cit != Components.end())
    return &(cit->second);
327

328 329 330 331
  cmCPackComponent* component =
    cmCPackGenerator::GetComponent(projectName, componentName);
  if (!component)
    return component;
332 333 334

  std::string name = GetComponentPackageName(component);
  PackagesMap::iterator pit = Packages.find(name);
335 336
  if (pit != Packages.end())
    return component;
337

338
  cmCPackIFWPackage* package = &Packages[name];
339 340
  package->Name = name;
  package->Generator = this;
341
  if (package->ConfigureFromComponent(component)) {
342 343
    package->Installer = &Installer;
    Installer.Packages.insert(
344
      std::pair<std::string, cmCPackIFWPackage*>(name, package));
345
    ComponentPackages.insert(
346 347
      std::pair<cmCPackComponent*, cmCPackIFWPackage*>(component, package));
    if (component->IsDownloaded) {
348
      DownloadedPackages.insert(package);
349
    } else {
350 351
      BinaryPackages.insert(package);
    }
352
  } else {
353
    Packages.erase(name);
354 355 356 357
    cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot configure package \""
                    << name << "\" for component \"" << component->Name << "\""
                    << std::endl);
  }
358 359 360 361

  return component;
}

362 363
cmCPackComponentGroup* cmCPackIFWGenerator::GetComponentGroup(
  const std::string& projectName, const std::string& groupName)
364
{
365 366 367 368
  cmCPackComponentGroup* group =
    cmCPackGenerator::GetComponentGroup(projectName, groupName);
  if (!group)
    return group;
369 370 371

  std::string name = GetGroupPackageName(group);
  PackagesMap::iterator pit = Packages.find(name);
372 373
  if (pit != Packages.end())
    return group;
374

375
  cmCPackIFWPackage* package = &Packages[name];
376 377
  package->Name = name;
  package->Generator = this;
378
  if (package->ConfigureFromGroup(group)) {
379 380
    package->Installer = &Installer;
    Installer.Packages.insert(
381
      std::pair<std::string, cmCPackIFWPackage*>(name, package));
382
    GroupPackages.insert(
383
      std::pair<cmCPackComponentGroup*, cmCPackIFWPackage*>(group, package));
384
    BinaryPackages.insert(package);
385
  } else {
386
    Packages.erase(name);
387 388 389 390
    cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot configure package \""
                    << name << "\" for component group \"" << group->Name
                    << "\"" << std::endl);
  }
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414
  return group;
}

enum cmCPackGenerator::CPackSetDestdirSupport
cmCPackIFWGenerator::SupportsSetDestdir() const
{
  return cmCPackGenerator::SETDESTDIR_SHOULD_NOT_BE_USED;
}

bool cmCPackIFWGenerator::SupportsAbsoluteDestination() const
{
  return false;
}

bool cmCPackIFWGenerator::SupportsComponentInstallation() const
{
  return true;
}

bool cmCPackIFWGenerator::IsOnePackage() const
{
  return componentPackageMethod == ONE_PACKAGE;
}

415
std::string cmCPackIFWGenerator::GetRootPackageName()
416
{
417
  // Default value
418
  std::string name = "root";
419
  if (const char* optIFW_PACKAGE_GROUP =
420
        this->GetOption("CPACK_IFW_PACKAGE_GROUP")) {
421 422 423 424 425
    // Configure from root group
    cmCPackIFWPackage package;
    package.Generator = this;
    package.ConfigureFromGroup(optIFW_PACKAGE_GROUP);
    name = package.Name;
426 427
  } else if (const char* optIFW_PACKAGE_NAME =
               this->GetOption("CPACK_IFW_PACKAGE_NAME")) {
428 429
    // Configure from root package name
    name = optIFW_PACKAGE_NAME;
430 431
  } else if (const char* optPACKAGE_NAME =
               this->GetOption("CPACK_PACKAGE_NAME")) {
432
    // Configure from package name
433
    name = optPACKAGE_NAME;
434
  }
435 436 437
  return name;
}

438 439
std::string cmCPackIFWGenerator::GetGroupPackageName(
  cmCPackComponentGroup* group) const
440 441
{
  std::string name;
442 443 444
  if (!group)
    return name;
  if (cmCPackIFWPackage* package = GetGroupPackage(group)) {
445
    return package->Name;
446 447 448 449
  }
  const char* option =
    GetOption("CPACK_IFW_COMPONENT_GROUP_" +
              cmsys::SystemTools::UpperCase(group->Name) + "_NAME");
450
  name = option ? option : group->Name;
451
  if (group->ParentGroup) {
452 453
    cmCPackIFWPackage* package = GetGroupPackage(group->ParentGroup);
    bool dot = !ResolveDuplicateNames;
454
    if (dot && name.substr(0, package->Name.size()) == package->Name) {
455
      dot = false;
456 457
    }
    if (dot) {
458 459
      name = package->Name + "." + name;
    }
460
  }
461 462 463 464
  return name;
}

std::string cmCPackIFWGenerator::GetComponentPackageName(
465
  cmCPackComponent* component) const
466 467
{
  std::string name;
468 469 470
  if (!component)
    return name;
  if (cmCPackIFWPackage* package = GetComponentPackage(component)) {
471
    return package->Name;
472 473 474
  }
  std::string prefix = "CPACK_IFW_COMPONENT_" +
    cmsys::SystemTools::UpperCase(component->Name) + "_";
475 476
  const char* option = GetOption(prefix + "NAME");
  name = option ? option : component->Name;
477
  if (component->Group) {
478
    cmCPackIFWPackage* package = GetGroupPackage(component->Group);
479 480
    if ((componentPackageMethod == ONE_PACKAGE_PER_GROUP) ||
        IsOn(prefix + "COMMON")) {
481
      return package->Name;
482
    }
483
    bool dot = !ResolveDuplicateNames;
484
    if (dot && name.substr(0, package->Name.size()) == package->Name) {
485
      dot = false;
486 487
    }
    if (dot) {
488 489
      name = package->Name + "." + name;
    }
490
  }
491 492 493 494
  return name;
}

cmCPackIFWPackage* cmCPackIFWGenerator::GetGroupPackage(
495
  cmCPackComponentGroup* group) const
496
{
497 498
  std::map<cmCPackComponentGroup*, cmCPackIFWPackage*>::const_iterator pit =
    GroupPackages.find(group);
499 500 501 502
  return pit != GroupPackages.end() ? pit->second : 0;
}

cmCPackIFWPackage* cmCPackIFWGenerator::GetComponentPackage(
503
  cmCPackComponent* component) const
504
{
505 506
  std::map<cmCPackComponent*, cmCPackIFWPackage*>::const_iterator pit =
    ComponentPackages.find(component);
507 508
  return pit != ComponentPackages.end() ? pit->second : 0;
}
509

510
void cmCPackIFWGenerator::WriteGeneratedByToStrim(cmXMLWriter& xout)
511
{
512 513
  std::stringstream comment;
  comment << "Generated by CPack " << CMake_VERSION << " IFW generator "
514 515
          << "for QtIFW ";
  if (IsVersionLess("2.0")) {
516
    comment << "less 2.0";
517
  } else {
518
    comment << FrameworkVersion;
519
  }
520 521
  comment << " tools at " << cmTimestamp().CurrentTime("", true);
  xout.Comment(comment.str().c_str());
522
}