Generate assembly for a target - cmake

I am trying to pass -S to GCC for one of my executables. I tried this:
set_target_properties(MyTarget PROPERTIES COMPILE_FLAGS "-S")
but I get "file format not recognized; treating as linker script"
(It builds fine without that line)
Is there something wrong with passing -S like this? Or is there another way to have CMake output the assembly .s files?

CMake has targets built in for both assembler and preprocessor output. For a file called src.cpp, CMake generates the target src.s for assembler output and src.i for the preprocessor output. It generates the assembler/preprocessor outputs for each target seperately in case the compile flags are different. Using the make generator for your CMake project, you can get the assembler and preprocessor outputs like this:
make src.s # assembler output
make src.i # preprocessor output

If you're trying to actually build MyTarget and leave the generated assembly, you can replace -S with -save-temps and then do make MyTarget

Related

Cmake get/query/print build settings on the command line?

Let's assume I have a Cmake C project, and I have something like this in the project:
project(my_project C CXX ASM)
set(my_executable_sources
main.c
file_one.c
)
set(my_executable_sources ${my_executable_sources} file_two.c)
add_executable(my_executable
${my_executable_sources}
file_three.c
)
Let's assume I'm in the ./build subfolder, and cmake ../ -G "Unix Makefiles" has passed successfully.
Can I somehow query build information from the command line using cmake?
For instance, I'm interested here in the final list of source files for my_executable; is there a command that would easily retrieve them? Say, like the following pseudocode:
$ cmake --pseudo-query-build --project="my_project" --target="my_executable" --query="source_files"
my_executable source files:
main.c
file_one.c
file_two.c
file_three.c
I don't see any cmake-generator-independent way of achieving this and even if you know the generator in use the project files generated.
You could modify your project to include a custom target that prints the sources though:
add_custom_target(print_my_executable_sources COMMAND ${CMAKE_COMMAND} -E echo "$<TARGET_PROPERTY:my_executable,SOURCES>" COMMAND_EXPAND_LISTS)
this allows you to use
cmake --build <binary_dir> [--config <configuration>] --target print_my_executable_sources
to print the sources, even if generator expressions are used in the sources.
Note: This does print all files in a single line; to get all the file names on separate lines, you could instead run cmake with the -P option passing the soures via -D and add logic to print one file name per line in the cmake script file.
Alternatively setting the CMAKE_EXPORT_COMPILE_COMMANDS variable to True during configuration could result in the generation of json files that would allow for the extraction of the information, but you'd need a json parser to extract the info. Furthermore this approach only works for the Makefile and Ninja CMake generators. Also I'm not sure you can tell which target a source file belongs to in all cases.
Start by obtaining the target's sources via this line (after add_executable):
get_target_property(MY_TARGET_SOURCES my_executable SOURCES)
And then proceed with a simple line at the end of the file (after add_executable)
message(STATUS ${MY_TARGET_SOURCES})
EDIT: For a full list of available target properties refer to this link.
EDIT2: As I've noticed now that you probably intend to just use it within the CLI, then for my solution you would also have to encapsulate it with a if/endif that checks for a definition e.g. if(SOURCES_DEBUG_INFO) and then run it with -DSOURCES_DEBUG_INFO=TRUE

Retrieve all link flags in CMake

In CMake, is it possible to programmatically retrieve the complete list of linker flags that will be used for a given target? The only way I can see to do this is to inspect the link.txt file in the target's CMakeFiles directory. Not ideal.
The use case that I'm interested in is to collect the data to include in something like a pkg-config file. I'm writing a library, and it includes a couple executable utilities that use the library. Building the executables (especially when the library is build statically) requires a non-trivial link line to link to my library and its dependencies. So I'd like to write out the link line necessary for building these executables to a data file included with the package such that other clients can know how to link.
As #Tsyvarev has commented there is no build-in command or property "to programmatically retrieve the complete list of linker flags" in CMake.
But inspired by your hint "so I'd like to write out the link line necessary for building these executables to a data file" I think I found a feasible solution (at least for makefile generators).
And if I understand your request correctly, we are not talking about simple verbose outputs like you get with e.g. CMAKE_VERBOSE_MAKEFILE, which would still need you to copy things manually.
So taking the following into account:
You need to run the generator first to get the real link line
CMake allows you to invent any linker language by name
You can define the link line with CMAKE_>LANG<_LINK_EXECUTABLE using variables and expansion rules
I came up with adding an LinkLine executable using my ECHO "linker" with the single purpose to create a link line file of my choosing:
set(CMAKE_ECHO_STANDARD_LIBRARIES ${CMAKE_CXX_STANDARD_LIBRARIES})
set(CMAKE_ECHO_FLAGS ${CMAKE_CXX_FLAGS})
set(CMAKE_ECHO_LINK_FLAGS ${CMAKE_CXX_LINK_FLAGS})
set(CMAKE_ECHO_IMPLICIT_LINK_DIRECTORIES ${CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES})
set(
CMAKE_ECHO_LINK_EXECUTABLE
"<CMAKE_COMMAND> -E echo \"<FLAGS> <LINK_FLAGS> <LINK_LIBRARIES>\" > <TARGET>"
)
add_executable(LinkLine "")
target_link_libraries(LinkLine MyLibraryTarget)
set_target_properties(
LinkLine
PROPERTIES
LINKER_LANGUAGE ECHO
SUFFIX ".txt"
)
The nice thing about this approach is, that the output of my LinkLine target can be used as any other "officially generated" executable output (e.g. in install() commands or post-build steps with generator expressions):
add_custom_command(
TARGET LinkLine
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:LinkLine> PackageCfg/$<TARGET_FILE_NAME:LinkLine>
)
References
Recursive list of LINK_LIBRARIES in CMake
add_custom_command is not generating a target

Display CMake variables without running CMake on a CMakeLists.txt file or manually inspecting config.cmake?

Suppose I have a package called Foo. If I run CMake on a CMakeLists.txt file that contains find_package(Foo), then I can print out the values of variables such as ${Foo_LIBRARIES} and ${Foo_INCLUDES}.
Is there an easy way to display these variables without having to run CMake on a CMakeLists.txt file, and without having to manually inspect the config.cmake file?
You asked: (1) Is there an easy way to display these variables without having to run cmake on a CMakeLists.txt file, and (2) without having to manually inspect the config.cmake file?
I can give you a yes answer to (2) but it does require that you (re)run cmake. But since you can re-run your cmake configure step by simply executing cmake . in the build directory, re-running cmake should not keep you from trying this approach. My answer is given in this SO answer and uses the get_cmake_property command. Here is that code encapsulated into a cmake macro, print_all_variables, so I can use it when debugging my cmake scripts.
macro(print_all_variables)
message(STATUS "print_all_variables------------------------------------------{")
get_cmake_property(_variableNames VARIABLES)
foreach (_variableName ${_variableNames})
message(STATUS "${_variableName}=${${_variableName}}")
endforeach()
message(STATUS "print_all_variables------------------------------------------}")
endmacro()
The macros are invoked with same syntax as cmake functions:
print_all_variables()
To simply print a value, you could do something like this:
message(STATUS "foo include dir: ${foo_INCLUDE}")
where ${foo_INCLUDE} is the value you desire to print.
Note: I'm using cmake > 3.14
Run CMake and have a look at the cache with the ccmake GUI tool. Then you'll get all the variables.
Or run CMake with -LH then you will get all variables printed after configuration.
So I think it is not possible to get the variables without running CMake.
Run cmake in find-package mode. Example to display a package`s include directories:
cmake -DNAME=ZLIB -DCOMPILER_ID=GNU -DLANGUAGE=C -DMODE=COMPILE --find-package
Example to display the libraries:
cmake -DNAME=ZLIB -DCOMPILER_ID=GNU -DLANGUAGE=C -DMODE=LINK --find-package
The NAME must be set to the package name. You can obtain your COMPILER_ID on this page. LANGUAGE can be C, CXX or Fortran.
I am always suspicious of variables changing values throughout a script somewhere so I like to see the value of a variable at a particular point in the running script. Combining the ideas from both Phil and Aaron B. this is what I'm using:
function(PRINT_VAR VARNAME)
message(STATUS "${VARNAME}: ${${VARNAME}}")
endfunction()
PRINT_VAR("CMAKE_CXX_COMPILER")
Then I can just litter PRINT_VAR statements around like I'm debugging code back in 1980
These variables are generally hardcoded into FindFoo.cmake so that it is not possible to extract them without running the function first. Note that sometimes the value of Foo_LIBRARIES depends on the system configuration, which is unknown until find_package(Foo) is run.

How to include a cmake Makefile after a target has been executed?

Given the following minimal example.
cmake_minimum_required(VERSION 2.8)
project(include_test)
add_custom_command(OUTPUT OtherCMakeLists.txt
COMMAND "${CMAKE_CURRENT_BINARY_DIR}/create_other_cmakelists")
add_custom_target(do_something DEPENDS OtherCMakeLists.txt)
What do_something should do here is first create OtherCMakeLists.txt. Now, let's assume that do_something has to do something else afterwards, e.g. compiling some code. I'd like that when the targets from something else are executed, the CMakeLists.txt will behave as if OtherCMakeLists.txt was included with include.
Is this possible?
As an example why this could be useful: OtherCMakeLists.txt might add some compiler flags that have influence on further compiling.
To my knowledge, it is not possible to generate CMakeLists.txt file with a custom target/command and use include CMake command with generated CMakeLists.txt
The problem is that the include command is called at so-called "Configuration time" (when cmake executable tries to parse all CMakeLists.txt), but the generation of file (CMakeLists.txt) is performed at "Build time" (when make command is invoked on generated build system)
add_custom_command has 2 different signatures:
add_custom_command(OUTPUT ...) will be executed at build time, too late to apply rules from a generated CMakeLists.txt generated.
add_custom_command(TARGET ...) to attach a specific command to a target. This command can be run on PRE_BUILD, PRE_LINK or POST_BUILD. Probably not what you want to achieve...
If you are trying to add some dynamic to your compile process, adding custom commands or target may not be your best option.
You should try to read doc for some other CMake commands that can be helpful in your case:
configure_file() that can process a file (OtherCMakeLists.txt.in) into another file (OtherCMakeLists.txt) replacing variables by their values. This is achieved at configuration time
execute_process() to run a command a configuration time (thx to #ComicSansMS)
set_target_properties() to set some compiler or link flags to a specific target depending on some conditions
The list of properties you can set on targets

Only run C preprocessor in cmake?

I'm trying to use cmake to simplify distributing my OpenCL program. I have a kernel file which includes several headers and other source files, and I want to have a single self contained executable.
My plan is to have cmake run the C preprocessor on the kernel source, turning the cl file and its includes into a single unit which is easier to work with.
I can use add_custom_command to do it by calling gcc/clang with -E, but then I don't get the flags to include the right directories to find the various header files in the command, and I don't see an easy way to find all current include directories to use in the custom call to the compiler.
Is there a way to run only the C preprocessor on a file with the current cmake environment?
CMake automatically generates make targets for preprocessing files. For each foo.c in your project there's a foo.i make target that will run only the preprocessor (with all the relevant -D and -I flags etc.). Run make help to see all other potentially useful targets that CMake generates in your makefiles.
BTW, I can't see how this "single unit" will be easier to work with for you.
This worked ok so far:
function(add_c_preprocessor_command)
# Add custom command to run C preprocessor.
#
# Arguments
# OUTPUT output file
# SOURCE input file
# TARGET CMake target to inherit compile definitions, include directories, and compile options
# EXTRA_C_FLAGS extra compiler flags added after all flags inherited from the TARGET
set(one_value_args TARGET SOURCE OUTPUT)
set(multi_value_args EXTRA_C_FLAGS)
cmake_parse_arguments(CPP "" "${one_value_args}" "${multi_value_args}" ${ARGN})
string(TOUPPER ${CMAKE_BUILD_TYPE} build_type)
string(REPLACE " " ";" c_flags "${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${build_type}}")
add_custom_command(
OUTPUT ${CPP_OUTPUT}
COMMAND ${CMAKE_C_COMPILER}
"-D$<JOIN:$<TARGET_PROPERTY:${CPP_TARGET},COMPILE_DEFINITIONS>,;-D>"
"-I$<JOIN:$<TARGET_PROPERTY:${CPP_TARGET},INCLUDE_DIRECTORIES>,;-I>"
${c_flags}
$<TARGET_PROPERTY:${CPP_TARGET},COMPILE_OPTIONS>
${CPP_EXTRA_C_FLAGS}
-E ${CPP_SOURCE} -o ${CPP_OUTPUT}
COMMAND_EXPAND_LISTS VERBATIM
IMPLICIT_DEPENDS C ${CPP_SOURCE}
DEPENDS ${CPP_SOURCE})
endfunction()
This will be a crude hack, but you can abuse add_definition for that, as "This command can be used to add any flags, but it was originally intended to add preprocessor definitions."
Alternatively you could just set the COMPILE_FLAGS property of the target to "-E", which will achieve the same effect but be local to that target.
I would suggest a different approach.
Build your kernel into a binary (example for ATI Stream: http://developer.amd.com/support/KnowledgeBase/Lists/KnowledgeBase/DispForm.aspx?ID=115 )
Compile this binary data into your program (as a char[] blob) and load it when your program starts.
With cmake and custom targets this should be quite simple.