Forcing CMake to output link.txt for executable?

I was developing a project of mine on Ubuntu 22, with:

$ cmake --version | head -1
cmake version 3.22.1

I noticed there, that there is a link.txt for both of my executables from the project, as well as for many other libraries; from the project’s build folder there, I can count:

build$ find . -name link.txt | wc -l
21

… 21 such link.txt files, after project is fully built.

So, I made a CMake custom command that utilizes this link.txt file (changes few parameters, and repeats linking in POST_BUILD step) and all was good and worked fine. Unfortunately, not for long.

Then I moved the project to Windows 10, MINGW64 shell - and suddenly the above custom command started failing; there I use:

$ /c/Program\ Files/CMake/bin/cmake.exe --version | head -1
cmake version 3.17.5

Looking further, I realized that there are no link.txt generated for my executables, however, there are link.txt for some supporting libraries; there, from the build folder, I can count:

$ find . -name link.txt | wc -l
10

… 10 link.txt files, after project is fully built - a lot fewer than 21 link.txt files for the exact same project building on Ubuntu with cmake 3.22.1

So, what is going on here, why the discrepancy? And how can I persuade CMake 3.17.5 on Windows 10 (or possibly other 3.1x versions) to also output all these link.txt files, especially for my executable, as CMake 3.22.1 on Ubuntu 22 does?

EDIT:

Some more stuff that I found:

  • link.txt files seem to be generated by the cmake ../ call
  • I’ve installed CMake 3.22.1 also on Windows, and no difference in respect to link.txt behavior - so the CMake version is not a problem, there is some intrinsic difference between Linux (Unix Makefile) and Windows (MSYS Makefile) setups, I guess
  • In Windows, in build/CMakeFiles/${PROJECT_NAME}.dir/ there is only a build.make, which has no mentions of link.txt, but has the complete linker command line. In Ubuntu, in build/CMakeFiles/${PROJECT_NAME}.dir/ there are both link.txt (with the complete linker command line) and build.make (which contains references to link.txt, but no complete linker command line).

Why cannot software ever be consistent, for crying out loud?

Is the creation of link.txt documented? I don’t think so, it’s an implementation detail.
The creation may depend on multiple things, most importantly it may be created that way only for make generators.

And in your case, I guess it depends on the command line length limit of your OS and the paths that you used for source and binary dir.
CMake uses the command directly, and only if the command line length limit may be hit, it works around that OS limit by using a response file (which is only possible for those compilers/versions which support using a response file).

If you don’t know how to achieve what you wanted to do with the official functionality, you could open a thread about that topic. But please do not rely on undocumented behavior of any tool.

2 Likes

Thanks for the response, @jtxa :

Is the creation of link.txt documented? I don’t think so, it’s an implementation detail.

Good you mention that - I guess a part of my frustration was that I could not find any reading on link.txt in CMake; at least there’s this post now :)

I guess it depends on the command line length limit of your OS

Ah, it makes sense now, and it explains the difference in behavior!

In any case, I solved this by checking first if build.make makes any references to link.txt, if so, I extract the linker command from link.txt, if not, from build.make, seems to work so far.