How can I get filename of current file for CMake - cmake

I am writing a CMake file to generate Makefiles for an Atmel Project.
The problem I have is that when building in Atmel studio, the options -MF <filname> and -MT"<filename>" are used. For atmel, these filenames are dependent on the input file, so eg. for file foo.c the flags will be set to
-MF "<path>/foo.d" -MT"<path>/foo.d"
How can I have the same behaviour from a CMake Project? What I basically want is below row but where foo is replaced with currently compiling file so it is replaced with bar.d, baz.d et.c.
target_compile_options (foo_project PRIVATE -MD -MP -MF "<path>/foo.d" -MT"<path>/foo.d")
hope I make somewhat sense...
thanks

Related

How can I tell CMake to put include directory flags after the compiler option flags in its object compile command?

I am facing problems due to the target holding the include paths first and then the compiler options after. How can I set the include paths after the compiler options for compiling source files of a target?
My CMakeLists.txt file:
project(HelloWorld)
cmake_minimum_required(VERSION 3.0)
add_library(HELLO_WORLD_LIB
STATIC
src/helloWorld.cpp
)
target_include_directories(
HELLO_WORLD_LIB AFTER PUBLIC D:\\temp\\includes
)
target_compile_options(HELLO_WORLD_LIB BEFORE PUBLIC -cpp -remap)
set_target_properties(HELLO_WORLD_LIB
PROPERTIES
OUTPUT_NAME hello
ARCHIVE_OUTPUT_DIRECTORY D:\\temp\\CMakeHelloWorld
SUFFIX .a
)
My cmake call:
call cmake -GNinja -S ./.. -DCMAKE_INSTALL_PREFIX=../_bin
call cmake --build . --config Debug --verbose -d keeprsp
call cmake --install .
The console output:
-- Configuring done
-- Generating done
-- Build files have been written to: D:/temp/CMakeHelloWorld/_build
[1/2] C:\mingw\test25_comp_8.1.0_testversion\bin\c++.exe -ID:/temp/includes -cpp -remap -MD -MT CMakeFiles/HELLO_WORLD_LIB.dir/src/helloWorld.cpp.obj -MF CMakeFiles\HELLO_WORLD_LIB.dir\src\helloWorld.cpp.obj.d -o CMakeFiles/HELLO_WORLD_LIB.dir/src/helloWorld.cpp.obj -c ../src/helloWorld.cpp
[2/2] cmd.exe /C "cd . && C:\toolbase\_ldata\cmake\.8-3.20.2\bin\cmake.exe -E rm -f ..\libhello.a && C:\mingw\test25_comp_8.1.0_testversion\bin\ar.exe qc ..\libhello.a CMakeFiles/HELLO_WORLD_LIB.dir/src/helloWorld.cpp.obj && C:\toolbase\mingw\test25_comp_8.1.0_testversion\bin\ranlib.exe ..\libhello.a && cd ."
-- Install configuration: ""
However if I try to add the include paths after compiler options, it sits before the compiler options. How can I set the compiler options before the include directories? like C:\toolbase\mingw\test25_comp_8.1.0_testversion\bin\c++.exe -cpp -remap -ID:/temp/includes.
The relevant CMake variable is CMAKE_CXX_COMPILE_OBJECT, which is the configuration point for what template to use for the command to compile an object. The default value is set in Modules/CMakeCXXInformation.cmake, and overrides are specified in various Modules/Platform/* or Modules/Compiler/* files. If you're curious, you can grep for the overrides with the following regex: set.*CXX_COMPILE_OBJECT.
The default one is set like this:
set(CMAKE_CXX_COMPILE_OBJECT
"<CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> -c <SOURCE>")
You probably want something like this (set it in your own CMakeLists.txt file, or in a toolchain file):
set(CMAKE_CXX_COMPILE_OBJECT
"<CMAKE_CXX_COMPILER> <DEFINES> <FLAGS> <INCLUDES> -o <OBJECT> -c <SOURCE>")
As far as I can tell, this configuration point is "global". I'm not aware of how to specify it with different values for different targets or source files.
If you're working with the Ninja generator and need this kind of change to affect the generated .rsp files, I think you'd need to build a modified version of CMake from source, since that behaviour seems to be baked into the binaries instead of CMake script files in the Modules/ directory. The relecant source file is Source/cmNinjaTargetGenerator.cxx. Look at the lines of code that do rule.RspContent = and you'll see:
rule.RspContent =
cmStrCat(' ', scanVars.Defines, ' ', scanVars.Includes, ' ', scanFlags);
You'd probably need to switch the order of scanVars.Includes and scanVars.scanFlags.
If you choose to make a modified CMake binary, as always, make sure you comply with the software licence.

error: target Objective-C runtime differs in PCH file vs. current file

I'm trying to compile Objective-C or .m file using command-line (generated by CMake) for Catalyst, but am stuck with two compile errors!
1. Whenever I enable Catalyst with one of below flags:
-target x86_64-apple-ios-macabi
-target x86_64-apple-ios13.0-macabi
-target x86_64-apple-ios13.5-macabi
-target x86_64-apple-ios13.7-macabi
2. Then force rebuild (click Clean Build Folder, then Build).
3. The build fails with error:
fatal error: 'UIKit/UIKit.h' file not found
4. But once I switch to 13.6, I mean, change the flag to:
-target x86_64-apple-ios13.6-macabi
5. Then force-rebuild, I get a new error:
error: target Objective-C runtime differs in PCH file vs. current file
Note that I am not using any PCH file, and both errors seem completely confusing.
Also, I searched and found post similar to second error, but the fix suggested (namely, switching to 13.6) is the cause of the second error.
(Was supposed to fix it, yet is triggering it).
After capturing Xcode's full command-line, I noticed that it had -x objective-c flag while my CMake had not!
After searching (about how CMake support's Obj-C),
found actual mistake!
1. Basically, CMake needed me to do something like:
project(MyProject C CXX OBJC OBJCXX)
Instead of:
project(MyProject)
2. Also, should add Obj-C flags into CMAKE_OBJC_FLAGS instead of CMAKE_C_LINK_FLAGS variable.
3. Now CMake automaticaly adds missing -x objective-c flag, and I just need to add my custom flags.
Full Xcode command-line:
-x objective-c -target x86_64-apple-ios13.6-macabi -fmessage-length=0 -fdiagnostics-show-note-include-stack -fmacro-backtrace-limit=0 -fobjc-arc -fmodules -gmodules -fmodules-cache-path=/Users/admin/Library/Developer/Xcode/DerivedData/ModuleCache.noindex -fmodules-prune-interval=86400 -fmodules-prune-after=345600 -fbuild-session-file=/Users/admin/Library/Developer/Xcode/DerivedData/ModuleCache.noindex/Session.modulevalidation -fmodules-validate-once-per-build-session -fmodule-name=MyProject -fapplication-extension -fpascal-strings -O0 -fno-common -DDEBUG=1 -DOBJC_OLD_DISPATCH_PROTOTYPES=0 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk -fasm-blocks -fstrict-aliasing -g -fprofile-instr-generate -fcoverage-mapping -index-store-path /MyBuildDir/Index/DataStore -iquote /MyBuildDir-cofig/MyProject-generated-files.hmap -I/MyBuildDir-cofig/MyProject-own-target-headers.hmap -I/MyBuildDir-cofig/MyProject-all-non-framework-target-headers.hmap -ivfsoverlay /MyBuildDir-cofig/all-product-headers.yaml -iquote /MyBuildDir-cofig/MyProject-project-headers.hmap -I/MyProductDir/include -isystem /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/System/iOSSupport/usr/include -I/MyBuildDir-cofig/DerivedSources-normal/x86_64 -I/MyBuildDir-cofig/DerivedSources/x86_64 -I/MyBuildDir-cofig/DerivedSources -F/MyProductDir -iframework /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/System/iOSSupport/System/Library/Frameworks -MMD -MT dependencies -MF /MyBuildDir-cofig/Objects-normal/x86_64/my-source.d --serialize-diagnostics /MyBuildDir-cofig/Objects-normal/x86_64/my-source.dia -c /Users/admin/my-project/my-source.m -o /MyBuildDir-cofig/Objects-normal/x86_64/my-source.o
Note that I replaced paths to shorten above, like:
MyBuildDir => /Users/admin/Library/Developer/Xcode/DerivedData/MyProject-gczfeuobxydqjrfbdhwzpqjsseyr
MyBuildDir-config => /Users/admin/Library/Developer/Xcode/DerivedData/MyProject-gczfeuobxydqjrfbdhwzpqjsseyr/Build/Intermediates.noindex/MyProject.build/Debug-maccatalyst/MyProject.build/
MyProductDir => /Users/admin/Library/Developer/Xcode/DerivedData/MyProject-gczfeuobxydqjrfbdhwzpqjsseyr/Build/Products/Debug-maccatalyst

CMake get all flags, includes and defines programatically

I'm using CMake 3.12 with linux and I try to extract all flags, includes and defines programatically from a target.
I found some help online, but it was always limited to the default settings induced by CMake.
For example with the variables :
CMAKE_CXX_FLAGS
CMAKE_CXX_FLAGS_DEBUG
CMAKE_CXX_FLAGS_RELEASE
...
Here I'm missing external flags.
I' stumbled upon the file "flags.make" located in the build folder of the project:
# CMAKE generated file: DO NOT EDIT!
# Generated by "Unix Makefiles" Generator, CMake Version 3.12
# compile C with /usr/bin/gcc-4.8
C_FLAGS = -O3 -DNDEBUG -fPIC
C_DEFINES = -DLINUX -DLINUX64 -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
C_INCLUDES =
Which is exactly what I need. Does anybody know how to access these variables within CMake?
Thank you!
Best regards
Fabian

CMake invocation of GLSLC with respect to includes/dependencies

I'm using glslc to compile GLSL shaders with #includes (not part of the core spec IIRC but supported in shaderc, which is the engine behind glslc, distributed with the LunarG Vulkan SDK) into SPIR-V for Vulkan and GL 4.5. glslc emits gcc-style depsfiles ([my_shader].[ext].d) files containing dependency info.
My project is built with cmake/ninja/MSVC 2017.
Today, I use a cmake custom_command to invoke glslc when a shader has changed on disk, as a post-build step to my primary target. However, this doesn't catch the changes in included files (isn't at all aware of the .d files or their contents), so rebuilding shaders when an included glsl file is changed can trip up myself and other people on my team.
It looks like ninja can invoke arbitrary compilers, and since ninja knows how to handle the depsfiles, I should be able to coerce ninja into running glslc -- unsure about other build systems since right now we're standardized on ninja.
So how can I tell cmake to configure ninja to use glslc for a specific target? Or is there a paradigmatic way to get this done? It looks like a cmake pull request to add support for glslc as a compiler didn't make it in to cmake circa 2016, so whatever I do is going to be a workaround.
CMake understands depfiles when used in conjunction with ninja.
DEPFILE
Specify a .d depfile for the Ninja generator. A .d file holds dependencies usually emitted by the custom command itself. Using DEPFILE with other generators than Ninja is an error.
add_custom_command(
OUTPUT ${source}.h
DEPENDS ${source}
COMMAND
glslc
-MD -MF ${source}.d
-o ${source}.h -mfmt=num
--target-env=opengl
${CMAKE_CURRENT_SOURCE_DIR}/${source}
DEPFILE ${source}.d
)
-M Generate make dependencies. Implies -E and -w.
-MM An alias for -M.
-MD Generate make dependencies and compile.
-MF <file> Write dependency output to the given file.
-MT <target> Specify the target of the rule emitted by dependency
generation.
EDIT: Getting fancier
find_package(Vulkan COMPONENTS glslc)
find_program(glslc_executable NAMES glslc HINTS Vulkan::glslc)
function(compile_shader target)
cmake_parse_arguments(PARSE_ARGV 1 arg "" "ENV;FORMAT" "SOURCES")
foreach(source ${arg_SOURCES})
add_custom_command(
OUTPUT ${source}.${arg_FORMAT}
DEPENDS ${source}
DEPFILE ${source}.d
COMMAND
${glslc_executable}
$<$<BOOL:${arg_ENV}>:--target-env=${arg_ENV}>
$<$<BOOL:${arg_FORMAT}>:-mfmt=${arg_FORMAT}>
-MD -MF ${source}.d
-o ${source}.${arg_FORMAT}
${CMAKE_CURRENT_SOURCE_DIR}/${source}
)
target_sources(${target} PRIVATE ${source}.${arg_FORMAT})
endforeach()
endfunction()
add_executable(dummy dummy.c)
compile_shader(dummy
ENV opengl
FORMAT num
SOURCES
dummy.vert
dummy.frag
)

Fortran file dependency with Intel ifort

I am working in a standard Unix environment, with Intel Fortran 2012 compiler.
since my codes have some old .f files and some newer .f90 files, the makefile is organized in the following structure,
f_sources= ... ...
f90_sources= ... ...
f_objects = $(patsubst %.f,%.o,$(f_sources))
f90_objects = $(patsubst %.f90,%.o,$(f90_sources))
$(f_objects): %.o: %.f
#echo compiling $<
$(FC) $(FC_FLAGS) -c $< -o $#
# compile f90 files:
$(f90_objects): %.o: %.f90
#echo compiling $<
$(FC) $(FC_FLAGS) -c $< -o $#
The problem is, few strange .f files depend on the modules defined in some .f90 files, and then the compiler seems not able to detect the dependency since I compile first all the .f files...
Error in opening the compiled module file. Check INCLUDE paths.
Is there a way to solve this problem?
Add
f77_file_with_module_dependency.o: f90_file_for_module.o
to your Makefile somewhere.
Supposing that you have a there.f file that depends on mod_here.f90, you declare in your makefile the following:
there.o: mod_here.o
$(FC) $(FC_FLAG) -c there.f -o there.o
When the makefile gets to this file, there.f, it will see that it depends on mod_here.f90, which hasn't yet been compiled, so it'll compile it.