try_compile: Add option to control type of target
Create a `CMAKE_TRY_COMPILE_TARGET_TYPE` option to specify use of `add_library(... STATIC ...)` for the generated test project. This will be useful for cross-compiling toolchains that cannot link a binary without custom flags or scripts.
This commit is contained in:
parent
509b1f08ea
commit
7f1bd9fe69
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
|
@ -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.
|
|
@ -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);
|
||||
}
|
||||
|
||||
/* 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());
|
||||
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 = "/";
|
||||
tmpOutputFile += targetName;
|
||||
tmpOutputFile +=this->Makefile->GetSafeDefinition("CMAKE_EXECUTABLE_SUFFIX");
|
||||
if (targetType == cmState::EXECUTABLE)
|
||||
{
|
||||
tmpOutputFile += targetName;
|
||||
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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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()
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -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\)
|
|
@ -0,0 +1,2 @@
|
|||
set(CMAKE_TRY_COMPILE_TARGET_TYPE INVALID)
|
||||
try_compile(result ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src.c)
|
|
@ -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()
|
|
@ -0,0 +1 @@
|
|||
int other(void) { return 0; }
|
Loading…
Reference in New Issue