[CMake] Add linker command file to object files
Michael Hertling
mhertling at online.de
Wed Jul 13 19:25:59 EDT 2011
On 07/13/2011 10:56 AM, Florian Reinhard wrote:
> Hi!
>
> Problem:
> I need to have a linker command file among the list of object files in
> a fixed order.
>
> Setup:
> Cmake 2.8.5
> custom non-gnu texas instruments cl6x toolchain
>
> Ideas:
> I figured that the object files list which one specifies as <objects>
> in CMAKE_C_LINK_EXECUTABLE are sorted in the way they are fed to
> "add_executable". So maybe one could treat a linker.cmd file as some
> fake object file?
>
> Thank you,
>
> Florian
The easiest workaround I know is to copy/symlink the linker.cmd file to
linker.cmd${CMAKE_C_OUTPUT_EXTENSION} via a custom command and mention
the result explicitly in ADD_EXECUTABLE(), e.g.:
CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
PROJECT(LINKERCOMMAND C)
SET(CMAKE_VERBOSE_MAKEFILE ON)
ADD_CUSTOM_COMMAND(
OUTPUT linker.cmd${CMAKE_C_OUTPUT_EXTENSION}
COMMAND ${CMAKE_COMMAND} -E create_symlink
${CMAKE_SOURCE_DIR}/linker.cmd
linker.cmd${CMAKE_C_OUTPUT_EXTENSION})
FILE(WRITE ${CMAKE_BINARY_DIR}/main.c "int main(void){return 0;}\n")
ADD_EXECUTABLE(main main.c linker.cmd${CMAKE_C_OUTPUT_EXTENSION})
Usually, I'd set the EXTERNAL_OBJECT source file property on linker.cmd
to TRUE and expect that it can be mentioned immediately among main's
sources, i.e.
SET_SOURCE_FILES_PROPERTIES(${CMAKE_SOURCE_DIR}/linker.cmd
PROPERTIES EXTERNAL_OBJECT TRUE)
...
ADD_EXECUTABLE(main main.c linker.cmd)
but this doesn't make linker.cmd appear in the linker command line.
AFAICS, the code in question resides in cmMakefileTargetGenerator::
WriteTargetBuildRules() from Source/cmMakefileTargetGenerator.cxx:
if(!this->GlobalGenerator->IgnoreFile
((*source)->GetExtension().c_str()))
{
// Generate this object file's rule file.
this->WriteObjectRuleFiles(*(*source));
}
else if((*source)->GetPropertyAsBool("EXTERNAL_OBJECT"))
{
// This is an external object file. Just add it.
this->ExternalObjects.push_back((*source)->GetFullPath());
}
else ...
This means that a source file can be added to the target's external
objects only if it's classified as "ignored" by cmGlobalGenerator::
IgnoreFile() from Source/cmGlobalGenerator.cxx:
bool cmGlobalGenerator::IgnoreFile(const char* l)
{
if(this->GetLanguageFromExtension(l))
{
return false;
}
return (this->IgnoreExtensions.count(l) > 0);
}
The only possibility for this function to return true - and, thus, the
concerned file to be checked for the EXTERNAL_OBJECT property - is the
extension's appearance in the cmGlobalGenerator::IgnoreExtensions map,
but the latter is initialized once from CMAKE_<LANG>_IGNORE_EXTENSIONS
when the project's languages are enabled, and later changes don't have
any effect. Furthermore, CMAKE_<LANG>_IGNORE_EXTENSIONS is initialized
in Modules/CMake<LANG>Compiler.cmake.in without any user-accessible
parameter, so there's no chance to add an additional extension to
be ignored and the respective file subsequently checked for the
EXTERNAL_OBJECT property, if I'm not mistaken.
Hence, my question to the CMake developers: Is this behavior intended,
or should the check for the EXTERNAL_OBJECT property take precedence
over the examination of the source file's extension, i.e.:
if((*source)->GetPropertyAsBool("EXTERNAL_OBJECT"))
{
// This is an external object file. Just add it.
this->ExternalObjects.push_back((*source)->GetFullPath());
}
else if(!this->GlobalGenerator->IgnoreFile
((*source)->GetExtension().c_str()))
{
// Generate this object file's rule file.
this->WriteObjectRuleFiles(*(*source));
}
else ...
In this manner, a file marked as EXTERNAL_OBJECT appears in the linker
command in any case, which is, IMO, what the user does expect from the
EXTERNAL_OBJECT property's documentation. Alternatively, there should
be a possibility to enhance the list of extensions to be ignored, so
cmGlobalGenerator::IgnoreFile() can return true for a user-specified
file extension, or do I miss something? Of course, any comments are
greatly appreciated.
Regards,
Michael
More information about the CMake
mailing list