mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-05 21:31:08 -06:00
cmake: Add --open option for IDE generators
This commit is contained in:
@@ -96,7 +96,7 @@ _cmake()
|
||||
_filedir
|
||||
return
|
||||
;;
|
||||
--build)
|
||||
--build|--open)
|
||||
_filedir -d
|
||||
return
|
||||
;;
|
||||
|
||||
@@ -11,6 +11,7 @@ Synopsis
|
||||
cmake [<options>] (<path-to-source> | <path-to-existing-build>)
|
||||
cmake [(-D <var>=<value>)...] -P <cmake-script-file>
|
||||
cmake --build <dir> [<options>...] [-- <build-tool-options>...]
|
||||
cmake --open <dir>
|
||||
cmake -E <command> [<options>...]
|
||||
cmake --find-package <options>...
|
||||
|
||||
@@ -51,6 +52,10 @@ Options
|
||||
``--build <dir>``
|
||||
See `Build Tool Mode`_.
|
||||
|
||||
``--open <dir>``
|
||||
Open the generated project in the associated application. This is
|
||||
only supported by some generators.
|
||||
|
||||
``-N``
|
||||
View mode only.
|
||||
|
||||
|
||||
6
Help/release/dev/cmake-open.rst
Normal file
6
Help/release/dev/cmake-open.rst
Normal file
@@ -0,0 +1,6 @@
|
||||
cmake-open
|
||||
----------
|
||||
|
||||
* The :manual:`cmake(1)` ``--open <dir>`` command line option can now
|
||||
be used to open generated IDE projects like Visual Studio solutions
|
||||
or Xcode projects.
|
||||
23
Modules/CMakeFindSublimeText2.cmake
Normal file
23
Modules/CMakeFindSublimeText2.cmake
Normal file
@@ -0,0 +1,23 @@
|
||||
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
# file Copyright.txt or https://cmake.org/licensing for details.
|
||||
|
||||
|
||||
# This file is included in CMakeSystemSpecificInformation.cmake if
|
||||
# the Sublime Text 2 extra generator has been selected.
|
||||
|
||||
find_program(CMAKE_SUBLIMETEXT_EXECUTABLE
|
||||
NAMES subl3 subl sublime_text
|
||||
PATHS
|
||||
"/Applications/Sublime Text.app/Contents/SharedSupport/bin"
|
||||
"/Applications/Sublime Text 3.app/Contents/SharedSupport/bin"
|
||||
"/Applications/Sublime Text 2.app/Contents/SharedSupport/bin"
|
||||
"$ENV{HOME}/Applications/Sublime Text.app/Contents/SharedSupport/bin"
|
||||
"$ENV{HOME}/Applications/Sublime Text 3.app/Contents/SharedSupport/bin"
|
||||
"$ENV{HOME}/Applications/Sublime Text 2.app/Contents/SharedSupport/bin"
|
||||
"/opt/sublime_text"
|
||||
"/opt/sublime_text_3"
|
||||
DOC "The Sublime Text executable")
|
||||
|
||||
if(CMAKE_SUBLIMETEXT_EXECUTABLE)
|
||||
set(CMAKE_OPEN_PROJECT_COMMAND "${CMAKE_SUBLIMETEXT_EXECUTABLE} --project <PROJECT_FILE>" )
|
||||
endif()
|
||||
@@ -24,6 +24,13 @@ std::string cmExternalMakefileProjectGenerator::CreateFullGeneratorName(
|
||||
return fullName;
|
||||
}
|
||||
|
||||
bool cmExternalMakefileProjectGenerator::Open(
|
||||
const std::string& /*bindir*/, const std::string& /*projectName*/,
|
||||
bool /*dryRun*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
cmExternalMakefileProjectGeneratorFactory::
|
||||
cmExternalMakefileProjectGeneratorFactory(const std::string& n,
|
||||
const std::string& doc)
|
||||
|
||||
@@ -55,6 +55,9 @@ public:
|
||||
void SetName(const std::string& n) { Name = n; }
|
||||
std::string GetName() const { return Name; }
|
||||
|
||||
virtual bool Open(const std::string& bindir, const std::string& projectName,
|
||||
bool dryRun);
|
||||
|
||||
protected:
|
||||
///! Contains the names of the global generators support by this generator.
|
||||
std::vector<std::string> SupportedGlobalGenerators;
|
||||
|
||||
@@ -400,3 +400,26 @@ std::string cmExtraSublimeTextGenerator::ComputeDefines(
|
||||
|
||||
return definesString;
|
||||
}
|
||||
|
||||
bool cmExtraSublimeTextGenerator::Open(const std::string& bindir,
|
||||
const std::string& projectName,
|
||||
bool dryRun)
|
||||
{
|
||||
const char* sublExecutable =
|
||||
this->GlobalGenerator->GetCMakeInstance()->GetCacheDefinition(
|
||||
"CMAKE_SUBLIMETEXT_EXECUTABLE");
|
||||
if (!sublExecutable) {
|
||||
return false;
|
||||
}
|
||||
if (cmSystemTools::IsNOTFOUND(sublExecutable)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string filename = bindir + "/" + projectName + ".sublime-project";
|
||||
if (dryRun) {
|
||||
return cmSystemTools::FileExists(filename, true);
|
||||
}
|
||||
|
||||
return cmSystemTools::RunSingleCommand(
|
||||
{ sublExecutable, "--project", filename });
|
||||
}
|
||||
|
||||
@@ -65,6 +65,9 @@ private:
|
||||
std::string ComputeDefines(cmSourceFile* source, cmLocalGenerator* lg,
|
||||
cmGeneratorTarget* gtgt);
|
||||
|
||||
bool Open(const std::string& bindir, const std::string& projectName,
|
||||
bool dryRun) override;
|
||||
|
||||
bool ExcludeBuildFolder;
|
||||
std::string EnvSettings;
|
||||
};
|
||||
|
||||
@@ -1824,6 +1824,16 @@ int cmGlobalGenerator::Build(const std::string& /*unused*/,
|
||||
return retVal;
|
||||
}
|
||||
|
||||
bool cmGlobalGenerator::Open(const std::string& bindir,
|
||||
const std::string& projectName, bool dryRun)
|
||||
{
|
||||
if (this->ExtraGenerator) {
|
||||
return this->ExtraGenerator->Open(bindir, projectName, dryRun);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string cmGlobalGenerator::GenerateCMakeBuildCommand(
|
||||
const std::string& target, const std::string& config,
|
||||
const std::string& native, bool ignoreErrors)
|
||||
|
||||
@@ -162,6 +162,12 @@ public:
|
||||
std::vector<std::string> const& nativeOptions =
|
||||
std::vector<std::string>());
|
||||
|
||||
/**
|
||||
* Open a generated IDE project given the following information.
|
||||
*/
|
||||
virtual bool Open(const std::string& bindir, const std::string& projectName,
|
||||
bool dryRun);
|
||||
|
||||
virtual void GenerateBuildCommand(
|
||||
std::vector<std::string>& makeCommand, const std::string& makeProgram,
|
||||
const std::string& projectName, const std::string& projectDir,
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
#include "cmGlobalVisualStudioGenerator.h"
|
||||
|
||||
#include "cmsys/Encoding.hxx"
|
||||
#include <future>
|
||||
#include <iostream>
|
||||
#include <objbase.h>
|
||||
#include <shellapi.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "cmAlgorithms.h"
|
||||
@@ -928,3 +931,33 @@ void cmGlobalVisualStudioGenerator::AddSymbolExportCommand(
|
||||
commandLines, "Auto build dll exports", ".");
|
||||
commands.push_back(command);
|
||||
}
|
||||
|
||||
static bool OpenSolution(std::string sln)
|
||||
{
|
||||
HRESULT comInitialized =
|
||||
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
|
||||
if (FAILED(comInitialized)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HINSTANCE hi =
|
||||
ShellExecuteA(NULL, "open", sln.c_str(), NULL, NULL, SW_SHOWNORMAL);
|
||||
|
||||
CoUninitialize();
|
||||
|
||||
return reinterpret_cast<intptr_t>(hi) > 32;
|
||||
}
|
||||
|
||||
bool cmGlobalVisualStudioGenerator::Open(const std::string& bindir,
|
||||
const std::string& projectName,
|
||||
bool dryRun)
|
||||
{
|
||||
std::string buildDir = cmSystemTools::ConvertToOutputPath(bindir.c_str());
|
||||
std::string sln = buildDir + "\\" + projectName + ".sln";
|
||||
|
||||
if (dryRun) {
|
||||
return cmSystemTools::FileExists(sln, true);
|
||||
}
|
||||
|
||||
return std::async(std::launch::async, OpenSolution, sln).get();
|
||||
}
|
||||
|
||||
@@ -131,6 +131,9 @@ public:
|
||||
std::vector<cmCustomCommand>& commands,
|
||||
std::string const& configName);
|
||||
|
||||
bool Open(const std::string& bindir, const std::string& projectName,
|
||||
bool dryRun) override;
|
||||
|
||||
protected:
|
||||
virtual void AddExtraIDETargets();
|
||||
|
||||
|
||||
@@ -35,6 +35,11 @@
|
||||
|
||||
struct cmLinkImplementation;
|
||||
|
||||
#if defined(CMAKE_BUILD_WITH_CMAKE) && defined(__APPLE__)
|
||||
#define HAVE_APPLICATION_SERVICES
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#endif
|
||||
|
||||
#if defined(CMAKE_BUILD_WITH_CMAKE)
|
||||
#include "cmXMLParser.h"
|
||||
|
||||
@@ -287,6 +292,35 @@ void cmGlobalXCodeGenerator::EnableLanguage(
|
||||
this->ComputeArchitectures(mf);
|
||||
}
|
||||
|
||||
bool cmGlobalXCodeGenerator::Open(const std::string& bindir,
|
||||
const std::string& projectName, bool dryRun)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
#ifdef HAVE_APPLICATION_SERVICES
|
||||
std::string url = bindir + "/" + projectName + ".xcodeproj";
|
||||
|
||||
if (dryRun) {
|
||||
return cmSystemTools::FileExists(url, false);
|
||||
}
|
||||
|
||||
CFStringRef cfStr = CFStringCreateWithCString(
|
||||
kCFAllocatorDefault, url.c_str(), kCFStringEncodingUTF8);
|
||||
if (cfStr) {
|
||||
CFURLRef cfUrl = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, cfStr,
|
||||
kCFURLPOSIXPathStyle, true);
|
||||
if (cfUrl) {
|
||||
OSStatus err = LSOpenCFURLRef(cfUrl, nullptr);
|
||||
ret = err == noErr;
|
||||
CFRelease(cfUrl);
|
||||
}
|
||||
CFRelease(cfStr);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void cmGlobalXCodeGenerator::GenerateBuildCommand(
|
||||
std::vector<std::string>& makeCommand, const std::string& makeProgram,
|
||||
const std::string& projectName, const std::string& /*projectDir*/,
|
||||
|
||||
@@ -55,6 +55,13 @@ public:
|
||||
*/
|
||||
void EnableLanguage(std::vector<std::string> const& languages, cmMakefile*,
|
||||
bool optional) override;
|
||||
|
||||
/**
|
||||
* Open a generated IDE project given the following information.
|
||||
*/
|
||||
bool Open(const std::string& bindir, const std::string& projectName,
|
||||
bool dryRun) override;
|
||||
|
||||
/**
|
||||
* Try running cmake and building a file. This is used for dynalically
|
||||
* loaded commands, not as part of the usual build process.
|
||||
|
||||
@@ -2425,6 +2425,49 @@ int cmake::Build(const std::string& dir, const std::string& target,
|
||||
nativeOptions);
|
||||
}
|
||||
|
||||
bool cmake::Open(const std::string& dir, bool dryRun)
|
||||
{
|
||||
this->SetHomeDirectory("");
|
||||
this->SetHomeOutputDirectory("");
|
||||
if (!cmSystemTools::FileIsDirectory(dir)) {
|
||||
std::cerr << "Error: " << dir << " is not a directory\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string cachePath = FindCacheFile(dir);
|
||||
if (!this->LoadCache(cachePath)) {
|
||||
std::cerr << "Error: could not load cache\n";
|
||||
return false;
|
||||
}
|
||||
const char* genName = this->State->GetCacheEntryValue("CMAKE_GENERATOR");
|
||||
if (!genName) {
|
||||
std::cerr << "Error: could not find CMAKE_GENERATOR in Cache\n";
|
||||
return false;
|
||||
}
|
||||
const char* extraGenName =
|
||||
this->State->GetInitializedCacheValue("CMAKE_EXTRA_GENERATOR");
|
||||
std::string fullName =
|
||||
cmExternalMakefileProjectGenerator::CreateFullGeneratorName(
|
||||
genName, extraGenName ? extraGenName : "");
|
||||
|
||||
std::unique_ptr<cmGlobalGenerator> gen(
|
||||
this->CreateGlobalGenerator(fullName));
|
||||
if (!gen.get()) {
|
||||
std::cerr << "Error: could create CMAKE_GENERATOR \"" << fullName
|
||||
<< "\"\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* cachedProjectName =
|
||||
this->State->GetCacheEntryValue("CMAKE_PROJECT_NAME");
|
||||
if (!cachedProjectName) {
|
||||
std::cerr << "Error: could not find CMAKE_PROJECT_NAME in Cache\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
return gen->Open(dir, cachedProjectName, dryRun);
|
||||
}
|
||||
|
||||
void cmake::WatchUnusedCli(const std::string& var)
|
||||
{
|
||||
#ifdef CMAKE_BUILD_WITH_CMAKE
|
||||
|
||||
@@ -401,6 +401,9 @@ public:
|
||||
const std::string& config,
|
||||
const std::vector<std::string>& nativeOptions, bool clean);
|
||||
|
||||
///! run the --open option
|
||||
bool Open(const std::string& dir, bool dryRun);
|
||||
|
||||
void UnwatchUnusedCli(const std::string& var);
|
||||
void WatchUnusedCli(const std::string& var);
|
||||
|
||||
|
||||
@@ -66,6 +66,7 @@ static const char* cmDocumentationOptions[][2] = {
|
||||
{ "-E", "CMake command mode." },
|
||||
{ "-L[A][H]", "List non-advanced cached variables." },
|
||||
{ "--build <dir>", "Build a CMake-generated project binary tree." },
|
||||
{ "--open <dir>", "Open generated project in the associated application." },
|
||||
{ "-N", "View mode only." },
|
||||
{ "-P <file>", "Process script mode." },
|
||||
{ "--find-package", "Run in pkg-config like mode." },
|
||||
@@ -100,6 +101,7 @@ static int do_command(int ac, char const* const* av)
|
||||
|
||||
int do_cmake(int ac, char const* const* av);
|
||||
static int do_build(int ac, char const* const* av);
|
||||
static int do_open(int ac, char const* const* av);
|
||||
|
||||
static cmMakefile* cmakemainGetMakefile(void* clientdata)
|
||||
{
|
||||
@@ -186,6 +188,9 @@ int main(int ac, char const* const* av)
|
||||
if (strcmp(av[1], "--build") == 0) {
|
||||
return do_build(ac, av);
|
||||
}
|
||||
if (strcmp(av[1], "--open") == 0) {
|
||||
return do_open(ac, av);
|
||||
}
|
||||
if (strcmp(av[1], "-E") == 0) {
|
||||
return do_command(ac, av);
|
||||
}
|
||||
@@ -423,3 +428,41 @@ static int do_build(int ac, char const* const* av)
|
||||
return cm.Build(dir, target, config, nativeOptions, clean);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int do_open(int ac, char const* const* av)
|
||||
{
|
||||
#ifndef CMAKE_BUILD_WITH_CMAKE
|
||||
std::cerr << "This cmake does not support --open\n";
|
||||
return -1;
|
||||
#else
|
||||
std::string dir;
|
||||
|
||||
enum Doing
|
||||
{
|
||||
DoingNone,
|
||||
DoingDir,
|
||||
};
|
||||
Doing doing = DoingDir;
|
||||
for (int i = 2; i < ac; ++i) {
|
||||
switch (doing) {
|
||||
case DoingDir:
|
||||
dir = cmSystemTools::CollapseFullPath(av[i]);
|
||||
doing = DoingNone;
|
||||
break;
|
||||
default:
|
||||
std::cerr << "Unknown argument " << av[i] << std::endl;
|
||||
dir.clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (dir.empty()) {
|
||||
std::cerr << "Usage: cmake --open <dir>\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
cmake cm(cmake::RoleInternal);
|
||||
cmSystemTools::SetMessageCallback(cmakemainMessageCallback, &cm);
|
||||
cm.SetProgressCallback(cmakemainProgressCallback, &cm);
|
||||
return cm.Open(dir, false) ? 0 : 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user