Merge topic 'try_compile-target-type'

7f1bd9fe try_compile: Add option to control type of target
This commit is contained in:
Brad King 2016-02-26 10:31:28 -05:00 committed by CMake Topic Stage
commit 79d4b5bec9
15 changed files with 136 additions and 15 deletions

View File

@ -112,3 +112,6 @@ The current setting of :policy:`CMP0065` is set in the generated project.
Set the :variable:`CMAKE_TRY_COMPILE_CONFIGURATION` variable to choose
a build configuration.
Set the :variable:`CMAKE_TRY_COMPILE_TARGET_TYPE` variable to specify
the type of target used for the source file signature.

View File

@ -292,6 +292,7 @@ Variables that Control the Build
/variable/CMAKE_STATIC_LINKER_FLAGS_CONFIG
/variable/CMAKE_STATIC_LINKER_FLAGS
/variable/CMAKE_TRY_COMPILE_CONFIGURATION
/variable/CMAKE_TRY_COMPILE_TARGET_TYPE
/variable/CMAKE_USE_RELATIVE_PATHS
/variable/CMAKE_VISIBILITY_INLINES_HIDDEN
/variable/CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD

View File

@ -0,0 +1,8 @@
try_compile-target-type
-----------------------
* The :command:`try_compile` command learned to check a new
:variable:`CMAKE_TRY_COMPILE_TARGET_TYPE` variable to optionally
build a static library instead of an executable. This is useful
for cross-compiling toolchains that cannot link binaries without
custom flags or scripts.

View File

@ -0,0 +1,15 @@
CMAKE_TRY_COMPILE_TARGET_TYPE
-----------------------------
Type of target generated for :command:`try_compile` calls using the
source file signature. Valid values are:
``EXECUTABLE``
Use :command:`add_executable` to name the source file in the
generated project. This is the default if no value is given.
``STATIC_LIBRARY``
Use :command:`add_library` with the ``STATIC`` option to name the
source file in the generated project. This avoids running the
linker and is intended for use with cross-compiling toolchains
that cannot link without custom flags or linker scripts.

View File

@ -19,13 +19,42 @@
#include <assert.h>
int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv)
int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
bool isTryRun)
{
this->BinaryDirectory = argv[1].c_str();
this->OutputFile = "";
// which signature were we called with ?
this->SrcFileSignature = true;
cmState::TargetType targetType = cmState::EXECUTABLE;
const char* tt =
this->Makefile->GetDefinition("CMAKE_TRY_COMPILE_TARGET_TYPE");
if (!isTryRun && tt && *tt)
{
if (strcmp(tt, cmState::GetTargetTypeName(cmState::EXECUTABLE)) == 0)
{
targetType = cmState::EXECUTABLE;
}
else if (strcmp(tt,
cmState::GetTargetTypeName(cmState::STATIC_LIBRARY)) == 0)
{
targetType = cmState::STATIC_LIBRARY;
}
else
{
this->Makefile->IssueMessage(
cmake::FATAL_ERROR,
std::string("Invalid value '") + tt + "' for "
"CMAKE_TRY_COMPILE_TARGET_TYPE. Only "
"'" + cmState::GetTargetTypeName(cmState::EXECUTABLE) + "' and "
"'" + cmState::GetTargetTypeName(cmState::STATIC_LIBRARY) + "' "
"are allowed."
);
return -1;
}
}
const char* sourceDirectory = argv[2].c_str();
const char* projectName = 0;
std::string targetName;
@ -486,11 +515,22 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv)
fprintf(fout, "set(CMAKE_ENABLE_EXPORTS %s)\n", ee);
}
if (targetType == cmState::EXECUTABLE)
{
/* Put the executable at a known location (for COPY_FILE). */
fprintf(fout, "set(CMAKE_RUNTIME_OUTPUT_DIRECTORY \"%s\")\n",
this->BinaryDirectory.c_str());
/* Create the actual executable. */
fprintf(fout, "add_executable(%s", targetName.c_str());
}
else // if (targetType == cmState::STATIC_LIBRARY)
{
/* Put the static library at a known location (for COPY_FILE). */
fprintf(fout, "set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY \"%s\")\n",
this->BinaryDirectory.c_str());
/* Create the actual static library. */
fprintf(fout, "add_library(%s STATIC", targetName.c_str());
}
for(std::vector<std::string>::iterator si = sources.begin();
si != sources.end(); ++si)
{
@ -549,7 +589,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv)
if (this->SrcFileSignature)
{
std::string copyFileErrorMessage;
this->FindOutputFile(targetName);
this->FindOutputFile(targetName, targetType);
if ((res==0) && !copyFile.empty())
{
@ -651,13 +691,26 @@ void cmCoreTryCompile::CleanupFiles(const char* binDir)
}
}
void cmCoreTryCompile::FindOutputFile(const std::string& targetName)
void cmCoreTryCompile::FindOutputFile(const std::string& targetName,
cmState::TargetType targetType)
{
this->FindErrorMessage = "";
this->OutputFile = "";
std::string tmpOutputFile = "/";
if (targetType == cmState::EXECUTABLE)
{
tmpOutputFile += targetName;
tmpOutputFile +=this->Makefile->GetSafeDefinition("CMAKE_EXECUTABLE_SUFFIX");
tmpOutputFile +=
this->Makefile->GetSafeDefinition("CMAKE_EXECUTABLE_SUFFIX");
}
else // if (targetType == cmState::STATIC_LIBRARY)
{
tmpOutputFile +=
this->Makefile->GetSafeDefinition("CMAKE_STATIC_LIBRARY_PREFIX");
tmpOutputFile += targetName;
tmpOutputFile +=
this->Makefile->GetSafeDefinition("CMAKE_STATIC_LIBRARY_SUFFIX");
}
// a list of directories where to search for the compilation result
// at first directly in the binary dir

View File

@ -30,7 +30,7 @@ public:
* commands, such as TryRun can access the same logic without
* duplication.
*/
int TryCompileCode(std::vector<std::string> const& argv);
int TryCompileCode(std::vector<std::string> const& argv, bool isTryRun);
/**
* This deletes all the files created by TryCompileCode.
@ -44,8 +44,8 @@ public:
TryCompileCode. The result is stored in OutputFile. If nothing is found,
the error message is stored in FindErrorMessage.
*/
void FindOutputFile(const std::string& targetName);
void FindOutputFile(const std::string& targetName,
cmState::TargetType targetType);
cmTypeMacro(cmCoreTryCompile, cmCommand);

View File

@ -28,7 +28,7 @@ bool cmTryCompileCommand
return false;
}
this->TryCompileCode(argv);
this->TryCompileCode(argv, false);
// if They specified clean then we clean up what we can
if (this->SrcFileSignature)

View File

@ -135,7 +135,7 @@ bool cmTryRunCommand
this->CompileResultVariable = argv[1];
// do the try compile
int res = this->TryCompileCode(tryCompile);
int res = this->TryCompileCode(tryCompile, true);
// now try running the command if it compiled
if (!res)

View File

@ -16,6 +16,10 @@ run_cmake(BadSources2)
run_cmake(NonSourceCopyFile)
run_cmake(NonSourceCompileDefinitions)
run_cmake(TargetTypeExe)
run_cmake(TargetTypeInvalid)
run_cmake(TargetTypeStatic)
run_cmake(CMP0056)
if(RunCMake_GENERATOR MATCHES "Make|Ninja")

View File

@ -0,0 +1,14 @@
enable_language(C)
set(CMAKE_TRY_COMPILE_TARGET_TYPE EXECUTABLE)
try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.c
OUTPUT_VARIABLE out
COPY_FILE ${CMAKE_CURRENT_BINARY_DIR}/copy
COPY_FILE_ERROR copy_err
)
if(NOT result)
message(FATAL_ERROR "try_compile failed:\n${out}")
endif()
if(copy_err)
message(FATAL_ERROR "try_compile COPY_FILE failed:\n${copy_err}")
endif()

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,5 @@
^CMake Error at TargetTypeInvalid.cmake:2 \(try_compile\):
Invalid value 'INVALID' for CMAKE_TRY_COMPILE_TARGET_TYPE. Only
'EXECUTABLE' and 'STATIC_LIBRARY' are allowed.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)

View File

@ -0,0 +1,2 @@
set(CMAKE_TRY_COMPILE_TARGET_TYPE INVALID)
try_compile(result ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src.c)

View File

@ -0,0 +1,14 @@
enable_language(C)
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/other.c
OUTPUT_VARIABLE out
COPY_FILE ${CMAKE_CURRENT_BINARY_DIR}/copy
COPY_FILE_ERROR copy_err
)
if(NOT result)
message(FATAL_ERROR "try_compile failed:\n${out}")
endif()
if(copy_err)
message(FATAL_ERROR "try_compile COPY_FILE failed:\n${copy_err}")
endif()

View File

@ -0,0 +1 @@
int other(void) { return 0; }