Commit e3b1bdb0 authored by Brad King's avatar Brad King
Browse files

ENH: Support exporting/importing of AppBundle targets.

  - Imported bundles have the MACOSX_BUNDLE property set
  - Added cmTarget::IsAppBundleOnApple method to simplify checks
  - Document BUNDLE keyword in INSTALL command
  - Updated IMPORTED_LOCATION property documentation for bundles
  - Updated ExportImport test to test bundles
parent 437043bb
......@@ -84,6 +84,11 @@ cmExportBuildFileGenerator
std::string prop = "IMPORTED_LOCATION";
prop += suffix;
std::string value = target->GetFullPath(config, false);
if(target->IsAppBundleOnApple())
{
value += ".app/Contents/MacOS/";
value += target->GetFullName(config, false);
}
properties[prop] = value;
}
......
......@@ -282,14 +282,19 @@ cmExportFileGenerator
<< " PROPERTY ENABLE_EXPORTS 1)\n";
}
// Mark the imported framework. This is done even on non-Apple
// platforms for reference and consistency purposes.
if(target->GetType() == cmTarget::SHARED_LIBRARY &&
target->GetPropertyAsBool("FRAMEWORK"))
// Mark the imported library if it is a framework.
if(target->IsFrameworkOnApple())
{
os << "SET_PROPERTY(TARGET " << targetName
<< " PROPERTY FRAMEWORK 1)\n";
}
// Mark the imported executable if it is an application bundle.
if(target->IsAppBundleOnApple())
{
os << "SET_PROPERTY(TARGET " << targetName
<< " PROPERTY MACOSX_BUNDLE 1)\n";
}
os << "\n";
}
......
......@@ -160,8 +160,8 @@ cmExportInstallFileGenerator
te->RuntimeGenerator, properties);
this->SetImportLocationProperty(config, suffix,
te->FrameworkGenerator, properties);
// TODO: Bundles?
this->SetImportLocationProperty(config, suffix,
te->BundleGenerator, properties);
// If any file location was set for the target add it to the
// import file.
......@@ -227,12 +227,17 @@ cmExportInstallFileGenerator
std::string fname = itgen->GetInstallFilename(config);
value += fname;
// Fix name for frameworks.
// Fix name for frameworks and bundles.
if(itgen->GetTarget()->IsFrameworkOnApple())
{
value += ".framework/";
value += fname;
}
else if(itgen->GetTarget()->IsAppBundleOnApple())
{
value += ".app/Contents/MacOS/";
value += fname;
}
// Store the property.
properties[prop] = value;
......
......@@ -451,9 +451,9 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
break;
case cmTarget::EXECUTABLE:
{
// Executables use the RUNTIME properties.
if(target.GetPropertyAsBool("MACOSX_BUNDLE"))
if(target.IsAppBundleOnApple())
{
// Application bundles use the BUNDLE properties.
if (!bundleArgs.GetDestination().empty())
{
bundleGenerator = CreateInstallTargetGenerator(target, bundleArgs,
......@@ -470,6 +470,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
}
else
{
// Executables use the RUNTIME properties.
if (!runtimeArgs.GetDestination().empty())
{
runtimeGenerator = CreateInstallTargetGenerator(target,
......
......@@ -99,7 +99,7 @@ public:
"\n"
"The TARGETS signature:\n"
" install(TARGETS targets... [EXPORT <export-name>]\n"
" [[ARCHIVE|LIBRARY|RUNTIME|FRAMEWORK]\n"
" [[ARCHIVE|LIBRARY|RUNTIME|FRAMEWORK|BUNDLE]\n"
" [DESTINATION <dir>]\n"
" [PERMISSIONS permissions...]\n"
" [CONFIGURATIONS [Debug|Release|...]]\n"
......@@ -107,10 +107,12 @@ public:
" [OPTIONAL]\n"
" ] [...])\n"
"The TARGETS form specifies rules for installing targets from a "
"project. There are four kinds of target files that may be "
"installed: archive, library, runtime, and framework. "
"project. There are five kinds of target files that may be "
"installed: archive, library, runtime, framework, and bundle. "
"Executables are always treated as runtime targets. "
"Executables are treated as runtime targets, except that those "
"marked with the MACOSX_BUNDLE property are treated as bundle "
"targets on OS X. "
"Static libraries are always treated as archive targets. "
"Module libraries are always treated as library targets. "
"For non-DLL platforms shared libraries are treated as library "
......
......@@ -176,8 +176,7 @@ cmInstallTargetGenerator
from1 += targetName;
// Handle OSX Bundles.
if(this->Target->GetMakefile()->IsOn("APPLE") &&
this->Target->GetPropertyAsBool("MACOSX_BUNDLE"))
if(this->Target->IsAppBundleOnApple())
{
// Compute the source locations of the bundle executable and
// Info.plist file.
......
......@@ -205,6 +205,8 @@ void cmTarget::DefineProperties(cmake *cm)
"Full path to the main file on disk for an IMPORTED target.",
"Specifies the location of an IMPORTED target file on disk. "
"For executables this is the location of the executable file. "
"For bundles on OS X this is the location of the executable file "
"inside Contents/MacOS under the application bundle folder. "
"For static libraries and modules this is the location of the "
"library or module. "
"For shared libraries on non-DLL platforms this is the location of "
......@@ -605,6 +607,14 @@ bool cmTarget::IsFrameworkOnApple()
this->GetPropertyAsBool("FRAMEWORK"));
}
//----------------------------------------------------------------------------
bool cmTarget::IsAppBundleOnApple()
{
return (this->GetType() == cmTarget::EXECUTABLE &&
this->Makefile->IsOn("APPLE") &&
this->GetPropertyAsBool("MACOSX_BUNDLE"));
}
//----------------------------------------------------------------------------
class cmTargetTraceDependencies
{
......
......@@ -324,6 +324,9 @@ public:
Apple. */
bool IsFrameworkOnApple();
/** Return whether this target is an executable Bundle on Apple. */
bool IsAppBundleOnApple();
private:
/**
* A list of direct dependencies. Use in conjunction with DependencyMap.
......
......@@ -21,14 +21,18 @@ add_library(testLib3 SHARED testLib3.c)
add_library(testLib4 SHARED testLib4.c)
set_property(TARGET testLib4 PROPERTY FRAMEWORK 1)
add_executable(testExe3 testExe3.c)
set_property(TARGET testExe3 PROPERTY MACOSX_BUNDLE 1)
# Install and export from install tree.
install(
TARGETS testExe1 testLib1 testLib2 testExe2 testLib3 testLib4
TARGETS testExe1 testLib1 testLib2 testExe2 testLib3 testLib4 testExe3
EXPORT exp
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
FRAMEWORK DESTINATION Frameworks
BUNDLE DESTINATION Applications
)
install(EXPORT exp NAMESPACE exp_ DESTINATION lib/exp)
......@@ -37,7 +41,7 @@ export(TARGETS testExe1 testLib1 testLib2
NAMESPACE bld_
FILE ExportBuildTree.cmake
)
export(TARGETS testExe2 testLib3 testLib4
export(TARGETS testExe2 testLib3 testLib4 testExe3
NAMESPACE bld_
APPEND FILE ExportBuildTree.cmake
)
#include <stdio.h>
int main(int argc, const char* argv[])
{
if(argc < 2)
{
fprintf(stderr, "Must specify output file.\n");
return 1;
}
{
FILE* f = fopen(argv[1], "w");
if(f)
{
fprintf(f, "int generated_by_testExe3() { return 0; }\n");
fclose(f);
}
else
{
fprintf(stderr, "Error writing to %s\n", argv[1]);
return 1;
}
}
return 0;
}
......@@ -17,10 +17,16 @@ add_custom_command(
COMMAND exp_testExe1 ${Import_BINARY_DIR}/exp_generated.c
DEPENDS exp_testExe1
)
add_custom_command(
OUTPUT ${Import_BINARY_DIR}/exp_generated3.c
COMMAND exp_testExe3 ${Import_BINARY_DIR}/exp_generated3.c
DEPENDS exp_testExe3
)
add_executable(imp_testExe1
imp_testExe1.c
${Import_BINARY_DIR}/exp_generated.c
${Import_BINARY_DIR}/exp_generated3.c
)
# Try linking to a library imported from the install tree.
......@@ -36,10 +42,16 @@ add_custom_command(
COMMAND bld_testExe1 ${Import_BINARY_DIR}/bld_generated.c
DEPENDS bld_testExe1
)
add_custom_command(
OUTPUT ${Import_BINARY_DIR}/bld_generated3.c
COMMAND bld_testExe3 ${Import_BINARY_DIR}/bld_generated3.c
DEPENDS bld_testExe3
)
add_executable(imp_testExe1b
imp_testExe1.c
${Import_BINARY_DIR}/bld_generated.c
${Import_BINARY_DIR}/bld_generated3.c
)
# Try linking to a library imported from the build tree.
......
extern int generated_by_testExe1();
extern int generated_by_testExe3();
extern int testLib2();
extern int testLib3();
extern int testLib4();
int main()
{
return testLib2() + generated_by_testExe1() + testLib3() + testLib4();
return (testLib2() + generated_by_testExe1() + testLib3() + testLib4()
+ generated_by_testExe3());
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment