per target cuda compiler options with cmake - c++

So I have a bit of an issue with setting up pdbs in cuda when using cmake and visual studio (2013 in the case).
Basically I think I want to do something like :
-Xcompiler "/Fd whatever.pdb"
to each add_cuda_library, but I can only seem to set CUDA_NVCC_FLAGS, CUDA_NVCC_FLAGS_RELEASE, CUDA_NVCC_FLAGS_DEBUG etc globally.
Right now I use
SET(CUDA_NVCC_FLAGS_RELEASE ${CUDA_NVCC_FLAGS}; -Xcompiler "/Fd nvcc_all.pdb")
And this dumps all the symbols into one file.
Problem is sometimes the build breaks when there are concurrent writes to that pdb. I've tried adding /FS, but it doesn't help.
Is there a cmake incantation to allow me to add a per lib cuda pdbs ?

You can try to pass the flags like this:
CUDA_ADD_LIBRARY(foo
...
OPTIONS "/Fd foo.pdb"
)

Related

How to remove /RTC1 from specific target or file in CMake

So I have a giant project that I joined with a bunch of cmake. Our debug builds run very slow, and we traced it back to both a specific target we are building (allegro legacy), and a specific file (ffscript.cpp). If we enable /O2 for both of these, we can go from an unbearable 30 fps to 300 fps uncapped. The problem is that these are incompatible with /RTC1 (run-time error checks), a flag which is apparently on (though I can't find where it's being set, so I assume CMake itself is setting it).
We figured out how to disable RTC1 for the entire project with STRING (REGEX REPLACE "/RTC(su|[1su])" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") STRING (REGEX REPLACE "/RTC(su|[1su])" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}"), but realized that /RTC1 sounds pretty useful everywhere else. We want to only disable it for this specific target and file but keep it elsewhere, but I cannot figure out the sanest way to do this that still works. I also want to add the /O2 flags to the specific file; it's already added for the target, but I don't know how to add it to a specific file (though I know how to do it manually via VS2022, I'd prefer to not lose these changes each time the CMake gets updated). I don't know what I should share, but here's the CMake file for this specific target (there's multiple CMakeLists.txt files in this project): https://pastebin.com/gYUJUGpE
Could someone help me out? I don't really know how to CMake at all, and it's pretty daunting. Would greatly appreciate it if someone could help me and explain in a way I could understand. Thanks!
Note: There was one solution I found on Stack Overflow which involved taking the entire global with a macro and applying it to each target individually, but that caused compile errors and I had to revert it.
Note: I am not sure whether it is actually valid/safe to link between targets with different values of /RTC. Don't take this answer as any confirmation that what you want will work out.
As for where the /RTC flag is getting set, your hunch is right. It can be set by CMake. See :/Modules/Platform/Windows-MSVC.cmake and search for "RTC". In particular, see the part which modifies CMAKE_${lang}_FLAGS_DEBUG_INIT.
Achieving what you want (removing /RTC for a specific target) is a bit difficult because unlike GNU compilers, which allow disabling most previously-specified flags with a "no-" prefix, I'm not aware of the CL compiler offering similar functionality, combined with the fact that options in CMAKE_<LANG>_FLAGS_<CONFIG> exist separately from those in the COMPILE_OPTIONS directory property and target property, and is combined into the final list of compile options for a target/source-file near the end of the process of building that compile options list (as opposed to being used to initialize the directory and target properties).
One workaround could be to keep doing what you did (remove /RTC from CMAKE_CXX_FLAGS_DEBUG and CMAKE_C_FLAGS_DEBUG), and then just add /RTC to the COMPILE_OPTIONS directory property of the root CMakeLists.txt via add_compile_options, which initializes the target property for all targets created/defined in subdirectories, and then remove /RTC from the target's COMPILE_OPTIONS property via get_property(TARGET) and set_property(TARGET).

Compile error CMAKE with CUDA on Visual Studio C++

I am having a problem compiling a project with CUDA on VS2017 c++.
I can get rid of this error by just changing the line in
Properties->CUDA C/C++->Command Line-> Additional Options:
%(AdditionalOptions) -Zi /W3 /wd4005 /wd4003 /wd4996 /nologo -Xcompiler="/EHsc -Zi -Ob0"
changed to
%(AdditionalOptions) -Xcompiler="/EHsc -Ob2"
After changing this option, the project compiles without any errors.
My Question is, how can I do it from CMAKE so that I don't have to change this property every time I regenerate the project?
Your .sln file is generated from cmake. You can use cmake-gui.exe to load the cmake cache file and query strings, then override that string in your CMakeLists.txt.
For your case, you would like to remove the annoying "/W3 /wd4005 /wd4003 /wd4996 /nologo " options. You can do like this:
Here, I open cmake-gui.exe, fillin the source folder and build folder of your project, and type "w3" in search box, and get "CMAKE_C_FLAGS". So you can override "CMAKE_C_FLAGS" in your CMakeLists.txt:
set(CMAKE_C_FLAGS "") # set it to empty
# you may also replace some options inside it, go and query cmake docs to see how to do that
Then, clean all the previous generated build files and re-cmake.

The proper way of forcing a 32-bit compile using CMake

Sorry that there are many similar questions, but I do find that Googling for CMake queries always yields similar-but-not-the-same scenarios, conflicting CMake commands and so on!
I need to force my project to build 32-bit binaries because I have to link with a library which is only available as 32-bit. I diagnosed this based on error messages such as:
/usr/bin/ld: i386 architecture of input file `*external-32bit-lib*' is incompatible with i386:x86-64 output
From what I gather, I should therefore use:
set (CMAKE_CXX_FLAGS "-m32")
This does change things - I now get several errors like:
/usr/bin/ld: i386 architecture of input file `*project-output-lib*' is incompatible with i386:x86-64 output
AND still get the same errors for the external library too. I think this is because the -m32 made gcc generate 32-bit binaries, but ld is still trying for 64-bit output? Further Googling for this problem didn't give any success, so if anyone could verify that I am right and give the correct way of doing this, I would be very grateful!
Many thanks!
If you want to compile and link for 32 bit using cmake use this for creating libraries and binaries:
Creating libraries:
add_library(mylib SHARED my_source.c)
set_target_properties(mylib PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32")
creating executables:
add_executable(mybin sources.c)
set_target_properties(mybin PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32")
Even if this seems like extra works, I believe a proper solution is to use toolchain file in this case. Something like:
# the name of the target operating system
set(CMAKE_SYSTEM_NAME Linux)
# which compilers to use for C and C++
set(CMAKE_C_COMPILER gcc)
set(CMAKE_C_FLAGS -m32)
set(CMAKE_CXX_COMPILER g++)
set(CMAKE_CXX_FLAGS -m32)
# here is the target environment located
set(CMAKE_FIND_ROOT_PATH /usr/i486-linux-gnu )
# adjust the default behaviour of the FIND_XXX() commands:
# search headers and libraries in the target environment, search
# programs in the host environment
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
Then usage is simply:
$ cmake -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake /path/to/source
The important part here is that one is now able to specify a root dir path (CMAKE_FIND_ROOT_PATH) which should be used to search for third party lib. Indeed your compiler may not be smart enough to know where to search for an x86 Qt library on an x86_64 system.
Having a toolchain file allows one to specify a different one on a par compiler basis, and you should be able to tweak the option when compiling in 32bits from a windows environement.
Nowadays this is extra works since compiling 32bits from an x86_64 Linux OS is pretty much trivial, but this solution will work for other more exotic setup.
For more information on toolchain file, one can check for example:
https://gitlab.kitware.com/cmake/community/-/wikis/doc/cmake/cross_compiling/Mingw
CMAKE_CXX_FLAGS only affects the C++ compiler. You probably also have to set the flag for the C compiler:
set (CMAKE_C_FLAGS "-m32")
It sounds like you did not pass m32 to LFLAGS too, or there are old obj files skulking about. Be sure to clean first.
This question is similar to yours: cmake, gcc, cuda and -m32
Use TRY_RUN command by the following source.
size.cpp:
#include <cstdlib>
int main( int argc, char** argv )
{
size_t size = sizeof(void*);
if ( size == 4 )
return 0;
return 1;
}
CMakeLists.txt:
TRY_RUN(RUN_RESULT_VAR COMPILE_RESULT_VAR ${your_temp_dir} size.cpp RUN_OUTPUT_VARIABLE IS_64_SYSTEM)
IF(IS_64_SYSTEM)
MESSAGE(FATAL_ERROR "64 compiling not allowed!")
ENDIF(IS_64_SYSTEM)
It will work on all standard compiler.
I used malat's approach and made a Toolchain file.
I have a Toolchain file that works on some Linux dists, perhaps it will give you inspiration. It may work for you as is, or you may need other ugly hacks to get other cmake scripts you rely on to work or w/e:
https://github.com/visualboyadvance-m/visualboyadvance-m/blob/master/cmake/Toolchain-cross-m32.cmake

jsoncpp on vc90?

anyone have jsoncpp working on vc90?
they use a build system, Scons, which I have never heard of. I installed the latest Scons, found an undocumented scons.bat, launched a vc90 prompt in my jsoncpp dir, modified the SConstruct file to support a msvc90 target (i copied the boilerplate from the msvc80 platform which was already supported) ran scons.bat platform=msvc90 and got errors:
scons: done reading SConscript files.
scons: Building targets ...
cl /Fobuildscons\msvc90\src\jsontestrunner\main.obj /c src\jsontestrunner\main.c
pp -GR -EHsc /nologo /MT /nologo /Iinclude /I.
main.cpp
c:\projects\docwayhead\wspt_docway_plugins\contrib\jsoncpp-src-0.5.0\include\jso
n\value.h(5) : fatal error C1083: Cannot open include file: 'string': No such fi
le or directory
scons: *** [buildscons\msvc90\src\jsontestrunner\main.obj] Error 2
scons: building terminated because of errors.
i've already put too much effort into getting this to build, and jsoncpp is clearly unmaintained, so i give up for now.
No need to use Scons.
Under the /makefiles/vc71/ you can find a visual studio solution which you can up convert and build.
Modify the msvc90 platform file to make sure VC90 include directories are used when calling cl (clearly not yet the case in the provided command line you provided).
Note that Scons is written using Python and so are its configuration files, so people who know Python around you might be able to help you efficiently, even if they know nothing about scons.
Are you sure your VS command line is working properly? I got it to work just by:
- Adding a msvc90 entry in allowed_values
- copy/pasting the msvc80 section later and modifying it to use env['MSVS_VERSION'] = 9.0
I'm using scons 1.3.0.
The scons setup for jsoncpp 0.5.0 does not support VS 9.0 or 10.0 out of the box. You need to first add msvc90 to the allowed_values in the SConstruct line 21, and the to add this section on line 103.
elif platform == 'msvc90':
env['MSVS_VERSION']='9.0'
for tool in ['msvc', 'msvs', 'mslink', 'masm', 'mslib']:
env.Tool( tool )
env['CXXFLAGS']='-GR -EHsc /nologo /MT'
Just replace 9.0 with 10.0 and 90 with 100 for VS 10.0 support.
As of version 0.6.0 of jsoncpp, you can avoid a lot of hassle by using the new Amalgamated version. This is just two .h files and one .cpp file that you compile directly into your projects. It's working great for me so far in VS 9 (and with a few mods I'm now able to compile it with C++Builder 2010 as well -- haven't really tested the result yet).
By the way, I've filed a bug against version 0.6.0-rc2; one line in the Amalgamated version of json.h needs to have a macro name changed.

Linking different libraries for Debug and Release builds in Cmake on windows?

So I've got a library I'm compiling and I need to link different third party things in depending on if it's the debug or release build (specifically the release or debug versions of those libraries). Is there an easy way to do this in Cmake?
Edit: I should note I'm using visual studio
According to the CMake documentation:
target_link_libraries(<target> [lib1 [lib2 [...]]] [[debug|optimized|general] <lib>] ...)
A "debug", "optimized", or "general"
keyword indicates that the library
immediately following it is to be used
only for the corresponding build
configuration.
So you should be able to do this:
add_executable( MyEXE ${SOURCES})
target_link_libraries( MyEXE debug 3PDebugLib)
target_link_libraries( MyEXE optimized 3PReleaseLib)
Somehow the answer from #Mike Willekes got CMake linking in the same target both release and debug for me :(
I only got this working by setting both configurations in one line, as suggested by #sakra in a related question - and doing so for every library that needed to be linked:
target_link_libraries ( app
debug ${Boost_FILESYSTEM_LIBRARY_DEBUG}
optimized ${Boost_FILESYSTEM_LIBRARY_RELEASE} )
target_link_libraries ( app
debug ${Boost_LOG_LIBRARY_DEBUG}
optimized ${Boost_LOG_LIBRARY_RELEASE} )
target_link_libraries ( app
debug ${Boost_PROGRAM_OPTIONS_LIBRARY_DEBUG}
optimized ${Boost_PROGRAM_OPTIONS_LIBRARY_RELEASE} )
# ...
I would like to add a few notes to the previous answers.
If you need to create a list of multiple files you want to link and store that in a cache variable then you need to add the optimized or debug specified before each and every library. This can be especially useful for larger makefiles/projects.
So for example you could do something like this:
set( MyFavLib_LIBRARIES
debug debug/module1.lib optimized release/module1.lib
debug debug/module2.lib optimized release/module2.lib )
target_link_libraries( app ${MyFavLib_LIBRARIES} )
What worked for me was to use $(Configuration) macro in a lib path provided to cmake.
So, assuming libs are stored in separate, correctly named folders, e.g.:
C:\boost\lib\Debug\libfoo.lib
C:\boost\lib\Release\libfoo.lib
You can then call cmake with:
cmake -G "Visual Studio 10 2010" -DBOOST_LIBRARYDIR=C:\boost\lib\$(Configuration)\libfoo.lib
That'll generate .vcxproj with Additional Dependencies including C:\boost\lib\$(Configuration)\libfoo.lib, what is evaluated to either C:\boost\lib\Release\libfoo.lib or C:\boost\lib\Debug\libfoo.lib depending on a chosen Configuration.
target_link_libraries with optimize and debug doesn't work for me. I follow the post of Mike Willekes, but release config also import debug library file in visual studio. Then, I use the following cmake code to solving this problem
add_library(BoostLib STATIC IMPORTED)
set_target_properties(BoostLib PROPERTIES
IMPORTED_LOCATION_DEBUG ${BoostLibPath}/debug/module1.lib
IMPORTED_LOCATION_RELEASE ${BoostLibPath}/release/module1.lib)
target_link_libraries(AppTarget BoostLib)